Compare commits

...

1 Commits

Author SHA1 Message Date
arvinxx 3ed0406fb4 push 2026-01-08 09:54:53 +08:00
9 changed files with 330 additions and 3 deletions
@@ -0,0 +1,11 @@
import mixedGroups from './mixed-groups.json';
import multipleCompressions from './multiple-compressions.json';
import parallelGroup from './parallel-group.json';
import simpleCompression from './simple-compression.json';
export const compression = {
mixedGroups,
multipleCompressions,
parallelGroup,
simpleCompression,
};
@@ -0,0 +1,80 @@
[
{
"id": "comp-group-1",
"role": "compressedGroup",
"content": "Summary: Initial project discussion about building a chat application.",
"parentId": null,
"createdAt": 1704060000000,
"updatedAt": 1704060000000,
"meta": {},
"pinnedMessages": [
{
"id": "pinned-architecture",
"role": "assistant",
"content": "Key architecture decision: React + tRPC + PostgreSQL",
"createdAt": "2024-01-01T08:00:00.000Z",
"model": "gpt-4",
"provider": "openai"
}
]
},
{
"id": "msg-compare-trigger",
"role": "user",
"content": "Which state management should I use: Redux, Zustand, or Jotai?",
"parentId": null,
"createdAt": 1704067200000,
"updatedAt": 1704067200000,
"meta": {}
},
{
"id": "parallel-group-state",
"role": "compareGroup",
"content": null,
"parentId": null,
"createdAt": 1704067205000,
"updatedAt": 1704067205000,
"meta": {},
"children": [
{
"id": "resp-redux",
"role": "assistant",
"content": "Redux: Best for large-scale apps with complex state logic...",
"createdAt": "2024-01-01T10:00:05.000Z",
"model": "gpt-4",
"provider": "openai"
},
{
"id": "resp-zustand",
"role": "assistant",
"content": "Zustand: Lightweight and simple, great for most React apps...",
"createdAt": "2024-01-01T10:00:06.000Z",
"model": "claude-3-5-sonnet",
"provider": "anthropic"
}
]
},
{
"id": "msg-decision",
"role": "user",
"content": "I'll go with Zustand then. Let's start implementation.",
"parentId": null,
"createdAt": 1704067210000,
"updatedAt": 1704067210000,
"meta": {}
},
{
"id": "msg-implementation",
"role": "assistant",
"content": "Great choice! Here's how to set up Zustand with TypeScript...",
"parentId": "msg-decision",
"createdAt": 1704067215000,
"updatedAt": 1704067215000,
"meta": {},
"metadata": {
"totalInputTokens": 300,
"totalOutputTokens": 450,
"totalTokens": 750
}
}
]
@@ -0,0 +1,67 @@
[
{
"id": "comp-group-1",
"role": "compressedGroup",
"content": "Summary: Early conversation about project setup and initial requirements.",
"parentId": null,
"createdAt": 1704060000000,
"updatedAt": 1704060000000,
"meta": {},
"pinnedMessages": [
{
"id": "pinned-1-1",
"role": "assistant",
"content": "Key decision: Use TypeScript with strict mode",
"createdAt": "2024-01-01T08:00:00.000Z",
"model": "gpt-4",
"provider": "openai"
}
]
},
{
"id": "msg-middle-001",
"role": "user",
"content": "Let's discuss the database schema",
"parentId": null,
"createdAt": 1704063600000,
"updatedAt": 1704063600000,
"meta": {}
},
{
"id": "msg-middle-002",
"role": "assistant",
"content": "Here's my suggested schema design...",
"parentId": "msg-middle-001",
"createdAt": 1704063605000,
"updatedAt": 1704063605000,
"meta": {}
},
{
"id": "comp-group-2",
"role": "compressedGroup",
"content": "Summary: Database schema discussions concluded with PostgreSQL + Drizzle ORM decision.",
"parentId": null,
"createdAt": 1704067200000,
"updatedAt": 1704067200000,
"meta": {},
"pinnedMessages": []
},
{
"id": "msg-recent-001",
"role": "user",
"content": "Now let's implement the API endpoints",
"parentId": null,
"createdAt": 1704070800000,
"updatedAt": 1704070800000,
"meta": {}
},
{
"id": "msg-recent-002",
"role": "assistant",
"content": "I'll create RESTful endpoints for CRUD operations...",
"parentId": "msg-recent-001",
"createdAt": 1704070805000,
"updatedAt": 1704070805000,
"meta": {}
}
]
@@ -0,0 +1,47 @@
[
{
"id": "msg-user-001",
"role": "user",
"content": "Compare REST vs GraphQL for my use case",
"parentId": null,
"createdAt": 1704067200000,
"updatedAt": 1704067200000,
"meta": {}
},
{
"id": "parallel-group-1",
"role": "compareGroup",
"content": null,
"parentId": null,
"createdAt": 1704067205000,
"updatedAt": 1704067205000,
"meta": {},
"children": [
{
"id": "parallel-resp-gpt4",
"role": "assistant",
"content": "From GPT-4's perspective: REST is simpler and well-suited for CRUD operations...",
"createdAt": "2024-01-01T10:00:05.000Z",
"model": "gpt-4",
"provider": "openai"
},
{
"id": "parallel-resp-claude",
"role": "assistant",
"content": "From Claude's perspective: GraphQL offers more flexibility with its query language...",
"createdAt": "2024-01-01T10:00:06.000Z",
"model": "claude-3-5-sonnet",
"provider": "anthropic"
}
]
},
{
"id": "msg-user-002",
"role": "user",
"content": "Thanks for the comparison!",
"parentId": null,
"createdAt": 1704067210000,
"updatedAt": 1704067210000,
"meta": {}
}
]
@@ -0,0 +1,52 @@
[
{
"id": "comp-group-1",
"role": "compressedGroup",
"content": "Summary: User asked about prime numbers. Assistant provided implementation and test cases.",
"parentId": null,
"createdAt": 1704067205000,
"updatedAt": 1704067205000,
"meta": {},
"pinnedMessages": [
{
"id": "pinned-msg-001",
"role": "assistant",
"content": "Here's a prime number checker function...",
"createdAt": "2024-01-01T10:01:00.000Z",
"model": "gpt-4",
"provider": "openai"
},
{
"id": "pinned-msg-002",
"role": "user",
"content": "Can you add documentation?",
"createdAt": "2024-01-01T10:02:00.000Z",
"model": null,
"provider": null
}
]
},
{
"id": "msg-recent-001",
"role": "user",
"content": "Now let's optimize it further",
"parentId": null,
"createdAt": 1704067210000,
"updatedAt": 1704067210000,
"meta": {}
},
{
"id": "msg-recent-002",
"role": "assistant",
"content": "Sure! Here's an optimized version using the Sieve of Eratosthenes...",
"parentId": "msg-recent-001",
"createdAt": 1704067215000,
"updatedAt": 1704067215000,
"meta": {},
"metadata": {
"totalInputTokens": 200,
"totalOutputTokens": 150,
"totalTokens": 350
}
}
]
@@ -5,6 +5,7 @@ import assistantChainWithFollowup from './assistant-chain-with-followup.json';
import { assistantGroup } from './assistantGroup';
import { branch } from './branch';
import { compare } from './compare';
import { compression } from './compression';
import linearConversation from './linear-conversation.json';
import { tasks } from './tasks';
@@ -15,6 +16,7 @@ export const inputs = {
assistantGroup,
branch,
compare,
compression,
linearConversation: linearConversation as Message[],
tasks,
};
@@ -12,7 +12,15 @@ interface BaseNode {
/** Unique identifier for this node */
id: string;
/** Type discriminator */
type: 'message' | 'assistantGroup' | 'compare' | 'branch' | 'agentCouncil' | 'tasks';
type:
| 'message'
| 'assistantGroup'
| 'compare'
| 'branch'
| 'agentCouncil'
| 'tasks'
| 'compressedGroup'
| 'compareGroup';
}
/**
@@ -83,6 +91,54 @@ export interface TasksNode extends BaseNode {
type: 'tasks';
}
/**
* Pinned message within a compression group
*/
export interface PinnedMessage {
content: string | null;
createdAt: Date | string;
id: string;
model: string | null;
provider: string | null;
role: string;
}
/**
* Compressed Group node - represents compressed/summarized messages
* Messages marked as compressed are hidden, and a summary is shown instead.
* Pinned messages (favorite=true) within the compression group are preserved.
*/
export interface CompressedGroupNode extends BaseNode {
/** Summary content of the compressed messages */
content: string | null;
/** Messages marked as favorite/pinned within this compression group */
pinnedMessages: PinnedMessage[];
type: 'compressedGroup';
}
/**
* Child message within a compare group (parallel responses)
*/
export interface CompareGroupChild {
content: string | null;
createdAt: Date | string;
id: string;
model: string | null;
provider: string | null;
role: string;
}
/**
* Compare Group node - represents parallel model responses
* Multiple models respond to the same user message in parallel.
* Different from CompareNode which is built from metadata.compare flag.
*/
export interface CompareGroupNode extends BaseNode {
/** Parallel responses from different models */
children: CompareGroupChild[];
type: 'compareGroup';
}
/**
* Union type of all display nodes
*/
@@ -92,4 +148,6 @@ export type ContextNode =
| CompareNode
| BranchNode
| AgentCouncilNode
| TasksNode;
| TasksNode
| CompressedGroupNode
| CompareGroupNode;
@@ -23,6 +23,10 @@ import type { UIChatMessage } from '@lobechat/types';
* - 'compare': Compare mode for parallel model outputs
* - 'agentCouncil': Multi-agent parallel responses (all enter context)
* - 'tasks': Aggregated async task messages with same parentId
*
* Database-provided roles from MessageModel.query with MessageGroup aggregation:
* - 'compressedGroup': Compressed/summarized messages with optional pinned messages
* - 'compareGroup': Parallel model responses (from database, not metadata-driven)
*/
export type FlatMessageRole =
| 'user'
@@ -34,7 +38,9 @@ export type FlatMessageRole =
| 'messageGroup'
| 'compare'
| 'agentCouncil'
| 'tasks';
| 'tasks'
| 'compressedGroup'
| 'compareGroup';
/**
* Message in flat list
@@ -14,10 +14,14 @@ export type {
AgentCouncilNode,
AssistantGroupNode,
BranchNode,
CompareGroupChild,
CompareGroupNode,
CompareNode,
CompressedGroupNode,
ContextNode,
MessageNode,
TasksNode,
PinnedMessage,
} from './contextTree';
// Flat Message List Types