@ftai/dsh-plugin-acn 0.1.0 → 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 (64) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/README.md +31 -4
  3. package/README_EN.md +31 -4
  4. package/docs/architecture.md +1 -0
  5. package/docs/assets/acn-claim-reuse.png +0 -0
  6. package/docs/config.md +19 -9
  7. package/docs/development.md +4 -4
  8. package/docs/dsh-compat.md +2 -2
  9. package/docs/user_guide.md +3 -1
  10. package/lib/{activities-LRoCwpzw.js → activities-B8U-iW4-.js} +84 -4
  11. package/lib/{checkpoint-Bmt8q2vB.js → checkpoint-CPFPOxBM.js} +2 -2
  12. package/lib/{checkpoint-RgcdqifN.js → checkpoint-c7aI4D-X.js} +1 -1
  13. package/lib/client.js +220 -223
  14. package/lib/{deliver-BuYQaPRW.js → deliver-C-dmhkfm.js} +1 -1
  15. package/lib/{delivery-status-D5m3178s.js → delivery-status-M7-Rwoyj.js} +4 -2
  16. package/lib/{dream-agent-DBszTHXY.js → dream-agent-BVqxbKFc.js} +3 -3
  17. package/lib/dream.js +3 -3
  18. package/lib/{effects-DJ4Xa7Tx.js → effects-DX1iy6FM.js} +2 -2
  19. package/lib/{evidence-store-DLFvSuNa.js → evidence-store-DW7kj20i.js} +1 -1
  20. package/lib/{formation-replay-CEOy5FkI.js → formation-replay-Bf4TSBiz.js} +1 -1
  21. package/lib/formation.js +5 -5
  22. package/lib/history-DPMHX3ZE.js +214 -0
  23. package/lib/inbox.js +2 -2
  24. package/lib/index.js +43 -47
  25. package/lib/{paths-CDYV5UH9.js → paths-B7NI9Ano.js} +6 -3
  26. package/lib/plugins/commands.js +3 -3
  27. package/lib/plugins/dream.js +4 -4
  28. package/lib/plugins/formation.js +3 -3
  29. package/lib/plugins/inbox.js +3 -3
  30. package/lib/plugins/knowledge.js +21 -23
  31. package/lib/plugins/prompt.js +1 -1
  32. package/lib/plugins/tools.js +1 -1
  33. package/lib/{prepare-DwHZudbA.js → prepare-CGXwBEcu.js} +2 -2
  34. package/lib/{scheduler-MaUEbXr3.js → scheduler-BfJSY1eq.js} +1 -1
  35. package/lib/{service-C_i3BzdP.js → service-BPwaZzFF.js} +3 -3
  36. package/lib/{service-B7AI5jds.js → service-BQaszW_v.js} +1 -1
  37. package/lib/{service-BcHV5mc7.js → service-BhniAHLo.js} +5 -5
  38. package/lib/{service-CNjqHCBR.js → service-C2lXoygJ.js} +4 -4
  39. package/lib/session-binding-zCSuizHs.js +342 -0
  40. package/lib/store.js +1 -1
  41. package/lib/{structured-lyQCK-Zk.js → structured-C9byFuzm.js} +1 -0
  42. package/lib/team.js +1 -1
  43. package/lib/types/activities.d.ts +2 -0
  44. package/lib/types/client/ActivityCard.d.ts +14 -0
  45. package/lib/types/client/ActivityDetails.d.ts +1 -1
  46. package/lib/types/client/SourceSessionLink.d.ts +2 -1
  47. package/lib/types/client/TeamSettingsPage.d.ts +0 -2
  48. package/lib/types/client/interaction-styles.d.ts +1 -1
  49. package/lib/types/client/locales.d.ts +1 -1
  50. package/lib/types/config.d.ts +1 -12
  51. package/lib/types/configuration.d.ts +0 -24
  52. package/lib/types/credentials.d.ts +0 -6
  53. package/lib/types/dsh-adapter/session-binding.d.ts +1 -1
  54. package/lib/types/interaction.d.ts +6 -15
  55. package/lib/types/store/delivery-status.d.ts +1 -0
  56. package/lib/types/store/history.d.ts +65 -0
  57. package/lib/types/store/library-directory.d.ts +4 -0
  58. package/lib/types/store/paths.d.ts +1 -1
  59. package/lib/upload.js +2 -2
  60. package/lib/{team-credentials-C9xHrPIi.js → upstreams-DEi-56tD.js} +164 -248
  61. package/lib/{worker-BBTYP2RE.js → worker-HMGzJFWd.js} +1 -1
  62. package/package.json +1 -1
  63. package/lib/presentation-BlLjgDjP.js +0 -47
  64. package/lib/session-binding-BQrOGhZI.js +0 -151
@@ -1,273 +1,153 @@
1
- import { S as timestampNanos, c as AgentIdSchema, i as effectiveUpdatedAt, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
- import { R as nextClaimUpdateAt } from "./evidence-store-DLFvSuNa.js";
1
+ import { S as timestampNanos, i as effectiveUpdatedAt, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
+ import { R as nextClaimUpdateAt } from "./evidence-store-DW7kj20i.js";
3
3
  import { n as claimRevision } from "./revision-DeoL_IUN.js";
4
4
  import { n as RevisionConflict, t as KnowledgeError } from "./errors-Bp_2WXBr.js";
5
5
  import { n as validateClaimText } from "./regular-file-BFpqMoub.js";
6
- import { C as StoreError, S as LockTimeoutError, d as removeFile, n as withFileLock, u as cleanupAtomicTemps, w as hasCode } from "./lock-DbmlKOoX.js";
6
+ import { C as StoreError, S as LockTimeoutError, d as removeFile, f as writeTextAtomic, n as withFileLock, u as cleanupAtomicTemps, w as hasCode } from "./lock-DbmlKOoX.js";
7
7
  import { n as AnalysisReadBoundary, r as KnowledgeBusy } from "./alignment-CwH0nBf-.js";
8
8
  import { i as ClaimStore } from "./reported-sets-DdEKdeVb.js";
9
9
  import { t as TraceStore } from "./traces-CHBo8y1z.js";
10
10
  import { r as UploadStore } from "./uploads-BCA2p92b.js";
11
- import { t as DreamStore } from "./checkpoint-RgcdqifN.js";
12
- import { a as assertStorageName, n as agentHomePath, t as AgentPaths } from "./paths-CDYV5UH9.js";
11
+ import { t as DreamStore } from "./checkpoint-c7aI4D-X.js";
12
+ import { C as resolveConfig, S as activeUpstream, b as UpstreamNameSchema, v as ConfigError, w as upstreamsOf, x as UpstreamSchema } from "./session-binding-zCSuizHs.js";
13
+ import { a as assertStorageName, n as agentHomePath, r as expandHomePath, t as AgentPaths } from "./paths-B7NI9Ano.js";
13
14
  import { n as ClaimEditStore } from "./disputes-ByEmi43j.js";
14
- import { n as FormationStore } from "./checkpoint-Bmt8q2vB.js";
15
- import { n as InboxEffectStore } from "./effects-DJ4Xa7Tx.js";
16
- import { t as TeamFacade } from "./service-B7AI5jds.js";
17
- import { t as DurableWorker } from "./worker-BBTYP2RE.js";
15
+ import { n as FormationStore } from "./checkpoint-CPFPOxBM.js";
16
+ import { n as InboxEffectStore } from "./effects-DX1iy6FM.js";
17
+ import { t as TeamFacade } from "./service-BQaszW_v.js";
18
+ import { t as DurableWorker } from "./worker-HMGzJFWd.js";
18
19
  import { r as MAX_TRACE_TASK_PAGE_LIMIT, t as ClaimUpdateSchema } from "./types-C2ST2Zdg.js";
19
20
  import { a as validatePage, n as claimListPage, r as page } from "./pages-BEWC3kmZ.js";
20
- import { t as PresentationStore } from "./presentation-BlLjgDjP.js";
21
+ import { n as PresentationStore, t as historicalKnowledge } from "./history-DPMHX3ZE.js";
21
22
  import { z } from "zod";
22
- import { createHash } from "node:crypto";
23
- import fs, { realpath } from "node:fs/promises";
23
+ import { createHash, randomUUID } from "node:crypto";
24
+ import fs, { readFile, realpath } from "node:fs/promises";
24
25
  import { join, resolve } from "node:path";
25
- //#region src/config.ts
26
- const positive = () => z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
27
- const nonnegative = () => z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
28
- const endpoint = z.string().refine((value) => {
29
- if (value === "") return true;
26
+ //#region src/store/library-directory.ts
27
+ const Summary = z.object({
28
+ id: UpstreamNameSchema,
29
+ name: UpstreamSchema.shape.name,
30
+ agentId: UpstreamSchema.shape.agentId,
31
+ enabled: UpstreamSchema.shape.enabled,
32
+ maintainerEndpoint: UpstreamSchema.shape.maintainerEndpoint,
33
+ routerEndpoint: UpstreamSchema.shape.routerEndpoint
34
+ });
35
+ const Index = z.object({
36
+ schemaVersion: z.literal(1),
37
+ upstreams: z.array(z.object({ summary: Summary })),
38
+ preferences: z.object({ defaultUpstream: z.string().nullable().optional() }).optional()
39
+ });
40
+ const ObjectRecord = z.record(z.string(), z.unknown());
41
+ async function sameDirectory(left, right) {
42
+ const a = resolve(expandHomePath(left));
43
+ const b = resolve(expandHomePath(right));
44
+ if (a === b) return true;
30
45
  try {
31
- const url = new URL(value);
32
- return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password && !url.search && !url.hash;
46
+ const [first, second] = await Promise.all([realpath(a), realpath(b)]);
47
+ return process.platform === "win32" ? first.toLowerCase() === second.toLowerCase() : first === second;
33
48
  } catch {
34
49
  return false;
35
50
  }
36
- });
37
- const UpstreamNameSchema = z.string().regex(/^[a-z0-9_-]+$/).refine((value) => ![
38
- "data",
39
- "skills",
40
- "config.toml",
41
- "acn.md",
42
- "logs",
43
- "tmp",
44
- ".git"
45
- ].includes(value));
46
- const UpstreamSchema = z.strictObject({
47
- name: z.string().trim().max(80).default(""),
48
- agentId: AgentIdSchema,
49
- enabled: z.boolean().default(true),
50
- routerEndpoint: endpoint.default(""),
51
- maintainerEndpoint: endpoint.default(""),
52
- keyEnv: z.string().regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/).default(""),
53
- timeoutMs: positive().default(15e3),
54
- legacyStorage: z.enum([
55
- "base",
56
- "personal",
57
- "connection"
58
- ]).optional(),
59
- legacyKey: z.string().regex(/^[a-zA-Z0-9_-]{1,80}$/).optional()
60
- }).superRefine((value, ctx) => {
61
- if (Boolean(value.routerEndpoint) !== Boolean(value.maintainerEndpoint)) ctx.addIssue({
62
- code: "custom",
63
- path: ["routerEndpoint"],
64
- message: "Configure both team endpoints or neither."
65
- });
66
- if (value.legacyStorage === "connection" !== (value.legacyKey !== void 0)) ctx.addIssue({
67
- code: "custom",
68
- path: ["legacyStorage"],
69
- message: "Invalid legacy storage mapping."
70
- });
71
- });
72
- const ConnectionSchema = z.strictObject({
73
- id: z.string().regex(/^[a-zA-Z0-9_-]{1,80}$/).refine((id) => !["personal", "legacy"].includes(id)),
74
- name: z.string().trim().min(1).max(80),
75
- enabled: z.boolean().default(true),
76
- agentId: AgentIdSchema,
77
- routerEndpoint: endpoint.refine(Boolean),
78
- maintainerEndpoint: endpoint.refine(Boolean),
79
- keyEnv: z.string().regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/).default(""),
80
- timeoutMs: positive().default(15e3)
81
- });
82
- const ConfigSchema = z.strictObject({
83
- upstream: z.string().default(""),
84
- upstreams: z.record(UpstreamNameSchema, UpstreamSchema).optional(),
85
- agentId: z.union([z.literal(""), AgentIdSchema]).default(""),
86
- home: z.string().trim().min(1).default("~/.acn-dsh"),
87
- sessionEpoch: nonnegative().default(0),
88
- connections: z.array(ConnectionSchema).max(50).default([]),
89
- defaultConnection: z.string().default(""),
90
- legacyEnabled: z.boolean().default(true),
91
- showCompletion: z.boolean().default(true),
92
- team: z.strictObject({
93
- routerEndpoint: endpoint.default(""),
94
- maintainerEndpoint: endpoint.default(""),
95
- keyEnv: z.string().regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/).default(""),
96
- timeoutMs: positive().default(15e3),
97
- routerTimeoutMs: positive().default(5e4),
98
- retryCount: nonnegative().default(3),
99
- retryBaseDelayMs: positive().default(500),
100
- retryMaxDelayMs: positive().default(8e3)
101
- }).prefault({}),
102
- llm: z.strictObject({
103
- provider: z.string().default(""),
104
- model: z.string().default(""),
105
- maxOutputTokens: positive().default(32768),
106
- timeoutMs: positive().default(6e5),
107
- structuredRetries: positive().default(5)
108
- }).prefault({}),
109
- catalog: z.strictObject({
110
- maxClaims: positive().default(20),
111
- maxChars: positive().default(24e3)
112
- }).prefault({}),
113
- formation: z.strictObject({
114
- recapOnCompaction: z.boolean().default(true),
115
- idleRecap: z.boolean().default(true),
116
- recapMinTurns: positive().default(10),
117
- recapMinTokens: positive().default(1e5),
118
- recapBatchIdleMinutes: positive().default(5),
119
- recapTailIdleMinutes: positive().default(60),
120
- recapScanSeconds: positive().default(30),
121
- finalizeIdleMinutes: nonnegative().default(0),
122
- finalizeOnDispose: z.boolean().default(false)
123
- }).prefault({}),
124
- inbox: z.strictObject({
125
- pullOnSessionStart: z.boolean().default(true),
126
- processingStaleAfterSecs: positive().default(600)
127
- }).prefault({}),
128
- dream: z.strictObject({
129
- enabled: z.boolean().default(true),
130
- minIntervalHours: positive().default(24),
131
- minChangedClaims: positive().default(5),
132
- checkIntervalHours: positive().default(4),
133
- evidenceCalibration: z.boolean().default(false),
134
- maxModelSteps: positive().max(128).default(24),
135
- maxWrapUpSteps: positive().max(8).default(3),
136
- evidenceMaxCalls: positive().max(256).default(32),
137
- evidenceMaxSteps: positive().max(128).default(24),
138
- evidenceMaxBytes: positive().max(16777216).default(1048576),
139
- evidenceMaxChars: positive().max(64e3).default(16e3),
140
- evidenceMaxFiles: positive().max(4096).default(256)
141
- }).prefault({})
142
- }).superRefine((config, ctx) => {
143
- if (config.upstreams !== void 0) {
144
- if (config.upstream !== "" && config.upstreams[config.upstream]?.enabled !== true) ctx.addIssue({
145
- code: "custom",
146
- path: ["upstream"],
147
- message: "Select an enabled upstream."
148
- });
149
- }
150
- if (new Set(config.connections.map((item) => item.id)).size !== config.connections.length) ctx.addIssue({
151
- code: "custom",
152
- path: ["connections"],
153
- message: "Connection identifiers must be unique."
154
- });
155
- if (config.defaultConnection !== "" && config.defaultConnection !== "legacy" && !config.connections.some((item) => item.id === config.defaultConnection && item.enabled)) ctx.addIssue({
156
- code: "custom",
157
- path: ["defaultConnection"],
158
- message: "Default connection must be enabled."
159
- });
160
- if (Boolean(config.team.routerEndpoint) !== Boolean(config.team.maintainerEndpoint)) ctx.addIssue({
161
- code: "custom",
162
- path: ["team"],
163
- message: "Configure both team endpoints or neither."
164
- });
165
- if (Boolean(config.llm.provider.trim()) !== Boolean(config.llm.model.trim())) ctx.addIssue({
166
- code: "custom",
167
- path: ["llm"],
168
- message: "Configure both provider and model or neither."
169
- });
170
- if (config.team.retryMaxDelayMs < config.team.retryBaseDelayMs) ctx.addIssue({
171
- code: "custom",
172
- path: ["team", "retryMaxDelayMs"],
173
- message: "Maximum retry delay must not be smaller than the base delay."
174
- });
175
- });
176
- var ConfigError = class extends Error {
177
- fields;
178
- kind = "config";
179
- constructor(fields) {
180
- super(`Invalid ACN configuration: ${fields.join(", ")}`);
181
- this.fields = fields;
182
- this.name = "ConfigError";
51
+ }
52
+ async function readIndex(home) {
53
+ let text;
54
+ try {
55
+ text = await readFile(join(expandHomePath(home), "settings.json"), "utf8");
56
+ } catch (error) {
57
+ if (hasCode(error, "ENOENT")) return null;
58
+ throw new ConfigError(["libraryIndex"]);
183
59
  }
184
- };
185
- function resolveConfig(input) {
186
- let value = input;
187
- if (typeof input === "object" && input !== null && !Array.isArray(input)) {
188
- const compatible = { ...input };
189
- delete compatible["projectUpstreams"];
190
- delete compatible["memory"];
191
- value = compatible;
60
+ try {
61
+ const raw = ObjectRecord.parse(JSON.parse(text));
62
+ const known = Index.parse(raw);
63
+ if (new Set(known.upstreams.map((item) => item.summary.id)).size !== known.upstreams.length) throw new ConfigError(["libraryIndex"]);
64
+ return {
65
+ raw,
66
+ known
67
+ };
68
+ } catch {
69
+ throw new ConfigError(["libraryIndex"]);
192
70
  }
193
- const parsed = ConfigSchema.safeParse(value);
194
- if (!parsed.success) throw new ConfigError([...new Set(parsed.error.issues.map((issue) => issue.path.join(".") || "config"))]);
195
- return parsed.data;
196
71
  }
197
- function upstreamsOf(config) {
198
- if (config.upstreams !== void 0) return config.upstreams;
199
- const items = {};
200
- if (config.agentId !== "") {
201
- items["personal"] = UpstreamSchema.parse({
202
- name: "个人知识",
203
- agentId: config.agentId,
204
- legacyStorage: config.team.routerEndpoint ? "personal" : "base"
205
- });
206
- if (config.team.routerEndpoint) items["legacy"] = UpstreamSchema.parse({
207
- name: "原有团队",
208
- agentId: config.agentId,
209
- enabled: config.legacyEnabled,
210
- routerEndpoint: config.team.routerEndpoint,
211
- maintainerEndpoint: config.team.maintainerEndpoint,
212
- keyEnv: config.team.keyEnv,
213
- timeoutMs: config.team.timeoutMs,
214
- legacyStorage: "base"
215
- });
216
- }
217
- for (const connection of config.connections) {
218
- const { id, ...value } = connection;
219
- let key = id.toLowerCase();
220
- while (items[key] !== void 0 || [
221
- "data",
222
- "skills",
223
- "logs",
224
- "tmp"
225
- ].includes(key)) key = `${key}_copy`;
226
- items[key] = UpstreamSchema.parse({
72
+ async function prepareLibraryDirectory(previous, next) {
73
+ const before = resolveConfig(previous);
74
+ const after = resolveConfig(next);
75
+ if ((before.upstreams !== void 0 || before.agentId !== "" || after.upstreams !== void 0) && await sameDirectory(before.home, after.home)) return {
76
+ ...next,
77
+ home: before.home
78
+ };
79
+ const index = await readIndex(after.home);
80
+ if (index === null) return next;
81
+ const upstreams = {};
82
+ for (const { summary } of index.known.upstreams) {
83
+ const { id, ...value } = summary;
84
+ const parsed = UpstreamSchema.safeParse({
227
85
  ...value,
228
- legacyStorage: "connection",
229
- legacyKey: id
86
+ timeoutMs: after.team.timeoutMs
87
+ });
88
+ if (!parsed.success) throw new ConfigError(["libraryIndex"]);
89
+ Object.defineProperty(upstreams, id, {
90
+ value: parsed.data,
91
+ enumerable: true,
92
+ writable: true,
93
+ configurable: true
230
94
  });
231
95
  }
232
- return items;
233
- }
234
- //#endregion
235
- //#region src/upstreams.ts
236
- function resolveUpstream(config, key, includeDisabled = false) {
237
- const profile = upstreamsOf(config)[key];
238
- if (profile === void 0 || !profile.enabled && !includeDisabled) return void 0;
239
- assertStorageName(key);
240
- if (profile.legacyKey !== void 0) assertStorageName(profile.legacyKey);
241
- const home = profile.legacyStorage === "base" ? config.home : profile.legacyStorage === "personal" ? join(config.home, "personal") : profile.legacyStorage === "connection" ? join(config.home, "connections", profile.legacyKey ?? "") : join(config.home, key, "data");
242
- return resolveConfig({
243
- ...config,
244
- upstreams: void 0,
245
- upstream: "",
96
+ const preferred = index.known.preferences?.defaultUpstream ?? "";
97
+ return {
98
+ ...next,
99
+ upstreams,
100
+ upstream: upstreams[preferred]?.enabled ? preferred : "",
101
+ agentId: "",
246
102
  connections: [],
247
- defaultConnection: "",
248
- sessionEpoch: 0,
249
- home,
250
- agentId: profile.agentId,
251
- legacyEnabled: true,
252
- team: {
253
- ...config.team,
254
- routerEndpoint: profile.routerEndpoint,
255
- maintainerEndpoint: profile.maintainerEndpoint,
256
- keyEnv: profile.keyEnv,
257
- timeoutMs: profile.timeoutMs
258
- }
259
- });
260
- }
261
- function defaultUpstream(config) {
262
- return config.upstreams === void 0 ? config.agentId ? "personal" : "" : config.upstream;
103
+ defaultConnection: ""
104
+ };
263
105
  }
264
- async function canonicalProjectPath(cwd) {
265
- const path = resolve(cwd);
266
- try {
267
- return await realpath(path);
268
- } catch {
269
- return path;
270
- }
106
+ async function syncLibraryIndex(config, logger) {
107
+ const profiles = upstreamsOf(config);
108
+ if (config.upstreams === void 0 && Object.keys(profiles).length === 0) return;
109
+ const path = join(expandHomePath(config.home), "settings.json");
110
+ await withFileLock(`${path}.lock`, async () => {
111
+ const index = await readIndex(config.home);
112
+ const previous = index?.known.upstreams ?? [];
113
+ const summaries = Object.entries(profiles).map(([id, item]) => Summary.parse({
114
+ id,
115
+ ...item
116
+ }));
117
+ const selected = config.upstreams === void 0 ? config.agentId ? "personal" : "" : config.upstream;
118
+ const expected = {
119
+ upstreams: summaries,
120
+ defaultUpstream: selected || null
121
+ };
122
+ if (index !== null && JSON.stringify({
123
+ upstreams: previous.map((item) => item.summary),
124
+ defaultUpstream: index.known.preferences?.defaultUpstream ?? null
125
+ }) === JSON.stringify(expected)) return;
126
+ const stored = z.array(ObjectRecord).parse(index?.raw.upstreams ?? []);
127
+ const upstreams = summaries.map((summary) => {
128
+ const position = previous.findIndex((item) => item.summary.id === summary.id);
129
+ const old = position < 0 ? void 0 : previous[position]?.summary;
130
+ const fields = position < 0 ? {} : stored[position] ?? {};
131
+ const sameTarget = old !== void 0 && old.agentId === summary.agentId && old.maintainerEndpoint === summary.maintainerEndpoint;
132
+ return {
133
+ ...fields,
134
+ summary,
135
+ maintainerRevision: sameTarget && typeof fields.maintainerRevision === "string" ? fields.maintainerRevision : randomUUID(),
136
+ identityEpoch: old?.agentId === summary.agentId && typeof fields.identityEpoch === "string" ? fields.identityEpoch : randomUUID()
137
+ };
138
+ });
139
+ const preferences = ObjectRecord.parse(index?.raw.preferences ?? {});
140
+ await writeTextAtomic(path, JSON.stringify({
141
+ ...index?.raw,
142
+ schemaVersion: 1,
143
+ revision: randomUUID(),
144
+ upstreams,
145
+ preferences: {
146
+ ...preferences,
147
+ defaultUpstream: selected || null
148
+ }
149
+ }, null, 2) + "\n", logger);
150
+ });
271
151
  }
272
152
  //#endregion
273
153
  //#region src/knowledge/service.ts
@@ -291,7 +171,7 @@ var AcnKnowledge = class {
291
171
  this.mode = config.team.routerEndpoint ? "team" : "solo";
292
172
  this.storeContext = this.agentId === null ? null : {
293
173
  agentId: this.agentId,
294
- paths: new AgentPaths(agentHomePath(config.home, this.agentId)),
174
+ paths: new AgentPaths(agentHomePath(config.home, this.agentId, activeUpstream(config))),
295
175
  mode: this.mode,
296
176
  logger
297
177
  };
@@ -317,6 +197,7 @@ var AcnKnowledge = class {
317
197
  }
318
198
  async initialize() {
319
199
  if (!this.configured) return;
200
+ if ((await historicalKnowledge(this.context())).applications.some((record) => record.state === "prepared")) throw new KnowledgeError("conflict", "知识目录还有未完成的历史提交,请先在原程序完成处理;当前插件不会重放旧任务。");
320
201
  await new PresentationStore(this.context()).initialize();
321
202
  await cleanupAtomicTemps(this.context().paths.root, this.logger);
322
203
  await new DreamStore(this.context()).recover();
@@ -576,4 +457,39 @@ function teamCredentials(ctx) {
576
457
  };
577
458
  }
578
459
  //#endregion
579
- export { defaultUpstream as a, ConnectionSchema as c, resolveConfig as d, upstreamsOf as f, canonicalProjectPath as i, UpstreamNameSchema as l, teamCredentials as n, resolveUpstream as o, AcnKnowledge as r, ConfigError as s, credentialReference as t, UpstreamSchema as u };
460
+ //#region src/upstreams.ts
461
+ function resolveUpstream(config, key, includeDisabled = false) {
462
+ const profile = upstreamsOf(config)[key];
463
+ if (profile === void 0 || !profile.enabled && !includeDisabled) return void 0;
464
+ assertStorageName(key);
465
+ return resolveConfig({
466
+ ...config,
467
+ upstreams: void 0,
468
+ upstream: key,
469
+ connections: [],
470
+ defaultConnection: "",
471
+ sessionEpoch: 0,
472
+ agentId: profile.agentId,
473
+ legacyEnabled: true,
474
+ team: {
475
+ ...config.team,
476
+ routerEndpoint: profile.routerEndpoint,
477
+ maintainerEndpoint: profile.maintainerEndpoint,
478
+ keyEnv: profile.keyEnv,
479
+ timeoutMs: profile.timeoutMs
480
+ }
481
+ });
482
+ }
483
+ function defaultUpstream(config) {
484
+ return config.upstreams === void 0 ? config.agentId ? "personal" : "" : config.upstream;
485
+ }
486
+ async function canonicalProjectPath(cwd) {
487
+ const path = resolve(cwd);
488
+ try {
489
+ return await realpath(path);
490
+ } catch {
491
+ return path;
492
+ }
493
+ }
494
+ //#endregion
495
+ export { teamCredentials as a, syncLibraryIndex as c, credentialReference as i, defaultUpstream as n, AcnKnowledge as o, resolveUpstream as r, prepareLibraryDirectory as s, canonicalProjectPath as t };
@@ -1,5 +1,5 @@
1
1
  import { S as LockTimeoutError, _ as JobError, b as Preempted, g as DreamYield, h as DreamStopped, t as acquireFileLease, x as jobPriority } from "./lock-DbmlKOoX.js";
2
- import { t as DreamStore } from "./checkpoint-RgcdqifN.js";
2
+ import { t as DreamStore } from "./checkpoint-c7aI4D-X.js";
3
3
  import { n as runnableJob, t as JobQueue } from "./queue-M917xHPS.js";
4
4
  //#region src/worker/worker.ts
5
5
  var DurableWorker = class {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ftai/dsh-plugin-acn",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "从agent工作轨迹中沉淀可复用的知识,让知识经验在团队中流动",
5
5
  "keywords": [
6
6
  "dsh",
@@ -1,47 +0,0 @@
1
- import { c as readYamlOr, l as writeYamlAtomic, n as withFileLock } from "./lock-DbmlKOoX.js";
2
- import { z } from "zod";
3
- import { join } from "node:path";
4
- //#region src/store/presentation.ts
5
- const Schema = z.object({
6
- schemaVersion: z.literal(1),
7
- baselineAt: z.number(),
8
- seen: z.record(z.string(), z.number())
9
- });
10
- var PresentationStore = class {
11
- context;
12
- path;
13
- constructor(context) {
14
- this.context = context;
15
- this.path = join(context.paths.root, "presentation.yaml");
16
- }
17
- read() {
18
- return readYamlOr(this.path, Schema, () => null);
19
- }
20
- async initialize() {
21
- await withFileLock(`${this.path}.lock`, async () => {
22
- if (await this.read() === null) await writeYamlAtomic(this.path, {
23
- schemaVersion: 1,
24
- baselineAt: Date.now(),
25
- seen: {}
26
- }, Schema, this.context.logger);
27
- });
28
- }
29
- async acknowledge(id, version) {
30
- await withFileLock(`${this.path}.lock`, async () => {
31
- const current = await this.read() ?? {
32
- schemaVersion: 1,
33
- baselineAt: Date.now(),
34
- seen: {}
35
- };
36
- await writeYamlAtomic(this.path, {
37
- ...current,
38
- seen: {
39
- ...current.seen,
40
- [id]: Math.max(version, current.seen[id] ?? 0)
41
- }
42
- }, Schema, this.context.logger);
43
- });
44
- }
45
- };
46
- //#endregion
47
- export { PresentationStore as t };
@@ -1,151 +0,0 @@
1
- import { n as agentHomePath } from "./paths-CDYV5UH9.js";
2
- import { z } from "zod";
3
- import { createHash } from "node:crypto";
4
- import { appendPluginRecord, pluginRecordOf } from "@deepseek-ai/dsh-session";
5
- //#region src/dsh-adapter/session-binding.ts
6
- const BindingSchema = z.strictObject({
7
- schemaVersion: z.literal(1),
8
- identity: z.string().regex(/^[0-9a-f]{64}$/)
9
- });
10
- const EligibilitySchema = z.strictObject({ schemaVersion: z.literal(1) });
11
- const emptyIdentity = createHash("sha256").update("").digest("hex");
12
- const SelectionSchema = z.strictObject({
13
- schemaVersion: z.literal(1),
14
- key: z.string(),
15
- identity: z.string().regex(/^[0-9a-f]{64}$/),
16
- prepared: z.boolean().optional()
17
- });
18
- const bindings = /* @__PURE__ */ new WeakMap();
19
- const identityOf = (config) => createHash("sha256").update(config.agentId === "" ? "" : agentHomePath(config.home, config.agentId)).digest("hex");
20
- const selections = /* @__PURE__ */ new WeakMap();
21
- const runningConfigurations = /* @__PURE__ */ new WeakMap();
22
- const activations = /* @__PURE__ */ new WeakMap();
23
- let activationSequence = 0;
24
- const configurationActivation = (header) => activations.get(header) ?? 0;
25
- function runningConfiguration(header) {
26
- return runningConfigurations.get(header);
27
- }
28
- function rememberConfiguration(header, config) {
29
- runningConfigurations.set(header, config);
30
- activations.set(header, ++activationSequence);
31
- }
32
- function forgetConfiguration(header) {
33
- runningConfigurations.delete(header);
34
- activations.delete(header);
35
- }
36
- function decodeSelection(value) {
37
- const parsed = SelectionSchema.safeParse(value);
38
- return parsed.success ? parsed.data : {
39
- schemaVersion: 1,
40
- key: "invalid",
41
- identity: "0".repeat(64)
42
- };
43
- }
44
- function observeSelection(header, event) {
45
- const record = pluginRecordOf(event);
46
- if (record?.type === "plugin:acn/team-selection") selections.set(header, decodeSelection(record.data));
47
- }
48
- function restoreSessionBinding(header, events) {
49
- const records = events.map(pluginRecordOf);
50
- const values = records.filter((record) => record?.type === "plugin:acn/session-binding").map((record) => BindingSchema.safeParse(record?.data));
51
- const first = values[0];
52
- bindings.set(header, first?.success && values.every((value) => value.success && value.data.identity === first.data.identity) ? first.data.identity : null);
53
- const selected = records.filter((record) => record?.type === "plugin:acn/team-selection").at(-1);
54
- selections.set(header, selected === void 0 ? void 0 : decodeSelection(selected.data));
55
- }
56
- function sessionSelection(ctx, header) {
57
- if (selections.has(header)) return selections.get(header);
58
- const last = (ctx.sessions.get(header.id)?.snapshotEvents().map(pluginRecordOf).filter((record) => record?.type === "plugin:acn/team-selection") ?? []).at(-1);
59
- const value = last === void 0 ? void 0 : decodeSelection(last.data);
60
- selections.set(header, value);
61
- return value;
62
- }
63
- function sessionHasWork(events) {
64
- return events.some((event) => event.type === "request/header" || event.type === "assistant/message" || event.type === "tool/result" || event.type === "turn/start" || event.type === "user/message" && event.data.source.kind === "user");
65
- }
66
- function sessionEligible(ctx, header, events = ctx.sessions.get(header.id)?.snapshotEvents()) {
67
- return events?.some((event) => {
68
- const record = pluginRecordOf(event);
69
- return record?.type === "plugin:acn/session-eligibility" && EligibilitySchema.safeParse(record.data).success || record?.type === "plugin:acn/session-binding" && BindingSchema.safeParse(record.data).data?.identity === emptyIdentity;
70
- }) ?? false;
71
- }
72
- function markSessionEligible(ctx, header) {
73
- const session = ctx.sessions.get(header.id);
74
- if (session === void 0 || session.firstLiveSeq > 0 || header.isSeeded || header.parentSession !== void 0 || sessionHasWork(session.snapshotEvents()) || sessionEligible(ctx, header)) return;
75
- appendPluginRecord(session, "plugin:acn/session-eligibility", { schemaVersion: 1 });
76
- }
77
- function sessionUnbound(ctx, header, events) {
78
- const seen = /* @__PURE__ */ new Set();
79
- let current = header;
80
- while (current !== void 0) {
81
- if (seen.has(current.id)) return false;
82
- seen.add(current.id);
83
- const history = current === header && events !== void 0 ? events : ctx.sessions.get(current.id)?.snapshotEvents();
84
- if (history === void 0) return current !== header;
85
- for (const event of history) {
86
- const record = pluginRecordOf(event);
87
- if (record?.type === "plugin:acn/team-selection") return false;
88
- if (record?.type === "plugin:acn/session-binding" && BindingSchema.safeParse(record.data).data?.identity !== emptyIdentity) return false;
89
- }
90
- current = current.parentSession === void 0 ? void 0 : ctx.sessions.get(current.parentSession)?.header;
91
- }
92
- return true;
93
- }
94
- function bindSession(ctx, config, header) {
95
- if (config.agentId === "") return;
96
- if (bindings.has(header)) return;
97
- const session = ctx.sessions.get(header.id);
98
- if (session === void 0) {
99
- bindings.set(header, null);
100
- return;
101
- }
102
- const records = session.snapshotEvents().map(pluginRecordOf).filter((record) => record?.type === "plugin:acn/session-binding");
103
- if (records.length > 0) {
104
- const values = records.map((record) => BindingSchema.safeParse(record?.data));
105
- const first = values[0];
106
- bindings.set(header, first?.success && values.every((value) => value.success && value.data.identity === first.data.identity) ? first.data.identity : null);
107
- return;
108
- }
109
- const parent = header.parentSession === void 0 ? void 0 : ctx.sessions.get(header.parentSession);
110
- const parentSelection = parent === void 0 ? void 0 : sessionSelection(ctx, parent.header);
111
- if (session.firstLiveSeq === 0 && sessionSelection(ctx, header) === void 0 && parentSelection !== void 0) appendPluginRecord(session, "plugin:acn/team-selection", parentSelection);
112
- const verifiedParent = parent !== void 0 && sessionAllowed(ctx, config, parent.header);
113
- if (session.firstLiveSeq > 0 || !verifiedParent && (!sessionEligible(ctx, header) || sessionHasWork(session.snapshotEvents()) || header.parentSession !== void 0 || header.isSeeded)) {
114
- bindings.set(header, null);
115
- return;
116
- }
117
- const identity = identityOf(config);
118
- bindings.set(header, identity);
119
- try {
120
- appendPluginRecord(session, "plugin:acn/session-binding", {
121
- schemaVersion: 1,
122
- identity
123
- });
124
- } catch (error) {
125
- bindings.set(header, null);
126
- throw error;
127
- }
128
- }
129
- const sessionChanged = "ACN 会话身份与当前配置不一致,或缺少可验证的历史身份记录,请新建会话。旧会话不能访问当前身份的知识。";
130
- const configurationBusy = "ACN 配置正在应用,请稍后重试。";
131
- const unboundSession = "本会话未启用 ACN,聊天仍可继续。只有安装插件后新建且尚未发送消息的会话可选择工作配置;如需使用 ACN,请新建会话。";
132
- function sessionAllowed(ctx, config, header) {
133
- if (config.agentId === "") return true;
134
- if (config.team.routerEndpoint && !config.legacyEnabled) return false;
135
- const identity = identityOf(config);
136
- const selected = sessionSelection(ctx, header);
137
- if (selected !== void 0) return selected.identity === identity;
138
- if (bindings.get(header) !== identity) return false;
139
- if (config.sessionEpoch === 0) return true;
140
- const seen = /* @__PURE__ */ new Set();
141
- let current = header;
142
- while (current !== void 0) {
143
- if (current.createdAt <= config.sessionEpoch || seen.has(current.id)) return false;
144
- seen.add(current.id);
145
- if (current.parentSession === void 0) return true;
146
- current = ctx.sessions.get(current.parentSession)?.header;
147
- }
148
- return false;
149
- }
150
- //#endregion
151
- export { unboundSession as _, identityOf as a, rememberConfiguration as c, sessionAllowed as d, sessionChanged as f, sessionUnbound as g, sessionSelection as h, forgetConfiguration as i, restoreSessionBinding as l, sessionHasWork as m, configurationActivation as n, markSessionEligible as o, sessionEligible as p, configurationBusy as r, observeSelection as s, bindSession as t, runningConfiguration as u };