aibroker 0.7.13 → 0.8.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.
@@ -0,0 +1,149 @@
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 { type PaiProject } from "./pai-projects.js";
27
+ import { type AckResult } from "./sessions.js";
28
+ export type DispatchOutcome = "delivered" | "spawned" | "unlaunchable" | "unreachable" | "skipped";
29
+ export interface DispatchResult {
30
+ outcome: DispatchOutcome;
31
+ project: string;
32
+ session: string;
33
+ reason: string;
34
+ }
35
+ export interface DispatchOptions {
36
+ /** Never launch a session; report `skipped` instead. */
37
+ noSpawn?: boolean;
38
+ /**
39
+ * Total wall-clock budget for the WHOLE dispatch, caller-supplied.
40
+ *
41
+ * Stages must share one deadline, not hold their own. Spawning runs
42
+ * readiness and then delivery in sequence, so per-stage limits add up: a 180s
43
+ * readiness limit plus a 120s delivery limit is a 300s worst case, which
44
+ * silently outlives a caller that budgeted 180s and kills the process itself.
45
+ * The caller then sees its own timeout instead of our reason — a failure we
46
+ * cannot reproduce from this side. One budget, split across the stages.
47
+ */
48
+ budgetMs?: number;
49
+ /** Cap on the readiness wait, within the budget. */
50
+ spawnTimeoutMs?: number;
51
+ /** Cap on the delivery wait, within the budget. */
52
+ deliverTimeoutMs?: number;
53
+ }
54
+ /**
55
+ * Everything dispatch() touches outside itself, injected so the outcome matrix
56
+ * can be tested without iTerm, a daemon, or a real `pai` binary. Production
57
+ * callers omit it and get the real implementations.
58
+ */
59
+ export interface DispatchDeps {
60
+ resolve: (name: string) => Promise<PaiProject | undefined>;
61
+ sessions: () => {
62
+ id: string;
63
+ name: string;
64
+ paiName: string | null;
65
+ }[];
66
+ deliver: (sessionId: string, body: string, timeoutMs: number) => Promise<AckResult>;
67
+ launch: (project: PaiProject) => Promise<{
68
+ itermSessionId: string;
69
+ }>;
70
+ waitReady: (sessionId: string, timeoutMs: number) => Promise<boolean>;
71
+ /** Clock for the shared budget; injectable so budget maths is testable. */
72
+ now: () => number;
73
+ }
74
+ /**
75
+ * Routing prefix for dispatched work.
76
+ *
77
+ * Deliberately NOT `[Session:PAI]`. That prefix means "reply to the sender on
78
+ * this channel", and for a dispatched task there is no sender left to reply to —
79
+ * the CLI that sent it has already exited. Promising a reply path that doesn't
80
+ * exist is worse than promising none, so `[Task]` says: act on it, don't reply,
81
+ * report by closing it on the tracker.
82
+ *
83
+ * The body carries the same contract in words, because a session that has never
84
+ * seen `[Task]` before must still do the right thing.
85
+ */
86
+ export declare const TASK_PREFIX = "[Task]";
87
+ /** Terminal access, injectable so the screen heuristics can be tested on real frames. */
88
+ export interface TerminalIO {
89
+ capture: (id: string) => string | null;
90
+ send: (id: string, text: string) => void;
91
+ sleep: (ms: number) => Promise<void>;
92
+ now: () => number;
93
+ }
94
+ /**
95
+ * Find a running session for `project`.
96
+ *
97
+ * Matches the project's display name, canonical name and every curated alias,
98
+ * case-insensitively — session labels and aliases disagree on capitalisation
99
+ * often enough that an exact match silently spawns a duplicate tab.
100
+ */
101
+ export declare function findSessionForProject(project: PaiProject, sessions: {
102
+ id: string;
103
+ name: string;
104
+ paiName: string | null;
105
+ }[]): {
106
+ id: string;
107
+ label: string;
108
+ } | null;
109
+ /**
110
+ * Wait until a freshly launched session can ACCEPT input.
111
+ *
112
+ * Note "accept", not "be idle". A launched session immediately runs its
113
+ * `/Name … go` preamble and stays busy for minutes; waiting for the screen to
114
+ * settle times out on a session that is perfectly healthy — which is exactly
115
+ * what the first version did. Claude Code queues typed input while it works, so
116
+ * the real gate is whether the input box has been drawn yet.
117
+ */
118
+ export declare function waitForReady(sessionId: string, timeoutMs: number, io?: TerminalIO): Promise<boolean>;
119
+ /** True when a frame shows Claude's input box drawn and ready to take text. */
120
+ export declare function isClaudeReady(frame: string): boolean;
121
+ /**
122
+ * Type `body` into a session and confirm Claude actually took it.
123
+ *
124
+ * Frame-counting (what `sessions checkpoint` uses) can't be trusted here: a
125
+ * session mid-task animates constantly, so "the screen changed" is true whether
126
+ * or not our text was submitted. Instead we use the one transition that only
127
+ * happens on submit — the text leaves the input box and appears above it:
128
+ *
129
+ * present in the frame, AND no longer on the ❯ input line -> submitted
130
+ *
131
+ * That works identically whether the session is idle or busy, which is the
132
+ * whole point for a freshly spawned session that is still running `go`.
133
+ */
134
+ export declare function submitAndConfirm(sessionId: string, body: string, timeoutMs: number, io?: TerminalIO, retries?: number): Promise<AckResult>;
135
+ /**
136
+ * Has `needle` left the input box and landed in the transcript?
137
+ *
138
+ * Present on screen is not enough — text sitting unsubmitted in the input box is
139
+ * also "present". Submission is the moment it appears while the ❯ line no longer
140
+ * holds it.
141
+ */
142
+ export declare function hasBeenSubmitted(frame: string, needle: string): boolean;
143
+ /**
144
+ * Resolve `project` to a session and deliver `message`, spawning if needed.
145
+ *
146
+ * Never throws for a routing outcome — see the module comment.
147
+ */
148
+ export declare function dispatch(projectName: string, message: string, opts?: DispatchOptions, deps?: DispatchDeps): Promise<DispatchResult>;
149
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/daemon/dispatch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,308 @@
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
+ // `timeoutMs` is a hard ceiling on this call, retries included. An earlier
135
+ // version floored the per-attempt wait at 4s, which quietly overrode a
136
+ // smaller budget: three attempts still ran for 12s when the caller allowed
137
+ // less. Anything that can outlive the caller's own kill timer defeats the
138
+ // point of being handed a budget at all.
139
+ const overallDeadline = io.now() + timeoutMs;
140
+ const perAttempt = Math.max(Math.min(4000, timeoutMs), Math.floor(timeoutMs / retries));
141
+ for (let attempt = 1; attempt <= retries; attempt++) {
142
+ if (io.now() >= overallDeadline)
143
+ break;
144
+ io.send(sessionId, body);
145
+ const deadline = Math.min(overallDeadline, io.now() + perAttempt);
146
+ while (io.now() < deadline) {
147
+ await io.sleep(500);
148
+ const frame = io.capture(sessionId);
149
+ if (frame === null)
150
+ continue;
151
+ if (hasBeenSubmitted(frame, needle))
152
+ return "ok";
153
+ }
154
+ }
155
+ return "no-ack";
156
+ }
157
+ /**
158
+ * Has `needle` left the input box and landed in the transcript?
159
+ *
160
+ * Present on screen is not enough — text sitting unsubmitted in the input box is
161
+ * also "present". Submission is the moment it appears while the ❯ line no longer
162
+ * holds it.
163
+ */
164
+ export function hasBeenSubmitted(frame, needle) {
165
+ const stillTyped = inputBoxLines(frame).some((l) => flatten(l).includes(needle.slice(0, 24)));
166
+ return !stillTyped && flatten(frame).includes(needle);
167
+ }
168
+ /**
169
+ * The lines inside Claude's input box.
170
+ *
171
+ * A caret alone will not do: Claude echoes each submitted message into the
172
+ * transcript with the SAME `❯` marker, so "a ❯ line contains our text" is true
173
+ * both before and after submitting — the check it was meant to power would
174
+ * never fire. The input box is identified structurally instead, as the region
175
+ * between the last two horizontal rules at the bottom of the frame.
176
+ */
177
+ function inputBoxLines(frame) {
178
+ const lines = frame.split("\n");
179
+ const rules = [];
180
+ lines.forEach((l, i) => { if (CLAUDE_UI.test(l))
181
+ rules.push(i); });
182
+ if (rules.length >= 2) {
183
+ const [open, close] = [rules[rules.length - 2], rules[rules.length - 1]];
184
+ return lines.slice(open + 1, close);
185
+ }
186
+ return lines.filter((l) => INPUT_LINE.test(l)); // no box drawn — best effort
187
+ }
188
+ /** Production wiring for DispatchDeps. */
189
+ const realDeps = {
190
+ resolve: findCuratedPaiProject,
191
+ sessions: liveSessions,
192
+ deliver: submitAndConfirm,
193
+ now: () => Date.now(),
194
+ launch: launchResolvedPaiProject,
195
+ waitReady: waitForReady,
196
+ };
197
+ function ackReason(res) {
198
+ switch (res) {
199
+ case "no-ack": return "session did not accept the message (never reacted)";
200
+ case "no-settle": return "session accepted the message but was still working when the timeout expired";
201
+ case "unreadable": return "session terminal could not be read";
202
+ default: return "";
203
+ }
204
+ }
205
+ /**
206
+ * Resolve `project` to a session and deliver `message`, spawning if needed.
207
+ *
208
+ * Never throws for a routing outcome — see the module comment.
209
+ */
210
+ export async function dispatch(projectName, message, opts = {}, deps = realDeps) {
211
+ const startedAt = deps.now();
212
+ const budgetMs = opts.budgetMs;
213
+ /** Time left in the caller's budget; Infinity when they set none. */
214
+ const left = () => budgetMs === undefined ? Infinity : Math.max(0, budgetMs - (deps.now() - startedAt));
215
+ const spawnTimeoutMs = Math.min(opts.spawnTimeoutMs ?? DEFAULT_SPAWN_TIMEOUT_MS, left());
216
+ const deliverTimeoutMs = () => Math.min(opts.deliverTimeoutMs ?? DEFAULT_DELIVER_TIMEOUT_MS, left());
217
+ const project = await deps.resolve(projectName);
218
+ if (!project) {
219
+ return {
220
+ outcome: "unlaunchable",
221
+ project: projectName,
222
+ session: "",
223
+ reason: `No curated alias for "${projectName}". Bus participation is opt-in: ` +
224
+ `run \`pai project name <identifier> ${projectName}\` to register one.`,
225
+ };
226
+ }
227
+ const label = project.displayName || project.name;
228
+ const body = `${TASK_PREFIX} ${message}`;
229
+ // ── already running? ──
230
+ const existing = findSessionForProject(project, deps.sessions());
231
+ if (existing) {
232
+ if (left() <= 0) {
233
+ return {
234
+ outcome: "unreachable",
235
+ project: label,
236
+ session: existing.label,
237
+ reason: `Budget of ${Math.round((budgetMs ?? 0) / 1000)}s left no time to deliver in.`,
238
+ };
239
+ }
240
+ const res = await deps.deliver(existing.id, body, deliverTimeoutMs());
241
+ if (res === "ok") {
242
+ return { outcome: "delivered", project: label, session: existing.label, reason: "" };
243
+ }
244
+ return {
245
+ outcome: "unreachable",
246
+ project: label,
247
+ session: existing.label,
248
+ reason: `Live session found but ${ackReason(res)}.`,
249
+ };
250
+ }
251
+ if (opts.noSpawn) {
252
+ return {
253
+ outcome: "skipped",
254
+ project: label,
255
+ session: "",
256
+ reason: "No live session and spawning was disabled (--no-spawn).",
257
+ };
258
+ }
259
+ // ── spawn, wait for it to come up, then deliver ──
260
+ let itermSessionId;
261
+ try {
262
+ ({ itermSessionId } = await deps.launch(project));
263
+ }
264
+ catch (err) {
265
+ return {
266
+ outcome: "unreachable",
267
+ project: label,
268
+ session: "",
269
+ reason: `Failed to launch a session: ${err instanceof Error ? err.message : String(err)}`,
270
+ };
271
+ }
272
+ invalidatePaiProjectCache();
273
+ log(`dispatch: launched "${label}" as ${itermSessionId}, waiting for it to accept input`);
274
+ if (!(await deps.waitReady(itermSessionId, spawnTimeoutMs))) {
275
+ return {
276
+ outcome: "unreachable",
277
+ project: label,
278
+ session: label,
279
+ reason: `Launched a session in ${project.rootPath} but it did not become ready ` +
280
+ `within ${Math.round(spawnTimeoutMs / 1000)}s. The tab is open — check why it did not start.`,
281
+ };
282
+ }
283
+ // Booting can eat the whole budget. Say so, rather than attempting a delivery
284
+ // with no time left and blaming the session for not answering.
285
+ if (left() <= 0) {
286
+ return {
287
+ outcome: "unreachable",
288
+ project: label,
289
+ session: label,
290
+ reason: `Launched a session in ${project.rootPath} and it came up, but the ` +
291
+ `${Math.round((budgetMs ?? 0) / 1000)}s budget was spent getting there, ` +
292
+ `leaving none to deliver in. Raise the timeout.`,
293
+ };
294
+ }
295
+ const res = await deps.deliver(itermSessionId, body, deliverTimeoutMs());
296
+ if (res === "ok") {
297
+ return { outcome: "spawned", project: label, session: label, reason: "" };
298
+ }
299
+ // Deliberately NOT "spawned": the tab exists but the work order never landed,
300
+ // and reporting success here is how a task silently disappears.
301
+ return {
302
+ outcome: "unreachable",
303
+ project: label,
304
+ session: label,
305
+ reason: `Spawned a session but ${ackReason(res)}.`,
306
+ };
307
+ }
308
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/daemon/dispatch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,yBAAyB,GAE1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE5F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAmDrC,8EAA8E;AAC9E,MAAM,wBAAwB,GAAG,MAAM,CAAC;AACxC,MAAM,0BAA0B,GAAG,OAAO,CAAC;AAC3C,MAAM,aAAa,GAAG,KAAK,CAAC;AAE5B;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAEpC,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAUnF,MAAM,MAAM,GAAe;IACzB,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,EAAE,CAAC;IACvC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,eAAe,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;IAClD,KAAK;IACL,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;CACtB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAmB,EACnB,QAAgE;IAEhE,MAAM,MAAM,GAAG,IAAI,GAAG,CACpB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;SAChE,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAC/B,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC;QAClC,IAAI,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0EAA0E;AAC1E,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IACpC,MAAM,UAAU,GAAG,4BAA4B,EAAE,CAAC;IAClD,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvB,EAAE,EAAE,CAAC,CAAC,EAAE;QACR,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,oBAAoB,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC;KAC9D,CAAC,CAAC,CAAC;AACN,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,GAAG,OAAO,CAAC;AAC3B,mFAAmF;AACnF,MAAM,SAAS,GAAG,QAAQ,CAAC;AAE3B,2EAA2E;AAC3E,SAAS,OAAO,CAAC,CAAS,IAAY,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAE7E;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiB,EACjB,SAAiB,EACjB,KAAiB,MAAM;IAEvB,MAAM,QAAQ,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACtC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC3B,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAC7B,IAAI,aAAa,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IACxC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,IAAY,EACZ,SAAiB,EACjB,KAAiB,MAAM,EACvB,OAAO,GAAG,CAAC;IAEX,IAAI,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI;QAAE,OAAO,YAAY,CAAC;IAExD,2EAA2E;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/F,IAAI,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAE7B,2EAA2E;IAC3E,uEAAuE;IACvE,2EAA2E;IAC3E,0EAA0E;IAC1E,yCAAyC;IACzC,MAAM,eAAe,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC;IAExF,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;QACpD,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,eAAe;YAAE,MAAM;QACvC,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,CAAC;QAClE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC3B,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACpC,IAAI,KAAK,KAAK,IAAI;gBAAE,SAAS;YAC7B,IAAI,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC;gBAAE,OAAO,IAAI,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9F,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AACxD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACzE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,6BAA6B;AAC/E,CAAC;AAED,0CAA0C;AAC1C,MAAM,QAAQ,GAAiB;IAC7B,OAAO,EAAE,qBAAqB;IAC9B,QAAQ,EAAE,YAAY;IACtB,OAAO,EAAE,gBAAgB;IACzB,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IACrB,MAAM,EAAE,wBAAwB;IAChC,SAAS,EAAE,YAAY;CACxB,CAAC;AAEF,SAAS,SAAS,CAAC,GAAc;IAC/B,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,QAAQ,CAAC,CAAC,OAAO,oDAAoD,CAAC;QAC3E,KAAK,WAAW,CAAC,CAAC,OAAO,6EAA6E,CAAC;QACvG,KAAK,YAAY,CAAC,CAAC,OAAO,oCAAoC,CAAC;QAC/D,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,WAAmB,EACnB,OAAe,EACf,OAAwB,EAAE,EAC1B,OAAqB,QAAQ;IAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,qEAAqE;IACrE,MAAM,IAAI,GAAG,GAAW,EAAE,CACxB,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC;IAEvF,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,wBAAwB,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,MAAM,gBAAgB,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,IAAI,0BAA0B,EAAE,IAAI,EAAE,CAAC,CAAC;IAErG,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,EAAE;YACX,MAAM,EACJ,yBAAyB,WAAW,kCAAkC;gBACtE,uCAAuC,WAAW,qBAAqB;SAC1E,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAClD,MAAM,IAAI,GAAG,GAAG,WAAW,IAAI,OAAO,EAAE,CAAC;IAEzC,yBAAyB;IACzB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YAChB,OAAO;gBACL,OAAO,EAAE,aAAa;gBACtB,OAAO,EAAE,KAAK;gBACd,OAAO,EAAE,QAAQ,CAAC,KAAK;gBACvB,MAAM,EAAE,aAAa,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,+BAA+B;aACvF,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;QACtE,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACvF,CAAC;QACD,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,QAAQ,CAAC,KAAK;YACvB,MAAM,EAAE,0BAA0B,SAAS,CAAC,GAAG,CAAC,GAAG;SACpD,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO;YACL,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,yDAAyD;SAClE,CAAC;IACJ,CAAC;IAED,oDAAoD;IACpD,IAAI,cAAsB,CAAC;IAC3B,IAAI,CAAC;QACH,CAAC,EAAE,cAAc,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,EAAE;YACX,MAAM,EAAE,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC1F,CAAC;IACJ,CAAC;IACD,yBAAyB,EAAE,CAAC;IAC5B,GAAG,CAAC,uBAAuB,KAAK,QAAQ,cAAc,kCAAkC,CAAC,CAAC;IAE1F,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,KAAK;YACd,MAAM,EACJ,yBAAyB,OAAO,CAAC,QAAQ,+BAA+B;gBACxE,UAAU,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,kDAAkD;SAChG,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,+DAA+D;IAC/D,IAAI,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QAChB,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,KAAK;YACd,MAAM,EACJ,yBAAyB,OAAO,CAAC,QAAQ,2BAA2B;gBACpE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,oCAAoC;gBACzE,gDAAgD;SACnD,CAAC;IACJ,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACzE,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAC5E,CAAC;IACD,8EAA8E;IAC9E,gEAAgE;IAChE,OAAO;QACL,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,KAAK;QACd,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,yBAAyB,SAAS,CAAC,GAAG,CAAC,GAAG;KACnD,CAAC;AACJ,CAAC"}
@@ -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":"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"}
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,oFAAoF;AACpF,SAAS,YAAY,CAAC,QAAsB,EAAE,IAAY;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAC9B,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;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAY;IACtD,OAAO,YAAY,CAAC,MAAM,eAAe,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAY;IAC/C,4EAA4E;IAC5E,gFAAgF;IAChF,+EAA+E;IAC/E,uBAAuB;IACvB,OAAO,YAAY,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;AACzD,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;IACD,OAAO,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE1B,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"}