@ftai/dsh-plugin-acn 0.0.0-stage → 0.1.0

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 (272) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +19 -0
  4. package/README.md +55 -2
  5. package/README_EN.md +56 -0
  6. package/cordis.patch.yml +29 -0
  7. package/docs/acn-compat.md +33 -0
  8. package/docs/architecture.md +129 -0
  9. package/docs/assets/activity-view.png +0 -0
  10. package/docs/assets/install-package.png +0 -0
  11. package/docs/assets/knowledge-model.png +0 -0
  12. package/docs/assets/knowledge-view.png +0 -0
  13. package/docs/assets/personal-configuration.png +0 -0
  14. package/docs/assets/session-upstream.png +0 -0
  15. package/docs/assets/upstream-settings.png +0 -0
  16. package/docs/assets/upstream-team.png +0 -0
  17. package/docs/command-reference.md +201 -0
  18. package/docs/config.md +243 -0
  19. package/docs/development.md +197 -0
  20. package/docs/dsh-compat.md +59 -0
  21. package/docs/index.md +16 -0
  22. package/docs/outstanding-issues.md +61 -0
  23. package/docs/user_guide.md +183 -0
  24. package/icon.svg +8 -0
  25. package/lib/activities-LRoCwpzw.js +327 -0
  26. package/lib/alignment-CwH0nBf-.js +80 -0
  27. package/lib/auth-DFI9yowX.js +71 -0
  28. package/lib/checkpoint-Bmt8q2vB.js +188 -0
  29. package/lib/checkpoint-RgcdqifN.js +318 -0
  30. package/lib/claim-DOAGe8ZK.js +168 -0
  31. package/lib/client.js +18420 -0
  32. package/lib/deliver-BuYQaPRW.js +168 -0
  33. package/lib/delivery-status-D5m3178s.js +87 -0
  34. package/lib/dispute-CtrInHzf.js +20 -0
  35. package/lib/disputes-ByEmi43j.js +51 -0
  36. package/lib/dream-agent-DBszTHXY.js +249 -0
  37. package/lib/dream.js +4 -0
  38. package/lib/effects-DJ4Xa7Tx.js +268 -0
  39. package/lib/errors-Bp_2WXBr.js +19 -0
  40. package/lib/errors-pPumDOGD.js +18 -0
  41. package/lib/evidence-store-DLFvSuNa.js +1030 -0
  42. package/lib/formation-D4LO31WW.js +187 -0
  43. package/lib/formation-replay-CEOy5FkI.js +87 -0
  44. package/lib/formation.js +9 -0
  45. package/lib/inbox-2CugZZQm.js +188 -0
  46. package/lib/inbox-DFtE2fOp.js +71 -0
  47. package/lib/inbox.js +3 -0
  48. package/lib/index.js +1377 -0
  49. package/lib/lock-DbmlKOoX.js +332 -0
  50. package/lib/pages-BEWC3kmZ.js +51 -0
  51. package/lib/paths-CDYV5UH9.js +154 -0
  52. package/lib/plugins/commands.js +590 -0
  53. package/lib/plugins/dream.js +66 -0
  54. package/lib/plugins/formation.js +66 -0
  55. package/lib/plugins/inbox.js +53 -0
  56. package/lib/plugins/knowledge.js +1111 -0
  57. package/lib/plugins/prompt.js +102 -0
  58. package/lib/plugins/tools.js +280 -0
  59. package/lib/policy-DnyHh7Bl.js +16 -0
  60. package/lib/prepare-DwHZudbA.js +134 -0
  61. package/lib/presentation-BlLjgDjP.js +47 -0
  62. package/lib/protocol.js +8 -0
  63. package/lib/queue-M917xHPS.js +153 -0
  64. package/lib/regular-file-BFpqMoub.js +136 -0
  65. package/lib/render-CJaVcKKC.js +48 -0
  66. package/lib/reported-sets-DdEKdeVb.js +122 -0
  67. package/lib/revision-DeoL_IUN.js +11 -0
  68. package/lib/scheduler-MaUEbXr3.js +64 -0
  69. package/lib/service-B7AI5jds.js +344 -0
  70. package/lib/service-BcHV5mc7.js +305 -0
  71. package/lib/service-CNjqHCBR.js +505 -0
  72. package/lib/service-C_i3BzdP.js +1106 -0
  73. package/lib/session-binding-BQrOGhZI.js +151 -0
  74. package/lib/session-state-CYqUhC95.js +38 -0
  75. package/lib/sessions-C2xuPFQv.js +218 -0
  76. package/lib/store.js +16 -0
  77. package/lib/structured-lyQCK-Zk.js +452 -0
  78. package/lib/subagent-yJsFxHmH.js +9 -0
  79. package/lib/team-credentials-C9xHrPIi.js +579 -0
  80. package/lib/team.js +3 -0
  81. package/lib/tool-schema-3b4gH1zf.js +28 -0
  82. package/lib/trace-Da0RnL5R.js +14 -0
  83. package/lib/traces-CHBo8y1z.js +11 -0
  84. package/lib/types/activities.d.ts +71 -0
  85. package/lib/types/advanced-configuration.d.ts +11 -0
  86. package/lib/types/client/ActivityDetails.d.ts +18 -0
  87. package/lib/types/client/AdvancedPreferences.d.ts +8 -0
  88. package/lib/types/client/BlankCommandFeedback.d.ts +10 -0
  89. package/lib/types/client/ComposerMenu.d.ts +24 -0
  90. package/lib/types/client/ConfigurationPage.d.ts +11 -0
  91. package/lib/types/client/ConnectionCheckDialog.d.ts +12 -0
  92. package/lib/types/client/KnowledgeDetail.d.ts +6 -0
  93. package/lib/types/client/KnowledgeDirectoryField.d.ts +11 -0
  94. package/lib/types/client/KnowledgePanel.d.ts +12 -0
  95. package/lib/types/client/KnowledgeReference.d.ts +13 -0
  96. package/lib/types/client/SessionToolbar.d.ts +16 -0
  97. package/lib/types/client/SettingsToast.d.ts +3 -0
  98. package/lib/types/client/SourceSessionLink.d.ts +15 -0
  99. package/lib/types/client/TeamCredentialField.d.ts +16 -0
  100. package/lib/types/client/TeamSettingsPage.d.ts +30 -0
  101. package/lib/types/client/configuration-errors.d.ts +2 -0
  102. package/lib/types/client/interaction-styles.d.ts +1 -0
  103. package/lib/types/client/interaction-ui.d.ts +30 -0
  104. package/lib/types/client/knowledge-labels.d.ts +5 -0
  105. package/lib/types/client/locales.d.ts +51 -0
  106. package/lib/types/commands/claim.d.ts +4 -0
  107. package/lib/types/commands/import.d.ts +10 -0
  108. package/lib/types/commands/status.d.ts +5 -0
  109. package/lib/types/config.d.ts +122 -0
  110. package/lib/types/configuration.d.ts +259 -0
  111. package/lib/types/credentials.d.ts +65 -0
  112. package/lib/types/dream/audit.d.ts +4 -0
  113. package/lib/types/dream/autonomous.d.ts +185 -0
  114. package/lib/types/dream/candidates.d.ts +34 -0
  115. package/lib/types/dream/checkpoint.d.ts +35 -0
  116. package/lib/types/dream/evidence-files.d.ts +10 -0
  117. package/lib/types/dream/evidence-store.d.ts +103 -0
  118. package/lib/types/dream/evidence.d.ts +30 -0
  119. package/lib/types/dream/index.d.ts +10 -0
  120. package/lib/types/dream/plan.d.ts +18 -0
  121. package/lib/types/dream/preservation.d.ts +6 -0
  122. package/lib/types/dream/review.d.ts +10 -0
  123. package/lib/types/dream/schema.d.ts +1475 -0
  124. package/lib/types/dream/service.d.ts +56 -0
  125. package/lib/types/dream/sync.d.ts +147 -0
  126. package/lib/types/dsh-adapter/configuration-remote.d.ts +1 -0
  127. package/lib/types/dsh-adapter/configuration-service.d.ts +28 -0
  128. package/lib/types/dsh-adapter/dream-agent.d.ts +4 -0
  129. package/lib/types/dsh-adapter/dream-evidence.d.ts +3 -0
  130. package/lib/types/dsh-adapter/formation-archive.d.ts +3 -0
  131. package/lib/types/dsh-adapter/formation-replay.d.ts +5 -0
  132. package/lib/types/dsh-adapter/formation.d.ts +4 -0
  133. package/lib/types/dsh-adapter/interaction-service.d.ts +13 -0
  134. package/lib/types/dsh-adapter/knowledge-paths.d.ts +3 -0
  135. package/lib/types/dsh-adapter/llm.d.ts +10 -0
  136. package/lib/types/dsh-adapter/project-upstream.d.ts +4 -0
  137. package/lib/types/dsh-adapter/runtime-pool.d.ts +110 -0
  138. package/lib/types/dsh-adapter/session-binding.d.ts +43 -0
  139. package/lib/types/dsh-adapter/source-sessions.d.ts +3 -0
  140. package/lib/types/dsh-adapter/team-credentials.d.ts +5 -0
  141. package/lib/types/dsh-adapter/tool-schema.d.ts +4 -0
  142. package/lib/types/dsh-adapter/tools.d.ts +5 -0
  143. package/lib/types/formation/capture.d.ts +19 -0
  144. package/lib/types/formation/checkpoint.d.ts +136 -0
  145. package/lib/types/formation/index.d.ts +10 -0
  146. package/lib/types/formation/prepare.d.ts +16 -0
  147. package/lib/types/formation/schema.d.ts +45 -0
  148. package/lib/types/formation/service.d.ts +58 -0
  149. package/lib/types/formation/transcript.d.ts +75 -0
  150. package/lib/types/formation/triggers.d.ts +3 -0
  151. package/lib/types/inbox/cascade.d.ts +3 -0
  152. package/lib/types/inbox/effects.d.ts +275 -0
  153. package/lib/types/inbox/index.d.ts +5 -0
  154. package/lib/types/inbox/prepare.d.ts +380 -0
  155. package/lib/types/inbox/service.d.ts +26 -0
  156. package/lib/types/inbox/sync.d.ts +9 -0
  157. package/lib/types/index.d.ts +1 -0
  158. package/lib/types/interaction-messages.d.ts +69 -0
  159. package/lib/types/interaction.d.ts +550 -0
  160. package/lib/types/knowledge/alignment.d.ts +49 -0
  161. package/lib/types/knowledge/catalog.d.ts +5 -0
  162. package/lib/types/knowledge/changes.d.ts +32 -0
  163. package/lib/types/knowledge/disputes.d.ts +3 -0
  164. package/lib/types/knowledge/errors.d.ts +9 -0
  165. package/lib/types/knowledge/ordering.d.ts +7 -0
  166. package/lib/types/knowledge/pages.d.ts +7 -0
  167. package/lib/types/knowledge/safety.d.ts +2 -0
  168. package/lib/types/knowledge/service.d.ts +52 -0
  169. package/lib/types/knowledge/sessions.d.ts +59 -0
  170. package/lib/types/knowledge/sources.d.ts +2 -0
  171. package/lib/types/knowledge/timestamps.d.ts +1 -0
  172. package/lib/types/knowledge/types.d.ts +84 -0
  173. package/lib/types/llm/response.d.ts +1 -0
  174. package/lib/types/llm/structured.d.ts +27 -0
  175. package/lib/types/local-name.d.ts +1 -0
  176. package/lib/types/plugins/client.d.ts +9 -0
  177. package/lib/types/plugins/commands.d.ts +11 -0
  178. package/lib/types/plugins/configuration.d.ts +8 -0
  179. package/lib/types/plugins/dream.d.ts +16 -0
  180. package/lib/types/plugins/formation.d.ts +16 -0
  181. package/lib/types/plugins/inbox.d.ts +16 -0
  182. package/lib/types/plugins/knowledge.d.ts +19 -0
  183. package/lib/types/plugins/prompt.d.ts +17 -0
  184. package/lib/types/plugins/tools.d.ts +10 -0
  185. package/lib/types/prompt/render.d.ts +2 -0
  186. package/lib/types/protocol/arbitration.d.ts +154 -0
  187. package/lib/types/protocol/auth.d.ts +31 -0
  188. package/lib/types/protocol/claim.d.ts +36 -0
  189. package/lib/types/protocol/dispute.d.ts +17 -0
  190. package/lib/types/protocol/ids.d.ts +20 -0
  191. package/lib/types/protocol/inbox.d.ts +141 -0
  192. package/lib/types/protocol/index.d.ts +11 -0
  193. package/lib/types/protocol/policy.d.ts +21 -0
  194. package/lib/types/protocol/revision.d.ts +2 -0
  195. package/lib/types/protocol/router.d.ts +114 -0
  196. package/lib/types/protocol/schema.d.ts +4 -0
  197. package/lib/types/protocol/time.d.ts +5 -0
  198. package/lib/types/protocol/trace.d.ts +11 -0
  199. package/lib/types/store/atomic.d.ts +8 -0
  200. package/lib/types/store/claim-edits.d.ts +33 -0
  201. package/lib/types/store/claims.d.ts +7 -0
  202. package/lib/types/store/context.d.ts +13 -0
  203. package/lib/types/store/delivery-status.d.ts +47 -0
  204. package/lib/types/store/disputes.d.ts +6 -0
  205. package/lib/types/store/entities.d.ts +16 -0
  206. package/lib/types/store/errors.d.ts +8 -0
  207. package/lib/types/store/inbox.d.ts +27 -0
  208. package/lib/types/store/index.d.ts +16 -0
  209. package/lib/types/store/jobs.d.ts +5 -0
  210. package/lib/types/store/lock.d.ts +11 -0
  211. package/lib/types/store/path-names.d.ts +2 -0
  212. package/lib/types/store/paths.d.ts +45 -0
  213. package/lib/types/store/presentation.d.ts +13 -0
  214. package/lib/types/store/regular-file.d.ts +2 -0
  215. package/lib/types/store/rejected-disputes.d.ts +18 -0
  216. package/lib/types/store/rename.d.ts +1 -0
  217. package/lib/types/store/reported-sets.d.ts +24 -0
  218. package/lib/types/store/session-state.d.ts +17 -0
  219. package/lib/types/store/traces.d.ts +6 -0
  220. package/lib/types/store/uploads.d.ts +312 -0
  221. package/lib/types/store/yaml.d.ts +8 -0
  222. package/lib/types/team/errors.d.ts +10 -0
  223. package/lib/types/team/http.d.ts +20 -0
  224. package/lib/types/team/index.d.ts +5 -0
  225. package/lib/types/team/maintainer-client.d.ts +18 -0
  226. package/lib/types/team/router-client.d.ts +14 -0
  227. package/lib/types/team/service.d.ts +28 -0
  228. package/lib/types/team/system-proxy.d.ts +9 -0
  229. package/lib/types/tools/claim.d.ts +63 -0
  230. package/lib/types/tools/consult-router.d.ts +11 -0
  231. package/lib/types/tools/subagent.d.ts +8 -0
  232. package/lib/types/tools/validation.d.ts +2 -0
  233. package/lib/types/upload/consolidation.d.ts +63 -0
  234. package/lib/types/upload/deliver.d.ts +15 -0
  235. package/lib/types/upload/index.d.ts +2 -0
  236. package/lib/types/upload/scheduler.d.ts +19 -0
  237. package/lib/types/upstreams.d.ts +5 -0
  238. package/lib/types/worker/queue.d.ts +17 -0
  239. package/lib/types/worker/types.d.ts +51 -0
  240. package/lib/types/worker/worker.d.ts +39 -0
  241. package/lib/types-C2ST2Zdg.js +17 -0
  242. package/lib/upload.js +3 -0
  243. package/lib/uploads-BCA2p92b.js +210 -0
  244. package/lib/worker-BBTYP2RE.js +185 -0
  245. package/locale/commands/en.json +1 -0
  246. package/locale/commands/zh.json +1 -0
  247. package/locale/dream/en.json +1 -0
  248. package/locale/dream/zh.json +1 -0
  249. package/locale/en.json +7 -0
  250. package/locale/formation/en.json +1 -0
  251. package/locale/formation/zh.json +1 -0
  252. package/locale/inbox/en.json +1 -0
  253. package/locale/inbox/zh.json +1 -0
  254. package/locale/knowledge/en.json +1 -0
  255. package/locale/knowledge/zh.json +1 -0
  256. package/locale/prompt/en.json +1 -0
  257. package/locale/prompt/zh.json +1 -0
  258. package/locale/tools/en.json +1 -0
  259. package/locale/tools/zh.json +1 -0
  260. package/locale/zh.json +7 -0
  261. package/package.json +262 -3
  262. package/prompts/claim_dream.j2 +77 -0
  263. package/prompts/claim_dream_legacy.j2 +63 -0
  264. package/prompts/dream_compaction.j2 +11 -0
  265. package/prompts/dream_evidence.j2 +5 -0
  266. package/prompts/inbox_claim_attribute_update_internalize.j2 +112 -0
  267. package/prompts/inbox_policy_update_internalize.j2 +87 -0
  268. package/prompts/knowledge.j2 +38 -0
  269. package/prompts/session_recap.j2 +113 -0
  270. package/prompts/what_is_claim.j2 +51 -0
  271. package/prompts/what_is_dispute.j2 +21 -0
  272. package/prompts/what_is_policy.j2 +22 -0
@@ -0,0 +1,505 @@
1
+ import { c as TranscriptStore, d as RecapOutputSchema, l as processedThrough, o as RouteSchema, r as structuredCall } from "./structured-lyQCK-Zk.js";
2
+ import { C as StoreError, _ as JobError, b as Preempted, l as writeYamlAtomic, n as withFileLock } from "./lock-DbmlKOoX.js";
3
+ import { n as recapClaimIds, t as prepareFormation } from "./prepare-DwHZudbA.js";
4
+ import { n as FormationStore } from "./checkpoint-Bmt8q2vB.js";
5
+ import { t as DurableWorker } from "./worker-BBTYP2RE.js";
6
+ import { setTimeout as setTimeout$1 } from "node:timers/promises";
7
+ //#region src/formation/triggers.ts
8
+ function idleTrigger(config, state, entries, now) {
9
+ if (!config.idleRecap || state.autoPaused || state.archiveIntent !== null || state.activityAt === 0) return;
10
+ const cursor = processedThrough(state);
11
+ const pending = entries.filter((entry) => entry.seq > cursor);
12
+ if (!pending.some((entry) => entry.text.trim() !== "")) return;
13
+ const elapsed = now - state.activityAt;
14
+ const turns = state.completedTurns.filter((end) => end > cursor).length;
15
+ const tokens = Math.ceil(pending.reduce((bytes, entry) => bytes + Buffer.byteLength(entry.text, "utf8"), 0) / 4);
16
+ if ((turns >= config.recapMinTurns || tokens >= config.recapMinTokens) && elapsed >= config.recapBatchIdleMinutes * 6e4) return "batch-idle";
17
+ if (elapsed >= config.recapTailIdleMinutes * 6e4) return "tail-idle";
18
+ }
19
+ //#endregion
20
+ //#region src/formation/capture.ts
21
+ var ProjectionFailure = class extends JobError {
22
+ code;
23
+ constructor(kind, message, code) {
24
+ super(kind, message);
25
+ this.code = code;
26
+ }
27
+ };
28
+ const ioCodes = [
29
+ "EPERM",
30
+ "EACCES",
31
+ "EBUSY",
32
+ "EAGAIN",
33
+ "EMFILE",
34
+ "ENFILE",
35
+ "ENOSPC",
36
+ "EDQUOT",
37
+ "EIO",
38
+ "ENOENT"
39
+ ];
40
+ function formationFault(error) {
41
+ let current = error;
42
+ for (let depth = 0; depth < 8 && typeof current === "object" && current !== null; depth += 1) {
43
+ if (current instanceof ProjectionFailure) return current.code;
44
+ const code = "code" in current ? current.code : void 0;
45
+ if (ioCodes.some((value) => value === code)) return String(code);
46
+ if (current instanceof JobError && [
47
+ "transcript",
48
+ "transcript_limit",
49
+ "transcript_source"
50
+ ].includes(current.kind)) return current.kind;
51
+ if (current instanceof StoreError && current.kind !== "io") return current.kind;
52
+ current = "cause" in current ? current.cause : void 0;
53
+ }
54
+ return "unknown";
55
+ }
56
+ async function retryFormation(action) {
57
+ for (let attempt = 0;; attempt += 1) try {
58
+ return await action();
59
+ } catch (error) {
60
+ if (attempt >= 2 || ![
61
+ "EPERM",
62
+ "EACCES",
63
+ "EBUSY",
64
+ "EAGAIN",
65
+ "EMFILE",
66
+ "ENFILE",
67
+ "lock_timeout"
68
+ ].includes(formationFault(error))) throw error;
69
+ await setTimeout$1(50 * (attempt + 1));
70
+ }
71
+ }
72
+ function projectionError(error, stage, seq) {
73
+ const code = formationFault(error);
74
+ const kind = code === "transcript_limit" ? "transcript_limit" : ["ENOSPC", "EDQUOT"].includes(code) ? "transcript_space" : [
75
+ "EPERM",
76
+ "EACCES",
77
+ "EBUSY",
78
+ "EAGAIN",
79
+ "EMFILE",
80
+ "ENFILE",
81
+ "lock_timeout"
82
+ ].includes(code) ? "transcript_occupied" : [
83
+ "transcript",
84
+ "decode",
85
+ "conflict"
86
+ ].includes(code) ? "transcript_corrupt" : code === "transcript_source" ? "transcript_source" : "transcript_io";
87
+ const hint = kind === "transcript_limit" ? "单条投影超过容量限制,无法自动跳过;请保留原会话并联系维护者处理。" : kind === "transcript_space" ? "存储空间或配额不足;请释放空间后重试。" : kind === "transcript_occupied" ? "文件暂不可写或锁等待超时,有限重试仍未恢复;请检查文件占用和目录权限后重试。" : kind === "transcript_corrupt" ? "本地投影存在损坏或冲突,未跳过缺失内容;请保留数据并联系维护者。" : kind === "transcript_source" ? "无法读取原会话日志来补齐投影;请恢复原会话及其工作配置后重试。" : "本地会话投影读写失败;请检查本地存储状态后重试。";
88
+ return new ProjectionFailure(kind, `复盘输入尚未完整准备(${stage}${seq === void 0 ? "" : `,seq=${seq}`},${code})。${hint} 修复后在活动页重试原任务,或再次复盘;本次未调用知识模型。`, code);
89
+ }
90
+ var FormationCapture = class {
91
+ transcript;
92
+ replay;
93
+ buffers = /* @__PURE__ */ new Map();
94
+ blocked = /* @__PURE__ */ new Map();
95
+ restored = /* @__PURE__ */ new Set();
96
+ constructor(transcript, replay) {
97
+ this.transcript = transcript;
98
+ this.replay = replay;
99
+ }
100
+ add(id, projection) {
101
+ const rows = this.buffers.get(id) ?? [];
102
+ rows.push(projection);
103
+ this.buffers.set(id, rows);
104
+ }
105
+ async drain(id, retry = false) {
106
+ const failure = this.blocked.get(id);
107
+ if (!retry && failure !== void 0) throw failure;
108
+ const rows = this.buffers.get(id);
109
+ while (rows !== void 0 && rows.length > 0) {
110
+ const projection = rows[0];
111
+ if (projection === void 0) break;
112
+ try {
113
+ await retryFormation(() => this.transcript.record(id, projection));
114
+ } catch (error) {
115
+ const failure = projectionError(error, "projection", projection.entry?.seq ?? projection.activity?.seq);
116
+ this.blocked.set(id, failure);
117
+ throw failure;
118
+ }
119
+ rows.shift();
120
+ }
121
+ this.buffers.delete(id);
122
+ this.blocked.delete(id);
123
+ }
124
+ async prepare(id) {
125
+ await this.drain(id, true);
126
+ if (!this.restored.has(id) && this.replay !== void 0) try {
127
+ const projections = await retryFormation(() => this.replay?.(id) ?? Promise.resolve([]));
128
+ await retryFormation(() => this.transcript.replay(id, projections));
129
+ this.restored.add(id);
130
+ } catch (error) {
131
+ throw projectionError(error, "replay");
132
+ }
133
+ }
134
+ ids() {
135
+ return [...this.buffers.keys()];
136
+ }
137
+ };
138
+ //#endregion
139
+ //#region src/formation/service.ts
140
+ var AcnFormation = class {
141
+ knowledge;
142
+ backend;
143
+ render;
144
+ routeReady;
145
+ worker;
146
+ transcript;
147
+ pending = Promise.resolve();
148
+ captures;
149
+ compactions = /* @__PURE__ */ new Map();
150
+ archiveChecks = /* @__PURE__ */ new Map();
151
+ archiveView;
152
+ timers = /* @__PURE__ */ new Map();
153
+ attached = /* @__PURE__ */ new Set();
154
+ activeSessions = /* @__PURE__ */ new Set();
155
+ scanner;
156
+ started = false;
157
+ closing = false;
158
+ closeTask;
159
+ unregister;
160
+ ownsWorker;
161
+ constructor(knowledge, backend, render, workerOptions = {}, worker, routeReady, replay) {
162
+ this.knowledge = knowledge;
163
+ this.backend = backend;
164
+ this.render = render;
165
+ this.routeReady = routeReady;
166
+ this.worker = worker ?? new DurableWorker(knowledge.context(), workerOptions);
167
+ this.ownsWorker = worker === void 0;
168
+ this.transcript = new TranscriptStore(knowledge.context());
169
+ this.captures = new FormationCapture(this.transcript, replay);
170
+ this.unregister = [this.worker.register("recap", (job, control) => this.run(job, control)), this.worker.register("finalize", (job, control) => this.run(job, control))];
171
+ }
172
+ async start() {
173
+ await new FormationStore(this.knowledge.context()).recover();
174
+ for (const id of await this.transcript.sessions(true)) try {
175
+ await this.captures.prepare(id);
176
+ await this.transcript.record(id, {});
177
+ if ((await this.transcript.state(id)).archivePending) await this.finishArchive(id);
178
+ } catch (error) {
179
+ this.report("replay", id, error);
180
+ }
181
+ await this.worker.start();
182
+ this.started = true;
183
+ this.scanner = setInterval(() => {
184
+ this.schedule("scan", void 0, () => this.scanPending(Date.now()));
185
+ }, this.knowledge.config.formation.recapScanSeconds * 1e3);
186
+ this.scanner.unref();
187
+ await this.scanPending(Date.now());
188
+ }
189
+ attach(id) {
190
+ this.attached.add(id);
191
+ this.idle(id);
192
+ }
193
+ capture(id, projection, compactedUntil) {
194
+ if (this.closing) return;
195
+ this.schedule("projection", id, async () => {
196
+ this.captures.add(id, projection);
197
+ if (compactedUntil !== void 0 && this.knowledge.config.formation.recapOnCompaction) this.compactions.set(id, Math.max(this.compactions.get(id) ?? -1, compactedUntil));
198
+ await this.captures.drain(id);
199
+ if (projection.route !== void 0) {
200
+ const route = projection.route;
201
+ try {
202
+ await retryFormation(() => this.rememberRoute(route));
203
+ } catch (error) {
204
+ this.report("route", id, error);
205
+ }
206
+ }
207
+ await this.flushCompaction(id);
208
+ });
209
+ }
210
+ report(stage, id, error) {
211
+ this.knowledge.logger.warn(`Knowledge formation failed: stage=${stage} session=${id ?? "-"} code=${formationFault(error)}.`);
212
+ }
213
+ schedule(stage, id, action) {
214
+ this.pending = this.pending.then(action).then(() => void 0).catch((error) => {
215
+ this.report(stage, id, error);
216
+ });
217
+ }
218
+ async flushCompaction(id) {
219
+ const until = this.compactions.get(id);
220
+ if (until === void 0) return;
221
+ try {
222
+ await retryFormation(() => this.enqueueNew(id, "recap", "compaction", until));
223
+ this.compactions.delete(id);
224
+ } catch (error) {
225
+ this.report("enqueue", id, error);
226
+ throw new JobError("formation_enqueue", "复盘任务入队失败,投影已保留;请检查本地存储后再次复盘。");
227
+ }
228
+ }
229
+ async flush(id) {
230
+ const task = this.pending.then(async () => {
231
+ const ids = id === void 0 ? /* @__PURE__ */ new Set([
232
+ ...await this.transcript.sessions(true),
233
+ ...this.captures.ids(),
234
+ ...this.compactions.keys()
235
+ ]) : /* @__PURE__ */ new Set([id]);
236
+ let failure;
237
+ for (const current of ids) try {
238
+ await this.captures.prepare(current);
239
+ await this.flushCompaction(current);
240
+ } catch (error) {
241
+ failure ??= error instanceof Error ? error : new JobError("storage", "本地复盘准备失败,请检查存储后重试。");
242
+ }
243
+ if (failure !== void 0) throw failure;
244
+ });
245
+ this.pending = task.catch(() => {});
246
+ await task;
247
+ }
248
+ async rememberRoute(route) {
249
+ const context = this.knowledge.context();
250
+ await withFileLock(`${context.paths.lastRoute}.lock`, () => writeYamlAtomic(context.paths.lastRoute, route, RouteSchema, context.logger));
251
+ }
252
+ running(id) {
253
+ this.activeSessions.add(id);
254
+ const timer = this.timers.get(id);
255
+ if (timer !== void 0) clearTimeout(timer);
256
+ this.timers.delete(id);
257
+ }
258
+ idle(id) {
259
+ this.running(id);
260
+ this.activeSessions.delete(id);
261
+ if (!this.closing) this.schedule("scan", id, () => this.checkIdle(id, Date.now()));
262
+ const minutes = this.knowledge.config.formation.finalizeIdleMinutes;
263
+ if (this.closing || minutes === 0) return;
264
+ const deadline = Date.now() + minutes * 6e4;
265
+ const wait = () => {
266
+ const remaining = deadline - Date.now();
267
+ if (remaining > 0) {
268
+ const timer = setTimeout(wait, Math.min(remaining, 2147483647));
269
+ timer.unref();
270
+ this.timers.set(id, timer);
271
+ } else {
272
+ this.timers.delete(id);
273
+ this.schedule("enqueue", id, async () => {
274
+ await this.captures.prepare(id);
275
+ return this.enqueue(id, "finalize");
276
+ });
277
+ }
278
+ };
279
+ wait();
280
+ }
281
+ disposed(id) {
282
+ this.running(id);
283
+ this.attached.delete(id);
284
+ this.activeSessions.delete(id);
285
+ if (!this.closing && this.knowledge.config.formation.finalizeOnDispose) this.schedule("enqueue", id, async () => {
286
+ await this.captures.prepare(id);
287
+ return this.enqueue(id, "finalize");
288
+ });
289
+ }
290
+ async finalize(id) {
291
+ await this.flush(id);
292
+ return this.enqueue(id, "finalize");
293
+ }
294
+ async recap(id) {
295
+ await this.flush(id);
296
+ const state = await this.transcript.state(id);
297
+ const until = this.activeSessions.has(id) ? Math.max(processedThrough(state), ...state.completedTurns) : state.lastSeenSeq;
298
+ return this.enqueueNew(id, "recap", "manual", until);
299
+ }
300
+ async scan(now = Date.now()) {
301
+ await this.pending;
302
+ await this.scanPending(now);
303
+ }
304
+ async scanPending(now) {
305
+ if (this.closing) return;
306
+ await this.reconcilePendingArchives();
307
+ for (const id of /* @__PURE__ */ new Set([...await this.transcript.sessions(true), ...this.captures.ids()])) try {
308
+ await this.checkIdle(id, now);
309
+ } catch (error) {
310
+ this.report("scan", id, error);
311
+ }
312
+ }
313
+ async checkIdle(id, now) {
314
+ if (!this.started || this.closing || this.activeSessions.has(id)) return;
315
+ await this.captures.prepare(id);
316
+ await this.flushCompaction(id);
317
+ await this.finishArchive(id);
318
+ const state = await this.transcript.state(id);
319
+ const trigger = idleTrigger(this.knowledge.config.formation, state, await this.transcript.read(id), now);
320
+ if (trigger === void 0) return;
321
+ const config = this.knowledge.config.llm;
322
+ const route = config.provider && config.model ? {
323
+ provider: config.provider,
324
+ model: config.model
325
+ } : state.lastRoute;
326
+ if (route === void 0 || this.routeReady !== void 0 && !await this.routeReady(route)) return;
327
+ if (!this.activeSessions.has(id)) await this.enqueueNew(id, "recap", trigger);
328
+ }
329
+ async beginArchive(id, upper) {
330
+ await this.pending;
331
+ if (!this.attached.has(id) && !this.captures.ids().includes(id) && !(await this.transcript.sessions(true)).includes(id)) return null;
332
+ await this.flush(id);
333
+ return (await this.transcript.lifecycle(id, (current) => {
334
+ current.archiveIntent = current.autoPaused && current.archivedThroughSeq !== null ? current.archivedThroughSeq : Math.min(upper ?? current.lastSeenSeq, current.lastSeenSeq);
335
+ })).archiveIntent;
336
+ }
337
+ async cancelArchive(id) {
338
+ await this.transcript.lifecycle(id, (state) => {
339
+ state.archiveIntent = null;
340
+ });
341
+ }
342
+ async archived(id, upper) {
343
+ this.archiveChecks.set(id, true);
344
+ await this.recordArchive(id, upper);
345
+ await this.flush(id);
346
+ await this.finishArchive(id);
347
+ }
348
+ async recordArchive(id, upper) {
349
+ await this.transcript.lifecycle(id, (state) => {
350
+ if (!state.autoPaused) {
351
+ state.autoPaused = true;
352
+ state.archivedThroughSeq = upper;
353
+ state.archivePending = true;
354
+ }
355
+ state.archiveIntent = null;
356
+ });
357
+ this.archiveChecks.delete(id);
358
+ }
359
+ async reconcileArchives(archived) {
360
+ this.archiveView = new Set(archived);
361
+ await this.pending;
362
+ await this.reconcilePendingArchives();
363
+ if (this.started) await this.scanPending(Date.now());
364
+ }
365
+ async reconcilePendingArchives() {
366
+ if (this.archiveView !== void 0) try {
367
+ for (const id of await this.transcript.sessions(true)) this.archiveChecks.set(id, this.archiveView.has(id));
368
+ this.archiveView = void 0;
369
+ } catch (error) {
370
+ this.report("scan", void 0, error);
371
+ return;
372
+ }
373
+ for (const [id, archived] of this.archiveChecks) try {
374
+ const state = await this.transcript.state(id);
375
+ if (state.archiveIntent !== null) if (archived) await this.recordArchive(id, state.archiveIntent);
376
+ else await this.cancelArchive(id);
377
+ else if (archived && state.archivedThroughSeq === null) await this.recordArchive(id, state.lastSeenSeq);
378
+ this.archiveChecks.delete(id);
379
+ } catch (error) {
380
+ this.report("replay", id, error);
381
+ }
382
+ }
383
+ async finishArchive(id) {
384
+ const state = await this.transcript.state(id);
385
+ if (!state.archivePending || state.archivedThroughSeq === null) return;
386
+ await this.enqueueNew(id, "finalize", "archive", state.archivedThroughSeq);
387
+ await this.transcript.lifecycle(id, (current) => {
388
+ current.archivePending = false;
389
+ });
390
+ }
391
+ async enqueueNew(id, kind, trigger, requestedUntil) {
392
+ const state = await this.transcript.state(id);
393
+ if (state.archiveIntent !== null || state.autoPaused && trigger !== "archive" && trigger !== "manual") return null;
394
+ const untilSeq = Math.min(requestedUntil ?? state.lastSeenSeq, state.lastSeenSeq, state.autoPaused ? state.archivedThroughSeq ?? -1 : state.lastSeenSeq);
395
+ const cursor = processedThrough(state);
396
+ if (untilSeq <= cursor || !(await this.transcript.read(id)).some((entry) => entry.seq > cursor && entry.seq <= untilSeq && entry.text.trim() !== "")) return null;
397
+ const existing = (await this.worker.queue.list()).find((job) => job.sessionId === id && (job.kind === kind || kind === "recap" && job.kind === "finalize") && typeof job.payload["untilSeq"] === "number" && job.payload["untilSeq"] >= untilSeq && (job.state === "queued" || job.state === "running" || trigger.endsWith("-idle") && job.state === "failed"));
398
+ if (existing !== void 0) return existing;
399
+ return this.worker.enqueue(kind, {
400
+ untilSeq,
401
+ trigger
402
+ }, id);
403
+ }
404
+ async enqueue(id, kind, requestedUntil) {
405
+ const state = await this.transcript.state(id);
406
+ const untilSeq = Math.min(requestedUntil ?? state.lastSeenSeq, state.lastSeenSeq, state.archiveIntent ?? (state.autoPaused ? state.archivedThroughSeq ?? -1 : state.lastSeenSeq));
407
+ return this.worker.enqueue(kind, { untilSeq }, id);
408
+ }
409
+ async run(job, control) {
410
+ const id = job.sessionId;
411
+ const until = job.payload["untilSeq"];
412
+ if (id === void 0 || typeof until !== "number" || !Number.isSafeInteger(until)) throw new JobError("validation", "形成任务缺少合法会话或区间。");
413
+ await this.flush(id);
414
+ await new FormationStore(this.knowledge.context()).recover();
415
+ const state = await this.transcript.state(id);
416
+ const fromSeq = processedThrough(state);
417
+ const untilSeq = Math.min(until, state.lastSeenSeq, state.archiveIntent ?? (state.autoPaused ? state.archivedThroughSeq ?? -1 : state.lastSeenSeq));
418
+ if (untilSeq <= fromSeq) {
419
+ if (job.kind === "finalize" && untilSeq >= 0) await this.transcript.advance(id, "finalize", untilSeq);
420
+ return { skipped: "already_processed" };
421
+ }
422
+ const entries = (await this.transcript.read(id)).filter((entry) => entry.seq > fromSeq && entry.seq <= untilSeq);
423
+ if (entries.length === 0) throw new JobError("transcript", "待处理区间的会话投影缺失;已保留任务,请检查本地 transcript 后重试。");
424
+ const analysisClaims = (await this.knowledge.snapshot()).claims;
425
+ const configured = this.knowledge.config.llm;
426
+ const route = configured.provider && configured.model ? {
427
+ provider: configured.provider,
428
+ model: configured.model
429
+ } : state.lastRoute;
430
+ if (route === void 0) throw new JobError("route", "没有本会话的 request/header 路由。请先完成一次会话请求,或配置 llm.provider 和 llm.model,然后用 /acn-status retry 重试。");
431
+ const input = JSON.stringify({
432
+ instruction: "根据本段真实任务证据形成可复用知识;没有有价值的新增或更新时返回空数组。",
433
+ transcript_projection: {
434
+ complete_history: false,
435
+ from_seq_exclusive: fromSeq,
436
+ until_seq_inclusive: untilSeq,
437
+ excluded: [
438
+ "system_instructions",
439
+ "catalog_injection",
440
+ "compaction_replacement",
441
+ "reasoning",
442
+ "private_memory",
443
+ "run_code_wrapper"
444
+ ],
445
+ tool_results: "complete_public_results",
446
+ legacy_tool_result_completeness: "unknown"
447
+ },
448
+ transcript: entries.map((entry) => ({
449
+ role: entry.type,
450
+ content: entry.text,
451
+ ...entry.projection === void 0 ? {} : { projection: entry.projection }
452
+ })),
453
+ local_claims: analysisClaims.filter((claim) => claim.status !== "deprecated")
454
+ });
455
+ const prepared = await structuredCall({
456
+ backend: this.backend,
457
+ context: this.knowledge.context(),
458
+ config: configured,
459
+ route,
460
+ jobId: job.id,
461
+ system: this.render("session_recap.j2", {}),
462
+ input,
463
+ schema: RecapOutputSchema,
464
+ parse: (value) => prepareFormation(value, this.knowledge.context().agentId, analysisClaims, recapClaimIds(entries.map((entry) => entry.text))),
465
+ signal: control.signal
466
+ });
467
+ control.signal.throwIfAborted();
468
+ if (job.kind === "recap" && (await this.worker.queue.list()).some((candidate) => candidate.kind === "finalize" && candidate.sessionId === id && candidate.state === "queued")) throw new Preempted();
469
+ const task = entries.filter((entry) => entry.type === "user").map((entry) => entry.text).join("\n") || "本段会话知识复盘";
470
+ return this.knowledge.applyFormation({
471
+ sessionId: id,
472
+ jobId: job.id,
473
+ kind: job.kind === "recap" ? "recap" : "finalize",
474
+ fromSeq,
475
+ untilSeq,
476
+ analysisClaims,
477
+ prepared,
478
+ task
479
+ }, control);
480
+ }
481
+ close() {
482
+ this.closeTask ??= this.finishClose();
483
+ return this.closeTask;
484
+ }
485
+ async finishClose() {
486
+ this.closing = true;
487
+ if (this.scanner !== void 0) clearInterval(this.scanner);
488
+ for (const timer of this.timers.values()) clearTimeout(timer);
489
+ this.timers.clear();
490
+ try {
491
+ await this.pending;
492
+ if (this.knowledge.config.formation.finalizeOnDispose) for (const id of this.attached) try {
493
+ await this.captures.prepare(id);
494
+ await this.enqueue(id, "finalize");
495
+ } catch (error) {
496
+ this.report("enqueue", id, error);
497
+ }
498
+ } finally {
499
+ for (const unregister of this.unregister) unregister();
500
+ if (this.ownsWorker) await this.worker.close();
501
+ }
502
+ }
503
+ };
504
+ //#endregion
505
+ export { AcnFormation as t };