instar 1.3.342 → 1.3.344

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/commands/init.d.ts +4 -4
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js.map +1 -1
  4. package/dist/commands/server.d.ts.map +1 -1
  5. package/dist/commands/server.js +47 -0
  6. package/dist/commands/server.js.map +1 -1
  7. package/dist/commands/setup.d.ts +1 -1
  8. package/dist/commands/setup.d.ts.map +1 -1
  9. package/dist/commands/setup.js.map +1 -1
  10. package/dist/core/Config.d.ts +12 -3
  11. package/dist/core/Config.d.ts.map +1 -1
  12. package/dist/core/Config.js +40 -6
  13. package/dist/core/Config.js.map +1 -1
  14. package/dist/core/FrameworkSessionStore.d.ts +1 -1
  15. package/dist/core/FrameworkSessionStore.d.ts.map +1 -1
  16. package/dist/core/PiCliIntelligenceProvider.d.ts +52 -0
  17. package/dist/core/PiCliIntelligenceProvider.d.ts.map +1 -0
  18. package/dist/core/PiCliIntelligenceProvider.js +71 -0
  19. package/dist/core/PiCliIntelligenceProvider.js.map +1 -0
  20. package/dist/core/PostUpdateMigrator.d.ts.map +1 -1
  21. package/dist/core/PostUpdateMigrator.js +14 -0
  22. package/dist/core/PostUpdateMigrator.js.map +1 -1
  23. package/dist/core/PreCompactionFlush.d.ts +1 -1
  24. package/dist/core/PreCompactionFlush.d.ts.map +1 -1
  25. package/dist/core/ResumeValidator.d.ts +1 -1
  26. package/dist/core/ResumeValidator.d.ts.map +1 -1
  27. package/dist/core/SessionManager.d.ts.map +1 -1
  28. package/dist/core/SessionManager.js +35 -1
  29. package/dist/core/SessionManager.js.map +1 -1
  30. package/dist/core/TopicFrameworksStore.d.ts.map +1 -1
  31. package/dist/core/TopicFrameworksStore.js +3 -0
  32. package/dist/core/TopicFrameworksStore.js.map +1 -1
  33. package/dist/core/frameworkInjectionProcesses.d.ts.map +1 -1
  34. package/dist/core/frameworkInjectionProcesses.js +4 -0
  35. package/dist/core/frameworkInjectionProcesses.js.map +1 -1
  36. package/dist/core/frameworkSessionLaunch.d.ts +8 -0
  37. package/dist/core/frameworkSessionLaunch.d.ts.map +1 -1
  38. package/dist/core/frameworkSessionLaunch.js +73 -0
  39. package/dist/core/frameworkSessionLaunch.js.map +1 -1
  40. package/dist/core/intelligenceProviderFactory.d.ts +15 -1
  41. package/dist/core/intelligenceProviderFactory.d.ts.map +1 -1
  42. package/dist/core/intelligenceProviderFactory.js +39 -1
  43. package/dist/core/intelligenceProviderFactory.js.map +1 -1
  44. package/dist/core/types.d.ts +18 -7
  45. package/dist/core/types.d.ts.map +1 -1
  46. package/dist/core/types.js.map +1 -1
  47. package/dist/messaging/shared/telegramRelayPrompt.d.ts +1 -1
  48. package/dist/messaging/shared/telegramRelayPrompt.d.ts.map +1 -1
  49. package/dist/monitoring/SessionReaper.d.ts +1 -1
  50. package/dist/monitoring/SessionReaper.d.ts.map +1 -1
  51. package/dist/monitoring/SessionReaper.js.map +1 -1
  52. package/dist/monitoring/frameworkActivitySignals.d.ts.map +1 -1
  53. package/dist/monitoring/frameworkActivitySignals.js +21 -0
  54. package/dist/monitoring/frameworkActivitySignals.js.map +1 -1
  55. package/dist/monitoring/frameworkProcessSignals.d.ts.map +1 -1
  56. package/dist/monitoring/frameworkProcessSignals.js +22 -0
  57. package/dist/monitoring/frameworkProcessSignals.js.map +1 -1
  58. package/dist/providers/adapters/pi-cli/capabilities.d.ts +31 -0
  59. package/dist/providers/adapters/pi-cli/capabilities.d.ts.map +1 -0
  60. package/dist/providers/adapters/pi-cli/capabilities.js +40 -0
  61. package/dist/providers/adapters/pi-cli/capabilities.js.map +1 -0
  62. package/dist/providers/adapters/pi-cli/config.d.ts +65 -0
  63. package/dist/providers/adapters/pi-cli/config.d.ts.map +1 -0
  64. package/dist/providers/adapters/pi-cli/config.js +43 -0
  65. package/dist/providers/adapters/pi-cli/config.js.map +1 -0
  66. package/dist/providers/adapters/pi-cli/control/piHardKill.d.ts +19 -0
  67. package/dist/providers/adapters/pi-cli/control/piHardKill.d.ts.map +1 -0
  68. package/dist/providers/adapters/pi-cli/control/piHardKill.js +67 -0
  69. package/dist/providers/adapters/pi-cli/control/piHardKill.js.map +1 -0
  70. package/dist/providers/adapters/pi-cli/errors.d.ts +43 -0
  71. package/dist/providers/adapters/pi-cli/errors.d.ts.map +1 -0
  72. package/dist/providers/adapters/pi-cli/errors.js +71 -0
  73. package/dist/providers/adapters/pi-cli/errors.js.map +1 -0
  74. package/dist/providers/adapters/pi-cli/index.d.ts +39 -0
  75. package/dist/providers/adapters/pi-cli/index.d.ts.map +1 -0
  76. package/dist/providers/adapters/pi-cli/index.js +69 -0
  77. package/dist/providers/adapters/pi-cli/index.js.map +1 -0
  78. package/dist/providers/adapters/pi-cli/observability/sessionId.d.ts +27 -0
  79. package/dist/providers/adapters/pi-cli/observability/sessionId.d.ts.map +1 -0
  80. package/dist/providers/adapters/pi-cli/observability/sessionId.js +53 -0
  81. package/dist/providers/adapters/pi-cli/observability/sessionId.js.map +1 -0
  82. package/dist/providers/adapters/pi-cli/policy.d.ts +44 -0
  83. package/dist/providers/adapters/pi-cli/policy.d.ts.map +1 -0
  84. package/dist/providers/adapters/pi-cli/policy.js +74 -0
  85. package/dist/providers/adapters/pi-cli/policy.js.map +1 -0
  86. package/dist/providers/adapters/pi-cli/transport/agenticSessionRpc.d.ts +34 -0
  87. package/dist/providers/adapters/pi-cli/transport/agenticSessionRpc.d.ts.map +1 -0
  88. package/dist/providers/adapters/pi-cli/transport/agenticSessionRpc.js +194 -0
  89. package/dist/providers/adapters/pi-cli/transport/agenticSessionRpc.js.map +1 -0
  90. package/dist/providers/adapters/pi-cli/transport/oneShotCompletion.d.ts +33 -0
  91. package/dist/providers/adapters/pi-cli/transport/oneShotCompletion.d.ts.map +1 -0
  92. package/dist/providers/adapters/pi-cli/transport/oneShotCompletion.js +166 -0
  93. package/dist/providers/adapters/pi-cli/transport/oneShotCompletion.js.map +1 -0
  94. package/dist/providers/adapters/pi-cli/transport/piSpawn.d.ts +87 -0
  95. package/dist/providers/adapters/pi-cli/transport/piSpawn.d.ts.map +1 -0
  96. package/dist/providers/adapters/pi-cli/transport/piSpawn.js +242 -0
  97. package/dist/providers/adapters/pi-cli/transport/piSpawn.js.map +1 -0
  98. package/dist/providers/adapters/pi-cli/transport/rpcClient.d.ts +103 -0
  99. package/dist/providers/adapters/pi-cli/transport/rpcClient.d.ts.map +1 -0
  100. package/dist/providers/adapters/pi-cli/transport/rpcClient.js +238 -0
  101. package/dist/providers/adapters/pi-cli/transport/rpcClient.js.map +1 -0
  102. package/dist/providers/bootRegistration.d.ts +38 -0
  103. package/dist/providers/bootRegistration.d.ts.map +1 -1
  104. package/dist/providers/bootRegistration.js +52 -0
  105. package/dist/providers/bootRegistration.js.map +1 -1
  106. package/dist/providers/parity/rules/skillParityRule.d.ts.map +1 -1
  107. package/dist/providers/parity/rules/skillParityRule.js +6 -0
  108. package/dist/providers/parity/rules/skillParityRule.js.map +1 -1
  109. package/dist/redteam/ScenarioPack.d.ts +161 -0
  110. package/dist/redteam/ScenarioPack.d.ts.map +1 -0
  111. package/dist/redteam/ScenarioPack.js +200 -0
  112. package/dist/redteam/ScenarioPack.js.map +1 -0
  113. package/dist/scaffold/templates.js +1 -1
  114. package/package.json +1 -1
  115. package/src/data/builtin-manifest.json +20 -20
  116. package/src/scaffold/templates.ts +1 -1
  117. package/upgrades/1.3.343.md +49 -0
  118. package/upgrades/1.3.344.md +46 -0
  119. package/upgrades/side-effects/pi-harness-integration.md +82 -0
  120. package/upgrades/side-effects/redteam-harness-phase1-core.md +53 -0
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Spawn helper for the pi CLI.
3
+ *
4
+ * Mirrors gemini-cli/transport/geminiSpawn.ts (process-level, framework-
5
+ * agnostic structure) but encodes the pi-specific credential boundary and the
6
+ * canonical one-shot argv.
7
+ *
8
+ * The argv (`buildPiOneShotArgv`) and the JSONL event-stream facts the
9
+ * one-shot parser depends on were verified HANDS-ON in the P0.1 eval (pi
10
+ * 0.78.1, docs/specs/_drafts/pi-eval-report.md) — they are ground truth, not
11
+ * inferred from docs.
12
+ *
13
+ * stdin discipline: like gemini, the binary may read stdin; without an
14
+ * explicit EOF it can hang waiting for input. `spawn` + an immediate
15
+ * `child.stdin.end()` defeats this (harmless and defensive regardless).
16
+ *
17
+ * Output-byte cap: captured stdout + stderr are hard-capped at
18
+ * `maxOutputBytes` and the result is flagged `truncated` — a runaway/looping
19
+ * child can never OOM the supervising process.
20
+ */
21
+ /** Default output cap: 8 MiB per stream. A one-shot final message is tiny;
22
+ * the cap only fires on a runaway/looping child. */
23
+ export declare const DEFAULT_MAX_OUTPUT_BYTES: number;
24
+ /**
25
+ * The canonical one-shot argv — pinned, no ambiguity. EVAL-VERIFIED (pi
26
+ * 0.78.1, P0.1):
27
+ *
28
+ * pi -p --mode json --no-session --offline [--model <pattern>] <prompt>
29
+ *
30
+ * - `-p` is pi's one-shot/print entrypoint.
31
+ * - `--mode json` emits the typed JSONL event stream on stdout (the format
32
+ * `oneShotCompletion.ts` parses for the assistant `message_end`).
33
+ * - `--no-session` keeps the call stateless — no session file is written
34
+ * (one-shot has nothing to resume).
35
+ * - `--offline` blocks the first-boot binary fetch (pi otherwise pulls `fd` +
36
+ * `ripgrep` from GitHub on first run — eval caveat 2); a one-shot text
37
+ * completion needs neither.
38
+ * - `--model <pattern>` is appended only when a model is configured; when
39
+ * omitted, pi's OWN configured default provider/model applies.
40
+ * - The prompt is the SOLE trailing POSITIONAL — exactly ONE argv element. A
41
+ * leading-dash prompt (`"--help me"`, `"-y do X"`) can NEVER be re-parsed as
42
+ * a flag because it is the last element AND all flags precede it (same
43
+ * argument-injection hardening note as gemini's `-p <prompt>`).
44
+ */
45
+ export declare function buildPiOneShotArgv(model: string | undefined, prompt: string): string[];
46
+ /**
47
+ * Provider billing-capable vars UNCONDITIONALLY deleted from the child env,
48
+ * regardless of allowlist contents. Any of these present could silently route
49
+ * pi onto a billed API key instead of its auth.json subscription / models.json
50
+ * custom-provider path. A false-negative (silent billing) is asymmetrically
51
+ * costly, so the delete is unconditional.
52
+ */
53
+ export declare const PI_BILLING_ENV_VARS: readonly ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN", "OPENAI_API_KEY", "GEMINI_API_KEY", "GOOGLE_API_KEY", "XAI_API_KEY", "GROQ_API_KEY", "OPENROUTER_API_KEY"];
54
+ /**
55
+ * Build the env for a `pi` child process per the no-API-keys rule. Constructs
56
+ * an explicit allowlist (variables not listed are dropped), then
57
+ * UNCONDITIONALLY hard-deletes every billing-capable provider var and clears
58
+ * `CLAUDECODE` (the Claude-Code session marker — pi must not believe it is
59
+ * running inside a Claude Code session).
60
+ */
61
+ export declare function buildPiChildEnv(parentEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
62
+ export interface PiSpawnResult {
63
+ exitCode: number | null;
64
+ stdout: string;
65
+ stderr: string;
66
+ /** True when stdout OR stderr capture hit the byte cap and was truncated. */
67
+ truncated: boolean;
68
+ }
69
+ export interface SpawnPiOptions {
70
+ timeoutMs: number;
71
+ env: NodeJS.ProcessEnv;
72
+ signal?: AbortSignal;
73
+ /** Hard cap on captured stdout/stderr bytes (each stream). */
74
+ maxOutputBytes?: number;
75
+ }
76
+ /**
77
+ * Spawn `pi` with the given argv and wait for completion.
78
+ *
79
+ * - Closes stdin immediately (pi may otherwise block waiting for EOF).
80
+ * - SIGTERM→SIGKILL on timeout (2s grace), AbortSignal handling.
81
+ * - Bounds captured stdout/stderr at `maxOutputBytes` (default 8 MiB),
82
+ * killing the child and flagging `truncated` once the cap is exceeded.
83
+ * - The caller fails only on a non-zero exit code; benign startup stderr lines
84
+ * are not treated as failures.
85
+ */
86
+ export declare function spawnPiAndWait(binary: string, args: string[], options: SpawnPiOptions): Promise<PiSpawnResult>;
87
+ //# sourceMappingURL=piSpawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piSpawn.d.ts","sourceRoot":"","sources":["../../../../../src/providers/adapters/pi-cli/transport/piSpawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH;qDACqD;AACrD,eAAO,MAAM,wBAAwB,QAAkB,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAUtF;AAyCD;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,sKAStB,CAAC;AAEX;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,GAAE,MAAM,CAAC,UAAwB,GACzC,MAAM,CAAC,UAAU,CAoBnB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8DAA8D;IAC9D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAsGxB"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Spawn helper for the pi CLI.
3
+ *
4
+ * Mirrors gemini-cli/transport/geminiSpawn.ts (process-level, framework-
5
+ * agnostic structure) but encodes the pi-specific credential boundary and the
6
+ * canonical one-shot argv.
7
+ *
8
+ * The argv (`buildPiOneShotArgv`) and the JSONL event-stream facts the
9
+ * one-shot parser depends on were verified HANDS-ON in the P0.1 eval (pi
10
+ * 0.78.1, docs/specs/_drafts/pi-eval-report.md) — they are ground truth, not
11
+ * inferred from docs.
12
+ *
13
+ * stdin discipline: like gemini, the binary may read stdin; without an
14
+ * explicit EOF it can hang waiting for input. `spawn` + an immediate
15
+ * `child.stdin.end()` defeats this (harmless and defensive regardless).
16
+ *
17
+ * Output-byte cap: captured stdout + stderr are hard-capped at
18
+ * `maxOutputBytes` and the result is flagged `truncated` — a runaway/looping
19
+ * child can never OOM the supervising process.
20
+ */
21
+ import { spawn } from 'node:child_process';
22
+ /** Default output cap: 8 MiB per stream. A one-shot final message is tiny;
23
+ * the cap only fires on a runaway/looping child. */
24
+ export const DEFAULT_MAX_OUTPUT_BYTES = 8 * 1024 * 1024;
25
+ /**
26
+ * The canonical one-shot argv — pinned, no ambiguity. EVAL-VERIFIED (pi
27
+ * 0.78.1, P0.1):
28
+ *
29
+ * pi -p --mode json --no-session --offline [--model <pattern>] <prompt>
30
+ *
31
+ * - `-p` is pi's one-shot/print entrypoint.
32
+ * - `--mode json` emits the typed JSONL event stream on stdout (the format
33
+ * `oneShotCompletion.ts` parses for the assistant `message_end`).
34
+ * - `--no-session` keeps the call stateless — no session file is written
35
+ * (one-shot has nothing to resume).
36
+ * - `--offline` blocks the first-boot binary fetch (pi otherwise pulls `fd` +
37
+ * `ripgrep` from GitHub on first run — eval caveat 2); a one-shot text
38
+ * completion needs neither.
39
+ * - `--model <pattern>` is appended only when a model is configured; when
40
+ * omitted, pi's OWN configured default provider/model applies.
41
+ * - The prompt is the SOLE trailing POSITIONAL — exactly ONE argv element. A
42
+ * leading-dash prompt (`"--help me"`, `"-y do X"`) can NEVER be re-parsed as
43
+ * a flag because it is the last element AND all flags precede it (same
44
+ * argument-injection hardening note as gemini's `-p <prompt>`).
45
+ */
46
+ export function buildPiOneShotArgv(model, prompt) {
47
+ return [
48
+ '-p',
49
+ '--mode',
50
+ 'json',
51
+ '--no-session',
52
+ '--offline',
53
+ ...(model ? ['--model', model] : []),
54
+ prompt,
55
+ ];
56
+ }
57
+ /**
58
+ * Env allowlist for pi child processes — the no-API-keys rule.
59
+ *
60
+ * Pi authenticates via its OWN `~/.pi/agent/auth.json` (subscription OAuth) or
61
+ * `~/.pi/agent/models.json` (custom-provider keys). HOME is passed through so
62
+ * pi can find those files; PATH so it can run its tools. A billing-capable
63
+ * provider key inherited from the parent process could silently route spend
64
+ * onto an API account — the exact leak class the no-API-keys rule forbids. So
65
+ * this is an explicit ALLOWLIST (anything not listed is dropped) PLUS an
66
+ * unconditional hard-delete of every billing var below.
67
+ */
68
+ const PI_ENV_ALLOWLIST = [
69
+ // Filesystem / user identity — HOME is load-bearing: pi reads
70
+ // ~/.pi/agent/auth.json + models.json relative to it.
71
+ 'HOME',
72
+ 'USER',
73
+ 'LOGNAME',
74
+ // Subprocess execution
75
+ 'PATH',
76
+ 'SHELL',
77
+ 'TMPDIR',
78
+ // Locale
79
+ 'LANG',
80
+ 'LANGUAGE',
81
+ 'LC_ALL',
82
+ 'LC_CTYPE',
83
+ 'LC_MESSAGES',
84
+ // Terminal sizing
85
+ 'COLUMNS',
86
+ 'LINES',
87
+ 'ROWS',
88
+ 'TERM',
89
+ // XDG base-dir conventions
90
+ 'XDG_CONFIG_HOME',
91
+ 'XDG_DATA_HOME',
92
+ 'XDG_CACHE_HOME',
93
+ 'XDG_STATE_HOME',
94
+ ];
95
+ /**
96
+ * Provider billing-capable vars UNCONDITIONALLY deleted from the child env,
97
+ * regardless of allowlist contents. Any of these present could silently route
98
+ * pi onto a billed API key instead of its auth.json subscription / models.json
99
+ * custom-provider path. A false-negative (silent billing) is asymmetrically
100
+ * costly, so the delete is unconditional.
101
+ */
102
+ export const PI_BILLING_ENV_VARS = [
103
+ 'ANTHROPIC_API_KEY',
104
+ 'CLAUDE_CODE_OAUTH_TOKEN',
105
+ 'OPENAI_API_KEY',
106
+ 'GEMINI_API_KEY',
107
+ 'GOOGLE_API_KEY',
108
+ 'XAI_API_KEY',
109
+ 'GROQ_API_KEY',
110
+ 'OPENROUTER_API_KEY',
111
+ ];
112
+ /**
113
+ * Build the env for a `pi` child process per the no-API-keys rule. Constructs
114
+ * an explicit allowlist (variables not listed are dropped), then
115
+ * UNCONDITIONALLY hard-deletes every billing-capable provider var and clears
116
+ * `CLAUDECODE` (the Claude-Code session marker — pi must not believe it is
117
+ * running inside a Claude Code session).
118
+ */
119
+ export function buildPiChildEnv(parentEnv = process.env) {
120
+ const env = {};
121
+ for (const key of PI_ENV_ALLOWLIST) {
122
+ const value = parentEnv[key];
123
+ if (value !== undefined) {
124
+ env[key] = value;
125
+ }
126
+ }
127
+ // Unconditional hard-delete — belt-and-suspenders against any allowlist
128
+ // expansion mistake AND any value that slipped through. Never billed.
129
+ for (const key of PI_BILLING_ENV_VARS) {
130
+ delete env[key];
131
+ }
132
+ // Pi must not inherit the Claude Code session marker.
133
+ delete env['CLAUDECODE'];
134
+ return env;
135
+ }
136
+ /**
137
+ * Spawn `pi` with the given argv and wait for completion.
138
+ *
139
+ * - Closes stdin immediately (pi may otherwise block waiting for EOF).
140
+ * - SIGTERM→SIGKILL on timeout (2s grace), AbortSignal handling.
141
+ * - Bounds captured stdout/stderr at `maxOutputBytes` (default 8 MiB),
142
+ * killing the child and flagging `truncated` once the cap is exceeded.
143
+ * - The caller fails only on a non-zero exit code; benign startup stderr lines
144
+ * are not treated as failures.
145
+ */
146
+ export async function spawnPiAndWait(binary, args, options) {
147
+ const maxBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
148
+ return new Promise((resolve, reject) => {
149
+ const child = spawn(binary, args, {
150
+ env: options.env,
151
+ stdio: ['pipe', 'pipe', 'pipe'],
152
+ });
153
+ const stdoutChunks = [];
154
+ const stderrChunks = [];
155
+ let stdoutBytes = 0;
156
+ let stderrBytes = 0;
157
+ let truncated = false;
158
+ let timedOut = false;
159
+ let aborted = false;
160
+ const timer = setTimeout(() => {
161
+ timedOut = true;
162
+ child.kill('SIGTERM');
163
+ setTimeout(() => child.kill('SIGKILL'), 2000).unref();
164
+ }, options.timeoutMs);
165
+ timer.unref();
166
+ const onAbort = () => {
167
+ aborted = true;
168
+ child.kill('SIGTERM');
169
+ };
170
+ options.signal?.addEventListener('abort', onAbort, { once: true });
171
+ const capTriggered = () => {
172
+ if (truncated)
173
+ return;
174
+ truncated = true;
175
+ // Stop the runaway child once either stream hits the cap. Best-effort.
176
+ child.kill('SIGTERM');
177
+ setTimeout(() => child.kill('SIGKILL'), 2000).unref();
178
+ };
179
+ child.stdout.on('data', (b) => {
180
+ // Any data arriving once the cap is already full means we are dropping
181
+ // output → flag truncated (covers the exact-boundary case where the
182
+ // previous chunk landed us precisely AT the cap).
183
+ if (stdoutBytes >= maxBytes) {
184
+ capTriggered();
185
+ return;
186
+ }
187
+ const remaining = maxBytes - stdoutBytes;
188
+ if (b.length > remaining) {
189
+ stdoutChunks.push(b.subarray(0, remaining));
190
+ stdoutBytes = maxBytes;
191
+ capTriggered();
192
+ }
193
+ else {
194
+ stdoutChunks.push(b);
195
+ stdoutBytes += b.length;
196
+ }
197
+ });
198
+ child.stderr.on('data', (b) => {
199
+ if (stderrBytes >= maxBytes) {
200
+ capTriggered();
201
+ return;
202
+ }
203
+ const remaining = maxBytes - stderrBytes;
204
+ if (b.length > remaining) {
205
+ stderrChunks.push(b.subarray(0, remaining));
206
+ stderrBytes = maxBytes;
207
+ capTriggered();
208
+ }
209
+ else {
210
+ stderrChunks.push(b);
211
+ stderrBytes += b.length;
212
+ }
213
+ });
214
+ child.on('error', (err) => {
215
+ clearTimeout(timer);
216
+ options.signal?.removeEventListener('abort', onAbort);
217
+ reject(err);
218
+ });
219
+ child.on('close', (code) => {
220
+ clearTimeout(timer);
221
+ options.signal?.removeEventListener('abort', onAbort);
222
+ const stdout = Buffer.concat(stdoutChunks).toString('utf-8');
223
+ const stderr = Buffer.concat(stderrChunks).toString('utf-8');
224
+ if (aborted) {
225
+ const e = new Error('Aborted');
226
+ e.name = 'AbortError';
227
+ return reject(e);
228
+ }
229
+ if (timedOut) {
230
+ const e = new Error(`Pi timed out after ${options.timeoutMs}ms`);
231
+ e.signal = 'SIGTERM';
232
+ e.killed = true;
233
+ e.stderr = stderr;
234
+ return reject(e);
235
+ }
236
+ resolve({ exitCode: code, stdout, stderr, truncated });
237
+ });
238
+ // Close stdin immediately so pi doesn't wait for input.
239
+ child.stdin.end();
240
+ });
241
+ }
242
+ //# sourceMappingURL=piSpawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"piSpawn.js","sourceRoot":"","sources":["../../../../../src/providers/adapters/pi-cli/transport/piSpawn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * PiRpcClient — typed client for pi's RPC mode (`pi --mode rpc`).
3
+ *
4
+ * Protocol (verified hands-on in the P0.1 eval, pi 0.78.1, and per upstream
5
+ * docs/rpc.md):
6
+ * - Commands: one JSON object per line on stdin.
7
+ * - Responses: `{"type":"response","command":…,"success":…,"id":…}` lines on
8
+ * stdout, correlated by the optional `id` we attach to every command.
9
+ * - Events: every other stdout line is an agent event (agent_start,
10
+ * turn_start, message_update, tool_execution_start|update|end, turn_end,
11
+ * agent_end, …), streamed asynchronously.
12
+ *
13
+ * FRAMING IS STRICT LF JSONL: split records on `\n` ONLY (tolerating a
14
+ * trailing `\r`). Node's `readline` is NOT protocol-compliant — it also
15
+ * splits on U+2028/U+2029, which are valid INSIDE JSON strings; using it
16
+ * would corrupt any record whose payload contains those code points. The
17
+ * splitter below buffers manually and is exported for direct unit testing.
18
+ *
19
+ * The subscription guard (policy.ts) is enforced by CALLERS at session/call
20
+ * construction — this client is the dumb pipe.
21
+ */
22
+ /** A parsed pi RPC response line. */
23
+ export interface PiRpcResponse {
24
+ id?: string;
25
+ type: 'response';
26
+ command: string;
27
+ success: boolean;
28
+ data?: unknown;
29
+ error?: string;
30
+ }
31
+ /** Any non-response pi event line (agent_start, message_update, …). */
32
+ export interface PiRpcEvent {
33
+ type: string;
34
+ [key: string]: unknown;
35
+ }
36
+ /**
37
+ * Strict-LF JSONL splitter. Feed raw chunks; complete lines invoke `onLine`
38
+ * with the line content (trailing `\r` stripped, empty lines skipped).
39
+ * Returns a function to flush the trailing partial line (used at stream end).
40
+ *
41
+ * Exported for unit tests — the U+2028/U+2029-inside-string case is pinned
42
+ * there so a refactor to `readline` (which would break it) fails loudly.
43
+ */
44
+ export declare function createStrictLfSplitter(onLine: (line: string) => void): {
45
+ push: (chunk: string) => void;
46
+ flush: () => void;
47
+ };
48
+ export interface PiRpcClientOptions {
49
+ /** Absolute path to the pi binary. */
50
+ binaryPath: string;
51
+ /** pi `--model` pattern (`provider/id`). Callers must pass policy first. */
52
+ model?: string;
53
+ /** `--session-dir` (durable transcripts). */
54
+ sessionDir?: string;
55
+ /** `--session-id` (create-or-resume a deterministic session). */
56
+ sessionId?: string;
57
+ /** Run ephemeral (`--no-session`). */
58
+ noSession?: boolean;
59
+ /** Working directory for the pi process (tool execution cwd). */
60
+ cwd?: string;
61
+ /** Extra env on top of the hardened child env (tests use this). */
62
+ envOverrides?: Record<string, string>;
63
+ }
64
+ /**
65
+ * One spawned `pi --mode rpc` process. Create with `PiRpcClient.spawn()`,
66
+ * drive with the typed command methods, consume `events()`, then `close()`.
67
+ */
68
+ export declare class PiRpcClient {
69
+ private readonly child;
70
+ private readonly pending;
71
+ private readonly eventQueue;
72
+ private eventWaiter;
73
+ private closed;
74
+ private exited;
75
+ private nextId;
76
+ static spawn(options: PiRpcClientOptions): PiRpcClient;
77
+ private constructor();
78
+ /** The underlying pid (HardKill primitive integration). */
79
+ get pid(): number | undefined;
80
+ get isExited(): boolean;
81
+ private onLine;
82
+ private enqueueEvent;
83
+ private wakeEventWaiter;
84
+ /** Send a raw command object (an `id` is attached automatically). */
85
+ request(command: Record<string, unknown>, timeoutMs?: number): Promise<PiRpcResponse>;
86
+ prompt(message: string, opts?: {
87
+ streamingBehavior?: 'steer' | 'followUp';
88
+ }): Promise<PiRpcResponse>;
89
+ steer(message: string): Promise<PiRpcResponse>;
90
+ followUp(message: string): Promise<PiRpcResponse>;
91
+ abort(): Promise<PiRpcResponse>;
92
+ getState(): Promise<PiRpcResponse>;
93
+ /**
94
+ * Async iterator over agent events (everything that isn't a correlated
95
+ * response). Ends when the process exits and the queue drains.
96
+ */
97
+ events(): AsyncGenerator<PiRpcEvent>;
98
+ /** End stdin, give pi a grace period, then escalate SIGTERM → SIGKILL. */
99
+ close(): Promise<void>;
100
+ /** Throw a typed error when spawn itself failed (no pid). */
101
+ assertSpawned(): void;
102
+ }
103
+ //# sourceMappingURL=rpcClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpcClient.d.ts","sourceRoot":"","sources":["../../../../../src/providers/adapters/pi-cli/transport/rpcClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAOH,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,uEAAuE;AACvE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG;IACtE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAqBA;AAED,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAKD;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqF;IAC7G,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;IAC/C,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAK;IAEnB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW;IActD,OAAO;IAkBP,2DAA2D;IAC3D,IAAI,GAAG,IAAI,MAAM,GAAG,SAAS,CAE5B;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,OAAO,CAAC,MAAM;IA2Bd,OAAO,CAAC,YAAY;IAKpB,OAAO,CAAC,eAAe;IAMvB,qEAAqE;IACrE,OAAO,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,SAA6B,GAAG,OAAO,CAAC,aAAa,CAAC;IAezG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,aAAa,CAAC;IAIpG,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAI9C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAIjD,KAAK,IAAI,OAAO,CAAC,aAAa,CAAC;IAI/B,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC;IAIlC;;;OAGG;IACI,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC;IAW3C,0EAA0E;IACpE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B,6DAA6D;IAC7D,aAAa,IAAI,IAAI;CAQtB"}