@ftai/dsh-plugin-acn 0.0.0-stage → 0.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 (276) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/LICENSE-APACHE +201 -0
  3. package/LICENSE-MIT +19 -0
  4. package/README.md +82 -2
  5. package/README_EN.md +83 -0
  6. package/cordis.patch.yml +29 -0
  7. package/docs/acn-compat.md +33 -0
  8. package/docs/architecture.md +130 -0
  9. package/docs/assets/acn-claim-reuse.png +0 -0
  10. package/docs/assets/activity-view.png +0 -0
  11. package/docs/assets/install-package.png +0 -0
  12. package/docs/assets/knowledge-model.png +0 -0
  13. package/docs/assets/knowledge-view.png +0 -0
  14. package/docs/assets/personal-configuration.png +0 -0
  15. package/docs/assets/session-upstream.png +0 -0
  16. package/docs/assets/upstream-settings.png +0 -0
  17. package/docs/assets/upstream-team.png +0 -0
  18. package/docs/command-reference.md +201 -0
  19. package/docs/config.md +253 -0
  20. package/docs/development.md +197 -0
  21. package/docs/dsh-compat.md +59 -0
  22. package/docs/index.md +16 -0
  23. package/docs/outstanding-issues.md +61 -0
  24. package/docs/user_guide.md +185 -0
  25. package/icon.svg +8 -0
  26. package/lib/activities-B8U-iW4-.js +407 -0
  27. package/lib/alignment-CwH0nBf-.js +80 -0
  28. package/lib/auth-DFI9yowX.js +71 -0
  29. package/lib/checkpoint-CPFPOxBM.js +188 -0
  30. package/lib/checkpoint-c7aI4D-X.js +318 -0
  31. package/lib/claim-DOAGe8ZK.js +168 -0
  32. package/lib/client.js +18417 -0
  33. package/lib/deliver-C-dmhkfm.js +168 -0
  34. package/lib/delivery-status-M7-Rwoyj.js +89 -0
  35. package/lib/dispute-CtrInHzf.js +20 -0
  36. package/lib/disputes-ByEmi43j.js +51 -0
  37. package/lib/dream-agent-BVqxbKFc.js +249 -0
  38. package/lib/dream.js +4 -0
  39. package/lib/effects-DX1iy6FM.js +268 -0
  40. package/lib/errors-Bp_2WXBr.js +19 -0
  41. package/lib/errors-pPumDOGD.js +18 -0
  42. package/lib/evidence-store-DW7kj20i.js +1030 -0
  43. package/lib/formation-D4LO31WW.js +187 -0
  44. package/lib/formation-replay-Bf4TSBiz.js +87 -0
  45. package/lib/formation.js +9 -0
  46. package/lib/history-DPMHX3ZE.js +214 -0
  47. package/lib/inbox-2CugZZQm.js +188 -0
  48. package/lib/inbox-DFtE2fOp.js +71 -0
  49. package/lib/inbox.js +3 -0
  50. package/lib/index.js +1373 -0
  51. package/lib/lock-DbmlKOoX.js +332 -0
  52. package/lib/pages-BEWC3kmZ.js +51 -0
  53. package/lib/paths-B7NI9Ano.js +157 -0
  54. package/lib/plugins/commands.js +590 -0
  55. package/lib/plugins/dream.js +66 -0
  56. package/lib/plugins/formation.js +66 -0
  57. package/lib/plugins/inbox.js +53 -0
  58. package/lib/plugins/knowledge.js +1109 -0
  59. package/lib/plugins/prompt.js +102 -0
  60. package/lib/plugins/tools.js +280 -0
  61. package/lib/policy-DnyHh7Bl.js +16 -0
  62. package/lib/prepare-CGXwBEcu.js +134 -0
  63. package/lib/protocol.js +8 -0
  64. package/lib/queue-M917xHPS.js +153 -0
  65. package/lib/regular-file-BFpqMoub.js +136 -0
  66. package/lib/render-CJaVcKKC.js +48 -0
  67. package/lib/reported-sets-DdEKdeVb.js +122 -0
  68. package/lib/revision-DeoL_IUN.js +11 -0
  69. package/lib/scheduler-BfJSY1eq.js +64 -0
  70. package/lib/service-BPwaZzFF.js +1106 -0
  71. package/lib/service-BQaszW_v.js +344 -0
  72. package/lib/service-BhniAHLo.js +305 -0
  73. package/lib/service-C2lXoygJ.js +505 -0
  74. package/lib/session-binding-zCSuizHs.js +342 -0
  75. package/lib/session-state-CYqUhC95.js +38 -0
  76. package/lib/sessions-C2xuPFQv.js +218 -0
  77. package/lib/store.js +16 -0
  78. package/lib/structured-C9byFuzm.js +453 -0
  79. package/lib/subagent-yJsFxHmH.js +9 -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 +73 -0
  85. package/lib/types/advanced-configuration.d.ts +11 -0
  86. package/lib/types/client/ActivityCard.d.ts +14 -0
  87. package/lib/types/client/ActivityDetails.d.ts +18 -0
  88. package/lib/types/client/AdvancedPreferences.d.ts +8 -0
  89. package/lib/types/client/BlankCommandFeedback.d.ts +10 -0
  90. package/lib/types/client/ComposerMenu.d.ts +24 -0
  91. package/lib/types/client/ConfigurationPage.d.ts +11 -0
  92. package/lib/types/client/ConnectionCheckDialog.d.ts +12 -0
  93. package/lib/types/client/KnowledgeDetail.d.ts +6 -0
  94. package/lib/types/client/KnowledgeDirectoryField.d.ts +11 -0
  95. package/lib/types/client/KnowledgePanel.d.ts +12 -0
  96. package/lib/types/client/KnowledgeReference.d.ts +13 -0
  97. package/lib/types/client/SessionToolbar.d.ts +16 -0
  98. package/lib/types/client/SettingsToast.d.ts +3 -0
  99. package/lib/types/client/SourceSessionLink.d.ts +16 -0
  100. package/lib/types/client/TeamCredentialField.d.ts +16 -0
  101. package/lib/types/client/TeamSettingsPage.d.ts +28 -0
  102. package/lib/types/client/configuration-errors.d.ts +2 -0
  103. package/lib/types/client/interaction-styles.d.ts +1 -0
  104. package/lib/types/client/interaction-ui.d.ts +30 -0
  105. package/lib/types/client/knowledge-labels.d.ts +5 -0
  106. package/lib/types/client/locales.d.ts +51 -0
  107. package/lib/types/commands/claim.d.ts +4 -0
  108. package/lib/types/commands/import.d.ts +10 -0
  109. package/lib/types/commands/status.d.ts +5 -0
  110. package/lib/types/config.d.ts +111 -0
  111. package/lib/types/configuration.d.ts +235 -0
  112. package/lib/types/credentials.d.ts +59 -0
  113. package/lib/types/dream/audit.d.ts +4 -0
  114. package/lib/types/dream/autonomous.d.ts +185 -0
  115. package/lib/types/dream/candidates.d.ts +34 -0
  116. package/lib/types/dream/checkpoint.d.ts +35 -0
  117. package/lib/types/dream/evidence-files.d.ts +10 -0
  118. package/lib/types/dream/evidence-store.d.ts +103 -0
  119. package/lib/types/dream/evidence.d.ts +30 -0
  120. package/lib/types/dream/index.d.ts +10 -0
  121. package/lib/types/dream/plan.d.ts +18 -0
  122. package/lib/types/dream/preservation.d.ts +6 -0
  123. package/lib/types/dream/review.d.ts +10 -0
  124. package/lib/types/dream/schema.d.ts +1475 -0
  125. package/lib/types/dream/service.d.ts +56 -0
  126. package/lib/types/dream/sync.d.ts +147 -0
  127. package/lib/types/dsh-adapter/configuration-remote.d.ts +1 -0
  128. package/lib/types/dsh-adapter/configuration-service.d.ts +28 -0
  129. package/lib/types/dsh-adapter/dream-agent.d.ts +4 -0
  130. package/lib/types/dsh-adapter/dream-evidence.d.ts +3 -0
  131. package/lib/types/dsh-adapter/formation-archive.d.ts +3 -0
  132. package/lib/types/dsh-adapter/formation-replay.d.ts +5 -0
  133. package/lib/types/dsh-adapter/formation.d.ts +4 -0
  134. package/lib/types/dsh-adapter/interaction-service.d.ts +13 -0
  135. package/lib/types/dsh-adapter/knowledge-paths.d.ts +3 -0
  136. package/lib/types/dsh-adapter/llm.d.ts +10 -0
  137. package/lib/types/dsh-adapter/project-upstream.d.ts +4 -0
  138. package/lib/types/dsh-adapter/runtime-pool.d.ts +110 -0
  139. package/lib/types/dsh-adapter/session-binding.d.ts +43 -0
  140. package/lib/types/dsh-adapter/source-sessions.d.ts +3 -0
  141. package/lib/types/dsh-adapter/team-credentials.d.ts +5 -0
  142. package/lib/types/dsh-adapter/tool-schema.d.ts +4 -0
  143. package/lib/types/dsh-adapter/tools.d.ts +5 -0
  144. package/lib/types/formation/capture.d.ts +19 -0
  145. package/lib/types/formation/checkpoint.d.ts +136 -0
  146. package/lib/types/formation/index.d.ts +10 -0
  147. package/lib/types/formation/prepare.d.ts +16 -0
  148. package/lib/types/formation/schema.d.ts +45 -0
  149. package/lib/types/formation/service.d.ts +58 -0
  150. package/lib/types/formation/transcript.d.ts +75 -0
  151. package/lib/types/formation/triggers.d.ts +3 -0
  152. package/lib/types/inbox/cascade.d.ts +3 -0
  153. package/lib/types/inbox/effects.d.ts +275 -0
  154. package/lib/types/inbox/index.d.ts +5 -0
  155. package/lib/types/inbox/prepare.d.ts +380 -0
  156. package/lib/types/inbox/service.d.ts +26 -0
  157. package/lib/types/inbox/sync.d.ts +9 -0
  158. package/lib/types/index.d.ts +1 -0
  159. package/lib/types/interaction-messages.d.ts +69 -0
  160. package/lib/types/interaction.d.ts +541 -0
  161. package/lib/types/knowledge/alignment.d.ts +49 -0
  162. package/lib/types/knowledge/catalog.d.ts +5 -0
  163. package/lib/types/knowledge/changes.d.ts +32 -0
  164. package/lib/types/knowledge/disputes.d.ts +3 -0
  165. package/lib/types/knowledge/errors.d.ts +9 -0
  166. package/lib/types/knowledge/ordering.d.ts +7 -0
  167. package/lib/types/knowledge/pages.d.ts +7 -0
  168. package/lib/types/knowledge/safety.d.ts +2 -0
  169. package/lib/types/knowledge/service.d.ts +52 -0
  170. package/lib/types/knowledge/sessions.d.ts +59 -0
  171. package/lib/types/knowledge/sources.d.ts +2 -0
  172. package/lib/types/knowledge/timestamps.d.ts +1 -0
  173. package/lib/types/knowledge/types.d.ts +84 -0
  174. package/lib/types/llm/response.d.ts +1 -0
  175. package/lib/types/llm/structured.d.ts +27 -0
  176. package/lib/types/local-name.d.ts +1 -0
  177. package/lib/types/plugins/client.d.ts +9 -0
  178. package/lib/types/plugins/commands.d.ts +11 -0
  179. package/lib/types/plugins/configuration.d.ts +8 -0
  180. package/lib/types/plugins/dream.d.ts +16 -0
  181. package/lib/types/plugins/formation.d.ts +16 -0
  182. package/lib/types/plugins/inbox.d.ts +16 -0
  183. package/lib/types/plugins/knowledge.d.ts +19 -0
  184. package/lib/types/plugins/prompt.d.ts +17 -0
  185. package/lib/types/plugins/tools.d.ts +10 -0
  186. package/lib/types/prompt/render.d.ts +2 -0
  187. package/lib/types/protocol/arbitration.d.ts +154 -0
  188. package/lib/types/protocol/auth.d.ts +31 -0
  189. package/lib/types/protocol/claim.d.ts +36 -0
  190. package/lib/types/protocol/dispute.d.ts +17 -0
  191. package/lib/types/protocol/ids.d.ts +20 -0
  192. package/lib/types/protocol/inbox.d.ts +141 -0
  193. package/lib/types/protocol/index.d.ts +11 -0
  194. package/lib/types/protocol/policy.d.ts +21 -0
  195. package/lib/types/protocol/revision.d.ts +2 -0
  196. package/lib/types/protocol/router.d.ts +114 -0
  197. package/lib/types/protocol/schema.d.ts +4 -0
  198. package/lib/types/protocol/time.d.ts +5 -0
  199. package/lib/types/protocol/trace.d.ts +11 -0
  200. package/lib/types/store/atomic.d.ts +8 -0
  201. package/lib/types/store/claim-edits.d.ts +33 -0
  202. package/lib/types/store/claims.d.ts +7 -0
  203. package/lib/types/store/context.d.ts +13 -0
  204. package/lib/types/store/delivery-status.d.ts +48 -0
  205. package/lib/types/store/disputes.d.ts +6 -0
  206. package/lib/types/store/entities.d.ts +16 -0
  207. package/lib/types/store/errors.d.ts +8 -0
  208. package/lib/types/store/history.d.ts +65 -0
  209. package/lib/types/store/inbox.d.ts +27 -0
  210. package/lib/types/store/index.d.ts +16 -0
  211. package/lib/types/store/jobs.d.ts +5 -0
  212. package/lib/types/store/library-directory.d.ts +4 -0
  213. package/lib/types/store/lock.d.ts +11 -0
  214. package/lib/types/store/path-names.d.ts +2 -0
  215. package/lib/types/store/paths.d.ts +45 -0
  216. package/lib/types/store/presentation.d.ts +13 -0
  217. package/lib/types/store/regular-file.d.ts +2 -0
  218. package/lib/types/store/rejected-disputes.d.ts +18 -0
  219. package/lib/types/store/rename.d.ts +1 -0
  220. package/lib/types/store/reported-sets.d.ts +24 -0
  221. package/lib/types/store/session-state.d.ts +17 -0
  222. package/lib/types/store/traces.d.ts +6 -0
  223. package/lib/types/store/uploads.d.ts +312 -0
  224. package/lib/types/store/yaml.d.ts +8 -0
  225. package/lib/types/team/errors.d.ts +10 -0
  226. package/lib/types/team/http.d.ts +20 -0
  227. package/lib/types/team/index.d.ts +5 -0
  228. package/lib/types/team/maintainer-client.d.ts +18 -0
  229. package/lib/types/team/router-client.d.ts +14 -0
  230. package/lib/types/team/service.d.ts +28 -0
  231. package/lib/types/team/system-proxy.d.ts +9 -0
  232. package/lib/types/tools/claim.d.ts +63 -0
  233. package/lib/types/tools/consult-router.d.ts +11 -0
  234. package/lib/types/tools/subagent.d.ts +8 -0
  235. package/lib/types/tools/validation.d.ts +2 -0
  236. package/lib/types/upload/consolidation.d.ts +63 -0
  237. package/lib/types/upload/deliver.d.ts +15 -0
  238. package/lib/types/upload/index.d.ts +2 -0
  239. package/lib/types/upload/scheduler.d.ts +19 -0
  240. package/lib/types/upstreams.d.ts +5 -0
  241. package/lib/types/worker/queue.d.ts +17 -0
  242. package/lib/types/worker/types.d.ts +51 -0
  243. package/lib/types/worker/worker.d.ts +39 -0
  244. package/lib/types-C2ST2Zdg.js +17 -0
  245. package/lib/upload.js +3 -0
  246. package/lib/uploads-BCA2p92b.js +210 -0
  247. package/lib/upstreams-DEi-56tD.js +495 -0
  248. package/lib/worker-HMGzJFWd.js +185 -0
  249. package/locale/commands/en.json +1 -0
  250. package/locale/commands/zh.json +1 -0
  251. package/locale/dream/en.json +1 -0
  252. package/locale/dream/zh.json +1 -0
  253. package/locale/en.json +7 -0
  254. package/locale/formation/en.json +1 -0
  255. package/locale/formation/zh.json +1 -0
  256. package/locale/inbox/en.json +1 -0
  257. package/locale/inbox/zh.json +1 -0
  258. package/locale/knowledge/en.json +1 -0
  259. package/locale/knowledge/zh.json +1 -0
  260. package/locale/prompt/en.json +1 -0
  261. package/locale/prompt/zh.json +1 -0
  262. package/locale/tools/en.json +1 -0
  263. package/locale/tools/zh.json +1 -0
  264. package/locale/zh.json +7 -0
  265. package/package.json +262 -3
  266. package/prompts/claim_dream.j2 +77 -0
  267. package/prompts/claim_dream_legacy.j2 +63 -0
  268. package/prompts/dream_compaction.j2 +11 -0
  269. package/prompts/dream_evidence.j2 +5 -0
  270. package/prompts/inbox_claim_attribute_update_internalize.j2 +112 -0
  271. package/prompts/inbox_policy_update_internalize.j2 +87 -0
  272. package/prompts/knowledge.j2 +38 -0
  273. package/prompts/session_recap.j2 +113 -0
  274. package/prompts/what_is_claim.j2 +51 -0
  275. package/prompts/what_is_dispute.j2 +21 -0
  276. package/prompts/what_is_policy.j2 +22 -0
@@ -0,0 +1,187 @@
1
+ import { t as ClaimSchema } from "./claim-DOAGe8ZK.js";
2
+ import { _ as JobError } from "./lock-DbmlKOoX.js";
3
+ import { t as PolicySchema } from "./policy-DnyHh7Bl.js";
4
+ import { z } from "zod";
5
+ import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
6
+ //#region src/llm/response.ts
7
+ function structuredResponseText(text) {
8
+ const trimmed = text.trim();
9
+ if (/^(?:\{|\[|```)/u.test(trimmed)) return text;
10
+ const end = trimmed.indexOf("</think>");
11
+ if (end < 0) return text;
12
+ const candidate = trimmed.slice(end + 8).trim().replace(/^```(?:json)?\s*\n?([\s\S]*?)\n?```$/iu, "$1");
13
+ try {
14
+ const value = JSON.parse(candidate);
15
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return candidate;
16
+ } catch {}
17
+ return text;
18
+ }
19
+ //#endregion
20
+ //#region src/dsh-adapter/llm.ts
21
+ function structuredBackend(ctx) {
22
+ return async (route, system, input, maxTokens, signal) => {
23
+ signal.throwIfAborted();
24
+ const call = await ctx.llm.prepareCall({
25
+ ...route,
26
+ maxTokens
27
+ }, signal);
28
+ const assembler = new BlockAssembler();
29
+ for await (const chunk of call.stream({
30
+ ...call.config,
31
+ messages: [createUserMessage({
32
+ content: [{
33
+ type: "text",
34
+ text: input
35
+ }],
36
+ source: { kind: "acn-formation" }
37
+ })],
38
+ system,
39
+ signal
40
+ })) {
41
+ signal.throwIfAborted();
42
+ assembler.push(chunk);
43
+ }
44
+ signal.throwIfAborted();
45
+ const finish = assembler.finish;
46
+ if (finish.kind === "error" || finish.kind === "aborted") {
47
+ const error = /* @__PURE__ */ new Error("Auxiliary model stream failed.");
48
+ error.code = finish.failure.code;
49
+ if (finish.failure.status !== void 0) error.status = finish.failure.status;
50
+ if (finish.failure.providerRetryAfterMs !== void 0) error.providerRetryAfterMs = finish.failure.providerRetryAfterMs;
51
+ throw error;
52
+ }
53
+ if (finish.kind === "max-tokens") throw new JobError("structured_output_limit", "后台模型输出达到 token 上限(MAX_TOKENS),JSON 可能被截断;请精简输出或提高输出上限。");
54
+ const blocks = assembler.blocks();
55
+ if (blocks.some((block) => block.type === "tool-call" || block.type === "image")) throw new JobError("structured_output_content", "后台模型应返回 JSON 文本,不应调用工具或返回附件。");
56
+ if (finish.kind !== "stop") throw new JobError("structured_output", "后台模型输出未完整结束;请重新提交完整 JSON 对象。");
57
+ return {
58
+ text: structuredResponseText(blocks.filter((block) => block.type === "text").map((block) => block.text).join("")),
59
+ ...assembler.usage === void 0 ? {} : { usage: assembler.usage }
60
+ };
61
+ };
62
+ }
63
+ //#endregion
64
+ //#region src/dsh-adapter/formation.ts
65
+ function text(blocks) {
66
+ return blocks.map((block) => block.type === "text" ? block.text : `[${block.type}]`).join("\n");
67
+ }
68
+ function projectedResult(seq, content) {
69
+ const chars = Array.from(content);
70
+ return {
71
+ seq,
72
+ type: "tool_result",
73
+ text: content,
74
+ projection: {
75
+ truncated: false,
76
+ original_chars: chars.length,
77
+ retained_chars: chars.length
78
+ }
79
+ };
80
+ }
81
+ function bodySources(value) {
82
+ if (Array.isArray(value)) return value.flatMap((item) => bodySources(item));
83
+ if (typeof value !== "object" || value === null) return [];
84
+ const claim = ClaimSchema.safeParse(value);
85
+ if (claim.success) return [claim.data.id];
86
+ const policy = PolicySchema.safeParse(value);
87
+ if (policy.success) return [policy.data.id];
88
+ return Object.values(value).flatMap((item) => bodySources(item));
89
+ }
90
+ function projectContent(event) {
91
+ switch (event.type) {
92
+ case "request/header": return { route: {
93
+ provider: event.data.header.config.provider,
94
+ model: event.data.header.config.model
95
+ } };
96
+ case "user/message":
97
+ if (event.data.source.kind === "acn-claim-changes" || event.surfaceOp !== "append" || "form" in event.data.source && (event.data.source.form === "instructions" || event.data.source.form === "catalog")) return {};
98
+ return { entry: {
99
+ seq: event.seq,
100
+ type: "user",
101
+ text: text(event.data.content)
102
+ } };
103
+ case "assistant/message": return { entry: {
104
+ seq: event.seq,
105
+ type: "assistant",
106
+ text: text(event.data.message.content.filter((block) => block.type === "text"))
107
+ } };
108
+ case "tool/call":
109
+ if (event.data.name.toLowerCase().includes("memory") || event.data.name === "run_code") return { privateCallId: event.data.callId };
110
+ return { entry: {
111
+ seq: event.seq,
112
+ type: "tool_call",
113
+ text: JSON.stringify({
114
+ name: event.data.name,
115
+ arguments: event.data.arguments
116
+ })
117
+ } };
118
+ case "tool/ptc-dispatch-start":
119
+ if (event.data.name.toLowerCase().includes("memory") || event.data.name === "run_code") return {};
120
+ return { entry: {
121
+ seq: event.seq,
122
+ type: "tool_call",
123
+ text: JSON.stringify({
124
+ name: event.data.name,
125
+ arguments: event.data.arguments
126
+ })
127
+ } };
128
+ case "tool/ptc-dispatch": {
129
+ if (event.data.name.toLowerCase().includes("memory") || event.data.name === "run_code") return {};
130
+ const content = text(event.data.content);
131
+ let seenSourceIds = [];
132
+ try {
133
+ seenSourceIds = bodySources(JSON.parse(content));
134
+ } catch {}
135
+ return {
136
+ seenSourceIds,
137
+ entry: projectedResult(event.seq, content)
138
+ };
139
+ }
140
+ case "tool/result": {
141
+ const content = text(event.data.message.content);
142
+ let seenSourceIds = [];
143
+ try {
144
+ seenSourceIds = bodySources(JSON.parse(content));
145
+ } catch {}
146
+ return {
147
+ resultCallId: event.data.message.toolCallId,
148
+ seenSourceIds,
149
+ entry: projectedResult(event.seq, content)
150
+ };
151
+ }
152
+ default: return {};
153
+ }
154
+ }
155
+ function projectEvent(event) {
156
+ const projection = projectContent(event);
157
+ if (event.type === "turn/start" || event.type === "turn/end") return {
158
+ ...projection,
159
+ activity: {
160
+ seq: event.seq,
161
+ at: event.time,
162
+ turn: event.type === "turn/start" ? "start" : event.data.reason.kind === "completed" ? "completed" : "ended"
163
+ }
164
+ };
165
+ if (projection.entry !== void 0) return {
166
+ ...projection,
167
+ activity: {
168
+ seq: event.seq,
169
+ at: event.time,
170
+ ...event.type === "user/message" && event.data.source.kind === "user" && event.surfaceOp === "append" ? { human: true } : {}
171
+ }
172
+ };
173
+ return projection;
174
+ }
175
+ const compactionSchema = z.object({
176
+ type: z.literal("compaction/summary"),
177
+ data: z.object({
178
+ shadowedRange: z.object({ end: z.number().int().nonnegative() }),
179
+ shadowedSeqs: z.array(z.number().int().nonnegative()).optional()
180
+ })
181
+ });
182
+ function compactionEnd(event) {
183
+ const parsed = compactionSchema.safeParse(event);
184
+ return parsed.success ? Math.max(parsed.data.data.shadowedRange.end, ...parsed.data.data.shadowedSeqs ?? []) : void 0;
185
+ }
186
+ //#endregion
187
+ export { projectEvent as n, structuredBackend as r, compactionEnd as t };
@@ -0,0 +1,87 @@
1
+ import { _ as JobError } from "./lock-DbmlKOoX.js";
2
+ import { d as sessionAllowed, l as restoreSessionBinding } from "./session-binding-zCSuizHs.js";
3
+ import { n as projectEvent } from "./formation-D4LO31WW.js";
4
+ import { n as isSubagent } from "./subagent-yJsFxHmH.js";
5
+ import { SessionId, pluginRecordOf } from "@deepseek-ai/dsh-session";
6
+ //#region src/dsh-adapter/formation-archive.ts
7
+ async function connectArchives(ctx, formation, owns) {
8
+ const registry = ctx.workspaceRegistry;
9
+ const original = registry.archiveSession.bind(registry);
10
+ const own = Object.getOwnPropertyDescriptor(registry, "archiveSession");
11
+ const wrapped = async (id, options) => {
12
+ if (registry.archivedSessionIds.includes(id)) return original.call(registry, id, options);
13
+ if (owns !== void 0 && !await owns(id)) return original.call(registry, id, options);
14
+ const session = ctx.sessions.get(id);
15
+ const upper = session === void 0 ? void 0 : session.seq - 1;
16
+ const frozen = await formation.beginArchive(id, upper);
17
+ try {
18
+ await original.call(registry, id, options);
19
+ } catch (error) {
20
+ if (frozen !== null) await formation.cancelArchive(id);
21
+ throw error;
22
+ }
23
+ if (frozen !== null) await formation.archived(id, frozen);
24
+ };
25
+ Object.defineProperty(registry, "archiveSession", {
26
+ configurable: true,
27
+ writable: true,
28
+ value: wrapped
29
+ });
30
+ ctx.effect(() => () => {
31
+ if (Object.getOwnPropertyDescriptor(registry, "archiveSession")?.value !== wrapped) return;
32
+ if (own === void 0) Reflect.deleteProperty(registry, "archiveSession");
33
+ else Object.defineProperty(registry, "archiveSession", own);
34
+ });
35
+ await formation.reconcileArchives(new Set(registry.archivedSessionIds));
36
+ }
37
+ //#endregion
38
+ //#region src/dsh-adapter/formation-replay.ts
39
+ async function readSession(ctx, id) {
40
+ const sessionId = SessionId(id);
41
+ const live = ctx.sessions.get(sessionId);
42
+ if (live !== void 0) return {
43
+ header: live.header,
44
+ events: live.snapshotEvents()
45
+ };
46
+ const persistence = ctx.get("sessionPersistence");
47
+ if (persistence === void 0 || await persistence.stat(sessionId) === void 0) return;
48
+ const handle = await persistence.open(sessionId, "read");
49
+ try {
50
+ return {
51
+ header: handle.header,
52
+ events: (await handle.read()).events
53
+ };
54
+ } finally {
55
+ await handle.close();
56
+ }
57
+ }
58
+ function owned(ctx, config, source) {
59
+ restoreSessionBinding(source.header, source.events);
60
+ return !isSubagent(source.header) && sessionAllowed(ctx, config, source.header);
61
+ }
62
+ function formationOwnership(ctx, config) {
63
+ return async (id) => {
64
+ const source = await readSession(ctx, id);
65
+ return source !== void 0 && owned(ctx, config, source);
66
+ };
67
+ }
68
+ function formationReplay(ctx, config) {
69
+ return async (id) => {
70
+ const source = await readSession(ctx, id);
71
+ if (source === void 0) throw new JobError("transcript_source", "Original session storage is unavailable.");
72
+ if (!owned(ctx, config, source)) throw new JobError("transcript_source", "Original session ownership does not match.");
73
+ const { events } = source;
74
+ const binding = events.find((event) => {
75
+ const record = pluginRecordOf(event);
76
+ return record?.type === "plugin:acn/session-binding" || record?.type === "plugin:acn/team-selection";
77
+ });
78
+ if (binding === void 0) throw new JobError("transcript_source", "Original session ownership is missing.");
79
+ const workspace = ctx.get("workspaceRegistry");
80
+ return [...events.filter((event) => event.seq >= binding.seq).map(projectEvent).filter((projection) => Object.keys(projection).length > 0), {
81
+ sourceSeq: events.at(-1)?.seq ?? -1,
82
+ ...workspace === void 0 ? {} : { sourceArchived: workspace.archivedSessionIds.includes(SessionId(id)) }
83
+ }];
84
+ };
85
+ }
86
+ //#endregion
87
+ export { formationReplay as n, connectArchives as r, formationOwnership as t };
@@ -0,0 +1,9 @@
1
+ import { a as FormationStateSchema, c as TranscriptStore, d as RecapOutputSchema, i as transportError, l as processedThrough, n as resolveRoute, o as RouteSchema, r as structuredCall, s as TranscriptEntrySchema, t as abortable, u as FormationValidationError } from "./structured-C9byFuzm.js";
2
+ import { _ as JobError, b as Preempted, g as DreamYield, h as DreamStopped, v as JobKindSchema, x as jobPriority, y as JobSchema } from "./lock-DbmlKOoX.js";
3
+ import { a as analysisIsStale, c as observeApplied, i as STALE_PLAN_WARNING, l as sameClaim, n as AnalysisReadBoundary, o as claimChanges, r as KnowledgeBusy, s as ensureKnowledgeReady, t as AnalysisChanged } from "./alignment-CwH0nBf-.js";
4
+ import { n as recapClaimIds, t as prepareFormation } from "./prepare-CGXwBEcu.js";
5
+ import { n as FormationStore, t as CheckpointSchema } from "./checkpoint-CPFPOxBM.js";
6
+ import { n as runnableJob, t as JobQueue } from "./queue-M917xHPS.js";
7
+ import { t as DurableWorker } from "./worker-HMGzJFWd.js";
8
+ import { t as AcnFormation } from "./service-C2lXoygJ.js";
9
+ export { AcnFormation, AnalysisChanged, AnalysisReadBoundary, CheckpointSchema, DreamStopped, DreamYield, DurableWorker, FormationStateSchema, FormationStore, FormationValidationError, JobError, JobKindSchema, JobQueue, JobSchema, KnowledgeBusy, Preempted, RecapOutputSchema, RouteSchema, STALE_PLAN_WARNING, TranscriptEntrySchema, TranscriptStore, abortable, analysisIsStale, claimChanges, ensureKnowledgeReady, jobPriority, observeApplied, prepareFormation, processedThrough, recapClaimIds, resolveRoute, runnableJob, sameClaim, structuredCall, transportError };
@@ -0,0 +1,214 @@
1
+ import { o as optional, t as ClaimSchema } from "./claim-DOAGe8ZK.js";
2
+ import { c as readYamlOr, l as writeYamlAtomic, n as withFileLock, w as hasCode } from "./lock-DbmlKOoX.js";
3
+ import { t as TraceSchema } from "./trace-Da0RnL5R.js";
4
+ import { t as DisputeSchema } from "./dispute-CtrInHzf.js";
5
+ import { z } from "zod";
6
+ import fs from "node:fs/promises";
7
+ import { basename, dirname, join } from "node:path";
8
+ import { parse } from "yaml";
9
+ //#region src/store/presentation.ts
10
+ const Schema = z.object({
11
+ schemaVersion: z.literal(1),
12
+ baselineAt: z.number(),
13
+ seen: z.record(z.string(), z.number())
14
+ });
15
+ var PresentationStore = class {
16
+ context;
17
+ path;
18
+ constructor(context) {
19
+ this.context = context;
20
+ this.path = join(context.paths.root, "presentation.yaml");
21
+ }
22
+ read() {
23
+ return readYamlOr(this.path, Schema, () => null);
24
+ }
25
+ async initialize() {
26
+ await withFileLock(`${this.path}.lock`, async () => {
27
+ if (await this.read() === null) await writeYamlAtomic(this.path, {
28
+ schemaVersion: 1,
29
+ baselineAt: Date.now(),
30
+ seen: {}
31
+ }, Schema, this.context.logger);
32
+ });
33
+ }
34
+ async acknowledge(id, version) {
35
+ await withFileLock(`${this.path}.lock`, async () => {
36
+ const current = await this.read() ?? {
37
+ schemaVersion: 1,
38
+ baselineAt: Date.now(),
39
+ seen: {}
40
+ };
41
+ await writeYamlAtomic(this.path, {
42
+ ...current,
43
+ seen: {
44
+ ...current.seen,
45
+ [id]: Math.max(version, current.seen[id] ?? 0)
46
+ }
47
+ }, Schema, this.context.logger);
48
+ });
49
+ }
50
+ };
51
+ //#endregion
52
+ //#region src/store/history.ts
53
+ const Session = z.string().regex(/^[a-zA-Z0-9_-]+$/);
54
+ const Application = z.object({
55
+ schema_version: z.literal(1),
56
+ state: z.enum([
57
+ "prepared",
58
+ "applied",
59
+ "cancelled"
60
+ ]),
61
+ application: z.object({
62
+ id: z.string().uuid(),
63
+ agent: z.string(),
64
+ knowledge: z.object({
65
+ claims: z.array(ClaimSchema),
66
+ disputes: z.array(DisputeSchema)
67
+ }),
68
+ trace: optional(TraceSchema)
69
+ })
70
+ });
71
+ const Journal = z.object({
72
+ schemaVersion: z.literal(1),
73
+ scope: z.object({
74
+ upstreamId: z.string(),
75
+ sessionId: Session
76
+ }),
77
+ jobs: z.array(z.object({
78
+ id: z.string().uuid(),
79
+ applicationId: z.string().uuid().nullable(),
80
+ work: z.object({ agentId: z.string() }).nullable(),
81
+ trigger: z.string(),
82
+ attempts: z.number().int().nonnegative(),
83
+ queuedAtMicros: z.number().nonnegative()
84
+ })),
85
+ presentationTimes: z.record(z.string(), z.number().nonnegative()).default({})
86
+ });
87
+ const Entity = z.discriminatedUnion("kind", [z.object({
88
+ kind: z.literal("claim"),
89
+ value: ClaimSchema
90
+ }), z.object({
91
+ kind: z.literal("dispute"),
92
+ value: DisputeSchema
93
+ })]);
94
+ const Ledger = z.object({
95
+ schemaVersion: z.literal(1),
96
+ scope: z.object({
97
+ upstream: z.string(),
98
+ agent: z.string()
99
+ }),
100
+ batches: z.array(z.object({
101
+ applicationId: z.string().uuid(),
102
+ owner: z.object({ sourceSession: Session }),
103
+ items: z.array(z.object({
104
+ entity: Entity,
105
+ state: z.string(),
106
+ lastConnectionRevision: optional(z.string()),
107
+ presentationAtMicros: z.number().nonnegative().default(0)
108
+ }))
109
+ }))
110
+ });
111
+ const ConnectionIndex = z.object({ upstreams: z.array(z.object({
112
+ summary: z.object({
113
+ id: z.string(),
114
+ agentId: z.string(),
115
+ maintainerEndpoint: z.string()
116
+ }),
117
+ maintainerRevision: z.string().optional()
118
+ })) });
119
+ async function documents(directory, schema, context) {
120
+ let names;
121
+ try {
122
+ names = await fs.readdir(directory);
123
+ } catch (error) {
124
+ if (hasCode(error, "ENOENT")) return [];
125
+ throw error;
126
+ }
127
+ const result = [];
128
+ for (const name of names.sort()) {
129
+ if (!name.endsWith(".yaml") || name.includes(".tmp.")) continue;
130
+ try {
131
+ const value = schema.safeParse(parse(await fs.readFile(join(directory, name), "utf8")));
132
+ if (value.success) result.push(value.data);
133
+ else context.logger.warn("Skipped an invalid historical knowledge record.");
134
+ } catch (error) {
135
+ if (hasCode(error, "ENOENT")) continue;
136
+ context.logger.warn("Could not read a historical knowledge record.");
137
+ }
138
+ }
139
+ return result;
140
+ }
141
+ async function historicalKnowledge(context) {
142
+ const result = {
143
+ applications: [],
144
+ sources: /* @__PURE__ */ new Map(),
145
+ deliveries: []
146
+ };
147
+ const upstreamRoot = dirname(dirname(context.paths.root));
148
+ const upstreamId = basename(upstreamRoot);
149
+ const add = (ids, session) => {
150
+ for (const id of ids) {
151
+ const sessions = result.sources.get(id) ?? /* @__PURE__ */ new Set();
152
+ sessions.add(session);
153
+ result.sources.set(id, sessions);
154
+ }
155
+ };
156
+ const origins = /* @__PURE__ */ new Map();
157
+ for (const journal of await documents(join(upstreamRoot, "supervisor", "journals"), Journal, context)) {
158
+ if (journal.scope.upstreamId !== upstreamId) continue;
159
+ for (const job of journal.jobs) if (job.applicationId !== null && job.work?.agentId === context.agentId) origins.set(job.applicationId, {
160
+ sessionId: journal.scope.sessionId,
161
+ trigger: job.trigger,
162
+ attempts: job.attempts,
163
+ updatedAt: (journal.presentationTimes[job.id] ?? job.queuedAtMicros) / 1e3
164
+ });
165
+ }
166
+ for (const record of await documents(join(context.paths.root, "applications"), Application, context)) {
167
+ const { application } = record;
168
+ if (application.agent !== context.agentId || application.knowledge.claims.some((claim) => claim.holder !== context.agentId) || application.knowledge.disputes.some((dispute) => dispute.reporter_agent_id !== context.agentId) || application.trace && application.trace.agent !== context.agentId) continue;
169
+ const origin = origins.get(application.id);
170
+ const entityIds = [
171
+ ...application.knowledge.claims.map((item) => item.id),
172
+ ...application.knowledge.disputes.map((item) => item.id),
173
+ ...application.trace ? [application.trace.id] : []
174
+ ];
175
+ const times = [
176
+ ...application.knowledge.claims.map((item) => item.updated_at ?? item.created_at),
177
+ ...application.knowledge.disputes.map((item) => item.created_at),
178
+ ...application.trace ? [application.trace.created_at] : []
179
+ ].map(Date.parse);
180
+ result.applications.push({
181
+ id: application.id,
182
+ state: record.state,
183
+ kind: origin?.trigger === "archive" ? "finalize" : origin === void 0 ? "history" : "recap",
184
+ attempts: origin?.attempts ?? 0,
185
+ updatedAt: origin?.updatedAt ?? Math.max(0, ...times),
186
+ entityIds,
187
+ claimCount: application.knowledge.claims.length,
188
+ disputeCount: application.knowledge.disputes.length,
189
+ traceCount: Number(application.trace !== void 0),
190
+ ...origin === void 0 ? {} : { sessionId: origin.sessionId }
191
+ });
192
+ if (origin !== void 0 && record.state === "applied") add(entityIds, origin.sessionId);
193
+ }
194
+ try {
195
+ const connection = ConnectionIndex.parse(JSON.parse(await fs.readFile(join(dirname(dirname(upstreamRoot)), "settings.json"), "utf8"))).upstreams.find((entry) => entry.summary.id === upstreamId && entry.summary.agentId === context.agentId);
196
+ const ledger = Ledger.parse(parse(await fs.readFile(join(context.paths.uploads, "ledger.yaml"), "utf8")));
197
+ if (ledger.scope.upstream !== upstreamId || ledger.scope.agent !== context.agentId) return result;
198
+ for (const batch of ledger.batches) for (const item of batch.items) {
199
+ if (!(item.entity.kind === "claim" ? item.entity.value.holder === context.agentId : item.entity.value.reporter_agent_id === context.agentId)) continue;
200
+ add([item.entity.value.id], batch.owner.sourceSession);
201
+ if (item.state === "delivered" && connection !== void 0 && connection.maintainerRevision !== void 0 && item.lastConnectionRevision === connection.maintainerRevision && connection.summary.maintainerEndpoint) result.deliveries.push({
202
+ entity: item.entity,
203
+ endpoint: connection.summary.maintainerEndpoint,
204
+ updatedAt: item.presentationAtMicros / 1e3,
205
+ sessionId: batch.owner.sourceSession
206
+ });
207
+ }
208
+ } catch (error) {
209
+ if (!hasCode(error, "ENOENT")) context.logger.warn("Could not read historical delivery acknowledgements.");
210
+ }
211
+ return result;
212
+ }
213
+ //#endregion
214
+ export { PresentationStore as n, historicalKnowledge as t };
@@ -0,0 +1,188 @@
1
+ import { S as timestampNanos, d as InboxIdSchema, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
+ import { C as StoreError, d as removeFile, l as writeYamlAtomic, m as renameFile, n as withFileLock, s as readYaml, w as hasCode } from "./lock-DbmlKOoX.js";
3
+ import { i as inboxEventAt, n as InboxMessageSchema } from "./inbox-DFtE2fOp.js";
4
+ import { randomBytes } from "node:crypto";
5
+ import fs from "node:fs/promises";
6
+ import { join } from "node:path";
7
+ import { isDeepStrictEqual } from "node:util";
8
+ //#region src/store/inbox.ts
9
+ var InboxStore = class {
10
+ context;
11
+ processingStaleAfterSecs;
12
+ constructor(context, processingStaleAfterSecs = 600) {
13
+ this.context = context;
14
+ this.processingStaleAfterSecs = processingStaleAfterSecs;
15
+ if (!Number.isFinite(processingStaleAfterSecs) || processingStaleAfterSecs < 0) throw new StoreError("decode", "Invalid inbox lease timeout.");
16
+ }
17
+ locked(action) {
18
+ return withFileLock(this.context.paths.knowledgeLock, action, { timeoutMs: this.context.lockTimeoutMs });
19
+ }
20
+ async names() {
21
+ try {
22
+ return (await fs.readdir(this.context.paths.inbox)).filter((name) => name.endsWith(".yaml") && !name.includes(".tmp."));
23
+ } catch (error) {
24
+ if (hasCode(error, "ENOENT")) return [];
25
+ throw error;
26
+ }
27
+ }
28
+ leasePath(claimed) {
29
+ const id = InboxIdSchema.parse(claimed.message.id);
30
+ if (!claimed.leaseId.startsWith(`${id}.processing.`) || !/^inbox_[0-9a-f]{8}\.processing\.[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*\.yaml$/.test(claimed.leaseId)) throw new StoreError("decode", "Invalid inbox lease identifier.");
31
+ return join(this.context.paths.inbox, claimed.leaseId);
32
+ }
33
+ async exists(path) {
34
+ try {
35
+ await fs.access(path);
36
+ return true;
37
+ } catch (error) {
38
+ if (hasCode(error, "ENOENT")) return false;
39
+ throw error;
40
+ }
41
+ }
42
+ async acceptPulled(value) {
43
+ const message = InboxMessageSchema.parse(value);
44
+ await this.locked(async () => {
45
+ const existing = (await this.names()).filter((name) => name === `${message.id}.yaml` || name === `${message.id}.done.yaml` || name.startsWith(`${message.id}.processing.`));
46
+ if (existing.length === 0) {
47
+ await writeYamlAtomic(this.context.paths.pendingInbox(message.id), message, InboxMessageSchema, this.context.logger);
48
+ return;
49
+ }
50
+ for (const name of existing) {
51
+ const actual = await readYaml(join(this.context.paths.inbox, name), InboxMessageSchema);
52
+ const comparable = (value) => JSON.parse(JSON.stringify({
53
+ ...value,
54
+ handled_at: void 0
55
+ }));
56
+ if (actual.id !== message.id || !isDeepStrictEqual(comparable(actual), comparable(message))) throw new StoreError("conflict", `Inbox snapshot conflict: ${message.id}`);
57
+ }
58
+ });
59
+ }
60
+ async pending() {
61
+ const pending = [];
62
+ for (const name of await this.names()) {
63
+ if (!/^inbox_[0-9a-f]{8}\.yaml$/.test(name)) continue;
64
+ const path = join(this.context.paths.inbox, name);
65
+ const message = await readYaml(path, InboxMessageSchema);
66
+ if (`${message.id}.yaml` !== name) throw new StoreError("decode", "Inbox ID differs from filename.");
67
+ if (await this.exists(this.context.paths.doneInbox(message.id))) {
68
+ await removeFile(path, this.context.logger);
69
+ continue;
70
+ }
71
+ pending.push({
72
+ message,
73
+ mtime: (await fs.stat(path)).mtimeMs
74
+ });
75
+ }
76
+ return pending.sort((a, b) => {
77
+ const first = timestampNanos(inboxEventAt(a.message));
78
+ const second = timestampNanos(inboxEventAt(b.message));
79
+ return (first < second ? -1 : first > second ? 1 : 0) || a.mtime - b.mtime || a.message.id.localeCompare(b.message.id);
80
+ }).map((item) => item.message);
81
+ }
82
+ listPending() {
83
+ return this.locked(() => this.pending());
84
+ }
85
+ async hasUnfinished() {
86
+ return (await this.names()).some((name) => /^inbox_[0-9a-f]{8}(?:\.processing\..+)?\.yaml$/.test(name));
87
+ }
88
+ async recoverUnlocked(nowMs, orphaned = false) {
89
+ let recovered = 0;
90
+ for (const name of await this.names()) {
91
+ if (!/^inbox_[0-9a-f]{8}\.processing\..+\.yaml$/.test(name)) continue;
92
+ const path = join(this.context.paths.inbox, name);
93
+ if (!orphaned && nowMs - (await fs.stat(path)).mtimeMs < this.processingStaleAfterSecs * 1e3) continue;
94
+ let message;
95
+ try {
96
+ message = await readYaml(path, InboxMessageSchema);
97
+ } catch (error) {
98
+ if (error instanceof StoreError && error.kind === "decode") {
99
+ this.context.logger.warn(`Preserved corrupt inbox lease: ${name}`);
100
+ continue;
101
+ }
102
+ throw error;
103
+ }
104
+ if (!name.startsWith(`${message.id}.processing.`)) {
105
+ this.context.logger.warn(`Preserved mismatched inbox lease: ${name}`);
106
+ continue;
107
+ }
108
+ const pending = this.context.paths.pendingInbox(message.id);
109
+ if (await this.exists(this.context.paths.doneInbox(message.id)) || await this.exists(pending)) await removeFile(path, this.context.logger);
110
+ else {
111
+ await renameFile(path, pending);
112
+ recovered += 1;
113
+ }
114
+ }
115
+ return recovered;
116
+ }
117
+ recoverStale(nowMs = Date.now()) {
118
+ return this.locked(() => this.recoverUnlocked(nowMs));
119
+ }
120
+ recoverOrphans() {
121
+ return this.locked(() => this.recoverUnlocked(Date.now(), true));
122
+ }
123
+ claimPending(limit = 1024) {
124
+ return this.locked(async () => {
125
+ await this.recoverUnlocked(Date.now());
126
+ const result = [];
127
+ for (const message of (await this.pending()).slice(0, limit)) {
128
+ const leaseId = `${message.id}.processing.${process.pid}.${randomBytes(8).toString("hex")}.yaml`;
129
+ const destination = join(this.context.paths.inbox, leaseId);
130
+ await renameFile(this.context.paths.pendingInbox(message.id), destination);
131
+ const now = /* @__PURE__ */ new Date();
132
+ await fs.utimes(destination, now, now);
133
+ result.push({
134
+ message,
135
+ leaseId
136
+ });
137
+ }
138
+ return result;
139
+ });
140
+ }
141
+ async validateSnapshotLocked(message) {
142
+ const comparable = (value) => ({
143
+ ...value,
144
+ handled_at: void 0
145
+ });
146
+ const names = (await this.names()).filter((name) => name === `${message.id}.yaml` || name === `${message.id}.done.yaml` || name.startsWith(`${message.id}.processing.`));
147
+ for (const name of names) if (!isDeepStrictEqual(comparable(await readYaml(join(this.context.paths.inbox, name), InboxMessageSchema)), comparable(message))) throw new StoreError("conflict", "Inbox completion snapshot mismatch.");
148
+ return names;
149
+ }
150
+ async completeSnapshotLocked(message) {
151
+ const names = await this.validateSnapshotLocked(message);
152
+ if (!names.includes(`${message.id}.done.yaml`)) await writeYamlAtomic(this.context.paths.doneInbox(message.id), {
153
+ ...message,
154
+ handled_at: nowSeconds()
155
+ }, InboxMessageSchema, this.context.logger);
156
+ for (const name of names) if (name !== `${message.id}.done.yaml`) await removeFile(join(this.context.paths.inbox, name), this.context.logger);
157
+ }
158
+ complete(claimed) {
159
+ const path = this.leasePath(claimed);
160
+ return this.locked(async () => {
161
+ if (!await this.exists(path)) {
162
+ if (await this.exists(this.context.paths.doneInbox(claimed.message.id))) return;
163
+ throw new StoreError("conflict", "Inbox lease is no longer owned by this task.");
164
+ }
165
+ const actual = await readYaml(path, InboxMessageSchema);
166
+ if (actual.id !== claimed.message.id) throw new StoreError("conflict", "Inbox lease snapshot mismatch.");
167
+ await writeYamlAtomic(this.context.paths.doneInbox(actual.id), {
168
+ ...actual,
169
+ handled_at: nowSeconds()
170
+ }, InboxMessageSchema, this.context.logger);
171
+ await removeFile(path, this.context.logger);
172
+ });
173
+ }
174
+ release(claimed) {
175
+ const path = this.leasePath(claimed);
176
+ return this.locked(async () => {
177
+ if (!await this.exists(path)) return;
178
+ if (await this.exists(this.context.paths.doneInbox(claimed.message.id))) {
179
+ await removeFile(path, this.context.logger);
180
+ return;
181
+ }
182
+ const pending = this.context.paths.pendingInbox(claimed.message.id);
183
+ if (!await this.exists(pending)) await renameFile(path, pending);
184
+ });
185
+ }
186
+ };
187
+ //#endregion
188
+ export { InboxStore as t };