billion-context-pi 0.1.55-pr.266.59 → 0.1.55

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 CHANGED
@@ -120,7 +120,7 @@ Worker runs on Pi's full default toolset - no `--tools` allowlist is applied, so
120
120
 
121
121
  The full delegate result is saved to a file (`/tmp/acp-delegate/<runId>.out`); the tool result and injected notification carry only the **task title + file path** (no preview) - use `read` for the details. This keeps the parent context lean.
122
122
 
123
- - **Interactive (TUI) & RPC modes**: `async:true` (default) runs the child in the background; a short completion notification is injected into the chat when it finishes — **unless the model already read the result file after the run finished** (detected via the `read` tool or a bash command referencing the file), in which case the notification is skipped: the model already has the result, so re-injecting it would only waste context. Set `delegate: { notifyIfRead: "always" }` in `acp.json` to restore the always-inject behavior.
123
+ - **Interactive (TUI) & RPC modes**: `async:true` (default) runs the child in the background; a short completion notification is injected into the chat when it finishes.
124
124
  - **Print / JSON modes** (`pi -p`, SDK): `async:true` auto-downgrades to **synchronous** — the result returns as the tool result in the same turn (the parent exits after one turn, so background injection would be lost).
125
125
  - **Failures are loud, never silent.** A run that fails (nonzero exit, spawn error, watchdog timeout) injects a `FAILED ⚠️` notification carrying a short error excerpt, so a failed delegate cannot hide among sibling completions. If a notification cannot be delivered at all, a recovery notice is attached to the next delegate notification or the next `acp_delegate` / `acp_delegate_wait` / `acp_delegate_cancel` tool result — a dispatched run's failure always reaches the model before it wraps up.
126
126
 
package/dist/config.d.ts CHANGED
@@ -12,12 +12,6 @@ export interface DelegateConfig {
12
12
  * "merged" — delegate token usage folded into the tool-result usage field,
13
13
  * counted as part of the main session totals. */
14
14
  displayUsage?: "merged" | "separate";
15
- /** What happens to the completion notification when the model has already
16
- * read the delegate's result file after the run finished.
17
- * "skip" (default) — the notification is not injected; the model already
18
- * saw the result, so re-injecting it would only waste context.
19
- * "always" — always inject the notification (previous behavior). */
20
- notifyIfRead?: "skip" | "always";
21
15
  }
22
16
  /** Compression tuning fields, shared by all three levels (global, provider,
23
17
  * model). Percentage fields accept a ratio (0.75) or percent string ("75%").
@@ -127,7 +121,6 @@ export declare const DEFAULT_TOOL_OUTPUT_MAX_BYTES = 200000;
127
121
  export declare function resolveDelegate(adapter: AdapterConfig): {
128
122
  enabled: boolean;
129
123
  displayUsage: "merged" | "separate";
130
- notifyIfRead: "skip" | "always";
131
124
  };
132
125
  /** Per-field deepest-wins merge of the three compression levels (global →
133
126
  * provider → model). An undefined field at a deeper level does NOT clear a
@@ -49,30 +49,11 @@ interface DelegateRun {
49
49
  /** True while the run sits in the coalescing notification queue (scheduled
50
50
  * for the next batched flush, not yet delivered). */
51
51
  notifyQueued?: boolean;
52
- /** When the model successfully read this run's result file (read tool, or a
53
- * bash command referencing it). A read at/after finishedAt means the model
54
- * already saw the final result — the completion notification is then
55
- * suppressed (notifyIfRead: "skip"). */
56
- readAt?: number;
57
- /** True when the completion notification was suppressed because the model
58
- * had already read the result file. Treated as delivered (injected=true)
59
- * so wait/recovery never re-surface the result. */
60
- readSuppressed?: boolean;
61
52
  }
62
53
  export declare function addDelegateUsage(u: Usage): void;
63
54
  export declare function getDelegateUsage(): Usage | undefined;
64
55
  export declare function resetDelegateUsage(): void;
65
56
  export declare function setDelegateDisplayUsage(mode: "merged" | "separate"): void;
66
- export declare function setDelegateNotifyIfRead(mode: "skip" | "always"): void;
67
- /** Mark the run whose result file the model just read (via the `read` tool).
68
- * Returns true when a run matched. A read of the final result file after the
69
- * run finished means the model already saw the result — the completion
70
- * notification is then suppressed (notifyIfRead: "skip"). */
71
- export declare function markDelegateResultRead(filePath: string): boolean;
72
- /** Mark runs referenced by a bash command (e.g. `cat <result file>`).
73
- * Matches runIds appearing anywhere in the command string; only existing
74
- * runs are affected, so task text that merely contains "del_..." is inert. */
75
- export declare function markDelegateRunReadByCommand(command: string): boolean;
76
57
  /** Snapshot of currently-running delegate runs, for the TUI status widget. */
77
58
  export declare function runningRunsSnapshot(): {
78
59
  runId: string;
@@ -183,7 +164,6 @@ export declare function formatBatchRunSection(run: DelegateRun): string;
183
164
  * in which case the caller delivers the full payload via formatRunResult(). */
184
165
  export declare function injectedWaitMessage(run: {
185
166
  injected?: boolean;
186
- readSuppressed?: boolean;
187
167
  result?: {
188
168
  file: string;
189
169
  };
@@ -220,18 +200,6 @@ export declare function buildChildArgs(args: DelegateArgs, rolePrompt: string, c
220
200
  * never exited). If a result was delivered (non-empty reply or stderr), the
221
201
  * run counts as completed (0); otherwise it stays null = genuine failure. */
222
202
  export declare function effectiveExitCode(code: number | null, output: string, stderr: string): number | null;
223
- /** Should the completion notification be suppressed because the model already
224
- * read the final result file? Only a read at/after finishedAt counts — a read
225
- * while the run was still in flight (readAt < finishedAt) saw partial output,
226
- * so the notification still goes out. */
227
- export declare function shouldSuppressRead(run: {
228
- readAt?: number;
229
- finishedAt?: number;
230
- }, mode: "skip" | "always"): boolean;
231
- /** Suppress the completion notification for a run the model already read:
232
- * mark it delivered (so wait/recovery/flush never re-surface the result),
233
- * account its usage in separate mode, and log the skip. Idempotent. */
234
- export declare function applyReadSuppression(run: DelegateRun, runId: string): void;
235
203
  /** status (set by finalize from the effective exit code) is the authority for
236
204
  * the FAILED/completed decision; the raw code is diagnostic display only
237
205
  * ("exit ?"), so the notification can never disagree with run.status. */
package/dist/index.js CHANGED
@@ -3610,14 +3610,12 @@ function resolveDelegate(adapter) {
3610
3610
  if (typeof d === "object" && d !== null) {
3611
3611
  return {
3612
3612
  enabled: d.enabled !== false,
3613
- displayUsage: d.displayUsage ?? adapter.displayUsage ?? "separate",
3614
- notifyIfRead: d.notifyIfRead ?? "skip"
3613
+ displayUsage: d.displayUsage ?? adapter.displayUsage ?? "separate"
3615
3614
  };
3616
3615
  }
3617
3616
  return {
3618
3617
  enabled: d !== false,
3619
- displayUsage: adapter.displayUsage ?? "separate",
3620
- notifyIfRead: "skip"
3618
+ displayUsage: adapter.displayUsage ?? "separate"
3621
3619
  };
3622
3620
  }
3623
3621
  function mergeCompress(global, provider, model) {
@@ -10438,39 +10436,6 @@ var delegateDisplayUsage = "separate";
10438
10436
  function setDelegateDisplayUsage(mode) {
10439
10437
  delegateDisplayUsage = mode;
10440
10438
  }
10441
- var delegateNotifyIfRead = "skip";
10442
- function setDelegateNotifyIfRead(mode) {
10443
- delegateNotifyIfRead = mode;
10444
- }
10445
- function markDelegateResultRead(filePath) {
10446
- if (!filePath) return false;
10447
- const abs = resolvePath(filePath);
10448
- let matched = false;
10449
- for (const run of runs.values()) {
10450
- if (join6(OUT_DIR, `${run.runId}.out`) === abs) {
10451
- run.readAt = Date.now();
10452
- suppressIfReadNow(run);
10453
- matched = true;
10454
- }
10455
- }
10456
- return matched;
10457
- }
10458
- function markDelegateRunReadByCommand(command) {
10459
- if (!command) return false;
10460
- const ids = command.match(/del_[a-z0-9]+_[a-z0-9]+/g);
10461
- if (!ids) return false;
10462
- let matched = false;
10463
- const now = Date.now();
10464
- for (const id of new Set(ids)) {
10465
- const run = runs.get(id);
10466
- if (run) {
10467
- run.readAt = now;
10468
- suppressIfReadNow(run);
10469
- matched = true;
10470
- }
10471
- }
10472
- return matched;
10473
- }
10474
10439
  function runningRunsSnapshot() {
10475
10440
  const out = [];
10476
10441
  for (const r of runs.values()) {
@@ -10652,7 +10617,7 @@ Agents (pick by name):
10652
10617
  ${AGENT_NAMES.map(agentListLine).join("\n")}
10653
10618
 
10654
10619
  Behavior:
10655
- \u2022 async=true (default): returns immediately with a runId. The delegate runs in the background. Call acp_delegate_wait({ runId }) to block for its result (up to a timeout); if you let the timeout lapse, or never call wait, a short completion notification (status + file path) is still injected into this chat when it finishes \u2014 unless you already read the result file after it finished, in which case the notification is skipped (you have the result). In one-shot sessions (print/json) async auto-downgrades to sync so the result is returned inline within the same turn. Call acp_delegate again to launch more runs in parallel.
10620
+ \u2022 async=true (default): returns immediately with a runId. The delegate runs in the background. Call acp_delegate_wait({ runId }) to block for its result (up to a timeout); if you let the timeout lapse, or never call wait, a short completion notification (status + file path) is still injected into this chat when it finishes. In one-shot sessions (print/json) async auto-downgrades to sync so the result is returned inline within the same turn. Call acp_delegate again to launch more runs in parallel.
10656
10621
  \u2022 async=false: blocks until the delegate finishes. The full output is saved to a file; the tool result contains the path. Use the \`read\` tool to open the file for the complete content.
10657
10622
 
10658
10623
  There is NO non-blocking status tool. To get a delegate's result, call acp_delegate_wait with the runId \u2014 it blocks until the run finishes or the timeout elapses. Use acp_delegate_cancel only to stop a run you no longer want.
@@ -10862,11 +10827,6 @@ ${first.text}`;
10862
10827
  return result;
10863
10828
  }
10864
10829
  function injectedWaitMessage(run, runId, remainingLine) {
10865
- if (run.readSuppressed) {
10866
- const file2 = run.result?.file;
10867
- const fileLine2 = file2 ? ` The result file is: \`${file2}\`.` : "";
10868
- return `Delegate \`${runId}\` already finished and you read its result file \u2014 no completion notification was injected.${remainingLine}${fileLine2}`;
10869
- }
10870
10830
  if (!run.injected) return null;
10871
10831
  const file = run.result?.file;
10872
10832
  const fileLine = file ? ` If you need details, read the result file: \`${file}\`.` : "";
@@ -11203,13 +11163,6 @@ ${output}`);
11203
11163
  delegateStatusWidget.poke();
11204
11164
  return;
11205
11165
  }
11206
- if (shouldSuppressRead(run, delegateNotifyIfRead)) {
11207
- applyReadSuppression(run, runId);
11208
- debug.event("delegate-done", { runId, code, status: run.status, injected: false, suppressed: true, outLen: output.length, file: file2 });
11209
- logInfo("delegate", { event: "done", runId, agent: args.agent, code, status: run.status, injected: false, suppressed: true, outLen: output.length, file: file2 });
11210
- delegateStatusWidget.poke();
11211
- return;
11212
- }
11213
11166
  scheduleRunNotification(pi, run);
11214
11167
  debug.event("delegate-done", { runId, code, status: run.status, injected: false, queued: true, outLen: output.length, file: file2 });
11215
11168
  logInfo("delegate", { event: "done", runId, agent: args.agent, code, status: run.status, injected: false, queued: true, outLen: output.length, file: file2 });
@@ -11255,7 +11208,7 @@ ${output}`);
11255
11208
  useJsonStream ? `Live activity is streaming to \`${activityFile}\` \u2014 read it anytime to watch the delegate work (tool calls and their output${args.showThinking ? ", plus thinking" : ""}).` : `The reply is streaming to \`${replyFile}\` \u2014 read it anytime to see partial output (this host has no json event mode, so tool activity is not visible).`,
11256
11209
  `A watchdog force-finishes a hung run: no output for ${IDLE_GRACE_MS / 6e4}m, 10s after output ends, or a ${ASYNC_TIMEOUT_MS / 6e4}m hard limit \u2014 the result reflects whatever was produced.`,
11257
11210
  ``,
11258
- `Call acp_delegate_wait({ runId: "${runId}" }) to block for the result (default 10s timeout). If the wait times out, or you skip it, a completion notification (with the result file path) is still injected here automatically when the delegate finishes \u2014 so you may also just continue other work now and let the result find you. (If you already read the result file after it finishes, that notification is skipped \u2014 you have the result.)`
11211
+ `Call acp_delegate_wait({ runId: "${runId}" }) to block for the result (default 10s timeout). If the wait times out, or you skip it, a completion notification (with the result file path) is still injected here automatically when the delegate finishes \u2014 so you may also just continue other work now and let the result find you.`
11259
11212
  ].join("\n");
11260
11213
  }
11261
11214
  const result = await waitForChild(child, signal);
@@ -11340,24 +11293,6 @@ function formatSyncResult(agent, runId, task, r, file) {
11340
11293
  function effectiveExitCode(code, output, stderr) {
11341
11294
  return code ?? (output || stderr ? 0 : null);
11342
11295
  }
11343
- function shouldSuppressRead(run, mode) {
11344
- if (mode !== "skip") return false;
11345
- if (run.readAt === void 0 || run.finishedAt === void 0) return false;
11346
- return run.readAt >= run.finishedAt;
11347
- }
11348
- function applyReadSuppression(run, runId) {
11349
- run.readSuppressed = true;
11350
- run.injected = true;
11351
- if (run.usage && !run.usageReported && delegateDisplayUsage === "separate") {
11352
- addDelegateUsage(run.usage);
11353
- run.usageReported = true;
11354
- }
11355
- debug.event("delegate-inject-suppressed", { runId, reason: "result-file-read", readAt: run.readAt, finishedAt: run.finishedAt });
11356
- logInfo("delegate", { event: "inject-suppressed", runId, reason: "result-file-read", readAt: run.readAt, finishedAt: run.finishedAt });
11357
- }
11358
- function suppressIfReadNow(run) {
11359
- if (shouldSuppressRead(run, delegateNotifyIfRead)) applyReadSuppression(run, run.runId);
11360
- }
11361
11296
  function injectResult(pi, agent, runId, task, status, code, file, timedOut, usage, mode = "separate", usageAlreadyReported, body, activityFile, signal) {
11362
11297
  const send = pi.sendUserMessage;
11363
11298
  if (typeof send !== "function") {
@@ -11420,10 +11355,6 @@ function notifyTerminalFailure(pi, run) {
11420
11355
  const hadWaiter = run.waiter !== void 0;
11421
11356
  run.waiter?.();
11422
11357
  if (hadWaiter || run.consumed) return;
11423
- if (shouldSuppressRead(run, delegateNotifyIfRead)) {
11424
- applyReadSuppression(run, run.runId);
11425
- return;
11426
- }
11427
11358
  scheduleRunNotification(pi, run);
11428
11359
  }
11429
11360
  function formatPayload(header, file, task, body, activityFile) {
@@ -12516,7 +12447,6 @@ function createAcpExtension(adapter = {}) {
12516
12447
  }
12517
12448
  const runtime = createRuntime(adapter);
12518
12449
  wireCompactionDisable(pi, runtime);
12519
- wireDelegateReadTracking(pi);
12520
12450
  wireSessionLifecycle(pi, runtime);
12521
12451
  wireContextTransform(pi, runtime);
12522
12452
  wireSystemPrompt(pi, runtime);
@@ -12553,18 +12483,6 @@ function wireCompactionDisable(pi, runtime) {
12553
12483
  return { cancel: true };
12554
12484
  });
12555
12485
  }
12556
- function wireDelegateReadTracking(pi) {
12557
- pi.on("tool_result", (event) => {
12558
- if (event.isError) return;
12559
- if (event.toolName === "read") {
12560
- const p = event.input.path;
12561
- if (typeof p === "string") markDelegateResultRead(p);
12562
- } else if (event.toolName === "bash") {
12563
- const cmd = event.input.command;
12564
- if (typeof cmd === "string") markDelegateRunReadByCommand(cmd);
12565
- }
12566
- });
12567
- }
12568
12486
  function wireSessionLifecycle(pi, runtime) {
12569
12487
  let ompWarned = false;
12570
12488
  pi.on("session_start", async (_event, ctx) => {
@@ -12590,9 +12508,7 @@ function wireSessionLifecycle(pi, runtime) {
12590
12508
  logInfo("session", { event: "start", sid, cwd: ctx.cwd, debug: runtime.adapter.debug ?? null, version: true ? "0.1.55" : null, model: modelInfo?.id ?? null, modelApi: modelInfo?.api ?? null, contextWindow: modelInfo?.contextWindow ?? null });
12591
12509
  try {
12592
12510
  await runtime.reloadConfig(ctx.cwd);
12593
- const delegateCfg = resolveDelegate(runtime.adapter);
12594
- setDelegateDisplayUsage(delegateCfg.displayUsage);
12595
- setDelegateNotifyIfRead(delegateCfg.notifyIfRead);
12511
+ setDelegateDisplayUsage(resolveDelegate(runtime.adapter).displayUsage);
12596
12512
  } catch (e) {
12597
12513
  logThrow("config", e, { sid, phase: "session_start" });
12598
12514
  }