zcode-acp-server 0.2.0 → 0.3.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 (64) hide show
  1. package/README.md +101 -15
  2. package/README.zh-CN.md +68 -13
  3. package/dist/bin/hub.d.ts +16 -0
  4. package/dist/bin/hub.d.ts.map +1 -0
  5. package/dist/bin/hub.js +41 -0
  6. package/dist/bin/hub.js.map +1 -0
  7. package/dist/handlers/account.d.ts +43 -0
  8. package/dist/handlers/account.d.ts.map +1 -0
  9. package/dist/handlers/account.js +59 -0
  10. package/dist/handlers/account.js.map +1 -0
  11. package/dist/handlers/io.d.ts +20 -1
  12. package/dist/handlers/io.d.ts.map +1 -1
  13. package/dist/handlers/io.js +57 -2
  14. package/dist/handlers/io.js.map +1 -1
  15. package/dist/handlers/replay.d.ts +79 -0
  16. package/dist/handlers/replay.d.ts.map +1 -0
  17. package/dist/handlers/replay.js +252 -0
  18. package/dist/handlers/replay.js.map +1 -0
  19. package/dist/handlers/session.d.ts.map +1 -1
  20. package/dist/handlers/session.js +64 -65
  21. package/dist/handlers/session.js.map +1 -1
  22. package/dist/handlers/slash.d.ts +23 -1
  23. package/dist/handlers/slash.d.ts.map +1 -1
  24. package/dist/handlers/slash.js +67 -6
  25. package/dist/handlers/slash.js.map +1 -1
  26. package/dist/index.js +47 -17
  27. package/dist/index.js.map +1 -1
  28. package/dist/remote/broadcast.d.ts +47 -0
  29. package/dist/remote/broadcast.d.ts.map +1 -0
  30. package/dist/remote/broadcast.js +121 -0
  31. package/dist/remote/broadcast.js.map +1 -0
  32. package/dist/remote/config.d.ts +32 -0
  33. package/dist/remote/config.d.ts.map +1 -0
  34. package/dist/remote/config.js +65 -0
  35. package/dist/remote/config.js.map +1 -0
  36. package/dist/remote/endpoint.d.ts +30 -0
  37. package/dist/remote/endpoint.d.ts.map +1 -0
  38. package/dist/remote/endpoint.js +213 -0
  39. package/dist/remote/endpoint.js.map +1 -0
  40. package/dist/remote/hub-server.d.ts +41 -0
  41. package/dist/remote/hub-server.d.ts.map +1 -0
  42. package/dist/remote/hub-server.js +346 -0
  43. package/dist/remote/hub-server.js.map +1 -0
  44. package/dist/server.d.ts +41 -7
  45. package/dist/server.d.ts.map +1 -1
  46. package/dist/server.js +69 -11
  47. package/dist/server.js.map +1 -1
  48. package/dist/utils.d.ts +1 -1
  49. package/dist/utils.d.ts.map +1 -1
  50. package/dist/utils.js +17 -1
  51. package/dist/utils.js.map +1 -1
  52. package/docs/ARCHITECTURE.md +47 -15
  53. package/docs/BACKLOG.md +3 -1
  54. package/docs/DEVELOPMENT.md +26 -0
  55. package/docs/PROTOCOL.md +67 -27
  56. package/docs/REMOTE-CLIENTS.md +260 -0
  57. package/docs/REPLAY-GUIDE.md +131 -0
  58. package/docs/TROUBLESHOOTING.md +39 -6
  59. package/docs/adr/0001-bridge-lifetime-follows-primary-client.md +14 -0
  60. package/docs/adr/0002-stateless-hub-over-per-bridge-acp-endpoints.md +23 -0
  61. package/docs/adr/0003-tail-replay-meta-and-cursor-pagination.md +40 -0
  62. package/docs/proposals/0001-tail-session-replay.md +136 -0
  63. package/docs/proposals/0002-plan-quota-usage.md +81 -0
  64. package/package.json +5 -2
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Tail replay kernel — slicing, cursor pagination, and the `session/load`
3
+ * replay/`session/load_earlier` handlers (Proposal 0001 / ADR-0003).
4
+ *
5
+ * session/load replays history as session/update notifications; for long
6
+ * sessions that cost is O(full history) on every attach and reconnect. The
7
+ * helpers here slice the fetched messages into turn-aligned batches and page
8
+ * backwards with an opaque cursor. Batches are sent under the per-session
9
+ * replay lock (`withReplayBatch` in io.ts) so a batch never interleaves with
10
+ * live-turn updates for the same session; `replayMessages` is the one sender
11
+ * that bypasses the per-message lock — it only runs inside a batch.
12
+ */
13
+ import type * as acp from "@agentclientprotocol/sdk";
14
+ import type { ZcodeMessage } from "../backend/types.js";
15
+ import type { ZcodeAcpServer } from "../server.js";
16
+ /** Upper bound for a requested tail/page size (values above clamp to this). */
17
+ export declare const MAX_REPLAY_LIMIT = 500;
18
+ /** Page size for `session/load_earlier` when the request omits `limit`. */
19
+ export declare const DEFAULT_EARLIER_LIMIT = 50;
20
+ /** Wire metadata describing one delivered batch (additive-only over time). */
21
+ export interface ReplayMeta {
22
+ cursor: string;
23
+ hasMore: boolean;
24
+ replayedMessages: number;
25
+ replayedTurns: number;
26
+ totalMessages: number;
27
+ totalTurns: number;
28
+ }
29
+ export interface ReplaySlice {
30
+ batch: ZcodeMessage[];
31
+ meta: ReplayMeta;
32
+ }
33
+ /** `session/load_earlier` params (top-level — our parser, not an ACP spec method). */
34
+ export interface LoadEarlierParams {
35
+ sessionId: string;
36
+ before?: string;
37
+ limit?: number;
38
+ }
39
+ /**
40
+ * Slice the last `limit` messages, aligned back to the start of the turn
41
+ * containing the oldest one — never a mid-turn cut. `limit: 0` attaches with
42
+ * metadata only (cursor anchors at the end of history).
43
+ */
44
+ export declare function sliceTail(messages: ZcodeMessage[], limit: number): ReplaySlice;
45
+ /** Full-history slice (no `_meta.zcode.limit` on session/load). */
46
+ export declare function fullSlice(messages: ZcodeMessage[]): ReplaySlice;
47
+ /**
48
+ * Slice up to `limit` messages strictly older than the `before` cursor.
49
+ * The cursor points into a prefix of history, so turns appended after it was
50
+ * minted keep it valid; only a history that shrank (compaction/truncation)
51
+ * throws `cursor expired` — clients map that to a full re-`session/load`.
52
+ */
53
+ export declare function sliceBefore(messages: ZcodeMessage[], before: string, limit: number): ReplaySlice;
54
+ /**
55
+ * Read the tail limit from `session/load`'s `_meta.zcode.limit`. The SDK's
56
+ * zod params schema strips unknown top-level keys, so bridge extensions ride
57
+ * in `_meta` (ADR-0003). Returns null when absent/non-finite = full replay.
58
+ */
59
+ export declare function readTailLimit(params: acp.LoadSessionRequest): number | null;
60
+ /** Fetch session/messages from zcode (the bridge's only history source). */
61
+ export declare function fetchMessages(server: ZcodeAcpServer, zcodeSid: string): Promise<ZcodeMessage[]>;
62
+ /**
63
+ * Replay messages as session/update notifications, oldest → newest.
64
+ *
65
+ * MUST run inside `withReplayBatch` for the session: this is the one sender
66
+ * that bypasses the per-message lock in sendSessionUpdate (the batch already
67
+ * holds it), which is what makes the batch atomic against live dispatch.
68
+ */
69
+ export declare function replayMessages(cx: acp.AgentContext, acpSid: string, messages: ZcodeMessage[]): Promise<number>;
70
+ /**
71
+ * `session/load_earlier` — deliver one page of history strictly older than
72
+ * the `before` cursor, oldest → newest (clients prepend). Requires the
73
+ * session to already be attached in this bridge; pagination never triggers
74
+ * an implicit backend resume.
75
+ */
76
+ export declare function loadEarlier(server: ZcodeAcpServer, params: LoadEarlierParams, cx: acp.AgentContext): Promise<{
77
+ replayMeta: ReplayMeta;
78
+ }>;
79
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/handlers/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,KAAK,GAAG,MAAM,0BAA0B,CAAC;AAErD,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,qBAAqB,CAAC;AAC7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAInD,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,2EAA2E;AAC3E,eAAO,MAAM,qBAAqB,KAAK,CAAC;AAExC,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAqFD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAW9E;AAED,mEAAmE;AACnE,wBAAgB,SAAS,CAAC,QAAQ,EAAE,YAAY,EAAE,GAAG,WAAW,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAchG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAK3E;AAED,4EAA4E;AAC5E,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,YAAY,EAAE,CAAC,CAWzB;AAYD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,GAAG,CAAC,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,YAAY,EAAE,GACvB,OAAO,CAAC,MAAM,CAAC,CA+DjB;AAED;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,iBAAiB,EACzB,EAAE,EAAE,GAAG,CAAC,YAAY,GACnB,OAAO,CAAC;IAAE,UAAU,EAAE,UAAU,CAAA;CAAE,CAAC,CAarC"}
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Tail replay kernel — slicing, cursor pagination, and the `session/load`
3
+ * replay/`session/load_earlier` handlers (Proposal 0001 / ADR-0003).
4
+ *
5
+ * session/load replays history as session/update notifications; for long
6
+ * sessions that cost is O(full history) on every attach and reconnect. The
7
+ * helpers here slice the fetched messages into turn-aligned batches and page
8
+ * backwards with an opaque cursor. Batches are sent under the per-session
9
+ * replay lock (`withReplayBatch` in io.ts) so a batch never interleaves with
10
+ * live-turn updates for the same session; `replayMessages` is the one sender
11
+ * that bypasses the per-message lock — it only runs inside a batch.
12
+ */
13
+ import { randomUUID } from "node:crypto";
14
+ import { log } from "../utils.js";
15
+ import { throwError, withReplayBatch } from "./io.js";
16
+ /** Upper bound for a requested tail/page size (values above clamp to this). */
17
+ export const MAX_REPLAY_LIMIT = 500;
18
+ /** Page size for `session/load_earlier` when the request omits `limit`. */
19
+ export const DEFAULT_EARLIER_LIMIT = 50;
20
+ /**
21
+ * Indices where a turn starts: every user message, plus 0 so leading
22
+ * non-user messages (system preambles) belong to the first turn.
23
+ */
24
+ function turnStarts(messages) {
25
+ const starts = messages.length > 0 ? [0] : [];
26
+ messages.forEach((m, i) => {
27
+ if (m.info?.role === "user" && i > 0)
28
+ starts.push(i);
29
+ });
30
+ return starts;
31
+ }
32
+ /** Count of turn starts inside [start, end). */
33
+ function turnsInRange(starts, start, end) {
34
+ return starts.filter((s) => s >= start && s < end).length;
35
+ }
36
+ function encodeCursor(messages, index, totalTurns) {
37
+ const anchor = messages[index]?.info?.id;
38
+ const payload = { v: 1, index, totalTurns };
39
+ if (anchor)
40
+ payload.id = anchor;
41
+ return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
42
+ }
43
+ function decodeCursor(before) {
44
+ try {
45
+ const raw = JSON.parse(Buffer.from(before, "base64url").toString("utf8"));
46
+ if (raw?.v !== 1 ||
47
+ !Number.isInteger(raw.index) ||
48
+ raw.index < 0 ||
49
+ !Number.isInteger(raw.totalTurns)) {
50
+ throw new Error("bad shape");
51
+ }
52
+ return raw;
53
+ }
54
+ catch {
55
+ // Garbage or foreign cursors are indistinguishable from expired ones.
56
+ return throwError(-32602, "cursor expired");
57
+ }
58
+ }
59
+ function buildSlice(messages, starts, start, end) {
60
+ const totalTurns = starts.length;
61
+ return {
62
+ batch: messages.slice(start, end),
63
+ meta: {
64
+ cursor: encodeCursor(messages, start, totalTurns),
65
+ hasMore: start > 0,
66
+ replayedMessages: end - start,
67
+ replayedTurns: turnsInRange(starts, start, end),
68
+ totalMessages: messages.length,
69
+ totalTurns,
70
+ },
71
+ };
72
+ }
73
+ /** The greatest turn start at or before `pos` (0 when none — starts include 0). */
74
+ function alignToTurnStart(starts, pos) {
75
+ let aligned = 0;
76
+ for (const s of starts) {
77
+ if (s <= pos)
78
+ aligned = s;
79
+ else
80
+ break;
81
+ }
82
+ return aligned;
83
+ }
84
+ function clampLimit(limit) {
85
+ return Math.max(0, Math.min(Math.floor(limit), MAX_REPLAY_LIMIT));
86
+ }
87
+ /**
88
+ * Slice the last `limit` messages, aligned back to the start of the turn
89
+ * containing the oldest one — never a mid-turn cut. `limit: 0` attaches with
90
+ * metadata only (cursor anchors at the end of history).
91
+ */
92
+ export function sliceTail(messages, limit) {
93
+ const starts = turnStarts(messages);
94
+ const clamped = clampLimit(limit);
95
+ if (clamped === 0) {
96
+ // Metadata-only attach: an empty batch whose cursor anchors at the end of
97
+ // history, so load_earlier pages the whole tail.
98
+ return buildSlice(messages, starts, messages.length, messages.length);
99
+ }
100
+ if (clamped >= messages.length)
101
+ return buildSlice(messages, starts, 0, messages.length);
102
+ const start = alignToTurnStart(starts, messages.length - clamped);
103
+ return buildSlice(messages, starts, start, messages.length);
104
+ }
105
+ /** Full-history slice (no `_meta.zcode.limit` on session/load). */
106
+ export function fullSlice(messages) {
107
+ return buildSlice(messages, turnStarts(messages), 0, messages.length);
108
+ }
109
+ /**
110
+ * Slice up to `limit` messages strictly older than the `before` cursor.
111
+ * The cursor points into a prefix of history, so turns appended after it was
112
+ * minted keep it valid; only a history that shrank (compaction/truncation)
113
+ * throws `cursor expired` — clients map that to a full re-`session/load`.
114
+ */
115
+ export function sliceBefore(messages, before, limit) {
116
+ const starts = turnStarts(messages);
117
+ const cur = decodeCursor(before);
118
+ if (cur.index > messages.length || cur.totalTurns > starts.length) {
119
+ return throwError(-32602, "cursor expired");
120
+ }
121
+ if (cur.id != null && cur.index < messages.length && messages[cur.index].info?.id !== cur.id) {
122
+ return throwError(-32602, "cursor expired");
123
+ }
124
+ const end = cur.index;
125
+ if (end === 0)
126
+ return buildSlice(messages, starts, 0, 0);
127
+ const clamped = clampLimit(limit);
128
+ const start = clamped === 0 ? end : alignToTurnStart(starts, Math.max(0, end - clamped));
129
+ return buildSlice(messages, starts, start, end);
130
+ }
131
+ /**
132
+ * Read the tail limit from `session/load`'s `_meta.zcode.limit`. The SDK's
133
+ * zod params schema strips unknown top-level keys, so bridge extensions ride
134
+ * in `_meta` (ADR-0003). Returns null when absent/non-finite = full replay.
135
+ */
136
+ export function readTailLimit(params) {
137
+ const zcode = params._meta?.zcode;
138
+ const raw = zcode?.limit;
139
+ if (typeof raw !== "number" || !Number.isFinite(raw))
140
+ return null;
141
+ return clampLimit(raw);
142
+ }
143
+ /** Fetch session/messages from zcode (the bridge's only history source). */
144
+ export async function fetchMessages(server, zcodeSid) {
145
+ const backend = server.ensureBackend();
146
+ const resp = await backend.request(server.nextId(), "session/messages", { sessionId: zcodeSid }, 8000);
147
+ if (resp.error)
148
+ return [];
149
+ const result = (resp.result ?? {});
150
+ return result.messages ?? [];
151
+ }
152
+ /**
153
+ * Strip harness-injected reminder blocks from user text. The agent runtime
154
+ * appends `<system-reminder>…</system-reminder>` blocks (TodoWrite nudges,
155
+ * context handoffs) to user turns as context plumbing — they are not user
156
+ * speech, and replaying them verbatim makes clients render them as user input.
157
+ */
158
+ function stripSystemReminders(text) {
159
+ return text.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").trim();
160
+ }
161
+ /**
162
+ * Replay messages as session/update notifications, oldest → newest.
163
+ *
164
+ * MUST run inside `withReplayBatch` for the session: this is the one sender
165
+ * that bypasses the per-message lock in sendSessionUpdate (the batch already
166
+ * holds it), which is what makes the batch atomic against live dispatch.
167
+ */
168
+ export async function replayMessages(cx, acpSid, messages) {
169
+ let replayed = 0;
170
+ for (const m of messages) {
171
+ const info = m.info ?? {};
172
+ const role = info.role;
173
+ const mid = info.id ?? `hist_${randomUUID().slice(0, 12)}`;
174
+ for (const p of m.parts ?? []) {
175
+ if (!p || typeof p !== "object")
176
+ continue;
177
+ const ptype = p.type;
178
+ if (ptype === "text") {
179
+ let text = p.text ?? "";
180
+ if (!text)
181
+ continue;
182
+ if (role === "user") {
183
+ text = stripSystemReminders(text);
184
+ if (!text)
185
+ continue;
186
+ }
187
+ await cx.notify("session/update", {
188
+ sessionId: acpSid,
189
+ update: {
190
+ sessionUpdate: role === "user" ? "user_message_chunk" : "agent_message_chunk",
191
+ content: { type: "text", text },
192
+ messageId: mid,
193
+ },
194
+ });
195
+ }
196
+ else if (ptype === "reasoning") {
197
+ const rp = p;
198
+ const text = rp.text ?? rp.content ?? "";
199
+ if (text) {
200
+ await cx.notify("session/update", {
201
+ sessionId: acpSid,
202
+ update: {
203
+ sessionUpdate: "agent_thought_chunk",
204
+ content: { type: "text", text },
205
+ messageId: `thought_${mid}`,
206
+ },
207
+ });
208
+ }
209
+ }
210
+ else if (ptype === "tool") {
211
+ const tp = p;
212
+ const title = tp.title ?? tp.tool ?? "tool call";
213
+ const histToolName = tp.tool ?? "";
214
+ await cx.notify("session/update", {
215
+ sessionId: acpSid,
216
+ update: {
217
+ sessionUpdate: "tool_call",
218
+ toolCallId: tp.id ?? `histtool_${randomUUID().slice(0, 8)}`,
219
+ title,
220
+ kind: "other",
221
+ status: tp.status ?? "completed",
222
+ ...(histToolName ? { _meta: { claudeCode: { toolName: histToolName } } } : {}),
223
+ },
224
+ });
225
+ }
226
+ // patch / step-start / other: skipped (history replay focuses on text + tool summary)
227
+ }
228
+ replayed += 1;
229
+ }
230
+ return replayed;
231
+ }
232
+ /**
233
+ * `session/load_earlier` — deliver one page of history strictly older than
234
+ * the `before` cursor, oldest → newest (clients prepend). Requires the
235
+ * session to already be attached in this bridge; pagination never triggers
236
+ * an implicit backend resume.
237
+ */
238
+ export async function loadEarlier(server, params, cx) {
239
+ const acpSid = params.sessionId;
240
+ const zcodeSid = server.resolveSid(acpSid);
241
+ if (!zcodeSid) {
242
+ return throwError(-32602, "session not registered — attach via session/load first");
243
+ }
244
+ if (!params.before)
245
+ return throwError(-32602, "before (cursor) required");
246
+ const messages = await fetchMessages(server, zcodeSid);
247
+ const slice = sliceBefore(messages, params.before, params.limit ?? DEFAULT_EARLIER_LIMIT);
248
+ await withReplayBatch(acpSid, () => replayMessages(cx, acpSid, slice.batch));
249
+ log(`session/load_earlier: ${slice.meta.replayedMessages} messages before cursor`);
250
+ return { replayMeta: slice.meta };
251
+ }
252
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/handlers/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAMzC,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEtD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AACpC,2EAA2E;AAC3E,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AA+BxC;;;GAGG;AACH,SAAS,UAAU,CAAC,QAAwB;IAC1C,MAAM,MAAM,GAAa,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxB,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,gDAAgD;AAChD,SAAS,YAAY,CAAC,MAAgB,EAAE,KAAa,EAAE,GAAW;IAChE,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,MAAM,CAAC;AAC5D,CAAC;AAED,SAAS,YAAY,CAAC,QAAwB,EAAE,KAAa,EAAE,UAAkB;IAC/E,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;IACzC,MAAM,OAAO,GAAkB,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC3D,IAAI,MAAM;QAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC;IAChC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,YAAY,CAAC,MAAc;IAClC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAkB,CAAC;QAC3F,IACE,GAAG,EAAE,CAAC,KAAK,CAAC;YACZ,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;YAC5B,GAAG,CAAC,KAAK,GAAG,CAAC;YACb,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,EACjC,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,sEAAsE;QACtE,OAAO,UAAU,CAAC,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CACjB,QAAwB,EACxB,MAAgB,EAChB,KAAa,EACb,GAAW;IAEX,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IACjC,OAAO;QACL,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC;QACjC,IAAI,EAAE;YACJ,MAAM,EAAE,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,UAAU,CAAC;YACjD,OAAO,EAAE,KAAK,GAAG,CAAC;YAClB,gBAAgB,EAAE,GAAG,GAAG,KAAK;YAC7B,aAAa,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC;YAC/C,aAAa,EAAE,QAAQ,CAAC,MAAM;YAC9B,UAAU;SACX;KACF,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,SAAS,gBAAgB,CAAC,MAAgB,EAAE,GAAW;IACrD,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG;YAAE,OAAO,GAAG,CAAC,CAAC;;YACrB,MAAM;IACb,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,QAAwB,EAAE,KAAa;IAC/D,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,OAAO,KAAK,CAAC,EAAE,CAAC;QAClB,0EAA0E;QAC1E,iDAAiD;QACjD,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,OAAO,IAAI,QAAQ,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxF,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,CAAC;IAClE,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC9D,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,SAAS,CAAC,QAAwB;IAChD,OAAO,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;AACxE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,QAAwB,EAAE,MAAc,EAAE,KAAa;IACjF,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,GAAG,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAClE,OAAO,UAAU,CAAC,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,IAAI,GAAG,CAAC,KAAK,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,CAAC;QAC7F,OAAO,UAAU,CAAC,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC;IACtB,IAAI,GAAG,KAAK,CAAC;QAAE,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC;IACzF,OAAO,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAA8B;IAC1D,MAAM,KAAK,GAAI,MAAM,CAAC,KAAqD,EAAE,KAAK,CAAC;IACnF,MAAM,GAAG,GAAG,KAAK,EAAE,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClE,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAsB,EACtB,QAAgB;IAEhB,MAAM,OAAO,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAChC,MAAM,CAAC,MAAM,EAAE,EACf,kBAAkB,EAClB,EAAE,SAAS,EAAE,QAAQ,EAAE,EACvB,IAAI,CACL,CAAC;IACF,IAAI,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAwB,CAAC;IAC1D,OAAO,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,SAAS,oBAAoB,CAAC,IAAY;IACxC,OAAO,IAAI,CAAC,OAAO,CAAC,+CAA+C,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAClF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAoB,EACpB,MAAc,EACd,QAAwB;IAExB,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,QAAQ,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QAC3D,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,SAAS;YAC1C,MAAM,KAAK,GAAI,CAAuB,CAAC,IAAI,CAAC;YAC5C,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBACrB,IAAI,IAAI,GAAI,CAAuB,CAAC,IAAI,IAAI,EAAE,CAAC;gBAC/C,IAAI,CAAC,IAAI;oBAAE,SAAS;gBACpB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;oBACpB,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;oBAClC,IAAI,CAAC,IAAI;wBAAE,SAAS;gBACtB,CAAC;gBACD,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;oBAChC,SAAS,EAAE,MAAM;oBACjB,MAAM,EAAE;wBACN,aAAa,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,qBAAqB;wBAC7E,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;wBAC/B,SAAS,EAAE,GAAG;qBACf;iBACF,CAAC,CAAC;YACL,CAAC;iBAAM,IAAI,KAAK,KAAK,WAAW,EAAE,CAAC;gBACjC,MAAM,EAAE,GAAG,CAAwC,CAAC;gBACpD,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC;gBACzC,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;wBAChC,SAAS,EAAE,MAAM;wBACjB,MAAM,EAAE;4BACN,aAAa,EAAE,qBAAqB;4BACpC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;4BAC/B,SAAS,EAAE,WAAW,GAAG,EAAE;yBAC5B;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;gBAC5B,MAAM,EAAE,GAAG,CAKV,CAAC;gBACF,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,IAAI,WAAW,CAAC;gBACjD,MAAM,YAAY,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;gBACnC,MAAM,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE;oBAChC,SAAS,EAAE,MAAM;oBACjB,MAAM,EAAE;wBACN,aAAa,EAAE,WAAW;wBAC1B,UAAU,EAAE,EAAE,CAAC,EAAE,IAAI,YAAY,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;wBAC3D,KAAK;wBACL,IAAI,EAAE,OAAO;wBACb,MAAM,EAAG,EAAE,CAAC,MAA6B,IAAI,WAAW;wBACxD,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC/E;iBACF,CAAC,CAAC;YACL,CAAC;YACD,sFAAsF;QACxF,CAAC;QACD,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAsB,EACtB,MAAyB,EACzB,EAAoB;IAEpB,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,UAAU,CAAC,CAAC,KAAK,EAAE,wDAAwD,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC,CAAC,KAAK,EAAE,0BAA0B,CAAC,CAAC;IAE1E,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,qBAAqB,CAAC,CAAC;IAC1F,MAAM,eAAe,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAC7E,GAAG,CAAC,yBAAyB,KAAK,CAAC,IAAI,CAAC,gBAAgB,yBAAyB,CAAC,CAAC;IACnF,OAAO,EAAE,UAAU,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;AACpC,CAAC"}
@@ -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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"}
@@ -22,7 +22,8 @@ import { lookupLazySession, recordMaterializedSession, rememberLazySession, } fr
22
22
  import { buildDiffContent, EventTranslator, extractLocations, formatTurnError, isTransientTurnError, ProjectionDiffer, } from "../translators/index.js";
23
23
  import { log, warn } from "../utils.js";
24
24
  import { dispatchEvent } from "./dispatch.js";
25
- import { sendSessionUpdate, sendTextChunk } from "./io.js";
25
+ import { sendSessionUpdate, sendTextChunk, withReplayBatch } from "./io.js";
26
+ import { fetchMessages, fullSlice, readTailLimit, replayMessages, sliceTail } from "./replay.js";
26
27
  import { handleServerRequests } from "./server-requests.js";
27
28
  /** Workspace descriptor used in session create/resume calls. */
28
29
  function workspaceFor(cwd) {
@@ -70,6 +71,9 @@ export async function newSession(server, params) {
70
71
  // backend session materializes; never shown in session/list.
71
72
  const acpSid = randomUUID();
72
73
  server.pendingSessions.set(acpSid, { cwd, mcpServers: params.mcpServers });
74
+ // Persists past materialization (pendingSessions is cleared on first use) so
75
+ // the remote discovery payload can still label the workspace.
76
+ server.sessionCwds.set(acpSid, cwd);
73
77
  // Durable alias so the placeholder survives a bridge restart and session/
74
78
  // resume can still resolve it (best-effort; failures are swallowed inside
75
79
  // the store).
@@ -113,6 +117,7 @@ export async function ensureRealSession(server, acpSid) {
113
117
  if (record) {
114
118
  pending = { cwd: record.cwd };
115
119
  server.pendingSessions.set(acpSid, pending);
120
+ server.sessionCwds.set(acpSid, record.cwd);
116
121
  }
117
122
  }
118
123
  if (!pending)
@@ -201,6 +206,36 @@ export async function listSessions(server, params) {
201
206
  log(`session/list → ${sessions.length} sessions`);
202
207
  return { sessions };
203
208
  }
209
+ /**
210
+ * Adopt the backend's stored title for a loaded/resumed session.
211
+ *
212
+ * The prompt loop's auto-title only fires for freshly created sessions
213
+ * (`titleEligibleSessions`), so a session resumed across a bridge restart
214
+ * would otherwise appear title-less in the hub's discovery API — remote
215
+ * clients have no editor-side session storage to fall back on. The backend's
216
+ * session/list is the only title source for sessions born in a previous
217
+ * bridge lifetime. Best-effort: failures log and leave the session untitled.
218
+ */
219
+ async function adoptStoredTitle(server, acpSid, zcodeSid) {
220
+ if (server.sessionTitles.has(acpSid))
221
+ return;
222
+ try {
223
+ const backend = server.ensureBackend();
224
+ const resp = await backend.request(server.nextId(), "session/list", {}, 15000);
225
+ if (resp.error)
226
+ return;
227
+ const result = (resp.result ?? {});
228
+ const hit = (result.sessions ?? []).find((s) => s.sessionId === zcodeSid);
229
+ if (hit?.title) {
230
+ server.sessionTitles.set(acpSid, hit.title);
231
+ server.touchSessionSummary(acpSid, hit.title);
232
+ log(`adopted stored title for ${acpSid.slice(0, 8)}: ${hit.title}`);
233
+ }
234
+ }
235
+ catch (e) {
236
+ log(`stored title lookup failed (non-fatal): ${e instanceof Error ? e.message : String(e)}`);
237
+ }
238
+ }
204
239
  /**
205
240
  * Resolve the backend session id for `session/resume` / `session/load`.
206
241
  *
@@ -273,6 +308,7 @@ export async function resumeSession(server, params, cx) {
273
308
  server.registerSession(acpSid, zcodeSid);
274
309
  log(`session/resume -> ${zcodeSid}`);
275
310
  server.ensureBackgroundListener(zcodeSid);
311
+ await adoptStoredTitle(server, acpSid, zcodeSid);
276
312
  // Initial usage_update so the editor shows the context bar immediately for a
277
313
  // resumed session (mirrors Python _on_session_resume → _emit_initial_usage).
278
314
  await emitInitialUsage(server, cx, acpSid, zcodeSid, getOrCreateDiffer(server, zcodeSid));
@@ -312,57 +348,16 @@ export async function loadSession(server, params, cx) {
312
348
  server.registerSession(acpSid, zcodeSid);
313
349
  log(`session/load → ${zcodeSid}`);
314
350
  server.ensureBackgroundListener(zcodeSid);
351
+ await adoptStoredTitle(server, acpSid, zcodeSid);
315
352
  const messages = await fetchMessages(server, zcodeSid);
316
- let replayed = 0;
317
- for (const m of messages) {
318
- const info = m.info ?? {};
319
- const role = info.role;
320
- const mid = info.id ?? `hist_${randomUUID().slice(0, 12)}`;
321
- for (const p of m.parts ?? []) {
322
- if (!p || typeof p !== "object")
323
- continue;
324
- const ptype = p.type;
325
- if (ptype === "text") {
326
- const text = p.text ?? "";
327
- if (!text)
328
- continue;
329
- const sessionUpdate = role === "user" ? "user_message_chunk" : "agent_message_chunk";
330
- await sendSessionUpdate(cx, acpSid, {
331
- sessionUpdate,
332
- content: { type: "text", text },
333
- messageId: mid,
334
- });
335
- }
336
- else if (ptype === "reasoning") {
337
- const rp = p;
338
- const text = rp.text ?? rp.content ?? "";
339
- if (text) {
340
- await sendSessionUpdate(cx, acpSid, {
341
- sessionUpdate: "agent_thought_chunk",
342
- content: { type: "text", text },
343
- messageId: `thought_${mid}`,
344
- });
345
- }
346
- }
347
- else if (ptype === "tool") {
348
- const tp = p;
349
- const title = tp.title ?? tp.tool ?? "tool call";
350
- const histToolName = tp.tool ?? "";
351
- const update = {
352
- sessionUpdate: "tool_call",
353
- toolCallId: tp.id ?? `histtool_${randomUUID().slice(0, 8)}`,
354
- title,
355
- kind: "other",
356
- status: tp.status ?? "completed",
357
- ...(histToolName ? { _meta: { claudeCode: { toolName: histToolName } } } : {}),
358
- };
359
- await sendSessionUpdate(cx, acpSid, update);
360
- }
361
- // patch / step-start / other: skipped (history replay focuses on text + tool summary)
362
- }
363
- replayed += 1;
364
- }
365
- log(`session/load: replayed ${replayed} messages`);
353
+ // Tail replay (Proposal 0001): a `_meta.zcode.limit` replays only the last
354
+ // N messages aligned to turn boundaries — the full replay stays the default
355
+ // for editors that send no `_meta` (Zed path unchanged).
356
+ const limit = readTailLimit(params);
357
+ const slice = limit === null ? fullSlice(messages) : sliceTail(messages, limit);
358
+ await withReplayBatch(acpSid, () => replayMessages(cx, acpSid, slice.batch));
359
+ log(`session/load: replayed ${slice.meta.replayedMessages} messages` +
360
+ `${limit === null ? "" : ` (tail limit ${limit}, total ${slice.meta.totalMessages})`}`);
366
361
  // Replay the existing todo list as an initial plan so a loaded session shows
367
362
  // its todos immediately (filter to PlanUpdate only — text/tools were already
368
363
  // replayed above and the differ hasn't mark_seen'd this history).
@@ -381,10 +376,13 @@ export async function loadSession(server, params, cx) {
381
376
  await emitInitialUsage(server, cx, acpSid, zcodeSid, getOrCreateDiffer(server, zcodeSid));
382
377
  const modes = await buildModes(server, zcodeSid);
383
378
  server.lastMode.set(acpSid, modes.currentModeId);
384
- return {
379
+ const result = {
385
380
  modes,
386
381
  configOptions: await buildConfigOptions(server, zcodeSid),
382
+ // Additive replay metadata — the anchor for load_earlier pagination.
383
+ replayMeta: slice.meta,
387
384
  };
385
+ return result;
388
386
  }
389
387
  /** `session/prompt` → subscribe-before-send, run the event-driven turn loop. */
390
388
  export async function prompt(server, params, cx, requestId) {
@@ -400,11 +398,17 @@ export async function prompt(server, params, cx, requestId) {
400
398
  // empty-prompt check so an invalid request doesn't create a backend session.
401
399
  const zcodeSid = await ensureRealSession(server, params.sessionId);
402
400
  // Slash-command interception: dispatches directly to ZCode methods and
403
- // returns end_turn without entering the turn loop. Unknown /x falls through.
404
- const { handleSlashCommand } = await import("./slash.js");
401
+ // returns end_turn without entering the turn loop. Known passthrough
402
+ // commands and unknown /x both return null for the normal turn loop.
403
+ const { handleSlashCommand, neutralizeSlashText } = await import("./slash.js");
405
404
  const intercepted = await handleSlashCommand(server, cx, params.sessionId, zcodeSid, text);
406
405
  if (intercepted)
407
406
  return intercepted;
407
+ // Wire text for the backend: unknown `/x` prompts (not advertised commands)
408
+ // are neutralized so the backend's command resolver never sees them — an
409
+ // unresolvable name can hard-fail the turn. Known commands pass through
410
+ // unchanged. The title/auto-compact paths below keep using the raw `text`.
411
+ const sendText = neutralizeSlashText(text);
408
412
  // Register self + preempt others under a per-session lock. The lock
409
413
  // serializes the critical section so that two concurrent prompts (B, C) for
410
414
  // the same session can't both miss each other and register at once: C waits
@@ -491,8 +495,8 @@ export async function prompt(server, params, cx, requestId) {
491
495
  const SEND_RETRY_INTERVAL_MS = 500;
492
496
  const SEND_RETRY_TIMEOUT_MS = 30_000;
493
497
  const sendParams = attachments.length > 0
494
- ? { sessionId: zcodeSid, content: text, attachments }
495
- : { sessionId: zcodeSid, content: text };
498
+ ? { sessionId: zcodeSid, content: sendText, attachments }
499
+ : { sessionId: zcodeSid, content: sendText };
496
500
  const sendT0 = Date.now();
497
501
  let sendAttempt = 0;
498
502
  while (true) {
@@ -556,6 +560,7 @@ export async function prompt(server, params, cx, requestId) {
556
560
  .find((l) => l.length > 0)
557
561
  ?.slice(0, 80) ?? text.slice(0, 80);
558
562
  server.sessionTitles.set(params.sessionId, title);
563
+ server.touchSessionSummary(params.sessionId, title);
559
564
  const { updateSessionTitle } = await import("../tasks-index.js");
560
565
  void updateSessionTitle(zcodeSid, title, text);
561
566
  await sendSessionUpdate(cx, params.sessionId, {
@@ -603,6 +608,9 @@ export async function prompt(server, params, cx, requestId) {
603
608
  finally {
604
609
  backend.unregisterEventListener(zcodeSid, listener);
605
610
  server.pendingTurns.delete(requestId);
611
+ // Turn end = session activity — refresh the discovery summary timestamp
612
+ // regardless of outcome (end_turn, cancelled, retries exhausted).
613
+ server.touchSessionSummary(params.sessionId);
606
614
  }
607
615
  }
608
616
  /**
@@ -914,15 +922,6 @@ async function resumeBackendSession(server, zcParams) {
914
922
  await sleep(1000);
915
923
  }
916
924
  }
917
- /** Fetch session/messages from zcode. */
918
- async function fetchMessages(server, zcodeSid) {
919
- const backend = server.ensureBackend();
920
- const resp = await backend.request(server.nextId(), "session/messages", { sessionId: zcodeSid }, 8000);
921
- if (resp.error)
922
- return [];
923
- const result = (resp.result ?? {});
924
- return result.messages ?? [];
925
- }
926
925
  /** Get or create the session-level ProjectionDiffer (persists across turns). */
927
926
  function getOrCreateDiffer(server, zcodeSid) {
928
927
  let d = server.differs.get(zcodeSid);