pi-open-agents 0.1.11 → 0.1.13
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/package.json +1 -1
- package/src/subagent/executor.ts +51 -11
package/package.json
CHANGED
package/src/subagent/executor.ts
CHANGED
|
@@ -339,6 +339,45 @@ function buildTaskArgument(task: string, taskFilePath: string | undefined): stri
|
|
|
339
339
|
return taskFilePath ? `Task: @${taskFilePath}` : `Task: ${task}`;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
// ─── Model Registry (best-effort) ───────────────────────────────────────────
|
|
343
|
+
|
|
344
|
+
interface AuthFactory {
|
|
345
|
+
create(authPath?: string): unknown;
|
|
346
|
+
}
|
|
347
|
+
interface RegistryFactory {
|
|
348
|
+
create(authStore: unknown, modelsPath: string | undefined): ContextWindowLookup;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Build a model registry for cost/context-window enrichment — best-effort and
|
|
353
|
+
* resilient.
|
|
354
|
+
*
|
|
355
|
+
* AuthStorage/ModelRegistry availability and signatures vary across
|
|
356
|
+
* pi-coding-agent host versions (AuthStorage was removed in newer releases;
|
|
357
|
+
* ModelRegistry's create() signature also changed). The registry is purely
|
|
358
|
+
* cosmetic — downstream usage enrichment tolerates a missing registry (see the
|
|
359
|
+
* contextWindowFromMessage / usageFromMessage guards). This must never throw, or
|
|
360
|
+
* subagent delegation breaks entirely. Factories are injectable for testing;
|
|
361
|
+
* pass `{ auth: undefined, model: undefined }` to simulate a host that lacks
|
|
362
|
+
* these symbols.
|
|
363
|
+
*/
|
|
364
|
+
export function buildModelRegistry(
|
|
365
|
+
agentDir: string | undefined,
|
|
366
|
+
factories: { auth?: AuthFactory; model?: RegistryFactory } = {},
|
|
367
|
+
): ContextWindowLookup | undefined {
|
|
368
|
+
const auth = ("auth" in factories ? factories.auth : AuthStorage) as AuthFactory | undefined;
|
|
369
|
+
const model = ("model" in factories ? factories.model : ModelRegistry) as RegistryFactory | undefined;
|
|
370
|
+
try {
|
|
371
|
+
if (!auth || typeof auth.create !== "function") return undefined;
|
|
372
|
+
if (!model || typeof model.create !== "function") return undefined;
|
|
373
|
+
const authPath = agentDir ? path.join(agentDir, "auth.json") : undefined;
|
|
374
|
+
const modelsPath = agentDir ? path.join(agentDir, "models.json") : undefined;
|
|
375
|
+
return model.create(auth.create(authPath), modelsPath);
|
|
376
|
+
} catch {
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
342
381
|
// ─── Main Executor ───────────────────────────────────────────────────────────
|
|
343
382
|
|
|
344
383
|
/**
|
|
@@ -413,13 +452,8 @@ export async function runSubagent(options: RunSubagentOptions): Promise<AgentRes
|
|
|
413
452
|
// ── Resolve pi CLI entry point ──
|
|
414
453
|
const pi = await resolvePi();
|
|
415
454
|
|
|
416
|
-
// ── Build model registry for cost lookups ──
|
|
417
|
-
const modelRegistry =
|
|
418
|
-
AuthStorage.create(
|
|
419
|
-
options.agentDir ? path.join(options.agentDir, "auth.json") : undefined,
|
|
420
|
-
),
|
|
421
|
-
options.agentDir ? path.join(options.agentDir, "models.json") : undefined,
|
|
422
|
-
);
|
|
455
|
+
// ── Build model registry for cost lookups (best-effort) ──
|
|
456
|
+
const modelRegistry = buildModelRegistry(options.agentDir);
|
|
423
457
|
|
|
424
458
|
// ── Build CLI args ──
|
|
425
459
|
const args = [
|
|
@@ -522,10 +556,16 @@ export async function runSubagent(options: RunSubagentOptions): Promise<AgentRes
|
|
|
522
556
|
}
|
|
523
557
|
|
|
524
558
|
if (event.type === "message_end" && event.message) {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
559
|
+
// pi 0.83.0+ emits message_end for EVERY role (user, assistant, toolResult),
|
|
560
|
+
// not just assistant. Only capture text/usage/model from assistant messages —
|
|
561
|
+
// otherwise the echoed user task ("Task: ...") and raw tool results leak into
|
|
562
|
+
// the subagent output when the final assistant turn has no text part.
|
|
563
|
+
if ((event.message as { role?: unknown }).role === "assistant") {
|
|
564
|
+
const text = textFromMessage(event.message);
|
|
565
|
+
if (text !== undefined) output = text;
|
|
566
|
+
updateUsage(usage, usageFromMessage(event.message, modelRegistry));
|
|
567
|
+
model = modelFromMessage(event.message) ?? model;
|
|
568
|
+
}
|
|
529
569
|
emit();
|
|
530
570
|
return;
|
|
531
571
|
}
|