@cat-factory/executor-harness 1.50.0 → 1.50.2
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/dist/agent-runner.js +35 -28
- package/package.json +3 -3
- package/src/agent-runner.ts +35 -31
package/dist/agent-runner.js
CHANGED
|
@@ -39,7 +39,8 @@ function attributeCumulativeUsage(calls, usage) {
|
|
|
39
39
|
* system-prompt flag — the caller prepends the composed system prompt to it so
|
|
40
40
|
* the role + best-practice context is not lost.
|
|
41
41
|
*/
|
|
42
|
-
function streamCli(
|
|
42
|
+
function streamCli(cli, prompt, opts, env, secrets, onEvent) {
|
|
43
|
+
const { command, args } = cli;
|
|
43
44
|
return new Promise((resolve, reject) => {
|
|
44
45
|
if (opts.signal?.aborted) {
|
|
45
46
|
reject(new Error(`${command} aborted before start`));
|
|
@@ -271,22 +272,25 @@ export async function runClaudeCode(opts) {
|
|
|
271
272
|
: { CLAUDE_CODE_OAUTH_TOKEN: opts.subscriptionToken }),
|
|
272
273
|
};
|
|
273
274
|
try {
|
|
274
|
-
const { stderrTail } = await streamCli(
|
|
275
|
-
'
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
275
|
+
const { stderrTail } = await streamCli({
|
|
276
|
+
command: 'claude',
|
|
277
|
+
args: [
|
|
278
|
+
'-p',
|
|
279
|
+
'--output-format',
|
|
280
|
+
'stream-json',
|
|
281
|
+
'--verbose',
|
|
282
|
+
// The per-run container IS the sandbox, and the run is fully headless (no one
|
|
283
|
+
// to approve a tool call) — so bypass permissions entirely. `acceptEdits`
|
|
284
|
+
// would auto-accept file edits but still gate Bash, which in `-p` mode is then
|
|
285
|
+
// denied, leaving the agent unable to run builds/tests/git to verify its work.
|
|
286
|
+
'--permission-mode',
|
|
287
|
+
'bypassPermissions',
|
|
288
|
+
'--model',
|
|
289
|
+
opts.model,
|
|
290
|
+
'--append-system-prompt',
|
|
291
|
+
opts.systemPrompt,
|
|
292
|
+
],
|
|
293
|
+
}, opts.userPrompt, opts, env, opts.subscriptionToken ? secretsToRedact(opts.subscriptionToken) : [], onEvent);
|
|
290
294
|
attributeCumulativeUsage(calls, usage);
|
|
291
295
|
return {
|
|
292
296
|
summary,
|
|
@@ -472,17 +476,20 @@ export async function runCodex(opts) {
|
|
|
472
476
|
}
|
|
473
477
|
};
|
|
474
478
|
try {
|
|
475
|
-
const { stderrTail } = await streamCli(
|
|
476
|
-
'
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
479
|
+
const { stderrTail } = await streamCli({
|
|
480
|
+
command: 'codex',
|
|
481
|
+
args: [
|
|
482
|
+
'exec',
|
|
483
|
+
'--json',
|
|
484
|
+
'--skip-git-repo-check',
|
|
485
|
+
// The per-run container IS the sandbox; let Codex write files and reach the
|
|
486
|
+
// vendor unrestricted, with no approval prompts (the run is headless).
|
|
487
|
+
'--dangerously-bypass-approvals-and-sandbox',
|
|
488
|
+
'--model',
|
|
489
|
+
opts.model,
|
|
490
|
+
'-',
|
|
491
|
+
],
|
|
492
|
+
}, prompt, opts, codexHome ? { CODEX_HOME: codexHome } : {}, opts.subscriptionToken ? secretsToRedact(opts.subscriptionToken) : [], onEvent);
|
|
486
493
|
// Fallback for a CLI/version that never emits per-turn `last_token_usage`: record a
|
|
487
494
|
// single call from the cumulative total + final text so the run is still observable.
|
|
488
495
|
if (calls.length === 0 && (usage || summary)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cat-factory/executor-harness",
|
|
3
|
-
"version": "1.50.
|
|
3
|
+
"version": "1.50.2",
|
|
4
4
|
"description": "Container payload: a thin TypeScript wrapper that runs the Pi coding agent against a cloned repo and opens a PR. Runs in the Cloudflare Container (and, in local native mode, as a host process); carries no secrets.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"hono": "^4.12.30",
|
|
27
27
|
"typescript": "7.0.2",
|
|
28
28
|
"vitest": "^4.1.10",
|
|
29
|
-
"@cat-factory/server": "0.138.
|
|
30
|
-
"@cat-factory/spend": "0.12.
|
|
29
|
+
"@cat-factory/server": "0.138.11",
|
|
30
|
+
"@cat-factory/spend": "0.12.63"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsc -p tsconfig.json",
|
package/src/agent-runner.ts
CHANGED
|
@@ -118,14 +118,14 @@ function attributeCumulativeUsage(
|
|
|
118
118
|
* the role + best-practice context is not lost.
|
|
119
119
|
*/
|
|
120
120
|
function streamCli(
|
|
121
|
-
command: string,
|
|
122
|
-
args: string[],
|
|
121
|
+
cli: { command: string; args: string[] },
|
|
123
122
|
prompt: string,
|
|
124
123
|
opts: SubscriptionRunOptions,
|
|
125
124
|
env: Record<string, string>,
|
|
126
125
|
secrets: string[],
|
|
127
126
|
onEvent: (event: Record<string, unknown>) => void,
|
|
128
127
|
): Promise<{ stderrTail: string }> {
|
|
128
|
+
const { command, args } = cli
|
|
129
129
|
return new Promise((resolve, reject) => {
|
|
130
130
|
if (opts.signal?.aborted) {
|
|
131
131
|
reject(new Error(`${command} aborted before start`))
|
|
@@ -374,23 +374,25 @@ export async function runClaudeCode(opts: SubscriptionRunOptions): Promise<PiRun
|
|
|
374
374
|
|
|
375
375
|
try {
|
|
376
376
|
const { stderrTail } = await streamCli(
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
377
|
+
{
|
|
378
|
+
command: 'claude',
|
|
379
|
+
args: [
|
|
380
|
+
'-p',
|
|
381
|
+
'--output-format',
|
|
382
|
+
'stream-json',
|
|
383
|
+
'--verbose',
|
|
384
|
+
// The per-run container IS the sandbox, and the run is fully headless (no one
|
|
385
|
+
// to approve a tool call) — so bypass permissions entirely. `acceptEdits`
|
|
386
|
+
// would auto-accept file edits but still gate Bash, which in `-p` mode is then
|
|
387
|
+
// denied, leaving the agent unable to run builds/tests/git to verify its work.
|
|
388
|
+
'--permission-mode',
|
|
389
|
+
'bypassPermissions',
|
|
390
|
+
'--model',
|
|
391
|
+
opts.model,
|
|
392
|
+
'--append-system-prompt',
|
|
393
|
+
opts.systemPrompt,
|
|
394
|
+
],
|
|
395
|
+
},
|
|
394
396
|
opts.userPrompt,
|
|
395
397
|
opts,
|
|
396
398
|
env,
|
|
@@ -594,18 +596,20 @@ export async function runCodex(opts: SubscriptionRunOptions): Promise<PiRunOutco
|
|
|
594
596
|
|
|
595
597
|
try {
|
|
596
598
|
const { stderrTail } = await streamCli(
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
599
|
+
{
|
|
600
|
+
command: 'codex',
|
|
601
|
+
args: [
|
|
602
|
+
'exec',
|
|
603
|
+
'--json',
|
|
604
|
+
'--skip-git-repo-check',
|
|
605
|
+
// The per-run container IS the sandbox; let Codex write files and reach the
|
|
606
|
+
// vendor unrestricted, with no approval prompts (the run is headless).
|
|
607
|
+
'--dangerously-bypass-approvals-and-sandbox',
|
|
608
|
+
'--model',
|
|
609
|
+
opts.model,
|
|
610
|
+
'-',
|
|
611
|
+
],
|
|
612
|
+
},
|
|
609
613
|
prompt,
|
|
610
614
|
opts,
|
|
611
615
|
codexHome ? { CODEX_HOME: codexHome } : {},
|