aibroker 0.7.13 → 0.8.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.
@@ -0,0 +1,275 @@
1
+ /**
2
+ * daemon/dispatch.ts — deliver a work order to a project's session.
3
+ *
4
+ * The transport half of PAI's task bus: PAI decides which project owns a task,
5
+ * hands us the project name plus a message body, and we resolve that to a live
6
+ * session and deliver it — spawning the session if none is running.
7
+ *
8
+ * ONE atomic call on purpose. A caller doing list → launch → send itself races:
9
+ * a session can start or die between the check and the send, and the caller ends
10
+ * up duplicating session-lifecycle logic it doesn't own.
11
+ *
12
+ * Outcomes are RESULTS, not errors. A task the bus can't route is an ordinary
13
+ * thing to report and move past — a batch must not abort because one project
14
+ * lacks an alias. Only genuine infrastructure failure throws.
15
+ *
16
+ * delivered — a live session accepted it
17
+ * spawned — no session ran; we launched one and it accepted it
18
+ * unlaunchable — no curated alias. Setup gap: `pai project name <id> <short>`
19
+ * unreachable — tab opened but the session never accepted input. Runtime bug.
20
+ * skipped — no live session and spawning was disabled
21
+ *
22
+ * `unlaunchable` and `unreachable` are deliberately distinct: the first is a
23
+ * missing alias, the second is a session that failed to come up. Collapsing
24
+ * them sends whoever reads the result looking in the wrong place.
25
+ */
26
+ import { snapshotAllSessions } from "../transport/sync-facade.js";
27
+ import { findCuratedPaiProject, launchResolvedPaiProject, invalidatePaiProjectCache, } from "./pai-projects.js";
28
+ import { getAllPersistentSessionNames, lookupPersistentName } from "../core/persistence.js";
29
+ import { captureSession, typeIntoSession } from "../transport/sync-facade.js";
30
+ import { log } from "../core/log.js";
31
+ /** A spawned Claude needs to boot and run its `/Name … go` preamble first. */
32
+ const DEFAULT_SPAWN_TIMEOUT_MS = 90_000;
33
+ const DEFAULT_DELIVER_TIMEOUT_MS = 120_000;
34
+ const READY_POLL_MS = 1_000;
35
+ /**
36
+ * Routing prefix for dispatched work.
37
+ *
38
+ * Deliberately NOT `[Session:PAI]`. That prefix means "reply to the sender on
39
+ * this channel", and for a dispatched task there is no sender left to reply to —
40
+ * the CLI that sent it has already exited. Promising a reply path that doesn't
41
+ * exist is worse than promising none, so `[Task]` says: act on it, don't reply,
42
+ * report by closing it on the tracker.
43
+ *
44
+ * The body carries the same contract in words, because a session that has never
45
+ * seen `[Task]` before must still do the right thing.
46
+ */
47
+ export const TASK_PREFIX = "[Task]";
48
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
49
+ const realIO = {
50
+ capture: (id) => captureSession(id, 60),
51
+ send: (id, text) => { typeIntoSession(id, text); },
52
+ sleep,
53
+ now: () => Date.now(),
54
+ };
55
+ /**
56
+ * Find a running session for `project`.
57
+ *
58
+ * Matches the project's display name, canonical name and every curated alias,
59
+ * case-insensitively — session labels and aliases disagree on capitalisation
60
+ * often enough that an exact match silently spawns a duplicate tab.
61
+ */
62
+ export function findSessionForProject(project, sessions) {
63
+ const wanted = new Set([project.displayName, project.name, project.slug, ...project.names]
64
+ .filter(Boolean)
65
+ .map((s) => s.toLowerCase()));
66
+ for (const s of sessions) {
67
+ const label = s.paiName ?? s.name;
68
+ if (label && wanted.has(label.toLowerCase()))
69
+ return { id: s.id, label };
70
+ }
71
+ return null;
72
+ }
73
+ /** Enumerate live sessions with their persistent (PAI) names resolved. */
74
+ function liveSessions() {
75
+ const snaps = snapshotAllSessions();
76
+ const persistent = getAllPersistentSessionNames();
77
+ return snaps.map((s) => ({
78
+ id: s.id,
79
+ name: s.name,
80
+ paiName: lookupPersistentName(persistent, s.id, s.aibrokerId),
81
+ }));
82
+ }
83
+ /** The line Claude's input box is drawn on. */
84
+ const INPUT_LINE = /^\s*❯/;
85
+ /** Claude's input box: a prompt caret sitting inside a run of box-drawing rule. */
86
+ const CLAUDE_UI = /─{20,}/;
87
+ /** Collapse whitespace so wrapped/padded terminal text compares sanely. */
88
+ function flatten(s) { return s.replace(/\s+/g, " ").trim(); }
89
+ /**
90
+ * Wait until a freshly launched session can ACCEPT input.
91
+ *
92
+ * Note "accept", not "be idle". A launched session immediately runs its
93
+ * `/Name … go` preamble and stays busy for minutes; waiting for the screen to
94
+ * settle times out on a session that is perfectly healthy — which is exactly
95
+ * what the first version did. Claude Code queues typed input while it works, so
96
+ * the real gate is whether the input box has been drawn yet.
97
+ */
98
+ export async function waitForReady(sessionId, timeoutMs, io = realIO) {
99
+ const deadline = io.now() + timeoutMs;
100
+ while (io.now() < deadline) {
101
+ await io.sleep(READY_POLL_MS);
102
+ const frame = io.capture(sessionId);
103
+ if (frame === null)
104
+ continue;
105
+ if (isClaudeReady(frame))
106
+ return true;
107
+ }
108
+ return false;
109
+ }
110
+ /** True when a frame shows Claude's input box drawn and ready to take text. */
111
+ export function isClaudeReady(frame) {
112
+ return CLAUDE_UI.test(frame) && frame.split("\n").some((l) => INPUT_LINE.test(l));
113
+ }
114
+ /**
115
+ * Type `body` into a session and confirm Claude actually took it.
116
+ *
117
+ * Frame-counting (what `sessions checkpoint` uses) can't be trusted here: a
118
+ * session mid-task animates constantly, so "the screen changed" is true whether
119
+ * or not our text was submitted. Instead we use the one transition that only
120
+ * happens on submit — the text leaves the input box and appears above it:
121
+ *
122
+ * present in the frame, AND no longer on the ❯ input line -> submitted
123
+ *
124
+ * That works identically whether the session is idle or busy, which is the
125
+ * whole point for a freshly spawned session that is still running `go`.
126
+ */
127
+ export async function submitAndConfirm(sessionId, body, timeoutMs, io = realIO, retries = 3) {
128
+ if (io.capture(sessionId) === null)
129
+ return "unreadable";
130
+ // A short distinctive slice: long bodies wrap and get truncated on screen.
131
+ const needle = flatten(body.split("\n").find((l) => l.trim().length > 0) ?? body).slice(0, 48);
132
+ if (!needle)
133
+ return "no-ack";
134
+ const perAttempt = Math.max(4000, Math.floor(timeoutMs / retries));
135
+ for (let attempt = 1; attempt <= retries; attempt++) {
136
+ io.send(sessionId, body);
137
+ const deadline = io.now() + perAttempt;
138
+ while (io.now() < deadline) {
139
+ await io.sleep(500);
140
+ const frame = io.capture(sessionId);
141
+ if (frame === null)
142
+ continue;
143
+ if (hasBeenSubmitted(frame, needle))
144
+ return "ok";
145
+ }
146
+ }
147
+ return "no-ack";
148
+ }
149
+ /**
150
+ * Has `needle` left the input box and landed in the transcript?
151
+ *
152
+ * Present on screen is not enough — text sitting unsubmitted in the input box is
153
+ * also "present". Submission is the moment it appears while the ❯ line no longer
154
+ * holds it.
155
+ */
156
+ export function hasBeenSubmitted(frame, needle) {
157
+ const stillTyped = inputBoxLines(frame).some((l) => flatten(l).includes(needle.slice(0, 24)));
158
+ return !stillTyped && flatten(frame).includes(needle);
159
+ }
160
+ /**
161
+ * The lines inside Claude's input box.
162
+ *
163
+ * A caret alone will not do: Claude echoes each submitted message into the
164
+ * transcript with the SAME `❯` marker, so "a ❯ line contains our text" is true
165
+ * both before and after submitting — the check it was meant to power would
166
+ * never fire. The input box is identified structurally instead, as the region
167
+ * between the last two horizontal rules at the bottom of the frame.
168
+ */
169
+ function inputBoxLines(frame) {
170
+ const lines = frame.split("\n");
171
+ const rules = [];
172
+ lines.forEach((l, i) => { if (CLAUDE_UI.test(l))
173
+ rules.push(i); });
174
+ if (rules.length >= 2) {
175
+ const [open, close] = [rules[rules.length - 2], rules[rules.length - 1]];
176
+ return lines.slice(open + 1, close);
177
+ }
178
+ return lines.filter((l) => INPUT_LINE.test(l)); // no box drawn — best effort
179
+ }
180
+ /** Production wiring for DispatchDeps. */
181
+ const realDeps = {
182
+ resolve: findCuratedPaiProject,
183
+ sessions: liveSessions,
184
+ deliver: submitAndConfirm,
185
+ launch: launchResolvedPaiProject,
186
+ waitReady: waitForReady,
187
+ };
188
+ function ackReason(res) {
189
+ switch (res) {
190
+ case "no-ack": return "session did not accept the message (never reacted)";
191
+ case "no-settle": return "session accepted the message but was still working when the timeout expired";
192
+ case "unreadable": return "session terminal could not be read";
193
+ default: return "";
194
+ }
195
+ }
196
+ /**
197
+ * Resolve `project` to a session and deliver `message`, spawning if needed.
198
+ *
199
+ * Never throws for a routing outcome — see the module comment.
200
+ */
201
+ export async function dispatch(projectName, message, opts = {}, deps = realDeps) {
202
+ const spawnTimeoutMs = opts.spawnTimeoutMs ?? DEFAULT_SPAWN_TIMEOUT_MS;
203
+ const deliverTimeoutMs = opts.deliverTimeoutMs ?? DEFAULT_DELIVER_TIMEOUT_MS;
204
+ const project = await deps.resolve(projectName);
205
+ if (!project) {
206
+ return {
207
+ outcome: "unlaunchable",
208
+ project: projectName,
209
+ session: "",
210
+ reason: `No curated alias for "${projectName}". Bus participation is opt-in: ` +
211
+ `run \`pai project name <identifier> ${projectName}\` to register one.`,
212
+ };
213
+ }
214
+ const label = project.displayName || project.name;
215
+ const body = `${TASK_PREFIX} ${message}`;
216
+ // ── already running? ──
217
+ const existing = findSessionForProject(project, deps.sessions());
218
+ if (existing) {
219
+ const res = await deps.deliver(existing.id, body, deliverTimeoutMs);
220
+ if (res === "ok") {
221
+ return { outcome: "delivered", project: label, session: existing.label, reason: "" };
222
+ }
223
+ return {
224
+ outcome: "unreachable",
225
+ project: label,
226
+ session: existing.label,
227
+ reason: `Live session found but ${ackReason(res)}.`,
228
+ };
229
+ }
230
+ if (opts.noSpawn) {
231
+ return {
232
+ outcome: "skipped",
233
+ project: label,
234
+ session: "",
235
+ reason: "No live session and spawning was disabled (--no-spawn).",
236
+ };
237
+ }
238
+ // ── spawn, wait for it to come up, then deliver ──
239
+ let itermSessionId;
240
+ try {
241
+ ({ itermSessionId } = await deps.launch(project));
242
+ }
243
+ catch (err) {
244
+ return {
245
+ outcome: "unreachable",
246
+ project: label,
247
+ session: "",
248
+ reason: `Failed to launch a session: ${err instanceof Error ? err.message : String(err)}`,
249
+ };
250
+ }
251
+ invalidatePaiProjectCache();
252
+ log(`dispatch: launched "${label}" as ${itermSessionId}, waiting for it to accept input`);
253
+ if (!(await deps.waitReady(itermSessionId, spawnTimeoutMs))) {
254
+ return {
255
+ outcome: "unreachable",
256
+ project: label,
257
+ session: label,
258
+ reason: `Launched a session in ${project.rootPath} but it did not become ready ` +
259
+ `within ${Math.round(spawnTimeoutMs / 1000)}s. The tab is open — check why it did not start.`,
260
+ };
261
+ }
262
+ const res = await deps.deliver(itermSessionId, body, deliverTimeoutMs);
263
+ if (res === "ok") {
264
+ return { outcome: "spawned", project: label, session: label, reason: "" };
265
+ }
266
+ // Deliberately NOT "spawned": the tab exists but the work order never landed,
267
+ // and reporting success here is how a task silently disappears.
268
+ return {
269
+ outcome: "unreachable",
270
+ project: label,
271
+ session: label,
272
+ reason: `Spawned a session but ${ackReason(res)}.`,
273
+ };
274
+ }
275
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/daemon/dispatch.ts"],"names":[],"mappings":"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"}
@@ -31,6 +31,20 @@ export declare function invalidatePaiProjectCache(): void;
31
31
  * Results are cached for 30 seconds.
32
32
  */
33
33
  export declare function listPaiProjects(all?: boolean): Promise<PaiProject[]>;
34
+ /**
35
+ * Find a project by any of its names or aliases, among CURATED projects only.
36
+ *
37
+ * Deliberately narrower than findPaiProject(). The `--all` set is ~118 entries
38
+ * with empty `names` and genuine ambiguity — three separate registry rows share
39
+ * the display name "Glidr" at different paths — so resolving a task against it
40
+ * silently dispatches work to the wrong directory. Bus participation therefore
41
+ * stays opt-in: a project joins by being given an alias
42
+ * (`pai project name <identifier> <shortname>`), and anything without one is
43
+ * reported as unlaunchable rather than guessed at.
44
+ *
45
+ * Matching is case-insensitive.
46
+ */
47
+ export declare function findCuratedPaiProject(name: string): Promise<PaiProject | undefined>;
34
48
  /**
35
49
  * Find a project by any of its names or aliases.
36
50
  * Matching is case-insensitive.
@@ -65,4 +79,18 @@ export declare function launchPaiProject(name: string): Promise<{
65
79
  itermSessionId: string;
66
80
  sessionId: string;
67
81
  }>;
82
+ /**
83
+ * Launch an ALREADY-RESOLVED project.
84
+ *
85
+ * Callers that resolved against a narrower set than findPaiProject() must use
86
+ * this. Passing a name back into launchPaiProject() launders it through the
87
+ * `--all` set a second time, so a careful curated resolve can still end up
88
+ * opening a different project that happens to share the display name — there
89
+ * are three "Glidr" rows at three different paths. Once resolution has picked
90
+ * a row, that row is what gets launched.
91
+ */
92
+ export declare function launchResolvedPaiProject(project: PaiProject): Promise<{
93
+ itermSessionId: string;
94
+ sessionId: string;
95
+ }>;
68
96
  //# sourceMappingURL=pai-projects.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pai-projects.d.ts","sourceRoot":"","sources":["../../src/daemon/pai-projects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;CACH;AAaD,0EAA0E;AAC1E,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AA+DD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,UAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAWxE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAalF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,SAAS,CAAC,CAWb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAgDxD"}
1
+ {"version":3,"file":"pai-projects.d.ts","sourceRoot":"","sources":["../../src/daemon/pai-projects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;CACH;AAaD,0EAA0E;AAC1E,wBAAgB,yBAAyB,IAAI,IAAI,CAGhD;AA+DD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,GAAG,UAAQ,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAWxE;AAcD;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAEzF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAMlF;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,GAAG,SAAS,CAAC,CAWb;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAMxD;AAED;;;;;;;;;GASG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CA6CxD"}
@@ -97,6 +97,31 @@ export async function listPaiProjects(all = false) {
97
97
  log(`pai-projects: loaded ${projects.length} project(s)${all ? " (all)" : ""}`);
98
98
  return projects;
99
99
  }
100
+ /** Case-insensitive match of a needle against a project's name, aliases or slug. */
101
+ function matchProject(projects, name) {
102
+ const needle = name.trim().toLowerCase();
103
+ if (!needle)
104
+ return undefined;
105
+ return projects.find((p) => p.name.toLowerCase() === needle ||
106
+ p.names.some((n) => n.toLowerCase() === needle) ||
107
+ p.slug.toLowerCase() === needle);
108
+ }
109
+ /**
110
+ * Find a project by any of its names or aliases, among CURATED projects only.
111
+ *
112
+ * Deliberately narrower than findPaiProject(). The `--all` set is ~118 entries
113
+ * with empty `names` and genuine ambiguity — three separate registry rows share
114
+ * the display name "Glidr" at different paths — so resolving a task against it
115
+ * silently dispatches work to the wrong directory. Bus participation therefore
116
+ * stays opt-in: a project joins by being given an alias
117
+ * (`pai project name <identifier> <shortname>`), and anything without one is
118
+ * reported as unlaunchable rather than guessed at.
119
+ *
120
+ * Matching is case-insensitive.
121
+ */
122
+ export async function findCuratedPaiProject(name) {
123
+ return matchProject(await listPaiProjects(false), name);
124
+ }
100
125
  /**
101
126
  * Find a project by any of its names or aliases.
102
127
  * Matching is case-insensitive.
@@ -106,11 +131,7 @@ export async function findPaiProject(name) {
106
131
  // the picker now offers every project (listPaiProjects(true)), so a launch of a
107
132
  // non-shortlisted project (e.g. glidr) must resolve here too, or it fails with
108
133
  // "project not found".
109
- const projects = await listPaiProjects(true);
110
- const needle = name.toLowerCase();
111
- return projects.find((p) => p.name.toLowerCase() === needle ||
112
- p.names.some((n) => n.toLowerCase() === needle) ||
113
- p.slug.toLowerCase() === needle);
134
+ return matchProject(await listPaiProjects(true), name);
114
135
  }
115
136
  /**
116
137
  * Get the effective (merged) config for a PAI project.
@@ -149,6 +170,20 @@ export async function launchPaiProject(name) {
149
170
  if (!project) {
150
171
  throw new Error(`PAI project "${name}" not found`);
151
172
  }
173
+ return launchResolvedPaiProject(project);
174
+ }
175
+ /**
176
+ * Launch an ALREADY-RESOLVED project.
177
+ *
178
+ * Callers that resolved against a narrower set than findPaiProject() must use
179
+ * this. Passing a name back into launchPaiProject() launders it through the
180
+ * `--all` set a second time, so a careful curated resolve can still end up
181
+ * opening a different project that happens to share the display name — there
182
+ * are three "Glidr" rows at three different paths. Once resolution has picked
183
+ * a row, that row is what gets launched.
184
+ */
185
+ export async function launchResolvedPaiProject(project) {
186
+ const name = project.name;
152
187
  // Get effective config (project overrides global defaults)
153
188
  const effective = await getEffectiveConfig(name) ?? project.sessionConfig ?? {};
154
189
  const flags = effective.flags ?? "";
@@ -1 +1 @@
1
- {"version":3,"file":"pai-projects.js","sourceRoot":"","sources":["../../src/daemon/pai-projects.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AA2B1C,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,IAAI,MAAM,GAAiB,IAAI,CAAC,CAAO,oBAAoB;AAC3D,IAAI,SAAS,GAAiB,IAAI,CAAC,CAAI,8BAA8B;AAErE,0EAA0E;AAC1E,MAAM,UAAU,yBAAyB;IACvC,MAAM,GAAG,IAAI,CAAC;IACd,SAAS,GAAG,IAAI,CAAC;AACnB,CAAC;AAED,qBAAqB;AAErB,iEAAiE;AACjE,KAAK,UAAU,YAAY,CAAC,GAAY;IACtC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAC5F,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,EAAE;YAClD,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,GAAG,CAAC,mDAAmD,CAAC,CAAC;YACzD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAA6B,EAAE,EAAE,CAAC,CAAC;YACjD,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7B,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;YACrF,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7B,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YACzD,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;YACtC,YAAY,EAAE,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YAC7E,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;YAC1C,aAAa,EAAE,IAAI,CAAC,cAAc;gBAChC,CAAC,CAAC;oBACE,UAAU,EAAE,OAAQ,IAAI,CAAC,cAA0C,CAAC,UAAU,KAAK,QAAQ;wBACzF,CAAC,CAAE,IAAI,CAAC,cAA0C,CAAC,UAAoB;wBACvE,CAAC,CAAC,SAAS;oBACb,KAAK,EAAE,OAAQ,IAAI,CAAC,cAA0C,CAAC,KAAK,KAAK,QAAQ;wBAC/E,CAAC,CAAE,IAAI,CAAC,cAA0C,CAAC,KAAe;wBAClE,CAAC,CAAC,SAAS;oBACb,GAAG,EACA,IAAI,CAAC,cAA0C,CAAC,GAAG,IAAI,IAAI;wBAC5D,OAAQ,IAAI,CAAC,cAA0C,CAAC,GAAG,KAAK,QAAQ;wBACtE,CAAC,CAAG,IAAI,CAAC,cAA0C,CAAC,GAA8B;wBAClF,CAAC,CAAC,SAAS;oBACf,SAAS,EACP,OAAQ,IAAI,CAAC,cAA0C,CAAC,SAAS,KAAK,SAAS;wBAC7E,CAAC,CAAG,IAAI,CAAC,cAA0C,CAAC,SAAqB;wBACzE,CAAC,CAAC,SAAS;iBAChB;gBACH,CAAC,CAAC,SAAS;SACd,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,6DAA6D;QAC7D,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3B,GAAG,CAAC,qEAAqE,CAAC,CAAC;QAC7E,CAAC;aAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClE,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,mBAAmB;AAEnB;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAG,GAAG,KAAK;IAC/C,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IACvC,IAAI,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,GAAG,YAAY,EAAE,CAAC;QACzD,OAAO,KAAK,CAAC,QAAQ,CAAC;IACxB,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAClD,IAAI,GAAG;QAAE,SAAS,GAAG,KAAK,CAAC;;QAAM,MAAM,GAAG,KAAK,CAAC;IAChD,GAAG,CAAC,wBAAwB,QAAQ,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,4EAA4E;IAC5E,gFAAgF;IAChF,+EAA+E;IAC/E,uBAAuB;IACvB,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAClC,OAAO,QAAQ,CAAC,IAAI,CAClB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM;QAC/B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC;QAC/C,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,MAAM,CAClC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAAY;IAMnD,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE;YACnF,OAAO,EAAE,KAAK;YACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACvC,OAAO,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY;IAEZ,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,gBAAgB,IAAI,aAAa,CAAC,CAAC;IACrD,CAAC;IAED,2DAA2D;IAC3D,MAAM,SAAS,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;IAEhF,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC;IAEhC,uDAAuD;IACvD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAClD,0EAA0E;IAC1E,0EAA0E;IAC1E,8DAA8D;IAC9D,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAClD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtC,8EAA8E;IAC9E,qEAAqE;IACrE,MAAM,MAAM,GAAG,WAAW,KAAK,UAAU,CAAC;IAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QAClE,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,kCAAkC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,UAAU,WAAW,WAAW,WAAW,CAAC,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC;IAE3E,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IAEtD,GAAG,CACD,+CAA+C,OAAO,CAAC,IAAI,IAAI;QAC/D,OAAO,OAAO,CAAC,QAAQ,eAAe,OAAO,GAAG,CACjD,CAAC;IAEF,0CAA0C;IAC1C,MAAM,cAAc,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,GAAG,CAAC,CAAC;IACvE,CAAC;IAED,GAAG,CAAC,uCAAuC,cAAc,iBAAiB,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC;IAE3F,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC;AAED,uDAAuD;AACvD,SAAS,WAAW,CAAC,CAAS;IAC5B,IAAI,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,CAAC,CAAC;IAC7C,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AACzC,CAAC"}
1
+ {"version":3,"file":"pai-projects.js","sourceRoot":"","sources":["../../src/daemon/pai-projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ interface Entry {
2
+ name: string;
3
+ cwd: string;
4
+ /** ISO timestamp of the last snapshot that saw this session open. */
5
+ lastSeen?: string;
6
+ /** ISO timestamp of the first snapshot that ever saw it. */
7
+ addedAt?: string;
8
+ }
9
+ /**
10
+ * Union `fresh` (what is open right now) into `existing` (the restore list).
11
+ *
12
+ * Pure and exported so the property that actually matters is testable: this
13
+ * never returns fewer entries than `existing`. Every historical way of losing
14
+ * the manifest — /exit-ing tabs one by one, a daemon outage, an iTerm restart —
15
+ * reaches this function as a small or empty `fresh`, and must be a no-op rather
16
+ * than a truncation.
17
+ */
18
+ export declare function mergeEntries(existing: Entry[], fresh: Entry[], now: string): Entry[];
19
+ export type AckResult = "ok" | "no-ack" | "no-settle" | "unreadable";
20
+ /** Injected so the ack state machine can be tested against a simulated terminal. */
21
+ export interface SessionProbe {
22
+ capture: (id: string) => string | null;
23
+ send: (id: string, text: string) => void;
24
+ sleep: (ms: number) => Promise<void>;
25
+ now: () => number;
26
+ onRetry?: (attempt: number, of: number) => void;
27
+ }
28
+ export declare const POLL_MS = 500;
29
+ /** Consecutive identical frames that mean "Claude stopped writing". */
30
+ export declare const SETTLE_TICKS = 4;
31
+ /** Distinct frames required before we believe the prompt was actually SUBMITTED. */
32
+ export declare const ACK_TRANSITIONS = 2;
33
+ /**
34
+ * Send `message` to one session and prove it was consumed.
35
+ *
36
+ * A successful `write text` only means keystrokes reached the terminal — not
37
+ * that Claude accepted the prompt. That gap is exactly what leaves you walking
38
+ * to every tab by hand after a hiccup. So we watch the screen instead.
39
+ *
40
+ * The subtlety: "the screen changed" is NOT proof of submission. Text typed into
41
+ * Claude's input box changes the screen too, so a send whose Enter was swallowed
42
+ * looks identical to a successful one for one frame — and then freezes. We
43
+ * therefore require ACK_TRANSITIONS *distinct* frames: a working Claude animates
44
+ * (spinner, streaming tokens) and trivially clears the bar, whereas text sitting
45
+ * unsubmitted in the box produces exactly one change and then stillness, so it
46
+ * correctly fails and retries.
47
+ *
48
+ * 1. send, then poll for ACK_TRANSITIONS distinct frames -> genuinely submitted
49
+ * 2. poll until SETTLE_TICKS identical frames -> Claude finished
50
+ *
51
+ * Frame-diffing is deliberately content-agnostic: it never parses what `pause
52
+ * session` prints, so it keeps working when that output changes.
53
+ */
54
+ export declare function sendVerified(sessionId: string, message: string, opts: {
55
+ timeoutMs: number;
56
+ retries: number;
57
+ }, probe: SessionProbe): Promise<AckResult>;
58
+ export declare function runSessions(args: string[]): Promise<void>;
59
+ export {};
60
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/daemon/sessions.ts"],"names":[],"mappings":"AAmDA,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyHD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,CAYpF;AAqED,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,CAAC;AAErE,oFAAoF;AACpF,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACvC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED,eAAO,MAAM,OAAO,MAAM,CAAC;AAC3B,uEAAuE;AACvE,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,oFAAoF;AACpF,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAC5C,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,SAAS,CAAC,CAoCpB;AA8JD,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAU/D"}