@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
package/lib/index.js ADDED
@@ -0,0 +1,1377 @@
1
+ import { S as timestampNanos, h as TraceIdSchema, i as effectiveUpdatedAt, l as ClaimIdSchema } from "./claim-DOAGe8ZK.js";
2
+ import { c as TranscriptStore } from "./structured-lyQCK-Zk.js";
3
+ import { n as claimRevision } from "./revision-DeoL_IUN.js";
4
+ import { _ as JobError, c as readYamlOr, l as writeYamlAtomic, n as withFileLock } from "./lock-DbmlKOoX.js";
5
+ import { i as ClaimStore } from "./reported-sets-DdEKdeVb.js";
6
+ import { t as TraceStore } from "./traces-CHBo8y1z.js";
7
+ import { a as disputeVersion, n as PendingUploadsSchema, r as UploadStore } from "./uploads-BCA2p92b.js";
8
+ import { t as DreamStore } from "./checkpoint-RgcdqifN.js";
9
+ import { n as deliveryTarget, t as DeliveryStatusStore } from "./delivery-status-D5m3178s.js";
10
+ import { t as TeamError } from "./errors-pPumDOGD.js";
11
+ import { t as UploadDelivery } from "./deliver-BuYQaPRW.js";
12
+ import { n as agentHomePath, o as invalidStorageName, r as expandHomePath, t as AgentPaths } from "./paths-CDYV5UH9.js";
13
+ import { r as configurationBusy, u as runningConfiguration } from "./session-binding-BQrOGhZI.js";
14
+ import { t as DisputeStore } from "./disputes-ByEmi43j.js";
15
+ import { n as FormationStore } from "./checkpoint-Bmt8q2vB.js";
16
+ import { t as TeamFacade } from "./service-B7AI5jds.js";
17
+ import { t as JobQueue } from "./queue-M917xHPS.js";
18
+ import { c as ConnectionSchema, d as resolveConfig, f as upstreamsOf, l as UpstreamNameSchema, n as teamCredentials, o as resolveUpstream, r as AcnKnowledge, s as ConfigError, t as credentialReference, u as UpstreamSchema } from "./team-credentials-C9xHrPIi.js";
19
+ import { a as messageInfo, n as allActivities, r as MessageInfoSchema, t as activityPage } from "./activities-LRoCwpzw.js";
20
+ import { t as PresentationStore } from "./presentation-BlLjgDjP.js";
21
+ import { z } from "zod";
22
+ import { createHash } from "node:crypto";
23
+ import { access, stat } from "node:fs/promises";
24
+ import { dirname, join, resolve } from "node:path";
25
+ import { constants } from "node:fs";
26
+ import { SessionId } from "@deepseek-ai/dsh-session";
27
+ import { BlockAssembler, createUserMessage } from "@deepseek-ai/dsh-llm";
28
+ import { createTypertRemoteInfo } from "@deepseek-ai/dsh-typert-protocol/remote-info";
29
+ import { TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
30
+ //#region src/advanced-configuration.ts
31
+ const seconds = z.number().min(.001).max(Number.MAX_SAFE_INTEGER / 1e3);
32
+ const milliseconds = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
33
+ const AdvancedConfigurationSchema = z.strictObject({
34
+ inboxProcessingStaleAfterSecs: z.number().int().positive().max(Number.MAX_SAFE_INTEGER),
35
+ routerQueryTimeoutSecs: seconds,
36
+ httpTimeoutSecs: seconds,
37
+ httpRetryCount: z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER),
38
+ httpRetryBaseDelayMs: milliseconds,
39
+ httpRetryMaxDelayMs: milliseconds
40
+ }).superRefine((value, ctx) => {
41
+ if (value.httpRetryMaxDelayMs < value.httpRetryBaseDelayMs) ctx.addIssue({
42
+ code: "custom",
43
+ path: ["httpRetryMaxDelayMs"],
44
+ message: "Maximum retry delay must not be smaller than the base delay."
45
+ });
46
+ });
47
+ function advancedConfiguration(raw) {
48
+ const config = resolveConfig(raw);
49
+ return {
50
+ inboxProcessingStaleAfterSecs: config.inbox.processingStaleAfterSecs,
51
+ routerQueryTimeoutSecs: config.team.routerTimeoutMs / 1e3,
52
+ httpTimeoutSecs: config.team.timeoutMs / 1e3,
53
+ httpRetryCount: config.team.retryCount,
54
+ httpRetryBaseDelayMs: config.team.retryBaseDelayMs,
55
+ httpRetryMaxDelayMs: config.team.retryMaxDelayMs
56
+ };
57
+ }
58
+ //#endregion
59
+ //#region src/configuration.ts
60
+ const ConfigurationValuesSchema = z.strictObject({
61
+ agentId: z.string().trim(),
62
+ home: z.string().trim(),
63
+ provider: z.string().trim(),
64
+ model: z.string().trim(),
65
+ mode: z.enum(["solo", "team"]),
66
+ routerEndpoint: z.string().trim(),
67
+ maintainerEndpoint: z.string().trim(),
68
+ keyEnv: z.string().trim(),
69
+ timeoutMs: z.number(),
70
+ legacyEnabled: z.boolean().optional(),
71
+ connections: z.array(ConnectionSchema).optional(),
72
+ defaultConnection: z.string().optional(),
73
+ showCompletion: z.boolean().optional(),
74
+ upstream: z.string().optional(),
75
+ upstreams: z.record(UpstreamNameSchema, UpstreamSchema).optional(),
76
+ advanced: AdvancedConfigurationSchema.optional()
77
+ });
78
+ const ModelChoiceSchema = z.strictObject({
79
+ provider: z.string(),
80
+ providerName: z.string(),
81
+ id: z.string(),
82
+ name: z.string()
83
+ });
84
+ const ConfigurationSnapshotSchema = z.strictObject({
85
+ revision: z.string(),
86
+ values: ConfigurationValuesSchema,
87
+ models: z.array(ModelChoiceSchema),
88
+ active: z.boolean(),
89
+ dataDirectory: z.string(),
90
+ upstreamPending: z.record(z.string(), z.number().int().nonnegative().nullable()).optional()
91
+ });
92
+ const SaveConfigurationSchema = z.strictObject({
93
+ revision: z.string(),
94
+ values: ConfigurationValuesSchema
95
+ });
96
+ const ConfigurationResultSchema = z.discriminatedUnion("ok", [z.strictObject({
97
+ ok: z.literal(true),
98
+ snapshot: ConfigurationSnapshotSchema
99
+ }), z.strictObject({
100
+ ok: z.literal(false),
101
+ code: z.enum([
102
+ "invalid",
103
+ "conflict",
104
+ "unavailable",
105
+ "persistence",
106
+ "inactive",
107
+ "busy"
108
+ ]),
109
+ fields: z.array(z.string())
110
+ })]);
111
+ function configurationValues(raw) {
112
+ const config = resolveConfig(raw);
113
+ return {
114
+ agentId: config.agentId,
115
+ home: config.home,
116
+ provider: config.llm.provider,
117
+ model: config.llm.model,
118
+ mode: config.team.routerEndpoint === "" ? "solo" : "team",
119
+ routerEndpoint: config.team.routerEndpoint,
120
+ maintainerEndpoint: config.team.maintainerEndpoint,
121
+ keyEnv: config.team.keyEnv,
122
+ timeoutMs: config.team.timeoutMs,
123
+ legacyEnabled: config.legacyEnabled,
124
+ connections: config.connections,
125
+ defaultConnection: config.defaultConnection,
126
+ showCompletion: config.showCompletion,
127
+ advanced: advancedConfiguration(config),
128
+ ...config.upstreams === void 0 ? {} : {
129
+ upstreams: config.upstreams,
130
+ upstream: config.upstream
131
+ }
132
+ };
133
+ }
134
+ function record(value) {
135
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
136
+ }
137
+ function mergeConfiguration(raw, values) {
138
+ if (values.upstreams !== void 0) {
139
+ const previous = upstreamsOf(resolveConfig(raw));
140
+ for (const [key, value] of Object.entries(values.upstreams)) if (value.legacyStorage !== previous[key]?.legacyStorage || value.legacyKey !== previous[key]?.legacyKey) throw new ConfigError([
141
+ "upstreams",
142
+ key,
143
+ "legacyStorage"
144
+ ]);
145
+ }
146
+ const next = {
147
+ ...raw,
148
+ agentId: values.agentId,
149
+ home: values.home,
150
+ ...values.upstreams === void 0 ? {} : {
151
+ upstreams: values.upstreams,
152
+ upstream: values.upstream ?? ""
153
+ },
154
+ ...values.legacyEnabled === void 0 ? {} : { legacyEnabled: values.legacyEnabled },
155
+ ...values.connections === void 0 ? {} : { connections: values.connections },
156
+ ...values.defaultConnection === void 0 ? {} : { defaultConnection: values.defaultConnection },
157
+ ...values.showCompletion === void 0 ? {} : { showCompletion: values.showCompletion },
158
+ llm: {
159
+ ...record(raw.llm),
160
+ provider: values.provider,
161
+ model: values.model
162
+ },
163
+ team: {
164
+ ...record(raw.team),
165
+ timeoutMs: values.timeoutMs,
166
+ routerEndpoint: values.mode === "team" ? values.routerEndpoint : "",
167
+ maintainerEndpoint: values.mode === "team" ? values.maintainerEndpoint : "",
168
+ keyEnv: values.mode === "team" ? values.keyEnv : ""
169
+ }
170
+ };
171
+ delete next["projectUpstreams"];
172
+ delete next["memory"];
173
+ const advanced = values.advanced;
174
+ if (advanced !== void 0) {
175
+ next["inbox"] = {
176
+ ...record(raw.inbox),
177
+ processingStaleAfterSecs: advanced.inboxProcessingStaleAfterSecs
178
+ };
179
+ const previousTeam = resolveConfig(raw).team;
180
+ const httpChanged = advanced.httpTimeoutSecs !== previousTeam.timeoutMs / 1e3;
181
+ const timeoutMs = httpChanged ? Math.round(advanced.httpTimeoutSecs * 1e3) : values.timeoutMs;
182
+ const routerTimeoutMs = advanced.routerQueryTimeoutSecs === previousTeam.routerTimeoutMs / 1e3 ? previousTeam.routerTimeoutMs : Math.round(advanced.routerQueryTimeoutSecs * 1e3);
183
+ next["team"] = {
184
+ ...record(next["team"]),
185
+ timeoutMs,
186
+ routerTimeoutMs,
187
+ retryCount: advanced.httpRetryCount,
188
+ retryBaseDelayMs: advanced.httpRetryBaseDelayMs,
189
+ retryMaxDelayMs: advanced.httpRetryMaxDelayMs
190
+ };
191
+ if (httpChanged && values.upstreams !== void 0) next["upstreams"] = Object.fromEntries(Object.entries(values.upstreams).map(([key, value]) => [key, {
192
+ ...value,
193
+ timeoutMs
194
+ }]));
195
+ if (httpChanged && values.connections !== void 0) next["connections"] = values.connections.map((value) => ({
196
+ ...value,
197
+ timeoutMs
198
+ }));
199
+ }
200
+ resolveConfig(next);
201
+ return next;
202
+ }
203
+ //#endregion
204
+ //#region src/interaction.ts
205
+ const RuntimeChoiceSchema = z.object({
206
+ key: z.string(),
207
+ name: z.string(),
208
+ agentId: z.string(),
209
+ enabled: z.boolean(),
210
+ mode: z.enum(["solo", "team"])
211
+ });
212
+ const SessionViewSchema = z.object({
213
+ sessionId: z.string(),
214
+ key: z.string(),
215
+ name: z.string(),
216
+ locked: z.boolean(),
217
+ available: z.boolean(),
218
+ phase: z.enum([
219
+ "ready",
220
+ "syncing",
221
+ "failed",
222
+ "blocked",
223
+ "unbound"
224
+ ]),
225
+ message: z.string(),
226
+ messageInfo: MessageInfoSchema.optional(),
227
+ defaultConnection: z.string(),
228
+ needsPreparation: z.boolean().default(false),
229
+ explicitSelection: z.boolean().default(false),
230
+ activeMode: z.enum(["solo", "team"]).optional(),
231
+ configurationChanged: z.boolean().optional(),
232
+ choices: z.array(RuntimeChoiceSchema),
233
+ showCompletion: z.boolean()
234
+ });
235
+ const SourceSessionSchema = z.object({
236
+ id: z.string(),
237
+ available: z.boolean(),
238
+ title: z.string().optional()
239
+ });
240
+ const KnowledgeItemSchema = z.object({
241
+ kind: z.enum([
242
+ "claim",
243
+ "dispute",
244
+ "trace"
245
+ ]),
246
+ id: z.string(),
247
+ name: z.string(),
248
+ status: z.string(),
249
+ detail: z.string(),
250
+ summary: z.string().optional(),
251
+ updatedAt: z.string().optional(),
252
+ delivery: z.enum([
253
+ "pending",
254
+ "synced",
255
+ "local"
256
+ ]).optional(),
257
+ sources: z.array(SourceSessionSchema).optional()
258
+ });
259
+ const ActivitySchema = z.object({
260
+ id: z.string(),
261
+ kind: z.string(),
262
+ state: z.string(),
263
+ attempts: z.number(),
264
+ updatedAt: z.number(),
265
+ unseen: z.boolean().default(false),
266
+ sessionId: z.string().optional(),
267
+ source: SourceSessionSchema.optional(),
268
+ summary: z.string(),
269
+ error: z.string().optional(),
270
+ summaryInfo: MessageInfoSchema.optional(),
271
+ errorInfo: MessageInfoSchema.optional(),
272
+ counts: z.record(z.string(), z.number()).optional(),
273
+ warnings: z.array(z.string()).optional(),
274
+ budgetLimited: z.boolean().optional(),
275
+ requiresAttention: z.boolean().optional(),
276
+ incompleteCandidates: z.array(z.object({
277
+ groupId: z.string(),
278
+ claimIds: z.array(ClaimIdSchema),
279
+ reason: z.string()
280
+ })).optional(),
281
+ entityId: z.string().optional(),
282
+ retryable: z.boolean().optional(),
283
+ acknowledged: z.boolean().optional(),
284
+ reportPath: z.string().optional(),
285
+ phase: z.enum([
286
+ "exploration",
287
+ "wrap_up",
288
+ "finished"
289
+ ]).optional()
290
+ });
291
+ const KnowledgeViewSchema = z.object({
292
+ key: z.string(),
293
+ name: z.string(),
294
+ items: z.array(KnowledgeItemSchema),
295
+ omitted: z.number(),
296
+ activities: z.array(ActivitySchema),
297
+ activitiesOmitted: z.number().nonnegative().optional(),
298
+ attentionCount: z.number().nonnegative().optional(),
299
+ runningCount: z.number().nonnegative().optional(),
300
+ activityKinds: z.array(z.string()).optional(),
301
+ activitySources: z.array(z.string()).optional(),
302
+ pendingClaims: z.number(),
303
+ pendingDisputes: z.number()
304
+ });
305
+ const ReferenceIdSchema = z.union([ClaimIdSchema, TraceIdSchema]);
306
+ const KnowledgeReferenceSchema = z.object({
307
+ key: z.string(),
308
+ id: ReferenceIdSchema,
309
+ item: KnowledgeItemSchema.optional()
310
+ });
311
+ const TeamConnectionInputSchema = z.union([ConnectionSchema, UpstreamSchema.safeExtend({ id: z.string().optional() })]);
312
+ const ConnectionChecksSchema = z.array(z.object({
313
+ service: z.enum(["router", "maintainer"]),
314
+ state: z.enum(["ok", "failed"]),
315
+ message: z.string()
316
+ }));
317
+ const InteractionRequestSchema = z.discriminatedUnion("action", [
318
+ z.object({
319
+ action: z.literal("session"),
320
+ sessionId: z.string()
321
+ }),
322
+ z.object({
323
+ action: z.literal("select"),
324
+ sessionId: z.string(),
325
+ key: z.string()
326
+ }),
327
+ z.object({
328
+ action: z.literal("cancel"),
329
+ sessionId: z.string()
330
+ }),
331
+ z.object({
332
+ action: z.literal("sync"),
333
+ sessionId: z.string()
334
+ }),
335
+ z.object({
336
+ action: z.literal("knowledge"),
337
+ key: z.string(),
338
+ query: z.string().max(500).default(""),
339
+ kind: z.enum([
340
+ "claim",
341
+ "dispute",
342
+ "trace"
343
+ ]).default("claim"),
344
+ status: z.string().max(30).default(""),
345
+ delivery: z.enum([
346
+ "all",
347
+ "pending",
348
+ "synced",
349
+ "local"
350
+ ]).default("all"),
351
+ offset: z.number().int().nonnegative().default(0)
352
+ }),
353
+ z.object({
354
+ action: z.literal("activity"),
355
+ key: z.string(),
356
+ attentionOnly: z.boolean().default(false),
357
+ sourceSession: z.string().default(""),
358
+ kind: z.string().max(30).default(""),
359
+ state: z.string().max(30).default(""),
360
+ offset: z.number().int().nonnegative().default(0)
361
+ }),
362
+ z.object({
363
+ action: z.literal("reference"),
364
+ key: z.string(),
365
+ id: ReferenceIdSchema
366
+ }),
367
+ z.object({
368
+ action: z.literal("source_session"),
369
+ sessionId: z.string().regex(/^[a-zA-Z0-9_-]+$/)
370
+ }),
371
+ z.object({
372
+ action: z.literal("open_directory"),
373
+ path: z.string().trim().min(1).max(32767)
374
+ }),
375
+ z.object({
376
+ action: z.literal("retry_delivery"),
377
+ key: z.string()
378
+ }),
379
+ z.object({
380
+ action: z.literal("dream_again"),
381
+ key: z.string(),
382
+ id: z.string()
383
+ }),
384
+ z.object({
385
+ action: z.literal("retry"),
386
+ key: z.string(),
387
+ id: z.string()
388
+ }),
389
+ z.object({
390
+ action: z.literal("ack"),
391
+ key: z.string(),
392
+ id: z.string(),
393
+ version: z.number().int().nonnegative()
394
+ }),
395
+ z.object({
396
+ action: z.literal("recap"),
397
+ sessionId: z.string()
398
+ }),
399
+ z.object({
400
+ action: z.literal("check"),
401
+ connection: TeamConnectionInputSchema
402
+ }),
403
+ z.object({
404
+ action: z.literal("probe"),
405
+ provider: z.string(),
406
+ model: z.string()
407
+ })
408
+ ]);
409
+ const InteractionResultSchema = z.object({
410
+ ok: z.boolean(),
411
+ message: z.string(),
412
+ messageInfo: MessageInfoSchema.optional(),
413
+ serviceAvailable: z.boolean().optional(),
414
+ session: SessionViewSchema.optional(),
415
+ knowledge: KnowledgeViewSchema.optional(),
416
+ reference: KnowledgeReferenceSchema.optional(),
417
+ sourceSession: SourceSessionSchema.optional(),
418
+ checks: ConnectionChecksSchema.optional()
419
+ });
420
+ //#endregion
421
+ //#region src/credentials.ts
422
+ const secret = z.string().min(1).max(16384).refine((value) => value.trim().length > 0);
423
+ const CredentialRequestSchema = z.discriminatedUnion("action", [
424
+ z.strictObject({
425
+ action: z.literal("describe"),
426
+ reference: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/)
427
+ }),
428
+ z.strictObject({
429
+ action: z.literal("store"),
430
+ reference: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/),
431
+ value: secret
432
+ }),
433
+ z.strictObject({
434
+ action: z.literal("discard"),
435
+ reference: z.string().regex(/^ACN_TEAM_[0-9A-F]{32}$/)
436
+ }),
437
+ z.strictObject({
438
+ action: z.literal("check"),
439
+ connection: TeamConnectionInputSchema,
440
+ value: secret
441
+ })
442
+ ]);
443
+ const CredentialResultSchema = z.strictObject({
444
+ ok: z.boolean(),
445
+ message: z.string(),
446
+ messageInfo: MessageInfoSchema.optional(),
447
+ configured: z.boolean().optional(),
448
+ writable: z.boolean().optional(),
449
+ checks: ConnectionChecksSchema.optional()
450
+ });
451
+ //#endregion
452
+ //#region src/dsh-adapter/configuration-remote.ts
453
+ const request = {
454
+ mode: "strict",
455
+ typeSymbol: "@ftai/dsh-plugin-acn#SaveConfiguration",
456
+ create: () => SaveConfigurationSchema
457
+ };
458
+ const configurationRemote = createTypertRemoteInfo({
459
+ package: "@ftai/dsh-plugin-acn",
460
+ methods: {
461
+ "acnConfiguration/credential": {
462
+ service: "acnConfiguration",
463
+ invocation: { kind: "direct" },
464
+ cancellation: { parameter: "signal" },
465
+ parameters: [{
466
+ name: "request",
467
+ source: "json",
468
+ codec: {
469
+ mode: "strict",
470
+ typeSymbol: "@ftai/dsh-plugin-acn#CredentialRequest",
471
+ create: () => CredentialRequestSchema
472
+ },
473
+ strictCodec: {
474
+ mode: "strict",
475
+ typeSymbol: "@ftai/dsh-plugin-acn#CredentialRequest",
476
+ create: () => CredentialRequestSchema
477
+ }
478
+ }],
479
+ result: {
480
+ mode: "strict",
481
+ typeSymbol: "@ftai/dsh-plugin-acn#CredentialResult",
482
+ create: () => CredentialResultSchema
483
+ }
484
+ },
485
+ "acnConfiguration/interact": {
486
+ service: "acnConfiguration",
487
+ invocation: { kind: "direct" },
488
+ cancellation: { parameter: "signal" },
489
+ parameters: [{
490
+ name: "request",
491
+ source: "json",
492
+ codec: {
493
+ mode: "strict",
494
+ typeSymbol: "@ftai/dsh-plugin-acn#InteractionRequest",
495
+ create: () => InteractionRequestSchema
496
+ },
497
+ strictCodec: {
498
+ mode: "strict",
499
+ typeSymbol: "@ftai/dsh-plugin-acn#InteractionRequest",
500
+ create: () => InteractionRequestSchema
501
+ }
502
+ }],
503
+ result: {
504
+ mode: "strict",
505
+ typeSymbol: "@ftai/dsh-plugin-acn#InteractionResult",
506
+ create: () => InteractionResultSchema
507
+ }
508
+ },
509
+ "acnConfiguration/read": {
510
+ service: "acnConfiguration",
511
+ invocation: { kind: "direct" },
512
+ parameters: [],
513
+ result: {
514
+ mode: "strict",
515
+ typeSymbol: "@ftai/dsh-plugin-acn#ConfigurationSnapshot",
516
+ create: () => ConfigurationSnapshotSchema
517
+ }
518
+ },
519
+ "acnConfiguration/save": {
520
+ service: "acnConfiguration",
521
+ invocation: { kind: "direct" },
522
+ parameters: [{
523
+ name: "request",
524
+ source: "json",
525
+ codec: request,
526
+ strictCodec: request
527
+ }],
528
+ result: {
529
+ mode: "strict",
530
+ typeSymbol: "@ftai/dsh-plugin-acn#ConfigurationResult",
531
+ create: () => ConfigurationResultSchema
532
+ }
533
+ }
534
+ }
535
+ }, z);
536
+ //#endregion
537
+ //#region src/knowledge/sources.ts
538
+ async function knowledgeSources(context, entityIds) {
539
+ const wanted = new Set(entityIds);
540
+ const sources = /* @__PURE__ */ new Map();
541
+ const add = (ids, session) => {
542
+ for (const id of ids) if (wanted.has(id)) {
543
+ const values = sources.get(id) ?? /* @__PURE__ */ new Set();
544
+ values.add(session);
545
+ sources.set(id, values);
546
+ }
547
+ };
548
+ if (wanted.size === 0) return /* @__PURE__ */ new Map();
549
+ const formation = new FormationStore(context);
550
+ for (const session of await new TranscriptStore(context).sessions()) try {
551
+ const record = await formation.read(session);
552
+ if (record?.status === "applied") add([
553
+ ...record.appliedClaims.filter((claim) => claim.holder === context.agentId).map((claim) => claim.id),
554
+ ...record.disputes.filter((dispute) => dispute.reporter_agent_id === context.agentId).map((dispute) => dispute.id),
555
+ ...record.trace?.agent === context.agentId ? [record.trace.id] : []
556
+ ], session);
557
+ } catch {
558
+ context.logger.warn("Could not read a knowledge source checkpoint.");
559
+ }
560
+ const traces = entityIds.some((id) => id.startsWith("trace_"));
561
+ const dream = new DreamStore(context);
562
+ for (const job of await new JobQueue(context).list()) {
563
+ if (job.sessionId === void 0) continue;
564
+ const result = z.object({
565
+ entityIds: z.array(z.string()).default([]),
566
+ updatedClaimIds: z.array(ClaimIdSchema).default([])
567
+ }).safeParse(job.result);
568
+ if (result.success) add([...result.data.entityIds, ...result.data.updatedClaimIds], job.sessionId);
569
+ if (!traces || job.kind !== "dream") continue;
570
+ try {
571
+ const final = await dream.final(job.id);
572
+ if (final?.applied) add([final.trace_id], job.sessionId);
573
+ for (const { checkpoint } of await dream.records(job.id)) if (checkpoint.applied) add([checkpoint.trace_id], job.sessionId);
574
+ } catch {
575
+ context.logger.warn("Could not read a knowledge source checkpoint.");
576
+ }
577
+ }
578
+ return new Map([...sources].map(([id, sessions]) => [id, [...sessions]]));
579
+ }
580
+ //#endregion
581
+ //#region src/knowledge/ordering.ts
582
+ function knowledgeChangedAt(item) {
583
+ return "holder" in item ? effectiveUpdatedAt(item) : "reporter_agent_id" in item ? item.resolved_at ?? item.created_at : item.created_at;
584
+ }
585
+ function statusOrder(item) {
586
+ if ("holder" in item) return {
587
+ active: 0,
588
+ stale: 1,
589
+ deprecated: 2
590
+ }[item.status];
591
+ return "reporter_agent_id" in item && item.status === "resolved" ? 1 : 0;
592
+ }
593
+ function recentFirst(left, right) {
594
+ const a = timestampNanos(left);
595
+ const b = timestampNanos(right);
596
+ return a === b ? 0 : a > b ? -1 : 1;
597
+ }
598
+ function compareKnowledge(left, right) {
599
+ return statusOrder(left) - statusOrder(right) || recentFirst(knowledgeChangedAt(left), knowledgeChangedAt(right)) || recentFirst(left.created_at, right.created_at) || left.id.localeCompare(right.id);
600
+ }
601
+ //#endregion
602
+ //#region src/dsh-adapter/source-sessions.ts
603
+ async function sourceSession(ctx, id, signal) {
604
+ try {
605
+ const sessionId = SessionId(id);
606
+ const live = ctx.sessions.get(sessionId);
607
+ let events;
608
+ if (live !== void 0) events = live.snapshotEvents();
609
+ else {
610
+ const controller = ctx.get("sessionController");
611
+ const persistence = ctx.get("sessionPersistence");
612
+ if (controller !== void 0) events = (await controller.inspect(sessionId, signal)).events;
613
+ else if (persistence !== void 0) {
614
+ const handle = await persistence.open(sessionId, "read");
615
+ try {
616
+ events = (await handle.read()).events;
617
+ } finally {
618
+ await handle.close();
619
+ }
620
+ } else return {
621
+ id,
622
+ available: false
623
+ };
624
+ }
625
+ signal?.throwIfAborted();
626
+ const latest = [...events].reverse().find((event) => String(event.type) === "session/title");
627
+ const title = z.object({ title: z.string() }).safeParse(latest?.data);
628
+ return {
629
+ id,
630
+ available: true,
631
+ ...title.success ? { title: title.data.title } : {}
632
+ };
633
+ } catch {
634
+ return {
635
+ id,
636
+ available: false
637
+ };
638
+ }
639
+ }
640
+ //#endregion
641
+ //#region src/dsh-adapter/interaction-service.ts
642
+ async function checkTeamConnection(ctx, connection, credential = teamCredentials(ctx), signal) {
643
+ if (!connection.routerEndpoint || !connection.maintainerEndpoint) return {
644
+ ok: false,
645
+ message: "单人配置不需要连接检查;请先填写两个团队地址。"
646
+ };
647
+ const config = resolveConfig({
648
+ agentId: connection.agentId,
649
+ team: {
650
+ routerEndpoint: connection.routerEndpoint,
651
+ maintainerEndpoint: connection.maintainerEndpoint,
652
+ keyEnv: connection.keyEnv,
653
+ timeoutMs: connection.timeoutMs,
654
+ retryCount: 0
655
+ }
656
+ });
657
+ if (config.agentId === "") return {
658
+ ok: false,
659
+ message: "请先填写 Agent ID。"
660
+ };
661
+ const team = new TeamFacade(config.team, config.agentId, ctx.logger, credential);
662
+ try {
663
+ const checks = await Promise.all(["maintainer", "router"].map(async (service) => {
664
+ const bounded = AbortSignal.any([AbortSignal.timeout(Math.min(config.team.timeoutMs, 15e3)), ...signal === void 0 ? [] : [signal]]);
665
+ try {
666
+ await team.request(service, async () => {
667
+ const health = await team[service].health(bounded);
668
+ if (health.team_auth_enabled && health.auth_passed !== true) throw new JobError("auth", "认证未通过,请检查团队鉴权密钥。");
669
+ if (service === "router") await team.router.overview(bounded);
670
+ });
671
+ return {
672
+ service,
673
+ state: "ok",
674
+ message: "连接与认证通过"
675
+ };
676
+ } catch (error) {
677
+ const reason = bounded.aborted ? bounded.reason instanceof Error && bounded.reason.name === "TimeoutError" ? "timeout" : "cancelled" : error instanceof TeamError ? error.connectionFailure ?? error.kind : error instanceof JobError ? error.kind : "network";
678
+ const messages = {
679
+ retryable: "服务暂时不可用,请检查服务状态后重试。",
680
+ auth: "认证未通过,请检查 Agent ID 和团队鉴权密钥。",
681
+ timeout: "连接超时,请检查服务状态和网络后重试。",
682
+ dns: "无法解析服务域名,请检查地址和网络。",
683
+ unreachable: "无法连接服务,请检查地址、端口和服务是否已启动。",
684
+ network: "网络连接失败,请检查网络或代理后重试。",
685
+ protocol: "服务响应不符合 ACN 协议,请联系团队管理员检查服务版本。",
686
+ client: "服务拒绝了请求,请检查服务地址和访问权限。",
687
+ cancelled: "检查已取消。"
688
+ };
689
+ return {
690
+ service,
691
+ state: "failed",
692
+ message: messages[reason] ?? messages["network"] ?? ""
693
+ };
694
+ }
695
+ }));
696
+ return {
697
+ ok: !signal?.aborted && checks.every((item) => item.state === "ok"),
698
+ message: signal?.aborted ? "检查已取消。" : checks.every((item) => item.state === "ok") ? "团队连接检查通过。" : "部分团队服务不可用;可保存配置并继续本地工作,团队同步前需恢复连接。",
699
+ checks
700
+ };
701
+ } finally {
702
+ await team.close();
703
+ }
704
+ }
705
+ async function readKnowledge(pool, key, kind, query, offset, entities = true, activityOptions = {}, filters = {}) {
706
+ const config = pool.config(key, true);
707
+ if (config === void 0 || config.agentId === "") throw new JobError("connection", "请选择可用的知识身份。");
708
+ const knowledge = pool.isBase(key) ? pool.base : new AcnKnowledge(config, pool.ctx.logger);
709
+ try {
710
+ const context = knowledge.context();
711
+ const values = !entities ? [] : kind === "claim" ? await new ClaimStore(context).list() : kind === "dispute" ? await new DisputeStore(context).list() : await new TraceStore(context).list();
712
+ const pending = await new UploadStore(context).read();
713
+ const pendingIds = new Set([...pending.claims, ...pending.disputes].map((item) => item.id));
714
+ const delivered = (await new DeliveryStatusStore(context).read()).delivered;
715
+ const target = knowledge.team === null ? "" : deliveryTarget(config.team.maintainerEndpoint);
716
+ const delivery = (item) => {
717
+ if (pendingIds.has(item.id)) return "pending";
718
+ const receipt = delivered[`${kind}-${item.id}`];
719
+ const version = "statement" in item ? claimRevision(item) : "reporter_agent_id" in item ? disputeVersion(item) : "";
720
+ return target !== "" && receipt?.target === target && receipt.version === version ? "synced" : "local";
721
+ };
722
+ const text = query.toLocaleLowerCase();
723
+ const matching = values.filter((item) => ("holder" in item ? item.holder === context.agentId : "agent" in item ? item.agent === context.agentId : item.reporter_agent_id === context.agentId) && JSON.stringify(item).toLocaleLowerCase().includes(text) && (!filters.status || "status" in item && item.status === filters.status) && (!filters.delivery || filters.delivery === "all" || delivery(item) === filters.delivery)).sort(compareKnowledge);
724
+ const rows = await allActivities(knowledge, (kind) => pool.supportsJob(key, kind));
725
+ const page = activityPage(rows, activityOptions);
726
+ const sessions = /* @__PURE__ */ new Map();
727
+ const sessionInfo = (id) => {
728
+ const current = sessions.get(id) ?? sourceSession(pool.ctx, id);
729
+ sessions.set(id, current);
730
+ return current;
731
+ };
732
+ const sources = entities ? await knowledgeSources(context, matching.slice(offset, offset + 30).map((item) => item.id)) : /* @__PURE__ */ new Map();
733
+ const items = await Promise.all(matching.slice(offset, offset + 30).map(async (item) => ({
734
+ kind,
735
+ id: item.id,
736
+ name: item.name,
737
+ status: "status" in item ? String(item.status) : "",
738
+ detail: JSON.stringify(item, null, 2),
739
+ summary: ("statement" in item ? item.statement : "summary" in item ? item.summary : item.task).slice(0, 500),
740
+ updatedAt: knowledgeChangedAt(item),
741
+ delivery: delivery(item),
742
+ sources: await Promise.all((sources.get(item.id) ?? []).map(sessionInfo))
743
+ })));
744
+ const activities = await Promise.all(page.activities.map(async (item) => item.sessionId === void 0 ? item : {
745
+ ...item,
746
+ source: await sessionInfo(item.sessionId)
747
+ }));
748
+ const issues = rows.filter((item) => item.kind === "delivery" && item.state === "rejected" && item.requiresAttention).length;
749
+ const attentionCount = pending.claims.length + pending.disputes.length + issues + rows.filter((item) => item.kind !== "delivery" && item.requiresAttention).length;
750
+ return {
751
+ key,
752
+ name: pool.choices().find((item) => item.key === key)?.name ?? key,
753
+ items,
754
+ omitted: Math.max(0, matching.length - offset - 30),
755
+ ...page,
756
+ activities,
757
+ activityKinds: [...new Set(rows.map((item) => item.kind))],
758
+ activitySources: [...new Set(rows.flatMap((item) => item.sessionId === void 0 ? [] : [item.sessionId]))],
759
+ attentionCount,
760
+ runningCount: rows.filter((item) => item.kind !== "delivery" && (item.state === "queued" || item.state === "running")).length,
761
+ pendingClaims: pending.claims.length,
762
+ pendingDisputes: pending.disputes.length
763
+ };
764
+ } finally {
765
+ if (knowledge !== pool.base) await knowledge.team?.close();
766
+ }
767
+ }
768
+ async function executeInteraction(ctx, input, runtimePool, signal) {
769
+ const parsed = InteractionRequestSchema.safeParse(input);
770
+ if (!parsed.success) return {
771
+ ok: false,
772
+ message: "请求字段不合法,请重新加载页面。"
773
+ };
774
+ const request = parsed.data;
775
+ const pool = runtimePool ?? ctx.get("acnRuntime");
776
+ try {
777
+ if (request.action === "open_directory") {
778
+ const controller = ctx.get("sessionController");
779
+ if (controller === void 0 || !controller.canOpenWorkspacePath()) return {
780
+ ok: false,
781
+ message: "当前主机无法打开系统文件管理器。"
782
+ };
783
+ const path = resolve(expandHomePath(request.path));
784
+ try {
785
+ if (!(await stat(path)).isDirectory()) return {
786
+ ok: false,
787
+ message: "请选择已有的目录。"
788
+ };
789
+ } catch {
790
+ return {
791
+ ok: false,
792
+ message: "目录不存在或无法访问,请检查路径。"
793
+ };
794
+ }
795
+ await controller.openWorkspacePath({ path }, signal ?? AbortSignal.timeout(15e3));
796
+ return {
797
+ ok: true,
798
+ message: ""
799
+ };
800
+ }
801
+ if (pool === void 0) return {
802
+ ok: false,
803
+ serviceAvailable: false,
804
+ message: "知识组件尚未启用,聊天仍可继续。请在插件管理中启用 ACN 知识组件。"
805
+ };
806
+ if (request.action === "source_session") {
807
+ const source = await sourceSession(ctx, request.sessionId, signal);
808
+ return {
809
+ ok: source.available,
810
+ message: source.available ? "" : "来源会话不可用,可能已删除或无法读取。",
811
+ sourceSession: source
812
+ };
813
+ }
814
+ if (request.action === "check") return await checkTeamConnection(ctx, request.connection, teamCredentials(ctx), signal);
815
+ if (request.action === "probe") {
816
+ if (!request.provider || !request.model) return {
817
+ ok: true,
818
+ message: "沿用会话模型;首次同步前请先选择聊天模型。"
819
+ };
820
+ const bounded = AbortSignal.any([AbortSignal.timeout(2e4), ...signal === void 0 ? [] : [signal]]);
821
+ bounded.throwIfAborted();
822
+ const call = await ctx.llm.prepareCall({
823
+ provider: request.provider,
824
+ model: request.model,
825
+ maxTokens: 1024
826
+ }, bounded);
827
+ const assembler = new BlockAssembler();
828
+ for await (const chunk of call.stream({
829
+ ...call.config,
830
+ system: "Reply with OK.",
831
+ messages: [createUserMessage({
832
+ content: [{
833
+ type: "text",
834
+ text: "Connection check."
835
+ }],
836
+ source: { kind: "acn-formation" }
837
+ })],
838
+ signal: bounded
839
+ })) assembler.push(chunk);
840
+ bounded.throwIfAborted();
841
+ if (assembler.finish.kind !== "stop") return {
842
+ ok: false,
843
+ message: "模型未正常完成检查,保留原模型。请检查模型配置或重试。"
844
+ };
845
+ return {
846
+ ok: true,
847
+ message: "知识模型检查通过。"
848
+ };
849
+ }
850
+ if (request.action === "knowledge") return {
851
+ ok: true,
852
+ message: "",
853
+ knowledge: await readKnowledge(pool, request.key, request.kind, request.query, request.offset, true, {}, request)
854
+ };
855
+ if (request.action === "reference") {
856
+ const config = pool.config(request.key, true);
857
+ if (config === void 0 || !config.agentId) throw new JobError("connection", "请选择可用的知识身份。");
858
+ const knowledge = pool.isBase(request.key) ? pool.base : new AcnKnowledge(config, ctx.logger);
859
+ try {
860
+ const trace = request.id.startsWith("trace_");
861
+ const item = (trace ? await new TraceStore(knowledge.context()).list() : await new ClaimStore(knowledge.context()).list()).find((value) => value.id === request.id && ("holder" in value ? value.holder : value.agent) === knowledge.agentId);
862
+ const origins = item === void 0 ? [] : (await knowledgeSources(knowledge.context(), [item.id])).get(item.id) ?? [];
863
+ const sources = await Promise.all(origins.map((id) => sourceSession(ctx, id, signal)));
864
+ return {
865
+ ok: true,
866
+ message: "",
867
+ reference: {
868
+ key: request.key,
869
+ id: request.id,
870
+ ...item === void 0 ? {} : { item: {
871
+ kind: trace ? "trace" : "claim",
872
+ id: item.id,
873
+ name: item.name,
874
+ status: "status" in item ? String(item.status) : "",
875
+ detail: JSON.stringify(item, null, 2),
876
+ sources
877
+ } }
878
+ }
879
+ };
880
+ } finally {
881
+ if (knowledge !== pool.base) await knowledge.team?.close();
882
+ }
883
+ }
884
+ if (request.action === "activity") return {
885
+ ok: true,
886
+ message: "",
887
+ knowledge: await readKnowledge(pool, request.key, "claim", "", 0, false, request)
888
+ };
889
+ if (request.action === "ack") {
890
+ const config = pool.config(request.key, true);
891
+ if (config === void 0 || !config.agentId) throw new JobError("connection", "知识身份不可用。");
892
+ const knowledge = pool.isBase(request.key) ? pool.base : new AcnKnowledge(config, ctx.logger);
893
+ try {
894
+ const job = await new JobQueue(knowledge.context()).read(request.id);
895
+ const rejected = job === null ? (await allActivities(knowledge, (kind) => pool.supportsJob(request.key, kind))).find((item) => item.id === request.id && item.state === "rejected") : void 0;
896
+ if (rejected !== void 0 && rejected.updatedAt === request.version) {
897
+ await new PresentationStore(knowledge.context()).acknowledge(rejected.id, request.version);
898
+ return {
899
+ ok: true,
900
+ message: "已标记知悉;该争议仍未成功投递。"
901
+ };
902
+ }
903
+ if (job === null || job.updatedAt !== request.version || !["succeeded", "failed"].includes(job.state)) return {
904
+ ok: false,
905
+ message: "任务状态已变化,请重新读取。"
906
+ };
907
+ await new PresentationStore(knowledge.context()).acknowledge(job.id, job.updatedAt);
908
+ return {
909
+ ok: true,
910
+ message: ""
911
+ };
912
+ } finally {
913
+ if (knowledge !== pool.base) await knowledge.team?.close();
914
+ }
915
+ }
916
+ if (request.action === "retry_delivery" || request.action === "dream_again") {
917
+ if (pool.config(request.key) === void 0) throw new JobError("connection", "连接已停用或删除,不能重试。");
918
+ const knowledge = await pool.activate(request.key);
919
+ if (request.action === "dream_again") {
920
+ const previous = await knowledge.jobs?.queue.read(request.id);
921
+ if (previous?.kind !== "dream" || previous.state !== "succeeded") throw new JobError("validation", "请先等待当前 Dream 结束,再重新整理。");
922
+ const dream = await pool.dreamService(request.key);
923
+ if (dream === void 0) throw new JobError("handler_inactive", "Dream 组件未启用,请在插件管理中启用后重试。");
924
+ await dream.request(typeof previous.payload["workspace_root"] === "string" ? previous.payload["workspace_root"] : void 0, previous.sessionId);
925
+ return {
926
+ ok: true,
927
+ message: "已创建新的 Dream 请求,将重新读取当前知识。"
928
+ };
929
+ }
930
+ if (knowledge.team === null) throw new JobError("connection", "单人配置不投递团队知识,请在设置中恢复团队连接。");
931
+ const report = await new UploadDelivery(knowledge.context(), knowledge.team).deliver(signal);
932
+ return {
933
+ ok: report.warnings.length === 0,
934
+ message: report.warnings.length > 0 ? "团队投递未全部完成,请查看活动中的具体原因。" : report.pendingClaims + report.pendingDisputes > 0 ? "仍有投递正在进行或等待依赖,待投记录已保留。" : "本轮团队投递已完成。"
935
+ };
936
+ }
937
+ if (request.action === "retry") {
938
+ if (pool.config(request.key) === void 0) throw new JobError("connection", "连接已停用或删除,不能重试。");
939
+ const knowledge = await pool.activate(request.key);
940
+ const job = await knowledge.jobs?.queue.read(request.id);
941
+ if (job !== null && job !== void 0 && !knowledge.jobs?.supports(job.kind)) throw new JobError("handler_inactive", "对应后台组件未启用,请在插件管理中启用后重试。");
942
+ if (job?.kind === "dream" && job.payload["paused"] === true) {
943
+ await knowledge.jobs?.queue.pauseDream(false);
944
+ knowledge.jobs?.wake(true);
945
+ } else await knowledge.jobs?.retry(request.id);
946
+ return {
947
+ ok: true,
948
+ message: "任务已重新入队。"
949
+ };
950
+ }
951
+ const id = SessionId(request.sessionId);
952
+ let session = ctx.sessions.get(id);
953
+ const controller = ctx.get("sessionController");
954
+ if (session === void 0 && request.action === "session" && controller !== void 0) {
955
+ const inspection = await controller.inspect(id);
956
+ return {
957
+ ok: true,
958
+ message: "",
959
+ session: await pool.sessionView(inspection.meta, inspection.events)
960
+ };
961
+ }
962
+ if (session === void 0 && controller !== void 0) {
963
+ const resolved = await controller.resolveAgent(id);
964
+ if ("agent" in resolved) session = resolved.agent.session;
965
+ }
966
+ if (session === void 0) return {
967
+ ok: false,
968
+ message: "会话不可用,请重新打开或新建会话。"
969
+ };
970
+ if (request.action === "session") return {
971
+ ok: true,
972
+ message: "",
973
+ session: await pool.sessionView(session.header)
974
+ };
975
+ if (request.action === "select") return {
976
+ ok: true,
977
+ message: "",
978
+ session: await pool.select(session.header, request.key)
979
+ };
980
+ if (request.action === "cancel") {
981
+ await pool.cancel(session.header);
982
+ return {
983
+ ok: true,
984
+ message: "",
985
+ session: await pool.sessionView(session.header)
986
+ };
987
+ }
988
+ if (request.action === "sync") {
989
+ await pool.sync(session.header);
990
+ return {
991
+ ok: true,
992
+ message: "",
993
+ session: await pool.sessionView(session.header)
994
+ };
995
+ }
996
+ const services = await pool.service(session.header);
997
+ const job = await services.formation?.recap(session.id);
998
+ return {
999
+ ok: services.formation !== void 0,
1000
+ message: services.formation === void 0 ? "知识形成组件未启用。" : job == null ? "没有可复盘的新增内容。" : "复盘已入队,可在处理活动中查看。"
1001
+ };
1002
+ } catch (error) {
1003
+ return {
1004
+ ok: false,
1005
+ message: error instanceof JobError ? error.message : "操作未完成。请检查连接、知识模型和本地存储后重试。",
1006
+ ...error instanceof JobError ? { messageInfo: messageInfo(error.message, error.kind) } : {}
1007
+ };
1008
+ }
1009
+ }
1010
+ //#endregion
1011
+ //#region src/dsh-adapter/configuration-service.ts
1012
+ function configurationRevision(raw) {
1013
+ return createHash("sha256").update(JSON.stringify(raw)).digest("hex");
1014
+ }
1015
+ var ConfigurationBusy = class extends Error {
1016
+ kind = "configuration_busy";
1017
+ };
1018
+ var ConfigurationConflict = class extends Error {
1019
+ kind = "configuration_conflict";
1020
+ };
1021
+ const activeState = 2;
1022
+ function entryConfig(entry) {
1023
+ return entry.options.config ?? {};
1024
+ }
1025
+ async function checkDirectory(path) {
1026
+ let current = path;
1027
+ for (;;) try {
1028
+ if (!(await stat(current)).isDirectory()) throw new ConfigError(["home"]);
1029
+ await access(current, constants.R_OK | constants.W_OK | constants.X_OK);
1030
+ return;
1031
+ } catch (error) {
1032
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") throw new ConfigError(["home"]);
1033
+ const parent = dirname(current);
1034
+ if (parent === current) throw new ConfigError(["home"]);
1035
+ current = parent;
1036
+ }
1037
+ }
1038
+ var ConfigurationService = class extends TypertRemoteService {
1039
+ pending = 0;
1040
+ mutationTail = Promise.resolve();
1041
+ stagedCredentials = /* @__PURE__ */ new Set();
1042
+ protectCredentials(raw) {
1043
+ const config = resolveConfig(raw);
1044
+ this.stagedCredentials.delete(config.team.keyEnv);
1045
+ for (const item of Object.values(upstreamsOf(config))) this.stagedCredentials.delete(item.keyEnv);
1046
+ }
1047
+ async serialize(operation) {
1048
+ const previous = this.mutationTail;
1049
+ let release;
1050
+ this.mutationTail = new Promise((resolve) => {
1051
+ release = resolve;
1052
+ });
1053
+ await previous;
1054
+ try {
1055
+ return await operation();
1056
+ } finally {
1057
+ release?.();
1058
+ }
1059
+ }
1060
+ async credential(request, signal) {
1061
+ const result = request.action !== "check" ? await this.serialize(() => this.credentialOperation(request, signal)) : await this.credentialOperation(request, signal);
1062
+ return {
1063
+ ...result,
1064
+ messageInfo: result.messageInfo ?? messageInfo(result.message)
1065
+ };
1066
+ }
1067
+ async credentialOperation(request, signal) {
1068
+ const parsed = CredentialRequestSchema.safeParse(request);
1069
+ if (!parsed.success) return {
1070
+ ok: false,
1071
+ message: "请检查团队配置,并填写有效的鉴权密钥。"
1072
+ };
1073
+ if (parsed.data.action === "check") try {
1074
+ const { connection, value } = parsed.data;
1075
+ return await checkTeamConnection(this.ctx, {
1076
+ ...connection,
1077
+ keyEnv: connection.keyEnv || "ACN_TEAM_DRAFT"
1078
+ }, () => Promise.resolve(value), signal);
1079
+ } catch {
1080
+ return {
1081
+ ok: false,
1082
+ message: "检查未完成,请核对团队配置后重试。"
1083
+ };
1084
+ }
1085
+ const provider = this.ctx.get("credentials");
1086
+ if (provider === void 0) return {
1087
+ ok: false,
1088
+ message: "当前 DSH 未提供凭据托管,无法在此页保存新密钥。仍可输入临时密钥检查连接;保存新密钥需使用支持凭据托管的 DSH。已有环境变量引用可继续沿用,高级配置方法见插件配置文档。",
1089
+ writable: false
1090
+ };
1091
+ try {
1092
+ const reference = credentialReference(parsed.data.reference);
1093
+ if (parsed.data.action === "discard") {
1094
+ if (!this.stagedCredentials.has(reference)) return {
1095
+ ok: false,
1096
+ message: "密钥已被配置或会话使用,保留现有凭据。"
1097
+ };
1098
+ const config = this.ctx.get("configEditor") === void 0 ? this.ctx.get("acnRuntime")?.base.config : resolveConfig(entryConfig(this.entry()));
1099
+ if (config !== void 0 && (config.team.keyEnv === reference || Object.values(upstreamsOf(config)).some((item) => item.keyEnv === reference)) || this.ctx.agents.list().some((agent) => runningConfiguration(agent.session.header)?.team.keyEnv === reference)) {
1100
+ this.stagedCredentials.delete(reference);
1101
+ return {
1102
+ ok: false,
1103
+ message: "密钥已被配置或会话使用,保留现有凭据。"
1104
+ };
1105
+ }
1106
+ await provider.unset(reference);
1107
+ this.stagedCredentials.delete(reference);
1108
+ return {
1109
+ ok: true,
1110
+ message: ""
1111
+ };
1112
+ }
1113
+ if (parsed.data.action === "store") {
1114
+ const info = await provider.describe(reference);
1115
+ if (!info.writable) return {
1116
+ ok: false,
1117
+ message: "当前密钥存储只读,无法保存新密钥;仍可检查连接,或留空保留现有密钥。",
1118
+ configured: info.configured,
1119
+ writable: false
1120
+ };
1121
+ if (info.configured) return {
1122
+ ok: false,
1123
+ message: "已有密钥引用不能覆盖,请重新输入并保存为新引用。"
1124
+ };
1125
+ await provider.set(reference, parsed.data.value);
1126
+ this.stagedCredentials.add(reference);
1127
+ }
1128
+ const info = await provider.describe(reference);
1129
+ return {
1130
+ ok: true,
1131
+ message: parsed.data.action === "store" ? "凭据已保存到 DSH 托管存储,完成配置保存后,新启动的会话才会采用;已有会话保留原连接。" : "",
1132
+ configured: info.configured,
1133
+ writable: info.writable
1134
+ };
1135
+ } catch {
1136
+ this.ctx.logger.warn("Team credential operation could not complete.");
1137
+ return {
1138
+ ok: false,
1139
+ message: "凭据操作未完成,请检查宿主凭据服务后重试。"
1140
+ };
1141
+ }
1142
+ }
1143
+ async interact(request, signal) {
1144
+ if (this.pending > 0 && [
1145
+ "select",
1146
+ "sync",
1147
+ "retry",
1148
+ "retry_delivery",
1149
+ "dream_again"
1150
+ ].includes(request.action)) return Promise.resolve({
1151
+ ok: false,
1152
+ message: configurationBusy
1153
+ });
1154
+ const pool = this.entry().fiber?.ctx.get("acnRuntime");
1155
+ const result = await executeInteraction(pool?.ctx ?? this.ctx, request, pool, signal);
1156
+ return {
1157
+ ...result,
1158
+ messageInfo: result.messageInfo ?? messageInfo(result.message),
1159
+ ...result.session === void 0 ? {} : { session: {
1160
+ ...result.session,
1161
+ messageInfo: messageInfo(result.session.message)
1162
+ } }
1163
+ };
1164
+ }
1165
+ constructor(ctx) {
1166
+ super(ctx, "acnConfiguration");
1167
+ ctx.on("agent/created", () => {
1168
+ if (this.pending > 0) throw new Error(configurationBusy);
1169
+ });
1170
+ ctx.on("agent/pre-step", async (_event, next) => {
1171
+ if (this.pending > 0) throw new Error(configurationBusy);
1172
+ const decision = await next();
1173
+ if (this.pending > 0) throw new Error(configurationBusy);
1174
+ return decision;
1175
+ });
1176
+ ctx.tools.guard((execution) => this.pending > 0 && ["claim", "consult_router"].includes(execution.name) ? configurationBusy : void 0);
1177
+ }
1178
+ checkIdle() {
1179
+ if (this.ctx.agents.list().some((agent) => agent.status === "running") || this.entry().fiber?.ctx.acnRuntime.preparing) throw new ConfigurationBusy();
1180
+ }
1181
+ entry() {
1182
+ const rows = this.ctx.configEditor.entries().filter((entry) => entry.options.id === "acn-knowledge" && entry.options.name === "@ftai/dsh-plugin-acn/knowledge");
1183
+ const entry = rows.length === 1 ? rows[0] : void 0;
1184
+ if (entry === void 0) throw new ConfigError(["acn-knowledge"]);
1185
+ return entry;
1186
+ }
1187
+ async models() {
1188
+ return (await Promise.all(this.ctx.llm.listProviders().map(async (provider) => {
1189
+ try {
1190
+ return (await this.ctx.llm.listModels(provider.id)).map((model) => ({
1191
+ provider: provider.id,
1192
+ providerName: provider.name,
1193
+ id: model.id,
1194
+ name: model.name
1195
+ }));
1196
+ } catch {
1197
+ return [];
1198
+ }
1199
+ }))).flat();
1200
+ }
1201
+ async read() {
1202
+ const models = await this.models();
1203
+ const entry = this.entry();
1204
+ const raw = entryConfig(entry);
1205
+ const values = configurationValues(raw);
1206
+ const config = resolveConfig(raw);
1207
+ const upstreamPending = {};
1208
+ for (const key of Object.keys(upstreamsOf(config))) try {
1209
+ const selected = resolveUpstream(config, key, true);
1210
+ if (selected === void 0) continue;
1211
+ const path = new AgentPaths(agentHomePath(selected.home, selected.agentId)).pendingUploads;
1212
+ const pending = await readYamlOr(path, PendingUploadsSchema, () => PendingUploadsSchema.parse({}));
1213
+ upstreamPending[key] = pending.claims.length + pending.disputes.length + (pending.consolidations?.length ?? 0) + (pending.acknowledgements?.length ?? 0);
1214
+ } catch {
1215
+ upstreamPending[key] = null;
1216
+ this.ctx.logger.warn("Could not read pending counts for an upstream; configuration remains available.");
1217
+ }
1218
+ let dataDirectory = "";
1219
+ try {
1220
+ const selected = config.upstreams === void 0 ? config : resolveUpstream(config, config.upstream);
1221
+ dataDirectory = selected?.agentId ? agentHomePath(selected.home, selected.agentId) : "";
1222
+ } catch {
1223
+ this.ctx.logger.warn("Could not resolve the selected data directory; configuration remains available.");
1224
+ }
1225
+ return {
1226
+ revision: configurationRevision(raw),
1227
+ values,
1228
+ models,
1229
+ active: entry.fiber?.state === activeState,
1230
+ dataDirectory,
1231
+ upstreamPending
1232
+ };
1233
+ }
1234
+ save(request) {
1235
+ return this.serialize(() => this.saveOperation(request));
1236
+ }
1237
+ async saveOperation(request) {
1238
+ const parsed = SaveConfigurationSchema.safeParse(request);
1239
+ if (!parsed.success) return {
1240
+ ok: false,
1241
+ code: "invalid",
1242
+ fields: [...new Set(parsed.error.issues.map((issue) => issue.path.join(".")))]
1243
+ };
1244
+ const { revision, values } = parsed.data;
1245
+ try {
1246
+ const entry = this.entry();
1247
+ this.protectCredentials(entryConfig(entry));
1248
+ if (configurationRevision(entryConfig(entry)) !== revision) return {
1249
+ ok: false,
1250
+ code: "conflict",
1251
+ fields: []
1252
+ };
1253
+ if (values.upstreams === void 0 && values.agentId === "") throw new ConfigError(["agentId"]);
1254
+ if (values.mode === "team" && (!values.routerEndpoint || !values.maintainerEndpoint)) throw new ConfigError(["team"]);
1255
+ const previous = configurationValues(entryConfig(entry));
1256
+ const candidate = resolveConfig(mergeConfiguration(entryConfig(entry), values));
1257
+ const enabled = Object.entries(upstreamsOf(candidate)).filter(([, item]) => item.enabled);
1258
+ if (enabled.flatMap(([key, item]) => [
1259
+ key,
1260
+ item.agentId,
1261
+ item.legacyKey ?? ""
1262
+ ]).some((name) => invalidStorageName(name))) return {
1263
+ ok: false,
1264
+ code: "invalid",
1265
+ fields: ["windowsStorageName"]
1266
+ };
1267
+ await checkDirectory(agentHomePath(candidate.home, "example"));
1268
+ for (const [key] of enabled) {
1269
+ const selected = resolveUpstream(candidate, key);
1270
+ if (selected !== void 0) await checkDirectory(agentHomePath(selected.home, selected.agentId));
1271
+ }
1272
+ if (values.upstreams !== void 0 && previous.upstreams === void 0 && (previous.agentId !== "" || (previous.connections?.length ?? 0) > 0)) {
1273
+ const backup = join(dirname(dirname(agentHomePath(previous.home, "example"))), "upstream-migration-v1.yaml");
1274
+ await withFileLock(`${backup}.lock`, async () => {
1275
+ if (await readYamlOr(backup, z.unknown(), () => null) === null) await writeYamlAtomic(backup, entryConfig(entry), z.unknown(), this.ctx.logger);
1276
+ });
1277
+ }
1278
+ if (values.provider !== "" && !(await this.models()).some((model) => model.provider === values.provider && model.id === values.model)) return {
1279
+ ok: false,
1280
+ code: "unavailable",
1281
+ fields: ["llm"]
1282
+ };
1283
+ this.checkIdle();
1284
+ this.pending += 1;
1285
+ let conflict = false;
1286
+ const identity = (value) => value.upstreams !== void 0 || value.agentId === "" ? "" : agentHomePath(value.home, value.agentId);
1287
+ const epoch = () => Math.max(Date.now(), ...this.ctx.agents.list().map((agent) => agent.session.header.createdAt));
1288
+ try {
1289
+ await this.ctx.configEditor.edit(entry, (current) => {
1290
+ if (configurationRevision(current) !== revision) {
1291
+ if (identity(configurationValues(current)) === identity(previous)) throw new ConfigurationConflict();
1292
+ conflict = true;
1293
+ return {
1294
+ ...current,
1295
+ sessionEpoch: epoch()
1296
+ };
1297
+ }
1298
+ this.checkIdle();
1299
+ const next = mergeConfiguration(current, values);
1300
+ this.protectCredentials(next);
1301
+ if (values.upstreams === void 0 && identity(previous) !== identity(values)) next.sessionEpoch = epoch();
1302
+ return next;
1303
+ });
1304
+ } finally {
1305
+ this.pending -= 1;
1306
+ }
1307
+ if (conflict) return {
1308
+ ok: false,
1309
+ code: "conflict",
1310
+ fields: []
1311
+ };
1312
+ if (entry.fiber?.state !== activeState) return {
1313
+ ok: false,
1314
+ code: "inactive",
1315
+ fields: []
1316
+ };
1317
+ return {
1318
+ ok: true,
1319
+ snapshot: await this.read()
1320
+ };
1321
+ } catch (error) {
1322
+ if (error instanceof ConfigurationBusy) return {
1323
+ ok: false,
1324
+ code: "busy",
1325
+ fields: []
1326
+ };
1327
+ if (error instanceof ConfigurationConflict) return {
1328
+ ok: false,
1329
+ code: "conflict",
1330
+ fields: []
1331
+ };
1332
+ if (error instanceof ConfigError) return {
1333
+ ok: false,
1334
+ code: "invalid",
1335
+ fields: [...error.fields]
1336
+ };
1337
+ this.ctx.logger.warn("ACN configuration could not be applied through the profile editor.");
1338
+ return {
1339
+ ok: false,
1340
+ code: "persistence",
1341
+ fields: []
1342
+ };
1343
+ }
1344
+ }
1345
+ };
1346
+ //#endregion
1347
+ //#region src/plugins/configuration.ts
1348
+ const name = "acn-configuration";
1349
+ function apply(ctx) {
1350
+ ctx.inject([
1351
+ "configEditor",
1352
+ "typert",
1353
+ "llm",
1354
+ "agents",
1355
+ "sessions",
1356
+ "tools"
1357
+ ], (child) => {
1358
+ child.effect(() => child.typert.register({
1359
+ package: "@ftai/dsh-plugin-acn",
1360
+ face: "host",
1361
+ schemas: [],
1362
+ model: {
1363
+ services: [],
1364
+ events: [],
1365
+ objects: []
1366
+ },
1367
+ invocations: configurationRemote.descriptors
1368
+ }));
1369
+ child.plugin(ConfigurationService);
1370
+ });
1371
+ }
1372
+ var configuration_default = {
1373
+ name,
1374
+ apply
1375
+ };
1376
+ //#endregion
1377
+ export { apply, configuration_default as default, name };