@lobehub/lobehub 2.0.0-next.32 → 2.0.0-next.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.github/workflows/test.yml +1 -0
  2. package/CHANGELOG.md +33 -0
  3. package/apps/desktop/package.json +1 -1
  4. package/changelog/v1.json +12 -0
  5. package/docker-compose/local/.env.example +3 -0
  6. package/docs/self-hosting/server-database/docker-compose.mdx +29 -0
  7. package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +29 -0
  8. package/package.json +1 -1
  9. package/packages/const/src/hotkeys.ts +3 -3
  10. package/packages/const/src/models.ts +2 -2
  11. package/packages/const/src/utils/merge.ts +3 -3
  12. package/packages/conversation-flow/package.json +13 -0
  13. package/packages/conversation-flow/src/__tests__/fixtures/index.ts +48 -0
  14. package/packages/conversation-flow/src/__tests__/fixtures/inputs/assistant-chain-with-followup.json +56 -0
  15. package/packages/conversation-flow/src/__tests__/fixtures/inputs/assistant-with-tools.json +144 -0
  16. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/active-index-1.json +131 -0
  17. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/assistant-branch.json +96 -0
  18. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/assistant-user-branch.json +123 -0
  19. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/conversation.json +128 -0
  20. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/index.ts +14 -0
  21. package/packages/conversation-flow/src/__tests__/fixtures/inputs/branch/nested.json +179 -0
  22. package/packages/conversation-flow/src/__tests__/fixtures/inputs/compare/index.ts +8 -0
  23. package/packages/conversation-flow/src/__tests__/fixtures/inputs/compare/simple.json +85 -0
  24. package/packages/conversation-flow/src/__tests__/fixtures/inputs/compare/with-tools.json +169 -0
  25. package/packages/conversation-flow/src/__tests__/fixtures/inputs/complex-scenario.json +107 -0
  26. package/packages/conversation-flow/src/__tests__/fixtures/inputs/index.ts +14 -0
  27. package/packages/conversation-flow/src/__tests__/fixtures/inputs/linear-conversation.json +59 -0
  28. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistant-chain-with-followup.json +135 -0
  29. package/packages/conversation-flow/src/__tests__/fixtures/outputs/assistant-with-tools.json +340 -0
  30. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/active-index-1.json +242 -0
  31. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/assistant-branch.json +208 -0
  32. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/assistant-user-branch.json +254 -0
  33. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/conversation.json +260 -0
  34. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/index.ts +14 -0
  35. package/packages/conversation-flow/src/__tests__/fixtures/outputs/branch/nested.json +389 -0
  36. package/packages/conversation-flow/src/__tests__/fixtures/outputs/compare/index.ts +8 -0
  37. package/packages/conversation-flow/src/__tests__/fixtures/outputs/compare/simple.json +224 -0
  38. package/packages/conversation-flow/src/__tests__/fixtures/outputs/compare/with-tools.json +418 -0
  39. package/packages/conversation-flow/src/__tests__/fixtures/outputs/complex-scenario.json +239 -0
  40. package/packages/conversation-flow/src/__tests__/fixtures/outputs/linear-conversation.json +138 -0
  41. package/packages/conversation-flow/src/__tests__/parse.test.ts +97 -0
  42. package/packages/conversation-flow/src/index.ts +17 -0
  43. package/packages/conversation-flow/src/indexing.ts +58 -0
  44. package/packages/conversation-flow/src/parse.ts +53 -0
  45. package/packages/conversation-flow/src/structuring.ts +38 -0
  46. package/packages/conversation-flow/src/transformation/BranchResolver.ts +66 -0
  47. package/packages/conversation-flow/src/transformation/ContextTreeBuilder.ts +292 -0
  48. package/packages/conversation-flow/src/transformation/FlatListBuilder.ts +421 -0
  49. package/packages/conversation-flow/src/transformation/MessageCollector.ts +166 -0
  50. package/packages/conversation-flow/src/transformation/MessageTransformer.ts +177 -0
  51. package/packages/conversation-flow/src/transformation/__tests__/BranchResolver.test.ts +151 -0
  52. package/packages/conversation-flow/src/transformation/__tests__/ContextTreeBuilder.test.ts +385 -0
  53. package/packages/conversation-flow/src/transformation/__tests__/FlatListBuilder.test.ts +511 -0
  54. package/packages/conversation-flow/src/transformation/__tests__/MessageCollector.test.ts +220 -0
  55. package/packages/conversation-flow/src/transformation/__tests__/MessageTransformer.test.ts +287 -0
  56. package/packages/conversation-flow/src/transformation/index.ts +78 -0
  57. package/packages/conversation-flow/src/types/contextTree.ts +65 -0
  58. package/packages/conversation-flow/src/types/flatMessageList.ts +66 -0
  59. package/packages/conversation-flow/src/types/shared.ts +63 -0
  60. package/packages/conversation-flow/src/types.ts +36 -0
  61. package/packages/conversation-flow/vitest.config.mts +10 -0
  62. package/packages/types/src/message/common/metadata.ts +5 -1
  63. package/src/app/[variants]/(main)/chat/@session/features/SessionListContent/List/Item/index.tsx +3 -4
  64. package/src/envs/__tests__/app.test.ts +47 -13
  65. package/src/envs/app.ts +6 -0
  66. package/src/server/routers/async/__tests__/caller.test.ts +333 -0
  67. package/src/server/routers/async/caller.ts +2 -1
  68. package/src/server/routers/lambda/__tests__/integration/message.integration.test.ts +57 -57
  69. package/src/server/routers/lambda/message.ts +2 -2
  70. package/src/server/services/message/__tests__/index.test.ts +4 -4
  71. package/src/server/services/message/index.ts +1 -1
  72. package/src/services/message/index.ts +2 -3
  73. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChat.test.ts +8 -8
  74. package/src/store/chat/slices/aiChat/actions/__tests__/generateAIChatV2.test.ts +8 -8
  75. package/src/store/chat/slices/aiChat/actions/__tests__/helpers.ts +1 -1
  76. package/src/store/chat/slices/aiChat/actions/generateAIChatV2.ts +1 -1
  77. package/src/store/chat/slices/message/action.test.ts +7 -7
  78. package/src/store/chat/slices/message/action.ts +2 -2
  79. package/src/store/chat/slices/plugin/action.test.ts +7 -7
  80. package/src/store/chat/slices/plugin/action.ts +1 -1
  81. package/packages/context-engine/ARCHITECTURE.md +0 -425
@@ -131,7 +131,7 @@ describe('generateAIChatV2 actions', () => {
131
131
  await result.current.sendMessage({ message: TEST_CONTENT.USER_MESSAGE });
132
132
  });
133
133
 
134
- expect(messageService.createNewMessage).not.toHaveBeenCalled();
134
+ expect(messageService.createMessage).not.toHaveBeenCalled();
135
135
  expect(result.current.internal_execAgentRuntime).not.toHaveBeenCalled();
136
136
  });
137
137
 
@@ -142,7 +142,7 @@ describe('generateAIChatV2 actions', () => {
142
142
  await result.current.sendMessage({ message: TEST_CONTENT.EMPTY });
143
143
  });
144
144
 
145
- expect(messageService.createNewMessage).not.toHaveBeenCalled();
145
+ expect(messageService.createMessage).not.toHaveBeenCalled();
146
146
  });
147
147
 
148
148
  it('should not send when message is empty with empty files array', async () => {
@@ -152,7 +152,7 @@ describe('generateAIChatV2 actions', () => {
152
152
  await result.current.sendMessage({ message: TEST_CONTENT.EMPTY, files: [] });
153
153
  });
154
154
 
155
- expect(messageService.createNewMessage).not.toHaveBeenCalled();
155
+ expect(messageService.createMessage).not.toHaveBeenCalled();
156
156
  });
157
157
  });
158
158
 
@@ -312,7 +312,7 @@ describe('generateAIChatV2 actions', () => {
312
312
  });
313
313
  });
314
314
 
315
- expect(messageService.createNewMessage).toHaveBeenCalled();
315
+ expect(messageService.createMessage).toHaveBeenCalled();
316
316
  expect(result.current.internal_execAgentRuntime).not.toHaveBeenCalled();
317
317
  });
318
318
 
@@ -749,7 +749,7 @@ describe('generateAIChatV2 actions', () => {
749
749
 
750
750
  beforeEach(() => {
751
751
  // Reset mocks
752
- vi.spyOn(messageService, 'createNewMessage').mockResolvedValue({
752
+ vi.spyOn(messageService, 'createMessage').mockResolvedValue({
753
753
  id: 'new-assistant-block-id',
754
754
  messages: [] as any,
755
755
  });
@@ -814,8 +814,8 @@ describe('generateAIChatV2 actions', () => {
814
814
  }),
815
815
  );
816
816
 
817
- // Verify that createNewMessage was called with message params
818
- expect(messageService.createNewMessage).toHaveBeenCalledWith(
817
+ // Verify that createMessage was called with message params
818
+ expect(messageService.createMessage).toHaveBeenCalledWith(
819
819
  expect.objectContaining({
820
820
  role: 'assistant',
821
821
  parentId: TOOL_RESULT_MSG_ID,
@@ -866,7 +866,7 @@ describe('generateAIChatV2 actions', () => {
866
866
  }),
867
867
  );
868
868
 
869
- expect(messageService.createNewMessage).toHaveBeenCalledWith(
869
+ expect(messageService.createMessage).toHaveBeenCalledWith(
870
870
  expect.objectContaining({
871
871
  role: 'assistant',
872
872
  parentId: 'non-existent-tool-result-id',
@@ -58,7 +58,7 @@ export const createMockAbortController = () => {
58
58
  */
59
59
  export const spyOnMessageService = () => {
60
60
  const createMessageSpy = vi
61
- .spyOn(messageService, 'createNewMessage')
61
+ .spyOn(messageService, 'createMessage')
62
62
  .mockResolvedValue({ id: TEST_IDS.NEW_MESSAGE_ID, messages: [] });
63
63
  const updateMessageSpy = vi
64
64
  .spyOn(messageService, 'updateMessage')
@@ -646,7 +646,7 @@ export const generateAIChatV2: StateCreator<
646
646
  payload.type,
647
647
  );
648
648
 
649
- // 2. 使用 createNewMessage 创建 tool 消息
649
+ // 2. 使用 createMessage 创建 tool 消息
650
650
  const toolMessage: CreateNewMessageParams = {
651
651
  content: '',
652
652
  parentId: assistantId,
@@ -25,7 +25,7 @@ vi.mock('@/services/message', () => ({
25
25
  removeMessage: vi.fn(),
26
26
  removeMessagesByAssistant: vi.fn(),
27
27
  removeMessages: vi.fn(() => Promise.resolve()),
28
- createNewMessage: vi.fn(() => Promise.resolve({ id: 'new-message-id', messages: [] })),
28
+ createMessage: vi.fn(() => Promise.resolve({ id: 'new-message-id', messages: [] })),
29
29
  updateMessage: vi.fn(),
30
30
  removeAllMessages: vi.fn(() => Promise.resolve()),
31
31
  },
@@ -71,7 +71,7 @@ describe('chatMessage actions', () => {
71
71
  await result.current.addAIMessage();
72
72
  });
73
73
 
74
- expect(messageService.createNewMessage).not.toHaveBeenCalled();
74
+ expect(messageService.createMessage).not.toHaveBeenCalled();
75
75
  expect(updateInputMessageSpy).not.toHaveBeenCalled();
76
76
  });
77
77
 
@@ -84,7 +84,7 @@ describe('chatMessage actions', () => {
84
84
  await result.current.addAIMessage();
85
85
  });
86
86
 
87
- expect(messageService.createNewMessage).toHaveBeenCalledWith({
87
+ expect(messageService.createMessage).toHaveBeenCalledWith({
88
88
  content: inputMessage,
89
89
  role: 'assistant',
90
90
  sessionId: mockState.activeId,
@@ -113,7 +113,7 @@ describe('chatMessage actions', () => {
113
113
  await result.current.addUserMessage({ message: 'test message' });
114
114
  });
115
115
 
116
- expect(messageService.createNewMessage).not.toHaveBeenCalled();
116
+ expect(messageService.createMessage).not.toHaveBeenCalled();
117
117
  expect(updateInputMessageSpy).not.toHaveBeenCalled();
118
118
  });
119
119
 
@@ -130,7 +130,7 @@ describe('chatMessage actions', () => {
130
130
  await result.current.addUserMessage({ message, fileList });
131
131
  });
132
132
 
133
- expect(messageService.createNewMessage).toHaveBeenCalledWith({
133
+ expect(messageService.createMessage).toHaveBeenCalledWith({
134
134
  content: message,
135
135
  files: fileList,
136
136
  role: 'user',
@@ -154,7 +154,7 @@ describe('chatMessage actions', () => {
154
154
  await result.current.addUserMessage({ message });
155
155
  });
156
156
 
157
- expect(messageService.createNewMessage).toHaveBeenCalledWith({
157
+ expect(messageService.createMessage).toHaveBeenCalledWith({
158
158
  content: message,
159
159
  files: undefined,
160
160
  role: 'user',
@@ -184,7 +184,7 @@ describe('chatMessage actions', () => {
184
184
  await result.current.addUserMessage({ message });
185
185
  });
186
186
 
187
- expect(messageService.createNewMessage).toHaveBeenCalledWith({
187
+ expect(messageService.createMessage).toHaveBeenCalledWith({
188
188
  content: message,
189
189
  files: undefined,
190
190
  role: 'user',
@@ -519,10 +519,10 @@ export const chatMessage: StateCreator<
519
519
  }
520
520
 
521
521
  try {
522
- const result = await messageService.createNewMessage(message);
522
+ const result = await messageService.createMessage(message);
523
523
 
524
524
  if (!context?.skipRefresh) {
525
- // Use the messages returned from createNewMessage (already grouped)
525
+ // Use the messages returned from createMessage (already grouped)
526
526
  replaceMessages(result.messages);
527
527
  }
528
528
 
@@ -26,7 +26,7 @@ vi.mock('@/services/message', () => ({
26
26
  updateMessageError: vi.fn(),
27
27
  updateMessagePluginState: vi.fn(),
28
28
  updateMessagePluginArguments: vi.fn(),
29
- createNewMessage: vi.fn(),
29
+ createMessage: vi.fn(),
30
30
  },
31
31
  }));
32
32
 
@@ -565,8 +565,8 @@ describe('ChatPluginAction', () => {
565
565
  describe('createAssistantMessageByPlugin', () => {
566
566
  it('should create an assistant message and replace messages', async () => {
567
567
  const mockMessages = [{ id: 'msg-1', content: 'test' }] as any;
568
- // 模拟 messageService.createNewMessage 方法的实现
569
- (messageService.createNewMessage as Mock).mockResolvedValue({
568
+ // 模拟 messageService.createMessage 方法的实现
569
+ (messageService.createMessage as Mock).mockResolvedValue({
570
570
  id: 'new-message-id',
571
571
  messages: mockMessages,
572
572
  });
@@ -588,8 +588,8 @@ describe('ChatPluginAction', () => {
588
588
  await result.current.createAssistantMessageByPlugin(content, parentId);
589
589
  });
590
590
 
591
- // 验证 messageService.createNewMessage 是否被带有正确参数调用
592
- expect(messageService.createNewMessage).toHaveBeenCalledWith({
591
+ // 验证 messageService.createMessage 是否被带有正确参数调用
592
+ expect(messageService.createMessage).toHaveBeenCalledWith({
593
593
  content,
594
594
  parentId,
595
595
  role: 'assistant',
@@ -604,7 +604,7 @@ describe('ChatPluginAction', () => {
604
604
  it('should handle errors when message creation fails', async () => {
605
605
  // 模拟 messageService.create 方法,使其抛出错误
606
606
  const errorMessage = 'Failed to create message';
607
- (messageService.createNewMessage as Mock).mockRejectedValue(new Error(errorMessage));
607
+ (messageService.createMessage as Mock).mockRejectedValue(new Error(errorMessage));
608
608
 
609
609
  // 设置初始状态并模拟 refreshMessages 方法
610
610
  const initialState = {
@@ -626,7 +626,7 @@ describe('ChatPluginAction', () => {
626
626
  });
627
627
 
628
628
  // 验证 messageService.create 是否被带有正确参数调用
629
- expect(messageService.createNewMessage).toHaveBeenCalledWith({
629
+ expect(messageService.createMessage).toHaveBeenCalledWith({
630
630
  content,
631
631
  parentId,
632
632
  role: 'assistant',
@@ -98,7 +98,7 @@ export const chatPlugin: StateCreator<
98
98
  topicId: get().activeTopicId, // if there is activeTopicId,then add it to topicId
99
99
  };
100
100
 
101
- const result = await messageService.createNewMessage(newMessage);
101
+ const result = await messageService.createMessage(newMessage);
102
102
  get().replaceMessages(result.messages);
103
103
  },
104
104
 
@@ -1,425 +0,0 @@
1
- # Context Engine 架构设计
2
-
3
- ## 概述
4
-
5
- Context Engine 是一个灵活的消息处理管道系统,用于在 AI 对话中动态管理和处理上下文信息。它提供了一种可扩展的方式来注入、转换和验证消息流。
6
-
7
- ## 核心概念
8
-
9
- ### 1. 处理器(Processor)
10
-
11
- 处理器是 Context Engine 的基本单元,负责对消息进行特定的处理操作。
12
-
13
- #### 处理器分类
14
-
15
- 根据功能职责,处理器分为以下几类:
16
-
17
- 1. **注入器(Injector)**
18
- - 职责:向消息流中添加新的上下文信息
19
- - 示例:SystemRoleInjector、HistoryInjector、RAGContextInjector
20
-
21
- 2. **转换器(Transformer)**
22
- - 职责:修改现有消息的内容或结构
23
- - 示例:MessageRoleTransformer、ImageContentProcessor
24
-
25
- 3. **截断器(Truncator)**
26
- - 职责:根据特定规则裁剪消息内容
27
- - 示例:HistoryTruncator、TokenBasedTruncator
28
-
29
- 4. **验证器(Validator)**
30
- - 职责:验证消息是否符合特定要求
31
- - 示例:ModelCapabilityValidator
32
-
33
- 5. **重排器(Reorderer)**
34
- - 职责:调整消息的顺序
35
- - 示例:ToolMessageReorder
36
-
37
- ### 2. 管道(Pipeline)
38
-
39
- 管道是一系列处理器的有序组合,消息流经管道时会被逐个处理器处理。
40
-
41
- ```typescript
42
- interface Pipeline {
43
- // 添加处理器到管道
44
- add(processor: BaseProcessor): Pipeline;
45
-
46
- // 执行管道处理
47
- execute(context: ProcessorContext): Promise<ProcessorContext>;
48
-
49
- // 获取管道中的所有处理器
50
- getProcessors(): BaseProcessor[];
51
- }
52
- ```
53
-
54
- ### 3. 上下文(Context)
55
-
56
- 上下文包含了处理器需要的所有信息:
57
-
58
- ```typescript
59
- interface ProcessorContext {
60
- messages: Message[]; // 消息列表
61
- metadata?: ProcessorMetadata; // 元数据
62
- variables?: Record<string, any>; // 变量
63
- abortSignal?: AbortSignal; // 中止信号
64
- }
65
- ```
66
-
67
- ## 架构设计
68
-
69
- ### 类层次结构
70
-
71
- ```
72
- BaseProcessor (抽象基类)
73
- ├── BaseInjector (注入器基类)
74
- │ ├── SystemRoleInjector
75
- │ ├── HistoryInjector
76
- │ ├── RAGContextInjector
77
- │ └── ...
78
- ├── BaseTransformer (转换器基类)
79
- │ ├── MessageRoleTransformer
80
- │ └── ImageContentProcessor
81
- ├── BaseTruncator (截断器基类)
82
- │ ├── HistoryTruncator
83
- │ └── TokenBasedTruncator
84
- ├── BaseValidator (验证器基类)
85
- │ └── ModelCapabilityValidator
86
- └── BaseReorderer (重排器基类)
87
- └── ToolMessageReorder
88
- ```
89
-
90
- ### 核心接口设计
91
-
92
- #### BaseProcessor
93
-
94
- ```typescript
95
- abstract class BaseProcessor {
96
- // 处理器类型
97
- abstract readonly type: ProcessorType;
98
-
99
- // 处理器名称
100
- abstract readonly name: string;
101
-
102
- // 主处理方法
103
- async process(context: ProcessorContext): Promise<ProcessorContext> {
104
- // 1. 前置验证
105
- this.validateInput(context);
106
-
107
- // 2. 执行处理
108
- const result = await this.doProcess(context);
109
-
110
- // 3. 后置验证
111
- this.validateOutput(result);
112
-
113
- return result;
114
- }
115
-
116
- // 子类实现的核心处理逻辑
117
- protected abstract doProcess(context: ProcessorContext): Promise<ProcessorContext>;
118
-
119
- // 输入验证(可选覆盖)
120
- protected validateInput(context: ProcessorContext): void {}
121
-
122
- // 输出验证(可选覆盖)
123
- protected validateOutput(context: ProcessorContext): void {}
124
- }
125
- ```
126
-
127
- #### BaseInjector
128
-
129
- ```typescript
130
- abstract class BaseInjector extends BaseProcessor {
131
- readonly type = ProcessorType.Injector;
132
-
133
- protected async doProcess(context: ProcessorContext): Promise<ProcessorContext> {
134
- // 1. 判断是否需要注入
135
- if (!this.shouldInject(context)) {
136
- return context;
137
- }
138
-
139
- // 2. 构建注入内容
140
- const content = await this.buildContent(context);
141
-
142
- // 3. 创建消息
143
- const message = this.createMessage(content, context);
144
-
145
- // 4. 确定注入位置
146
- const position = this.getInjectionPosition(context);
147
-
148
- // 5. 执行注入
149
- return this.inject(context, message, position);
150
- }
151
-
152
- // 子类需要实现的方法
153
- protected abstract shouldInject(context: ProcessorContext): boolean;
154
- protected abstract buildContent(context: ProcessorContext): Promise<string>;
155
-
156
- // 可选覆盖的方法
157
- protected getInjectionPosition(context: ProcessorContext): number {
158
- return 0; // 默认注入到开头
159
- }
160
-
161
- protected createMessage(content: string, context: ProcessorContext): Message {
162
- return {
163
- role: 'system',
164
- content,
165
- metadata: { injectedBy: this.name }
166
- };
167
- }
168
- }
169
- ```
170
-
171
- ## 使用方式
172
-
173
- ### 1. 创建自定义处理器
174
-
175
- ```typescript
176
- // 创建一个自定义注入器
177
- class CustomContextInjector extends BaseInjector {
178
- readonly name = 'custom-context-injector';
179
-
180
- protected shouldInject(context: ProcessorContext): boolean {
181
- // 判断逻辑
182
- return !context.messages.some(msg =>
183
- msg.metadata?.injectedBy === this.name
184
- );
185
- }
186
-
187
- protected async buildContent(context: ProcessorContext): Promise<string> {
188
- // 构建内容逻辑
189
- return `Custom context: ${context.variables?.customValue}`;
190
- }
191
- }
192
- ```
193
-
194
- ### 2. 构建处理管道
195
-
196
- ```typescript
197
- // 使用工厂模式创建管道
198
- const pipeline = createPipeline()
199
- .add(new SystemRoleInjector())
200
- .add(new HistoryInjector({ maxMessages: 10 }))
201
- .add(new CustomContextInjector())
202
- .add(new MessageRoleTransformer())
203
- .add(new TokenBasedTruncator({ maxTokens: 4000 }))
204
- .add(new ModelCapabilityValidator());
205
-
206
- // 执行管道
207
- const result = await pipeline.execute({
208
- messages: initialMessages,
209
- variables: { customValue: 'test' },
210
- metadata: { model: 'gpt-4' }
211
- });
212
- ```
213
-
214
- ### 3. 条件处理
215
-
216
- ```typescript
217
- // 基于条件的管道构建
218
- const pipeline = createPipeline();
219
-
220
- if (config.enableRAG) {
221
- pipeline.add(new RAGContextInjector());
222
- }
223
-
224
- if (config.enableSearch) {
225
- pipeline.add(new SearchContextInjector());
226
- }
227
-
228
- // 始终添加的处理器
229
- pipeline
230
- .add(new HistoryTruncator())
231
- .add(new ModelCapabilityValidator());
232
- ```
233
-
234
- ### 4. 错误处理
235
-
236
- ```typescript
237
- try {
238
- const result = await pipeline.execute(context);
239
- } catch (error) {
240
- if (error instanceof ProcessorError) {
241
- console.error(`Processor ${error.processorName} failed:`, error.message);
242
- } else if (error instanceof PipelineError) {
243
- console.error('Pipeline execution failed:', error.message);
244
- }
245
- }
246
- ```
247
-
248
- ## 配置管理
249
-
250
- ### 处理器配置
251
-
252
- 每个处理器可以接受特定的配置选项:
253
-
254
- ```typescript
255
- interface ProcessorConfig {
256
- // 通用配置
257
- enabled?: boolean;
258
- priority?: number;
259
-
260
- // 处理器特定配置
261
- [key: string]: any;
262
- }
263
-
264
- // 示例:历史注入器配置
265
- interface HistoryInjectorConfig extends ProcessorConfig {
266
- maxMessages?: number;
267
- includeSystemMessages?: boolean;
268
- preserveTools?: boolean;
269
- }
270
- ```
271
-
272
- ### 管道配置
273
-
274
- ```typescript
275
- interface PipelineConfig {
276
- processors: Array<{
277
- type: string;
278
- config?: ProcessorConfig;
279
- }>;
280
-
281
- // 全局配置
282
- abortOnError?: boolean;
283
- timeout?: number;
284
- }
285
-
286
- // 从配置创建管道
287
- const pipeline = createPipelineFromConfig({
288
- processors: [
289
- { type: 'system-role', config: { enabled: true } },
290
- { type: 'history', config: { maxMessages: 20 } },
291
- { type: 'rag', config: { threshold: 0.7 } }
292
- ],
293
- abortOnError: false,
294
- timeout: 30000
295
- });
296
- ```
297
-
298
- ## 最佳实践
299
-
300
- ### 1. 单一职责原则
301
- 每个处理器应该只负责一种特定的处理任务。
302
-
303
- ### 2. 可配置性
304
- 处理器应该通过配置参数来控制行为,而不是硬编码。
305
-
306
- ### 3. 错误处理
307
- - 使用具体的错误类型
308
- - 提供有意义的错误信息
309
- - 考虑错误恢复策略
310
-
311
- ### 4. 性能优化
312
- - 避免不必要的消息复制
313
- - 使用流式处理处理大量数据
314
- - 实现适当的缓存机制
315
-
316
- ### 5. 测试
317
- - 为每个处理器编写单元测试
318
- - 测试处理器组合的集成测试
319
- - 边界条件和错误场景测试
320
-
321
- ## 扩展机制
322
-
323
- ### 1. 自定义处理器类型
324
-
325
- ```typescript
326
- // 定义新的处理器类型
327
- enum CustomProcessorType {
328
- Analyzer = 'analyzer',
329
- Enhancer = 'enhancer'
330
- }
331
-
332
- // 创建对应的基类
333
- abstract class BaseAnalyzer extends BaseProcessor {
334
- readonly type = CustomProcessorType.Analyzer;
335
-
336
- // 分析器特定的方法
337
- protected abstract analyze(messages: Message[]): AnalysisResult;
338
- }
339
- ```
340
-
341
- ### 2. 处理器组合
342
-
343
- ```typescript
344
- // 创建复合处理器
345
- class CompositeProcessor extends BaseProcessor {
346
- constructor(private processors: BaseProcessor[]) {
347
- super();
348
- }
349
-
350
- protected async doProcess(context: ProcessorContext): Promise<ProcessorContext> {
351
- let result = context;
352
- for (const processor of this.processors) {
353
- result = await processor.process(result);
354
- }
355
- return result;
356
- }
357
- }
358
- ```
359
-
360
- ### 3. 插件系统
361
-
362
- ```typescript
363
- interface ProcessorPlugin {
364
- name: string;
365
- version: string;
366
- processors: ProcessorDefinition[];
367
- }
368
-
369
- // 注册插件
370
- registry.registerPlugin({
371
- name: 'custom-processors',
372
- version: '1.0.0',
373
- processors: [
374
- { type: 'custom-injector', factory: () => new CustomInjector() },
375
- { type: 'custom-validator', factory: () => new CustomValidator() }
376
- ]
377
- });
378
- ```
379
-
380
- ## 迁移指南
381
-
382
- ### 从当前架构迁移
383
-
384
- 1. **BaseProvider 迁移到 BaseInjector**
385
- ```typescript
386
- // 旧代码
387
- class MyProvider extends BaseProvider {
388
- doProcess(context) {
389
- // 实现
390
- }
391
- }
392
-
393
- // 新代码
394
- class MyInjector extends BaseInjector {
395
- shouldInject(context) {
396
- // 判断逻辑
397
- }
398
-
399
- buildContent(context) {
400
- // 构建内容
401
- }
402
- }
403
- ```
404
-
405
- 2. **处理器分类**
406
- - 将现有处理器按功能分类
407
- - 继承对应的基类
408
- - 实现必要的抽象方法
409
-
410
- 3. **配置迁移**
411
- - 统一配置格式
412
- - 支持向后兼容
413
- - 提供迁移工具
414
-
415
- ## 总结
416
-
417
- 新的 Context Engine 架构提供了:
418
-
419
- 1. **清晰的分层结构**:基于功能的处理器分类
420
- 2. **灵活的扩展机制**:易于添加新的处理器类型
421
- 3. **强大的组合能力**:通过管道组合实现复杂功能
422
- 4. **完善的错误处理**:细粒度的错误类型和恢复策略
423
- 5. **优秀的可测试性**:模块化设计便于单元测试
424
-
425
- 这种设计使得 Context Engine 更加模块化、可维护和可扩展,能够更好地满足不同场景下的上下文处理需求。