@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,70 @@
1
+ "use strict";
2
+ // ============================================================
3
+ // VectorIndex — 向量索引接口与内存实现
4
+ // 纯 JS 余弦相似度,零外部依赖
5
+ // ============================================================
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.InMemoryVectorIndex = void 0;
8
+ /**
9
+ * InMemoryVectorIndex — 内存向量索引
10
+ * 纯 JS 余弦相似度实现,零外部依赖
11
+ */
12
+ class InMemoryVectorIndex {
13
+ items = new Map();
14
+ /** 预计算的向量范数缓存 */
15
+ norms = new Map();
16
+ build(items) {
17
+ this.items.clear();
18
+ this.norms.clear();
19
+ for (const item of items) {
20
+ this.items.set(item.id, item);
21
+ this.norms.set(item.id, this.computeNorm(item.vector));
22
+ }
23
+ }
24
+ async search(query, k) {
25
+ if (this.items.size === 0 || k <= 0)
26
+ return [];
27
+ const queryNorm = this.computeNorm(query);
28
+ if (queryNorm === 0)
29
+ return [];
30
+ const results = [];
31
+ for (const [id, item] of this.items) {
32
+ const itemNorm = this.norms.get(id) ?? this.computeNorm(item.vector);
33
+ if (itemNorm === 0)
34
+ continue;
35
+ const score = this.dotProduct(query, item.vector) / (queryNorm * itemNorm);
36
+ results.push({ id, score, metadata: item.metadata });
37
+ }
38
+ results.sort((a, b) => b.score - a.score);
39
+ return results.slice(0, k);
40
+ }
41
+ add(item) {
42
+ this.items.set(item.id, item);
43
+ this.norms.set(item.id, this.computeNorm(item.vector));
44
+ }
45
+ remove(id) {
46
+ this.items.delete(id);
47
+ this.norms.delete(id);
48
+ }
49
+ size() {
50
+ return this.items.size;
51
+ }
52
+ // ---- 内部方法 ----
53
+ dotProduct(a, b) {
54
+ let sum = 0;
55
+ const len = Math.min(a.length, b.length);
56
+ for (let i = 0; i < len; i++) {
57
+ sum += a[i] * b[i];
58
+ }
59
+ return sum;
60
+ }
61
+ computeNorm(vec) {
62
+ let sum = 0;
63
+ for (let i = 0; i < vec.length; i++) {
64
+ sum += vec[i] * vec[i];
65
+ }
66
+ return Math.sqrt(sum);
67
+ }
68
+ }
69
+ exports.InMemoryVectorIndex = InMemoryVectorIndex;
70
+ //# sourceMappingURL=vector-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-index.js","sourceRoot":"","sources":["../../../src/skill/vector-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { Message } from '../types.js';
2
+ import type { HistoryPersistence } from '../agent/types.js';
3
+ export interface JsonlHistoryPersistenceOptions {
4
+ /** 存储目录(相对于 data 目录),默认 'history' */
5
+ dir?: string;
6
+ /** 使用项目级目录({cwd}/data)而非全局目录(~/.agent/data) */
7
+ projectLocal?: boolean;
8
+ /** 直接使用绝对路径(忽略 projectLocal 和 dir) */
9
+ absoluteDir?: string;
10
+ }
11
+ /**
12
+ * Append-only JSONL 会话历史持久化
13
+ *
14
+ * 文件路径:{dataDir}/{dir}/{sessionId}.jsonl
15
+ *
16
+ * 特点:
17
+ * - Append-only:只追加不修改,保证审计完整性
18
+ * - JSONL 格式:每行一条 JSON,人类可读,可用 jq/grep 查询
19
+ * - 异步写入:不阻塞 Agent Loop
20
+ * - 容错:损坏行跳过,不中断加载
21
+ */
22
+ export declare class JsonlHistoryPersistence implements HistoryPersistence {
23
+ private dir;
24
+ private projectLocal;
25
+ private absoluteDir?;
26
+ constructor(options?: JsonlHistoryPersistenceOptions);
27
+ /** 获取会话历史文件路径 */
28
+ private getFilePath;
29
+ /** 确保目录存在 */
30
+ private ensureDir;
31
+ save(sessionId: string, message: Message): Promise<void>;
32
+ load(sessionId: string): Promise<Message[] | null>;
33
+ delete(sessionId: string): Promise<void>;
34
+ exists(sessionId: string): Promise<boolean>;
35
+ }
36
+ //# sourceMappingURL=history-persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-persistence.d.ts","sourceRoot":"","sources":["../../../src/store/history-persistence.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,MAAM,WAAW,8BAA8B;IAC7C,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,WAAW,CAAC,CAAS;gBAEjB,OAAO,GAAE,8BAAmC;IAMxD,iBAAiB;IACjB,OAAO,CAAC,WAAW;IASnB,aAAa;YACC,SAAS;IAOjB,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxD,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;IA+BlD,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CASlD"}
@@ -0,0 +1,142 @@
1
+ "use strict";
2
+ // ============================================================
3
+ // JsonlHistoryPersistence — Append-only JSONL 会话历史持久化
4
+ // ============================================================
5
+ //
6
+ // 每个 session 一个 .jsonl 文件,每行一条 Message JSON。
7
+ // - save(): 追加一行(append-only,不覆盖已有内容)
8
+ // - load(): 逐行读取重建 Message[]
9
+ // - delete(): 删除文件
10
+ //
11
+ // 设计参考:Claude Code 的 append-only JSONL 转录
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.JsonlHistoryPersistence = void 0;
47
+ const fsp = __importStar(require("fs/promises"));
48
+ const path = __importStar(require("path"));
49
+ const data_dir_ts_1 = require("../utils/data-dir.js");
50
+ /**
51
+ * Append-only JSONL 会话历史持久化
52
+ *
53
+ * 文件路径:{dataDir}/{dir}/{sessionId}.jsonl
54
+ *
55
+ * 特点:
56
+ * - Append-only:只追加不修改,保证审计完整性
57
+ * - JSONL 格式:每行一条 JSON,人类可读,可用 jq/grep 查询
58
+ * - 异步写入:不阻塞 Agent Loop
59
+ * - 容错:损坏行跳过,不中断加载
60
+ */
61
+ class JsonlHistoryPersistence {
62
+ dir;
63
+ projectLocal;
64
+ absoluteDir;
65
+ constructor(options = {}) {
66
+ this.dir = options.dir || 'history';
67
+ this.projectLocal = options.projectLocal ?? false;
68
+ this.absoluteDir = options.absoluteDir;
69
+ }
70
+ /** 获取会话历史文件路径 */
71
+ getFilePath(sessionId) {
72
+ // 防止路径遍历:只允许字母数字和 -_
73
+ const safeId = sessionId.replace(/[^a-zA-Z0-9_-]/g, '_');
74
+ if (this.absoluteDir) {
75
+ return path.join(this.absoluteDir, `${safeId}.jsonl`);
76
+ }
77
+ return (0, data_dir_ts_1.getDataPath)(`${this.dir}/${safeId}.jsonl`);
78
+ }
79
+ /** 确保目录存在 */
80
+ async ensureDir() {
81
+ const dirPath = this.absoluteDir
82
+ ? this.absoluteDir
83
+ : path.dirname((0, data_dir_ts_1.getDataPath)(`${this.dir}/.placeholder`));
84
+ await fsp.mkdir(dirPath, { recursive: true });
85
+ }
86
+ async save(sessionId, message) {
87
+ await this.ensureDir();
88
+ const filePath = this.getFilePath(sessionId);
89
+ const line = JSON.stringify(message) + '\n';
90
+ await fsp.appendFile(filePath, line, 'utf-8');
91
+ }
92
+ async load(sessionId) {
93
+ const filePath = this.getFilePath(sessionId);
94
+ try {
95
+ await fsp.access(filePath);
96
+ }
97
+ catch {
98
+ return null;
99
+ }
100
+ try {
101
+ const raw = await fsp.readFile(filePath, 'utf-8');
102
+ const lines = raw.split('\n').filter(line => line.trim());
103
+ const messages = [];
104
+ for (const line of lines) {
105
+ try {
106
+ const msg = JSON.parse(line);
107
+ messages.push(msg);
108
+ }
109
+ catch {
110
+ // 跳过损坏行(如写入中断导致的不完整 JSON)
111
+ console.warn(`[JsonlHistoryPersistence] Skipped malformed line in ${filePath}`);
112
+ }
113
+ }
114
+ return messages;
115
+ }
116
+ catch (e) {
117
+ console.error(`[JsonlHistoryPersistence] load error: ${filePath}`, e);
118
+ return null;
119
+ }
120
+ }
121
+ async delete(sessionId) {
122
+ const filePath = this.getFilePath(sessionId);
123
+ try {
124
+ await fsp.unlink(filePath);
125
+ }
126
+ catch {
127
+ // 文件不存在时静默忽略
128
+ }
129
+ }
130
+ async exists(sessionId) {
131
+ const filePath = this.getFilePath(sessionId);
132
+ try {
133
+ await fsp.access(filePath);
134
+ return true;
135
+ }
136
+ catch {
137
+ return false;
138
+ }
139
+ }
140
+ }
141
+ exports.JsonlHistoryPersistence = JsonlHistoryPersistence;
142
+ //# sourceMappingURL=history-persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-persistence.js","sourceRoot":"","sources":["../../../src/store/history-persistence.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,30 @@
1
+ /** 文本内容部分 */
2
+ export interface TextPart {
3
+ type: 'text';
4
+ text: string;
5
+ }
6
+ /** 图片内容部分 */
7
+ export interface ImagePart {
8
+ type: 'image';
9
+ /** 图片来源:URL(http/https)或 base64 data URI(data:image/png;base64,...) */
10
+ source: string;
11
+ /** 图片 MIME 类型(如 image/png, image/jpeg),base64 时可从 data URI 推断 */
12
+ mimeType?: string;
13
+ /** 图片详情级别(OpenAI: low/high/auto),默认 auto */
14
+ detail?: 'low' | 'high' | 'auto';
15
+ }
16
+ /** 文件内容部分(PDF、文档等,由上层解析为文本后注入) */
17
+ export interface FilePart {
18
+ type: 'file';
19
+ /** 文件名 */
20
+ filename: string;
21
+ /** 文件内容(文本形式,已由上层解析提取) */
22
+ content: string;
23
+ /** 文件 MIME 类型 */
24
+ mimeType?: string;
25
+ }
26
+ /** 多模态内容部分(discriminated union) */
27
+ export type ContentPart = TextPart | ImagePart | FilePart;
1
28
  /** 消息角色 */
2
29
  export type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
3
30
  /** LLM 发起的工具调用 */
@@ -12,7 +39,8 @@ export interface ToolCall {
12
39
  /** LLM 消息 */
13
40
  export interface Message {
14
41
  role: MessageRole;
15
- content: string | null;
42
+ /** 消息内容:纯文本字符串、多模态内容部分数组、或 null(无内容) */
43
+ content: string | ContentPart[] | null;
16
44
  /** assistant 消息中的工具调用请求 */
17
45
  tool_calls?: ToolCall[];
18
46
  /** tool 消息对应的 tool_call id */
@@ -24,6 +52,17 @@ export interface Message {
24
52
  /** 扩展字段,上层可附加任意元数据 */
25
53
  metadata?: Record<string, unknown>;
26
54
  }
55
+ /**
56
+ * 从 Message.content 中提取纯文本(用于 Skill 路由、去重检测等场景)
57
+ * - string 直接返回
58
+ * - ContentPart[] 拼接所有 TextPart 和 FilePart 的文本
59
+ * - null 返回空字符串
60
+ */
61
+ export declare function extractTextFromContent(content: string | ContentPart[] | null): string;
62
+ /**
63
+ * 判断消息内容是否为多模态(包含非文本部分)
64
+ */
65
+ export declare function isMultimodalContent(content: string | ContentPart[] | null): boolean;
27
66
  /** 所有事件的公共基座 */
28
67
  export interface BaseEvent {
29
68
  /** 事件时间戳(毫秒) */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAMA,WAAW;AACX,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAEnE,kBAAkB;AAClB,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE;QACR,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAED,aAAa;AACb,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,QAAQ,EAAE,CAAC;IACxB,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,sBAAsB;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAID,gBAAgB;AAChB,MAAM,WAAW,SAAS;IACxB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW;IACX,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,eAAe;AACf,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,qBAAqB;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,iBAAiB;AACjB,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,aAAa;AACb,MAAM,WAAW,eAAgB,SAAQ,SAAS;IAChD,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,aAAa;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAqB;AACrB,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,iBAAiB;AACjB,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,aAAa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,iBAAiB;AACjB,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,iCAAiC;IACjC,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,4BAA4B;AAC5B,MAAM,WAAW,aAAc,SAAQ,SAAS;IAC9C,IAAI,EAAE,UAAU,CAAC;IACjB,wBAAwB;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,uBAAuB;AACvB,MAAM,WAAW,UAAW,SAAQ,SAAS;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,mBAAmB;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,sCAAsC;AACtC,MAAM,MAAM,UAAU,GAClB,aAAa,GACb,aAAa,GACb,eAAe,GACf,YAAY,GACZ,SAAS,GACT,UAAU,GACV,aAAa,GACb,UAAU,CAAC;AAIf,iBAAiB;AACjB,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,kBAAkB;AAClB,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,mBAAmB;AACnB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,GAAG,SAAS,GAAG,gBAAgB,GAAG,OAAO,CAAC;IAC7D,aAAa;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,mBAAmB;IACnB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,UAAU,GAAG,gBAAgB,GAAG,WAAW,GAAG,UAAU,CAAC;AAI5F,0BAA0B;AAC1B,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC;IAC3C,qBAAqB;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/dist/cjs/types.js CHANGED
@@ -3,4 +3,38 @@
3
3
  // Core 全局共享类型
4
4
  // ============================================================
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractTextFromContent = extractTextFromContent;
7
+ exports.isMultimodalContent = isMultimodalContent;
8
+ // ---- ContentPart 辅助函数 ----
9
+ /**
10
+ * 从 Message.content 中提取纯文本(用于 Skill 路由、去重检测等场景)
11
+ * - string 直接返回
12
+ * - ContentPart[] 拼接所有 TextPart 和 FilePart 的文本
13
+ * - null 返回空字符串
14
+ */
15
+ function extractTextFromContent(content) {
16
+ if (content == null)
17
+ return '';
18
+ if (typeof content === 'string')
19
+ return content;
20
+ return content
21
+ .map(part => {
22
+ if (part.type === 'text')
23
+ return part.text;
24
+ if (part.type === 'file')
25
+ return `[file: ${part.filename}]\n${part.content}`;
26
+ if (part.type === 'image')
27
+ return `[image: ${part.source.slice(0, 80)}]`;
28
+ return '';
29
+ })
30
+ .join('\n');
31
+ }
32
+ /**
33
+ * 判断消息内容是否为多模态(包含非文本部分)
34
+ */
35
+ function isMultimodalContent(content) {
36
+ if (content == null || typeof content === 'string')
37
+ return false;
38
+ return content.some(part => part.type === 'image' || part.type === 'file');
39
+ }
6
40
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA,+DAA+D;AAC/D,cAAc;AACd,+DAA+D"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";AAAA,+DAA+D;AAC/D,cAAc;AACd,+DAA+D;;AA2E/D,wDAWC;AAKD,kDAGC;AA3BD,6BAA6B;AAE7B;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,OAAsC;IAC3E,IAAI,OAAO,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAChD,OAAO,OAAO;SACX,GAAG,CAAC,IAAI,CAAC,EAAE;QACV,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC;QAC3C,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,UAAU,IAAI,CAAC,QAAQ,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAC7E,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,WAAW,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC;QACzE,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,OAAsC;IACxE,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACjE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;AAC7E,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../../src/utils/token-counter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AA6B3C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuBhD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CA0B9D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD"}
1
+ {"version":3,"file":"token-counter.d.ts","sourceRoot":"","sources":["../../../src/utils/token-counter.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,OAAO,EAAe,MAAM,aAAa,CAAC;AA6BxD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuBhD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAiC9D;AA0BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD"}
@@ -72,7 +72,15 @@ function countMessageTokens(messages) {
72
72
  total += countTokens(msg.role || '');
73
73
  // content
74
74
  if (msg.content) {
75
- total += countTokens(typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content));
75
+ if (typeof msg.content === 'string') {
76
+ total += countTokens(msg.content);
77
+ }
78
+ else {
79
+ // ContentPart[]:逐部分计算
80
+ for (const part of msg.content) {
81
+ total += countContentPartTokens(part);
82
+ }
83
+ }
76
84
  }
77
85
  // tool_calls (序列化后的 token 数)
78
86
  if (msg.tool_calls) {
@@ -90,6 +98,30 @@ function countMessageTokens(messages) {
90
98
  total += 2;
91
99
  return total;
92
100
  }
101
+ /**
102
+ * 计算单个 ContentPart 的 token 估算值
103
+ * - TextPart: 精确计数
104
+ * - ImagePart: 按详情级别估算(参考 OpenAI Vision 定价)
105
+ * - low: ~85 tokens(512x512 固定)
106
+ * - high: ~170 tokens/tile(最多 4 tiles → ~680)
107
+ * - auto: 默认按 low 估算
108
+ * - FilePart: 计数文本内容
109
+ */
110
+ function countContentPartTokens(part) {
111
+ switch (part.type) {
112
+ case 'text':
113
+ return countTokens(part.text);
114
+ case 'image':
115
+ // OpenAI Vision: low=85, high=170*tiles(1-4), auto≈85
116
+ if (part.detail === 'high')
117
+ return 680;
118
+ return 85;
119
+ case 'file':
120
+ return countTokens(part.content) + countTokens(part.filename);
121
+ default:
122
+ return 0;
123
+ }
124
+ }
93
125
  /**
94
126
  * 估算文本 token 数(快速估算,不加载 tiktoken)
95
127
  * 适用于对精度要求不高的场景,约 4 字符 = 1 token
@@ -1 +1 @@
1
- {"version":3,"file":"token-counter.js","sourceRoot":"","sources":["../../../src/utils/token-counter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"token-counter.js","sourceRoot":"","sources":["../../../src/utils/token-counter.ts"],"names":[],"mappings":"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"}
@@ -36,6 +36,29 @@ export declare class AgentEngine {
36
36
  * 获取会话历史副本(用于持久化保存)
37
37
  */
38
38
  getHistorySnapshot(sessionId: string): Message[];
39
+ /**
40
+ * 从持久化存储加载会话历史(重启后恢复 Agent 上下文)
41
+ * 需要在 run() 之前调用
42
+ * @returns true 如果加载成功且有历史消息
43
+ */
44
+ loadHistory(sessionId: string): Promise<boolean>;
45
+ /**
46
+ * 截断会话历史到指定位置(消息编辑场景)
47
+ * @param sessionId 会话 ID
48
+ * @param toIndex 保留的消息数量
49
+ * @returns 被截断掉的消息数量
50
+ */
51
+ truncateHistory(sessionId: string, toIndex: number): number;
52
+ /**
53
+ * 从现有会话分叉创建新会话(对话分支场景)
54
+ * @param sourceSessionId 源会话 ID
55
+ * @param targetSessionId 目标会话 ID
56
+ * @param fromIndex 从源会话复制到哪个位置
57
+ * @returns 新会话中的消息数量
58
+ */
59
+ forkHistory(sourceSessionId: string, targetSessionId: string, fromIndex?: number): number;
60
+ /** 获取会话历史的消息数量 */
61
+ getHistoryLength(sessionId: string): number;
39
62
  /**
40
63
  * 执行 Agent 任务(流式推送事件)
41
64
  * 上层通过 for-await-of 消费事件流
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/agent/engine.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAuD,MAAM,aAAa,CAAC;AAGzH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAe,MAAM,YAAY,CAAC;AAEvE,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AA4D5E,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA4G;IAC1H,8BAA8B;IAC9B,OAAO,CAAC,SAAS,CAAkC;IACnD,6CAA6C;IAC7C,OAAO,CAAC,QAAQ,CAAsC;IACtD,4CAA4C;IAC5C,OAAO,CAAC,WAAW,CAA+B;IAElD,gBAAgB;IAChB,OAAO,CAAC,cAAc,CAAiB;IACvC,kBAAkB;IAClB,OAAO,CAAC,SAAS,CAAY;IAC7B,gBAAgB;IAChB,OAAO,CAAC,YAAY,CAAoB;IAExC,wBAAwB;IACxB,OAAO,CAAC,cAAc,CAAc;IACpC,iCAAiC;IACjC,OAAO,CAAC,WAAW,CAAc;gBAErB,MAAM,EAAE,WAAW;IAkD/B,yDAAyD;IACzD,eAAe,IAAI,YAAY;IAI/B,2CAA2C;IAC3C,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAInC,mEAAmE;IACnE,eAAe,IAAI,OAAO,qBAAqB,EAAE,YAAY,GAAG,SAAS;IAIzE;;;OAGG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI;IAIxD;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE;IAIhD;;;OAGG;IACI,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;IAoC3D,0CAA0C;YAC5B,YAAY;IAe1B,wCAAwC;IACxC,OAAO,CAAC,oBAAoB;IA4D5B,6BAA6B;IAC7B,OAAO,CAAC,eAAe;IAyCvB,qBAAqB;IACrB,OAAO,CAAC,gBAAgB;IAmBxB,0BAA0B;YACZ,UAAU;IAyBxB,sCAAsC;YACvB,SAAS;IAgJxB;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IASlD,yCAAyC;IACzC,OAAO,CAAC,aAAa;IAgBrB;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAoB3B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAuC5B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAiC1B,wBAAwB;IACxB,OAAO,CAAC,oBAAoB;IAsC5B;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAuB/B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IA2B9B,uBAAuB;IACjB,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAkBzE,6BAA6B;YACf,kBAAkB;IAwBhC,yCAAyC;IACnC,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,aAAa,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAqB5G,OAAO,CAAC,QAAQ;IAkBhB,uBAAuB;IACvB,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAQ9B,uBAAuB;IACvB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW;IAIzC,oBAAoB;IACpB,OAAO,IAAI,IAAI;IAYf,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU;IAI1E,OAAO,CAAC,eAAe;CAOxB"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../../src/agent/engine.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@
3
3
  // ============================================================
4
4
  // 职责:编排 HistoryManager、LLMCaller、ToolExecutor 完成 ReAct 循环
5
5
  // 历史管理、LLM 调用、工具执行已分别抽离到独立模块
6
+ import { extractTextFromContent } from "../types.js";
6
7
  import { HistoryManager } from "./history-manager.js";
7
8
  import { LLMCaller } from "./llm-caller.js";
8
9
  import { AgentToolExecutor } from "./tool-executor.js";
@@ -67,6 +68,7 @@ export class AgentEngine {
67
68
  maxMessages: this.config.maxMessages,
68
69
  contextBudget: this.config.contextBudget,
69
70
  toolResultStore: this.config.toolResultStore,
71
+ persistence: this.config.historyPersistence,
70
72
  });
71
73
  this.llmCaller = new LLMCaller({
72
74
  llmProvider: this.config.llmProvider,
@@ -123,6 +125,37 @@ export class AgentEngine {
123
125
  getHistorySnapshot(sessionId) {
124
126
  return this.historyManager.getHistorySnapshot(sessionId);
125
127
  }
128
+ /**
129
+ * 从持久化存储加载会话历史(重启后恢复 Agent 上下文)
130
+ * 需要在 run() 之前调用
131
+ * @returns true 如果加载成功且有历史消息
132
+ */
133
+ async loadHistory(sessionId) {
134
+ return this.historyManager.loadHistory(sessionId);
135
+ }
136
+ /**
137
+ * 截断会话历史到指定位置(消息编辑场景)
138
+ * @param sessionId 会话 ID
139
+ * @param toIndex 保留的消息数量
140
+ * @returns 被截断掉的消息数量
141
+ */
142
+ truncateHistory(sessionId, toIndex) {
143
+ return this.historyManager.truncateHistory(sessionId, toIndex);
144
+ }
145
+ /**
146
+ * 从现有会话分叉创建新会话(对话分支场景)
147
+ * @param sourceSessionId 源会话 ID
148
+ * @param targetSessionId 目标会话 ID
149
+ * @param fromIndex 从源会话复制到哪个位置
150
+ * @returns 新会话中的消息数量
151
+ */
152
+ forkHistory(sourceSessionId, targetSessionId, fromIndex) {
153
+ return this.historyManager.forkHistory(sourceSessionId, targetSessionId, fromIndex);
154
+ }
155
+ /** 获取会话历史的消息数量 */
156
+ getHistoryLength(sessionId) {
157
+ return this.historyManager.getHistoryLength(sessionId);
158
+ }
126
159
  /**
127
160
  * 执行 Agent 任务(流式推送事件)
128
161
  * 上层通过 for-await-of 消费事件流
@@ -171,9 +204,11 @@ export class AgentEngine {
171
204
  }
172
205
  if (this.config.skillRouter) {
173
206
  this.statusMap.set(sessionId, 'thinking');
174
- const routeResult = await this.config.skillRouter.route(options.message);
207
+ // Skill 路由基于文本匹配,从多模态消息中提取文本
208
+ const routeText = typeof options.message === 'string' ? options.message : extractTextFromContent(options.message);
209
+ const routeResult = await this.config.skillRouter.route(routeText);
175
210
  if (routeResult.skill) {
176
- return { skillContent: routeResult.skill.content, actualMessage: routeResult.message, skillMatched: true };
211
+ return { skillContent: routeResult.skill.content, actualMessage: options.message, skillMatched: true };
177
212
  }
178
213
  }
179
214
  return { actualMessage: options.message, skillMatched: false };
@@ -226,12 +261,20 @@ export class AgentEngine {
226
261
  // 则不再重复追加,避免 LLM 看到两条连续相同的 user 消息导致意图理解偏差
227
262
  const history = this.historyManager.getHistory(sessionId);
228
263
  const lastMsg = history.length > 0 ? history[history.length - 1] : null;
264
+ // 多模态消息去重:比较文本内容
265
+ const actualText = typeof actualMessage === 'string' ? actualMessage : extractTextFromContent(actualMessage);
229
266
  const isDuplicateUserMessage = lastMsg?.role === 'user'
230
267
  && typeof lastMsg.content === 'string'
231
- && lastMsg.content === actualMessage;
268
+ && lastMsg.content === actualText;
269
+ // 非破坏性上下文投影(Context Collapse):
270
+ // 当历史 token 超过预算时,使用投影而非破坏性压缩,保留原始历史完整
271
+ const maxContextTokens = this.config.contextBudget?.maxContextTokens ?? 100000;
272
+ const projectedHistory = this.historyManager.getProjectedHistory
273
+ ? this.historyManager.getProjectedHistory(sessionId, maxContextTokens)
274
+ : history;
232
275
  return this.config.contextManager.buildMessages({
233
276
  systemPrompt,
234
- history,
277
+ history: projectedHistory,
235
278
  userMessage: isDuplicateUserMessage ? undefined : actualMessage,
236
279
  });
237
280
  }
@@ -326,6 +369,25 @@ export class AgentEngine {
326
369
  yield this.emitDone(state);
327
370
  return;
328
371
  }
372
+ // Token 预算检查
373
+ if (this.config.usageTracker && this.config.tokenBudget) {
374
+ const budgetCheck = this.config.usageTracker.checkBudget(state.sessionId, this.config.tokenBudget);
375
+ if (budgetCheck.exceeded) {
376
+ if (this.config.tokenBudget.onExceed === 'abort') {
377
+ console.warn(`[Engine] Token budget exceeded: ${budgetCheck.currentTokens}/${budgetCheck.maxTokens}, aborting session ${state.sessionId}`);
378
+ yield this.createEvent(state.sessionId, {
379
+ type: 'error',
380
+ error: `Token budget exceeded (${budgetCheck.currentTokens}/${budgetCheck.maxTokens} tokens). Task aborted to prevent cost overrun.`,
381
+ recoverable: false,
382
+ });
383
+ yield this.emitDone(state);
384
+ return;
385
+ }
386
+ else {
387
+ console.warn(`[Engine] Token budget warning: ${budgetCheck.currentTokens}/${budgetCheck.maxTokens} for session ${state.sessionId}`);
388
+ }
389
+ }
390
+ }
329
391
  // Middleware.before + Hook: on_iteration_start
330
392
  await this.runMiddlewarePhase('before', state);
331
393
  await this.runHooks('on_iteration_start', {
@@ -379,7 +441,7 @@ export class AgentEngine {
379
441
  }
380
442
  this.historyManager.addHistory(state.sessionId, assistant);
381
443
  if (assistant.content) {
382
- state.lastContent = assistant.content;
444
+ state.lastContent = extractTextFromContent(assistant.content);
383
445
  state.consecutiveSilentIterations = 0;
384
446
  }
385
447
  // 无 tool_calls → 检查是否提前停止(上一轮有工具调用,说明任务可能未完成)
@@ -720,6 +782,17 @@ export class AgentEngine {
720
782
  // ---- 辅助 ----
721
783
  emitDone(state) {
722
784
  this.statusMap.set(state.sessionId, 'idle');
785
+ // 记录 Token 用量到 UsageTracker
786
+ if (this.config.usageTracker && state.totalUsage) {
787
+ const modelInfo = this.config.llmProvider.getModel();
788
+ this.config.usageTracker.record({
789
+ sessionId: state.sessionId,
790
+ provider: modelInfo.provider,
791
+ model: modelInfo.model,
792
+ usage: state.totalUsage,
793
+ iterations: state.iteration,
794
+ });
795
+ }
723
796
  this.runHooks('on_complete', {
724
797
  sessionId: state.sessionId,
725
798
  iteration: state.iteration,