MCPcopy Create free account
hub / github.com/cortexkit/magic-context / PiSubagentRunner

Class PiSubagentRunner

packages/pi-plugin/src/subagent-runner.ts:360–1056  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

358 * the core contract.
359 */
360export class PiSubagentRunner implements SubagentRunner {
361 readonly harness = "pi";
362
363 /**
364 * How to invoke a Pi subagent (command + fixed leading args + shell flag).
365 * Resolved once at construction in the host process so `process.argv[1]`
366 * points at the host `cli.js`. See {@link resolvePiInvocation} for the
367 * cross-platform order; an explicit `options.piBinary` overrides it (test
368 * seam + advanced users who point at their own pi build).
369 */
370 private readonly invocation: PiInvocation;
371 private readonly spawnImpl: typeof childProcess.spawn;
372 private readonly platform: NodeJS.Platform;
373
374 constructor(
375 options: {
376 piBinary?: string;
377 platform?: NodeJS.Platform;
378 /** Test seam for subprocess lifecycle tests. Production uses child_process.spawn. */
379 spawnImpl?: typeof childProcess.spawn;
380 } = {},
381 ) {
382 this.invocation = options.piBinary
383 ? { command: options.piBinary, prefixArgs: [] }
384 : resolvePiInvocation();
385 this.spawnImpl = options.spawnImpl ?? childProcess.spawn;
386 this.platform = options.platform ?? process.platform;
387 }
388
389 async run(options: SubagentRunOptions): Promise<SubagentRunResult> {
390 const models = [options.model, ...(options.fallbackModels ?? [])].filter(
391 (model): model is string => typeof model === "string" && model.length > 0,
392 );
393 const attempts = models.length > 0 ? models : [undefined];
394 let lastResult: SubagentRunResult | null = null;
395 for (let index = 0; index < attempts.length; index += 1) {
396 const model = attempts[index];
397 const attemptOptions = {
398 ...options,
399 model,
400 fallbackModels: undefined,
401 };
402 const result = await this.runOnce(attemptOptions);
403 if (result.ok) return result;
404 lastResult = result;
405 if (index >= attempts.length - 1 || !isFallbackEligible(result.reason)) {
406 return result;
407 }
408 }
409 return (
410 lastResult ?? this.runOnce({ ...options, fallbackModels: undefined })
411 );
412 }
413
414 private async runOnce(
415 options: SubagentRunOptions,
416 ): Promise<SubagentRunResult> {
417 const startTime = Date.now();

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected