@cicctencent/agent-core 0.1.17 → 0.1.19

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 (210) hide show
  1. package/README.md +70 -1
  2. package/dist/cjs/agent/engine.d.ts +23 -0
  3. package/dist/cjs/agent/engine.d.ts.map +1 -1
  4. package/dist/cjs/agent/engine.js +78 -5
  5. package/dist/cjs/agent/engine.js.map +1 -1
  6. package/dist/cjs/agent/history-manager.d.ts +66 -1
  7. package/dist/cjs/agent/history-manager.d.ts.map +1 -1
  8. package/dist/cjs/agent/history-manager.js +232 -0
  9. package/dist/cjs/agent/history-manager.js.map +1 -1
  10. package/dist/cjs/agent/llm-caller.d.ts.map +1 -1
  11. package/dist/cjs/agent/llm-caller.js +10 -4
  12. package/dist/cjs/agent/llm-caller.js.map +1 -1
  13. package/dist/cjs/agent/profile-loader.d.ts +56 -0
  14. package/dist/cjs/agent/profile-loader.d.ts.map +1 -0
  15. package/dist/cjs/agent/profile-loader.js +145 -0
  16. package/dist/cjs/agent/profile-loader.js.map +1 -0
  17. package/dist/cjs/agent/types.d.ts +32 -3
  18. package/dist/cjs/agent/types.d.ts.map +1 -1
  19. package/dist/cjs/agent/types.js.map +1 -1
  20. package/dist/cjs/context/types.d.ts +3 -3
  21. package/dist/cjs/context/types.d.ts.map +1 -1
  22. package/dist/cjs/index.d.ts +26 -2
  23. package/dist/cjs/index.d.ts.map +1 -1
  24. package/dist/cjs/index.js +42 -11
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/kb/in-memory-kb.d.ts +29 -0
  27. package/dist/cjs/kb/in-memory-kb.d.ts.map +1 -0
  28. package/dist/cjs/kb/in-memory-kb.js +210 -0
  29. package/dist/cjs/kb/in-memory-kb.js.map +1 -0
  30. package/dist/cjs/kb/rag-middleware.d.ts +31 -0
  31. package/dist/cjs/kb/rag-middleware.d.ts.map +1 -0
  32. package/dist/cjs/kb/rag-middleware.js +94 -0
  33. package/dist/cjs/kb/rag-middleware.js.map +1 -0
  34. package/dist/cjs/kb/types.d.ts +80 -0
  35. package/dist/cjs/kb/types.d.ts.map +1 -0
  36. package/dist/cjs/kb/types.js +6 -0
  37. package/dist/cjs/kb/types.js.map +1 -0
  38. package/dist/cjs/llm/anthropic-provider.d.ts +7 -0
  39. package/dist/cjs/llm/anthropic-provider.d.ts.map +1 -1
  40. package/dist/cjs/llm/anthropic-provider.js +84 -9
  41. package/dist/cjs/llm/anthropic-provider.js.map +1 -1
  42. package/dist/cjs/llm/openai-provider.d.ts +9 -0
  43. package/dist/cjs/llm/openai-provider.d.ts.map +1 -1
  44. package/dist/cjs/llm/openai-provider.js +41 -1
  45. package/dist/cjs/llm/openai-provider.js.map +1 -1
  46. package/dist/cjs/llm/pricing.d.ts +26 -0
  47. package/dist/cjs/llm/pricing.d.ts.map +1 -0
  48. package/dist/cjs/llm/pricing.js +86 -0
  49. package/dist/cjs/llm/pricing.js.map +1 -0
  50. package/dist/cjs/llm/usage-tracker.d.ts +119 -0
  51. package/dist/cjs/llm/usage-tracker.d.ts.map +1 -0
  52. package/dist/cjs/llm/usage-tracker.js +105 -0
  53. package/dist/cjs/llm/usage-tracker.js.map +1 -0
  54. package/dist/cjs/memory/extractor.js +1 -1
  55. package/dist/cjs/memory/extractor.js.map +1 -1
  56. package/dist/cjs/memory/persona.js +1 -1
  57. package/dist/cjs/memory/persona.js.map +1 -1
  58. package/dist/cjs/memory/scene.js +1 -1
  59. package/dist/cjs/memory/scene.js.map +1 -1
  60. package/dist/cjs/middleware/types.d.ts +2 -4
  61. package/dist/cjs/middleware/types.d.ts.map +1 -1
  62. package/dist/cjs/middleware/workspace-notes.d.ts +36 -0
  63. package/dist/cjs/middleware/workspace-notes.d.ts.map +1 -0
  64. package/dist/cjs/middleware/workspace-notes.js +53 -0
  65. package/dist/cjs/middleware/workspace-notes.js.map +1 -0
  66. package/dist/cjs/observability/logger.d.ts +1 -0
  67. package/dist/cjs/observability/logger.d.ts.map +1 -1
  68. package/dist/cjs/observability/logger.js.map +1 -1
  69. package/dist/cjs/observability/trace.d.ts +45 -0
  70. package/dist/cjs/observability/trace.d.ts.map +1 -0
  71. package/dist/cjs/observability/trace.js +59 -0
  72. package/dist/cjs/observability/trace.js.map +1 -0
  73. package/dist/cjs/runtime/run-registry-interface.d.ts +42 -0
  74. package/dist/cjs/runtime/run-registry-interface.d.ts.map +1 -0
  75. package/dist/cjs/runtime/run-registry-interface.js +7 -0
  76. package/dist/cjs/runtime/run-registry-interface.js.map +1 -0
  77. package/dist/cjs/runtime/run-registry.d.ts +15 -2
  78. package/dist/cjs/runtime/run-registry.d.ts.map +1 -1
  79. package/dist/cjs/runtime/run-registry.js +43 -1
  80. package/dist/cjs/runtime/run-registry.js.map +1 -1
  81. package/dist/cjs/sandbox/code-sandbox.d.ts +42 -0
  82. package/dist/cjs/sandbox/code-sandbox.d.ts.map +1 -0
  83. package/dist/cjs/sandbox/code-sandbox.js +59 -0
  84. package/dist/cjs/sandbox/code-sandbox.js.map +1 -0
  85. package/dist/cjs/skill/router.d.ts +20 -1
  86. package/dist/cjs/skill/router.d.ts.map +1 -1
  87. package/dist/cjs/skill/router.js +39 -1
  88. package/dist/cjs/skill/router.js.map +1 -1
  89. package/dist/cjs/skill/types.d.ts +1 -1
  90. package/dist/cjs/skill/types.d.ts.map +1 -1
  91. package/dist/cjs/skill/vector-index.d.ts +42 -0
  92. package/dist/cjs/skill/vector-index.d.ts.map +1 -0
  93. package/dist/cjs/skill/vector-index.js +70 -0
  94. package/dist/cjs/skill/vector-index.js.map +1 -0
  95. package/dist/cjs/store/history-persistence.d.ts +36 -0
  96. package/dist/cjs/store/history-persistence.d.ts.map +1 -0
  97. package/dist/cjs/store/history-persistence.js +142 -0
  98. package/dist/cjs/store/history-persistence.js.map +1 -0
  99. package/dist/cjs/types.d.ts +40 -1
  100. package/dist/cjs/types.d.ts.map +1 -1
  101. package/dist/cjs/types.js +34 -0
  102. package/dist/cjs/types.js.map +1 -1
  103. package/dist/cjs/utils/token-counter.d.ts.map +1 -1
  104. package/dist/cjs/utils/token-counter.js +33 -1
  105. package/dist/cjs/utils/token-counter.js.map +1 -1
  106. package/dist/esm/agent/engine.d.ts +23 -0
  107. package/dist/esm/agent/engine.d.ts.map +1 -1
  108. package/dist/esm/agent/engine.js +78 -5
  109. package/dist/esm/agent/engine.js.map +1 -1
  110. package/dist/esm/agent/history-manager.d.ts +66 -1
  111. package/dist/esm/agent/history-manager.d.ts.map +1 -1
  112. package/dist/esm/agent/history-manager.js +232 -0
  113. package/dist/esm/agent/history-manager.js.map +1 -1
  114. package/dist/esm/agent/llm-caller.d.ts.map +1 -1
  115. package/dist/esm/agent/llm-caller.js +10 -4
  116. package/dist/esm/agent/llm-caller.js.map +1 -1
  117. package/dist/esm/agent/profile-loader.d.ts +56 -0
  118. package/dist/esm/agent/profile-loader.d.ts.map +1 -0
  119. package/dist/esm/agent/profile-loader.js +108 -0
  120. package/dist/esm/agent/profile-loader.js.map +1 -0
  121. package/dist/esm/agent/types.d.ts +32 -3
  122. package/dist/esm/agent/types.d.ts.map +1 -1
  123. package/dist/esm/agent/types.js.map +1 -1
  124. package/dist/esm/context/types.d.ts +3 -3
  125. package/dist/esm/context/types.d.ts.map +1 -1
  126. package/dist/esm/index.d.ts +26 -2
  127. package/dist/esm/index.d.ts.map +1 -1
  128. package/dist/esm/index.js +12 -0
  129. package/dist/esm/index.js.map +1 -1
  130. package/dist/esm/kb/in-memory-kb.d.ts +29 -0
  131. package/dist/esm/kb/in-memory-kb.d.ts.map +1 -0
  132. package/dist/esm/kb/in-memory-kb.js +206 -0
  133. package/dist/esm/kb/in-memory-kb.js.map +1 -0
  134. package/dist/esm/kb/rag-middleware.d.ts +31 -0
  135. package/dist/esm/kb/rag-middleware.d.ts.map +1 -0
  136. package/dist/esm/kb/rag-middleware.js +91 -0
  137. package/dist/esm/kb/rag-middleware.js.map +1 -0
  138. package/dist/esm/kb/types.d.ts +80 -0
  139. package/dist/esm/kb/types.d.ts.map +1 -0
  140. package/dist/esm/kb/types.js +5 -0
  141. package/dist/esm/kb/types.js.map +1 -0
  142. package/dist/esm/llm/anthropic-provider.d.ts +7 -0
  143. package/dist/esm/llm/anthropic-provider.d.ts.map +1 -1
  144. package/dist/esm/llm/anthropic-provider.js +84 -9
  145. package/dist/esm/llm/anthropic-provider.js.map +1 -1
  146. package/dist/esm/llm/openai-provider.d.ts +9 -0
  147. package/dist/esm/llm/openai-provider.d.ts.map +1 -1
  148. package/dist/esm/llm/openai-provider.js +41 -1
  149. package/dist/esm/llm/openai-provider.js.map +1 -1
  150. package/dist/esm/llm/pricing.d.ts +26 -0
  151. package/dist/esm/llm/pricing.d.ts.map +1 -0
  152. package/dist/esm/llm/pricing.js +81 -0
  153. package/dist/esm/llm/pricing.js.map +1 -0
  154. package/dist/esm/llm/usage-tracker.d.ts +119 -0
  155. package/dist/esm/llm/usage-tracker.d.ts.map +1 -0
  156. package/dist/esm/llm/usage-tracker.js +101 -0
  157. package/dist/esm/llm/usage-tracker.js.map +1 -0
  158. package/dist/esm/memory/extractor.js +1 -1
  159. package/dist/esm/memory/extractor.js.map +1 -1
  160. package/dist/esm/memory/persona.js +1 -1
  161. package/dist/esm/memory/persona.js.map +1 -1
  162. package/dist/esm/memory/scene.js +1 -1
  163. package/dist/esm/memory/scene.js.map +1 -1
  164. package/dist/esm/middleware/types.d.ts +2 -4
  165. package/dist/esm/middleware/types.d.ts.map +1 -1
  166. package/dist/esm/middleware/workspace-notes.d.ts +36 -0
  167. package/dist/esm/middleware/workspace-notes.d.ts.map +1 -0
  168. package/dist/esm/middleware/workspace-notes.js +49 -0
  169. package/dist/esm/middleware/workspace-notes.js.map +1 -0
  170. package/dist/esm/observability/logger.d.ts +1 -0
  171. package/dist/esm/observability/logger.d.ts.map +1 -1
  172. package/dist/esm/observability/logger.js.map +1 -1
  173. package/dist/esm/observability/trace.d.ts +45 -0
  174. package/dist/esm/observability/trace.d.ts.map +1 -0
  175. package/dist/esm/observability/trace.js +55 -0
  176. package/dist/esm/observability/trace.js.map +1 -0
  177. package/dist/esm/runtime/run-registry-interface.d.ts +42 -0
  178. package/dist/esm/runtime/run-registry-interface.d.ts.map +1 -0
  179. package/dist/esm/runtime/run-registry-interface.js +6 -0
  180. package/dist/esm/runtime/run-registry-interface.js.map +1 -0
  181. package/dist/esm/runtime/run-registry.d.ts +15 -2
  182. package/dist/esm/runtime/run-registry.d.ts.map +1 -1
  183. package/dist/esm/runtime/run-registry.js +43 -1
  184. package/dist/esm/runtime/run-registry.js.map +1 -1
  185. package/dist/esm/sandbox/code-sandbox.d.ts +42 -0
  186. package/dist/esm/sandbox/code-sandbox.d.ts.map +1 -0
  187. package/dist/esm/sandbox/code-sandbox.js +56 -0
  188. package/dist/esm/sandbox/code-sandbox.js.map +1 -0
  189. package/dist/esm/skill/router.d.ts +20 -1
  190. package/dist/esm/skill/router.d.ts.map +1 -1
  191. package/dist/esm/skill/router.js +37 -0
  192. package/dist/esm/skill/router.js.map +1 -1
  193. package/dist/esm/skill/types.d.ts +1 -1
  194. package/dist/esm/skill/types.d.ts.map +1 -1
  195. package/dist/esm/skill/vector-index.d.ts +42 -0
  196. package/dist/esm/skill/vector-index.d.ts.map +1 -0
  197. package/dist/esm/skill/vector-index.js +66 -0
  198. package/dist/esm/skill/vector-index.js.map +1 -0
  199. package/dist/esm/store/history-persistence.d.ts +36 -0
  200. package/dist/esm/store/history-persistence.d.ts.map +1 -0
  201. package/dist/esm/store/history-persistence.js +105 -0
  202. package/dist/esm/store/history-persistence.js.map +1 -0
  203. package/dist/esm/types.d.ts +40 -1
  204. package/dist/esm/types.d.ts.map +1 -1
  205. package/dist/esm/types.js +32 -1
  206. package/dist/esm/types.js.map +1 -1
  207. package/dist/esm/utils/token-counter.d.ts.map +1 -1
  208. package/dist/esm/utils/token-counter.js +33 -1
  209. package/dist/esm/utils/token-counter.js.map +1 -1
  210. package/package.json +1 -1
@@ -0,0 +1,206 @@
1
+ // ============================================================
2
+ // InMemoryKnowledgeBase — 内存知识库实现(TF-IDF 关键词匹配)
3
+ // ============================================================
4
+ // ---- 文本分词 ----
5
+ /**
6
+ * 将文本分词为小写词项数组
7
+ * 按非字母数字字符分割,过滤空串和过短词
8
+ */
9
+ function tokenize(text) {
10
+ return text
11
+ .toLowerCase()
12
+ .split(/[^a-z0-9\u4e00-\u9fff]+/)
13
+ .filter(t => t.length > 0);
14
+ }
15
+ /** 计算词项频率(TF) */
16
+ function computeTF(tokens) {
17
+ const tf = new Map();
18
+ for (const t of tokens) {
19
+ tf.set(t, (tf.get(t) || 0) + 1);
20
+ }
21
+ // 归一化:除以总词数
22
+ const total = tokens.length;
23
+ if (total > 0) {
24
+ for (const [k, v] of tf) {
25
+ tf.set(k, v / total);
26
+ }
27
+ }
28
+ return tf;
29
+ }
30
+ // ---- InMemoryKnowledgeBase ----
31
+ /**
32
+ * 内存知识库实现
33
+ *
34
+ * 当注入 EmbeddingProvider 时使用语义向量检索(余弦相似度);
35
+ * 未注入时回退到 TF-IDF 关键词匹配(余弦相似度)。
36
+ *
37
+ * 零外部依赖,适合开发/测试及小规模知识库场景。
38
+ */
39
+ export class InMemoryKnowledgeBase {
40
+ /** 文档存储:docId -> StoredDoc */
41
+ docs = new Map();
42
+ /** 嵌入向量提供者(可选) */
43
+ embeddingProvider;
44
+ /** 全局文档频率:term -> 包含该词的文档数 */
45
+ df = new Map();
46
+ /** 总文档数(用于 IDF 计算) */
47
+ totalDocs = 0;
48
+ /** 缓存的 chunk TF-IDF 向量:chunkId -> TFIDFVector */
49
+ chunkVectors = new Map();
50
+ constructor(embeddingProvider) {
51
+ this.embeddingProvider = embeddingProvider;
52
+ }
53
+ async ingest(docId, chunks) {
54
+ if (!chunks.length)
55
+ return;
56
+ // 如果已有同 ID 文档,先移除
57
+ if (this.docs.has(docId)) {
58
+ await this.remove(docId);
59
+ }
60
+ // 生成嵌入向量(如果提供了 EmbeddingProvider)
61
+ if (this.embeddingProvider) {
62
+ const texts = chunks.map(c => c.content);
63
+ const embeddings = await this.embeddingProvider.embed(texts);
64
+ chunks = chunks.map((c, i) => ({ ...c, embedding: embeddings[i] }));
65
+ }
66
+ const now = new Date().toISOString();
67
+ const title = chunks[0]?.metadata?.title || docId;
68
+ const doc = {
69
+ meta: {
70
+ id: docId,
71
+ title,
72
+ chunkCount: chunks.length,
73
+ createdAt: now,
74
+ metadata: chunks[0]?.metadata,
75
+ },
76
+ chunks,
77
+ };
78
+ this.docs.set(docId, doc);
79
+ this.totalDocs++;
80
+ // 更新 DF(文档频率)
81
+ const docTerms = new Set();
82
+ for (const chunk of chunks) {
83
+ const tokens = tokenize(chunk.content);
84
+ for (const t of tokens)
85
+ docTerms.add(t);
86
+ }
87
+ for (const t of docTerms) {
88
+ this.df.set(t, (this.df.get(t) || 0) + 1);
89
+ }
90
+ // 计算并缓存每个 chunk 的 TF-IDF 向量
91
+ for (const chunk of chunks) {
92
+ this.chunkVectors.set(chunk.id, this.computeTFIDF(chunk.content));
93
+ }
94
+ }
95
+ async search(query, topK = 5) {
96
+ if (this.docs.size === 0)
97
+ return [];
98
+ const results = [];
99
+ // 如果有 EmbeddingProvider,使用语义检索
100
+ if (this.embeddingProvider) {
101
+ const [queryEmbedding] = await this.embeddingProvider.embed([query]);
102
+ for (const doc of this.docs.values()) {
103
+ for (const chunk of doc.chunks) {
104
+ if (!chunk.embedding)
105
+ continue;
106
+ const score = cosineSimilarity(queryEmbedding, chunk.embedding);
107
+ results.push({ chunk, score });
108
+ }
109
+ }
110
+ }
111
+ else {
112
+ // 回退到 TF-IDF 关键词匹配
113
+ const queryVector = this.computeTFIDF(query);
114
+ for (const doc of this.docs.values()) {
115
+ for (const chunk of doc.chunks) {
116
+ const chunkVector = this.chunkVectors.get(chunk.id);
117
+ if (!chunkVector)
118
+ continue;
119
+ const score = cosineSimilaritySparse(queryVector, chunkVector);
120
+ results.push({ chunk, score });
121
+ }
122
+ }
123
+ }
124
+ // 按得分降序排列,取 topK
125
+ results.sort((a, b) => b.score - a.score);
126
+ return results.slice(0, topK);
127
+ }
128
+ async remove(docId) {
129
+ const doc = this.docs.get(docId);
130
+ if (!doc)
131
+ return;
132
+ // 移除 chunk 向量缓存
133
+ for (const chunk of doc.chunks) {
134
+ this.chunkVectors.delete(chunk.id);
135
+ }
136
+ // 更新 DF
137
+ const docTerms = new Set();
138
+ for (const chunk of doc.chunks) {
139
+ const tokens = tokenize(chunk.content);
140
+ for (const t of tokens)
141
+ docTerms.add(t);
142
+ }
143
+ for (const t of docTerms) {
144
+ const count = this.df.get(t);
145
+ if (count != null) {
146
+ if (count <= 1)
147
+ this.df.delete(t);
148
+ else
149
+ this.df.set(t, count - 1);
150
+ }
151
+ }
152
+ this.docs.delete(docId);
153
+ this.totalDocs--;
154
+ }
155
+ async list() {
156
+ return Array.from(this.docs.values()).map(d => d.meta);
157
+ }
158
+ // ---- TF-IDF 计算 ----
159
+ /** 计算文本的 TF-IDF 稀疏向量 */
160
+ computeTFIDF(text) {
161
+ const tokens = tokenize(text);
162
+ const tf = computeTF(tokens);
163
+ const vector = new Map();
164
+ for (const [term, tfVal] of tf) {
165
+ const dfVal = this.df.get(term) || 0;
166
+ // IDF = log((1 + N) / (1 + DF)) + 1 (平滑处理)
167
+ const idf = Math.log((1 + this.totalDocs) / (1 + dfVal)) + 1;
168
+ vector.set(term, tfVal * idf);
169
+ }
170
+ return vector;
171
+ }
172
+ }
173
+ // ---- 向量相似度计算 ----
174
+ /** 计算两个稠密向量的余弦相似度 */
175
+ function cosineSimilarity(a, b) {
176
+ if (a.length !== b.length || a.length === 0)
177
+ return 0;
178
+ let dot = 0;
179
+ let magA = 0;
180
+ let magB = 0;
181
+ for (let i = 0; i < a.length; i++) {
182
+ dot += a[i] * b[i];
183
+ magA += a[i] * a[i];
184
+ magB += b[i] * b[i];
185
+ }
186
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
187
+ return denom === 0 ? 0 : dot / denom;
188
+ }
189
+ /** 计算两个稀疏向量(Map)的余弦相似度 */
190
+ function cosineSimilaritySparse(a, b) {
191
+ let dot = 0;
192
+ let magA = 0;
193
+ let magB = 0;
194
+ for (const [k, v] of a) {
195
+ magA += v * v;
196
+ const bv = b.get(k);
197
+ if (bv != null)
198
+ dot += v * bv;
199
+ }
200
+ for (const [, v] of b) {
201
+ magB += v * v;
202
+ }
203
+ const denom = Math.sqrt(magA) * Math.sqrt(magB);
204
+ return denom === 0 ? 0 : dot / denom;
205
+ }
206
+ //# sourceMappingURL=in-memory-kb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-kb.js","sourceRoot":"","sources":["../../../src/kb/in-memory-kb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { Middleware } from '../middleware/types.js';
2
+ import type { KnowledgeBase } from './types.js';
3
+ /** RAG 中间件配置 */
4
+ export interface RAGMiddlewareOptions {
5
+ /** 检索结果数量(默认 3) */
6
+ topK?: number;
7
+ /** 注入的上下文笔记标题(默认 "Retrieved Knowledge") */
8
+ noteTitle?: string;
9
+ /** 每个分块最大字符数(默认 500,超出截断) */
10
+ maxChunkLength?: number;
11
+ /** 最低相似度阈值(低于此值的结果不注入,默认 0.01) */
12
+ minScore?: number;
13
+ /** 是否仅在首轮迭代注入(默认 false,每轮都检索) */
14
+ firstIterationOnly?: boolean;
15
+ /** 日志输出函数 */
16
+ logger?: (msg: string) => void;
17
+ }
18
+ /**
19
+ * 创建 RAG(检索增强生成)中间件
20
+ *
21
+ * 在每轮迭代开始前:
22
+ * 1. 提取用户最新消息文本
23
+ * 2. 检索知识库中相关分块
24
+ * 3. 将检索结果格式化为系统级上下文笔记,注入到消息列表末尾
25
+ *
26
+ * @param kb 知识库实例
27
+ * @param options 配置选项
28
+ * @returns Middleware 实例
29
+ */
30
+ export declare function createRAGMiddleware(kb: KnowledgeBase, options?: RAGMiddlewareOptions): Middleware;
31
+ //# sourceMappingURL=rag-middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-middleware.d.ts","sourceRoot":"","sources":["../../../src/kb/rag-middleware.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAqB,MAAM,wBAAwB,CAAC;AAG5E,OAAO,KAAK,EAAE,aAAa,EAAgB,MAAM,YAAY,CAAC;AAI9D,gBAAgB;AAChB,MAAM,WAAW,oBAAoB;IACnC,mBAAmB;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa;IACb,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,aAAa,EACjB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,UAAU,CAkFZ"}
@@ -0,0 +1,91 @@
1
+ // ============================================================
2
+ // RAGMiddleware — 检索增强生成中间件
3
+ // ============================================================
4
+ import { extractTextFromContent } from "../types.js";
5
+ // ---- createRAGMiddleware ----
6
+ /**
7
+ * 创建 RAG(检索增强生成)中间件
8
+ *
9
+ * 在每轮迭代开始前:
10
+ * 1. 提取用户最新消息文本
11
+ * 2. 检索知识库中相关分块
12
+ * 3. 将检索结果格式化为系统级上下文笔记,注入到消息列表末尾
13
+ *
14
+ * @param kb 知识库实例
15
+ * @param options 配置选项
16
+ * @returns Middleware 实例
17
+ */
18
+ export function createRAGMiddleware(kb, options) {
19
+ const topK = options?.topK ?? 3;
20
+ const noteTitle = options?.noteTitle ?? 'Retrieved Knowledge';
21
+ const maxChunkLength = options?.maxChunkLength ?? 500;
22
+ const minScore = options?.minScore ?? 0.01;
23
+ const firstIterationOnly = options?.firstIterationOnly ?? false;
24
+ const logger = options?.logger ?? (() => { });
25
+ /** 已注入过的会话集合(用于 firstIterationOnly 模式) */
26
+ const injectedSessions = new Set();
27
+ /** 格式化检索结果为上下文笔记 */
28
+ function formatContextNote(results) {
29
+ const lines = [`--- ${noteTitle} ---`];
30
+ for (let i = 0; i < results.length; i++) {
31
+ const { chunk, score } = results[i];
32
+ let content = chunk.content;
33
+ if (content.length > maxChunkLength) {
34
+ content = content.slice(0, maxChunkLength) + '...';
35
+ }
36
+ const source = chunk.metadata?.title
37
+ ? `[${chunk.metadata.title}]`
38
+ : `[doc: ${chunk.docId}]`;
39
+ lines.push(`[${i + 1}] ${source} (score: ${score.toFixed(3)})`);
40
+ lines.push(content);
41
+ lines.push('');
42
+ }
43
+ return lines.join('\n');
44
+ }
45
+ /** 从消息列表中提取最新的用户消息文本 */
46
+ function getLatestUserMessage(messages) {
47
+ for (let i = messages.length - 1; i >= 0; i--) {
48
+ const msg = messages[i];
49
+ if (msg.role === 'user') {
50
+ return extractTextFromContent(msg.content);
51
+ }
52
+ }
53
+ return '';
54
+ }
55
+ return {
56
+ name: 'rag',
57
+ async before(ctx) {
58
+ // firstIterationOnly 模式:仅首轮注入
59
+ if (firstIterationOnly && injectedSessions.has(ctx.sessionId)) {
60
+ return;
61
+ }
62
+ // 提取最新用户消息
63
+ const query = getLatestUserMessage(ctx.messages);
64
+ if (!query.trim())
65
+ return;
66
+ try {
67
+ const results = await kb.search(query, topK);
68
+ // 过滤低分结果
69
+ const filtered = results.filter(r => r.score >= minScore);
70
+ if (filtered.length === 0)
71
+ return;
72
+ // 格式化上下文笔记
73
+ const note = formatContextNote(filtered);
74
+ // 注入系统级上下文消息
75
+ const contextMessage = {
76
+ role: 'system',
77
+ content: note,
78
+ };
79
+ // ctx.messages 是 ReadonlyArray,但底层是可变数组
80
+ // 与引擎内部注入消息的模式一致(如 progress nudge、iteration guard 等)
81
+ ctx.messages.push(contextMessage);
82
+ injectedSessions.add(ctx.sessionId);
83
+ logger(`[RAG] Injected ${filtered.length} chunks for session ${ctx.sessionId} (iter ${ctx.iteration})`);
84
+ }
85
+ catch (e) {
86
+ logger(`[RAG] Search failed: ${e?.message || e}`);
87
+ }
88
+ },
89
+ };
90
+ }
91
+ //# sourceMappingURL=rag-middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag-middleware.js","sourceRoot":"","sources":["../../../src/kb/rag-middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /** 文本分块(知识库最小检索单元) */
2
+ export interface TextChunk {
3
+ /** 分块唯一 ID */
4
+ id: string;
5
+ /** 所属文档 ID */
6
+ docId: string;
7
+ /** 分块文本内容 */
8
+ content: string;
9
+ /** 预计算的嵌入向量(可选,由 EmbeddingProvider 生成) */
10
+ embedding?: number[];
11
+ /** 附加元数据(如页码、标题、来源等) */
12
+ metadata?: Record<string, unknown>;
13
+ }
14
+ /** 知识库检索结果 */
15
+ export interface SearchResult {
16
+ /** 匹配到的文本分块 */
17
+ chunk: TextChunk;
18
+ /** 相似度得分(0~1,越高越相关) */
19
+ score: number;
20
+ }
21
+ /** 文档元数据 */
22
+ export interface DocMeta {
23
+ /** 文档 ID */
24
+ id: string;
25
+ /** 文档标题 */
26
+ title: string;
27
+ /** 分块数量 */
28
+ chunkCount: number;
29
+ /** 创建时间(ISO 8601) */
30
+ createdAt: string;
31
+ /** 附加元数据 */
32
+ metadata?: Record<string, unknown>;
33
+ }
34
+ /**
35
+ * 嵌入向量提供者接口
36
+ *
37
+ * 将文本转换为高维向量,用于语义检索。
38
+ * Core 仅定义接口,具体实现由上层注入(如调用 OpenAI Embeddings API)。
39
+ */
40
+ export interface EmbeddingProvider {
41
+ /**
42
+ * 批量生成文本的嵌入向量
43
+ * @param texts 文本数组
44
+ * @returns 嵌入向量数组(与输入一一对应)
45
+ */
46
+ embed(texts: string[]): Promise<number[][]>;
47
+ }
48
+ /**
49
+ * 知识库接口
50
+ *
51
+ * 提供文档摄入、语义/关键词检索、文档管理和列表功能。
52
+ * Core 定义接口,具体实现可以是内存型(InMemoryKnowledgeBase)
53
+ * 或外部向量数据库(由上层注入)。
54
+ */
55
+ export interface KnowledgeBase {
56
+ /**
57
+ * 摄入文档分块
58
+ * @param docId 文档 ID
59
+ * @param chunks 文本分块数组
60
+ */
61
+ ingest(docId: string, chunks: TextChunk[]): Promise<void>;
62
+ /**
63
+ * 检索与查询最相关的分块
64
+ * @param query 查询文本
65
+ * @param topK 返回结果数量(默认 5)
66
+ * @returns 按相关度降序排列的检索结果
67
+ */
68
+ search(query: string, topK?: number): Promise<SearchResult[]>;
69
+ /**
70
+ * 删除指定文档及其所有分块
71
+ * @param docId 文档 ID
72
+ */
73
+ remove(docId: string): Promise<void>;
74
+ /**
75
+ * 列出知识库中的所有文档元数据
76
+ * @returns 文档元数据数组
77
+ */
78
+ list(): Promise<DocMeta[]>;
79
+ }
80
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/kb/types.ts"],"names":[],"mappings":"AAMA,sBAAsB;AACtB,MAAM,WAAW,SAAS;IACxB,cAAc;IACd,EAAE,EAAE,MAAM,CAAC;IACX,cAAc;IACd,KAAK,EAAE,MAAM,CAAC;IACd,aAAa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAID,cAAc;AACd,MAAM,WAAW,YAAY;IAC3B,eAAe;IACf,KAAK,EAAE,SAAS,CAAC;IACjB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,YAAY;AACZ,MAAM,WAAW,OAAO;IACtB,YAAY;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAID;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;CAC7C;AAID;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1D;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAE9D;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAErC;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;CAC5B"}
@@ -0,0 +1,5 @@
1
+ // ============================================================
2
+ // KnowledgeBase — 知识库类型定义
3
+ // ============================================================
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/kb/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,0BAA0B;AAC1B,+DAA+D"}
@@ -20,6 +20,13 @@ export declare class AnthropicProvider implements LLMProvider {
20
20
  * - assistant 的 tool_calls 转换为 tool_use 块
21
21
  */
22
22
  private convertMessages;
23
+ /**
24
+ * 将 ContentPart[] 转换为 Anthropic content blocks
25
+ * - TextPart → {type: 'text', text}
26
+ * - ImagePart → {type: 'image', source: {type: 'base64'|'url', ...}}
27
+ * - FilePart → {type: 'text', text: '[file]\n${content}'}
28
+ */
29
+ private convertContentPartsForAnthropic;
23
30
  private convertTools;
24
31
  private buildRequestBody;
25
32
  private parseResponse;
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../../../src/llm/anthropic-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA+C3G,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAkE;gBAEpE,MAAM,EAAE,WAAW;IAY/B,QAAQ,IAAI,SAAS;IAUf,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAexB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAa9C,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC,SAAS,CAAC;IAkIhE,WAAW;IACX,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IAMjD;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAiEvB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,gBAAgB;IAqBxB,OAAO,CAAC,aAAa;YAwCP,SAAS;CA2BxB"}
1
+ {"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../../../src/llm/anthropic-provider.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgD3G,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,MAAM,CAAkE;gBAEpE,MAAM,EAAE,WAAW;IAY/B,QAAQ,IAAI,SAAS;IAUf,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAexB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAa9C,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC,SAAS,CAAC;IAkIhE,WAAW;IACX,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IAMjD;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA0EvB;;;;;OAKG;IACH,OAAO,CAAC,+BAA+B;IA2CvC,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,gBAAgB;IAqCxB,OAAO,CAAC,aAAa;YAwCP,SAAS;CA2BxB"}
@@ -204,17 +204,27 @@ export class AnthropicProvider {
204
204
  for (const msg of messages) {
205
205
  switch (msg.role) {
206
206
  case 'system':
207
- system = (system ? system + '\n\n' : '') + (msg.content || '');
207
+ system = (system ? system + '\n\n' : '') + (typeof msg.content === 'string' ? msg.content : '');
208
208
  break;
209
- case 'user':
210
- result.push({ role: 'user', content: msg.content || '' });
209
+ case 'user': {
210
+ // 多模态内容:ContentPart[] Anthropic content blocks
211
+ if (Array.isArray(msg.content)) {
212
+ const blocks = this.convertContentPartsForAnthropic(msg.content);
213
+ result.push({ role: 'user', content: blocks });
214
+ }
215
+ else {
216
+ result.push({ role: 'user', content: msg.content || '' });
217
+ }
211
218
  break;
219
+ }
212
220
  case 'assistant': {
213
221
  if (msg.tool_calls?.length) {
214
222
  // assistant 带 tool_calls → text + tool_use blocks
215
223
  const blocks = [];
216
224
  if (msg.content) {
217
- blocks.push({ type: 'text', text: msg.content });
225
+ const textContent = typeof msg.content === 'string' ? msg.content : msg.content.map(p => p.type === 'text' ? p.text : '').join('');
226
+ if (textContent)
227
+ blocks.push({ type: 'text', text: textContent });
218
228
  }
219
229
  for (const tc of msg.tool_calls) {
220
230
  let input;
@@ -236,7 +246,8 @@ export class AnthropicProvider {
236
246
  result.push({ role: 'assistant', content: blocks });
237
247
  }
238
248
  else {
239
- result.push({ role: 'assistant', content: msg.content || '' });
249
+ const textContent = typeof msg.content === 'string' ? msg.content : (msg.content || []).map(p => p.type === 'text' ? p.text : '').join('');
250
+ result.push({ role: 'assistant', content: textContent || '' });
240
251
  }
241
252
  break;
242
253
  }
@@ -247,7 +258,7 @@ export class AnthropicProvider {
247
258
  content: [{
248
259
  type: 'tool_result',
249
260
  tool_use_id: msg.tool_call_id,
250
- content: msg.content || '',
261
+ content: typeof msg.content === 'string' ? msg.content : '',
251
262
  }],
252
263
  });
253
264
  break;
@@ -256,6 +267,55 @@ export class AnthropicProvider {
256
267
  }
257
268
  return { system, messages: result };
258
269
  }
270
+ /**
271
+ * 将 ContentPart[] 转换为 Anthropic content blocks
272
+ * - TextPart → {type: 'text', text}
273
+ * - ImagePart → {type: 'image', source: {type: 'base64'|'url', ...}}
274
+ * - FilePart → {type: 'text', text: '[file]\n${content}'}
275
+ */
276
+ convertContentPartsForAnthropic(parts) {
277
+ const blocks = [];
278
+ for (const part of parts) {
279
+ switch (part.type) {
280
+ case 'text':
281
+ blocks.push({ type: 'text', text: part.text });
282
+ break;
283
+ case 'image': {
284
+ const source = part.source;
285
+ // base64 data URI → Anthropic base64 source
286
+ const dataUriMatch = source.match(/^data:(image\/[a-zA-Z+]+);base64,(.+)$/);
287
+ if (dataUriMatch) {
288
+ blocks.push({
289
+ type: 'image',
290
+ source: {
291
+ type: 'base64',
292
+ media_type: dataUriMatch[1],
293
+ data: dataUriMatch[2],
294
+ },
295
+ });
296
+ }
297
+ else {
298
+ // URL → Anthropic url source
299
+ blocks.push({
300
+ type: 'image',
301
+ source: {
302
+ type: 'url',
303
+ url: source,
304
+ },
305
+ });
306
+ }
307
+ break;
308
+ }
309
+ case 'file':
310
+ blocks.push({
311
+ type: 'text',
312
+ text: `[File: ${part.filename}]\n\n${part.content}`,
313
+ });
314
+ break;
315
+ }
316
+ }
317
+ return blocks;
318
+ }
259
319
  convertTools(params) {
260
320
  if (!params.tools?.length)
261
321
  return undefined;
@@ -278,10 +338,25 @@ export class AnthropicProvider {
278
338
  messages,
279
339
  temperature: params.temperature ?? this.config.temperature,
280
340
  };
281
- if (system)
282
- body.system = system;
283
- if (tools?.length)
341
+ // Prompt 缓存:对 system prompt 和 tools 插入 cache_control 断点
342
+ // Anthropic 会缓存这些稳定内容,减少重复 API 调用成本
343
+ const enableCache = this.config.extra?.enableCache !== false; // 默认启用
344
+ if (system) {
345
+ if (enableCache) {
346
+ // system 使用 content block 格式以支持 cache_control
347
+ body.system = [{ type: 'text', text: system, cache_control: { type: 'ephemeral' } }];
348
+ }
349
+ else {
350
+ body.system = system;
351
+ }
352
+ }
353
+ if (tools?.length) {
354
+ if (enableCache) {
355
+ // 在最后一个 tool 上添加 cache_control 断点
356
+ tools[tools.length - 1] = { ...tools[tools.length - 1], cache_control: { type: 'ephemeral' } };
357
+ }
284
358
  body.tools = tools;
359
+ }
285
360
  return body;
286
361
  }
287
362
  parseResponse(data) {