@monoes/monomindcli 2.9.20 → 2.9.22
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/.claude/helpers/control-start.cjs +7 -1
- package/.claude/skills/mastermind-createorg/SKILL.md +26 -3
- package/dist/src/commands/events.d.ts +9 -0
- package/dist/src/commands/events.d.ts.map +1 -0
- package/dist/src/commands/events.js +89 -0
- package/dist/src/commands/events.js.map +1 -0
- package/dist/src/commands/index.d.ts +1 -1
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +2 -1
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts +21 -0
- package/dist/src/commands/org-observe.d.ts.map +1 -1
- package/dist/src/commands/org-observe.js +88 -6
- package/dist/src/commands/org-observe.js.map +1 -1
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +20 -0
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/orgrt/approvals.d.ts +16 -1
- package/dist/src/orgrt/approvals.d.ts.map +1 -1
- package/dist/src/orgrt/approvals.js +44 -2
- package/dist/src/orgrt/approvals.js.map +1 -1
- package/dist/src/orgrt/copilot-runner.d.ts +14 -0
- package/dist/src/orgrt/copilot-runner.d.ts.map +1 -0
- package/dist/src/orgrt/copilot-runner.js +250 -0
- package/dist/src/orgrt/copilot-runner.js.map +1 -0
- package/dist/src/orgrt/crush-runner.d.ts +24 -0
- package/dist/src/orgrt/crush-runner.d.ts.map +1 -0
- package/dist/src/orgrt/crush-runner.js +251 -0
- package/dist/src/orgrt/crush-runner.js.map +1 -0
- package/dist/src/orgrt/daemon.d.ts +40 -1
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +68 -4
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/grok-runner.d.ts +18 -0
- package/dist/src/orgrt/grok-runner.d.ts.map +1 -0
- package/dist/src/orgrt/grok-runner.js +323 -0
- package/dist/src/orgrt/grok-runner.js.map +1 -0
- package/dist/src/orgrt/pi-rpc-runner.d.ts +68 -0
- package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -0
- package/dist/src/orgrt/pi-rpc-runner.js +400 -0
- package/dist/src/orgrt/pi-rpc-runner.js.map +1 -0
- package/dist/src/orgrt/pi-runner.d.ts +16 -0
- package/dist/src/orgrt/pi-runner.d.ts.map +1 -0
- package/dist/src/orgrt/pi-runner.js +264 -0
- package/dist/src/orgrt/pi-runner.js.map +1 -0
- package/dist/src/orgrt/qwen-runner.d.ts +18 -0
- package/dist/src/orgrt/qwen-runner.d.ts.map +1 -0
- package/dist/src/orgrt/qwen-runner.js +267 -0
- package/dist/src/orgrt/qwen-runner.js.map +1 -0
- package/dist/src/orgrt/session.js +1 -1
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +21 -0
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +9 -2
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/orgrt/usage-proxy.d.ts +32 -0
- package/dist/src/orgrt/usage-proxy.d.ts.map +1 -0
- package/dist/src/orgrt/usage-proxy.js +226 -0
- package/dist/src/orgrt/usage-proxy.js.map +1 -0
- package/dist/src/ui/dashboard.html +63 -0
- package/dist/src/ui/orgs.html +8 -1
- package/dist/src/ui/routes-org.mjs +26 -0
- package/dist/src/utils/resource-governor.d.ts.map +1 -1
- package/dist/src/utils/resource-governor.js +11 -2
- package/dist/src/utils/resource-governor.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { AgentRunner, AgentRunArgs, AgentMessage } from './agent-runner.js';
|
|
2
|
+
interface PiContentBlock {
|
|
3
|
+
type: string;
|
|
4
|
+
text?: string;
|
|
5
|
+
thinking?: string;
|
|
6
|
+
id?: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
arguments?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
interface PiRpcMessage {
|
|
11
|
+
content?: PiContentBlock[];
|
|
12
|
+
}
|
|
13
|
+
/** Pure, transport-independent JSONL line decoder — feed it raw string
|
|
14
|
+
* chunks, get back every complete parsed object found so far (silently
|
|
15
|
+
* skipping malformed lines rather than throwing, matching this repo's
|
|
16
|
+
* other subprocess parsers). Exported for unit testing without a real
|
|
17
|
+
* subprocess. */
|
|
18
|
+
export declare class JsonlDecoder {
|
|
19
|
+
private buf;
|
|
20
|
+
feed(chunk: string): Record<string, unknown>[];
|
|
21
|
+
}
|
|
22
|
+
/** Encode a client→server RPC command as one LF-terminated JSON line.
|
|
23
|
+
* Exported for unit testing the exact wire format. */
|
|
24
|
+
export declare function encodePiRpcCommand(cmd: {
|
|
25
|
+
type: string;
|
|
26
|
+
message?: string;
|
|
27
|
+
id?: string;
|
|
28
|
+
}): string;
|
|
29
|
+
/** Extract assistant-visible text and org tool_call fences from a
|
|
30
|
+
* message_end event's `message.content` array. `thinking` blocks are
|
|
31
|
+
* dropped (internal reasoning, not meant for the bus); `toolCall` blocks
|
|
32
|
+
* are pi's own native tool calls, executed autonomously by pi itself —
|
|
33
|
+
* this runner never sees their results and doesn't need to. Exported for
|
|
34
|
+
* unit testing against fixture content arrays. */
|
|
35
|
+
export declare function extractPiRpcText(message: PiRpcMessage): string;
|
|
36
|
+
/** The subset of a spawned child process this runner needs — narrower than
|
|
37
|
+
* node:child_process's real type, and deliberately duck-typed so tests can
|
|
38
|
+
* supply a fake implementation (an EventEmitter-backed fake process) to
|
|
39
|
+
* exercise the full turn-completion state machine without a real `pi`
|
|
40
|
+
* binary. Given the residual protocol-inference risk documented in this
|
|
41
|
+
* file's header, testing the orchestration logic itself — not just the
|
|
42
|
+
* pure JSONL/extraction helpers — is the point of this seam. */
|
|
43
|
+
export interface PiRpcProcess {
|
|
44
|
+
stdin: {
|
|
45
|
+
write(data: string): void;
|
|
46
|
+
} | null;
|
|
47
|
+
stdout: {
|
|
48
|
+
on(event: 'data', cb: (chunk: Buffer) => void): void;
|
|
49
|
+
} | null;
|
|
50
|
+
stderr: {
|
|
51
|
+
on(event: 'data', cb: (chunk: Buffer) => void): void;
|
|
52
|
+
} | null;
|
|
53
|
+
on(event: 'close', cb: (code: number | null) => void): void;
|
|
54
|
+
on(event: 'error', cb: (err: Error) => void): void;
|
|
55
|
+
kill(signal?: string): void;
|
|
56
|
+
}
|
|
57
|
+
export type SpawnPiRpc = (bin: string, args: string[], opts: {
|
|
58
|
+
cwd: string;
|
|
59
|
+
env: Record<string, string | undefined>;
|
|
60
|
+
}) => PiRpcProcess;
|
|
61
|
+
export declare class PiRpcAgentRunner implements AgentRunner {
|
|
62
|
+
private piBin?;
|
|
63
|
+
private spawnFn;
|
|
64
|
+
constructor(piBin?: string | undefined, spawnFn?: SpawnPiRpc);
|
|
65
|
+
run(args: AgentRunArgs): AsyncIterable<AgentMessage>;
|
|
66
|
+
}
|
|
67
|
+
export {};
|
|
68
|
+
//# sourceMappingURL=pi-rpc-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-rpc-runner.d.ts","sourceRoot":"","sources":["../../../src/orgrt/pi-rpc-runner.ts"],"names":[],"mappings":"AA2DA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAUjF,UAAU,cAAc;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAAE;AAC7I,UAAU,YAAY;IAAG,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;CAAE;AAEtD;;;;kBAIkB;AAClB,qBAAa,YAAY;IACvB,OAAO,CAAC,GAAG,CAAM;IACjB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAW7C;CACF;AAED;uDACuD;AACvD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAE/F;AAED;;;;;mDAKmD;AACnD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAK9D;AAED;;;;;;iEAMiE;AACjE,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE;QAAE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5C,MAAM,EAAE;QAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,MAAM,EAAE;QAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5D,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACnD,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CAAE,KAAK,YAAY,CAAC;AAKvI,qBAAa,gBAAiB,YAAW,WAAW;IACtC,OAAO,CAAC,KAAK,CAAC;IAAU,OAAO,CAAC,OAAO;IAAnD,YAAoB,KAAK,CAAC,EAAE,MAAM,YAAA,EAAU,OAAO,GAAE,UAA8B,EAAI;IAEhF,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,CAqR1D;CACF"}
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// packages/@monomind/cli/src/orgrt/pi-rpc-runner.ts
|
|
2
|
+
/**
|
|
3
|
+
* PiRpcAgentRunner — AgentRunner impl backed by the Pi coding agent CLI's
|
|
4
|
+
* `--mode rpc` (session-lifetime, bidirectional JSON-over-stdio), instead of
|
|
5
|
+
* the default PiAgentRunner (pi-runner.ts), which spawns a fresh `pi --mode
|
|
6
|
+
* json` process per mailbox turn.
|
|
7
|
+
*
|
|
8
|
+
* OPT-IN, not the default. Select via role/org `runtime: 'pi-rpc'`. Prefer
|
|
9
|
+
* plain `runtime: 'pi'` (PiAgentRunner) unless you specifically want the
|
|
10
|
+
* benefit this buys: the subprocess stays alive for the WHOLE mailbox
|
|
11
|
+
* session, so conversational context carries naturally (no --session-dir
|
|
12
|
+
* resume guessing) and there's no per-turn spawn/bootstrap cost.
|
|
13
|
+
*
|
|
14
|
+
* Protocol — JSON objects, one per line (LF-delimited), verified against
|
|
15
|
+
* pi-mono's rpc.md doc source directly (literal JSON examples quoted below,
|
|
16
|
+
* not paraphrased from prose — unlike this file's sibling runners, which
|
|
17
|
+
* work from public docs that don't always show raw wire examples):
|
|
18
|
+
*
|
|
19
|
+
* Client → server (this runner sends), each with an optional "id" for
|
|
20
|
+
* response correlation:
|
|
21
|
+
* {"type":"prompt","message":"<text>"} — new/continuing turn
|
|
22
|
+
* {"type":"get_state"} — poll idle/streaming status
|
|
23
|
+
* {"type":"abort"} — not used by this runner
|
|
24
|
+
*
|
|
25
|
+
* Server → client:
|
|
26
|
+
* {"type":"response","command":"prompt","success":true}
|
|
27
|
+
* {"type":"response","command":"get_state","success":true,
|
|
28
|
+
* "data":{"isStreaming":false, ...}}
|
|
29
|
+
* {"type":"agent_start"}
|
|
30
|
+
* {"type":"message_update","usage":{"input":N,"output":N,"totalTokens":N,
|
|
31
|
+
* "cost":{"total":N}},"assistantMessageEvent":{...}} — streaming deltas, ignored
|
|
32
|
+
* {"type":"message_end","message":{"role":"assistant","content":[
|
|
33
|
+
* {"type":"text","text":"..."},
|
|
34
|
+
* {"type":"thinking","thinking":"..."},
|
|
35
|
+
* {"type":"toolCall","id":"call_1","name":"bash","arguments":{...}}
|
|
36
|
+
* ]}}
|
|
37
|
+
*
|
|
38
|
+
* KNOWN GAP — turn-completion detection is a best-effort HEURISTIC, not a
|
|
39
|
+
* confirmed protocol contract: pi executes its own native tools (bash, file
|
|
40
|
+
* edits, …) autonomously inside the RPC session, so a single `prompt` can
|
|
41
|
+
* produce MULTIPLE agent_start/message_end cycles before pi is genuinely
|
|
42
|
+
* done responding, and the docs don't show an explicit "fully idle" event
|
|
43
|
+
* distinct from message_end. This runner sends `get_state` after every
|
|
44
|
+
* message_end and treats `data.isStreaming === false` as "done" — a
|
|
45
|
+
* reasonable, protocol-grounded inference (get_state IS documented), but
|
|
46
|
+
* NOT independently verified against a live pi install (none was available
|
|
47
|
+
* here). If pi's real behavior differs, this could end a turn early or hang
|
|
48
|
+
* waiting past STARTUP_GRACE_MS. Validate against a real `pi --mode rpc`
|
|
49
|
+
* session before relying on this in production; fall back to plain
|
|
50
|
+
* `runtime: 'pi'` if it misbehaves.
|
|
51
|
+
*
|
|
52
|
+
* Org tools (org_send, knowledge_search, ask_human, …) — FENCE PROTOCOL:
|
|
53
|
+
* Pi's own native tools (bash, file edits) execute autonomously inside pi
|
|
54
|
+
* itself and never reach this runner — only org tools ride the shared
|
|
55
|
+
* tool-fence protocol (tool-fence.ts), extracted from message_end's text
|
|
56
|
+
* content and fed back as a new `prompt` command in the SAME session.
|
|
57
|
+
*/
|
|
58
|
+
import { spawn } from 'node:child_process';
|
|
59
|
+
import { join } from 'node:path';
|
|
60
|
+
import { buildToolProtocol, parseToolCalls, executeToolCall, formatToolResults, MAX_TOOL_ROUNDS, TOOL_CALL_RE } from './tool-fence.js';
|
|
61
|
+
/** Distinct from a turn timeout — this is how long we wait for pi to settle
|
|
62
|
+
* to isStreaming:false after a message_end before giving up on the
|
|
63
|
+
* heuristic and treating the turn as complete anyway (better to risk
|
|
64
|
+
* cutting a turn slightly short than to hang forever on a wrong inference). */
|
|
65
|
+
const SETTLE_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes
|
|
66
|
+
const STARTUP_GRACE_MS = 45_000;
|
|
67
|
+
/** Pure, transport-independent JSONL line decoder — feed it raw string
|
|
68
|
+
* chunks, get back every complete parsed object found so far (silently
|
|
69
|
+
* skipping malformed lines rather than throwing, matching this repo's
|
|
70
|
+
* other subprocess parsers). Exported for unit testing without a real
|
|
71
|
+
* subprocess. */
|
|
72
|
+
export class JsonlDecoder {
|
|
73
|
+
buf = '';
|
|
74
|
+
feed(chunk) {
|
|
75
|
+
this.buf += chunk;
|
|
76
|
+
const parts = this.buf.split('\n');
|
|
77
|
+
this.buf = parts.pop() ?? '';
|
|
78
|
+
const out = [];
|
|
79
|
+
for (const line of parts) {
|
|
80
|
+
const trimmed = line.trim();
|
|
81
|
+
if (!trimmed)
|
|
82
|
+
continue;
|
|
83
|
+
try {
|
|
84
|
+
out.push(JSON.parse(trimmed));
|
|
85
|
+
}
|
|
86
|
+
catch { /* skip malformed line */ }
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/** Encode a client→server RPC command as one LF-terminated JSON line.
|
|
92
|
+
* Exported for unit testing the exact wire format. */
|
|
93
|
+
export function encodePiRpcCommand(cmd) {
|
|
94
|
+
return JSON.stringify(cmd) + '\n';
|
|
95
|
+
}
|
|
96
|
+
/** Extract assistant-visible text and org tool_call fences from a
|
|
97
|
+
* message_end event's `message.content` array. `thinking` blocks are
|
|
98
|
+
* dropped (internal reasoning, not meant for the bus); `toolCall` blocks
|
|
99
|
+
* are pi's own native tool calls, executed autonomously by pi itself —
|
|
100
|
+
* this runner never sees their results and doesn't need to. Exported for
|
|
101
|
+
* unit testing against fixture content arrays. */
|
|
102
|
+
export function extractPiRpcText(message) {
|
|
103
|
+
return (message.content ?? [])
|
|
104
|
+
.filter((b) => b.type === 'text' && typeof b.text === 'string')
|
|
105
|
+
.map((b) => b.text)
|
|
106
|
+
.join('\n');
|
|
107
|
+
}
|
|
108
|
+
const defaultSpawnPiRpc = (bin, args, opts) => spawn(bin, args, { cwd: opts.cwd, env: opts.env, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
109
|
+
export class PiRpcAgentRunner {
|
|
110
|
+
piBin;
|
|
111
|
+
spawnFn;
|
|
112
|
+
constructor(piBin, spawnFn = defaultSpawnPiRpc) {
|
|
113
|
+
this.piBin = piBin;
|
|
114
|
+
this.spawnFn = spawnFn;
|
|
115
|
+
}
|
|
116
|
+
async *run(args) {
|
|
117
|
+
const bin = this.piBin || process.env.PI_CLI_BIN || 'pi';
|
|
118
|
+
const sessionDir = join(args.cwd, '.monomind-pi-session');
|
|
119
|
+
const cliArgs = ['--mode', 'rpc', '--approve', '--session-dir', sessionDir];
|
|
120
|
+
if (args.model)
|
|
121
|
+
cliArgs.push('--model', args.model);
|
|
122
|
+
const child = this.spawnFn(bin, cliArgs, {
|
|
123
|
+
cwd: args.cwd,
|
|
124
|
+
env: { ...process.env, PI_TELEMETRY: '0', PI_SKIP_VERSION_CHECK: '1', ...args.env },
|
|
125
|
+
});
|
|
126
|
+
let stderrTail = '';
|
|
127
|
+
child.stderr?.on('data', (c) => { stderrTail = (stderrTail + c.toString()).slice(-4000); });
|
|
128
|
+
const decoder = new JsonlDecoder();
|
|
129
|
+
const eventQueue = [];
|
|
130
|
+
const waiters = [];
|
|
131
|
+
let closed = false;
|
|
132
|
+
let closeCode = null;
|
|
133
|
+
// Bumped only by REAL stdout activity (not the synthetic __closed__/
|
|
134
|
+
// __error__/__hang__ events pushed below) — see silenceWatchdog further
|
|
135
|
+
// down, which uses this to detect a mid-session hang.
|
|
136
|
+
let lastEventAt = Date.now();
|
|
137
|
+
const pushEvents = (evs) => {
|
|
138
|
+
for (const ev of evs) {
|
|
139
|
+
const waiter = waiters.shift();
|
|
140
|
+
if (waiter)
|
|
141
|
+
waiter(ev);
|
|
142
|
+
else
|
|
143
|
+
eventQueue.push(ev);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
child.stdout?.on('data', (c) => { lastEventAt = Date.now(); pushEvents(decoder.feed(c.toString())); });
|
|
147
|
+
// Distinct from `closed` (which WE set to stop routing new commands, e.g.
|
|
148
|
+
// as soon as a hang is suspected) — this is only true once the OS
|
|
149
|
+
// confirms the process actually exited. The finally block below uses it
|
|
150
|
+
// to decide whether a pending SIGKILL escalation is still needed.
|
|
151
|
+
let processExited = false;
|
|
152
|
+
child.on('close', (code) => { closed = true; processExited = true; closeCode = code; pushEvents([{ type: '__closed__', code }]); });
|
|
153
|
+
child.on('error', (err) => { closed = true; pushEvents([{ type: '__error__', error: err }]); });
|
|
154
|
+
const nextEvent = () => {
|
|
155
|
+
const queued = eventQueue.shift();
|
|
156
|
+
if (queued)
|
|
157
|
+
return Promise.resolve(queued);
|
|
158
|
+
if (closed)
|
|
159
|
+
return Promise.resolve({ type: '__closed__', code: closeCode });
|
|
160
|
+
return new Promise((resolve) => waiters.push(resolve));
|
|
161
|
+
};
|
|
162
|
+
const send = (cmd) => {
|
|
163
|
+
child.stdin?.write(encodePiRpcCommand(cmd));
|
|
164
|
+
};
|
|
165
|
+
// SIGTERM→SIGKILL escalation, matching the other subprocess runners'
|
|
166
|
+
// pattern — a hang detection that only ever sends SIGTERM would leave a
|
|
167
|
+
// zombie process behind if pi ignores it.
|
|
168
|
+
const KILL_GRACE_MS = 5000;
|
|
169
|
+
let killTimer;
|
|
170
|
+
const killChild = () => {
|
|
171
|
+
try {
|
|
172
|
+
child.kill('SIGTERM');
|
|
173
|
+
}
|
|
174
|
+
catch { /* already gone */ }
|
|
175
|
+
killTimer = setTimeout(() => { try {
|
|
176
|
+
child.kill('SIGKILL');
|
|
177
|
+
}
|
|
178
|
+
catch { /* already gone */ } }, KILL_GRACE_MS);
|
|
179
|
+
killTimer.unref?.();
|
|
180
|
+
};
|
|
181
|
+
// Startup-hang detection — same rationale as the other subprocess
|
|
182
|
+
// runners' STARTUP_GRACE_MS, applied once at process start rather than
|
|
183
|
+
// per turn since the process is long-lived here.
|
|
184
|
+
let sawAnyEvent = false;
|
|
185
|
+
let hangTimer = setTimeout(() => {
|
|
186
|
+
if (!sawAnyEvent) {
|
|
187
|
+
closed = true;
|
|
188
|
+
killChild();
|
|
189
|
+
pushEvents([{ type: '__hang__' }]);
|
|
190
|
+
}
|
|
191
|
+
}, STARTUP_GRACE_MS);
|
|
192
|
+
const disarmHang = () => { if (!sawAnyEvent) {
|
|
193
|
+
sawAnyEvent = true;
|
|
194
|
+
if (hangTimer) {
|
|
195
|
+
clearTimeout(hangTimer);
|
|
196
|
+
hangTimer = undefined;
|
|
197
|
+
}
|
|
198
|
+
} };
|
|
199
|
+
// Rolling watchdog — catches a hang AFTER the startup check has already
|
|
200
|
+
// passed (e.g. pi wedges mid-session on turn 5), which the one-shot
|
|
201
|
+
// startup timer above can't see since it disarms itself on the first
|
|
202
|
+
// event. Checked periodically rather than a single per-turn timer,
|
|
203
|
+
// since a turn's own wait can legitimately take a long time (real model
|
|
204
|
+
// latency) — what matters is total SILENCE from the process, not how
|
|
205
|
+
// long any one turn takes.
|
|
206
|
+
//
|
|
207
|
+
// PAUSED (not just clock-bumped) whenever this runner isn't actually
|
|
208
|
+
// waiting on pi — either an org tool call is in flight (executeToolCall
|
|
209
|
+
// can run ask_human, which waits on a real person and can legitimately
|
|
210
|
+
// take far longer than MID_SESSION_SILENCE_MS), or there's no turn in
|
|
211
|
+
// flight at all: `for await (const p of args.prompt)` blocks on the
|
|
212
|
+
// ROLE'S OWN MAILBOX (session.ts), which idles for as long as the role
|
|
213
|
+
// has nothing new to do — completely normal, and NOT "pi is wedged".
|
|
214
|
+
// A pure "bump lastEventAt" approach would still let the watchdog fire
|
|
215
|
+
// mid-wait for anything slower than the silence window itself; pausing
|
|
216
|
+
// the check entirely for the duration is the correct fix in both cases.
|
|
217
|
+
let toolCallInFlight = false;
|
|
218
|
+
let turnInFlight = false;
|
|
219
|
+
const MID_SESSION_SILENCE_MS = SETTLE_TIMEOUT_MS; // reuse the same bound the settle-heuristic gives up at
|
|
220
|
+
const silenceWatchdog = setInterval(() => {
|
|
221
|
+
if (closed || toolCallInFlight || !turnInFlight)
|
|
222
|
+
return;
|
|
223
|
+
if (Date.now() - lastEventAt > MID_SESSION_SILENCE_MS) {
|
|
224
|
+
closed = true;
|
|
225
|
+
killChild();
|
|
226
|
+
pushEvents([{ type: '__hang__' }]);
|
|
227
|
+
}
|
|
228
|
+
}, 30_000);
|
|
229
|
+
silenceWatchdog.unref?.();
|
|
230
|
+
try {
|
|
231
|
+
let first = true;
|
|
232
|
+
for await (const p of args.prompt) {
|
|
233
|
+
const text = typeof p === 'string' ? p : (p?.message?.content ?? String(p ?? ''));
|
|
234
|
+
let nextMessage = first ? `${args.systemPrompt}${buildToolProtocol(args.tools)}\n\n---\n\n${text}` : text;
|
|
235
|
+
first = false;
|
|
236
|
+
let turnInputTokens = 0;
|
|
237
|
+
let turnOutputTokens = 0;
|
|
238
|
+
let round = 0;
|
|
239
|
+
// The silence watchdog only applies from here to the end of this
|
|
240
|
+
// turn's work — see its declaration above. Always cleared in
|
|
241
|
+
// `finally` so a thrown error (which exits the loop) can't leave it
|
|
242
|
+
// stuck true and permanently disable the watchdog for the rest of
|
|
243
|
+
// the session.
|
|
244
|
+
turnInFlight = true;
|
|
245
|
+
try {
|
|
246
|
+
turnLoop: for (;;) {
|
|
247
|
+
send({ type: 'prompt', message: nextMessage });
|
|
248
|
+
const collectedText = [];
|
|
249
|
+
const settleDeadline = Date.now() + SETTLE_TIMEOUT_MS;
|
|
250
|
+
let sawMessageEnd = false;
|
|
251
|
+
for (;;) {
|
|
252
|
+
const ev = await nextEvent();
|
|
253
|
+
disarmHang();
|
|
254
|
+
const kind = ev.type;
|
|
255
|
+
// Checked on EVERY event, not only get_state responses — a
|
|
256
|
+
// stream of message_update/message_end events with pi never
|
|
257
|
+
// actually answering get_state (e.g. it doesn't recognize the
|
|
258
|
+
// command, or a response gets lost) would otherwise never hit
|
|
259
|
+
// the deadline check below and could wait past it indefinitely.
|
|
260
|
+
if (sawMessageEnd && Date.now() > settleDeadline)
|
|
261
|
+
break;
|
|
262
|
+
if (kind === '__closed__' || kind === '__error__' || kind === '__hang__') {
|
|
263
|
+
if (kind === '__error__') {
|
|
264
|
+
// Rethrow the ORIGINAL spawn error (not a fresh generic one)
|
|
265
|
+
// so the outer catch's `err.code === 'ENOENT'` check below
|
|
266
|
+
// can actually match it — a wrapped/re-created Error loses
|
|
267
|
+
// the .code property, which silently broke the "missing pi
|
|
268
|
+
// binary" install-instructions message.
|
|
269
|
+
throw ev.error;
|
|
270
|
+
}
|
|
271
|
+
const hangSuspected = kind === '__hang__';
|
|
272
|
+
throw new Error(hangSuspected
|
|
273
|
+
? `PiRpcAgentRunner: pi produced no output within ${STARTUP_GRACE_MS / 1000}s and was killed. ` +
|
|
274
|
+
'This usually means it is stuck on a prompt headless mode has no way to answer. Run `pi` ' +
|
|
275
|
+
`once manually in a real terminal in this project to check, then retry.${stderrTail ? `\nstderr: ${stderrTail.slice(-500)}` : ''}`
|
|
276
|
+
: `PiRpcAgentRunner: pi rpc process ended unexpectedly (${kind})` +
|
|
277
|
+
(stderrTail ? `\nstderr: ${stderrTail.slice(-500)}` : ''));
|
|
278
|
+
}
|
|
279
|
+
if (kind === 'message_update') {
|
|
280
|
+
// Overwrite (not accumulate) — the confirmed example in this
|
|
281
|
+
// file's header shows `usage` as a running total FOR THE
|
|
282
|
+
// CURRENT RESPONSE, so the latest value read during a turn is
|
|
283
|
+
// that turn's correct total. UNCONFIRMED: whether it's scoped
|
|
284
|
+
// to the current prompt or to the whole (session-lifetime) rpc
|
|
285
|
+
// process. If it turns out to be session-cumulative, every
|
|
286
|
+
// turn after the first would over-report by including prior
|
|
287
|
+
// turns' tokens — inflating org budget consumption. Validate
|
|
288
|
+
// against a live pi install before relying on this for tight
|
|
289
|
+
// budget enforcement; this is exactly the kind of gap opt-in
|
|
290
|
+
// 'pi-rpc' (vs. default 'pi') is meant to warn callers about.
|
|
291
|
+
const usage = ev.usage;
|
|
292
|
+
if (usage) {
|
|
293
|
+
turnInputTokens = usage.input ?? turnInputTokens;
|
|
294
|
+
turnOutputTokens = usage.output ?? turnOutputTokens;
|
|
295
|
+
}
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (kind === 'message_end') {
|
|
299
|
+
sawMessageEnd = true;
|
|
300
|
+
const message = ev.message;
|
|
301
|
+
if (message) {
|
|
302
|
+
const text2 = extractPiRpcText(message);
|
|
303
|
+
if (text2)
|
|
304
|
+
collectedText.push(text2);
|
|
305
|
+
}
|
|
306
|
+
// See file header: get_state is the documented, best-effort
|
|
307
|
+
// signal for "pi is done responding to this prompt", since a
|
|
308
|
+
// single prompt can trigger multiple internal tool-use cycles.
|
|
309
|
+
send({ type: 'get_state' });
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (kind === 'response' && ev.command === 'get_state') {
|
|
313
|
+
const data = ev.data;
|
|
314
|
+
if (data?.isStreaming === false)
|
|
315
|
+
break; // turn settled — fall through to tool-fence handling below
|
|
316
|
+
if (Date.now() > settleDeadline)
|
|
317
|
+
break; // heuristic gave up — proceed rather than hang forever
|
|
318
|
+
continue; // still streaming — keep waiting for more message_end cycles
|
|
319
|
+
}
|
|
320
|
+
// agent_start, other response acks, tool_execution_* (pi's own
|
|
321
|
+
// native tools — nothing for this runner to do) — ignored.
|
|
322
|
+
}
|
|
323
|
+
if (!sawMessageEnd)
|
|
324
|
+
break turnLoop; // nothing to extract this round — avoid an infinite loop on an empty settle
|
|
325
|
+
const rawText = collectedText.join('\n');
|
|
326
|
+
const visibleText = rawText.replace(TOOL_CALL_RE, '').trim();
|
|
327
|
+
if (visibleText)
|
|
328
|
+
yield { type: 'assistant', text: visibleText };
|
|
329
|
+
const malformed = [];
|
|
330
|
+
const calls = parseToolCalls([rawText], (raw, err) => malformed.push(`[monomind] ignored malformed tool_call fence (${err}): ${raw.slice(0, 200)}`));
|
|
331
|
+
for (const note of malformed)
|
|
332
|
+
yield { type: 'assistant', text: note };
|
|
333
|
+
if (calls.length === 0)
|
|
334
|
+
break turnLoop;
|
|
335
|
+
round += 1;
|
|
336
|
+
if (round > MAX_TOOL_ROUNDS) {
|
|
337
|
+
yield { type: 'assistant', text: `[monomind] tool-call round cap (${MAX_TOOL_ROUNDS}) reached — dropping ${calls.length} pending tool call(s)` };
|
|
338
|
+
break turnLoop;
|
|
339
|
+
}
|
|
340
|
+
// Pause the silence watchdog for the duration — see its
|
|
341
|
+
// declaration above for why a call like ask_human blocking on a
|
|
342
|
+
// human isn't "pi is wedged". Always un-paused in `finally` so an
|
|
343
|
+
// exception out of executeToolCall can't leave it stuck off.
|
|
344
|
+
toolCallInFlight = true;
|
|
345
|
+
const results = [];
|
|
346
|
+
try {
|
|
347
|
+
for (const call of calls)
|
|
348
|
+
results.push(await executeToolCall(args.tools, call, args.canUseTool));
|
|
349
|
+
}
|
|
350
|
+
finally {
|
|
351
|
+
toolCallInFlight = false;
|
|
352
|
+
lastEventAt = Date.now(); // the post-tool-call silence window starts fresh, not already partway elapsed
|
|
353
|
+
}
|
|
354
|
+
nextMessage = formatToolResults(calls, results);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
finally {
|
|
358
|
+
turnInFlight = false;
|
|
359
|
+
}
|
|
360
|
+
yield {
|
|
361
|
+
type: 'result',
|
|
362
|
+
subtype: 'success',
|
|
363
|
+
input_tokens: turnInputTokens,
|
|
364
|
+
output_tokens: turnOutputTokens,
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
if (err.code === 'ENOENT') {
|
|
370
|
+
throw new Error('PiRpcAgentRunner requires the Pi coding agent CLI (pi) on PATH. ' +
|
|
371
|
+
'Install it: npm install -g @mariozechner/pi-coding-agent, then configure a ' +
|
|
372
|
+
'provider. Or unset the runtime to use Claude.');
|
|
373
|
+
}
|
|
374
|
+
throw err;
|
|
375
|
+
}
|
|
376
|
+
finally {
|
|
377
|
+
if (hangTimer)
|
|
378
|
+
clearTimeout(hangTimer);
|
|
379
|
+
clearInterval(silenceWatchdog);
|
|
380
|
+
if (processExited) {
|
|
381
|
+
// Process is confirmed dead — any pending SIGKILL escalation from
|
|
382
|
+
// killChild() is no longer needed.
|
|
383
|
+
if (killTimer)
|
|
384
|
+
clearTimeout(killTimer);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
// NOT confirmed dead (e.g. the hang/silence watchdog fired and
|
|
388
|
+
// sent SIGTERM, but the process hasn't closed yet). Clearing
|
|
389
|
+
// killTimer here would cancel the SIGKILL escalation mid-grace-
|
|
390
|
+
// period and orphan a process that's ignoring SIGTERM — exactly
|
|
391
|
+
// the wedged case these watchdogs exist to handle. Leave the
|
|
392
|
+
// existing (unref'd) escalation timer running, or arm a fresh one
|
|
393
|
+
// if we're exiting via a path that never called killChild() at all.
|
|
394
|
+
if (!killTimer)
|
|
395
|
+
killChild();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
//# sourceMappingURL=pi-rpc-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-rpc-runner.js","sourceRoot":"","sources":["../../../src/orgrt/pi-rpc-runner.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEvI;;;gFAGgF;AAChF,MAAM,iBAAiB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;AACvD,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAKhC;;;;kBAIkB;AAClB,MAAM,OAAO,YAAY;IACf,GAAG,GAAG,EAAE,CAAC;IACjB,IAAI,CAAC,KAAa;QAChB,IAAI,CAAC,GAAG,IAAI,KAAK,CAAC;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAC7B,MAAM,GAAG,GAA8B,EAAE,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,IAAI,CAAC;gBAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,yBAAyB,CAAC,CAAC;QAC5E,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF;AAED;uDACuD;AACvD,MAAM,UAAU,kBAAkB,CAAC,GAAoD;IACrF,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;AACpC,CAAC;AAED;;;;;mDAKmD;AACnD,MAAM,UAAU,gBAAgB,CAAC,OAAqB;IACpD,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;SAC9D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAc,CAAC;SAC5B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAoBD,MAAM,iBAAiB,GAAe,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CACxD,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAA4B,CAAC;AAEjH,MAAM,OAAO,gBAAgB;IACP,KAAK;IAAmB,OAAO;IAAnD,YAAoB,KAAc,EAAU,OAAO,GAAe,iBAAiB;qBAA/D,KAAK;uBAAmB,OAAO;IAAmC,CAAC;IAEvF,KAAK,CAAC,CAAC,GAAG,CAAC,IAAkB;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC;QACzD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;QAE1D,MAAM,OAAO,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QAC5E,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE;YACvC,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,qBAAqB,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE;SACpF,CAAC,CAAC;QAEH,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,GAAG,UAAU,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEpG,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;QACnC,MAAM,UAAU,GAA8B,EAAE,CAAC;QACjD,MAAM,OAAO,GAAiD,EAAE,CAAC;QACjE,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,IAAI,SAAS,GAAkB,IAAI,CAAC;QACpC,qEAAqE;QACrE,wEAAwE;QACxE,sDAAsD;QACtD,IAAI,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,MAAM,UAAU,GAAG,CAAC,GAA8B,EAAE,EAAE;YACpD,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;gBACrB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;gBAC/B,IAAI,MAAM;oBAAE,MAAM,CAAC,EAAE,CAAC,CAAC;;oBAClB,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC;QACF,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,GAAG,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/G,0EAA0E;QAC1E,kEAAkE;QAClE,wEAAwE;QACxE,kEAAkE;QAClE,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpI,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM,GAAG,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhG,MAAM,SAAS,GAAG,GAAqC,EAAE;YACvD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,CAAC;YAClC,IAAI,MAAM;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,MAAM;gBAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;YAC5E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACzD,CAAC,CAAC;QAEF,MAAM,IAAI,GAAG,CAAC,GAAoD,EAAQ,EAAE;YAC1E,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC;QAEF,qEAAqE;QACrE,wEAAwE;QACxE,0CAA0C;QAC1C,MAAM,aAAa,GAAG,IAAI,CAAC;QAC3B,IAAI,SAAoD,CAAC;QACzD,MAAM,SAAS,GAAG,GAAS,EAAE;YAC3B,IAAI,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;YAC3D,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;YAC7G,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;QACtB,CAAC,CAAC;QAEF,kEAAkE;QAClE,uEAAuE;QACvE,iDAAiD;QACjD,IAAI,WAAW,GAAG,KAAK,CAAC;QACxB,IAAI,SAAS,GAA8C,UAAU,CAAC,GAAG,EAAE;YACzE,IAAI,CAAC,WAAW,EAAE,CAAC;gBAAC,MAAM,GAAG,IAAI,CAAC;gBAAC,SAAS,EAAE,CAAC;gBAAC,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;YAAC,CAAC;QACvF,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAErB,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAAC,WAAW,GAAG,IAAI,CAAC;YAAC,IAAI,SAAS,EAAE,CAAC;gBAAC,YAAY,CAAC,SAAS,CAAC,CAAC;gBAAC,SAAS,GAAG,SAAS,CAAC;YAAC,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC;QAE1I,wEAAwE;QACxE,oEAAoE;QACpE,qEAAqE;QACrE,mEAAmE;QACnE,wEAAwE;QACxE,qEAAqE;QACrE,2BAA2B;QAC3B,EAAE;QACF,qEAAqE;QACrE,wEAAwE;QACxE,uEAAuE;QACvE,sEAAsE;QACtE,oEAAoE;QACpE,uEAAuE;QACvE,qEAAqE;QACrE,uEAAuE;QACvE,uEAAuE;QACvE,wEAAwE;QACxE,IAAI,gBAAgB,GAAG,KAAK,CAAC;QAC7B,IAAI,YAAY,GAAG,KAAK,CAAC;QACzB,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,CAAC,wDAAwD;QAC1G,MAAM,eAAe,GAAmC,WAAW,CAAC,GAAG,EAAE;YACvE,IAAI,MAAM,IAAI,gBAAgB,IAAI,CAAC,YAAY;gBAAE,OAAO;YACxD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,GAAG,sBAAsB,EAAE,CAAC;gBACtD,MAAM,GAAG,IAAI,CAAC;gBACd,SAAS,EAAE,CAAC;gBACZ,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;YACrC,CAAC;QACH,CAAC,EAAE,MAAM,CAAC,CAAC;QACX,eAAe,CAAC,KAAK,EAAE,EAAE,CAAC;QAE1B,IAAI,CAAC;YACH,IAAI,KAAK,GAAG,IAAI,CAAC;YACjB,IAAI,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAClC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;gBAClF,IAAI,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC1G,KAAK,GAAG,KAAK,CAAC;gBAEd,IAAI,eAAe,GAAG,CAAC,CAAC;gBACxB,IAAI,gBAAgB,GAAG,CAAC,CAAC;gBACzB,IAAI,KAAK,GAAG,CAAC,CAAC;gBAEd,iEAAiE;gBACjE,6DAA6D;gBAC7D,oEAAoE;gBACpE,kEAAkE;gBAClE,eAAe;gBACf,YAAY,GAAG,IAAI,CAAC;gBACpB,IAAI,CAAC;oBACL,QAAQ,EAAE,SAAS,CAAC;wBAClB,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;wBAE/C,MAAM,aAAa,GAAa,EAAE,CAAC;wBACnC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,iBAAiB,CAAC;wBACtD,IAAI,aAAa,GAAG,KAAK,CAAC;wBAE1B,SAAS,CAAC;4BACR,MAAM,EAAE,GAAG,MAAM,SAAS,EAAE,CAAC;4BAC7B,UAAU,EAAE,CAAC;4BACb,MAAM,IAAI,GAAG,EAAE,CAAC,IAA0B,CAAC;4BAE3C,2DAA2D;4BAC3D,4DAA4D;4BAC5D,8DAA8D;4BAC9D,8DAA8D;4BAC9D,gEAAgE;4BAChE,IAAI,aAAa,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc;gCAAE,MAAM;4BAExD,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,WAAW,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gCACzE,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;oCACzB,6DAA6D;oCAC7D,2DAA2D;oCAC3D,2DAA2D;oCAC3D,2DAA2D;oCAC3D,wCAAwC;oCACxC,MAAM,EAAE,CAAC,KAAc,CAAC;gCAC1B,CAAC;gCACD,MAAM,aAAa,GAAG,IAAI,KAAK,UAAU,CAAC;gCAC1C,MAAM,IAAI,KAAK,CACb,aAAa;oCACX,CAAC,CAAC,kDAAkD,gBAAgB,GAAG,IAAI,oBAAoB;wCAC7F,0FAA0F;wCAC1F,yEAAyE,UAAU,CAAC,CAAC,CAAC,aAAa,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;oCACpI,CAAC,CAAC,wDAAwD,IAAI,GAAG;wCAC/D,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,UAAU,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9D,CAAC;4BACJ,CAAC;4BAED,IAAI,IAAI,KAAK,gBAAgB,EAAE,CAAC;gCAC9B,6DAA6D;gCAC7D,yDAAyD;gCACzD,8DAA8D;gCAC9D,8DAA8D;gCAC9D,+DAA+D;gCAC/D,2DAA2D;gCAC3D,4DAA4D;gCAC5D,6DAA6D;gCAC7D,6DAA6D;gCAC7D,6DAA6D;gCAC7D,8DAA8D;gCAC9D,MAAM,KAAK,GAAG,EAAE,CAAC,KAAwD,CAAC;gCAC1E,IAAI,KAAK,EAAE,CAAC;oCACV,eAAe,GAAG,KAAK,CAAC,KAAK,IAAI,eAAe,CAAC;oCACjD,gBAAgB,GAAG,KAAK,CAAC,MAAM,IAAI,gBAAgB,CAAC;gCACtD,CAAC;gCACD,SAAS;4BACX,CAAC;4BAED,IAAI,IAAI,KAAK,aAAa,EAAE,CAAC;gCAC3B,aAAa,GAAG,IAAI,CAAC;gCACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAmC,CAAC;gCACvD,IAAI,OAAO,EAAE,CAAC;oCACZ,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;oCACxC,IAAI,KAAK;wCAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gCACvC,CAAC;gCACD,4DAA4D;gCAC5D,6DAA6D;gCAC7D,+DAA+D;gCAC/D,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;gCAC5B,SAAS;4BACX,CAAC;4BAED,IAAI,IAAI,KAAK,UAAU,IAAI,EAAE,CAAC,OAAO,KAAK,WAAW,EAAE,CAAC;gCACtD,MAAM,IAAI,GAAG,EAAE,CAAC,IAA6C,CAAC;gCAC9D,IAAI,IAAI,EAAE,WAAW,KAAK,KAAK;oCAAE,MAAM,CAAC,2DAA2D;gCACnG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc;oCAAE,MAAM,CAAC,uDAAuD;gCAC/F,SAAS,CAAC,6DAA6D;4BACzE,CAAC;4BAED,+DAA+D;4BAC/D,2DAA2D;wBAC7D,CAAC;wBAED,IAAI,CAAC,aAAa;4BAAE,MAAM,QAAQ,CAAC,CAAC,4EAA4E;wBAEhH,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACzC,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;wBAC7D,IAAI,WAAW;4BAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;wBAEhE,MAAM,SAAS,GAAa,EAAE,CAAC;wBAC/B,MAAM,KAAK,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAClE,iDAAiD,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAC9E,CAAC,CAAC;wBACH,KAAK,MAAM,IAAI,IAAI,SAAS;4BAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;wBACtE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;4BAAE,MAAM,QAAQ,CAAC;wBAEvC,KAAK,IAAI,CAAC,CAAC;wBACX,IAAI,KAAK,GAAG,eAAe,EAAE,CAAC;4BAC5B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,mCAAmC,eAAe,wBAAwB,KAAK,CAAC,MAAM,uBAAuB,EAAE,CAAC;4BACjJ,MAAM,QAAQ,CAAC;wBACjB,CAAC;wBAED,wDAAwD;wBACxD,gEAAgE;wBAChE,kEAAkE;wBAClE,6DAA6D;wBAC7D,gBAAgB,GAAG,IAAI,CAAC;wBACxB,MAAM,OAAO,GAAa,EAAE,CAAC;wBAC7B,IAAI,CAAC;4BACH,KAAK,MAAM,IAAI,IAAI,KAAK;gCAAE,OAAO,CAAC,IAAI,CAAC,MAAM,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;wBACnG,CAAC;gCAAS,CAAC;4BACT,gBAAgB,GAAG,KAAK,CAAC;4BACzB,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,8EAA8E;wBAC1G,CAAC;wBACD,WAAW,GAAG,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;oBAClD,CAAC;gBACD,CAAC;wBAAS,CAAC;oBACT,YAAY,GAAG,KAAK,CAAC;gBACvB,CAAC;gBAED,MAAM;oBACJ,IAAI,EAAE,QAAQ;oBACd,OAAO,EAAE,SAAS;oBAClB,YAAY,EAAE,eAAe;oBAC7B,aAAa,EAAE,gBAAgB;iBAChC,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrD,MAAM,IAAI,KAAK,CACb,kEAAkE;oBAClE,6EAA6E;oBAC7E,+CAA+C,CAChD,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;gBAAS,CAAC;YACT,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,aAAa,CAAC,eAAe,CAAC,CAAC;YAC/B,IAAI,aAAa,EAAE,CAAC;gBAClB,kEAAkE;gBAClE,mCAAmC;gBACnC,IAAI,SAAS;oBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,+DAA+D;gBAC/D,6DAA6D;gBAC7D,gEAAgE;gBAChE,gEAAgE;gBAChE,6DAA6D;gBAC7D,kEAAkE;gBAClE,oEAAoE;gBACpE,IAAI,CAAC,SAAS;oBAAE,SAAS,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AgentRunner, AgentRunArgs, AgentMessage } from './agent-runner.js';
|
|
2
|
+
/** Pure JSON-event parser — exported for unit testing against fixture lines
|
|
3
|
+
* (pi-runner.test.ts). */
|
|
4
|
+
export declare function parsePiEvents(lines: string[]): {
|
|
5
|
+
texts: string[];
|
|
6
|
+
rawTexts: string[];
|
|
7
|
+
inputTokens: number;
|
|
8
|
+
outputTokens: number;
|
|
9
|
+
};
|
|
10
|
+
export declare class PiAgentRunner implements AgentRunner {
|
|
11
|
+
private piBin?;
|
|
12
|
+
constructor(piBin?: string | undefined);
|
|
13
|
+
run(args: AgentRunArgs): AsyncIterable<AgentMessage>;
|
|
14
|
+
private runTurn;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=pi-runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi-runner.d.ts","sourceRoot":"","sources":["../../../src/orgrt/pi-runner.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAkBjF;2BAC2B;AAC3B,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG;IAC9C,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;CAChF,CA4BA;AAeD,qBAAa,aAAc,YAAW,WAAW;IACnC,OAAO,CAAC,KAAK,CAAC;IAA1B,YAAoB,KAAK,CAAC,EAAE,MAAM,YAAA,EAAI;IAE/B,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC,YAAY,CAAC,CA0E1D;IAED,OAAO,CAAC,OAAO;CA8FhB"}
|