@cat-factory/executor-harness 1.134.0 → 1.137.0
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 +48 -0
- package/dist/agent-capabilities.d.ts +21 -24
- package/dist/agent-capabilities.js +22 -50
- package/dist/agent-runner.d.ts +7 -0
- package/dist/agent-runner.js +26 -183
- package/dist/agent-shared.d.ts +14 -5
- package/dist/agent-shared.js +14 -5
- package/dist/agent.js +22 -9
- package/dist/claude-cli.d.ts +90 -0
- package/dist/claude-cli.js +181 -0
- package/dist/claude-home.d.ts +41 -0
- package/dist/claude-home.js +159 -0
- package/dist/environment-inventory.d.ts +158 -0
- package/dist/environment-inventory.js +412 -0
- package/dist/multi-repo-coding.js +6 -8
- package/dist/pi-workspace.js +80 -58
- package/package.json +2 -2
- package/src/agent-capabilities.ts +25 -51
- package/src/agent-runner.ts +26 -214
- package/src/agent-shared.ts +16 -5
- package/src/agent.ts +23 -9
- package/src/claude-cli.ts +217 -0
- package/src/claude-home.ts +233 -0
- package/src/environment-inventory.ts +512 -0
- package/src/multi-repo-coding.ts +6 -8
- package/src/pi-workspace.ts +90 -58
package/src/pi-workspace.ts
CHANGED
|
@@ -308,6 +308,90 @@ export async function checkoutHasBlueprints(dir: string, multiRepo: boolean): Pr
|
|
|
308
308
|
return checks.some(Boolean)
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
+
/**
|
|
312
|
+
* Run one pass on a SUBSCRIPTION harness (Claude Code / Codex): the leased-credential path, which
|
|
313
|
+
* shares only the checkout preparation with the Pi one.
|
|
314
|
+
*
|
|
315
|
+
* Split out of {@link runAgentInWorkspace} for its cyclomatic budget. It is also the honest seam:
|
|
316
|
+
* everything here is a decision about what the vendor's own CLI is handed, while everything left
|
|
317
|
+
* behind is about the proxy-backed Pi run.
|
|
318
|
+
*/
|
|
319
|
+
async function runSubscriptionInWorkspace(
|
|
320
|
+
harness: 'claude-code' | 'codex',
|
|
321
|
+
spec: AgentRunSpec,
|
|
322
|
+
opts: RunOptions,
|
|
323
|
+
prepared: {
|
|
324
|
+
contextFiles: ContextFileInfo[]
|
|
325
|
+
imageGuidance: string
|
|
326
|
+
workspaceProbe: WorkspaceProbe
|
|
327
|
+
},
|
|
328
|
+
): Promise<PiRunOutcome> {
|
|
329
|
+
const { contextFiles, imageGuidance, workspaceProbe } = prepared
|
|
330
|
+
// Ambient (native) mode authenticates with the developer's own CLI login, so no
|
|
331
|
+
// leased token is required; otherwise the leased subscription token is mandatory.
|
|
332
|
+
if (!spec.ambientAuth && !spec.subscriptionToken) {
|
|
333
|
+
throw new Error(`The ${harness} harness requires a subscription token`)
|
|
334
|
+
}
|
|
335
|
+
const subOutcome = await runSubscriptionHarness(harness, {
|
|
336
|
+
cwd: spec.dir,
|
|
337
|
+
model: spec.model,
|
|
338
|
+
systemPrompt: `${subscriptionSystemPrompt(spec.systemPrompt, contextFiles)}${imageGuidance}`,
|
|
339
|
+
userPrompt: spec.userPrompt,
|
|
340
|
+
...(spec.subscriptionToken ? { subscriptionToken: spec.subscriptionToken } : {}),
|
|
341
|
+
subscriptionBaseUrl: spec.subscriptionBaseUrl,
|
|
342
|
+
...(spec.ambientAuth ? { ambientAuth: true } : {}),
|
|
343
|
+
...(spec.skills?.length ? { skills: spec.skills } : {}),
|
|
344
|
+
...(spec.mcpServers?.length ? { mcpServers: spec.mcpServers } : {}),
|
|
345
|
+
// Codex's own image tool. Passed for both subscription harnesses because the option lives on
|
|
346
|
+
// the shared run options; `runClaudeCode` ignores it, since claude-code has no such tool and
|
|
347
|
+
// (unlike an MCP server) there is nothing to report as unservable — the backend never
|
|
348
|
+
// resolves a codex-served generator onto a claude-code step, because admission refuses it.
|
|
349
|
+
...(spec.generateImages ? { generateImages: true } : {}),
|
|
350
|
+
// `spec.webSearchProxy` is deliberately NOT forwarded. It states whether OUR PROXY serves web
|
|
351
|
+
// research for this run's account, which is what Pi's tools ride and what they would fail
|
|
352
|
+
// without; neither subscription CLI touches that proxy. Claude Code's `WebSearch`/`WebFetch`
|
|
353
|
+
// are served by the vendor the leased subscription already pays and are declared
|
|
354
|
+
// unconditionally (see `CLAUDE_TOOL_SET`), and Codex's surface is per-tool config rather than
|
|
355
|
+
// a list. Passing the proxy's availability here would withhold working tools on the strength
|
|
356
|
+
// of an unrelated deployment's wiring.
|
|
357
|
+
...(opts.agentEnv ? { extraEnv: opts.agentEnv } : {}),
|
|
358
|
+
signal: opts.signal,
|
|
359
|
+
// Run the SAME no-progress guard Pi gets (previously claude-code/codex had none): env
|
|
360
|
+
// defaults merged loosen-only with the kind's tuning + the backend's complexity-scaled
|
|
361
|
+
// no-edit allowance, so a claude-code run that stops making progress is killed early
|
|
362
|
+
// instead of burning the full wall-clock budget. The claude runner consumes it; codex
|
|
363
|
+
// ignores it for now (its stream isn't wired to the guard).
|
|
364
|
+
guardLimits: mergeGuardLimits(progressGuardLimitsFromEnv(), spec.guardLimits),
|
|
365
|
+
expectsEdits: spec.expectsEdits ?? true,
|
|
366
|
+
// What the guard's no-edit bound actually decides on (see `buildWorkspaceProbe`).
|
|
367
|
+
workspaceProbe,
|
|
368
|
+
onActivity: opts.onActivity,
|
|
369
|
+
onProgress: opts.onProgress,
|
|
370
|
+
// The run's tool-call trajectory, the same hook the Pi path feeds — so a subscription run
|
|
371
|
+
// and a proxied one produce the same evidence rather than one of them producing none.
|
|
372
|
+
onSpan: opts.onSpan,
|
|
373
|
+
// The tool-silence window (stuck-run audit F13), opened by whichever CLI actually runs.
|
|
374
|
+
// Wired for BOTH subscription harnesses: each reports tool activity on its own stream, so
|
|
375
|
+
// each can beat the window it opens.
|
|
376
|
+
beginToolWindow: opts.beginToolWindow,
|
|
377
|
+
// Per-slice review capture, so a parallel review's finished slices are persisted as they
|
|
378
|
+
// land rather than only in the terminal output. Only the subscription runners fan work out
|
|
379
|
+
// across subagents, so this is the only path that can produce it.
|
|
380
|
+
onSliceReviews: opts.onSliceReviews,
|
|
381
|
+
// What the CLI reported about the tool servers it loaded. Wired for BOTH subscription
|
|
382
|
+
// harnesses even though only claude-code's stream carries the report today: the hook is a
|
|
383
|
+
// pass-through, and a codex run that never calls it leaves the backend's record honestly
|
|
384
|
+
// absent rather than claiming every server it wired failed to start.
|
|
385
|
+
onToolServers: opts.onToolServers,
|
|
386
|
+
// Stream this run's per-call telemetry to the job's live drain. The subscription
|
|
387
|
+
// harnesses are the only producers of `callMetrics` (Pi's calls are metered by the LLM
|
|
388
|
+
// proxy as they happen), so this is the only path that needs the hook.
|
|
389
|
+
onCallMetric: opts.onCallMetric,
|
|
390
|
+
...(opts.log ? { log: opts.log } : {}),
|
|
391
|
+
})
|
|
392
|
+
return withEffortReport(spec.dir, subOutcome)
|
|
393
|
+
}
|
|
394
|
+
|
|
311
395
|
/**
|
|
312
396
|
* Write Pi's global agent context (`~/.pi/agent/AGENTS.md`) + provider config,
|
|
313
397
|
* then run Pi once in `spec.dir` and return its summary/stats/stderr. The context
|
|
@@ -362,67 +446,15 @@ export async function runAgentInWorkspace(
|
|
|
362
446
|
// the half that matters there anyway.
|
|
363
447
|
const workspaceProbe = await buildWorkspaceProbe(spec, opts.signal)
|
|
364
448
|
|
|
365
|
-
// Subscription harnesses (Claude Code / Codex) authenticate with the leased
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
// push, watchdogs) is unchanged.
|
|
449
|
+
// Subscription harnesses (Claude Code / Codex) authenticate with the leased token and talk
|
|
450
|
+
// direct to the vendor: no proxy config, no AGENTS.md. The system prompt is passed straight to
|
|
451
|
+
// the CLI; everything around this (clone, push, watchdogs) is unchanged.
|
|
369
452
|
if (spec.harness === 'claude-code' || spec.harness === 'codex') {
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
throw new Error(`The ${spec.harness} harness requires a subscription token`)
|
|
374
|
-
}
|
|
375
|
-
const subOutcome = await runSubscriptionHarness(spec.harness, {
|
|
376
|
-
cwd: spec.dir,
|
|
377
|
-
model: spec.model,
|
|
378
|
-
systemPrompt: `${subscriptionSystemPrompt(spec.systemPrompt, contextFiles)}${imageGuidance}`,
|
|
379
|
-
userPrompt: spec.userPrompt,
|
|
380
|
-
...(spec.subscriptionToken ? { subscriptionToken: spec.subscriptionToken } : {}),
|
|
381
|
-
subscriptionBaseUrl: spec.subscriptionBaseUrl,
|
|
382
|
-
...(spec.ambientAuth ? { ambientAuth: true } : {}),
|
|
383
|
-
...(spec.skills?.length ? { skills: spec.skills } : {}),
|
|
384
|
-
...(spec.mcpServers?.length ? { mcpServers: spec.mcpServers } : {}),
|
|
385
|
-
// Codex's own image tool. Passed for both subscription harnesses because the option lives on
|
|
386
|
-
// the shared run options; `runClaudeCode` ignores it, since claude-code has no such tool and
|
|
387
|
-
// (unlike an MCP server) there is nothing to report as unservable — the backend never
|
|
388
|
-
// resolves a codex-served generator onto a claude-code step, because admission refuses it.
|
|
389
|
-
...(spec.generateImages ? { generateImages: true } : {}),
|
|
390
|
-
...(opts.agentEnv ? { extraEnv: opts.agentEnv } : {}),
|
|
391
|
-
signal: opts.signal,
|
|
392
|
-
// Run the SAME no-progress guard Pi gets (previously claude-code/codex had none): env
|
|
393
|
-
// defaults merged loosen-only with the kind's tuning + the backend's complexity-scaled
|
|
394
|
-
// no-edit allowance, so a claude-code run that stops making progress is killed early
|
|
395
|
-
// instead of burning the full wall-clock budget. The claude runner consumes it; codex
|
|
396
|
-
// ignores it for now (its stream isn't wired to the guard).
|
|
397
|
-
guardLimits: mergeGuardLimits(progressGuardLimitsFromEnv(), spec.guardLimits),
|
|
398
|
-
expectsEdits: spec.expectsEdits ?? true,
|
|
399
|
-
// What the guard's no-edit bound actually decides on (see `buildWorkspaceProbe`).
|
|
453
|
+
return await runSubscriptionInWorkspace(spec.harness, spec, opts, {
|
|
454
|
+
contextFiles,
|
|
455
|
+
imageGuidance,
|
|
400
456
|
workspaceProbe,
|
|
401
|
-
onActivity: opts.onActivity,
|
|
402
|
-
onProgress: opts.onProgress,
|
|
403
|
-
// The run's tool-call trajectory, the same hook the Pi path feeds — so a subscription run
|
|
404
|
-
// and a proxied one produce the same evidence rather than one of them producing none.
|
|
405
|
-
onSpan: opts.onSpan,
|
|
406
|
-
// The tool-silence window (stuck-run audit F13), opened by whichever CLI actually runs.
|
|
407
|
-
// Wired for BOTH subscription harnesses: each reports tool activity on its own stream, so
|
|
408
|
-
// each can beat the window it opens.
|
|
409
|
-
beginToolWindow: opts.beginToolWindow,
|
|
410
|
-
// Per-slice review capture, so a parallel review's finished slices are persisted as they
|
|
411
|
-
// land rather than only in the terminal output. Only the subscription runners fan work out
|
|
412
|
-
// across subagents, so this is the only path that can produce it.
|
|
413
|
-
onSliceReviews: opts.onSliceReviews,
|
|
414
|
-
// What the CLI reported about the tool servers it loaded. Wired for BOTH subscription
|
|
415
|
-
// harnesses even though only claude-code's stream carries the report today: the hook is a
|
|
416
|
-
// pass-through, and a codex run that never calls it leaves the backend's record honestly
|
|
417
|
-
// absent rather than claiming every server it wired failed to start.
|
|
418
|
-
onToolServers: opts.onToolServers,
|
|
419
|
-
// Stream this run's per-call telemetry to the job's live drain. The subscription
|
|
420
|
-
// harnesses are the only producers of `callMetrics` (Pi's calls are metered by the LLM
|
|
421
|
-
// proxy as they happen), so this is the only path that needs the hook.
|
|
422
|
-
onCallMetric: opts.onCallMetric,
|
|
423
|
-
...(opts.log ? { log: opts.log } : {}),
|
|
424
457
|
})
|
|
425
|
-
return withEffortReport(spec.dir, subOutcome)
|
|
426
458
|
}
|
|
427
459
|
if (!spec.proxyBaseUrl || !spec.sessionToken) {
|
|
428
460
|
throw new Error('The Pi harness requires proxyBaseUrl and sessionToken')
|