pi-cohort 7.1.2 → 7.2.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.
@@ -32,6 +32,7 @@ import {
32
32
  } from "../../shared/settings.ts";
33
33
  import { discoverAvailableSkills, normalizeSkillInput } from "../../agents/skills.ts";
34
34
  import { runSync } from "./execution.ts";
35
+ import type { PiRuntimeIdentity } from "../shared/pi-spawn.ts";
35
36
  import { buildChainSummary } from "../../shared/formatters.ts";
36
37
  import { compactForegroundDetails, getSingleResultOutput, mapConcurrent, resolveChildCwd } from "../../shared/utils.ts";
37
38
  import { recordRun } from "../shared/run-history.ts";
@@ -85,6 +86,7 @@ interface ChainExecutionDetailsInput {
85
86
  }
86
87
 
87
88
  interface ParallelChainRunInput {
89
+ runtime: PiRuntimeIdentity;
88
90
  step: ParallelStep;
89
91
  parallelTemplates: string[];
90
92
  parallelBehaviors: ResolvedStepBehavior[];
@@ -260,6 +262,7 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
260
262
  ? createStructuredOutputRuntime(task.outputSchema, path.join(input.chainDir, "structured-output"))
261
263
  : undefined;
262
264
  const result = await runSync(input.ctx.cwd, input.agents, task.agent, taskStr, {
265
+ runtime: input.runtime,
263
266
  cwd: taskCwd,
264
267
  signal: input.signal,
265
268
  interruptSignal: interruptController.signal,
@@ -347,6 +350,7 @@ async function runParallelChainTasks(input: ParallelChainRunInput): Promise<Sing
347
350
  }
348
351
 
349
352
  interface ChainExecutionParams {
353
+ runtime: PiRuntimeIdentity;
350
354
  chain: ChainStep[];
351
355
  task?: string;
352
356
  agents: AgentConfig[];
@@ -629,6 +633,7 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
629
633
  createParallelDirs(chainDir, stepIndex, step.parallel.length, agentNames);
630
634
 
631
635
  const parallelResults = await runParallelChainTasks({
636
+ runtime: params.runtime,
632
637
  step,
633
638
  parallelTemplates,
634
639
  parallelBehaviors,
@@ -822,6 +827,7 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
822
827
  progressCreated = ensureParallelProgressFile(chainDir, progressCreated, parallelBehaviors);
823
828
  createParallelDirs(chainDir, stepIndex, dynamicParallelStep.parallel.length, dynamicParallelStep.parallel.map((task) => task.agent));
824
829
  const parallelResults = await runParallelChainTasks({
830
+ runtime: params.runtime,
825
831
  step: dynamicParallelStep,
826
832
  parallelTemplates,
827
833
  parallelBehaviors,
@@ -1021,6 +1027,7 @@ export async function executeChain(params: ChainExecutionParams): Promise<ChainE
1021
1027
  ? createStructuredOutputRuntime(seqStep.outputSchema, path.join(chainDir, "structured-output"))
1022
1028
  : undefined;
1023
1029
  const r = await runSync(ctx.cwd, agents, seqStep.agent, stepTask, {
1030
+ runtime: params.runtime,
1024
1031
  cwd: resolveChildCwd(cwd ?? ctx.cwd, seqStep.cwd),
1025
1032
  signal,
1026
1033
  interruptSignal: interruptController.signal,
@@ -41,7 +41,8 @@ import {
41
41
  } from "../../shared/utils.ts";
42
42
  import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
43
43
  import { blockedLine } from "../shared/completion-guard.ts";
44
- import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
44
+ import { getPiSpawnCommand, PiRuntimeLaunchError } from "../shared/pi-spawn.ts";
45
+ import { PINNED_AGENT_DIR_OVERRIDE } from "../../shared/agent-dir.ts";
45
46
  import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
46
47
  import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
47
48
  import { buildPiArgs, cleanupTempDir } from "../shared/pi-args.ts";
@@ -170,11 +171,11 @@ async function runSingleAttempt(
170
171
  let interruptedByControl = false;
171
172
  let pendingControlEvents: ControlEvent[] = init.pendingControlEvents;
172
173
  const controlConfig = init.controlConfig;
173
- const spawnEnv = { ...process.env, ...sharedEnv, ...getSubagentDepthEnv(options.maxSubagentDepth) };
174
+ const spawnEnv = { ...process.env, ...sharedEnv, ...getSubagentDepthEnv(options.maxSubagentDepth), ...(PINNED_AGENT_DIR_OVERRIDE ? { PI_CODING_AGENT_DIR: PINNED_AGENT_DIR_OVERRIDE } : {}) };
174
175
  let observedMutationAttempt = false;
175
176
 
176
- const exitCode = await new Promise<number>((resolve) => {
177
- const spawnSpec = getPiSpawnCommand(args);
177
+ const exitCode = await new Promise<number>((resolve, reject) => {
178
+ const spawnSpec = getPiSpawnCommand(args, options.runtime);
178
179
  const proc = spawn(spawnSpec.command, spawnSpec.args, {
179
180
  cwd: options.cwd ?? runtimeCwd,
180
181
  env: spawnEnv,
@@ -553,6 +554,7 @@ async function runSingleAttempt(
553
554
  if (!result.error) {
554
555
  result.error = error instanceof Error ? error.message : String(error);
555
556
  }
557
+ reject(new PiRuntimeLaunchError(`${options.runtime.nodeExecPath} ${options.runtime.piEntryPath}: ${error.message}`));
556
558
  finish(1);
557
559
  });
558
560
 
@@ -591,7 +593,7 @@ async function runSingleAttempt(
591
593
  removeInterruptListener = () => options.interruptSignal?.removeEventListener("abort", interrupt);
592
594
  }
593
595
  }
594
- });
596
+ }).finally(() => cleanupTempDir(tempDir));
595
597
  result.exitCode = exitCode;
596
598
  return finalizeSingleAttempt(result, progress, {
597
599
  agent,
@@ -640,6 +642,12 @@ export async function runSync(
640
642
  };
641
643
  }
642
644
 
645
+ try {
646
+ getPiSpawnCommand([], options.runtime);
647
+ } catch (error) {
648
+ return failedResult(agentName, task, error instanceof Error ? error.message : String(error));
649
+ }
650
+
643
651
  const childCwd = options.cwd ?? runtimeCwd;
644
652
  let backendSelection: ExecutionBackendSelectionResult;
645
653
  try {
@@ -717,6 +725,7 @@ export async function runSync(
717
725
  try {
718
726
  externalOwner = await (dependencies.createExternalOwner ?? createExternalExecution)({
719
727
  backend: backendSelection.selection.backend,
728
+ runtime: options.runtime,
720
729
  runId: options.runId,
721
730
  childId,
722
731
  cwd: childCwd,
@@ -724,8 +733,8 @@ export async function runSync(
724
733
  signal: options.signal ?? NEVER_ABORTED_SIGNAL,
725
734
  });
726
735
  await externalOwner.ready;
727
- } catch {
728
- lastResult = failedResult(agentName, task, safeExternalFailure("startup"));
736
+ } catch (error) {
737
+ lastResult = failedResult(agentName, task, error instanceof PiRuntimeLaunchError ? error.message : safeExternalFailure("startup"));
729
738
  }
730
739
  }
731
740
 
@@ -746,6 +755,7 @@ export async function runSync(
746
755
  originalTask: task,
747
756
  };
748
757
  let result: SingleResult;
758
+ let runtimeFailure = false;
749
759
  if (externalOwner) {
750
760
  try {
751
761
  result = await (dependencies.runExternalAttempt ?? runExternalSingleAttempt)({
@@ -758,13 +768,20 @@ export async function runSync(
758
768
  options,
759
769
  shared,
760
770
  });
761
- } catch {
762
- result = failedResult(agentName, task, safeExternalFailure("attempt"));
771
+ } catch (error) {
772
+ runtimeFailure = error instanceof PiRuntimeLaunchError;
773
+ result = failedResult(agentName, task, runtimeFailure ? (error as Error).message : safeExternalFailure("attempt"));
763
774
  }
764
775
  } else {
765
- result = await (dependencies.runNativeAttempt ?? runSingleAttempt)(
766
- runtimeCwd, effectiveAgent, taskWithAcceptance, candidate, options, shared,
767
- );
776
+ try {
777
+ result = await (dependencies.runNativeAttempt ?? runSingleAttempt)(
778
+ runtimeCwd, effectiveAgent, taskWithAcceptance, candidate, options, shared,
779
+ );
780
+ } catch (error) {
781
+ if (!(error instanceof PiRuntimeLaunchError)) throw error;
782
+ runtimeFailure = true;
783
+ result = failedResult(agentName, task, error.message);
784
+ }
768
785
  }
769
786
  lastResult = result;
770
787
  sumUsage(aggregateUsage, result.usage);
@@ -782,7 +799,7 @@ export async function runSync(
782
799
  if (attemptSucceeded) {
783
800
  break;
784
801
  }
785
- if (blockedLine(result.error ?? "") || !isRetryableModelFailure(result.error) || i === modelsToTry.length - 1) {
802
+ if (runtimeFailure || blockedLine(result.error ?? "") || !isRetryableModelFailure(result.error) || i === modelsToTry.length - 1) {
786
803
  break;
787
804
  }
788
805
  attemptNotes.push(formatModelAttemptNote(attempt, modelsToTry[i + 1]));
@@ -12,6 +12,7 @@ import type { RunSyncOptions, SingleResult, Usage } from "../../shared/types.ts"
12
12
  import { getSubagentDepthEnv } from "../../shared/types.ts";
13
13
  import { buildPiArgs, cleanupTempDir } from "../shared/pi-args.ts";
14
14
  import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
15
+ import { PINNED_AGENT_DIR_OVERRIDE } from "../../shared/agent-dir.ts";
15
16
  import { isMutatingTool } from "../shared/long-running-guard.ts";
16
17
  import type { ExternalAttemptResult, ExternalExecution } from "../shared/external-execution.ts";
17
18
  import { type AttemptSharedInit, finalizeSingleAttempt, initializeAttempt } from "./attempt-finalization.ts";
@@ -104,8 +105,8 @@ export async function runExternalSingleAttempt(input: RunExternalSingleAttemptIn
104
105
  args.push("--extension", REPORTING_EXTENSION_PATH);
105
106
  if (taskArg !== undefined) args.push(taskArg);
106
107
 
107
- const spawnSpec = getPiSpawnCommand(args);
108
- const mergedEnv: Record<string, string | undefined> = { ...process.env, ...sharedEnv, ...getSubagentDepthEnv(options.maxSubagentDepth) };
108
+ const spawnSpec = getPiSpawnCommand(args, options.runtime);
109
+ const mergedEnv: Record<string, string | undefined> = { ...process.env, ...sharedEnv, ...getSubagentDepthEnv(options.maxSubagentDepth), ...(PINNED_AGENT_DIR_OVERRIDE ? { PI_CODING_AGENT_DIR: PINNED_AGENT_DIR_OVERRIDE } : {}) };
109
110
  const environment: Record<string, string> = {};
110
111
  for (const [key, value] of Object.entries(mergedEnv)) {
111
112
  if (value !== undefined) environment[key] = value;