zcode-acp-server 0.78.0 → 0.79.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.
package/README.md CHANGED
@@ -353,7 +353,7 @@ Thanks to everyone who has contributed (updated automatically from the
353
353
  <a href="https://github.com/william0wang/zcode-acp/graphs/contributors">
354
354
  <!-- release-please re-stamps &v= on every release: the new URL busts the
355
355
  contrib.rocks and GitHub camo image caches. -->
356
- <img src="https://contrib.rocks/image?repo=william0wang/zcode-acp&v=0.78.0" alt="Contributors" /> <!-- x-release-please-version -->
356
+ <img src="https://contrib.rocks/image?repo=william0wang/zcode-acp&v=0.79.1" alt="Contributors" /> <!-- x-release-please-version -->
357
357
  </a>
358
358
 
359
359
  ## Related Projects
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Bridge-side remote-close record (ADR-0006 persistence amendment).
3
+ *
4
+ * A remote close retires the conversation from discovery with an IN-MEMORY
5
+ * stamp (`server.discoveryRetiredAt`) — and a serve-origin bridge then
6
+ * EXITS itself (last conversation closed), so the stamp dies with the
7
+ * process. When the hub incubates the next serve bridge and a client's
8
+ * reconnect ladder session/loads the conversation, the fresh process has no
9
+ * retirement memory: the load re-arms discovery, the heartbeat re-advertises
10
+ * the sid, the hub clears its close tombstone, and the conversation the user
11
+ * closed resurrects on every surface (observed live 2026-10-28: closed
12
+ * 00:48, resurrected by an auto load at 01:07 with a real turn).
13
+ *
14
+ * This store is the durable half of the retirement: the close endpoint
15
+ * records EVERY id spelling of the conversation (editor aliases + backend
16
+ * sess_ id), the auto-load retirement gate reads it (`loadSession`), and
17
+ * genuine use (`markSessionActive` — a prompt, a user-intent load) clears
18
+ * it, preserving ADR-0006's self-heal: touching the session reopens it.
19
+ *
20
+ * Same durability rules as the lazy-alias store: a tiny JSON file under
21
+ * ~/.zcode/v2 shared by every bridge process, written only via temp+rename.
22
+ * Best-effort by design — read failures read as "nothing closed", write
23
+ * failures are logged and simply do not stick.
24
+ */
25
+ /**
26
+ * True when this id spelling belongs to a remotely closed conversation the
27
+ * user has not touched since (within the TTL). The auto-load retirement gate
28
+ * consults this; a USER-intent load or real use clears the record instead.
29
+ */
30
+ export declare function isClosedSessionId(sid: string | undefined): boolean;
31
+ /**
32
+ * Record every id spelling of a remotely closed conversation (the close
33
+ * endpoint's alias set plus the backend sess_ id). TTL-expired entries are
34
+ * pruned at write.
35
+ */
36
+ export declare function recordClosedSessionIds(sids: Array<string | undefined>): void;
37
+ /**
38
+ * Clear the close record for a conversation's id spellings — genuine use
39
+ * (`markSessionActive`): a prompt turn or a user-intent load reopens the
40
+ * conversation and the next serve-bridge respawn must not re-retire it.
41
+ * No-op (no write) when nothing is recorded.
42
+ */
43
+ export declare function clearClosedSessionIds(sids: Array<string | undefined>): void;
44
+ //# sourceMappingURL=closed-sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closed-sessions.d.ts","sourceRoot":"","sources":["../src/closed-sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA0DH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAIlE;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,CAU5E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,CAY3E"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Bridge-side remote-close record (ADR-0006 persistence amendment).
3
+ *
4
+ * A remote close retires the conversation from discovery with an IN-MEMORY
5
+ * stamp (`server.discoveryRetiredAt`) — and a serve-origin bridge then
6
+ * EXITS itself (last conversation closed), so the stamp dies with the
7
+ * process. When the hub incubates the next serve bridge and a client's
8
+ * reconnect ladder session/loads the conversation, the fresh process has no
9
+ * retirement memory: the load re-arms discovery, the heartbeat re-advertises
10
+ * the sid, the hub clears its close tombstone, and the conversation the user
11
+ * closed resurrects on every surface (observed live 2026-10-28: closed
12
+ * 00:48, resurrected by an auto load at 01:07 with a real turn).
13
+ *
14
+ * This store is the durable half of the retirement: the close endpoint
15
+ * records EVERY id spelling of the conversation (editor aliases + backend
16
+ * sess_ id), the auto-load retirement gate reads it (`loadSession`), and
17
+ * genuine use (`markSessionActive` — a prompt, a user-intent load) clears
18
+ * it, preserving ADR-0006's self-heal: touching the session reopens it.
19
+ *
20
+ * Same durability rules as the lazy-alias store: a tiny JSON file under
21
+ * ~/.zcode/v2 shared by every bridge process, written only via temp+rename.
22
+ * Best-effort by design — read failures read as "nothing closed", write
23
+ * failures are logged and simply do not stick.
24
+ */
25
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
26
+ import path from "node:path";
27
+ import process from "node:process";
28
+ import { warn, zcodeHomeDir } from "./utils.js";
29
+ /** Store file lives next to the lazy-alias store under ~/.zcode/v2/. */
30
+ const STORE_FILENAME = "acp-closed-sessions.json";
31
+ /**
32
+ * Entries older than this expire: a conversation closed this long ago
33
+ * without a single bridge-side touch stays closed in any practical sense,
34
+ * and the expiry bounds staleness mistakes (a desktop-side reopen that never
35
+ * passed through a bridge would otherwise keep the App's tab retired
36
+ * forever).
37
+ */
38
+ const TTL_MS = 30 * 24 * 60 * 60 * 1000;
39
+ /** Resolved at call time so tests can stub HOME/ZCODE_HOME without re-importing. */
40
+ function storePath() {
41
+ return path.join(zcodeHomeDir(), "v2", STORE_FILENAME);
42
+ }
43
+ function readTable() {
44
+ try {
45
+ const p = storePath();
46
+ if (!existsSync(p))
47
+ return {};
48
+ const raw = JSON.parse(readFileSync(p, "utf8"));
49
+ if (typeof raw !== "object" || raw === null)
50
+ return {};
51
+ const out = {};
52
+ for (const [sid, at] of Object.entries(raw)) {
53
+ if (typeof at === "number")
54
+ out[sid] = at;
55
+ }
56
+ return out;
57
+ }
58
+ catch {
59
+ // Corrupt or unreadable reads as nothing closed — never fatal.
60
+ return {};
61
+ }
62
+ }
63
+ function persist(table) {
64
+ try {
65
+ const p = storePath();
66
+ const dir = path.dirname(p);
67
+ mkdirSync(dir, { recursive: true });
68
+ const tmp = `${p}.tmp-${process.pid}`;
69
+ writeFileSync(tmp, JSON.stringify(table, null, 2));
70
+ renameSync(tmp, p);
71
+ }
72
+ catch (e) {
73
+ warn(`closed-sessions: store write failed ` +
74
+ `(${e instanceof Error ? e.message : String(e)}) — the close record will not stick`);
75
+ }
76
+ }
77
+ /**
78
+ * True when this id spelling belongs to a remotely closed conversation the
79
+ * user has not touched since (within the TTL). The auto-load retirement gate
80
+ * consults this; a USER-intent load or real use clears the record instead.
81
+ */
82
+ export function isClosedSessionId(sid) {
83
+ if (typeof sid !== "string" || sid.length === 0)
84
+ return false;
85
+ const at = readTable()[sid];
86
+ return at !== undefined && Date.now() - at <= TTL_MS;
87
+ }
88
+ /**
89
+ * Record every id spelling of a remotely closed conversation (the close
90
+ * endpoint's alias set plus the backend sess_ id). TTL-expired entries are
91
+ * pruned at write.
92
+ */
93
+ export function recordClosedSessionIds(sids) {
94
+ const ids = sids.filter((sid) => typeof sid === "string" && sid.length > 0);
95
+ if (ids.length === 0)
96
+ return;
97
+ const table = readTable();
98
+ const now = Date.now();
99
+ for (const [sid, at] of Object.entries(table)) {
100
+ if (now - at > TTL_MS)
101
+ delete table[sid];
102
+ }
103
+ for (const sid of new Set(ids))
104
+ table[sid] = now;
105
+ persist(table);
106
+ }
107
+ /**
108
+ * Clear the close record for a conversation's id spellings — genuine use
109
+ * (`markSessionActive`): a prompt turn or a user-intent load reopens the
110
+ * conversation and the next serve-bridge respawn must not re-retire it.
111
+ * No-op (no write) when nothing is recorded.
112
+ */
113
+ export function clearClosedSessionIds(sids) {
114
+ const ids = sids.filter((sid) => typeof sid === "string" && sid.length > 0);
115
+ if (ids.length === 0)
116
+ return;
117
+ const table = readTable();
118
+ let touched = false;
119
+ for (const sid of new Set(ids)) {
120
+ if (sid in table) {
121
+ delete table[sid];
122
+ touched = true;
123
+ }
124
+ }
125
+ if (touched)
126
+ persist(table);
127
+ }
128
+ //# sourceMappingURL=closed-sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"closed-sessions.js","sourceRoot":"","sources":["../src/closed-sessions.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  {
2
- "fingerprint": "b8f341b7e3c5eb5cdad2dc04f97cfc445ea3a7a7581887f9f656eacbc64c3970",
3
- "fileCount": 130
2
+ "fingerprint": "eec36210dd1b4b8ecaddfcb13f30e97baf59386d617d6957088dac4dffee6fb0",
3
+ "fileCount": 131
4
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/handlers/session.ts"],"names":[],"mappings":"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"}
@@ -33,7 +33,8 @@ import { effectiveWorkflowGate, effectiveWorkflowGateNow, ensureWorkflowPolicyPu
33
33
  import { messages } from "../i18n.js";
34
34
  import { lookupLazySession, lookupModelChoiceByZcodeSid, recordMaterializedSession, rememberLazySession, } from "../lazy-sessions.js";
35
35
  import { refreshTerminalTabTitle } from "../terminal-title.js";
36
- import { buildDiffContent, EventTranslator, extractLocations, formatTurnError, isBackendLostError, isTransientTurnError, ProjectionDiffer, } from "../translators/index.js";
36
+ import { isClosedSessionId } from "../closed-sessions.js";
37
+ import { buildDiffContent, EventTranslator, extractLocations, formatTurnError, isBackendLostError, isGatewayBlipTurnError, isTransientTurnError, ProjectionDiffer, } from "../translators/index.js";
37
38
  import { clientConnectionRoot, log, warn, zcodeHomeDir } from "../utils.js";
38
39
  import { dispatchEvent } from "./dispatch.js";
39
40
  import { emitSessionTurnState, sendAvailableCommandsDeferred, sendSessionUpdate, sendTextChunk, withReplayBatch, } from "./io.js";
@@ -1257,8 +1258,14 @@ export async function loadSession(server, params, cx, opts = {}) {
1257
1258
  // on every surface and the auto-409 gate disarms with it. The response
1258
1259
  // discloses the suppression via `_meta.zcode.sessionClosed: true` so the
1259
1260
  // client can retire its tab locally. "user" (the default — old clients)
1260
- // keeps the manual-reopen re-arm exactly as before.
1261
- const retiredForAuto = readLoadIntent(params) === "auto" && server.isDiscoveryRetired(acpSid);
1261
+ // keeps the manual-reopen re-arm exactly as before. Retirement is checked
1262
+ // BOTH in memory AND in the durable close record: a serve-origin bridge
1263
+ // EXITS on last close, so the hub-incubated successor process has no
1264
+ // in-memory stamp — without the durable lookup a reconnect ladder's auto
1265
+ // load resurrected the closed conversation on the fresh bridge (observed
1266
+ // 2026-10-28: closed 00:48, auto-loaded back to life 01:07).
1267
+ const retiredForAuto = readLoadIntent(params) === "auto" &&
1268
+ (server.isDiscoveryRetired(acpSid) || isClosedSessionId(acpSid) || isClosedSessionId(zcodeSid));
1262
1269
  if (!alreadyLive) {
1263
1270
  // Same mcpServers contract as resume: the client may re-declare them on
1264
1271
  // load; a stored set keeps riding along when it doesn't (#193).
@@ -1876,17 +1883,32 @@ export async function runOneTurn(server, opts) {
1876
1883
  suppressRetryNotice = true;
1877
1884
  continue;
1878
1885
  }
1879
- // Only a transient TurnFailedError is retryable; everything else (send
1880
- // failures, non-transient turn errors, exhausted retries, cancellation)
1881
- // propagates to the caller.
1886
+ // Transient failures and one-shot gateway blips are retried; everything
1887
+ // else (send failures, terminal turn errors, cancellation) propagates
1888
+ // to the caller.
1882
1889
  if (e instanceof TurnFailedError) {
1883
1890
  const transient = isTransientTurnError(e.turnError);
1884
- if (attempt < MAX_TURN_ATTEMPTS && !turn.cancelled && transient) {
1891
+ // A relay gateway's transient fault arrives as a request-failure
1892
+ // cause code the upstream classifier marked non-retryable — its
1893
+ // verdict judges the request shape, not the gateway's health
1894
+ // (observed 2026-10-28: intermittent 400 invalid_request_error from
1895
+ // a forwarding gateway, resend succeeded). Give those a bounded
1896
+ // resend too; quota/context-exceeded/model-not-found stay terminal.
1897
+ const gatewayBlip = !transient && isGatewayBlipTurnError(e.turnError);
1898
+ if (attempt < MAX_TURN_ATTEMPTS && !turn.cancelled && (transient || gatewayBlip)) {
1885
1899
  lastTurnError = e.turnError;
1886
1900
  continue;
1887
1901
  }
1888
- if (!transient)
1902
+ if (!transient && !gatewayBlip)
1889
1903
  throw turnFailureRequestError(e);
1904
+ // Retries exhausted on a transient/gateway-blip failure: degrade
1905
+ // gracefully below (user-visible notice + end_turn, goal-loop
1906
+ // pauses via its structured throw) instead of a hard error that
1907
+ // stops the session. A cancelled turn keeps the raw propagate.
1908
+ if (turn.cancelled)
1909
+ throw e;
1910
+ lastTurnError = e.turnError;
1911
+ break;
1890
1912
  }
1891
1913
  throw e;
1892
1914
  }