@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,22 +1,22 @@
1
- import { o as RouteSchema, t as abortable } from "../structured-lyQCK-Zk.js";
1
+ import { o as RouteSchema, t as abortable } from "../structured-C9byFuzm.js";
2
2
  import { _ as JobError, c as readYamlOr, l as writeYamlAtomic, n as withFileLock, w as hasCode } from "../lock-DbmlKOoX.js";
3
- import { t as AcnDream } from "../service-C_i3BzdP.js";
4
- import { n as agentHomePath } from "../paths-CDYV5UH9.js";
5
- import { _ as unboundSession, a as identityOf, c as rememberConfiguration, d as sessionAllowed, f as sessionChanged, g as sessionUnbound, h as sessionSelection, i as forgetConfiguration, l as restoreSessionBinding, m as sessionHasWork, n as configurationActivation, o as markSessionEligible, p as sessionEligible, s as observeSelection, t as bindSession, u as runningConfiguration } from "../session-binding-BQrOGhZI.js";
3
+ import { t as AcnDream } from "../service-BPwaZzFF.js";
4
+ import { C as resolveConfig, _ as unboundSession, a as identityOf, c as rememberConfiguration, d as sessionAllowed, f as sessionChanged, g as sessionUnbound, h as sessionSelection, i as forgetConfiguration, l as restoreSessionBinding, m as sessionHasWork, n as configurationActivation, o as markSessionEligible, p as sessionEligible, s as observeSelection, t as bindSession, u as runningConfiguration, w as upstreamsOf } from "../session-binding-zCSuizHs.js";
5
+ import { r as expandHomePath } from "../paths-B7NI9Ano.js";
6
6
  import { n as projectEvent, r as structuredBackend, t as compactionEnd } from "../formation-D4LO31WW.js";
7
- import { t as autonomousDreamRunner } from "../dream-agent-DBszTHXY.js";
7
+ import { t as autonomousDreamRunner } from "../dream-agent-BVqxbKFc.js";
8
8
  import { t as loadPromptRenderer } from "../render-CJaVcKKC.js";
9
9
  import { n as isSubagent, t as isEvidenceAgent } from "../subagent-yJsFxHmH.js";
10
- import { t as UploadScheduler } from "../scheduler-MaUEbXr3.js";
11
- import { t as AcnInbox } from "../service-BcHV5mc7.js";
12
- import { t as AcnFormation } from "../service-CNjqHCBR.js";
13
- import { n as formationReplay, r as connectArchives, t as formationOwnership } from "../formation-replay-CEOy5FkI.js";
14
- import { a as defaultUpstream, d as resolveConfig, f as upstreamsOf, i as canonicalProjectPath, n as teamCredentials, o as resolveUpstream, r as AcnKnowledge } from "../team-credentials-C9xHrPIi.js";
10
+ import { t as UploadScheduler } from "../scheduler-BfJSY1eq.js";
11
+ import { t as AcnInbox } from "../service-BhniAHLo.js";
12
+ import { t as AcnFormation } from "../service-C2lXoygJ.js";
13
+ import { n as formationReplay, r as connectArchives, t as formationOwnership } from "../formation-replay-Bf4TSBiz.js";
14
+ import { a as teamCredentials, c as syncLibraryIndex, n as defaultUpstream, o as AcnKnowledge, r as resolveUpstream, s as prepareLibraryDirectory, t as canonicalProjectPath } from "../upstreams-DEi-56tD.js";
15
15
  import { t as KnowledgeSessions } from "../sessions-C2xuPFQv.js";
16
16
  import { z } from "zod";
17
17
  import { createHash } from "node:crypto";
18
18
  import fs from "node:fs/promises";
19
- import { dirname, join, resolve } from "node:path";
19
+ import { join, resolve } from "node:path";
20
20
  import { appendPluginRecord } from "@deepseek-ai/dsh-session";
21
21
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
22
22
  import Schema from "@deepseek-ai/schemastery";
@@ -59,7 +59,7 @@ async function* linkedFiles(root, signal) {
59
59
  }
60
60
  }
61
61
  function protectKnowledgePaths(ctx, knowledge) {
62
- const privateHome = dirname(dirname(agentHomePath(knowledge.config.home, "private-root")));
62
+ const privateHome = resolve(expandHomePath(knowledge.config.home));
63
63
  const privateAlias = async (path, recursive, signal) => {
64
64
  const privateLinks = /* @__PURE__ */ new Set();
65
65
  for await (const identity of linkedFiles(privateHome, signal)) privateLinks.add(identity);
@@ -74,7 +74,7 @@ function protectKnowledgePaths(ctx, knowledge) {
74
74
  };
75
75
  const validated = /* @__PURE__ */ new WeakMap();
76
76
  const targetAllowed = async (target, recursive, signal) => {
77
- const mapped = ctx.fs.processPathFromHostPath(dirname(dirname(agentHomePath(knowledge.config.home, "private-root"))));
77
+ const mapped = ctx.fs.processPathFromHostPath(resolve(expandHomePath(knowledge.config.home)));
78
78
  if (mapped === void 0) return true;
79
79
  const root = await ctx.fs.resolve(mapped, signal === void 0 ? {} : { signal });
80
80
  return !ctx.fs.contains(root, target) && !(recursive && ctx.fs.contains(target, root));
@@ -256,9 +256,7 @@ var RuntimePool = class {
256
256
  }));
257
257
  }
258
258
  config(key, includeDisabled = false) {
259
- const profiles = upstreamsOf(this.base.config);
260
- const mapped = profiles[key] === void 0 ? Object.keys(profiles).find((name) => profiles[name]?.legacyKey === key) : key;
261
- return mapped === void 0 ? void 0 : resolveUpstream(this.base.config, mapped, includeDisabled);
259
+ return resolveUpstream(this.base.config, key, includeDisabled);
262
260
  }
263
261
  forSession(header) {
264
262
  const config = this.config(this.key(header));
@@ -305,12 +303,10 @@ var RuntimePool = class {
305
303
  return Promise.resolve(this.view(header, events));
306
304
  }
307
305
  key(header) {
308
- const key = this.selected(header)?.key ?? (this.base.config.upstreams === void 0 ? this.base.mode === "team" ? "legacy" : "personal" : this.defaultFor());
309
- const profiles = upstreamsOf(this.base.config);
310
- return profiles[key] === void 0 ? Object.keys(profiles).find((name) => profiles[name]?.legacyKey === key) ?? key : key;
306
+ return this.selected(header)?.key ?? (this.base.config.upstreams === void 0 ? "personal" : this.defaultFor());
311
307
  }
312
308
  isBase(key) {
313
- return key === "" || this.base.config.upstreams === void 0 && key === (this.base.mode === "team" ? "legacy" : "personal");
309
+ return key === "" || this.base.config.upstreams === void 0 && key === "personal";
314
310
  }
315
311
  allowed(header) {
316
312
  const selected = this.selected(header);
@@ -468,7 +464,7 @@ var RuntimePool = class {
468
464
  const hadUserAtStart = this.hasUser(header);
469
465
  if (this.syncs.get(header.id)?.phase === "syncing") throw new JobError("busy", "收件同步仍在进行。");
470
466
  const selectedKey = this.key(header);
471
- if (this.base.config.upstreams === void 0 && selectedKey === "personal") throw new JobError("connection", "单人模式没有团队收件箱。");
467
+ if (this.base.config.upstreams === void 0 && this.base.mode === "solo" && selectedKey === "personal") throw new JobError("connection", "单人模式没有团队收件箱。");
472
468
  const controller = new AbortController();
473
469
  const state = {
474
470
  phase: "syncing",
@@ -703,7 +699,7 @@ var RuntimePool = class {
703
699
  if (text === null) {
704
700
  text = "";
705
701
  if (!(this.ctx.sessions.get(header.id)?.snapshotEvents().some((event) => event.type === "request/header") ?? true)) try {
706
- text = await fs.readFile(join(resolve(agentHomePath(this.base.config.home, "example"), "..", ".."), this.key(header), "ACN.md"), "utf8");
702
+ text = await fs.readFile(join(resolve(expandHomePath(this.base.config.home)), "upstreams", this.key(header), "ACN.md"), "utf8");
707
703
  } catch (error) {
708
704
  if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
709
705
  }
@@ -1045,7 +1041,9 @@ const Config = Schema.object({
1045
1041
  })
1046
1042
  });
1047
1043
  async function apply(ctx, input = {}) {
1048
- const config = resolveConfig(input);
1044
+ const raw = input;
1045
+ const config = resolveConfig(await prepareLibraryDirectory(raw, raw));
1046
+ await syncLibraryIndex(config, ctx.logger);
1049
1047
  const knowledge = new AcnKnowledge(config.upstreams === void 0 ? config : {
1050
1048
  ...config,
1051
1049
  agentId: ""
@@ -1,4 +1,4 @@
1
- import { d as sessionAllowed } from "../session-binding-BQrOGhZI.js";
1
+ import { d as sessionAllowed } from "../session-binding-zCSuizHs.js";
2
2
  import { t as loadPromptRenderer } from "../render-CJaVcKKC.js";
3
3
  import { t as isEvidenceAgent } from "../subagent-yJsFxHmH.js";
4
4
  import { t as KnowledgeSessions } from "../sessions-C2xuPFQv.js";
@@ -4,7 +4,7 @@ import { S as LockTimeoutError } from "../lock-DbmlKOoX.js";
4
4
  import { r as KnowledgeBusy } from "../alignment-CwH0nBf-.js";
5
5
  import { t as SessionStateStore } from "../session-state-CYqUhC95.js";
6
6
  import { t as TeamError } from "../errors-pPumDOGD.js";
7
- import { u as runningConfiguration } from "../session-binding-BQrOGhZI.js";
7
+ import { u as runningConfiguration } from "../session-binding-zCSuizHs.js";
8
8
  import { t as toolParameters } from "../tool-schema-3b4gH1zf.js";
9
9
  import { n as isSubagent } from "../subagent-yJsFxHmH.js";
10
10
  import { t as ClaimUpdateSchema } from "../types-C2ST2Zdg.js";
@@ -1,6 +1,6 @@
1
1
  import { _ as deriveDisputeId, g as deriveClaimId, i as effectiveUpdatedAt, l as ClaimIdSchema, m as SourceIdSchema, u as DisputeIdSchema, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
- import { d as RecapOutputSchema, u as FormationValidationError } from "./structured-lyQCK-Zk.js";
3
- import { R as nextClaimUpdateAt } from "./evidence-store-DLFvSuNa.js";
2
+ import { d as RecapOutputSchema, u as FormationValidationError } from "./structured-C9byFuzm.js";
3
+ import { R as nextClaimUpdateAt } from "./evidence-store-DW7kj20i.js";
4
4
  import { n as validateClaimText } from "./regular-file-BFpqMoub.js";
5
5
  //#region src/formation/prepare.ts
6
6
  function requireValid(condition, message) {
@@ -1,5 +1,5 @@
1
1
  import { r as UploadStore } from "./uploads-BCA2p92b.js";
2
- import { t as UploadDelivery } from "./deliver-BuYQaPRW.js";
2
+ import { t as UploadDelivery } from "./deliver-C-dmhkfm.js";
3
3
  //#region src/upload/scheduler.ts
4
4
  var UploadScheduler = class {
5
5
  knowledge;
@@ -1,12 +1,12 @@
1
1
  import { h as TraceIdSchema, l as ClaimIdSchema, t as ClaimSchema, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
- import { n as resolveRoute, r as structuredCall } from "./structured-lyQCK-Zk.js";
3
- import { A as valueHash, B as CandidateSchema, C as expandDraft, D as sameIds, E as reviewInput, G as DraftResponseSchema, M as validateEvidenceSummaryPreservation, O as validateCandidates, U as DiscoverySchema, W as DraftGroupSchema, X as KeepReasonSchema, Y as HashSchema, Z as KeySchema, _ as dreamEligible, a as GlobArgs, b as validateSelfReview, ct as ReviewSummarySchema, g as conservativeTokens, h as claimInput, j as validateEvidencePreservation, k as validateConsolidationSources, o as GrepArgs, pt as requireDream, q as DreamValidationError, r as EvidenceStore, rt as ProgressSchema, s as ReadArgs, st as ReviewResponseSchema, ut as SemanticReviewSchema, w as prepareGroup, x as validateSemanticReview } from "./evidence-store-DLFvSuNa.js";
2
+ import { n as resolveRoute, r as structuredCall } from "./structured-C9byFuzm.js";
3
+ import { A as valueHash, B as CandidateSchema, C as expandDraft, D as sameIds, E as reviewInput, G as DraftResponseSchema, M as validateEvidenceSummaryPreservation, O as validateCandidates, U as DiscoverySchema, W as DraftGroupSchema, X as KeepReasonSchema, Y as HashSchema, Z as KeySchema, _ as dreamEligible, a as GlobArgs, b as validateSelfReview, ct as ReviewSummarySchema, g as conservativeTokens, h as claimInput, j as validateEvidencePreservation, k as validateConsolidationSources, o as GrepArgs, pt as requireDream, q as DreamValidationError, r as EvidenceStore, rt as ProgressSchema, s as ReadArgs, st as ReviewResponseSchema, ut as SemanticReviewSchema, w as prepareGroup, x as validateSemanticReview } from "./evidence-store-DW7kj20i.js";
4
4
  import { C as StoreError, S as LockTimeoutError, _ as JobError, c as readYamlOr, g as DreamYield, h as DreamStopped, l as writeYamlAtomic, n as withFileLock, s as readYaml, w as hasCode, x as jobPriority } from "./lock-DbmlKOoX.js";
5
5
  import { l as sameClaim, r as KnowledgeBusy, s as ensureKnowledgeReady } from "./alignment-CwH0nBf-.js";
6
6
  import { i as ClaimStore } from "./reported-sets-DdEKdeVb.js";
7
7
  import { t as TraceStore } from "./traces-CHBo8y1z.js";
8
8
  import { r as UploadStore, t as ConsolidationDeliverySchema } from "./uploads-BCA2p92b.js";
9
- import { t as UploadDelivery } from "./deliver-BuYQaPRW.js";
9
+ import { t as UploadDelivery } from "./deliver-C-dmhkfm.js";
10
10
  import { z } from "zod";
11
11
  import fs from "node:fs/promises";
12
12
  import { join } from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { t as ClaimSchema, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
- import { t as abortable } from "./structured-lyQCK-Zk.js";
2
+ import { t as abortable } from "./structured-C9byFuzm.js";
3
3
  import { n as validateAgentReport } from "./dispute-CtrInHzf.js";
4
4
  import { t as TeamError } from "./errors-pPumDOGD.js";
5
5
  import { n as InboxMessageSchema, t as InboxAckRequestSchema } from "./inbox-DFtE2fOp.js";
@@ -1,14 +1,14 @@
1
1
  import { i as effectiveUpdatedAt, x as nowSeconds } from "./claim-DOAGe8ZK.js";
2
- import { d as RecapOutputSchema, n as resolveRoute, r as structuredCall, u as FormationValidationError } from "./structured-lyQCK-Zk.js";
3
- import { R as nextClaimUpdateAt } from "./evidence-store-DLFvSuNa.js";
2
+ import { d as RecapOutputSchema, n as resolveRoute, r as structuredCall, u as FormationValidationError } from "./structured-C9byFuzm.js";
3
+ import { R as nextClaimUpdateAt } from "./evidence-store-DW7kj20i.js";
4
4
  import { _ as JobError } from "./lock-DbmlKOoX.js";
5
5
  import { s as ensureKnowledgeReady } from "./alignment-CwH0nBf-.js";
6
6
  import { t as TeamError } from "./errors-pPumDOGD.js";
7
- import { t as UploadDelivery } from "./deliver-BuYQaPRW.js";
8
- import { t as prepareFormation } from "./prepare-DwHZudbA.js";
7
+ import { t as UploadDelivery } from "./deliver-C-dmhkfm.js";
8
+ import { t as prepareFormation } from "./prepare-CGXwBEcu.js";
9
9
  import { s as DisputeResolutionSchema } from "./inbox-DFtE2fOp.js";
10
10
  import { t as InboxStore } from "./inbox-2CugZZQm.js";
11
- import { n as InboxEffectStore } from "./effects-DJ4Xa7Tx.js";
11
+ import { n as InboxEffectStore } from "./effects-DX1iy6FM.js";
12
12
  //#region src/inbox/prepare.ts
13
13
  const InternalizeOutputSchema = RecapOutputSchema.omit({ used_claim_ids: true });
14
14
  function valid(condition, message) {
@@ -1,8 +1,8 @@
1
- import { c as TranscriptStore, d as RecapOutputSchema, l as processedThrough, o as RouteSchema, r as structuredCall } from "./structured-lyQCK-Zk.js";
1
+ import { c as TranscriptStore, d as RecapOutputSchema, l as processedThrough, o as RouteSchema, r as structuredCall } from "./structured-C9byFuzm.js";
2
2
  import { C as StoreError, _ as JobError, b as Preempted, l as writeYamlAtomic, n as withFileLock } from "./lock-DbmlKOoX.js";
3
- import { n as recapClaimIds, t as prepareFormation } from "./prepare-DwHZudbA.js";
4
- import { n as FormationStore } from "./checkpoint-Bmt8q2vB.js";
5
- import { t as DurableWorker } from "./worker-BBTYP2RE.js";
3
+ import { n as recapClaimIds, t as prepareFormation } from "./prepare-CGXwBEcu.js";
4
+ import { n as FormationStore } from "./checkpoint-CPFPOxBM.js";
5
+ import { t as DurableWorker } from "./worker-HMGzJFWd.js";
6
6
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
7
7
  //#region src/formation/triggers.ts
8
8
  function idleTrigger(config, state, entries, now) {
@@ -0,0 +1,342 @@
1
+ import { c as AgentIdSchema } from "./claim-DOAGe8ZK.js";
2
+ import { n as agentHomePath } from "./paths-B7NI9Ano.js";
3
+ import { z } from "zod";
4
+ import { createHash } from "node:crypto";
5
+ import { appendPluginRecord, pluginRecordOf } from "@deepseek-ai/dsh-session";
6
+ //#region src/config.ts
7
+ const positive = () => z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
8
+ const nonnegative = () => z.number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
9
+ const endpoint = z.string().refine((value) => {
10
+ if (value === "") return true;
11
+ try {
12
+ const url = new URL(value);
13
+ return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password && !url.search && !url.hash;
14
+ } catch {
15
+ return false;
16
+ }
17
+ });
18
+ const UpstreamNameSchema = z.string().regex(/^[a-z0-9_-]+$/).refine((value) => ![
19
+ "data",
20
+ "skills",
21
+ "config.toml",
22
+ "acn.md",
23
+ "logs",
24
+ "tmp",
25
+ ".git"
26
+ ].includes(value));
27
+ const UpstreamSchema = z.strictObject({
28
+ name: z.string().trim().max(80).default(""),
29
+ agentId: AgentIdSchema,
30
+ enabled: z.boolean().default(true),
31
+ routerEndpoint: endpoint.default(""),
32
+ maintainerEndpoint: endpoint.default(""),
33
+ keyEnv: z.string().regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/).default(""),
34
+ timeoutMs: positive().default(15e3)
35
+ }).superRefine((value, ctx) => {
36
+ if (Boolean(value.routerEndpoint) !== Boolean(value.maintainerEndpoint)) ctx.addIssue({
37
+ code: "custom",
38
+ path: ["routerEndpoint"],
39
+ message: "Configure both team endpoints or neither."
40
+ });
41
+ });
42
+ const ConnectionSchema = z.strictObject({
43
+ id: z.string().regex(/^[a-zA-Z0-9_-]{1,80}$/).refine((id) => !["personal", "legacy"].includes(id)),
44
+ name: z.string().trim().min(1).max(80),
45
+ enabled: z.boolean().default(true),
46
+ agentId: AgentIdSchema,
47
+ routerEndpoint: endpoint.refine(Boolean),
48
+ maintainerEndpoint: endpoint.refine(Boolean),
49
+ keyEnv: z.string().regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/).default(""),
50
+ timeoutMs: positive().default(15e3)
51
+ });
52
+ const ConfigSchema = z.strictObject({
53
+ upstream: z.string().default(""),
54
+ upstreams: z.record(UpstreamNameSchema, UpstreamSchema).optional(),
55
+ agentId: z.union([z.literal(""), AgentIdSchema]).default(""),
56
+ home: z.string().trim().min(1).default("~/.acn-dsh"),
57
+ sessionEpoch: nonnegative().default(0),
58
+ connections: z.array(ConnectionSchema).max(50).default([]),
59
+ defaultConnection: z.string().default(""),
60
+ legacyEnabled: z.boolean().default(true),
61
+ showCompletion: z.boolean().default(true),
62
+ team: z.strictObject({
63
+ routerEndpoint: endpoint.default(""),
64
+ maintainerEndpoint: endpoint.default(""),
65
+ keyEnv: z.string().regex(/^(?:[A-Za-z_][A-Za-z0-9_]*)?$/).default(""),
66
+ timeoutMs: positive().default(15e3),
67
+ routerTimeoutMs: positive().default(5e4),
68
+ retryCount: nonnegative().default(3),
69
+ retryBaseDelayMs: positive().default(500),
70
+ retryMaxDelayMs: positive().default(8e3)
71
+ }).prefault({}),
72
+ llm: z.strictObject({
73
+ provider: z.string().default(""),
74
+ model: z.string().default(""),
75
+ maxOutputTokens: positive().default(32768),
76
+ timeoutMs: positive().default(6e5),
77
+ structuredRetries: positive().default(5)
78
+ }).prefault({}),
79
+ catalog: z.strictObject({
80
+ maxClaims: positive().default(20),
81
+ maxChars: positive().default(24e3)
82
+ }).prefault({}),
83
+ formation: z.strictObject({
84
+ recapOnCompaction: z.boolean().default(true),
85
+ idleRecap: z.boolean().default(true),
86
+ recapMinTurns: positive().default(10),
87
+ recapMinTokens: positive().default(1e5),
88
+ recapBatchIdleMinutes: positive().default(5),
89
+ recapTailIdleMinutes: positive().default(60),
90
+ recapScanSeconds: positive().default(30),
91
+ finalizeIdleMinutes: nonnegative().default(0),
92
+ finalizeOnDispose: z.boolean().default(false)
93
+ }).prefault({}),
94
+ inbox: z.strictObject({
95
+ pullOnSessionStart: z.boolean().default(true),
96
+ processingStaleAfterSecs: positive().default(600)
97
+ }).prefault({}),
98
+ dream: z.strictObject({
99
+ enabled: z.boolean().default(true),
100
+ minIntervalHours: positive().default(24),
101
+ minChangedClaims: positive().default(5),
102
+ checkIntervalHours: positive().default(4),
103
+ evidenceCalibration: z.boolean().default(false),
104
+ maxModelSteps: positive().max(128).default(24),
105
+ maxWrapUpSteps: positive().max(8).default(3),
106
+ evidenceMaxCalls: positive().max(256).default(32),
107
+ evidenceMaxSteps: positive().max(128).default(24),
108
+ evidenceMaxBytes: positive().max(16777216).default(1048576),
109
+ evidenceMaxChars: positive().max(64e3).default(16e3),
110
+ evidenceMaxFiles: positive().max(4096).default(256)
111
+ }).prefault({})
112
+ }).superRefine((config, ctx) => {
113
+ if (config.upstreams !== void 0) {
114
+ if (config.upstream !== "" && config.upstreams[config.upstream]?.enabled !== true) ctx.addIssue({
115
+ code: "custom",
116
+ path: ["upstream"],
117
+ message: "Select an enabled upstream."
118
+ });
119
+ }
120
+ if (new Set(config.connections.map((item) => item.id)).size !== config.connections.length) ctx.addIssue({
121
+ code: "custom",
122
+ path: ["connections"],
123
+ message: "Connection identifiers must be unique."
124
+ });
125
+ if (config.defaultConnection !== "" && config.defaultConnection !== "legacy" && !config.connections.some((item) => item.id === config.defaultConnection && item.enabled)) ctx.addIssue({
126
+ code: "custom",
127
+ path: ["defaultConnection"],
128
+ message: "Default connection must be enabled."
129
+ });
130
+ if (Boolean(config.team.routerEndpoint) !== Boolean(config.team.maintainerEndpoint)) ctx.addIssue({
131
+ code: "custom",
132
+ path: ["team"],
133
+ message: "Configure both team endpoints or neither."
134
+ });
135
+ if (Boolean(config.llm.provider.trim()) !== Boolean(config.llm.model.trim())) ctx.addIssue({
136
+ code: "custom",
137
+ path: ["llm"],
138
+ message: "Configure both provider and model or neither."
139
+ });
140
+ if (config.team.retryMaxDelayMs < config.team.retryBaseDelayMs) ctx.addIssue({
141
+ code: "custom",
142
+ path: ["team", "retryMaxDelayMs"],
143
+ message: "Maximum retry delay must not be smaller than the base delay."
144
+ });
145
+ });
146
+ var ConfigError = class extends Error {
147
+ fields;
148
+ kind = "config";
149
+ constructor(fields) {
150
+ super(`Invalid ACN configuration: ${fields.join(", ")}`);
151
+ this.fields = fields;
152
+ this.name = "ConfigError";
153
+ }
154
+ };
155
+ function resolveConfig(input) {
156
+ let value = input;
157
+ if (typeof input === "object" && input !== null && !Array.isArray(input)) {
158
+ const compatible = { ...input };
159
+ delete compatible["projectUpstreams"];
160
+ delete compatible["memory"];
161
+ value = compatible;
162
+ }
163
+ const parsed = ConfigSchema.safeParse(value);
164
+ if (!parsed.success) throw new ConfigError([...new Set(parsed.error.issues.map((issue) => issue.path.join(".") || "config"))]);
165
+ return parsed.data;
166
+ }
167
+ function upstreamsOf(config) {
168
+ if (config.upstreams !== void 0) return config.upstreams;
169
+ const items = {};
170
+ if (config.agentId !== "") items["personal"] = UpstreamSchema.parse({
171
+ name: config.team.routerEndpoint ? "团队" : "个人知识",
172
+ agentId: config.agentId,
173
+ enabled: config.legacyEnabled,
174
+ routerEndpoint: config.team.routerEndpoint,
175
+ maintainerEndpoint: config.team.maintainerEndpoint,
176
+ keyEnv: config.team.keyEnv,
177
+ timeoutMs: config.team.timeoutMs
178
+ });
179
+ for (const connection of config.connections) {
180
+ const { id, ...value } = connection;
181
+ let key = id.toLowerCase();
182
+ while (items[key] !== void 0 || [
183
+ "data",
184
+ "skills",
185
+ "logs",
186
+ "tmp"
187
+ ].includes(key)) key = `${key}_copy`;
188
+ items[key] = UpstreamSchema.parse(value);
189
+ }
190
+ return items;
191
+ }
192
+ function activeUpstream(config) {
193
+ return config.upstream || "personal";
194
+ }
195
+ //#endregion
196
+ //#region src/dsh-adapter/session-binding.ts
197
+ const BindingSchema = z.strictObject({
198
+ schemaVersion: z.literal(1),
199
+ identity: z.string().regex(/^[0-9a-f]{64}$/)
200
+ });
201
+ const EligibilitySchema = z.strictObject({ schemaVersion: z.literal(1) });
202
+ const emptyIdentity = createHash("sha256").update("").digest("hex");
203
+ const SelectionSchema = z.strictObject({
204
+ schemaVersion: z.literal(1),
205
+ key: z.string(),
206
+ identity: z.string().regex(/^[0-9a-f]{64}$/),
207
+ prepared: z.boolean().optional()
208
+ });
209
+ const bindings = /* @__PURE__ */ new WeakMap();
210
+ const identityOf = (config) => createHash("sha256").update(config.agentId === "" ? "" : agentHomePath(config.home, config.agentId, activeUpstream(config))).digest("hex");
211
+ const selections = /* @__PURE__ */ new WeakMap();
212
+ const runningConfigurations = /* @__PURE__ */ new WeakMap();
213
+ const activations = /* @__PURE__ */ new WeakMap();
214
+ let activationSequence = 0;
215
+ const configurationActivation = (header) => activations.get(header) ?? 0;
216
+ function runningConfiguration(header) {
217
+ return runningConfigurations.get(header);
218
+ }
219
+ function rememberConfiguration(header, config) {
220
+ runningConfigurations.set(header, config);
221
+ activations.set(header, ++activationSequence);
222
+ }
223
+ function forgetConfiguration(header) {
224
+ runningConfigurations.delete(header);
225
+ activations.delete(header);
226
+ }
227
+ function decodeSelection(value) {
228
+ const parsed = SelectionSchema.safeParse(value);
229
+ return parsed.success ? parsed.data : {
230
+ schemaVersion: 1,
231
+ key: "invalid",
232
+ identity: "0".repeat(64)
233
+ };
234
+ }
235
+ function observeSelection(header, event) {
236
+ const record = pluginRecordOf(event);
237
+ if (record?.type === "plugin:acn/team-selection") selections.set(header, decodeSelection(record.data));
238
+ }
239
+ function restoreSessionBinding(header, events) {
240
+ const records = events.map(pluginRecordOf);
241
+ const values = records.filter((record) => record?.type === "plugin:acn/session-binding").map((record) => BindingSchema.safeParse(record?.data));
242
+ const first = values[0];
243
+ bindings.set(header, first?.success && values.every((value) => value.success && value.data.identity === first.data.identity) ? first.data.identity : null);
244
+ const selected = records.filter((record) => record?.type === "plugin:acn/team-selection").at(-1);
245
+ selections.set(header, selected === void 0 ? void 0 : decodeSelection(selected.data));
246
+ }
247
+ function sessionSelection(ctx, header) {
248
+ if (selections.has(header)) return selections.get(header);
249
+ const last = (ctx.sessions.get(header.id)?.snapshotEvents().map(pluginRecordOf).filter((record) => record?.type === "plugin:acn/team-selection") ?? []).at(-1);
250
+ const value = last === void 0 ? void 0 : decodeSelection(last.data);
251
+ selections.set(header, value);
252
+ return value;
253
+ }
254
+ function sessionHasWork(events) {
255
+ 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");
256
+ }
257
+ function sessionEligible(ctx, header, events = ctx.sessions.get(header.id)?.snapshotEvents()) {
258
+ return events?.some((event) => {
259
+ const record = pluginRecordOf(event);
260
+ 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;
261
+ }) ?? false;
262
+ }
263
+ function markSessionEligible(ctx, header) {
264
+ const session = ctx.sessions.get(header.id);
265
+ if (session === void 0 || session.firstLiveSeq > 0 || header.isSeeded || header.parentSession !== void 0 || sessionHasWork(session.snapshotEvents()) || sessionEligible(ctx, header)) return;
266
+ appendPluginRecord(session, "plugin:acn/session-eligibility", { schemaVersion: 1 });
267
+ }
268
+ function sessionUnbound(ctx, header, events) {
269
+ const seen = /* @__PURE__ */ new Set();
270
+ let current = header;
271
+ while (current !== void 0) {
272
+ if (seen.has(current.id)) return false;
273
+ seen.add(current.id);
274
+ const history = current === header && events !== void 0 ? events : ctx.sessions.get(current.id)?.snapshotEvents();
275
+ if (history === void 0) return current !== header;
276
+ for (const event of history) {
277
+ const record = pluginRecordOf(event);
278
+ if (record?.type === "plugin:acn/team-selection") return false;
279
+ if (record?.type === "plugin:acn/session-binding" && BindingSchema.safeParse(record.data).data?.identity !== emptyIdentity) return false;
280
+ }
281
+ current = current.parentSession === void 0 ? void 0 : ctx.sessions.get(current.parentSession)?.header;
282
+ }
283
+ return true;
284
+ }
285
+ function bindSession(ctx, config, header) {
286
+ if (config.agentId === "") return;
287
+ if (bindings.has(header)) return;
288
+ const session = ctx.sessions.get(header.id);
289
+ if (session === void 0) {
290
+ bindings.set(header, null);
291
+ return;
292
+ }
293
+ const records = session.snapshotEvents().map(pluginRecordOf).filter((record) => record?.type === "plugin:acn/session-binding");
294
+ if (records.length > 0) {
295
+ const values = records.map((record) => BindingSchema.safeParse(record?.data));
296
+ const first = values[0];
297
+ bindings.set(header, first?.success && values.every((value) => value.success && value.data.identity === first.data.identity) ? first.data.identity : null);
298
+ return;
299
+ }
300
+ const parent = header.parentSession === void 0 ? void 0 : ctx.sessions.get(header.parentSession);
301
+ const parentSelection = parent === void 0 ? void 0 : sessionSelection(ctx, parent.header);
302
+ if (session.firstLiveSeq === 0 && sessionSelection(ctx, header) === void 0 && parentSelection !== void 0) appendPluginRecord(session, "plugin:acn/team-selection", parentSelection);
303
+ const verifiedParent = parent !== void 0 && sessionAllowed(ctx, config, parent.header);
304
+ if (session.firstLiveSeq > 0 || !verifiedParent && (!sessionEligible(ctx, header) || sessionHasWork(session.snapshotEvents()) || header.parentSession !== void 0 || header.isSeeded)) {
305
+ bindings.set(header, null);
306
+ return;
307
+ }
308
+ const identity = identityOf(config);
309
+ bindings.set(header, identity);
310
+ try {
311
+ appendPluginRecord(session, "plugin:acn/session-binding", {
312
+ schemaVersion: 1,
313
+ identity
314
+ });
315
+ } catch (error) {
316
+ bindings.set(header, null);
317
+ throw error;
318
+ }
319
+ }
320
+ const sessionChanged = "ACN 会话身份与当前配置不一致,或缺少可验证的历史身份记录,请新建会话。旧会话不能访问当前身份的知识。";
321
+ const configurationBusy = "ACN 配置正在应用,请稍后重试。";
322
+ const unboundSession = "本会话未启用 ACN,聊天仍可继续。只有安装插件后新建且尚未发送消息的会话可选择工作配置;如需使用 ACN,请新建会话。";
323
+ function sessionAllowed(ctx, config, header) {
324
+ if (config.agentId === "") return true;
325
+ if (config.team.routerEndpoint && !config.legacyEnabled) return false;
326
+ const identity = identityOf(config);
327
+ const selected = sessionSelection(ctx, header);
328
+ if (selected !== void 0) return selected.identity === identity;
329
+ if (bindings.get(header) !== identity) return false;
330
+ if (config.sessionEpoch === 0) return true;
331
+ const seen = /* @__PURE__ */ new Set();
332
+ let current = header;
333
+ while (current !== void 0) {
334
+ if (current.createdAt <= config.sessionEpoch || seen.has(current.id)) return false;
335
+ seen.add(current.id);
336
+ if (current.parentSession === void 0) return true;
337
+ current = ctx.sessions.get(current.parentSession)?.header;
338
+ }
339
+ return false;
340
+ }
341
+ //#endregion
342
+ export { resolveConfig as C, activeUpstream as S, unboundSession as _, identityOf as a, UpstreamNameSchema as b, 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, ConfigError as v, upstreamsOf as w, UpstreamSchema as x, ConnectionSchema as y };
package/lib/store.js CHANGED
@@ -3,7 +3,7 @@ import { a as EntityStore, i as ClaimStore, n as ReportedSetsSchema, r as report
3
3
  import { t as TraceStore } from "./traces-CHBo8y1z.js";
4
4
  import { n as PendingUploadsSchema, r as UploadStore, t as ConsolidationDeliverySchema } from "./uploads-BCA2p92b.js";
5
5
  import { n as VersionedDocumentSchema, r as VersionedFileStore, t as SessionStateStore } from "./session-state-CYqUhC95.js";
6
- import { i as safeKey, n as agentHomePath, r as expandHomePath, t as AgentPaths } from "./paths-CDYV5UH9.js";
6
+ import { i as safeKey, n as agentHomePath, r as expandHomePath, t as AgentPaths } from "./paths-B7NI9Ano.js";
7
7
  import { n as ClaimEditStore, r as PendingClaimEditSchema, t as DisputeStore } from "./disputes-ByEmi43j.js";
8
8
  import { t as InboxStore } from "./inbox-2CugZZQm.js";
9
9
  //#region src/store/jobs.ts
@@ -374,6 +374,7 @@ async function structuredCall(options) {
374
374
  for (let attempt = 1; attempt <= config.structuredRetries; attempt += 1) {
375
375
  signal.throwIfAborted();
376
376
  for (let transport = 1; transport <= 3; transport += 1) {
377
+ signal.throwIfAborted();
377
378
  let response;
378
379
  const startedAt = Date.now();
379
380
  const timeout = AbortSignal.timeout(config.timeoutMs);
package/lib/team.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as TeamError } from "./errors-pPumDOGD.js";
2
- import { a as bypassProxy, i as TeamHttp, n as MaintainerClient, o as teamUrl, r as RouterClient, t as TeamFacade } from "./service-B7AI5jds.js";
2
+ import { a as bypassProxy, i as TeamHttp, n as MaintainerClient, o as teamUrl, r as RouterClient, t as TeamFacade } from "./service-BQaszW_v.js";
3
3
  export { MaintainerClient, RouterClient, TeamError, TeamFacade, TeamHttp, bypassProxy, teamUrl };
@@ -6,6 +6,7 @@ export declare function activityDetails(result: unknown): {
6
6
  counts: {
7
7
  [k: string]: number;
8
8
  };
9
+ entityIds: ((string & z.core.$brand<"ClaimId">) | (string & z.core.$brand<"TraceId">) | (string & z.core.$brand<"DisputeId">))[];
9
10
  summary: string;
10
11
  warnings: string[];
11
12
  incompleteCandidates: {
@@ -61,6 +62,7 @@ export declare function activityPage(rows: Activity[], options?: ActivityPage):
61
62
  claimIds: (string & z.core.$brand<"ClaimId">)[];
62
63
  reason: string;
63
64
  }[] | undefined;
65
+ entityIds?: ((string & z.core.$brand<"ClaimId">) | (string & z.core.$brand<"TraceId">) | (string & z.core.$brand<"DisputeId">))[] | undefined;
64
66
  entityId?: string | undefined;
65
67
  retryable?: boolean | undefined;
66
68
  acknowledged?: boolean | undefined;
@@ -0,0 +1,14 @@
1
+ import type { Activity, InteractionRequest } from '../interaction.js';
2
+ import type { InteractionApi } from './TeamSettingsPage.js';
3
+ import type { Copy } from './interaction-ui.js';
4
+ export declare function ActivityCard(props: {
5
+ item: Activity;
6
+ runtimeKey: string;
7
+ busy: boolean;
8
+ c: Copy;
9
+ api: InteractionApi;
10
+ action: (request: InteractionRequest) => void;
11
+ openSource?: ((id: string) => void) | undefined;
12
+ openClaim: (id: string, from: string) => void;
13
+ openComponents?: (() => void) | undefined;
14
+ }): import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,7 @@ import type { Copy } from './interaction-ui.js';
4
4
  export declare function activityKind(kind: string, c: Copy): string;
5
5
  export declare function activityState(item: Activity, c: Copy): string;
6
6
  export declare function activitySummary(item: Activity, c: Copy): string;
7
- export declare function ActivityDetails({ item, runtimeKey, busy, c, api, showSummary, action, openSource, openClaim, openComponents }: {
7
+ export declare function ActivityDetails({ item, runtimeKey, busy, c, showSummary, action, openClaim, openComponents }: {
8
8
  item: Activity;
9
9
  runtimeKey: string;
10
10
  busy: boolean;
@@ -1,7 +1,8 @@
1
1
  import type { SourceSession } from '../interaction.js';
2
2
  import type { InteractionApi } from './TeamSettingsPage.js';
3
3
  import type { Copy } from './interaction-ui.js';
4
- export declare function SourceSessionLink({ source, api, c, open }: {
4
+ export declare function SourceSessionLink({ source, api, c, open, label: customLabel }: {
5
+ label?: string | undefined;
5
6
  source: SourceSession;
6
7
  api: InteractionApi;
7
8
  c: Copy;
@@ -24,7 +24,5 @@ export declare function settingsUpstreams(values: ConfigurationValues): Record<s
24
24
  maintainerEndpoint: string;
25
25
  keyEnv: string;
26
26
  timeoutMs: number;
27
- legacyStorage?: "base" | "personal" | "connection" | undefined;
28
- legacyKey?: string | undefined;
29
27
  }>;
30
28
  export declare function TeamSettingsPage({ api, t, openKnowledge, initialTab, openPlugins }: TeamSettingsProps): import("react/jsx-runtime").JSX.Element;