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.
- package/README.md +49 -1
- package/dist/daemon/cli.js +13 -1
- package/dist/daemon/cli.js.map +1 -1
- package/dist/daemon/core-handlers.d.ts.map +1 -1
- package/dist/daemon/core-handlers.js +24 -0
- package/dist/daemon/core-handlers.js.map +1 -1
- package/dist/daemon/dispatch-cli.d.ts +2 -0
- package/dist/daemon/dispatch-cli.d.ts.map +1 -0
- package/dist/daemon/dispatch-cli.js +120 -0
- package/dist/daemon/dispatch-cli.js.map +1 -0
- package/dist/daemon/dispatch.d.ts +149 -0
- package/dist/daemon/dispatch.d.ts.map +1 -0
- package/dist/daemon/dispatch.js +308 -0
- package/dist/daemon/dispatch.js.map +1 -0
- package/dist/daemon/pai-projects.d.ts +28 -0
- package/dist/daemon/pai-projects.d.ts.map +1 -1
- package/dist/daemon/pai-projects.js +40 -5
- package/dist/daemon/pai-projects.js.map +1 -1
- package/dist/daemon/sessions.d.ts +60 -0
- package/dist/daemon/sessions.d.ts.map +1 -0
- package/dist/daemon/sessions.js +597 -0
- package/dist/daemon/sessions.js.map +1 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/transport/sync-facade.d.ts +6 -0
- package/dist/transport/sync-facade.d.ts.map +1 -1
- package/dist/transport/sync-facade.js +12 -0
- package/dist/transport/sync-facade.js.map +1 -1
- package/package.json +3 -2
|
@@ -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":"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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,
|
|
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
|
-
|
|
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":"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"}
|