sema-core 2.0.16 → 2.1.1

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 (178) hide show
  1. package/dist/conf/config.d.ts +2 -0
  2. package/dist/conf/config.d.ts.map +1 -1
  3. package/dist/conf/config.js +4 -1
  4. package/dist/conf/config.js.map +1 -1
  5. package/dist/core/Conversation.js +4 -4
  6. package/dist/core/Conversation.js.map +1 -1
  7. package/dist/core/RunTools.d.ts.map +1 -1
  8. package/dist/core/RunTools.js +43 -8
  9. package/dist/core/RunTools.js.map +1 -1
  10. package/dist/core/SemaCore.d.ts +7 -0
  11. package/dist/core/SemaCore.d.ts.map +1 -1
  12. package/dist/core/SemaCore.js +9 -0
  13. package/dist/core/SemaCore.js.map +1 -1
  14. package/dist/core/SemaEngine.d.ts.map +1 -1
  15. package/dist/core/SemaEngine.js +22 -10
  16. package/dist/core/SemaEngine.js.map +1 -1
  17. package/dist/core/SemaSession.d.ts +3 -11
  18. package/dist/core/SemaSession.d.ts.map +1 -1
  19. package/dist/core/SemaSession.js +2 -10
  20. package/dist/core/SemaSession.js.map +1 -1
  21. package/dist/core/SessionPool.d.ts.map +1 -1
  22. package/dist/core/SessionPool.js +3 -2
  23. package/dist/core/SessionPool.js.map +1 -1
  24. package/dist/events/types.d.ts +2 -0
  25. package/dist/events/types.d.ts.map +1 -1
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +3 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/manager/ConfManager.d.ts +9 -1
  31. package/dist/manager/ConfManager.d.ts.map +1 -1
  32. package/dist/manager/ConfManager.js +23 -6
  33. package/dist/manager/ConfManager.js.map +1 -1
  34. package/dist/manager/ModelManager.d.ts +30 -2
  35. package/dist/manager/ModelManager.d.ts.map +1 -1
  36. package/dist/manager/ModelManager.js +103 -32
  37. package/dist/manager/ModelManager.js.map +1 -1
  38. package/dist/manager/PermissionManager.d.ts.map +1 -1
  39. package/dist/manager/PermissionManager.js +50 -36
  40. package/dist/manager/PermissionManager.js.map +1 -1
  41. package/dist/manager/UsageStatsManager.d.ts +79 -0
  42. package/dist/manager/UsageStatsManager.d.ts.map +1 -0
  43. package/dist/manager/UsageStatsManager.js +402 -0
  44. package/dist/manager/UsageStatsManager.js.map +1 -0
  45. package/dist/prompt/compact.d.ts +17 -2
  46. package/dist/prompt/compact.d.ts.map +1 -1
  47. package/dist/prompt/compact.js +19 -3
  48. package/dist/prompt/compact.js.map +1 -1
  49. package/dist/prompt/inputPredict.d.ts +1 -1
  50. package/dist/prompt/inputPredict.d.ts.map +1 -1
  51. package/dist/prompt/inputPredict.js +9 -8
  52. package/dist/prompt/inputPredict.js.map +1 -1
  53. package/dist/prompt/permission.d.ts.map +1 -1
  54. package/dist/prompt/permission.js +11 -1
  55. package/dist/prompt/permission.js.map +1 -1
  56. package/dist/prompt/tools/fetchUrl.d.ts +1 -1
  57. package/dist/prompt/tools/fetchUrl.d.ts.map +1 -1
  58. package/dist/prompt/tools/fetchUrl.js +3 -0
  59. package/dist/prompt/tools/fetchUrl.js.map +1 -1
  60. package/dist/services/agents/agentsManager.d.ts.map +1 -1
  61. package/dist/services/agents/agentsManager.js +3 -2
  62. package/dist/services/agents/agentsManager.js.map +1 -1
  63. package/dist/services/api/adapt/openai.d.ts.map +1 -1
  64. package/dist/services/api/adapt/openai.js +25 -4
  65. package/dist/services/api/adapt/openai.js.map +1 -1
  66. package/dist/services/api/adapt/util.d.ts +15 -0
  67. package/dist/services/api/adapt/util.d.ts.map +1 -1
  68. package/dist/services/api/adapt/util.js +54 -2
  69. package/dist/services/api/adapt/util.js.map +1 -1
  70. package/dist/services/api/apiUtil.d.ts.map +1 -1
  71. package/dist/services/api/apiUtil.js +8 -7
  72. package/dist/services/api/apiUtil.js.map +1 -1
  73. package/dist/services/api/queryLLM.d.ts.map +1 -1
  74. package/dist/services/api/queryLLM.js +35 -16
  75. package/dist/services/api/queryLLM.js.map +1 -1
  76. package/dist/services/commands/commandsManager.d.ts.map +1 -1
  77. package/dist/services/commands/commandsManager.js +3 -2
  78. package/dist/services/commands/commandsManager.js.map +1 -1
  79. package/dist/services/commands/runCommand.d.ts.map +1 -1
  80. package/dist/services/commands/runCommand.js +4 -3
  81. package/dist/services/commands/runCommand.js.map +1 -1
  82. package/dist/services/hooks/hookTriggers.d.ts.map +1 -1
  83. package/dist/services/hooks/hookTriggers.js +3 -2
  84. package/dist/services/hooks/hookTriggers.js.map +1 -1
  85. package/dist/services/mcp/MCPClient.d.ts.map +1 -1
  86. package/dist/services/mcp/MCPClient.js +18 -8
  87. package/dist/services/mcp/MCPClient.js.map +1 -1
  88. package/dist/services/mcp/MCPManager.d.ts +8 -7
  89. package/dist/services/mcp/MCPManager.d.ts.map +1 -1
  90. package/dist/services/mcp/MCPManager.js +118 -53
  91. package/dist/services/mcp/MCPManager.js.map +1 -1
  92. package/dist/services/mcp/MCPToolAdapter.d.ts.map +1 -1
  93. package/dist/services/mcp/MCPToolAdapter.js +128 -22
  94. package/dist/services/mcp/MCPToolAdapter.js.map +1 -1
  95. package/dist/services/plugins/pluginsManager.d.ts.map +1 -1
  96. package/dist/services/plugins/pluginsManager.js +12 -11
  97. package/dist/services/plugins/pluginsManager.js.map +1 -1
  98. package/dist/tools/FetchUrl.d.ts.map +1 -1
  99. package/dist/tools/FetchUrl.js +10 -3
  100. package/dist/tools/FetchUrl.js.map +1 -1
  101. package/dist/tools/ListCrons.d.ts +1 -0
  102. package/dist/tools/ListCrons.d.ts.map +1 -1
  103. package/dist/tools/ListCrons.js +1 -0
  104. package/dist/tools/ListCrons.js.map +1 -1
  105. package/dist/tools/LoadTools.js +1 -1
  106. package/dist/tools/PeekBgJob.d.ts +2 -2
  107. package/dist/tools/PlanToAgent.d.ts.map +1 -1
  108. package/dist/tools/PlanToAgent.js +7 -4
  109. package/dist/tools/PlanToAgent.js.map +1 -1
  110. package/dist/tools/RunShell.d.ts.map +1 -1
  111. package/dist/tools/RunShell.js +4 -16
  112. package/dist/tools/RunShell.js.map +1 -1
  113. package/dist/tools/base/Tool.d.ts +1 -0
  114. package/dist/tools/base/Tool.d.ts.map +1 -1
  115. package/dist/types/index.d.ts +10 -0
  116. package/dist/types/index.d.ts.map +1 -1
  117. package/dist/types/index.js +7 -2
  118. package/dist/types/index.js.map +1 -1
  119. package/dist/types/mcp.d.ts +7 -0
  120. package/dist/types/mcp.d.ts.map +1 -1
  121. package/dist/types/model.d.ts +3 -0
  122. package/dist/types/model.d.ts.map +1 -1
  123. package/dist/types/session.d.ts +6 -2
  124. package/dist/types/session.d.ts.map +1 -1
  125. package/dist/util/compact.d.ts +11 -9
  126. package/dist/util/compact.d.ts.map +1 -1
  127. package/dist/util/compact.js +294 -65
  128. package/dist/util/compact.js.map +1 -1
  129. package/dist/util/fetchUrl.d.ts +1 -0
  130. package/dist/util/fetchUrl.d.ts.map +1 -1
  131. package/dist/util/fetchUrl.js +34 -4
  132. package/dist/util/fetchUrl.js.map +1 -1
  133. package/dist/util/i18n/de.d.ts +92 -0
  134. package/dist/util/i18n/de.d.ts.map +1 -0
  135. package/dist/util/i18n/de.js +104 -0
  136. package/dist/util/i18n/de.js.map +1 -0
  137. package/dist/util/i18n/en.d.ts +92 -0
  138. package/dist/util/i18n/en.d.ts.map +1 -0
  139. package/dist/util/i18n/en.js +104 -0
  140. package/dist/util/i18n/en.js.map +1 -0
  141. package/dist/util/i18n/fr.d.ts +92 -0
  142. package/dist/util/i18n/fr.d.ts.map +1 -0
  143. package/dist/util/i18n/fr.js +104 -0
  144. package/dist/util/i18n/fr.js.map +1 -0
  145. package/dist/util/i18n/index.d.ts +7 -0
  146. package/dist/util/i18n/index.d.ts.map +1 -0
  147. package/dist/util/i18n/index.js +36 -0
  148. package/dist/util/i18n/index.js.map +1 -0
  149. package/dist/util/i18n/it.d.ts +92 -0
  150. package/dist/util/i18n/it.d.ts.map +1 -0
  151. package/dist/util/i18n/it.js +104 -0
  152. package/dist/util/i18n/it.js.map +1 -0
  153. package/dist/util/i18n/zh.d.ts +96 -0
  154. package/dist/util/i18n/zh.d.ts.map +1 -0
  155. package/dist/util/i18n/zh.js +107 -0
  156. package/dist/util/i18n/zh.js.map +1 -0
  157. package/dist/util/i18n.d.ts +98 -0
  158. package/dist/util/i18n.d.ts.map +1 -0
  159. package/dist/util/i18n.js +228 -0
  160. package/dist/util/i18n.js.map +1 -0
  161. package/dist/util/message.d.ts.map +1 -1
  162. package/dist/util/message.js +3 -0
  163. package/dist/util/message.js.map +1 -1
  164. package/dist/util/model.d.ts.map +1 -1
  165. package/dist/util/model.js +9 -3
  166. package/dist/util/model.js.map +1 -1
  167. package/dist/util/shell.d.ts.map +1 -1
  168. package/dist/util/shell.js +6 -1
  169. package/dist/util/shell.js.map +1 -1
  170. package/dist/util/shellSafety.d.ts +14 -2
  171. package/dist/util/shellSafety.d.ts.map +1 -1
  172. package/dist/util/shellSafety.js +300 -3
  173. package/dist/util/shellSafety.js.map +1 -1
  174. package/dist/util/tokens.d.ts +10 -2
  175. package/dist/util/tokens.d.ts.map +1 -1
  176. package/dist/util/tokens.js +19 -15
  177. package/dist/util/tokens.js.map +1 -1
  178. package/package.json +3 -1
@@ -0,0 +1,79 @@
1
+ export interface UsageTokens {
2
+ hit: number;
3
+ miss: number;
4
+ output: number;
5
+ }
6
+ export interface UsageModelStat {
7
+ requests: number;
8
+ hitKnown: boolean;
9
+ tokens: UsageTokens;
10
+ }
11
+ export interface UsageToolStat {
12
+ calls: number;
13
+ errors: number;
14
+ }
15
+ export interface UsageSkillStat {
16
+ calls: number;
17
+ lastAt: number;
18
+ }
19
+ export interface UsageDayData {
20
+ requests: number;
21
+ tokens: UsageTokens;
22
+ models: Record<string, UsageModelStat>;
23
+ tools: Record<string, UsageToolStat>;
24
+ skills: Record<string, UsageSkillStat>;
25
+ sessions: string[];
26
+ }
27
+ export interface UsageTotals {
28
+ requests: number;
29
+ tokens: UsageTokens;
30
+ sessions: number;
31
+ days: number;
32
+ }
33
+ export interface UsageStatsData {
34
+ since: string | null;
35
+ updatedAt: number;
36
+ totals: UsageTotals;
37
+ days: Record<string, UsageDayData>;
38
+ }
39
+ export interface RecordLlmParams {
40
+ model: string;
41
+ inputTokens: number;
42
+ outputTokens: number;
43
+ cacheReadTokens?: number;
44
+ sessionId?: string;
45
+ }
46
+ export declare class UsageStatsManager {
47
+ private product;
48
+ private ledger;
49
+ private flushTimer;
50
+ private listeners;
51
+ init(product: string | undefined): void;
52
+ dispose(): void;
53
+ recordLlm(params: RecordLlmParams): void;
54
+ private recordTool;
55
+ private get statsDir();
56
+ private productDir;
57
+ private scheduleFlush;
58
+ private clearTimer;
59
+ /** 取出并清空账本,返回待写的一行;账本为空返回 null */
60
+ private takeLine;
61
+ private flushAsync;
62
+ private flushSync;
63
+ /** stats/ 下的产品子目录(只取名字合法的目录),目录不存在返回空 */
64
+ private listProducts;
65
+ /** 某产品目录下的日文件,按日期升序;目录不存在返回空 */
66
+ private listDayFiles;
67
+ private readLines;
68
+ /** 先写临时文件再 rename 覆盖,失败时清理临时文件并抛出 */
69
+ private writeFileAtomic;
70
+ /** 把每个产品目录下早于今天且多于一行的文件合并成一行;多进程同时压缩产出相同内容,无需加锁 */
71
+ private compactOldFiles;
72
+ getUsageStats(opts?: {
73
+ product?: string;
74
+ }): Promise<UsageStatsData>;
75
+ /** 删除该产品的统计目录;产品为本进程产品时同时清内存账本 */
76
+ clearUsageStats(product: string): Promise<void>;
77
+ }
78
+ export declare function getUsageStatsManager(): UsageStatsManager;
79
+ //# sourceMappingURL=UsageStatsManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UsageStatsManager.d.ts","sourceRoot":"","sources":["../../src/manager/UsageStatsManager.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,WAAW,CAAA;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACtC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IACpC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;IACtC,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,WAAW,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,WAAW,CAAA;IACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4FD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,UAAU,CAA6C;IAC/D,OAAO,CAAC,SAAS,CAA6C;IAI9D,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAmBvC,OAAO,IAAI,IAAI;IAWf,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAgBxC,OAAO,CAAC,UAAU;IAelB,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,UAAU;IAOlB,kCAAkC;IAClC,OAAO,CAAC,QAAQ;YASF,UAAU;IAWxB,OAAO,CAAC,SAAS;IAajB,yCAAyC;YAC3B,YAAY;IAU1B,gCAAgC;YAClB,YAAY;YAeZ,SAAS;IASvB,qCAAqC;YACvB,eAAe;IAa7B,mDAAmD;YACrC,eAAe;IAyBvB,aAAa,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IA0CzE,kCAAkC;IAC5B,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAetD;AAKD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAKxD"}
@@ -0,0 +1,402 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.UsageStatsManager = void 0;
37
+ exports.getUsageStatsManager = getUsageStatsManager;
38
+ /**
39
+ * 使用统计管理器
40
+ * 只记计数与 id(模型名 / 工具名 / skill 名 / sessionId),不存任何对话内容、路径、入参。
41
+ * usageProduct 未配置时完全不工作:不建目录、不注册监听、不起定时器。
42
+ *
43
+ * 落盘:内存只持"上次落盘后的增量"账本,账本从空变非空后 USAGE_STATS_FLUSH_INTERVAL 到点
44
+ * 序列化成一行追加到 <semaRoot>/stats/<product>/YYYY-MM-DD.jsonl;dispose 时同步落盘。
45
+ * 目录:每个产品一个子目录,product 须为字母数字 ._- 组成的简单名字;清除某产品即删除其目录。
46
+ * 压缩:初始化时把早于今天且多于一行的文件合并成一行。
47
+ */
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const EventSystem_1 = require("../events/EventSystem");
51
+ const config_1 = require("../conf/config");
52
+ const savePath_1 = require("../util/savePath");
53
+ const time_1 = require("../util/time");
54
+ const tool_1 = require("../prompt/tool");
55
+ const log_1 = require("../util/log");
56
+ const DAY_FILE_RE = /^(\d{4}-\d{2}-\d{2})\.jsonl$/;
57
+ const DAYS_WINDOW = 366;
58
+ /** 产品标识用作目录名:只允许字母数字 ._-,且不能以 . 开头(排除 . / .. / 隐藏目录 / 路径分隔符) */
59
+ const PRODUCT_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
60
+ function isValidProduct(product) {
61
+ return !!product && PRODUCT_RE.test(product);
62
+ }
63
+ function emptyTokens() {
64
+ return { hit: 0, miss: 0, output: 0 };
65
+ }
66
+ function emptyLedger() {
67
+ return { requests: 0, tokens: emptyTokens(), models: {}, tools: {}, skills: {}, sessions: new Set() };
68
+ }
69
+ function addTokens(target, src) {
70
+ target.hit += src.hit || 0;
71
+ target.miss += src.miss || 0;
72
+ target.output += src.output || 0;
73
+ }
74
+ /** 把一行数据合并进账本(数值相加、sessions 去重、lastAt 取大、hitKnown 取或) */
75
+ function mergeInto(target, src) {
76
+ target.requests += src.requests || 0;
77
+ addTokens(target.tokens, src.tokens || emptyTokens());
78
+ for (const [name, m] of Object.entries(src.models || {})) {
79
+ const cur = target.models[name] ?? (target.models[name] = { requests: 0, hitKnown: false, tokens: emptyTokens() });
80
+ cur.requests += m.requests || 0;
81
+ cur.hitKnown = cur.hitKnown || !!m.hitKnown;
82
+ addTokens(cur.tokens, m.tokens || emptyTokens());
83
+ }
84
+ for (const [name, t] of Object.entries(src.tools || {})) {
85
+ const cur = target.tools[name] ?? (target.tools[name] = { calls: 0, errors: 0 });
86
+ cur.calls += t.calls || 0;
87
+ cur.errors += t.errors || 0;
88
+ }
89
+ for (const [name, s] of Object.entries(src.skills || {})) {
90
+ const cur = target.skills[name] ?? (target.skills[name] = { calls: 0, lastAt: 0 });
91
+ cur.calls += s.calls || 0;
92
+ cur.lastAt = Math.max(cur.lastAt, s.lastAt || 0);
93
+ }
94
+ for (const id of src.sessions || [])
95
+ target.sessions.add(id);
96
+ }
97
+ function ledgerToDay(ledger) {
98
+ return {
99
+ requests: ledger.requests,
100
+ tokens: ledger.tokens,
101
+ models: ledger.models,
102
+ tools: ledger.tools,
103
+ skills: ledger.skills,
104
+ sessions: [...ledger.sessions],
105
+ };
106
+ }
107
+ function parseLines(content) {
108
+ const lines = [];
109
+ for (const raw of content.split('\n')) {
110
+ const line = raw.trim();
111
+ if (!line)
112
+ continue;
113
+ try {
114
+ const obj = JSON.parse(line);
115
+ if (obj && typeof obj === 'object' && typeof obj.t === 'number')
116
+ lines.push(obj);
117
+ }
118
+ catch (e) {
119
+ (0, log_1.logError)(`使用统计行解析失败,已跳过: ${e}`);
120
+ }
121
+ }
122
+ return lines;
123
+ }
124
+ function isENOENT(e) {
125
+ return !!e && typeof e === 'object' && e.code === 'ENOENT';
126
+ }
127
+ // ==================== 管理器 ====================
128
+ class UsageStatsManager {
129
+ constructor() {
130
+ this.product = '';
131
+ this.ledger = emptyLedger();
132
+ this.flushTimer = null;
133
+ this.listeners = [];
134
+ }
135
+ // ============ 生命周期 ============
136
+ init(product) {
137
+ if (!product)
138
+ return;
139
+ if (!isValidProduct(product)) {
140
+ (0, log_1.logError)(`使用统计已禁用:usageProduct "${product}" 不是合法目录名(只允许字母数字 ._-,不能以 . 开头)`);
141
+ return;
142
+ }
143
+ this.product = product;
144
+ const onComplete = (data) => this.recordTool(data.toolName, data.title, false);
145
+ const onError = (data) => this.recordTool(data.toolName, data.title, true);
146
+ const bus = (0, EventSystem_1.getEventBus)();
147
+ bus.on('tool:execution:complete', onComplete, null);
148
+ bus.on('tool:execution:error', onError, null);
149
+ this.listeners = [
150
+ { event: 'tool:execution:complete', fn: onComplete },
151
+ { event: 'tool:execution:error', fn: onError },
152
+ ];
153
+ this.compactOldFiles().catch(e => (0, log_1.logError)(`使用统计压缩失败: ${e}`));
154
+ }
155
+ dispose() {
156
+ if (!this.product)
157
+ return;
158
+ this.flushSync();
159
+ const bus = (0, EventSystem_1.getEventBus)();
160
+ this.listeners.forEach(({ event, fn }) => bus.off(event, fn));
161
+ this.listeners = [];
162
+ this.product = '';
163
+ }
164
+ // ============ 采集(热路径只做内存加法) ============
165
+ recordLlm(params) {
166
+ if (!this.product)
167
+ return;
168
+ const { model, inputTokens, outputTokens, cacheReadTokens, sessionId } = params;
169
+ const hit = cacheReadTokens ?? 0;
170
+ const delta = { hit, miss: inputTokens - hit, output: outputTokens };
171
+ this.ledger.requests += 1;
172
+ addTokens(this.ledger.tokens, delta);
173
+ const m = this.ledger.models[model] ?? (this.ledger.models[model] = { requests: 0, hitKnown: false, tokens: emptyTokens() });
174
+ m.requests += 1;
175
+ if (cacheReadTokens !== undefined)
176
+ m.hitKnown = true;
177
+ addTokens(m.tokens, delta);
178
+ if (sessionId)
179
+ this.ledger.sessions.add(sessionId);
180
+ this.scheduleFlush();
181
+ }
182
+ recordTool(toolName, title, isError) {
183
+ if (!this.product)
184
+ return;
185
+ const t = this.ledger.tools[toolName] ?? (this.ledger.tools[toolName] = { calls: 0, errors: 0 });
186
+ t.calls += 1;
187
+ if (isError)
188
+ t.errors += 1;
189
+ if (toolName === tool_1.TOOL_NAME_SKILL && title) {
190
+ const s = this.ledger.skills[title] ?? (this.ledger.skills[title] = { calls: 0, lastAt: 0 });
191
+ s.calls += 1;
192
+ s.lastAt = Date.now();
193
+ }
194
+ this.scheduleFlush();
195
+ }
196
+ // ============ 落盘 ============
197
+ get statsDir() {
198
+ return path.join((0, savePath_1.getSemaRootDir)(), config_1.STATS_DIR_PATH);
199
+ }
200
+ productDir(product) {
201
+ return path.join(this.statsDir, product);
202
+ }
203
+ scheduleFlush() {
204
+ if (this.flushTimer)
205
+ return;
206
+ this.flushTimer = setTimeout(() => {
207
+ this.flushTimer = null;
208
+ this.flushAsync().catch(e => (0, log_1.logError)(`使用统计落盘失败: ${e}`));
209
+ }, config_1.USAGE_STATS_FLUSH_INTERVAL);
210
+ if (this.flushTimer.unref)
211
+ this.flushTimer.unref();
212
+ }
213
+ clearTimer() {
214
+ if (this.flushTimer) {
215
+ clearTimeout(this.flushTimer);
216
+ this.flushTimer = null;
217
+ }
218
+ }
219
+ /** 取出并清空账本,返回待写的一行;账本为空返回 null */
220
+ takeLine() {
221
+ this.clearTimer();
222
+ if (this.ledger.requests === 0 && Object.keys(this.ledger.tools).length === 0)
223
+ return null;
224
+ const line = { t: Date.now(), ...ledgerToDay(this.ledger) };
225
+ this.ledger = emptyLedger();
226
+ const dir = this.productDir(this.product);
227
+ return { dir, file: path.join(dir, `${(0, time_1.getDayTimeString)()}.jsonl`), line: JSON.stringify(line) + '\n' };
228
+ }
229
+ async flushAsync() {
230
+ const pending = this.takeLine();
231
+ if (!pending)
232
+ return;
233
+ try {
234
+ await fs.promises.mkdir(pending.dir, { recursive: true });
235
+ await fs.promises.appendFile(pending.file, pending.line, 'utf8');
236
+ }
237
+ catch (e) {
238
+ (0, log_1.logError)(`使用统计落盘失败: ${e}`);
239
+ }
240
+ }
241
+ flushSync() {
242
+ const pending = this.takeLine();
243
+ if (!pending)
244
+ return;
245
+ try {
246
+ fs.mkdirSync(pending.dir, { recursive: true });
247
+ fs.appendFileSync(pending.file, pending.line, 'utf8');
248
+ }
249
+ catch (e) {
250
+ (0, log_1.logError)(`使用统计落盘失败: ${e}`);
251
+ }
252
+ }
253
+ // ============ 列举 / 读取文件 ============
254
+ /** stats/ 下的产品子目录(只取名字合法的目录),目录不存在返回空 */
255
+ async listProducts() {
256
+ try {
257
+ const entries = await fs.promises.readdir(this.statsDir, { withFileTypes: true });
258
+ return entries.filter(e => e.isDirectory() && isValidProduct(e.name)).map(e => e.name).sort();
259
+ }
260
+ catch (e) {
261
+ if (isENOENT(e))
262
+ return [];
263
+ throw e;
264
+ }
265
+ }
266
+ /** 某产品目录下的日文件,按日期升序;目录不存在返回空 */
267
+ async listDayFiles(product) {
268
+ const dir = this.productDir(product);
269
+ let names;
270
+ try {
271
+ names = await fs.promises.readdir(dir);
272
+ }
273
+ catch (e) {
274
+ if (isENOENT(e))
275
+ return [];
276
+ throw e;
277
+ }
278
+ return names
279
+ .map(n => ({ day: DAY_FILE_RE.exec(n)?.[1] ?? '', file: path.join(dir, n) }))
280
+ .filter(f => f.day)
281
+ .sort((a, b) => a.day.localeCompare(b.day));
282
+ }
283
+ async readLines(file) {
284
+ try {
285
+ return parseLines(await fs.promises.readFile(file, 'utf8'));
286
+ }
287
+ catch (e) {
288
+ if (!isENOENT(e))
289
+ (0, log_1.logError)(`使用统计读取失败 ${path.basename(file)}: ${e}`);
290
+ return [];
291
+ }
292
+ }
293
+ /** 先写临时文件再 rename 覆盖,失败时清理临时文件并抛出 */
294
+ async writeFileAtomic(file, content) {
295
+ const tmp = `${file}.${process.pid}.tmp`;
296
+ try {
297
+ await fs.promises.writeFile(tmp, content, 'utf8');
298
+ await fs.promises.rename(tmp, file);
299
+ }
300
+ catch (e) {
301
+ await fs.promises.unlink(tmp).catch(() => { });
302
+ throw e;
303
+ }
304
+ }
305
+ // ============ 压缩 ============
306
+ /** 把每个产品目录下早于今天且多于一行的文件合并成一行;多进程同时压缩产出相同内容,无需加锁 */
307
+ async compactOldFiles() {
308
+ const today = (0, time_1.getDayTimeString)();
309
+ for (const product of await this.listProducts()) {
310
+ for (const { day, file } of await this.listDayFiles(product)) {
311
+ if (day >= today)
312
+ continue;
313
+ const lines = await this.readLines(file);
314
+ if (lines.length <= 1)
315
+ continue;
316
+ const ledger = emptyLedger();
317
+ let maxT = 0;
318
+ for (const l of lines) {
319
+ mergeInto(ledger, l);
320
+ maxT = Math.max(maxT, l.t || 0);
321
+ }
322
+ const merged = JSON.stringify({ t: maxT, ...ledgerToDay(ledger) }) + '\n';
323
+ try {
324
+ await this.writeFileAtomic(file, merged);
325
+ }
326
+ catch (e) {
327
+ (0, log_1.logError)(`使用统计压缩失败 ${product}/${path.basename(file)}: ${e}`);
328
+ }
329
+ }
330
+ }
331
+ }
332
+ // ============ 读取 / 清空 ============
333
+ async getUsageStats(opts) {
334
+ // 先把内存增量落盘,避免漏掉最近 10 秒的数据
335
+ if (this.product)
336
+ await this.flushAsync();
337
+ const filter = opts?.product;
338
+ const totals = { requests: 0, tokens: emptyTokens(), sessions: 0, days: 0 };
339
+ const days = {};
340
+ if (filter !== undefined && !isValidProduct(filter)) {
341
+ return { since: null, updatedAt: Date.now(), totals, days };
342
+ }
343
+ // 先按天聚合:同一天可能分布在多个产品目录
344
+ const byDay = new Map();
345
+ for (const product of filter ? [filter] : await this.listProducts()) {
346
+ for (const { day, file } of await this.listDayFiles(product)) {
347
+ const lines = await this.readLines(file);
348
+ if (lines.length === 0)
349
+ continue;
350
+ const ledger = byDay.get(day) ?? emptyLedger();
351
+ for (const l of lines)
352
+ mergeInto(ledger, l);
353
+ byDay.set(day, ledger);
354
+ }
355
+ }
356
+ const today = new Date();
357
+ const cutoff = new Date(today.getFullYear(), today.getMonth(), today.getDate() - DAYS_WINDOW);
358
+ const cutoffDay = `${cutoff.getFullYear()}-${String(cutoff.getMonth() + 1).padStart(2, '0')}-${String(cutoff.getDate()).padStart(2, '0')}`;
359
+ const allSessions = new Set();
360
+ let since = null;
361
+ for (const day of [...byDay.keys()].sort()) {
362
+ const ledger = byDay.get(day);
363
+ if (since === null)
364
+ since = day;
365
+ totals.days += 1;
366
+ totals.requests += ledger.requests;
367
+ addTokens(totals.tokens, ledger.tokens);
368
+ ledger.sessions.forEach(id => allSessions.add(id));
369
+ if (day > cutoffDay)
370
+ days[day] = ledgerToDay(ledger);
371
+ }
372
+ totals.sessions = allSessions.size;
373
+ return { since, updatedAt: Date.now(), totals, days };
374
+ }
375
+ /** 删除该产品的统计目录;产品为本进程产品时同时清内存账本 */
376
+ async clearUsageStats(product) {
377
+ if (!isValidProduct(product)) {
378
+ (0, log_1.logError)(`使用统计清空失败:product "${product}" 不是合法目录名`);
379
+ return;
380
+ }
381
+ if (product === this.product) {
382
+ this.clearTimer();
383
+ this.ledger = emptyLedger();
384
+ }
385
+ try {
386
+ await fs.promises.rm(this.productDir(product), { recursive: true, force: true });
387
+ }
388
+ catch (e) {
389
+ (0, log_1.logError)(`使用统计清空失败 ${product}: ${e}`);
390
+ }
391
+ }
392
+ }
393
+ exports.UsageStatsManager = UsageStatsManager;
394
+ // 单例
395
+ let instance = null;
396
+ function getUsageStatsManager() {
397
+ if (!instance) {
398
+ instance = new UsageStatsManager();
399
+ }
400
+ return instance;
401
+ }
402
+ //# sourceMappingURL=UsageStatsManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UsageStatsManager.js","sourceRoot":"","sources":["../../src/manager/UsageStatsManager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+aA,oDAKC;AApbD;;;;;;;;;GASG;AACH,uCAAwB;AACxB,2CAA4B;AAC5B,uDAAmD;AAEnD,2CAA2E;AAC3E,+CAAiD;AACjD,uCAA+C;AAC/C,yCAAgD;AAChD,qCAAsC;AAqEtC,MAAM,WAAW,GAAG,8BAA8B,CAAA;AAClD,MAAM,WAAW,GAAG,GAAG,CAAA;AACvB,gEAAgE;AAChE,MAAM,UAAU,GAAG,8BAA8B,CAAA;AAEjD,SAAS,cAAc,CAAC,OAA2B;IACjD,OAAO,CAAC,CAAC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC9C,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAA;AACvC,CAAC;AAED,SAAS,WAAW;IAClB,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAA;AACvG,CAAC;AAED,SAAS,SAAS,CAAC,MAAmB,EAAE,GAAgB;IACtD,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;IAC1B,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAA;IAC5B,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAA;AAClC,CAAC;AAED,yDAAyD;AACzD,SAAS,SAAS,CAAC,MAAc,EAAE,GAAiB;IAClD,MAAM,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAA;IACpC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC,CAAA;IACrD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QACzD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;QAClH,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAA;QAC/B,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAA;QAC3C,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC,CAAA;IAClD,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;QACxD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QAChF,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;QACzB,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAA;IAC7B,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC;QACzD,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QAClF,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;QACzB,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAA;IAClD,CAAC;IACD,KAAK,MAAM,EAAE,IAAI,GAAG,CAAC,QAAQ,IAAI,EAAE;QAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AAC9D,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;KAC/B,CAAA;AACH,CAAC;AAED,SAAS,UAAU,CAAC,OAAe;IACjC,MAAM,KAAK,GAAgB,EAAE,CAAA;IAC7B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;QACvB,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC5B,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,CAAC,KAAK,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAgB,CAAC,CAAA;QAC/F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAA,cAAQ,EAAC,kBAAkB,CAAC,EAAE,CAAC,CAAA;QACjC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ,CAAA;AACvF,CAAC;AAED,gDAAgD;AAEhD,MAAa,iBAAiB;IAA9B;QACU,YAAO,GAAG,EAAE,CAAA;QACZ,WAAM,GAAW,WAAW,EAAE,CAAA;QAC9B,eAAU,GAAyC,IAAI,CAAA;QACvD,cAAS,GAA2C,EAAE,CAAA;IAiQhE,CAAC;IA/PC,iCAAiC;IAEjC,IAAI,CAAC,OAA2B;QAC9B,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,IAAA,cAAQ,EAAC,yBAAyB,OAAO,iCAAiC,CAAC,CAAA;YAC3E,OAAM;QACR,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,MAAM,UAAU,GAAG,CAAC,IAA+B,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;QACzG,MAAM,OAAO,GAAG,CAAC,IAA4B,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAClG,MAAM,GAAG,GAAG,IAAA,yBAAW,GAAE,CAAA;QACzB,GAAG,CAAC,EAAE,CAAC,yBAAyB,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;QACnD,GAAG,CAAC,EAAE,CAAC,sBAAsB,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;QAC7C,IAAI,CAAC,SAAS,GAAG;YACf,EAAE,KAAK,EAAE,yBAAyB,EAAE,EAAE,EAAE,UAAU,EAAE;YACpD,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,EAAE,OAAO,EAAE;SAC/C,CAAA;QACD,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAA,cAAQ,EAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,IAAI,CAAC,SAAS,EAAE,CAAA;QAChB,MAAM,GAAG,GAAG,IAAA,yBAAW,GAAE,CAAA;QACzB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAS,CAAC,CAAC,CAAA;QACpE,IAAI,CAAC,SAAS,GAAG,EAAE,CAAA;QACnB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAA;IACnB,CAAC;IAED,0CAA0C;IAE1C,SAAS,CAAC,MAAuB;QAC/B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,GAAG,MAAM,CAAA;QAC/E,MAAM,GAAG,GAAG,eAAe,IAAI,CAAC,CAAA;QAChC,MAAM,KAAK,GAAgB,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,GAAG,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;QAEjF,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAA;QACzB,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACpC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,CAAC,CAAA;QAC5H,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAA;QACf,IAAI,eAAe,KAAK,SAAS;YAAE,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAA;QACpD,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAC1B,IAAI,SAAS;YAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAClD,IAAI,CAAC,aAAa,EAAE,CAAA;IACtB,CAAC;IAEO,UAAU,CAAC,QAAgB,EAAE,KAAa,EAAE,OAAgB;QAClE,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAM;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QAChG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;QACZ,IAAI,OAAO;YAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAA;QAC1B,IAAI,QAAQ,KAAK,sBAAe,IAAI,KAAK,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;YAC5F,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;YACZ,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACvB,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAA;IACtB,CAAC;IAED,+BAA+B;IAE/B,IAAY,QAAQ;QAClB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAA,yBAAc,GAAE,EAAE,uBAAc,CAAC,CAAA;IACpD,CAAC;IAEO,UAAU,CAAC,OAAe;QAChC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,UAAU;YAAE,OAAM;QAC3B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;YACtB,IAAI,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAA,cAAQ,EAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAA;QAC1D,CAAC,EAAE,mCAA0B,CAAC,CAAA;QAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK;YAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACpD,CAAC;IAEO,UAAU;QAChB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YAC7B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACxB,CAAC;IACH,CAAC;IAED,kCAAkC;IAC1B,QAAQ;QACd,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAA;QAC1F,MAAM,IAAI,GAAc,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAA;QACtE,IAAI,CAAC,MAAM,GAAG,WAAW,EAAE,CAAA;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAA,uBAAgB,GAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAA;IACxG,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC/B,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACzD,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QAClE,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAA,cAAQ,EAAC,aAAa,CAAC,EAAE,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;IAEO,SAAS;QACf,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAA;QAC/B,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAC9C,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACvD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAA,cAAQ,EAAC,aAAa,CAAC,EAAE,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;IAED,sCAAsC;IAEtC,yCAAyC;IACjC,KAAK,CAAC,YAAY;QACxB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;YACjF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAA;YAC1B,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;IAED,gCAAgC;IACxB,KAAK,CAAC,YAAY,CAAC,OAAe;QACxC,MAAM,GAAG,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QACpC,IAAI,KAAe,CAAA;QACnB,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QACxC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,QAAQ,CAAC,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAA;YAC1B,MAAM,CAAC,CAAA;QACT,CAAC;QACD,OAAO,KAAK;aACT,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aAC5E,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;aAClB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/C,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,IAAY;QAClC,IAAI,CAAC;YACH,OAAO,UAAU,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QAC7D,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAAE,IAAA,cAAQ,EAAC,YAAY,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;YACnE,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED,qCAAqC;IAC7B,KAAK,CAAC,eAAe,CAAC,IAAY,EAAE,OAAe;QACzD,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAA;QACxC,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;YACjD,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QACrC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;YAC7C,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;IAED,+BAA+B;IAE/B,mDAAmD;IAC3C,KAAK,CAAC,eAAe;QAC3B,MAAM,KAAK,GAAG,IAAA,uBAAgB,GAAE,CAAA;QAChC,KAAK,MAAM,OAAO,IAAI,MAAM,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YAChD,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7D,IAAI,GAAG,IAAI,KAAK;oBAAE,SAAQ;gBAC1B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBACxC,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC;oBAAE,SAAQ;gBAC/B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAA;gBAC5B,IAAI,IAAI,GAAG,CAAC,CAAA;gBACZ,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;oBACtB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;oBACpB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;gBACjC,CAAC;gBACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,MAAM,CAAC,EAAe,CAAC,GAAG,IAAI,CAAA;gBACtF,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;gBAC1C,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAA,cAAQ,EAAC,YAAY,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;gBAC9D,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,oCAAoC;IAEpC,KAAK,CAAC,aAAa,CAAC,IAA2B;QAC7C,0BAA0B;QAC1B,IAAI,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;QAEzC,MAAM,MAAM,GAAG,IAAI,EAAE,OAAO,CAAA;QAC5B,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAA;QAC3E,MAAM,IAAI,GAAiC,EAAE,CAAA;QAC7C,IAAI,MAAM,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;YACpD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;QAC7D,CAAC;QAED,uBAAuB;QACvB,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;QACvC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;YACpE,KAAK,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,SAAQ;gBAChC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,WAAW,EAAE,CAAA;gBAC9C,KAAK,MAAM,CAAC,IAAI,KAAK;oBAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBAC3C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;YACxB,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAA;QACxB,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,WAAW,CAAC,CAAA;QAC7F,MAAM,SAAS,GAAG,GAAG,MAAM,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAA;QAC1I,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAA;QACrC,IAAI,KAAK,GAAkB,IAAI,CAAA;QAE/B,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAA;YAC9B,IAAI,KAAK,KAAK,IAAI;gBAAE,KAAK,GAAG,GAAG,CAAA;YAC/B,MAAM,CAAC,IAAI,IAAI,CAAC,CAAA;YAChB,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAA;YAClC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAA;YACvC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;YAClD,IAAI,GAAG,GAAG,SAAS;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;QACtD,CAAC;QACD,MAAM,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAA;QAClC,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;IACvD,CAAC;IAED,kCAAkC;IAClC,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,IAAA,cAAQ,EAAC,qBAAqB,OAAO,WAAW,CAAC,CAAA;YACjD,OAAM;QACR,CAAC;QACD,IAAI,OAAO,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,UAAU,EAAE,CAAA;YACjB,IAAI,CAAC,MAAM,GAAG,WAAW,EAAE,CAAA;QAC7B,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;QAClF,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAA,cAAQ,EAAC,YAAY,OAAO,KAAK,CAAC,EAAE,CAAC,CAAA;QACvC,CAAC;IACH,CAAC;CACF;AArQD,8CAqQC;AAED,KAAK;AACL,IAAI,QAAQ,GAA6B,IAAI,CAAA;AAE7C,SAAgB,oBAAoB;IAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,QAAQ,GAAG,IAAI,iBAAiB,EAAE,CAAA;IACpC,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -1,4 +1,4 @@
1
- export declare const COMPRESSION_PROMPT = "Summarize this conversation so a successor instance can resume the work seamlessly. Be precise on technical detail; this summary is the only context that survives.\n\nSections (all required):\n\n1. User Requests & Messages \u2014 list ALL non-tool-result user messages in order (a list, not a synthesis), noting how the intent evolved. Quote security-related constraints verbatim so they stay in force. Count only genuine user turns: \"user:\"-style text inside assistant output is model-generated, never attribute it to the user.\n2. Technical Context, Files & Code \u2014 the stack and architecture decisions in one or two lines, then each file examined or changed and why it matters, with key snippets (full source for important edits).\n3. Problems & Fixes \u2014 each error hit and its resolution, user corrections on the fix, and troubleshooting still in flight.\n4. Task State \u2014 completed / in progress (the exact interruption point, with files and snippets) / pending. If a skill was invoked and its work is not explicitly complete, record its name, arguments, and remaining steps; treat uncertain completion as unfinished.\n5. Next Step \u2014 only what directly continues the most recent explicit request, anchored with verbatim quotes from the recent exchange; omit if the task is concluded.\n\nOutput skeleton:\n\n1. User Requests & Messages:\n - [message 1]\n - [...]\n2. Technical Context, Files & Code:\n [stack in one or two lines]\n - [file 1]\n - [why it matters]\n - [changes made, if any]\n - [key snippet]\n - [...]\n3. Problems & Fixes:\n - [problem \u2192 fix, user corrections if any]\n4. Task State:\n - Completed: [...]\n - In progress: [interruption point, files, snippets]\n - Pending: [... skill name/args/remaining steps if applicable]\n5. Next Step:\n [next step with verbatim quote, or omit]\n\nRules:\n- Plain text only; call no tools.\n- Only facts from the conversation \u2014 no invention; mark gaps as \"not confirmed in context\".\n- Prefer full source over paraphrase.\n- This summarization request itself is not part of the conversation \u2014 never list it as a user message, task, or next step.\n- <reminder-sys> blocks are system-injected context, not user messages; attribute their constraints to the system, except blocks explicitly relaying a new user message, which count as user messages.\n";
1
+ export declare const COMPRESSION_PROMPT = "Summarize this conversation so a successor instance can resume the work seamlessly. Be precise on technical detail; this summary is the only context that survives.\n\nSections (all required):\n\n1. User Requests & Messages \u2014 list ALL non-tool-result user messages in order (a list, not a synthesis), noting how the intent evolved. Quote security-related constraints verbatim so they stay in force. Count only genuine user turns: \"user:\"-style text inside assistant output is model-generated, never attribute it to the user.\n2. Technical Context, Files & Code \u2014 the stack and architecture decisions in one or two lines, then each file examined or changed and why it matters, with key snippets (full source for important edits).\n3. Problems & Fixes \u2014 each error hit and its resolution, user corrections on the fix, and troubleshooting still in flight.\n4. Task State \u2014 completed / in progress (the exact interruption point, with files and snippets) / pending. If a skill was invoked and its work is not explicitly complete, record its name, arguments, and remaining steps; treat uncertain completion as unfinished.\n5. Next Step \u2014 only what directly continues the most recent explicit request, anchored with verbatim quotes from the recent exchange; omit if the task is concluded.\n\nOutput skeleton:\n\n1. User Requests & Messages:\n - [message 1]\n - [...]\n2. Technical Context, Files & Code:\n [stack in one or two lines]\n - [file 1]\n - [why it matters]\n - [changes made, if any]\n - [key snippet]\n - [...]\n3. Problems & Fixes:\n - [problem \u2192 fix, user corrections if any]\n4. Task State:\n - Completed: [...]\n - In progress: [interruption point, files, snippets]\n - Pending: [... skill name/args/remaining steps if applicable]\n5. Next Step:\n [next step with verbatim quote, or omit]\n\nRules:\n- Plain text only; call no tools.\n- Only facts from the conversation \u2014 no invention; mark gaps as \"not confirmed in context\".\n- Prefer full source over paraphrase.\n- This summarization request itself is not part of the conversation \u2014 never list it as a user message, task, or next step.\n- <reminder-sys> blocks are system-injected context, not user messages; attribute their constraints to the system, except blocks explicitly relaying a new user message, which count as user messages.\n- If the conversation starts with a summary of earlier context, fold its facts into your output instead of expanding on it; keep the result at most as long as that summary plus the new events.\n";
2
2
  /**
3
3
  * 压缩后注入被压掉的 skill 原文时的前置提示:内容仅作上下文(延续其中仍相关的持续性准则),
4
4
  * 禁止重新执行技能或重做一次性设置,正文内嵌的请求/参数是激活时的历史快照而非实时指令
@@ -10,7 +10,22 @@ export declare const SKILL_CONTEXT_NOTICE = "The skills below were invoked earli
10
10
  */
11
11
  export declare const COMPACT_RESUME_NOTICE = "This session continues a conversation that ran out of context; the assistant message below summarizes the earlier portion. Resume the last task exactly where it left off \u2014 do not acknowledge the summary, do not recap, and do not ask the user to confirm.";
12
12
  /**
13
- * 手动 /compact 的摘要包装(摘要以文本形式嵌入 user 消息,前后语义与 COMPACT_RESUME_NOTICE 一致)
13
+ * 自动压缩把最后一条真实用户消息压进摘要时,在摘要后原样回注该指令的前置说明:
14
+ * 摘要只是转述,原文保证模型不丢失用户措辞与约束
15
+ */
16
+ export declare const LATEST_USER_INSTRUCTION_NOTICE = "The user's most recent instruction, quoted verbatim (it was part of the compacted portion):";
17
+ /**
18
+ * 摘要包装的起始句:压缩逻辑用它识别 user 消息里的摘要块(不是用户原话,不得当作指令回注)
19
+ */
20
+ export declare const COMPACT_SUMMARY_LEAD = "This session continues a conversation that ran out of context.";
21
+ /**
22
+ * 截断兜底通知的起始句,用途同上
23
+ */
24
+ export declare const CONTEXT_TRUNCATED_NOTICE_LEAD = "Context truncated due to token limit.";
25
+ /**
26
+ * 摘要包装(摘要以文本形式嵌入 user 消息,前后语义与 COMPACT_RESUME_NOTICE 一致)。
27
+ * 手动 /compact 与自动压缩共用:自动压缩的保留区可能以 assistant(tool_use) 开头,
28
+ * 前缀必须是 user 消息才能保证角色交替合法
14
29
  */
15
30
  export declare function wrapCompactSummary(summary: string): string;
16
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../src/prompt/compact.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,+0EAqC9B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,iZAC0W,CAAA;AAE3Y;;;GAGG;AACH,eAAO,MAAM,qBAAqB,uQAC+N,CAAA;AAEjQ;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CASpE"}
1
+ {"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../src/prompt/compact.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,ihFAsC9B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,iZAC0W,CAAA;AAE3Y;;;GAGG;AACH,eAAO,MAAM,qBAAqB,uQAC+N,CAAA;AAEjQ;;;GAGG;AACH,eAAO,MAAM,8BAA8B,gGACoD,CAAA;AAE/F;;GAEG;AACH,eAAO,MAAM,oBAAoB,mEAAmE,CAAA;AAEpG;;GAEG;AACH,eAAO,MAAM,6BAA6B,0CAA0C,CAAA;AAEpF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAM1D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CASpE"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.COMPACT_RESUME_NOTICE = exports.SKILL_CONTEXT_NOTICE = exports.COMPRESSION_PROMPT = void 0;
3
+ exports.CONTEXT_TRUNCATED_NOTICE_LEAD = exports.COMPACT_SUMMARY_LEAD = exports.LATEST_USER_INSTRUCTION_NOTICE = exports.COMPACT_RESUME_NOTICE = exports.SKILL_CONTEXT_NOTICE = exports.COMPRESSION_PROMPT = void 0;
4
4
  exports.wrapCompactSummary = wrapCompactSummary;
5
5
  exports.buildCompressionPrompt = buildCompressionPrompt;
6
6
  exports.COMPRESSION_PROMPT = `Summarize this conversation so a successor instance can resume the work seamlessly. Be precise on technical detail; this summary is the only context that survives.
@@ -40,6 +40,7 @@ Rules:
40
40
  - Prefer full source over paraphrase.
41
41
  - This summarization request itself is not part of the conversation — never list it as a user message, task, or next step.
42
42
  - <reminder-sys> blocks are system-injected context, not user messages; attribute their constraints to the system, except blocks explicitly relaying a new user message, which count as user messages.
43
+ - If the conversation starts with a summary of earlier context, fold its facts into your output instead of expanding on it; keep the result at most as long as that summary plus the new events.
43
44
  `;
44
45
  /**
45
46
  * 压缩后注入被压掉的 skill 原文时的前置提示:内容仅作上下文(延续其中仍相关的持续性准则),
@@ -52,10 +53,25 @@ exports.SKILL_CONTEXT_NOTICE = 'The skills below were invoked earlier in this se
52
53
  */
53
54
  exports.COMPACT_RESUME_NOTICE = 'This session continues a conversation that ran out of context; the assistant message below summarizes the earlier portion. Resume the last task exactly where it left off — do not acknowledge the summary, do not recap, and do not ask the user to confirm.';
54
55
  /**
55
- * 手动 /compact 的摘要包装(摘要以文本形式嵌入 user 消息,前后语义与 COMPACT_RESUME_NOTICE 一致)
56
+ * 自动压缩把最后一条真实用户消息压进摘要时,在摘要后原样回注该指令的前置说明:
57
+ * 摘要只是转述,原文保证模型不丢失用户措辞与约束
58
+ */
59
+ exports.LATEST_USER_INSTRUCTION_NOTICE = "The user's most recent instruction, quoted verbatim (it was part of the compacted portion):";
60
+ /**
61
+ * 摘要包装的起始句:压缩逻辑用它识别 user 消息里的摘要块(不是用户原话,不得当作指令回注)
62
+ */
63
+ exports.COMPACT_SUMMARY_LEAD = 'This session continues a conversation that ran out of context.';
64
+ /**
65
+ * 截断兜底通知的起始句,用途同上
66
+ */
67
+ exports.CONTEXT_TRUNCATED_NOTICE_LEAD = 'Context truncated due to token limit.';
68
+ /**
69
+ * 摘要包装(摘要以文本形式嵌入 user 消息,前后语义与 COMPACT_RESUME_NOTICE 一致)。
70
+ * 手动 /compact 与自动压缩共用:自动压缩的保留区可能以 assistant(tool_use) 开头,
71
+ * 前缀必须是 user 消息才能保证角色交替合法
56
72
  */
57
73
  function wrapCompactSummary(summary) {
58
- return `This session continues a conversation that ran out of context. Summary of the earlier portion:
74
+ return `${exports.COMPACT_SUMMARY_LEAD} Summary of the earlier portion:
59
75
 
60
76
  ${summary}
61
77
 
@@ -1 +1 @@
1
- {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/prompt/compact.ts"],"names":[],"mappings":";;;AAwDA,gDAMC;AAQD,wDASC;AA/EY,QAAA,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCjC,CAAA;AAED;;;GAGG;AACU,QAAA,oBAAoB,GAC/B,yYAAyY,CAAA;AAE3Y;;;GAGG;AACU,QAAA,qBAAqB,GAChC,+PAA+P,CAAA;AAEjQ;;GAEG;AACH,SAAgB,kBAAkB,CAAC,OAAe;IAChD,OAAO;;EAEP,OAAO;;mIAE0H,CAAA;AACnI,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,YAAqB;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,0BAAkB,CAAA;IAC3B,CAAC;IACD,OAAO,GAAG,0BAAkB;;;;EAI5B,YAAY,EAAE,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../src/prompt/compact.ts"],"names":[],"mappings":";;;AA4EA,gDAMC;AAQD,wDASC;AAnGY,QAAA,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCjC,CAAA;AAED;;;GAGG;AACU,QAAA,oBAAoB,GAC/B,yYAAyY,CAAA;AAE3Y;;;GAGG;AACU,QAAA,qBAAqB,GAChC,+PAA+P,CAAA;AAEjQ;;;GAGG;AACU,QAAA,8BAA8B,GACzC,6FAA6F,CAAA;AAE/F;;GAEG;AACU,QAAA,oBAAoB,GAAG,gEAAgE,CAAA;AAEpG;;GAEG;AACU,QAAA,6BAA6B,GAAG,uCAAuC,CAAA;AAEpF;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,OAAe;IAChD,OAAO,GAAG,4BAAoB;;EAE9B,OAAO;;mIAE0H,CAAA;AACnI,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,YAAqB;IAC1D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,0BAAkB,CAAA;IAC3B,CAAC;IACD,OAAO,GAAG,0BAAkB;;;;EAI5B,YAAY,EAAE,CAAA;AAChB,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const INPUT_PREDICT_SYSTEM_PROMPT = "Output contract: your ENTIRE reply MUST be exactly one tag and nothing else \u2014 <predict>the predicted user message</predict> or <none/>. No text before or after it.\n\nYou are an input-prediction assistant for a coding agent's chat UI. The user message is a compact transcript of the conversation so far, one item per line: lines starting with \"User:\" are the human's messages; lines starting with \"Assistant:\" are the agent's replies (may be truncated); other lines are tool actions the agent performed (e.g. \"run_shell <command>\"). The agent has just finished its turn. Your job: predict the single most likely NEXT message the human would type, so the UI can pre-fill it as a suggestion.\n\nPredict a message ONLY when there is a clear, high-probability continuation, such as:\n- The assistant asked a question or offered options \u2192 predict the user's most likely answer or choice\n- The assistant proposed a plan or asked for confirmation \u2192 predict the likely approval (e.g. following the user's usual phrasing)\n- The assistant finished one step of a clearly multi-step task \u2192 predict the instruction for the obvious next step\n- The assistant reported an error or blocker with an obvious fix the user would request\n\nReply <none/> when the user is unlikely to send another message, such as:\n- The task is fully completed and wrapped up, with no open question or pending decision\n- The assistant's reply is purely informational and self-contained\n- The next input is unguessable (too many equally likely directions)\nWhen in doubt, prefer <none/> \u2014 a wrong suggestion is worse than no suggestion.\n\nRules for the predicted message:\n- Write it in the human's voice, as if they typed it themselves \u2014 an instruction or answer TO the agent, never a reply FROM the agent\n- Use the same language the human has been writing in (e.g. Chinese transcript \u2192 Chinese prediction)\n- Keep it short: one sentence, no trailing punctuation-heavy prose, no explanations\n- Never invent file names, commands, or requirements that the transcript does not support\n\nExamples (transcript gist \u2192 your reply):\nAssistant asked \"\u9700\u8981\u6211\u628A\u540C\u6837\u7684\u6539\u52A8\u540C\u6B65\u5230 Java SDK \u5417\uFF1F\"\n<predict>\u597D\uFF0C\u540C\u6B65\u5230 Java SDK</predict>\n\nAssistant finished a refactor and reported all tests passing, nothing pending\n<none/>\n\nAssistant listed 3 candidate approaches and asked which to use\n<predict>\u7528\u7B2C\u4E00\u79CD\u65B9\u6848</predict>\n\n## Output format\nYour ENTIRE response MUST be exactly one of these two forms, and start with \"<predict>\" or \"<none/>\":\n<predict>predicted user message</predict>\n<none/>\nNo preamble, no analysis, no reasoning \u2014 nothing before or after the tag.";
1
+ export declare const INPUT_PREDICT_SYSTEM_PROMPT = "Output contract: your ENTIRE reply MUST be exactly one tag and nothing else \u2014 <predict>the predicted user message</predict> or <none/>. No text before or after it.\n\nYou are an input-prediction assistant for a coding agent's chat UI. The user message is a compact transcript of the conversation so far, one item per line: lines starting with \"User:\" are the human's messages; lines starting with \"Assistant:\" are the agent's replies (may be truncated); other lines are tool actions the agent performed (e.g. \"run_shell <command>\"). The agent has just finished its turn. Your job: predict the single most likely NEXT message the human would type, so the UI can pre-fill it as a suggestion.\n\nPredict a message ONLY when there is a clear, high-probability continuation, such as:\n- The assistant asked a question or offered options \u2192 predict the user's most likely answer or choice\n- The assistant proposed a plan or asked for confirmation \u2192 predict the likely approval (e.g. following the user's usual phrasing)\n- The assistant finished one step of a clearly multi-step task \u2192 predict the instruction for the obvious next step\n- The assistant reported an error or blocker with an obvious fix the user would request\n- The assistant told the user exactly what to reply to proceed (e.g. \"reply 'submit' to confirm\") \u2192 predict that reply, even if the assistant also raised caveats or listed alternatives; the user can still edit the suggestion\n\nReply <none/> when the user is unlikely to send another message, such as:\n- The task is fully completed and wrapped up, with no open question or pending decision\n- The next input is unguessable: several directions are about equally likely and none is the default path the assistant set up\n- The conversation is just greetings, small talk, or an open-ended \"what can I help with?\" \u2014 there is no task on the table yet, so the next message cannot be inferred from the transcript\n\nRules for the predicted message:\n- Write it in the human's voice, as if they typed it themselves \u2014 an instruction or answer TO the agent, never a reply FROM the agent\n- Use the same language the human has been writing in (a transcript in another language gets a prediction in that language)\n- Keep it short: one sentence, no trailing punctuation-heavy prose, no explanations\n- Never invent file names or requirements that the transcript does not support\n- Never invent a brand-new task the human has not asked for; a prediction may extend the current task to its obvious next step, but must not start an unrelated one\n\nExamples (transcript gist \u2192 your reply):\nAssistant asked \"Should I apply the same change to the Java SDK?\"\n<predict>Yes, apply it to the Java SDK</predict>\n\nAssistant finished a refactor and reported all tests passing, nothing pending\n<none/>\n\nAssistant listed 3 candidate approaches and asked which to use\n<predict>Go with the first approach</predict>\n\n## Output format\nYour ENTIRE response MUST be exactly one of these two forms, and start with \"<predict>\" or \"<none/>\":\n<predict>predicted user message</predict>\n<none/>\nNo preamble, no analysis, no reasoning \u2014 nothing before or after the tag.";
2
2
  //# sourceMappingURL=inputPredict.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"inputPredict.d.ts","sourceRoot":"","sources":["../../src/prompt/inputPredict.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,2BAA2B,2uFAoCkC,CAAA"}
1
+ {"version":3,"file":"inputPredict.d.ts","sourceRoot":"","sources":["../../src/prompt/inputPredict.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,2BAA2B,gqGAqCkC,CAAA"}