pi-ptc-subagents 3.1.0 → 3.3.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/CHANGELOG.md CHANGED
@@ -5,6 +5,51 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.3.0] - 2026-10-16
9
+
10
+ ### Added
11
+
12
+ - **A dispatched child's token usage is persisted on the task record, so a child that reported
13
+ nothing still accounts for what it cost (issue #199).** `TaskRecord` gains a top-level optional
14
+ `usage` — the host's own six-field counter (`input`, `output`, `cacheRead`, `cacheWrite`, `cost`,
15
+ `turns`), accumulated from the child's assistant `message_end` blocks — written on **every**
16
+ terminal close for any child the host actually started, independent of `reportChannel` and of the
17
+ outcome: a `"none"` / `"opted-out"` child is accounted for, and so is one that closed `failed` or
18
+ `canceled`. The same measurement now reaches both model-facing readers of that child:
19
+ `ptc_task_output` prints the host's `usage:` line for a child that has no report block to put it
20
+ in, the foreground `ptc_subagent` renders it as a `usage` row in the child-report block it
21
+ already emitted, and both tools' `structuredContent` gains a top-level `usage` with the same four
22
+ numbers the text shows. **`report.usage` is unchanged**: still the four-field view (`input`,
23
+ `output`, `cost`, `turns`), still written only when the close resolves `succeeded` with a report,
24
+ and still what the report block renders — the two agree on the fields they share because both are
25
+ read off the same accumulator. An absent `usage` is a claim rather than a gap: a `running` task
26
+ has not closed yet, a `lost` record was never observed closing, a child that never started has
27
+ nothing to account for, and a record written before the field existed carries none — while a
28
+ record without one renders the block it rendered before, unchanged. ADR-0022 §3 and ADR-0032
29
+ record the amendment.
30
+
31
+ ## [3.2.0] - 2026-10-15
32
+
33
+ ### Added
34
+
35
+ - **A dispatched child can be asked to be read-only, per call.** A new optional `readOnly`
36
+ argument on the dispatch call takes `"strict"` or `"lenient"` — strings only. Strict replaces
37
+ the child's tool list with the read set — `read`, `grep`, `find`,
38
+ `ls`, plus the child report tool when the report contract is on — so the write tools are never
39
+ declared to the child and it cannot call them. Lenient leaves the tool list exactly as it would
40
+ have been and adds one line to the `<pi-ptc-context>` block the child already receives.
41
+ The design first carried a boolean short spelling, and it was reversed before release rather
42
+ than after: measured, pi's validator coerces booleans — `readOnly: 0` would have silently
43
+ become "no tier", a full-capability child for a caller who asked to be read-only — and a string
44
+ enum refuses every wrong-typed value at the schema instead. No released version ever shipped
45
+ the boolean form.
46
+ A tier set on the call beats an agent definition's declared `tools:` for strict; for lenient
47
+ there is no precedence question, because the tier does not touch the tool list at all.
48
+ Nothing breaks for anyone who does not pass it: an ordinary dispatch's argv and prompt are
49
+ unchanged. **This is a capability narrowing, not a security boundary** — `bash` is deliberately
50
+ absent from the strict set, so a strict child cannot run tests or call `git`, and no hostile
51
+ child is contained by any of it. ADR-0041 records the reasoning and the alternatives.
52
+
8
53
  ## [3.1.0] - 2026-10-15
9
54
 
10
55
  ### Changed
@@ -33,6 +78,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
33
78
  third state so a skipped leg is never mistaken for a passing one. See
34
79
  [docs/agents/pi-compat-matrix.md](docs/agents/pi-compat-matrix.md).
35
80
 
81
+ - **The declared peer floor is now a floor you can actually compile against.** `peerDependencies`
82
+ says `>=0.86.0`, but `tsc --noEmit` over pi 0.86.0 used to report 20 errors — the package ran
83
+ there and failed to typecheck, which is the worst of both. It now reports 0, and
84
+ `pnpm run compat:pi 0.86.0` passes every step. The package owns the three post-0.86.0 type
85
+ surfaces (`ToolExposure`, and `outputSchema` / `exposure` / `defaultActive` on `ToolDefinition`)
86
+ so `src/` depends on no pi newer than the floor; those fields arrived in 0.99.0, and a pi that
87
+ does not read them is unaffected by their presence.
88
+
89
+ Note the two floors are different things: **0.99.0 is where those capabilities appear** —
90
+ `isError`, codemode, `exposure`, `structuredContent` — and this package still falls back
91
+ below it. **0.86.0 is the floor it compiles and runs on.** An earlier revision of these notes
92
+ recorded 0.86.x/0.87.x as type-broken; that was measured before this work and no longer holds.
93
+
36
94
  ### Documentation
37
95
 
38
96
  - Measured capability and feature-surface matrices across all 14 published pi versions from
@@ -164,8 +222,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
164
222
  binding list itself is unchanged, and `powershell` is currently not reachable from PTC
165
223
  programs even when enabled (tracked separately).
166
224
 
225
+ [3.3.0]: https://github.com/a1121611810/pi-ptc-subagents/compare/v3.2.0...v3.3.0
226
+ [3.2.0]: https://github.com/a1121611810/pi-ptc-subagents/compare/v3.1.0...v3.2.0
167
227
  [3.1.0]: https://github.com/a1121611810/pi-ptc-subagents/compare/v3.0.0...v3.1.0
168
- [Unreleased]: https://github.com/a1121611810/pi-ptc-subagents/compare/v3.1.0...HEAD
169
228
  [3.0.0]: https://github.com/a1121611810/pi-ptc-subagents/compare/v2.1.0...v3.0.0
170
229
  [2.1.0]: https://github.com/a1121611810/pi-ptc-subagents/compare/v2.0.3...v2.1.0
171
230
  [2.0.3]: https://github.com/a1121611810/pi-ptc-subagents/compare/v2.0.2...v2.0.3
package/README.md CHANGED
@@ -96,8 +96,10 @@ const [read, scoutA, scoutB] = await Promise.all([
96
96
 
97
97
  **The child report.** A dispatched child returns more than prose: under the report contract
98
98
  ([ADR-0032](./docs/adr/0032-child-report.md)) it hands back a `summary`, `findings` each
99
- carrying independent evidence, `files_touched`, and token usage the host measured. The
100
- result names the channel that delivered it — `"tool"`, `"prompt-json"`, or `"none"` — and
99
+ carrying independent evidence, `files_touched`, and token usage the host measured. On the
100
+ background path that same measurement is written to the task record itself, on every terminal
101
+ close for a child that started — so a child that reported nothing, or failed, still shows what it
102
+ cost. The result names the channel that delivered it — `"tool"`, `"prompt-json"`, or `"none"` — and
101
103
  `"none"` means the child ran but did not comply, which must not read as "returned nothing".
102
104
  An agent opts out with one frontmatter line, `childReport: false`, and its channel reads
103
105
  `"opted-out"`. `ptc_subagent` renders the same report into the text the model reads, bounded
package/dist/index.d.ts CHANGED
@@ -215,12 +215,14 @@ interface TaskSpawnSource {
215
215
  callerId: string;
216
216
  }
217
217
  /**
218
- * Session-level row tracking the lifecycle of one background child. 19 ADR-0022 §3 fields (its
219
- * "21 fields" heading is an authoring miscount) plus two optional ADR-0023 owner-identity
220
- * fields — 21 today, persisted as-is. Optional fields are absent on
221
- * records still `running` (e.g. `finishedAt` / `exitCode` / `outputRef` are written at
218
+ * Session-level row tracking the lifecycle of one background child. 20 pre-ownership fields since
219
+ * the 2026-10-16 #199 amendment (19 ADR-0022 §3 originals — its "21 fields" heading is an
220
+ * authoring miscount — plus `usage`), two optional ADR-0023 owner-identity fields, two ADR-0032
221
+ * report fields and ADR-0041's `readOnlyTier`; 25 today, persisted as-is. Optional fields are
222
+ * absent on records still `running` (e.g. `finishedAt` / `exitCode` / `outputRef` are written at
222
223
  * transition time, not at spawn) and `ownerPid` / `ownerBootMs` are absent on pre-upgrade
223
- * legacy records.
224
+ * legacy records. The `report` / `reportChannel` pair is absent unless the record reached
225
+ * `succeeded` (ADR-0032); `usage` is written on every terminal close once a child started.
224
226
  */
225
227
  interface TaskRecord {
226
228
  id: ULID;
@@ -278,6 +280,26 @@ interface TaskRecord {
278
280
  * read as "none".
279
281
  */
280
282
  reportChannel?: ChildReportChannel;
283
+ /**
284
+ * ADR-0041 §"The tier that took effect is reported", on the background front. The tier the
285
+ * call resolved to, persisted at SPAWN so `ptc_task_output` can hand it back beside the child's
286
+ * prose — a background dispatch returns a `DispatchHandle`, so this is the whole of the
287
+ * foreground `DispatchResult.readOnlyTier` for a task that is still running.
288
+ *
289
+ * Unlike the two report fields above it is NOT conditional on `succeeded`: a tier is a fact
290
+ * about the request, so a failed or canceled read-only child still states it. Absent means no
291
+ * tier was asked for, which is the same claim the foreground result's absent field makes.
292
+ */
293
+ readOnlyTier?: ReadOnlyTier;
294
+ /**
295
+ * Host-observed token usage for this child (ADR-0032's counter, moved to its own carrier).
296
+ * Written on every terminal close for any child the host actually started — independent of
297
+ * `reportChannel` and of the close outcome — so a `none` / `opted-out` child, or one that
298
+ * failed, still accounts for what it cost. The full six-field `DispatchUsage` accumulator;
299
+ * `report.usage` remains the four-field derived view the report block renders.
300
+ * Absent on records written before this field existed, and on children that never started.
301
+ */
302
+ usage?: DispatchUsage;
281
303
  }
282
304
  /**
283
305
  * Per-subscriber cursor for one TaskRecord (ADR-0022 §5). Cursor is per-subscriber (not per-task)
@@ -387,6 +409,7 @@ type TaskCommand = {
387
409
  stderrDiagnostic?: string;
388
410
  report?: ChildReport;
389
411
  reportChannel: ChildReportChannel;
412
+ usage?: DispatchUsage;
390
413
  };
391
414
  /** Outcome of one successful command: the persisted record, emitted events, and cursor. */
392
415
  interface TransitionResult {
@@ -502,6 +525,28 @@ interface DispatchDeps {
502
525
  */
503
526
  outputStorage?: OutputStorage;
504
527
  }
528
+ /**
529
+ * ADR-0041: the two read-only tiers. `strict` narrows what the child can be handed;
530
+ * `lenient` narrows nothing and only states the posture.
531
+ *
532
+ * **Strings only, and that is load-bearing rather than a style choice.** Measured against pi's
533
+ * `validateToolArguments`: a union that includes `Type.Boolean()` COERCES — `1` and `"true"`
534
+ * arrive as `true`, `0` and `"false"` arrive as `false` — while a union of string literals
535
+ * refuses every one of them. The boolean short spelling therefore bought a silent type coercion
536
+ * on the parameter whose entire job is to be unambiguous, and it cost more than the token it
537
+ * saved. A pure string enum is also the shape tool schemas support most widely, which a mixed
538
+ * `boolean | enum` union is not.
539
+ */
540
+ type ReadOnlyTier = "strict" | "lenient";
541
+ /** Token usage accumulated from the child's message_end events. Optional. */
542
+ interface DispatchUsage {
543
+ input: number;
544
+ output: number;
545
+ cacheRead: number;
546
+ cacheWrite: number;
547
+ cost: number;
548
+ turns: number;
549
+ }
505
550
  //#endregion
506
551
  //#region src/runtime/notification-pipeline.d.ts
507
552
  /** Idle-wake callback: one subscriber's pending events, delivered in cursor order. */
@@ -961,7 +1006,7 @@ export declare function resolveCodemodeActivation(activeToolNames: readonly stri
961
1006
  * handing our orchestration surface away is the whole point of `subagents` mode (ADR-0026) —
962
1007
  * but only while that `codemode` is actually going to run (ADR-0027).
963
1008
  *
964
- * The five cases, as a table (ADR-0029 adds the last row):
1009
+ * The four cases, as a table (ADR-0029 adds the last row):
965
1010
  *
966
1011
  * | codemode on disk | switch | activation | surface | why |
967
1012
  * | ---------------- | -------------- | ---------- | ----------- | ------------------------------------------ |
package/dist/index.js CHANGED
@@ -1,60 +1,62 @@
1
- import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./protocol-CfOgxz3u.js";import{DEFAULT_MAX_BYTES as s,DEFAULT_MAX_LINES as c,createBashTool as l,createEditTool as u,createFindTool as d,createGrepTool as f,createLsTool as p,createReadTool as m,createWriteTool as h,defineTool as g,formatSize as _,formatSkillsForPrompt as v,getAgentDir as y,truncateTail as b}from"@earendil-works/pi-coding-agent";import{Type as x}from"typebox";import{validateToolArguments as S}from"@earendil-works/pi-ai";import*as C from"node:fs";import{existsSync as w,readFileSync as T,realpathSync as ee,statSync as te,writeFileSync as ne}from"node:fs";import*as re from"node:os";import{homedir as E,tmpdir as D}from"node:os";import*as O from"node:path";import{basename as ie,dirname as k,join as A,relative as ae,resolve as j,sep as oe}from"node:path";import{spawn as se}from"node:child_process";import{randomBytes as M,randomUUID as ce}from"node:crypto";import{ok as N}from"node:assert/strict";import{MessageChannel as le,Worker as ue}from"node:worker_threads";import de from"node:diagnostics_channel";import{fileURLToPath as fe,pathToFileURL as pe}from"node:url";import{truncateToWidth as P,visibleWidth as F}from"@earendil-works/pi-tui";import{appendFile as me,mkdir as he,readFile as ge,readdir as _e,rename as ve,unlink as ye,writeFile as be}from"node:fs/promises";import{minimatch as xe}from"minimatch";function I(e){return g(e)}const Se=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`;function Ce(e){let t=``,n=Math.max(0,Math.floor(e));for(let e=0;e<10;e++)t=(Se[n%32]??`0`)+t,n=Math.floor(n/32);return t}function we(e){let t=``,n=0,r=0;for(let i=0;i<e.length&&t.length<16;i++)for(n=n<<8|(e[i]??0),r+=8;r>=5&&t.length<16;)r-=5,t+=Se[n>>>r&31];return t.padEnd(16,`0`)}function Te(e){let t=new Uint8Array(e);for(let e=t.length-1;e>=0;e--){if((t[e]??0)<255)return t[e]=(t[e]??0)+1,t;t[e]=0}return t}function Ee(e){let t=e.randomBytes??(e=>new Uint8Array(M(e))),n=-1,r=/* @__PURE__ */ new Uint8Array(10);return{next(){let i=Math.max(0,Math.floor(e.now())),a=i>n?i:n,o=a===n?Te(r):t(10);return n=a,r=o,Ce(a)+we(o)}}}const De=Ee({now:()=>Date.now()});function Oe(){return De.next()}function ke(e){let t=e.trim();if(t.length===0)return null;try{return JSON.parse(t)}catch{return null}}function Ae(e,t){if(e.pid===void 0)return!1;try{return e.kill(t),!0}catch{return!1}}function je(e,t){if(e.eventWaiters.length>0){let n=e.eventWaiters.shift();n&&n(t);return}e.events.push(t)}function Me(e,t){if(e.exited)return;e.exited=!0,e.exitValue=t;for(let n of e.exitWaiters)n(t);e.exitWaiters=[];let n=e.eventWaiters;e.eventWaiters=[];for(let e of n)e(null);for(let t of e.stderrWaiters)t(e.stderr);e.stderrWaiters=[]}function Ne(e,t){let n=t.sessionDir===void 0?[...e]:e.filter(e=>e!==`--no-session`);return t.sessionDir!==void 0&&(n.push(`--session-dir`,t.sessionDir),t.sessionId!==void 0&&n.push(`--session-id`,t.sessionId),t.sessionName!==void 0&&n.push(`--name`,t.sessionName)),n}const Pe={warn:e=>{console.warn(`[pi-ptc.lifecycle] `+e)}};function Fe(e){return e.length<=200?e:e.slice(0,200)+`…`}var Ie=class{#e;constructor(e={}){this.#e=e.logger??Pe}spawn(e,t){if(e.length===0)throw TypeError(`RealChildProcessLifecycle.spawn: argv must include the command`);let n=Ne(e,t),r=n[0],i=n.slice(1),a=se(r,i,{cwd:t.cwd,shell:!1,stdio:[`ignore`,`pipe`,`pipe`],env:t.env}),o={proc:a,events:[],eventWaiters:[],exited:!1,exitValue:null,stderrWaiters:[],exitWaiters:[],stderr:``,lineBuffer:``},s={id:Oe(),opaque:o},c=a.stdout;c&&c.on(`data`,e=>{o.lineBuffer+=e.toString(`utf-8`);let t=o.lineBuffer.indexOf(`
1
+ import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./protocol-CfOgxz3u.js";import{DEFAULT_MAX_BYTES as s,DEFAULT_MAX_LINES as c,createBashTool as l,createEditTool as u,createFindTool as d,createGrepTool as f,createLsTool as p,createReadTool as m,createWriteTool as h,defineTool as g,formatSize as _,formatSkillsForPrompt as v,getAgentDir as y,truncateTail as b}from"@earendil-works/pi-coding-agent";import{Type as x}from"typebox";import{validateToolArguments as S}from"@earendil-works/pi-ai";import*as C from"node:fs";import{existsSync as w,readFileSync as T,realpathSync as ee,statSync as te,writeFileSync as E}from"node:fs";import*as D from"node:os";import{homedir as ne,tmpdir as O}from"node:os";import*as k from"node:path";import{basename as re,dirname as A,join as j,relative as ie,resolve as M,sep as ae}from"node:path";import{spawn as oe}from"node:child_process";import{randomBytes as se,randomUUID as ce}from"node:crypto";import{ok as N}from"node:assert/strict";import{MessageChannel as le,Worker as ue}from"node:worker_threads";import de from"node:diagnostics_channel";import{fileURLToPath as fe,pathToFileURL as pe}from"node:url";import{truncateToWidth as P,visibleWidth as F}from"@earendil-works/pi-tui";import{appendFile as me,mkdir as he,readFile as ge,readdir as _e,rename as ve,unlink as ye,writeFile as be}from"node:fs/promises";import{minimatch as xe}from"minimatch";function I(e){return g(e)}const Se=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`;function Ce(e){let t=``,n=Math.max(0,Math.floor(e));for(let e=0;e<10;e++)t=(Se[n%32]??`0`)+t,n=Math.floor(n/32);return t}function we(e){let t=``,n=0,r=0;for(let i=0;i<e.length&&t.length<16;i++)for(n=n<<8|(e[i]??0),r+=8;r>=5&&t.length<16;)r-=5,t+=Se[n>>>r&31];return t.padEnd(16,`0`)}function Te(e){let t=new Uint8Array(e);for(let e=t.length-1;e>=0;e--){if((t[e]??0)<255)return t[e]=(t[e]??0)+1,t;t[e]=0}return t}function Ee(e){let t=e.randomBytes??(e=>new Uint8Array(se(e))),n=-1,r=/* @__PURE__ */ new Uint8Array(10);return{next(){let i=Math.max(0,Math.floor(e.now())),a=i>n?i:n,o=a===n?Te(r):t(10);return n=a,r=o,Ce(a)+we(o)}}}const De=Ee({now:()=>Date.now()});function Oe(){return De.next()}function ke(e){let t=e.trim();if(t.length===0)return null;try{return JSON.parse(t)}catch{return null}}function Ae(e,t){if(e.pid===void 0)return!1;try{return e.kill(t),!0}catch{return!1}}function je(e,t){if(e.eventWaiters.length>0){let n=e.eventWaiters.shift();n&&n(t);return}e.events.push(t)}function Me(e,t){if(e.exited)return;e.exited=!0,e.exitValue=t;for(let n of e.exitWaiters)n(t);e.exitWaiters=[];let n=e.eventWaiters;e.eventWaiters=[];for(let e of n)e(null);for(let t of e.stderrWaiters)t(e.stderr);e.stderrWaiters=[]}function Ne(e,t){let n=t.sessionDir===void 0?[...e]:e.filter(e=>e!==`--no-session`);return t.sessionDir!==void 0&&(n.push(`--session-dir`,t.sessionDir),t.sessionId!==void 0&&n.push(`--session-id`,t.sessionId),t.sessionName!==void 0&&n.push(`--name`,t.sessionName)),n}const Pe={warn:e=>{console.warn(`[pi-ptc.lifecycle] `+e)}};function Fe(e){return e.length<=200?e:e.slice(0,200)+`…`}var Ie=class{#e;constructor(e={}){this.#e=e.logger??Pe}spawn(e,t){if(e.length===0)throw TypeError(`RealChildProcessLifecycle.spawn: argv must include the command`);let n=Ne(e,t),r=n[0],i=n.slice(1),a=oe(r,i,{cwd:t.cwd,shell:!1,stdio:[`ignore`,`pipe`,`pipe`],env:t.env}),o={proc:a,events:[],eventWaiters:[],exited:!1,exitValue:null,stderrWaiters:[],exitWaiters:[],stderr:``,lineBuffer:``},s={id:Oe(),opaque:o},c=a.stdout;c&&c.on(`data`,e=>{o.lineBuffer+=e.toString(`utf-8`);let t=o.lineBuffer.indexOf(`
2
2
  `);for(;t>=0;){let e=o.lineBuffer.slice(0,t);o.lineBuffer=o.lineBuffer.slice(t+1);let n=ke(e);n?je(o,n):e.trim().length>0&&this.#t(s,e),t=o.lineBuffer.indexOf(`
3
3
  `)}});let l=a.stderr;return l&&l.on(`data`,e=>{o.stderr+=e.toString(`utf-8`)}),a.on(`close`,(e,t)=>{let n=o.lineBuffer.trim();if(n.length>0){let e=ke(n);e?je(o,e):this.#t(s,n),o.lineBuffer=``}Me(o,{code:e,signal:t})}),a.on(`error`,e=>{o.stderr+=`[spawn-error] `+e.message+`
4
- `,o.exited||Me(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;Ae(n.proc,t)}events(e){let t=e.opaque;return{async*[Symbol.asyncIterator](){for(;;){if(t.events.length>0){let e=t.events.shift();e!==void 0&&(yield e);continue}if(t.exited)return;let e=await new Promise(e=>{t.eventWaiters.push(e)});if(e===null)return;yield e}}}}exit(e){let t=e.opaque;return t.exited&&t.exitValue?Promise.resolve(t.exitValue):new Promise(e=>{t.exitWaiters.push(e)})}stderr(e){let t=e.opaque;return t.exited?Promise.resolve(t.stderr):new Promise(e=>{t.stderrWaiters.push(e)})}#t(e,t){this.#e.warn(`child ${e.id}: dropped a non-JSON stdout line (${t.length} chars): `+Fe(t))}};const Le=`ptc_child_report`,L=Object.freeze({timeoutMs:12e4,maxTimeoutMs:6e5,maxOutputBytes:67108864,maxMessageBytes:134217728,maxPendingCalls:128,maxParallelSubCalls:10,dispatchConcurrency:8,maxDispatchDepth:3,maxItemsPerCall:4096,graceMs:3e3,maxOldGenerationSizeMb:512,maxYoungGenerationSizeMb:64,poolSize:4,poolAcquireTimeoutMs:3e4,drainGraceMs:5e3}),Re=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function ze(e=process.env){let t={};for(let n of Re){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function Be(e={}){let t={...L};for(let n of Object.keys(L)){let r=e[n];if(r!==void 0){if(typeof r!=`number`||!Number.isFinite(r)||r<=0)throw TypeError(`invalid PTC config override for ${n}: ${String(r)}`);t[n]=r}}return t}function Ve(e,t=L){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const He={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},Ue=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),We=/* @__PURE__ */ new Set([`running`,`stopping`]);function Ge(e,t,n,r){if(n!==`canceled`&&n!==`succeeded`){if(t.childError!==void 0)return t.childError;if(t.stderrDiagnostic!==void 0)return t.stderrDiagnostic;if(t.exitCode===0&&!r)return`dispatch produced no final text`}}function Ke(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function qe(e){return typeof e==`string`&&e.length>0}const Je=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function Ye(e){return typeof e==`string`&&Je.has(e)}function Xe(e,t){return e.ownerPid===t.pid&&e.ownerBootMs===t.bootMs}function Ze(e){try{return process.kill(e,0),!0}catch(e){let t=e?.code;if(t===`ESRCH`)return!1;if(t===`EPERM`)return!0;throw e}}function Qe(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var $e=class{#e;#t;#n;#r;#i;#a;#o=/* @__PURE__ */ new Set;#s=Promise.resolve();constructor(e,t){this.#e=e,this.#t=t.clock,this.#n=t.logger,this.#r=t.owner,this.#i=t.isPidAlive??Ze,this.#a=Ee({now:()=>this.#t()})}async transition(e,t){let n=await this.#h(()=>this.#c(e,t)),r=n.events[n.events.length-1];return r!==void 0&&this.#g(n.record,r,t.logger),n}onTransition(e){this.#o.add(e);let t=!0;return()=>{t&&(t=!1,this.#o.delete(e))}}async#c(e,t){switch(e.kind){case`spawn`:return this.#l(e,t);case`transition`:return this.#u(e,t);case`stop`:return this.#d(e,t);case`reconcile-lost`:return this.#p(e,t);case`resolve-exit`:return this.#f(e,t)}throw Error(`transition: unknown command kind ${String(e.kind)}`)}async get(e){return qe(e)?await this.#e.loadTask(e):null}async query(e){let t=e.limit??100;if(!Number.isInteger(t)||t<0)throw Error(`query: limit must be a non-negative integer, got ${String(e.limit)}`);let n=e.orderBy??`createdAt-desc`,r=e.label===void 0?void 0:{label:e.label},i=[];for await(let t of this.#e.listTasks(r))(e.status===void 0||e.status.includes(t.status))&&i.push(t);return i.sort((e,t)=>n===`createdAt-asc`?e.createdAt-t.createdAt:t.createdAt-e.createdAt),i.slice(0,t)}async reconcileLostTasks(){let e=[];for await(let t of this.#e.listTasks())We.has(t.status)&&this.#_(t)&&e.push(t);let t=[];for(let n of e){let e=await this.transition({kind:`reconcile-lost`,taskId:n.id,reason:`lost_on_session_restart`},{clock:this.#t,callerId:this.#S(n),logger:this.#n});t.push(e.record)}return this.#n?.info(`reconcileLostTasks: marked ${t.length} task(s) lost`),t}async#l(e,t){let n=Math.max(0,Math.floor(t.clock())),r=e.handle;if(r==null)throw Error(`spawn: handle is required`);if(r.status!==`running`)throw Error(`spawn: handle.status must be "running", got ${String(r.status)}`);let i=qe(r.taskId),a=i?r.taskId:this.#a.next();if(await this.#e.loadTask(a)!==null)throw Error(`spawn: task ${a} already exists (duplicate spawn)`);let o={...e.record,id:a,label:e.record.label.length>0?e.record.label:r.label,status:`running`,createdAt:n,startedAt:n,finishedAt:void 0,durationMs:void 0,transitionAt:n,parentTaskId:e.parentTaskId??e.record.parentTaskId};this.#r!==void 0&&(o.ownerPid=this.#r.pid,o.ownerBootMs=this.#r.bootMs),i||(r.taskId=a);let s=t.callerId,c=this.#x(a,s,`running`,n,o);return await this.#e.saveSubscription({subscriberId:s,taskId:a,cursor:c.eventId,status:`active`,createdAt:n}),await this.#e.appendEvents(s,[c]),await this.#e.saveTask(o),(t.logger??this.#n)?.info(`spawn: task ${a} (${o.label}) running for subscriber ${s}`),{record:o,events:[c],cursor:c.eventId}}async#u(e,t){if(!Ke(e.to))throw Error(`transition: unknown target state ${String(e.to)}`);let n=await this.#y(e.taskId);if(this.#v(n,e.to),e.to===`lost`&&!Ye(e.reason))throw Error(`transition: to "lost" requires a LostReason (session_ended_while_running | user_killed_via_esc | lost_on_session_restart)`+(e.reason===void 0?``:`, got ${String(e.reason)}`));return this.#m(n,e.to,t,{reason:e.reason,stopReason:e.stopReason,errorMessage:e.errorMessage,exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview})}async#d(e,t){let n=await this.#y(e.taskId);return n.status===`stopping`?{record:n,events:[],cursor:(await this.#e.loadSubscription(t.callerId,n.id))?.cursor??n.id,fromStatus:n.status}:(this.#v(n,`stopping`),this.#m(n,`stopping`,t,{stopReason:e.reason}))}async#f(e,t){let n=await this.#y(e.taskId);if(n.status!==`running`&&n.status!==`stopping`)throw Error(`resolve-exit: task ${n.id} is terminal (${n.status}); the single terminal writer refuses to overwrite it`);let r=(e.outputBytes??0)>0,i=n.status===`stopping`?`canceled`:e.exitCode===0&&r?`succeeded`:`failed`;return this.#v(n,i),this.#m(n,i,t,{exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview,errorMessage:Ge(n,e,i,r),...i===`succeeded`?{report:e.report,reportChannel:e.reportChannel}:{}})}async#p(e,t){let n=await this.#y(e.taskId);if(!We.has(n.status))throw Error(`reconcile-lost: task ${n.id} is terminal (${n.status}); only running/stopping tasks can be reconciled`);return this.#m(n,`lost`,t,{errorMessage:e.reason})}async#m(e,t,n,r){let i=Math.max(0,Math.floor(n.clock())),a={...e,status:t,transitionAt:i};Ue.has(t)&&(a.finishedAt=i,a.durationMs=i-e.startedAt),r.stopReason!==void 0&&(a.stopReason=r.stopReason),r.errorMessage!==void 0&&(a.errorMessage=r.errorMessage),r.exitCode!==void 0&&(a.exitCode=r.exitCode),r.outputRef!==void 0&&(a.outputRef=r.outputRef),r.outputBytes!==void 0&&(a.outputBytes=r.outputBytes),r.outputPreview!==void 0&&(a.outputPreview=r.outputPreview),r.report!==void 0&&(a.report=r.report),r.reportChannel!==void 0&&(a.reportChannel=r.reportChannel),r.reason!==void 0&&((t===`stopping`||t===`canceled`)&&a.stopReason===void 0&&(a.stopReason=r.reason),(t===`failed`||t===`lost`)&&a.errorMessage===void 0&&(a.errorMessage=r.reason));let o=n.callerId,s=this.#x(e.id,o,t,i,a);return await this.#b(o,e.id,i,s.eventId),await this.#e.appendEvents(o,[s]),await this.#e.saveTask(a),(n.logger??this.#n)?.info(`transition: task ${e.id} ${e.status} -> ${t} (subscriber ${o})`),{record:a,events:[s],cursor:s.eventId,fromStatus:e.status}}async#h(e){let t=this.#s.then(e,e);return this.#s=t.then(()=>void 0,()=>void 0),await t}#g(e,t,n){for(let r of this.#o)try{r(e,t)}catch(t){let r=t instanceof Error?t.message:String(t),i=`transition observer threw for task ${e.id}: ${r}`,a=n??this.#n;a===void 0?console.warn(`[task-registry] `+i):a.warn(i)}}#_(e){return e.ownerPid===void 0||!this.#i(e.ownerPid)}#v(e,t){let n=He[e.status];if(!n.includes(t)){let r=n.length===0?`<terminal>`:n.join(`, `);throw Error(`illegal transition for task ${e.id}: ${e.status} -> ${t} (allowed from ${e.status}: ${r})`)}}async#y(e){if(!qe(e))throw Error(`transition: taskId is required`);let t=await this.#e.loadTask(e);if(t===null)throw Error(`transition: unknown taskId ${e}`);return t}async#b(e,t,n,r){await this.#e.loadSubscription(e,t)===null&&(await this.#e.saveSubscription({subscriberId:e,taskId:t,cursor:r,status:`active`,createdAt:n}),this.#n?.warn(`subscription: auto-created for subscriber ${e} on task ${t} at cursor ${r}`))}#x(e,t,n,r,i){let a=i.outputBytes,o=a!==void 0&&a<=2048?i.outputPreview:void 0;return{eventId:this.#a.next(),subscriptionId:t,taskId:e,type:Qe(e,n),status:n,transitionAtMs:r,outputBytes:a,outputPreview:o}}#S(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}};function et(e,t){return new $e(e,t)}function tt(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function nt(e){for(let t=1;t<e.length;t++)if(tt(e[t-1],e[t])>0)return!1;return!0}var rt=class e{#e;#t;#n;#r;constructor(){this.#e=/* @__PURE__ */ new Map,this.#t=/* @__PURE__ */ new Map,this.#n=/* @__PURE__ */ new Set,this.#r=/* @__PURE__ */ new Map}static#i(e,t){return`${e}-${t}`}#a(e){return this.#n.has(e)}async loadTask(e){let t=this.#e.get(e);return t===void 0?null:structuredClone(t)}async saveTask(e){N(e,`saveTask: record is required`),this.#e.set(e.id,structuredClone(e))}async deleteTask(e){if(!this.#e.has(e))throw Error(`deleteTask: unknown taskId ${e}`);this.#e.delete(e)}async*listTasks(e){for(let t of this.#e.values())(e?.status===void 0||t.status===e.status)&&(e?.label===void 0||t.label===e.label)&&(yield structuredClone(t))}async loadSubscription(t,n){let r=this.#t.get(e.#i(t,n));return r===void 0?null:structuredClone(r)}async saveSubscription(t){N(t,`saveSubscription: sub is required`);let n=e.#i(t.subscriberId,t.taskId);this.#t.set(n,structuredClone(t)),this.#n.add(t.subscriberId)}async appendEvents(e,t){if(!this.#a(e))throw Error(`appendEvents: unknown subscriptionId ${e}`);if(t.length===0)return;let n=this.#r.get(e)??[],r=nt(t)?[...t]:[...t].sort(tt),i=n.length===0?void 0:n[n.length-1]?.eventId,a=r[0]?.eventId;if(i===void 0||a!==void 0&&i<=a){for(let e of r)n.push(structuredClone(e));this.#r.set(e,n);return}let o=[...n,...r.map(e=>structuredClone(e))];o.sort(tt),this.#r.set(e,o)}async*loadEvents(e,t){if(!this.#a(e))throw Error(`loadEvents: unknown subscriptionId ${e}`);let n=this.#r.get(e)??[],r=0;if(t!==void 0){let e=0,i=n.length;for(;e<i;){let r=e+i>>>1;(n[r]?.eventId??``)<=t?e=r+1:i=r}r=e}for(let e=r;e<n.length;e++)yield structuredClone(n[e])}};const it=new Ie;var at=class{limit;#e;#t=/* @__PURE__ */ new Set;constructor(e){if(!Number.isInteger(e)||e<0)throw TypeError(`DispatchSlotCounter: limit must be a non-negative integer, got ${String(e)}`);this.limit=e,this.#e=0}get active(){return this.#e}tryAcquire(e){return e!==void 0&&this.#t.has(e)||this.#e>=this.limit?!1:(e!==void 0&&this.#t.add(e),this.#e+=1,!0)}release(e){if(e!==void 0){if(!this.#t.delete(e))return;--this.#e;return}this.#e>this.#t.size&&--this.#e}};const ot=new at(L.dispatchConcurrency);let st;function ct(e,t){return e.taskRegistry===void 0?(st??=new $e(new rt,{clock:t}),st):e.taskRegistry}const lt={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}},ut=Object.freeze({name:``,source:`unknown`,systemPrompt:``});function dt(e,t,n,r={}){let i=r.reportContract!==!1,a=[`<pi-ptc-context depth="`+t+`" max-depth="`+n+`">`,`You are a PTC run at depth `+t+` (root is depth 0). You may write PTC programs and you may`,`call pi.dispatch(...) to spawn further children, but each level costs a fresh pi subprocess.`,`The remaining depth budget is `+n+` - `+t+`. Beyond it, pi.dispatch rejects with`,`{ status: "rejected", errorMessage: "dispatch depth limit reached" }.`,`You were dispatched by another pi session as a fresh context. You cannot see that session's`,`conversation and you cannot ask it anything, so if the task you were given is underspecified,`,`say which part is underspecified and answer the rest rather than inventing the missing`,`context. Your final message is the deliverable: it is what the caller receives, so put the`,`answer there rather than narrating how you found it.`,...i?['Before you finish, hand the host a child report. Prefer calling the `ptc_child_report` tool once with it. If that tool is not available to you, end your reply with a fenced ```json block containing a JSON object with exactly these keys: "summary" (one line, your own words), "findings" (an array of objects each with "what" and "evidence", where evidence is the independent thing that supports the claim), and "files_touched" (an array of paths you created or modified). Either way your prose answer is kept alongside the report and never replaced by it, and you must not report usage or token counts — those are measured by the host.']:[],`</pi-ptc-context>`].join(`
5
- `);return e.length===0?a:e+`
4
+ `,o.exited||Me(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;Ae(n.proc,t)}events(e){let t=e.opaque;return{async*[Symbol.asyncIterator](){for(;;){if(t.events.length>0){let e=t.events.shift();e!==void 0&&(yield e);continue}if(t.exited)return;let e=await new Promise(e=>{t.eventWaiters.push(e)});if(e===null)return;yield e}}}}exit(e){let t=e.opaque;return t.exited&&t.exitValue?Promise.resolve(t.exitValue):new Promise(e=>{t.exitWaiters.push(e)})}stderr(e){let t=e.opaque;return t.exited?Promise.resolve(t.stderr):new Promise(e=>{t.stderrWaiters.push(e)})}#t(e,t){this.#e.warn(`child ${e.id}: dropped a non-JSON stdout line (${t.length} chars): `+Fe(t))}};const Le=`ptc_child_report`,L=Object.freeze({timeoutMs:12e4,maxTimeoutMs:6e5,maxOutputBytes:67108864,maxMessageBytes:134217728,maxPendingCalls:128,maxParallelSubCalls:10,dispatchConcurrency:8,maxDispatchDepth:3,maxItemsPerCall:4096,graceMs:3e3,maxOldGenerationSizeMb:512,maxYoungGenerationSizeMb:64,poolSize:4,poolAcquireTimeoutMs:3e4,drainGraceMs:5e3}),Re=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function ze(e=process.env){let t={};for(let n of Re){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function Be(e={}){let t={...L};for(let n of Object.keys(L)){let r=e[n];if(r!==void 0){if(typeof r!=`number`||!Number.isFinite(r)||r<=0)throw TypeError(`invalid PTC config override for ${n}: ${String(r)}`);t[n]=r}}return t}function Ve(e,t=L){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const He={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},Ue=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),We=/* @__PURE__ */ new Set([`running`,`stopping`]);function Ge(e,t,n,r){if(n!==`canceled`&&n!==`succeeded`){if(t.childError!==void 0)return t.childError;if(t.stderrDiagnostic!==void 0)return t.stderrDiagnostic;if(t.exitCode===0&&!r)return`dispatch produced no final text`}}function Ke(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function qe(e){return typeof e==`string`&&e.length>0}const Je=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function Ye(e){return typeof e==`string`&&Je.has(e)}function Xe(e,t){return e.ownerPid===t.pid&&e.ownerBootMs===t.bootMs}function Ze(e){try{return process.kill(e,0),!0}catch(e){let t=e?.code;if(t===`ESRCH`)return!1;if(t===`EPERM`)return!0;throw e}}function Qe(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var $e=class{#e;#t;#n;#r;#i;#a;#o=/* @__PURE__ */ new Set;#s=Promise.resolve();constructor(e,t){this.#e=e,this.#t=t.clock,this.#n=t.logger,this.#r=t.owner,this.#i=t.isPidAlive??Ze,this.#a=Ee({now:()=>this.#t()})}async transition(e,t){let n=await this.#h(()=>this.#c(e,t)),r=n.events[n.events.length-1];return r!==void 0&&this.#g(n.record,r,t.logger),n}onTransition(e){this.#o.add(e);let t=!0;return()=>{t&&(t=!1,this.#o.delete(e))}}async#c(e,t){switch(e.kind){case`spawn`:return this.#l(e,t);case`transition`:return this.#u(e,t);case`stop`:return this.#d(e,t);case`reconcile-lost`:return this.#p(e,t);case`resolve-exit`:return this.#f(e,t)}throw Error(`transition: unknown command kind ${String(e.kind)}`)}async get(e){return qe(e)?await this.#e.loadTask(e):null}async query(e){let t=e.limit??100;if(!Number.isInteger(t)||t<0)throw Error(`query: limit must be a non-negative integer, got ${String(e.limit)}`);let n=e.orderBy??`createdAt-desc`,r=e.label===void 0?void 0:{label:e.label},i=[];for await(let t of this.#e.listTasks(r))(e.status===void 0||e.status.includes(t.status))&&i.push(t);return i.sort((e,t)=>n===`createdAt-asc`?e.createdAt-t.createdAt:t.createdAt-e.createdAt),i.slice(0,t)}async reconcileLostTasks(){let e=[];for await(let t of this.#e.listTasks())We.has(t.status)&&this.#_(t)&&e.push(t);let t=[];for(let n of e){let e=await this.transition({kind:`reconcile-lost`,taskId:n.id,reason:`lost_on_session_restart`},{clock:this.#t,callerId:this.#S(n),logger:this.#n});t.push(e.record)}return this.#n?.info(`reconcileLostTasks: marked ${t.length} task(s) lost`),t}async#l(e,t){let n=Math.max(0,Math.floor(t.clock())),r=e.handle;if(r==null)throw Error(`spawn: handle is required`);if(r.status!==`running`)throw Error(`spawn: handle.status must be "running", got ${String(r.status)}`);let i=qe(r.taskId),a=i?r.taskId:this.#a.next();if(await this.#e.loadTask(a)!==null)throw Error(`spawn: task ${a} already exists (duplicate spawn)`);let o={...e.record,id:a,label:e.record.label.length>0?e.record.label:r.label,status:`running`,createdAt:n,startedAt:n,finishedAt:void 0,durationMs:void 0,transitionAt:n,parentTaskId:e.parentTaskId??e.record.parentTaskId};this.#r!==void 0&&(o.ownerPid=this.#r.pid,o.ownerBootMs=this.#r.bootMs),i||(r.taskId=a);let s=t.callerId,c=this.#x(a,s,`running`,n,o);return await this.#e.saveSubscription({subscriberId:s,taskId:a,cursor:c.eventId,status:`active`,createdAt:n}),await this.#e.appendEvents(s,[c]),await this.#e.saveTask(o),(t.logger??this.#n)?.info(`spawn: task ${a} (${o.label}) running for subscriber ${s}`),{record:o,events:[c],cursor:c.eventId}}async#u(e,t){if(!Ke(e.to))throw Error(`transition: unknown target state ${String(e.to)}`);let n=await this.#y(e.taskId);if(this.#v(n,e.to),e.to===`lost`&&!Ye(e.reason))throw Error(`transition: to "lost" requires a LostReason (session_ended_while_running | user_killed_via_esc | lost_on_session_restart)`+(e.reason===void 0?``:`, got ${String(e.reason)}`));return this.#m(n,e.to,t,{reason:e.reason,stopReason:e.stopReason,errorMessage:e.errorMessage,exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview})}async#d(e,t){let n=await this.#y(e.taskId);return n.status===`stopping`?{record:n,events:[],cursor:(await this.#e.loadSubscription(t.callerId,n.id))?.cursor??n.id,fromStatus:n.status}:(this.#v(n,`stopping`),this.#m(n,`stopping`,t,{stopReason:e.reason}))}async#f(e,t){let n=await this.#y(e.taskId);if(n.status!==`running`&&n.status!==`stopping`)throw Error(`resolve-exit: task ${n.id} is terminal (${n.status}); the single terminal writer refuses to overwrite it`);let r=(e.outputBytes??0)>0,i=n.status===`stopping`?`canceled`:e.exitCode===0&&r?`succeeded`:`failed`;return this.#v(n,i),this.#m(n,i,t,{exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview,errorMessage:Ge(n,e,i,r),usage:e.usage,...i===`succeeded`?{report:e.report,reportChannel:e.reportChannel}:{}})}async#p(e,t){let n=await this.#y(e.taskId);if(!We.has(n.status))throw Error(`reconcile-lost: task ${n.id} is terminal (${n.status}); only running/stopping tasks can be reconciled`);return this.#m(n,`lost`,t,{errorMessage:e.reason})}async#m(e,t,n,r){let i=Math.max(0,Math.floor(n.clock())),a={...e,status:t,transitionAt:i};Ue.has(t)&&(a.finishedAt=i,a.durationMs=i-e.startedAt),r.stopReason!==void 0&&(a.stopReason=r.stopReason),r.errorMessage!==void 0&&(a.errorMessage=r.errorMessage),r.exitCode!==void 0&&(a.exitCode=r.exitCode),r.outputRef!==void 0&&(a.outputRef=r.outputRef),r.outputBytes!==void 0&&(a.outputBytes=r.outputBytes),r.outputPreview!==void 0&&(a.outputPreview=r.outputPreview),r.report!==void 0&&(a.report=r.report),r.reportChannel!==void 0&&(a.reportChannel=r.reportChannel),r.usage!==void 0&&(a.usage=r.usage),r.reason!==void 0&&((t===`stopping`||t===`canceled`)&&a.stopReason===void 0&&(a.stopReason=r.reason),(t===`failed`||t===`lost`)&&a.errorMessage===void 0&&(a.errorMessage=r.reason));let o=n.callerId,s=this.#x(e.id,o,t,i,a);return await this.#b(o,e.id,i,s.eventId),await this.#e.appendEvents(o,[s]),await this.#e.saveTask(a),(n.logger??this.#n)?.info(`transition: task ${e.id} ${e.status} -> ${t} (subscriber ${o})`),{record:a,events:[s],cursor:s.eventId,fromStatus:e.status}}async#h(e){let t=this.#s.then(e,e);return this.#s=t.then(()=>void 0,()=>void 0),await t}#g(e,t,n){for(let r of this.#o)try{r(e,t)}catch(t){let r=t instanceof Error?t.message:String(t),i=`transition observer threw for task ${e.id}: ${r}`,a=n??this.#n;a===void 0?console.warn(`[task-registry] `+i):a.warn(i)}}#_(e){return e.ownerPid===void 0||!this.#i(e.ownerPid)}#v(e,t){let n=He[e.status];if(!n.includes(t)){let r=n.length===0?`<terminal>`:n.join(`, `);throw Error(`illegal transition for task ${e.id}: ${e.status} -> ${t} (allowed from ${e.status}: ${r})`)}}async#y(e){if(!qe(e))throw Error(`transition: taskId is required`);let t=await this.#e.loadTask(e);if(t===null)throw Error(`transition: unknown taskId ${e}`);return t}async#b(e,t,n,r){await this.#e.loadSubscription(e,t)===null&&(await this.#e.saveSubscription({subscriberId:e,taskId:t,cursor:r,status:`active`,createdAt:n}),this.#n?.warn(`subscription: auto-created for subscriber ${e} on task ${t} at cursor ${r}`))}#x(e,t,n,r,i){let a=i.outputBytes,o=a!==void 0&&a<=2048?i.outputPreview:void 0;return{eventId:this.#a.next(),subscriptionId:t,taskId:e,type:Qe(e,n),status:n,transitionAtMs:r,outputBytes:a,outputPreview:o}}#S(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}};function et(e,t){return new $e(e,t)}function tt(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function nt(e){for(let t=1;t<e.length;t++)if(tt(e[t-1],e[t])>0)return!1;return!0}var rt=class e{#e;#t;#n;#r;constructor(){this.#e=/* @__PURE__ */ new Map,this.#t=/* @__PURE__ */ new Map,this.#n=/* @__PURE__ */ new Set,this.#r=/* @__PURE__ */ new Map}static#i(e,t){return`${e}-${t}`}#a(e){return this.#n.has(e)}async loadTask(e){let t=this.#e.get(e);return t===void 0?null:structuredClone(t)}async saveTask(e){N(e,`saveTask: record is required`),this.#e.set(e.id,structuredClone(e))}async deleteTask(e){if(!this.#e.has(e))throw Error(`deleteTask: unknown taskId ${e}`);this.#e.delete(e)}async*listTasks(e){for(let t of this.#e.values())(e?.status===void 0||t.status===e.status)&&(e?.label===void 0||t.label===e.label)&&(yield structuredClone(t))}async loadSubscription(t,n){let r=this.#t.get(e.#i(t,n));return r===void 0?null:structuredClone(r)}async saveSubscription(t){N(t,`saveSubscription: sub is required`);let n=e.#i(t.subscriberId,t.taskId);this.#t.set(n,structuredClone(t)),this.#n.add(t.subscriberId)}async appendEvents(e,t){if(!this.#a(e))throw Error(`appendEvents: unknown subscriptionId ${e}`);if(t.length===0)return;let n=this.#r.get(e)??[],r=nt(t)?[...t]:[...t].sort(tt),i=n.length===0?void 0:n[n.length-1]?.eventId,a=r[0]?.eventId;if(i===void 0||a!==void 0&&i<=a){for(let e of r)n.push(structuredClone(e));this.#r.set(e,n);return}let o=[...n,...r.map(e=>structuredClone(e))];o.sort(tt),this.#r.set(e,o)}async*loadEvents(e,t){if(!this.#a(e))throw Error(`loadEvents: unknown subscriptionId ${e}`);let n=this.#r.get(e)??[],r=0;if(t!==void 0){let e=0,i=n.length;for(;e<i;){let r=e+i>>>1;(n[r]?.eventId??``)<=t?e=r+1:i=r}r=e}for(let e=r;e<n.length;e++)yield structuredClone(n[e])}};const it=new Ie;var at=class{limit;#e;#t=/* @__PURE__ */ new Set;constructor(e){if(!Number.isInteger(e)||e<0)throw TypeError(`DispatchSlotCounter: limit must be a non-negative integer, got ${String(e)}`);this.limit=e,this.#e=0}get active(){return this.#e}tryAcquire(e){return e!==void 0&&this.#t.has(e)||this.#e>=this.limit?!1:(e!==void 0&&this.#t.add(e),this.#e+=1,!0)}release(e){if(e!==void 0){if(!this.#t.delete(e))return;--this.#e;return}this.#e>this.#t.size&&--this.#e}};const ot=new at(L.dispatchConcurrency);let st;function ct(e,t){return e.taskRegistry===void 0?(st??=new $e(new rt,{clock:t}),st):e.taskRegistry}const lt={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}},ut=[`read`,`grep`,`find`,`ls`];function R(e){return e===`strict`||e===`lenient`?e:void 0}function dt(e){return e==null||e===`strict`||e===`lenient`}function ft(e){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`invalid readOnly value: `+(typeof e==`object`&&e?JSON.stringify(e):String(e))+` (readOnly accepts "strict" or "lenient"; null and undefined ask for no tier)`}}function z(e,t){return t===void 0?e:{...e,readOnlyTier:t}}const pt=Object.freeze({name:``,source:`unknown`,systemPrompt:``});function mt(e,t,n,r={}){let i=r.reportContract!==!1,a=R(r.readOnly),o=[`<pi-ptc-context depth="`+t+`" max-depth="`+n+`">`,`You are a PTC run at depth `+t+` (root is depth 0). You may write PTC programs and you may`,`call pi.dispatch(...) to spawn further children, but each level costs a fresh pi subprocess.`,`The remaining depth budget is `+n+` - `+t+`. Beyond it, pi.dispatch rejects with`,`{ status: "rejected", errorMessage: "dispatch depth limit reached" }.`,`You were dispatched by another pi session as a fresh context. You cannot see that session's`,`conversation and you cannot ask it anything, so if the task you were given is underspecified,`,`say which part is underspecified and answer the rest rather than inventing the missing`,`context. Your final message is the deliverable: it is what the caller receives, so put the`,`answer there rather than narrating how you found it.`,...i?['Before you finish, hand the host a child report. Prefer calling the `ptc_child_report` tool once with it. If that tool is not available to you, end your reply with a fenced ```json block containing a JSON object with exactly these keys: "summary" (one line, your own words), "findings" (an array of objects each with "what" and "evidence", where evidence is the independent thing that supports the claim), and "files_touched" (an array of paths you created or modified). Either way your prose answer is kept alongside the report and never replaced by it, and you must not report usage or token counts — those are measured by the host.']:[],...a===`lenient`?[`You were dispatched read-only: do not create, modify or delete files, and do not run commands that would. Your tools are otherwise all still available to you — this is an instruction, not a restriction, so a task that genuinely needs to write is worth saying so rather than failing quietly.`]:[],`</pi-ptc-context>`].join(`
5
+ `);return e.length===0?o:e+`
6
6
 
7
- `+a}function ft(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch depth limit reached`}}function pt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch concurrency limit reached`}}function mt(e,t,n={}){e.kill(t,`SIGTERM`);let r=setTimeout(()=>{n.isDone?.()!==!0&&e.kill(t,`SIGKILL`)},5e3);return n.unref===!0&&r.unref(),()=>clearTimeout(r)}function ht(){return{...ft(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function gt(){return{...pt(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function _t(e){if(e!==void 0&&e.length!==0)return e.includes(`Response was truncated: the model reached its output token limit.`)?`child response was truncated at the model's output token limit (pi exited non-zero)`:void 0}function vt(e){if(e.aborted)return{status:`rejected`,errorMessage:`dispatch cancelled`};if(e.exitCode===0&&e.finalText.length>0)return{status:`fulfilled`};if(e.exitCode===0)return{status:`rejected`,errorMessage:`dispatch produced no final text`};let t=_t(e.stderr);return{status:`rejected`,...t===void 0?{}:{errorMessage:t}}}function yt(e,t){let n=e.match(RegExp(`^`+t+`:\\s*(.+)$`,`m`));if(!n)return;let r=(n[1]??``).trim();if(r.length>=2){let e=r[0],t=r[r.length-1];(e===`"`&&t===`"`||e===`'`&&t===`'`)&&(r=r.slice(1,-1))}return r.length===0?void 0:r}function bt(e,t){let n=e.match(RegExp(`^`+t+`:\\s*(.+)$`,`m`));if(!n)return;let r=(n[1]??``).trim();r.startsWith(`[`)&&r.endsWith(`]`)&&(r=r.slice(1,-1));let i=r.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);return i.length===0?void 0:i}function xt(e){let t=yt(e,`childReport`);if(t!==void 0)return t.toLowerCase()!==`false`&&t.toLowerCase()!==`no`}function St(e){return e.childReport!==!1}function Ct(e){let t=e.match(/^\uFEFF?[ \t]*(?:\r?\n)?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n([\s\S]*))?$/);if(!t)return null;let n=(t[1]??``).replace(/\r\n/g,`
7
+ `+o}function ht(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch depth limit reached`}}function gt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch concurrency limit reached`}}function _t(e,t,n={}){e.kill(t,`SIGTERM`);let r=setTimeout(()=>{n.isDone?.()!==!0&&e.kill(t,`SIGKILL`)},5e3);return n.unref===!0&&r.unref(),()=>clearTimeout(r)}function vt(){return{...ht(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function yt(){return{...gt(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function bt(e){if(e!==void 0&&e.length!==0)return e.includes(`Response was truncated: the model reached its output token limit.`)?`child response was truncated at the model's output token limit (pi exited non-zero)`:void 0}function xt(e){if(e.aborted)return{status:`rejected`,errorMessage:`dispatch cancelled`};if(e.exitCode===0&&e.finalText.length>0)return{status:`fulfilled`};if(e.exitCode===0)return{status:`rejected`,errorMessage:`dispatch produced no final text`};let t=bt(e.stderr);return{status:`rejected`,...t===void 0?{}:{errorMessage:t}}}function St(e,t){let n=e.match(RegExp(`^`+t+`:\\s*(.+)$`,`m`));if(!n)return;let r=(n[1]??``).trim();if(r.length>=2){let e=r[0],t=r[r.length-1];(e===`"`&&t===`"`||e===`'`&&t===`'`)&&(r=r.slice(1,-1))}return r.length===0?void 0:r}function Ct(e,t){let n=e.match(RegExp(`^`+t+`:\\s*(.+)$`,`m`));if(!n)return;let r=(n[1]??``).trim();r.startsWith(`[`)&&r.endsWith(`]`)&&(r=r.slice(1,-1));let i=r.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);return i.length===0?void 0:i}function wt(e){let t=St(e,`childReport`);if(t!==void 0)return t.toLowerCase()!==`false`&&t.toLowerCase()!==`no`}function Tt(e){return e.childReport!==!1}function Et(e){let t=e.match(/^\uFEFF?[ \t]*(?:\r?\n)?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n([\s\S]*))?$/);if(!t)return null;let n=(t[1]??``).replace(/\r\n/g,`
8
8
  `),r=(t[2]??``).replace(/\r\n/g,`
9
- `),i=yt(n,`name`);if(!i)return null;let a=yt(n,`description`)??``,o=yt(n,`model`)??``,s=bt(n,`tools`),c=xt(n),l={name:i,systemPrompt:r.trim()};return a!==void 0&&(l.description=a),o!==void 0&&(l.model=o),s!==void 0&&(l.tools=s),c!==void 0&&(l.childReport=c),l}function wt(e,t,n,r){let{userDir:i,projectDir:a}=Tt({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:O.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:O.join(a,e+`.md`),source:`project`});for(let t of o){let n;try{n=C.readFileSync(t.path,`utf-8`)}catch{continue}let r=Ct(n);if(r&&r.name===e){let e={name:r.name,source:t.source,systemPrompt:r.systemPrompt};return r.model!==void 0&&(e.model=r.model),r.tools!==void 0&&(e.tools=r.tools),r.childReport!==void 0&&(e.childReport=r.childReport),e}}return null}function Tt(e){let t=e.homeDir??re.homedir();return{userDir:O.join(t,`.pi`,`agent`,`agents`),projectDir:O.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function Et(e){let t=e?.code;return typeof t==`string`?t:String(e)}function Dt(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function Ot(e,t){let n=O.resolve(e),r=O.resolve(t),i=e=>O.dirname(e),a=n,o=!1;for(let e=0;e<=8;e+=1){try{if(C.statSync(a).isDirectory()){o=!0;break}}catch{}if(a===r)break;let e=i(a);if(e===a)break;a=e}if(o){for(let e=n;e!==a&&e!==i(e);e=i(e))if(kt(e))return!0;return!1}return a===r&&kt(r)}function kt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function At(e,t,n){let r=Et(n);return r!==`ENOENT`&&r!==`ENOTDIR`||Dt(e)?!1:!Ot(e,t)}function jt(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=Tt(e),a=[];(e.agentScope===`user`||e.agentScope===`both`)&&a.push({dir:t,boundary:r,source:`user`}),(e.agentScope===`project`||e.agentScope===`both`)&&a.push({dir:n,boundary:i,source:`project`});let o=/* @__PURE__ */ new Map;for(let{dir:e,boundary:t,source:n}of a){let r;try{r=C.readdirSync(e)}catch(n){if(!At(e,t,n)){let t=Et(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of r){if(!t.endsWith(`.md`))continue;let r=t.slice(0,-3),i=O.join(e,t),a;try{a=C.readFileSync(i,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`pi.dispatch: cannot read agent file ${i}: ${t}; falling back to the filename`),o.has(r)||o.set(r,{name:r,description:``,source:n});continue}let s=Ct(a),c=s?.name??r;c.length!==0&&(o.has(c)||o.set(c,{name:c,description:(s?.description??``).trim(),source:n}))}}return[...o.values()]}function Mt(e){return jt(e).map(e=>e.name).sort()}function Nt(e){let t=jt(e),n="`agent` is optional: omit it for a fresh generalist pi with pi's own system prompt and its full toolset. Name a definition to NARROW the child instead.";if(t.length===0)return n+` None are registered here, so there is nothing to name.`;let r=t.map(e=>{let t=e.description.length>0?e.description:`(no description given)`;return`- ${e.name} (${e.source} scope): ${t}`});return n+"\nRegistered definitions — pass `agentScope` matching the scope shown, since it defaults "+`to "user" and does not see the others:
9
+ `),i=St(n,`name`);if(!i)return null;let a=St(n,`description`)??``,o=St(n,`model`)??``,s=Ct(n,`tools`),c=wt(n),l={name:i,systemPrompt:r.trim()};return a!==void 0&&(l.description=a),o!==void 0&&(l.model=o),s!==void 0&&(l.tools=s),c!==void 0&&(l.childReport=c),l}function Dt(e,t,n,r){let{userDir:i,projectDir:a}=Ot({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:k.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:k.join(a,e+`.md`),source:`project`});for(let t of o){let n;try{n=C.readFileSync(t.path,`utf-8`)}catch{continue}let r=Et(n);if(r&&r.name===e){let e={name:r.name,source:t.source,systemPrompt:r.systemPrompt};return r.model!==void 0&&(e.model=r.model),r.tools!==void 0&&(e.tools=r.tools),r.childReport!==void 0&&(e.childReport=r.childReport),e}}return null}function Ot(e){let t=e.homeDir??D.homedir();return{userDir:k.join(t,`.pi`,`agent`,`agents`),projectDir:k.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function kt(e){let t=e?.code;return typeof t==`string`?t:String(e)}function At(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function jt(e,t){let n=k.resolve(e),r=k.resolve(t),i=e=>k.dirname(e),a=n,o=!1;for(let e=0;e<=8;e+=1){try{if(C.statSync(a).isDirectory()){o=!0;break}}catch{}if(a===r)break;let e=i(a);if(e===a)break;a=e}if(o){for(let e=n;e!==a&&e!==i(e);e=i(e))if(Mt(e))return!0;return!1}return a===r&&Mt(r)}function Mt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function Nt(e,t,n){let r=kt(n);return r!==`ENOENT`&&r!==`ENOTDIR`||At(e)?!1:!jt(e,t)}function Pt(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=Ot(e),a=[];(e.agentScope===`user`||e.agentScope===`both`)&&a.push({dir:t,boundary:r,source:`user`}),(e.agentScope===`project`||e.agentScope===`both`)&&a.push({dir:n,boundary:i,source:`project`});let o=/* @__PURE__ */ new Map;for(let{dir:e,boundary:t,source:n}of a){let r;try{r=C.readdirSync(e)}catch(n){if(!Nt(e,t,n)){let t=kt(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of r){if(!t.endsWith(`.md`))continue;let r=t.slice(0,-3),i=k.join(e,t),a;try{a=C.readFileSync(i,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`pi.dispatch: cannot read agent file ${i}: ${t}; falling back to the filename`),o.has(r)||o.set(r,{name:r,description:``,source:n});continue}let s=Et(a),c=s?.name??r;c.length!==0&&(o.has(c)||o.set(c,{name:c,description:(s?.description??``).trim(),source:n}))}}return[...o.values()]}function Ft(e){return Pt(e).map(e=>e.name).sort()}function It(e){let t=Pt(e),n="`agent` is optional: omit it for a fresh generalist pi with pi's own system prompt and its full toolset. Name a definition to NARROW the child instead.";if(t.length===0)return n+` None are registered here, so there is nothing to name.`;let r=t.map(e=>{let t=e.description.length>0?e.description:`(no description given)`;return`- ${e.name} (${e.source} scope): ${t}`});return n+"\nRegistered definitions — pass `agentScope` matching the scope shown, since it defaults "+`to "user" and does not see the others:
10
10
  `+r.join(`
11
- `)}function Pt(e){let{userDir:t,projectDir:n}=Tt(e),r=Mt(e);return`registered agents: ${r.length>0?`[`+r.join(`, `)+`]`:`(none)`} — agents load from ${t}/<name>.md (user scope) or ${n}/<name>.md (project scope); register one as an agent markdown file: frontmatter header (\`---\\nname: <agent-name>\\n---\`) followed by the system prompt body`}function Ft(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:`agent, when given, must be a non-empty string — omit it entirely to dispatch a generalist child; `+Pt(e)}}function It(e){return e!==void 0&&(typeof e!=`string`||e.trim().length===0)}function Lt(e){return e===void 0}function Rt(e,t,n){if(Lt(e.agent))return{kind:`resolved`,agent:ut};let r=wt(e.agent,t,n);return r?{kind:`resolved`,agent:r}:{kind:`unknown`,name:e.agent}}function zt(e,t,n,r=0){return{text:``,status:`rejected`,started:!1,agentName:e,durationMs:r,exitCode:1,reportChannel:`none`,errorMessage:`unknown agent: `+e+` (agentScope=`+t+`, cwd=`+n+`). `+Pt({cwd:n,agentScope:t})}}function Bt(e){let t=e.tools??[];if(!St(e))return t.length>0?t:void 0;if(t.length!==0)return t.includes(`ptc_child_report`)?t:[...t,Le]}function Vt(e,t,n){let r=[`--mode`,`json`,`-p`,`--no-session`],i=e.model??t.model;i&&r.push(`--model`,i);let a=e.thinkingLevel??`off`;r.push(`--thinking`,a);let o=Bt(t);return o!==void 0&&r.push(`--tools`,o.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}let Ht=Ut;async function Ut(e,t){let n=await C.promises.mkdtemp(O.join(re.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=O.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function Wt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Gt(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message.content;if(!Array.isArray(t))return;let n;for(let e of t)e&&e.type===`text`&&typeof e.text==`string`&&(n=e.text);return n}function Kt(e,t){if(t.type!==`message_end`)return e;let n=t.message;if(n?.role!==`assistant`||n.usage===void 0)return e;let r=e??{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,turns:0};return r.input+=n.usage.input??0,r.output+=n.usage.output??0,r.cacheRead+=n.usage.cacheRead??0,r.cacheWrite+=n.usage.cacheWrite??0,r.cost+=n.usage.cost?.total??0,r.turns+=1,r}function qt(e){let t=[],n;for(let r of e.split(`
11
+ `)}function Lt(e){let{userDir:t,projectDir:n}=Ot(e),r=Ft(e);return`registered agents: ${r.length>0?`[`+r.join(`, `)+`]`:`(none)`} — agents load from ${t}/<name>.md (user scope) or ${n}/<name>.md (project scope); register one as an agent markdown file: frontmatter header (\`---\\nname: <agent-name>\\n---\`) followed by the system prompt body`}function Rt(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:`agent, when given, must be a non-empty string — omit it entirely to dispatch a generalist child; `+Lt(e)}}function zt(e){return e!==void 0&&(typeof e!=`string`||e.trim().length===0)}function Bt(e){return e===void 0}function Vt(e,t,n){if(Bt(e.agent))return{kind:`resolved`,agent:pt};let r=Dt(e.agent,t,n);return r?{kind:`resolved`,agent:r}:{kind:`unknown`,name:e.agent}}function Ht(e,t,n,r=0){return{text:``,status:`rejected`,started:!1,agentName:e,durationMs:r,exitCode:1,reportChannel:`none`,errorMessage:`unknown agent: `+e+` (agentScope=`+t+`, cwd=`+n+`). `+Lt({cwd:n,agentScope:t})}}function Ut(e,t){if(R(t)===`strict`)return Tt(e)?[...ut,Le]:ut;let n=e.tools??[];if(!Tt(e))return n.length>0?n:void 0;if(n.length!==0)return n.includes(`ptc_child_report`)?n:[...n,Le]}function Wt(e,t,n){let r=[`--mode`,`json`,`-p`,`--no-session`],i=e.model??t.model;i&&r.push(`--model`,i);let a=e.thinkingLevel??`off`;r.push(`--thinking`,a);let o=Ut(t,e.readOnly);return o!==void 0&&r.push(`--tools`,o.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}let Gt=Kt;async function Kt(e,t){let n=await C.promises.mkdtemp(k.join(D.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=k.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function qt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Jt(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message.content;if(!Array.isArray(t))return;let n;for(let e of t)e&&e.type===`text`&&typeof e.text==`string`&&(n=e.text);return n}function Yt(e,t){if(t.type!==`message_end`)return e;let n=t.message;if(n?.role!==`assistant`||n.usage===void 0)return e;let r=e??{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,turns:0};return r.input+=n.usage.input??0,r.output+=n.usage.output??0,r.cacheRead+=n.usage.cacheRead??0,r.cacheWrite+=n.usage.cacheWrite??0,r.cost+=n.usage.cost?.total??0,r.turns+=1,r}function Xt(e){let t=[],n;for(let r of e.split(`
12
12
  `)){let e=r.trim();if(n===void 0){let t=/^(`{3,}|~{3,})(.*)$/.exec(e);t&&(n={marker:(t[1]??``)[0],info:(t[2]??``).trim(),body:[]});continue}RegExp(`^`+n.marker+`{3,}\\s*$`).test(e)?(t.push({info:n.info,body:n.body.join(`
13
13
  `)}),n=void 0):n.body.push(r)}return n!==void 0&&t.push({info:n.info,body:n.body.join(`
14
- `)}),t}function Jt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Yt(e){if(!Jt(e))return;let{summary:t,findings:n,files_touched:r}=e;if(typeof t!=`string`||!Array.isArray(n))return;let i=[];for(let e of n){if(!Jt(e)||typeof e.what!=`string`||typeof e.evidence!=`string`)return;i.push({what:e.what,evidence:e.evidence})}if(!Array.isArray(r))return;let a=[];for(let e of r){if(typeof e!=`string`)return;a.push(e)}return{summary:t,findings:i,files_touched:a}}function Xt(e){let t=qt(e),n=t[t.length-1];if(n===void 0)return{reportChannel:`none`};let r;try{r=JSON.parse(n.body)}catch{return{reportChannel:`none`}}let i=Yt(r);return i===void 0?{reportChannel:`none`}:{report:i,reportChannel:`prompt-json`}}function Zt(e){if(e.type===`tool_execution_end`&&e.toolName===`ptc_child_report`&&e.isError!==!0)return Yt(e.result?.structuredContent)}function Qt(){return{prompt:{reportChannel:`none`},tool:void 0}}function $t(e,t){let n=Zt(t);n!==void 0&&(e.tool=n)}function en(e){return e.tool===void 0?e.prompt:{report:e.tool,reportChannel:`tool`}}function tn(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message;if(t.stopReason!==`error`)return;let n=t.errorMessage;return typeof n==`string`&&n.trim().length>0?n.trim():`child reported stopReason: error`}async function nn(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return ht();if(It(e.agent))return Ft({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`});let i=Oe(),a=n.slots??ot;if(!a.tryAcquire(i))return gt();let o=n.clock??(()=>Date.now()),s=n.logger??lt,c=e.cwd??t.cwd,l=e.agentScope??`user`,u=n.lifecycle??it,d=t.callerId??`dispatch:`+String(t.callId),f=ct(n,o),p=n.outputStorage,m=Rt(e,c,l);if(m.kind===`unknown`)return a.release(i),zt(m.name,l,c);let h=m.agent,g,_;try{let n=e.label??e.task.slice(0,64),l=St(h),m=dt(h.systemPrompt,r,t.maxDispatchDepth,{reportContract:l}),v=await Ht(h.name,m);_=v;let y=Vt(e,h,v.filePath),b={cwd:c,env:{...process.env,PI_PTC_DEPTH:String(r),PI_PTC_TASK_ID:i},promptFile:v.filePath};t.sessionDir!==void 0&&(b.sessionDir=t.sessionDir,b.sessionId=i,b.sessionName=`bgdispatch:`+i),g=u.spawn([`pi`,...y],b);let x=g,S={kind:`ptc-program`,callerId:d};await f.transition({kind:`spawn`,handle:{taskId:i,label:n,status:`running`},record:{label:n,agentName:h.name,depth:r,startedAt:Math.max(0,Math.floor(o())),finishedAt:void 0,durationMs:void 0,outputRef:void 0,outputBytes:void 0,outputPreview:void 0,stopReason:void 0,errorMessage:void 0,exitCode:void 0,spawnSource:S,parentTaskId:t.parentTaskId}},{clock:o,callerId:d,logger:s});let C=!1,w,T=f.onTransition((e,t)=>{e.id===i&&t.status===`stopping`&&(C||w!==void 0||(w=mt(u,x,{isDone:()=>C,unref:!0})))});return(async()=>{let e=``,t,n=Qt(),r;try{for await(let i of u.events(x)){$t(n,i);let a=Gt(i);a!==void 0&&(e=a,n.prompt=Xt(a)),r=Kt(r,i);let o=tn(i);o!==void 0&&(t=o)}C=!0,w?.();let a=(await u.exit(x)).code??-1,c=await u.stderr(x),m=a===0?void 0:_t(c),h=Buffer.byteLength(e,`utf8`),g=h<=2048?e:void 0,_;if(p!==void 0)try{await p.writeOutput(i,e),_=p.outputRef(i)}catch(e){let t=e instanceof Error?e.message:String(e);s.warn(`background dispatch output persistence for task `+i+` failed: `+t)}let v=l?en(n):{reportChannel:`opted-out`};await f.transition({kind:`resolve-exit`,taskId:i,exitCode:a,reportChannel:v.reportChannel,...v.report===void 0?{}:{report:{...v.report,usage:{input:r?.input??0,output:r?.output??0,cost:r?.cost??0,turns:r?.turns??0}}},outputRef:_,outputBytes:h,outputPreview:g,childError:t,...m===void 0?{}:{stderrDiagnostic:m}},{clock:o,callerId:d,logger:s})}catch(t){let n=t instanceof Error?t.message:String(t);s.warn(`background dispatch pump for task `+i+` failed after `+String(e.length)+` chars of buffered output: `+n)}finally{T(),w?.(),Wt(v),a.release(i)}})(),{taskId:i,label:n,status:`running`}}catch(e){let t=e instanceof Error?e.message:String(e);return g!==void 0&&mt(u,g,{unref:!0}),_!==void 0&&Wt(_),a.release(i),s.warn(`background dispatch failed for agent `+h.name+`: `+t),{text:``,status:`rejected`,started:g!==void 0,agentName:h.name,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`background dispatch failed: `+t}}}async function rn(e,t,n={}){if(e.background===!0)return await nn(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return ft();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now();if(It(e.agent))return Ft({cwd:i,agentScope:a});let s=n.slots??ot;if(!s.tryAcquire())return pt();let c=Rt(e,i,a);if(c.kind===`unknown`)return s.release(),zt(c.name,a,i,Date.now()-o);let l=c.agent,u=St(l),d=dt(l.systemPrompt,r,t.maxDispatchDepth,{reportContract:u}),f,p=n.lifecycle??it,m;try{f=await Ht(l.name,d),m=Vt(e,l,f.filePath)}catch(e){throw s.release(),e}return await new Promise(e=>{let a=``,c,d=Qt(),h=-1,g=``,_=!1,v,y,b=!1,x=(r,i,m=!0)=>{if(_)return;_=!0,s.release(),y!==void 0&&p.exit(y).catch(e=>{(n.logger??lt).warn(`exit() failed for a foreground child; the session live set may retain it: `+(e instanceof Error?e.message:String(e)))}),v?.(),t.signal&&t.signal.removeEventListener(`abort`,S),Wt(f);let b=u?en(d):{reportChannel:`opted-out`},x={text:a,status:r,started:m,agentName:l.name,durationMs:Date.now()-o,exitCode:h,reportChannel:b.reportChannel};b.report&&(x.report={...b.report,usage:{input:c?.input??0,output:c?.output??0,cost:c?.cost??0,turns:c?.turns??0}}),c&&(x.usage=c),g.length>0&&(x.stderr=g),i&&(x.errorMessage=i),e(x)},S=()=>{y&&!_&&(b=!0,v=mt(p,y,{isDone:()=>_}))};try{y=p.spawn([`pi`,...m],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:f.filePath})}catch(e){x(`rejected`,`failed to spawn pi: `+(e instanceof Error?e.message:String(e)),!1);return}t.signal&&(t.signal.aborted?S():t.signal.addEventListener(`abort`,S,{once:!0})),(async()=>{if(!y)return;let e=y;try{for await(let t of p.events(e))if($t(d,t),t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(c=Kt(c,t),Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(a=t.text,d.prompt=Xt(t.text))}let t=await it.exit(e);h=t.code??-1,g=await it.stderr(e);let n=g.match(/^\[spawn-error\] (.+)$/m);if(n&&t.code===null&&t.signal===null){x(`rejected`,`failed to spawn pi: `+n[1],!1);return}let{status:r,errorMessage:i}=vt({exitCode:h,finalText:a,aborted:b,stderr:g});x(r,i)}catch(e){let t=e instanceof Error?e.message:String(e);x(`rejected`,`dispatch internal error: `+t)}})()})}const R=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],z=`pi.dispatch`,an=[`bash`];function on(e){return an.includes(e)}function sn(e){if(e===void 0)return[];let t=new Set(e);for(let e of t)if(!on(e))throw TypeError(`unknown PTC opt-in binding "${e}"; opt-in bindings: ${an.join(`, `)}`);return R.filter(e=>t.has(e))}const cn=R.filter(e=>!on(e)),ln={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},un=x.Object({agent:x.Optional(x.String({minLength:1,description:`Optional. Name a registered agent definition to narrow the child, or omit it entirely for a fresh generalist pi with pi's own prompt and its full toolset. A name with no definition behind it is refused; an empty string is refused.`})),task:x.String({minLength:1}),cwd:x.Optional(x.String()),agentScope:x.Optional(x.Union([x.Literal(`user`),x.Literal(`project`),x.Literal(`both`)],{description:`Which agent directories to search: "user" (~/.pi/agent/agents, the default), "project" (<cwd>/.pi/agents), or "both". Defaults to "user", which cannot see project agents.`})),model:x.Optional(x.String()),thinkingLevel:x.Optional(x.String()),background:x.Optional(x.Boolean()),label:x.Optional(x.String())}),dn={name:z,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters:un};function fn(e,t){let n=t.trim();return n.length===0?`${e} reported a failure with no message`:`${e} failed: ${n.length<=2e3?n:`…${n.slice(-2e3)}`}`}function pn(e){let t=new Set(sn(e.optIns)),n=e.names??R.filter(e=>cn.includes(e)||t.has(e)),r=e.includeDispatch??e.names===void 0,i=/* @__PURE__ */ new Map;for(let t of n){let n=ln[t];if(!n)throw TypeError(`unknown PTC binding "${t}"; known bindings: ${R.join(`, `)}`);let r=n(e.cwd);i.set(t,{name:t,execute:async(e,t)=>{let n=`ptc:${t.callId}`,i={type:`toolCall`,id:n,name:r.name,arguments:e},a=S(r,i),o;try{o=await r.execute(n,a,t.signal,void 0)}catch(e){throw Error(fn(r.name,e instanceof Error?e.message:String(e)))}if(o.isError===!0)throw Error(fn(r.name,(o.content??[]).filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text??``).join(`
15
- `)));return{content:o.content,details:o.details===void 0?null:o.details}}})}return r&&i.set(z,{name:z,execute:async(t,n)=>{let r={type:`toolCall`,id:`ptc:${n.callId}`,name:z,arguments:t},i;try{i=S(dn,r)}catch(n){let r=typeof t==`object`&&t&&!Array.isArray(t)?t:void 0,i=r?.agent,a=r?.agentScope;return It(i)?Ft({cwd:e.cwd,agentScope:a===`user`||a===`project`||a===`both`?a:`user`}):{text:``,status:`rejected`,started:!1,agentName:typeof i==`string`?i:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:n instanceof Error?n.message:String(n)}}return rn(i,{signal:n.signal,callId:n.callId,cwd:e.cwd,depth:n.depth,maxDispatchDepth:n.maxDispatchDepth,...n.callerId===void 0?{}:{callerId:n.callerId},...n.sessionDir===void 0?{}:{sessionDir:n.sessionDir},...n.parentTaskId===void 0?{}:{parentTaskId:n.parentTaskId}},n.dispatchDeps)}}),i}function mn(){let e=/* @__PURE__ */ new Map;return{recordStart(t,n,r){if(e.has(t))throw Error(`duplicate sub-call callId ${t}`);e.set(t,{callId:t,name:n,args:r,status:`running`,startMs:Date.now()})},recordEnd(t,n,r){let i=e.get(t);if(i===void 0)throw Error(`recordEnd on unknown callId ${t}`);return i.status=n,i.endMs=Date.now(),i.durationMs=i.endMs-i.startMs,n===`rejected`&&(i.durationMs=0),r?.errorMessage!==void 0&&(i.errorMessage=r.errorMessage),r?.resultSummary!==void 0&&(i.resultSummary=r.resultSummary),i},snapshot(){return[...e.values()].map(e=>({...e}))}}}function hn(e){return{name:`ptc-${e.surface}`,env:e.env,workerData:e.runId===void 0?{env:e.env}:{runId:e.runId,env:e.env},resourceLimits:{maxOldGenerationSizeMb:e.limits.maxOldGenerationSizeMb,maxYoungGenerationSizeMb:e.limits.maxYoungGenerationSizeMb}}}const B={acquireLatency:de.channel(`ptc:pool:acquire-latency`),resetTime:de.channel(`ptc:worker:reset-time`),imageBytes:de.channel(`ptc:image:hoist-bytes`)};function V(e,t){e.publish(t)}var gn=class{#e;#t;#n;#r;#i;#a=[];#o=/* @__PURE__ */ new Set;#s=[];#c=/* @__PURE__ */ new WeakMap;#l=0;#u=0;#d=!1;constructor(e){if(typeof e.buildWorkerUrl!=`function`)throw TypeError(`WorkerPool: buildWorkerUrl must be a function`);if(e.size!==void 0&&(typeof e.size!=`number`||!Number.isFinite(e.size)||e.size<=0))throw TypeError(`WorkerPool: size must be a positive finite number, received ${String(e.size)}`);if(e.acquireTimeoutMs!==void 0&&(typeof e.acquireTimeoutMs!=`number`||!Number.isFinite(e.acquireTimeoutMs)||e.acquireTimeoutMs<=0))throw TypeError(`WorkerPool: acquireTimeoutMs must be a positive finite number, received ${String(e.acquireTimeoutMs)}`);if(e.drainGraceMs!==void 0&&(typeof e.drainGraceMs!=`number`||!Number.isFinite(e.drainGraceMs)||e.drainGraceMs<=0))throw TypeError(`WorkerPool: drainGraceMs must be a positive finite number, received ${String(e.drainGraceMs)}`);this.#e=e.buildWorkerUrl,this.#t=e.size??4,this.#n=e.acquireTimeoutMs??3e4,this.#r=e.drainGraceMs??5e3,this.#i=e.workerOptions}async acquire(){if(this.#d)throw Error(`pool has been drained and can no longer serve workers`);this.#l+=1;let e=Date.now(),t=this.#a.shift();for(;t!==void 0&&!this.#p(t);)t=this.#a.shift();if(t!==void 0)return this.#o.add(t),t.ref(),V(B.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-e}),t;if(this.#o.size<this.#t){let t=this.#f();return this.#o.add(t),V(B.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-e}),t}return this.#u+=1,await new Promise((t,n)=>{let r=setTimeout(()=>{let e=this.#s.findIndex(e=>e.timer===r);e>=0&&this.#s.splice(e,1),n(/* @__PURE__ */ Error(`pool acquire timed out after ${this.#n} ms`))},this.#n);this.#s.push({resolve:t,reject:n,timer:r,startedAt:e})})}release(e){if(!this.#o.delete(e)||!this.#p(e))return;this.#c.set(e,Date.now());let t=this.#s.shift();if(t){clearTimeout(t.timer),this.#o.add(e),V(B.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-t.startedAt}),t.resolve(e);return}this.#a.push(e),e.unref()}lastSettledAt(e){return this.#c.get(e)}async drain(){for(;this.#s.length>0;){let e=this.#s.shift();if(!e)break;clearTimeout(e.timer),e.reject(/* @__PURE__ */ Error(`pool drained before acquire could be satisfied`))}let e=Date.now()+this.#r;for(;this.#o.size>0&&Date.now()<e;)await new Promise(e=>setTimeout(e,5));let t=[...this.#a,...this.#o];this.#a.length=0,this.#o.clear(),await Promise.all(t.map(e=>e.terminate().catch(()=>void 0))),this.#d=!0}stats(){return{resident:this.#o.size+this.#a.length,inFlight:this.#o.size,waiters:this.#s.length,totalAcquires:this.#l,poolExhaustions:this.#u}}#f(){let e=new ue(this.#e(),this.#i);return e.once(`exit`,()=>{let t=this.#a.indexOf(e);if(t>=0){this.#a.splice(t,1);return}this.#o.delete(e)}),e}#p(e){return e.threadId!==-1}};function _n(e){V(B.imageBytes,{byteLength:e})}function vn(e){V(B.resetTime,{durationMs:e})}function yn(){let e=k(fe(import.meta.url)),t=[j(e,`worker.js`),j(e,`worker-entry.ts`)];for(let e of t)if(w(e))return pe(e);throw Error(`worker entry not found; tried: ${t.join(`, `)}`)}function bn(e){if(typeof e!=`object`||!e)return;let t=e;if(t.status!==`rejected`)return;let n=typeof t.errorMessage==`string`?t.errorMessage:t.started===!1?`dispatch refused`:`dispatch failed`;return{kind:t.started===!1?`refused`:`failed`,message:n}}function H(e){return e instanceof Error?e.message:String(e)}function xn(e){if(typeof e!=`object`||!e)return;let t=e.content;if(Array.isArray(t)&&t.length>0){let e=t[0];if(typeof e==`object`&&e){let t=e.text;if(typeof t==`string`&&t.length>0){let e=t.indexOf(`
16
- `);return e===-1?t:t.slice(0,e)}}}}function Sn(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function Cn(e,t){let n=/* @__PURE__ */ new WeakSet,r=e=>{if(e!=null){if(e instanceof ArrayBuffer){t(e);return}if(ArrayBuffer.isView(e)){t(e);return}if(typeof e==`object`&&!n.has(e)){if(n.add(e),Array.isArray(e)){for(let t of e)r(t);return}for(let t of Object.keys(e))r(e[t])}}};r(e)}function wn(e){try{let t=Buffer.byteLength(JSON.stringify(e,(e,t)=>Sn(t)?null:t)??``,`utf8`),n=0;return Cn(e,e=>{n+=e.byteLength}),t+n}catch{return 1/0}}async function Tn(e){let i=Be(e.config),s=ze(),c=e.runId??ce(),l=Ve(e.timeoutMs,i),u=[],d=[],f=[];if(e.signal?.aborted)return{logs:u,narrations:d,phases:f,error:{kind:n.abort,message:`run cancelled before start`}};let p;try{p=e.pool?await e.pool.acquire():new ue(yn(),hn({surface:e.surface,env:s,limits:i,runId:c}))}catch(e){return{logs:u,narrations:d,phases:f,error:{kind:n.workerExit,message:`pool acquire failed: ${H(e)}`}}}return await new Promise(s=>{let m=new le,h=m.port1,g=m.port2,_=new AbortController,v=!1,y=mn(),b=()=>{v||e.onSubCallChange?.(()=>y.snapshot())},x={recordStart(e,t,n){y.recordStart(e,t,n),b()},recordEnd(e,t,n){let r=y.recordEnd(e,t,n);return b(),r},snapshot:()=>y.snapshot()},S,C=!1,w=0,T=0,ee=new at(i.dispatchConcurrency),te=0,ne=[],re=e.depth??0,E,D,O=[],ie=e=>{let t=[],n=e?.content;if(!Array.isArray(n))return t;for(let e of n){if(typeof e!=`object`||!e)continue;let n=e;if(n.type!==`image`)continue;let r;typeof n.data==`string`&&n.data.length>0?r=n.data:n.bytes instanceof ArrayBuffer&&n.bytes.byteLength>0&&(r=Buffer.from(n.bytes).toString(`base64`)),r!==void 0&&t.push({data:r,mimeType:typeof n.mimeType==`string`?n.mimeType:`application/octet-stream`})}return t},k=e=>e===`timeout`?`run timed out after ${l} ms`:`run cancelled`,A=e=>e===`timeout`?n.timeout:n.abort,ae=t=>{if(v)return;v=!0,E&&clearTimeout(E),D&&clearTimeout(D),e.signal?.removeEventListener(`abort`,F),_.abort(),h.close(),e.pool?e.pool.release(p):p.terminate();let n=x.snapshot();s(n.length>0?{...t,subCalls:n}:t)},j=(e,t,n)=>{ae({logs:u,narrations:d,phases:f,error:n===void 0?{kind:e,message:t}:{kind:e,message:t,stack:n}})},oe=e=>{if(!v){if(!r(e)){j(n.protocol,`internal error: malformed host frame`);return}h.postMessage(e)}},se=()=>{let t={kind:o.init,runId:c,surface:e.surface,code:e.code,bindings:[...e.bindings.keys()],bindingCandidates:[...R],maxItemsPerCall:i.maxItemsPerCall,maxPendingCalls:i.maxPendingCalls,...e.args===void 0?{}:{args:e.args}};if(!r(t)){j(n.protocol,`internal error: malformed init frame`);return}let a=wn(t);if(a>i.maxMessageBytes){j(n.protocol,`init frame of ${a} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}oe(t)},M=(e,t)=>(T+=e,T<=i.maxOutputBytes||(j(n.outputLimit,`${t} exceeded the output budget: logs + result reached ${T} bytes (maxOutputBytes=${i.maxOutputBytes}); ${u.length} log line(s) retained`),!1)),ce=async()=>{if(te<i.maxParallelSubCalls){te+=1;return}await new Promise(e=>{ne.push(e)})},N=()=>{let e=ne.shift();if(e){e();return}--te},ue=e=>{if(x.recordStart(e.callId,e.tool,e.args),w+=1,w>i.maxPendingCalls){x.recordEnd(e.callId,`error`,{errorMessage:`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`}),j(n.protocol,`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`);return}de(e).finally(()=>{--w})},de=async t=>{let r=e.bindings.get(t.tool);if(!r){x.recordEnd(t.callId,`error`,{errorMessage:`no binding named "${t.tool}" in this run; available bindings: `+([...e.bindings.keys()].join(`, `)||`(none)`)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:`no binding named "${t.tool}" in this run; available bindings: `+([...e.bindings.keys()].join(`, `)||`(none)`)});return}let a=t.tool===z;if(!a&&(await ce(),v)){x.recordEnd(t.callId,`cancelled`,{errorMessage:`run settled before binding started`}),N();return}try{let s=await r.execute(t.args,{signal:_.signal,callId:t.callId,depth:re,maxDispatchDepth:i.maxDispatchDepth,callerId:c,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...e.sessionDir===void 0?{}:{sessionDir:e.sessionDir},dispatchDeps:{...e.dispatchDeps,slots:e.dispatchDeps?.slots??ee}}),l=ie(s),u={kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:s},d=wn(u);if(d>i.maxMessageBytes){x.recordEnd(t.callId,`error`,{errorMessage:`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`}),j(n.protocol,`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}if(fe(u))for(let e of l)O.push(e),_n(Buffer.byteLength(e.data,`base64`));if(_.signal.aborted)x.recordEnd(t.callId,`cancelled`,{errorMessage:`binding aborted by run cancellation`});else{let e=a?bn(s):void 0;e===void 0?x.recordEnd(t.callId,`ok`,{resultSummary:xn(s)}):x.recordEnd(t.callId,e.kind===`refused`?`rejected`:`error`,{errorMessage:e.message})}}catch(e){_.signal.aborted?x.recordEnd(t.callId,`cancelled`,{errorMessage:H(e)}):x.recordEnd(t.callId,`error`,{errorMessage:H(e)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:H(e)})}finally{a||N()}},fe=e=>{if(v)return!1;try{return h.postMessage(e),!0}catch(t){try{h.postMessage({kind:o.callResult,callId:e.callId,tool:e.tool,ok:!1,message:`binding result could not be transferred: ${H(t)}`})}catch{j(n.protocol,`binding result is not transferable`)}return!1}},pe=e=>S?{logs:u,narrations:d,phases:f,error:{kind:A(S),message:k(S)}}:e,P=r=>{if(v)return;if(!a(r)){j(n.protocol,`malformed worker frame`);return}let o=r.kind===t.ready?0:wn(r);if(!Number.isFinite(o)){j(n.protocol,`worker frame could not be serialized for accounting`);return}if(o>i.maxMessageBytes){j(n.protocol,`control frame of ${o} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}switch(r.kind){case t.ready:if(e.pool){let t=e.pool.lastSettledAt(p);t!==void 0&&vn(Date.now()-t)}if(!C&&(C=!0,S)){me(S);return}se();return;case t.call:ue(r);return;case t.log:M(o,`console output`)&&u.push(r.text);return;case t.narration:M(o,`workflow narration`)&&d.push(r.message);return;case t.phase:M(o,`workflow phase`)&&f.push(r.title);return;case t.result:{if(!M(o,`completion value`))return;let e={logs:u,narrations:d,phases:f,...O.length>0?{images:O}:{}};ae(pe(r.value===void 0?e:{...e,value:r.value}));return}case t.error:ae(pe({logs:u,narrations:d,phases:f,error:r.error}));return;default:j(n.protocol,`unknown worker frame`)}};function F(){he(`abort`)}let me=e=>{D&&clearTimeout(D),D=setTimeout(()=>{j(A(e),k(e))},i.graceMs)};function he(e){if(!v){if(S){j(A(S),k(S));return}S=e,_.abort(),oe({kind:o.cancel,reason:e}),me(e)}}p.on(`error`,e=>{j(n.workerExit,`worker failed: ${H(e)}`)}),p.on(`exit`,e=>{j(n.workerExit,`worker exited with code ${e} before the run completed`)}),h.on(`message`,P),h.on(`messageerror`,()=>{j(n.protocol,`worker sent a frame that could not be deserialized`)}),e.signal?.addEventListener(`abort`,F,{once:!0}),E=setTimeout(()=>{he(`timeout`)},l);let ge={kind:o.connect,port:g};r(ge)?p.postMessage(ge,[g]):j(n.protocol,`internal error: malformed connect frame`)})}const En=["Return value: every `tools.<name>(args)` call above resolves to `{ content, details }`.","`content` is an ARRAY of content blocks, never a string, so a text result is","`result.content[0].text`; `details` is that tool's own detail object or `null`, never","`undefined`. No binding result has a `files`, `output`, `matches` or `entries` field:","`bash`, `grep`, `find` and `ls` hand back ONE text block of newline-separated rows that","you split yourself, and the empty answer is a sentinel string (`No matches found`,","`No files found matching pattern`, `(empty directory)`) rather than an empty list.","A failing call REJECTS with `ToolCallError` instead of resolving, so wrap the call in","`try`/`catch` (or `Promise.allSettled`): a path that is not there, a builtin this run did not",`bind. A name that is not a builtin is simply not a function.`],Dn=/* @__PURE__ */ new Map([[`bash`,"`bash` rejects on a non-zero exit rather than resolving with its output."],[`write`,"`write` always reports `details: null`."],[`edit`,"`edit` always reports a `details` object carrying `diff` and `patch`."],[z,'`tools["pi.dispatch"]` is the exception: it resolves to `{ text, status, ... }` with no `content` and never throws, so read `status`.']]),On=[En.join(`
17
- `),`Exceptions: `+[...Dn.values()].join(` `)].join(`
18
- `),kn=`pi-ptc-output-`;function An(e,t=kn){let n=A(D(),`${t}${ce()}.txt`);return ne(n,e,`utf8`),n}function jn(e,t){let n=e.totalLines-e.outputLines+1,r=e.totalLines;return e.lastLinePartial?`[Showing last ${_(e.outputBytes)} of line ${r}. Full output: ${t}]`:e.truncatedBy===`lines`?`[Showing lines ${n}-${r} of ${e.totalLines}. Full output: ${t}]`:`[Showing lines ${n}-${r} of ${e.totalLines} (${_(s)} limit). Full output: ${t}]`}function Mn(e,t=kn,n={}){let r=b(e,{maxLines:c,maxBytes:s});if(!r.truncated)return{text:e,truncated:!1};let i=An(n.fullText??e,t);return{text:`${r.content}\n\n${jn(r,i)}`,truncated:!0,fullPath:i}}const Nn=200,Pn=new RegExp([`(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))`,`[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]`].join(`|`),`g`);function Fn(e){return!e.includes(`\x1B`)&&!e.includes(`›`)?e:e.replace(Pn,``)}function U(e){let t=Fn(e).replace(/\r/g,``);if(t.length===0)return t;let n=``;for(let e of t){let t=e.codePointAt(0);if(t!==void 0){if(t===10||t===9){n+=e;continue}t<=31||t>=65529&&t<=65531||(n+=e)}}return n}const In=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function Ln(e){return In.test(e)?e:JSON.stringify(e)}function Rn(e){if(e===null)return`null`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(typeof e==`string`){let t=U(e);return t.includes(`
19
- `)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=Rn(n);if(e===void 0)return;t.push(e)}return`[${t.join(`, `)}]`}let t=Object.keys(e);if(t.length===0)return`{}`;let n=[];for(let r of t){let t=Rn(e[r]??null);if(t===void 0)return;n.push(`${Ln(r)}: ${t}`)}return`{${n.join(`, `)}}`}function zn(e){let t=Rn(e);if(t!==void 0)return t.length<=100?t:void 0}function Bn(e){return e===null?`null`:typeof e==`string`?U(e):String(e)}function Vn(e,t){if(typeof e!=`object`||!e)return[`${t}${Bn(e)}`];if(Array.isArray(e)){if(e.length===0)return[`${t}[]`];let n=[`${t}[`];for(let r of e){let e=zn(r);if(e!==void 0){n.push(`${t} ${e}`);continue}n.push(...Hn(r,t+` `))}return n.push(`${t}]`),n}let n=Object.keys(e);if(n.length===0)return[`${t}{}`];let r=[`${t}{`],i=t+` `;for(let t of n){let n=e[t]??null,a=zn(n);if(a!==void 0){r.push(`${i}${Ln(t)}: ${a}`);continue}if(typeof n==`string`){r.push(`${i}${Ln(t)}:`);for(let e of U(n).split(`
20
- `))r.push(e.length===0?``:`${i} ${e}`);continue}let o=Vn(n,i);r.push(`${i}${Ln(t)}: ${(o[0]??``).trimStart()}`.trimEnd(),...o.slice(1))}return r.push(`${t}}`),r}function Hn(e,t){return typeof e==`string`?U(e).split(`
21
- `):typeof e!=`object`||!e?[String(e)]:Vn(e,t)}function Un(e){return e.split(`
14
+ `)}),t}function Zt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Qt(e){if(!Zt(e))return;let{summary:t,findings:n,files_touched:r}=e;if(typeof t!=`string`||!Array.isArray(n))return;let i=[];for(let e of n){if(!Zt(e)||typeof e.what!=`string`||typeof e.evidence!=`string`)return;i.push({what:e.what,evidence:e.evidence})}if(!Array.isArray(r))return;let a=[];for(let e of r){if(typeof e!=`string`)return;a.push(e)}return{summary:t,findings:i,files_touched:a}}function $t(e){let t=Xt(e),n=t[t.length-1];if(n===void 0)return{reportChannel:`none`};let r;try{r=JSON.parse(n.body)}catch{return{reportChannel:`none`}}let i=Qt(r);return i===void 0?{reportChannel:`none`}:{report:i,reportChannel:`prompt-json`}}function en(e){if(e.type===`tool_execution_end`&&e.toolName===`ptc_child_report`&&e.isError!==!0)return Qt(e.result?.structuredContent)}function tn(){return{prompt:{reportChannel:`none`},tool:void 0}}function nn(e,t){let n=en(t);n!==void 0&&(e.tool=n)}function rn(e){return e.tool===void 0?e.prompt:{report:e.tool,reportChannel:`tool`}}function an(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message;if(t.stopReason!==`error`)return;let n=t.errorMessage;return typeof n==`string`&&n.trim().length>0?n.trim():`child reported stopReason: error`}async function on(e,t,n,r){let i=t.depth+1;if(i>t.maxDispatchDepth)return z(vt(),r);if(zt(e.agent))return z(Rt({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`}),r);let a=Oe(),o=n.slots??ot;if(!o.tryAcquire(a))return z(yt(),r);let s=n.clock??(()=>Date.now()),c=n.logger??lt,l=e.cwd??t.cwd,u=e.agentScope??`user`,d=n.lifecycle??it,f=t.callerId??`dispatch:`+String(t.callId),p=ct(n,s),m=n.outputStorage,h=Vt(e,l,u);if(h.kind===`unknown`)return o.release(a),z(Ht(h.name,u,l),r);let g=h.agent,_,v;try{let n=e.label??e.task.slice(0,64),u=Tt(g),h=mt(g.systemPrompt,i,t.maxDispatchDepth,{reportContract:u,readOnly:e.readOnly}),y=await Gt(g.name,h);v=y;let b=Wt(e,g,y.filePath),x={cwd:l,env:{...process.env,PI_PTC_DEPTH:String(i),PI_PTC_TASK_ID:a},promptFile:y.filePath};t.sessionDir!==void 0&&(x.sessionDir=t.sessionDir,x.sessionId=a,x.sessionName=`bgdispatch:`+a),_=d.spawn([`pi`,...b],x);let S=_,C={kind:`ptc-program`,callerId:f};await p.transition({kind:`spawn`,handle:{taskId:a,label:n,status:`running`},record:{label:n,agentName:g.name,depth:i,startedAt:Math.max(0,Math.floor(s())),finishedAt:void 0,durationMs:void 0,outputRef:void 0,outputBytes:void 0,outputPreview:void 0,stopReason:void 0,errorMessage:void 0,exitCode:void 0,spawnSource:C,parentTaskId:t.parentTaskId,...r===void 0?{}:{readOnlyTier:r}}},{clock:s,callerId:f,logger:c});let w=!1,T,ee=p.onTransition((e,t)=>{e.id===a&&t.status===`stopping`&&(w||T!==void 0||(T=_t(d,S,{isDone:()=>w,unref:!0})))});return(async()=>{let e=``,t,n=tn(),r;try{for await(let i of d.events(S)){nn(n,i);let a=Jt(i);a!==void 0&&(e=a,n.prompt=$t(a)),r=Yt(r,i);let o=an(i);o!==void 0&&(t=o)}w=!0,T?.();let i=(await d.exit(S)).code??-1,o=await d.stderr(S),l=i===0?void 0:bt(o),h=Buffer.byteLength(e,`utf8`),g=h<=2048?e:void 0,_;if(m!==void 0)try{await m.writeOutput(a,e),_=m.outputRef(a)}catch(e){let t=e instanceof Error?e.message:String(e);c.warn(`background dispatch output persistence for task `+a+` failed: `+t)}let v=u?rn(n):{reportChannel:`opted-out`};await p.transition({kind:`resolve-exit`,taskId:a,exitCode:i,reportChannel:v.reportChannel,usage:r,...v.report===void 0?{}:{report:{...v.report,usage:{input:r?.input??0,output:r?.output??0,cost:r?.cost??0,turns:r?.turns??0}}},outputRef:_,outputBytes:h,outputPreview:g,childError:t,...l===void 0?{}:{stderrDiagnostic:l}},{clock:s,callerId:f,logger:c})}catch(t){let n=t instanceof Error?t.message:String(t);c.warn(`background dispatch pump for task `+a+` failed after `+String(e.length)+` chars of buffered output: `+n)}finally{ee(),T?.(),qt(y),o.release(a)}})(),{taskId:a,label:n,status:`running`}}catch(e){let t=e instanceof Error?e.message:String(e);return _!==void 0&&_t(d,_,{unref:!0}),v!==void 0&&qt(v),o.release(a),c.warn(`background dispatch failed for agent `+g.name+`: `+t),z({text:``,status:`rejected`,started:_!==void 0,agentName:g.name,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`background dispatch failed: `+t},r)}}async function sn(e,t,n={}){if(!dt(e.readOnly))return ft(e.readOnly);let r=R(e.readOnly);if(e.background===!0)return await on(e,t,n,r);let i=t.depth+1;if(i>t.maxDispatchDepth)return z(ht(),r);let a=e.cwd??t.cwd,o=e.agentScope??`user`,s=Date.now();if(zt(e.agent))return z(Rt({cwd:a,agentScope:o}),r);let c=n.slots??ot;if(!c.tryAcquire())return z(gt(),r);let l=Vt(e,a,o);if(l.kind===`unknown`)return c.release(),z(Ht(l.name,o,a,Date.now()-s),r);let u=l.agent,d=Tt(u),f=mt(u.systemPrompt,i,t.maxDispatchDepth,{reportContract:d,readOnly:e.readOnly}),p,m=n.lifecycle??it,h;try{p=await Gt(u.name,f),h=Wt(e,u,p.filePath)}catch(e){throw c.release(),e}return await new Promise(e=>{let o=``,l,f=tn(),g=-1,_=``,v=!1,y,b,x=!1,S=(i,a,h=!0)=>{if(v)return;v=!0,c.release(),b!==void 0&&m.exit(b).catch(e=>{(n.logger??lt).warn(`exit() failed for a foreground child; the session live set may retain it: `+(e instanceof Error?e.message:String(e)))}),y?.(),t.signal&&t.signal.removeEventListener(`abort`,C),qt(p);let x=d?rn(f):{reportChannel:`opted-out`},S=z({text:o,status:i,started:h,agentName:u.name,durationMs:Date.now()-s,exitCode:g,reportChannel:x.reportChannel},r);x.report&&(S.report={...x.report,usage:{input:l?.input??0,output:l?.output??0,cost:l?.cost??0,turns:l?.turns??0}}),l&&(S.usage=l),_.length>0&&(S.stderr=_),a&&(S.errorMessage=a),e(S)},C=()=>{b&&!v&&(x=!0,y=_t(m,b,{isDone:()=>v}))};try{b=m.spawn([`pi`,...h],{cwd:a,env:{...process.env,PI_PTC_DEPTH:String(i)},promptFile:p.filePath})}catch(e){S(`rejected`,`failed to spawn pi: `+(e instanceof Error?e.message:String(e)),!1);return}t.signal&&(t.signal.aborted?C():t.signal.addEventListener(`abort`,C,{once:!0})),(async()=>{if(!b)return;let e=b;try{for await(let t of m.events(e))if(nn(f,t),t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(l=Yt(l,t),Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(o=t.text,f.prompt=$t(t.text))}let t=await it.exit(e);g=t.code??-1,_=await it.stderr(e);let n=_.match(/^\[spawn-error\] (.+)$/m);if(n&&t.code===null&&t.signal===null){S(`rejected`,`failed to spawn pi: `+n[1],!1);return}let{status:r,errorMessage:i}=xt({exitCode:g,finalText:o,aborted:x,stderr:_});S(r,i)}catch(e){let t=e instanceof Error?e.message:String(e);S(`rejected`,`dispatch internal error: `+t)}})()})}const B=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],V=`pi.dispatch`,cn=[`bash`];function ln(e){return cn.includes(e)}function un(e){if(e===void 0)return[];let t=new Set(e);for(let e of t)if(!ln(e))throw TypeError(`unknown PTC opt-in binding "${e}"; opt-in bindings: ${cn.join(`, `)}`);return B.filter(e=>t.has(e))}const dn=B.filter(e=>!ln(e)),fn={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},pn=x.Object({agent:x.Optional(x.String({minLength:1,description:`Optional. Name a registered agent definition to narrow the child, or omit it entirely for a fresh generalist pi with pi's own prompt and its full toolset. A name with no definition behind it is refused; an empty string is refused.`})),task:x.String({minLength:1}),cwd:x.Optional(x.String()),agentScope:x.Optional(x.Union([x.Literal(`user`),x.Literal(`project`),x.Literal(`both`)],{description:`Which agent directories to search: "user" (~/.pi/agent/agents, the default), "project" (<cwd>/.pi/agents), or "both". Defaults to "user", which cannot see project agents.`})),model:x.Optional(x.String()),thinkingLevel:x.Optional(x.String()),background:x.Optional(x.Boolean()),label:x.Optional(x.String()),readOnly:x.Optional(x.Union([x.Literal(`strict`),x.Literal(`lenient`)],{description:`Ask for a read-only child. "strict": its tools are narrowed to the read set, so it cannot write anything. "lenient": its tools are left exactly as they would have been and it is only told to work without modifying anything. Omit for today’s behaviour.`}))}),mn={name:V,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters:pn};function hn(e){return R(e?.readOnly)}function gn(e,t){let n=t.trim();return n.length===0?`${e} reported a failure with no message`:`${e} failed: ${n.length<=2e3?n:`…${n.slice(-2e3)}`}`}function _n(e){let t=new Set(un(e.optIns)),n=e.names??B.filter(e=>dn.includes(e)||t.has(e)),r=e.includeDispatch??e.names===void 0,i=/* @__PURE__ */ new Map;for(let t of n){let n=fn[t];if(!n)throw TypeError(`unknown PTC binding "${t}"; known bindings: ${B.join(`, `)}`);let r=n(e.cwd);i.set(t,{name:t,execute:async(e,t)=>{let n=`ptc:${t.callId}`,i={type:`toolCall`,id:n,name:r.name,arguments:e},a=S(r,i),o;try{o=await r.execute(n,a,t.signal,void 0)}catch(e){throw Error(gn(r.name,e instanceof Error?e.message:String(e)))}if(o.isError===!0)throw Error(gn(r.name,(o.content??[]).filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text??``).join(`
15
+ `)));return{content:o.content,details:o.details===void 0?null:o.details}}})}return r&&i.set(V,{name:V,execute:async(t,n)=>{let r={type:`toolCall`,id:`ptc:${n.callId}`,name:V,arguments:t},i;try{i=S(mn,r)}catch(n){let r=typeof t==`object`&&t&&!Array.isArray(t)?t:void 0,i=r?.agent,a=r?.agentScope;return zt(i)?z(Rt({cwd:e.cwd,agentScope:a===`user`||a===`project`||a===`both`?a:`user`}),hn(r)):z({text:``,status:`rejected`,started:!1,agentName:typeof i==`string`?i:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:n instanceof Error?n.message:String(n)},hn(r))}return sn(i,{signal:n.signal,callId:n.callId,cwd:e.cwd,depth:n.depth,maxDispatchDepth:n.maxDispatchDepth,...n.callerId===void 0?{}:{callerId:n.callerId},...n.sessionDir===void 0?{}:{sessionDir:n.sessionDir},...n.parentTaskId===void 0?{}:{parentTaskId:n.parentTaskId}},n.dispatchDeps)}}),i}function vn(){let e=/* @__PURE__ */ new Map;return{recordStart(t,n,r){if(e.has(t))throw Error(`duplicate sub-call callId ${t}`);e.set(t,{callId:t,name:n,args:r,status:`running`,startMs:Date.now()})},recordEnd(t,n,r){let i=e.get(t);if(i===void 0)throw Error(`recordEnd on unknown callId ${t}`);return i.status=n,i.endMs=Date.now(),i.durationMs=i.endMs-i.startMs,n===`rejected`&&(i.durationMs=0),r?.errorMessage!==void 0&&(i.errorMessage=r.errorMessage),r?.resultSummary!==void 0&&(i.resultSummary=r.resultSummary),i},snapshot(){return[...e.values()].map(e=>({...e}))}}}function yn(e){return{name:`ptc-${e.surface}`,env:e.env,workerData:e.runId===void 0?{env:e.env}:{runId:e.runId,env:e.env},resourceLimits:{maxOldGenerationSizeMb:e.limits.maxOldGenerationSizeMb,maxYoungGenerationSizeMb:e.limits.maxYoungGenerationSizeMb}}}const bn={acquireLatency:de.channel(`ptc:pool:acquire-latency`),resetTime:de.channel(`ptc:worker:reset-time`),imageBytes:de.channel(`ptc:image:hoist-bytes`)};function xn(e,t){e.publish(t)}var Sn=class{#e;#t;#n;#r;#i;#a=[];#o=/* @__PURE__ */ new Set;#s=[];#c=/* @__PURE__ */ new WeakMap;#l=0;#u=0;#d=!1;constructor(e){if(typeof e.buildWorkerUrl!=`function`)throw TypeError(`WorkerPool: buildWorkerUrl must be a function`);if(e.size!==void 0&&(typeof e.size!=`number`||!Number.isFinite(e.size)||e.size<=0))throw TypeError(`WorkerPool: size must be a positive finite number, received ${String(e.size)}`);if(e.acquireTimeoutMs!==void 0&&(typeof e.acquireTimeoutMs!=`number`||!Number.isFinite(e.acquireTimeoutMs)||e.acquireTimeoutMs<=0))throw TypeError(`WorkerPool: acquireTimeoutMs must be a positive finite number, received ${String(e.acquireTimeoutMs)}`);if(e.drainGraceMs!==void 0&&(typeof e.drainGraceMs!=`number`||!Number.isFinite(e.drainGraceMs)||e.drainGraceMs<=0))throw TypeError(`WorkerPool: drainGraceMs must be a positive finite number, received ${String(e.drainGraceMs)}`);this.#e=e.buildWorkerUrl,this.#t=e.size??4,this.#n=e.acquireTimeoutMs??3e4,this.#r=e.drainGraceMs??5e3,this.#i=e.workerOptions}async acquire(){if(this.#d)throw Error(`pool has been drained and can no longer serve workers`);this.#l+=1;let e=Date.now(),t=this.#a.shift();for(;t!==void 0&&!this.#p(t);)t=this.#a.shift();if(t!==void 0)return this.#o.add(t),t.ref(),xn(bn.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-e}),t;if(this.#o.size<this.#t){let t=this.#f();return this.#o.add(t),xn(bn.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-e}),t}return this.#u+=1,await new Promise((t,n)=>{let r=setTimeout(()=>{let e=this.#s.findIndex(e=>e.timer===r);e>=0&&this.#s.splice(e,1),n(/* @__PURE__ */ Error(`pool acquire timed out after ${this.#n} ms`))},this.#n);this.#s.push({resolve:t,reject:n,timer:r,startedAt:e})})}release(e){if(!this.#o.delete(e)||!this.#p(e))return;this.#c.set(e,Date.now());let t=this.#s.shift();if(t){clearTimeout(t.timer),this.#o.add(e),xn(bn.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-t.startedAt}),t.resolve(e);return}this.#a.push(e),e.unref()}lastSettledAt(e){return this.#c.get(e)}async drain(){for(;this.#s.length>0;){let e=this.#s.shift();if(!e)break;clearTimeout(e.timer),e.reject(/* @__PURE__ */ Error(`pool drained before acquire could be satisfied`))}let e=Date.now()+this.#r;for(;this.#o.size>0&&Date.now()<e;)await new Promise(e=>setTimeout(e,5));let t=[...this.#a,...this.#o];this.#a.length=0,this.#o.clear(),await Promise.all(t.map(e=>e.terminate().catch(()=>void 0))),this.#d=!0}stats(){return{resident:this.#o.size+this.#a.length,inFlight:this.#o.size,waiters:this.#s.length,totalAcquires:this.#l,poolExhaustions:this.#u}}#f(){let e=new ue(this.#e(),this.#i);return e.once(`exit`,()=>{let t=this.#a.indexOf(e);if(t>=0){this.#a.splice(t,1);return}this.#o.delete(e)}),e}#p(e){return e.threadId!==-1}};function Cn(e){xn(bn.imageBytes,{byteLength:e})}function wn(e){xn(bn.resetTime,{durationMs:e})}function Tn(){let e=A(fe(import.meta.url)),t=[M(e,`worker.js`),M(e,`worker-entry.ts`)];for(let e of t)if(w(e))return pe(e);throw Error(`worker entry not found; tried: ${t.join(`, `)}`)}function En(e){if(typeof e!=`object`||!e)return;let t=e;if(t.status!==`rejected`)return;let n=typeof t.errorMessage==`string`?t.errorMessage:t.started===!1?`dispatch refused`:`dispatch failed`;return{kind:t.started===!1?`refused`:`failed`,message:n}}function H(e){return e instanceof Error?e.message:String(e)}function Dn(e){if(typeof e!=`object`||!e)return;let t=e.content;if(Array.isArray(t)&&t.length>0){let e=t[0];if(typeof e==`object`&&e){let t=e.text;if(typeof t==`string`&&t.length>0){let e=t.indexOf(`
16
+ `);return e===-1?t:t.slice(0,e)}}}}function On(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function kn(e,t){let n=/* @__PURE__ */ new WeakSet,r=e=>{if(e!=null){if(e instanceof ArrayBuffer){t(e);return}if(ArrayBuffer.isView(e)){t(e);return}if(typeof e==`object`&&!n.has(e)){if(n.add(e),Array.isArray(e)){for(let t of e)r(t);return}for(let t of Object.keys(e))r(e[t])}}};r(e)}function An(e){try{let t=Buffer.byteLength(JSON.stringify(e,(e,t)=>On(t)?null:t)??``,`utf8`),n=0;return kn(e,e=>{n+=e.byteLength}),t+n}catch{return 1/0}}async function jn(e){let i=Be(e.config),s=ze(),c=e.runId??ce(),l=Ve(e.timeoutMs,i),u=[],d=[],f=[];if(e.signal?.aborted)return{logs:u,narrations:d,phases:f,error:{kind:n.abort,message:`run cancelled before start`}};let p;try{p=e.pool?await e.pool.acquire():new ue(Tn(),yn({surface:e.surface,env:s,limits:i,runId:c}))}catch(e){return{logs:u,narrations:d,phases:f,error:{kind:n.workerExit,message:`pool acquire failed: ${H(e)}`}}}return await new Promise(s=>{let m=new le,h=m.port1,g=m.port2,_=new AbortController,v=!1,y=vn(),b=()=>{v||e.onSubCallChange?.(()=>y.snapshot())},x={recordStart(e,t,n){y.recordStart(e,t,n),b()},recordEnd(e,t,n){let r=y.recordEnd(e,t,n);return b(),r},snapshot:()=>y.snapshot()},S,C=!1,w=0,T=0,ee=new at(i.dispatchConcurrency),te=0,E=[],D=e.depth??0,ne,O,k=[],re=e=>{let t=[],n=e?.content;if(!Array.isArray(n))return t;for(let e of n){if(typeof e!=`object`||!e)continue;let n=e;if(n.type!==`image`)continue;let r;typeof n.data==`string`&&n.data.length>0?r=n.data:n.bytes instanceof ArrayBuffer&&n.bytes.byteLength>0&&(r=Buffer.from(n.bytes).toString(`base64`)),r!==void 0&&t.push({data:r,mimeType:typeof n.mimeType==`string`?n.mimeType:`application/octet-stream`})}return t},A=e=>e===`timeout`?`run timed out after ${l} ms`:`run cancelled`,j=e=>e===`timeout`?n.timeout:n.abort,ie=t=>{if(v)return;v=!0,ne&&clearTimeout(ne),O&&clearTimeout(O),e.signal?.removeEventListener(`abort`,F),_.abort(),h.close(),e.pool?e.pool.release(p):p.terminate();let n=x.snapshot();s(n.length>0?{...t,subCalls:n}:t)},M=(e,t,n)=>{ie({logs:u,narrations:d,phases:f,error:n===void 0?{kind:e,message:t}:{kind:e,message:t,stack:n}})},ae=e=>{if(!v){if(!r(e)){M(n.protocol,`internal error: malformed host frame`);return}h.postMessage(e)}},oe=()=>{let t={kind:o.init,runId:c,surface:e.surface,code:e.code,bindings:[...e.bindings.keys()],bindingCandidates:[...B],maxItemsPerCall:i.maxItemsPerCall,maxPendingCalls:i.maxPendingCalls,...e.args===void 0?{}:{args:e.args}};if(!r(t)){M(n.protocol,`internal error: malformed init frame`);return}let a=An(t);if(a>i.maxMessageBytes){M(n.protocol,`init frame of ${a} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}ae(t)},se=(e,t)=>(T+=e,T<=i.maxOutputBytes||(M(n.outputLimit,`${t} exceeded the output budget: logs + result reached ${T} bytes (maxOutputBytes=${i.maxOutputBytes}); ${u.length} log line(s) retained`),!1)),ce=async()=>{if(te<i.maxParallelSubCalls){te+=1;return}await new Promise(e=>{E.push(e)})},N=()=>{let e=E.shift();if(e){e();return}--te},ue=e=>{if(x.recordStart(e.callId,e.tool,e.args),w+=1,w>i.maxPendingCalls){x.recordEnd(e.callId,`error`,{errorMessage:`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`}),M(n.protocol,`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`);return}de(e).finally(()=>{--w})},de=async t=>{let r=e.bindings.get(t.tool);if(!r){x.recordEnd(t.callId,`error`,{errorMessage:`no binding named "${t.tool}" in this run; available bindings: `+([...e.bindings.keys()].join(`, `)||`(none)`)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:`no binding named "${t.tool}" in this run; available bindings: `+([...e.bindings.keys()].join(`, `)||`(none)`)});return}let a=t.tool===V;if(!a&&(await ce(),v)){x.recordEnd(t.callId,`cancelled`,{errorMessage:`run settled before binding started`}),N();return}try{let s=await r.execute(t.args,{signal:_.signal,callId:t.callId,depth:D,maxDispatchDepth:i.maxDispatchDepth,callerId:c,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...e.sessionDir===void 0?{}:{sessionDir:e.sessionDir},dispatchDeps:{...e.dispatchDeps,slots:e.dispatchDeps?.slots??ee}}),l=re(s),u={kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:s},d=An(u);if(d>i.maxMessageBytes){x.recordEnd(t.callId,`error`,{errorMessage:`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`}),M(n.protocol,`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}if(fe(u))for(let e of l)k.push(e),Cn(Buffer.byteLength(e.data,`base64`));if(_.signal.aborted)x.recordEnd(t.callId,`cancelled`,{errorMessage:`binding aborted by run cancellation`});else{let e=a?En(s):void 0;e===void 0?x.recordEnd(t.callId,`ok`,{resultSummary:Dn(s)}):x.recordEnd(t.callId,e.kind===`refused`?`rejected`:`error`,{errorMessage:e.message})}}catch(e){_.signal.aborted?x.recordEnd(t.callId,`cancelled`,{errorMessage:H(e)}):x.recordEnd(t.callId,`error`,{errorMessage:H(e)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:H(e)})}finally{a||N()}},fe=e=>{if(v)return!1;try{return h.postMessage(e),!0}catch(t){try{h.postMessage({kind:o.callResult,callId:e.callId,tool:e.tool,ok:!1,message:`binding result could not be transferred: ${H(t)}`})}catch{M(n.protocol,`binding result is not transferable`)}return!1}},pe=e=>S?{logs:u,narrations:d,phases:f,error:{kind:j(S),message:A(S)}}:e,P=r=>{if(v)return;if(!a(r)){M(n.protocol,`malformed worker frame`);return}let o=r.kind===t.ready?0:An(r);if(!Number.isFinite(o)){M(n.protocol,`worker frame could not be serialized for accounting`);return}if(o>i.maxMessageBytes){M(n.protocol,`control frame of ${o} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}switch(r.kind){case t.ready:if(e.pool){let t=e.pool.lastSettledAt(p);t!==void 0&&wn(Date.now()-t)}if(!C&&(C=!0,S)){me(S);return}oe();return;case t.call:ue(r);return;case t.log:se(o,`console output`)&&u.push(r.text);return;case t.narration:se(o,`workflow narration`)&&d.push(r.message);return;case t.phase:se(o,`workflow phase`)&&f.push(r.title);return;case t.result:{if(!se(o,`completion value`))return;let e={logs:u,narrations:d,phases:f,...k.length>0?{images:k}:{}};ie(pe(r.value===void 0?e:{...e,value:r.value}));return}case t.error:ie(pe({logs:u,narrations:d,phases:f,error:r.error}));return;default:M(n.protocol,`unknown worker frame`)}};function F(){he(`abort`)}let me=e=>{O&&clearTimeout(O),O=setTimeout(()=>{M(j(e),A(e))},i.graceMs)};function he(e){if(!v){if(S){M(j(S),A(S));return}S=e,_.abort(),ae({kind:o.cancel,reason:e}),me(e)}}p.on(`error`,e=>{M(n.workerExit,`worker failed: ${H(e)}`)}),p.on(`exit`,e=>{M(n.workerExit,`worker exited with code ${e} before the run completed`)}),h.on(`message`,P),h.on(`messageerror`,()=>{M(n.protocol,`worker sent a frame that could not be deserialized`)}),e.signal?.addEventListener(`abort`,F,{once:!0}),ne=setTimeout(()=>{he(`timeout`)},l);let ge={kind:o.connect,port:g};r(ge)?p.postMessage(ge,[g]):M(n.protocol,`internal error: malformed connect frame`)})}const Mn=["Return value: every `tools.<name>(args)` call above resolves to `{ content, details }`.","`content` is an ARRAY of content blocks, never a string, so a text result is","`result.content[0].text`; `details` is that tool's own detail object or `null`, never","`undefined`. No binding result has a `files`, `output`, `matches` or `entries` field:","`bash`, `grep`, `find` and `ls` hand back ONE text block of newline-separated rows that","you split yourself, and the empty answer is a sentinel string (`No matches found`,","`No files found matching pattern`, `(empty directory)`) rather than an empty list.","A failing call REJECTS with `ToolCallError` instead of resolving, so wrap the call in","`try`/`catch` (or `Promise.allSettled`): a path that is not there, a builtin this run did not",`bind. A name that is not a builtin is simply not a function.`],Nn=/* @__PURE__ */ new Map([[`bash`,"`bash` rejects on a non-zero exit rather than resolving with its output."],[`write`,"`write` always reports `details: null`."],[`edit`,"`edit` always reports a `details` object carrying `diff` and `patch`."],[V,'`tools["pi.dispatch"]` is the exception: it resolves to `{ text, status, ... }` with no `content` and never throws, so read `status`.']]),Pn=[Mn.join(`
17
+ `),`Exceptions: `+[...Nn.values()].join(` `)].join(`
18
+ `),Fn=`pi-ptc-output-`;function In(e,t=Fn){let n=j(O(),`${t}${ce()}.txt`);return E(n,e,`utf8`),n}function Ln(e,t){let n=e.totalLines-e.outputLines+1,r=e.totalLines;return e.lastLinePartial?`[Showing last ${_(e.outputBytes)} of line ${r}. Full output: ${t}]`:e.truncatedBy===`lines`?`[Showing lines ${n}-${r} of ${e.totalLines}. Full output: ${t}]`:`[Showing lines ${n}-${r} of ${e.totalLines} (${_(s)} limit). Full output: ${t}]`}function Rn(e,t=Fn,n={}){let r=b(e,{maxLines:c,maxBytes:s});if(!r.truncated)return{text:e,truncated:!1};let i=In(n.fullText??e,t);return{text:`${r.content}\n\n${Ln(r,i)}`,truncated:!0,fullPath:i}}const zn=200,Bn=new RegExp([`(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))`,`[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]`].join(`|`),`g`);function Vn(e){return!e.includes(`\x1B`)&&!e.includes(`›`)?e:e.replace(Bn,``)}function U(e){let t=Vn(e).replace(/\r/g,``);if(t.length===0)return t;let n=``;for(let e of t){let t=e.codePointAt(0);if(t!==void 0){if(t===10||t===9){n+=e;continue}t<=31||t>=65529&&t<=65531||(n+=e)}}return n}const Hn=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function Un(e){return Hn.test(e)?e:JSON.stringify(e)}function Wn(e){if(e===null)return`null`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(typeof e==`string`){let t=U(e);return t.includes(`
19
+ `)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=Wn(n);if(e===void 0)return;t.push(e)}return`[${t.join(`, `)}]`}let t=Object.keys(e);if(t.length===0)return`{}`;let n=[];for(let r of t){let t=Wn(e[r]??null);if(t===void 0)return;n.push(`${Un(r)}: ${t}`)}return`{${n.join(`, `)}}`}function Gn(e){let t=Wn(e);if(t!==void 0)return t.length<=100?t:void 0}function Kn(e){return e===null?`null`:typeof e==`string`?U(e):String(e)}function qn(e,t){if(typeof e!=`object`||!e)return[`${t}${Kn(e)}`];if(Array.isArray(e)){if(e.length===0)return[`${t}[]`];let n=[`${t}[`];for(let r of e){let e=Gn(r);if(e!==void 0){n.push(`${t} ${e}`);continue}n.push(...Jn(r,t+` `))}return n.push(`${t}]`),n}let n=Object.keys(e);if(n.length===0)return[`${t}{}`];let r=[`${t}{`],i=t+` `;for(let t of n){let n=e[t]??null,a=Gn(n);if(a!==void 0){r.push(`${i}${Un(t)}: ${a}`);continue}if(typeof n==`string`){r.push(`${i}${Un(t)}:`);for(let e of U(n).split(`
20
+ `))r.push(e.length===0?``:`${i} ${e}`);continue}let o=qn(n,i);r.push(`${i}${Un(t)}: ${(o[0]??``).trimStart()}`.trimEnd(),...o.slice(1))}return r.push(`${t}}`),r}function Jn(e,t){return typeof e==`string`?U(e).split(`
21
+ `):typeof e!=`object`||!e?[String(e)]:qn(e,t)}function Yn(e){return e.split(`
22
22
  `).map(e=>e.length>200?`${e.slice(0,199)}…`:e).join(`
23
- `)}function Wn(e){if(typeof e==`string`)return Un(U(e));if(typeof e!=`object`||!e)return String(e);let t=zn(e);return Un((t===void 0?Hn(e,``):[t]).join(`
24
- `))}function Gn(e=process.env){let t=e.PI_PTC_DEPTH;return t===void 0||!/^\d+$/.test(t)?0:Number.parseInt(t,10)}function Kn(e=process.env){let t=e.PI_PTC_TASK_ID;if(t!==void 0&&/^[0-9A-HJKMNP-TV-Z]{26}$/.test(t))return t}function W(e,t){let n=e===void 0?void 0:new Set(e),r=new Set(sn(t));return R.filter(e=>(n===void 0||n.has(e))&&(cn.includes(e)||r.has(e)))}const qn=["Image-bearing tool results inside a program (a `tools.read` on a PNG, say) are attached to you after the run — never return image data as the completion value.",`Use ptc_run_code when a task needs several tool calls whose intermediate output you do not need to see — gather it inside the program and return only the final value.`,`Use ptc_workflow instead of ptc_run_code when the work has named phases and the user benefits from seeing progress narration.`],Jn={run_code:`ptc_run_code`,workflow:`ptc_workflow`};function Yn(e){let t=e?.cwd;return typeof t==`string`&&t.length>0?t:process.cwd()}function Xn(e){let{surface:t,startedAt:n,onUpdate:r}=e;if(r===void 0)return{update:()=>{},cancel:()=>{}};let i=0,a,o,s=()=>{if(o===void 0)return;let e=o;o=void 0,i=Date.now(),r({content:[],details:{surface:t,logs:[],narrations:[],phases:[],warnings:[],durationMs:Date.now()-n,imageCount:0,subCalls:e()}})};return{update(e){o=e;let t=100-(Date.now()-i);if(t<=0){a!==void 0&&(clearTimeout(a),a=void 0),s();return}a??=setTimeout(()=>{a=void 0,s()},t)},cancel(){a!==void 0&&(clearTimeout(a),a=void 0),o=void 0}}}function Zn(e){return[...e.phases.map(e=>`[phase] ${U(e)}`),...e.narrations.map(e=>`[log] ${U(e)}`),...e.logs.map(e=>U(e))]}function Qn(e){let t=e.error;if(t===void 0)return/* @__PURE__ */ Error(`internal error: a successful PTC run was rendered as a failure`);let n=Zn(e),r=n.length===0?``:`\nCaptured output:\n${n.join(`
25
- `)}`,i=Error(U(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function $n(e){let{outcome:t,surface:n}=e,r=[...e.warnings??[]],i=t.images??[],a=[];t.phases.length>0&&a.push(`Phases: ${t.phases.map(e=>U(e)).join(` → `)}`),t.narrations.length>0&&a.push(t.narrations.map(e=>U(e)).join(`
23
+ `)}function Xn(e){if(typeof e==`string`)return Yn(U(e));if(typeof e!=`object`||!e)return String(e);let t=Gn(e);return Yn((t===void 0?Jn(e,``):[t]).join(`
24
+ `))}function Zn(e=process.env){let t=e.PI_PTC_DEPTH;return t===void 0||!/^\d+$/.test(t)?0:Number.parseInt(t,10)}function Qn(e=process.env){let t=e.PI_PTC_TASK_ID;if(t!==void 0&&/^[0-9A-HJKMNP-TV-Z]{26}$/.test(t))return t}function W(e,t){let n=e===void 0?void 0:new Set(e),r=new Set(un(t));return B.filter(e=>(n===void 0||n.has(e))&&(dn.includes(e)||r.has(e)))}const $n=["Image-bearing tool results inside a program (a `tools.read` on a PNG, say) are attached to you after the run — never return image data as the completion value.",`Use ptc_run_code when a task needs several tool calls whose intermediate output you do not need to see — gather it inside the program and return only the final value.`,`Use ptc_workflow instead of ptc_run_code when the work has named phases and the user benefits from seeing progress narration.`],er={run_code:`ptc_run_code`,workflow:`ptc_workflow`};function tr(e){let t=e?.cwd;return typeof t==`string`&&t.length>0?t:process.cwd()}function nr(e){let{surface:t,startedAt:n,onUpdate:r}=e;if(r===void 0)return{update:()=>{},cancel:()=>{}};let i=0,a,o,s=()=>{if(o===void 0)return;let e=o;o=void 0,i=Date.now(),r({content:[],details:{surface:t,logs:[],narrations:[],phases:[],warnings:[],durationMs:Date.now()-n,imageCount:0,subCalls:e()}})};return{update(e){o=e;let t=100-(Date.now()-i);if(t<=0){a!==void 0&&(clearTimeout(a),a=void 0),s();return}a??=setTimeout(()=>{a=void 0,s()},t)},cancel(){a!==void 0&&(clearTimeout(a),a=void 0),o=void 0}}}function rr(e){return[...e.phases.map(e=>`[phase] ${U(e)}`),...e.narrations.map(e=>`[log] ${U(e)}`),...e.logs.map(e=>U(e))]}function ir(e){let t=e.error;if(t===void 0)return/* @__PURE__ */ Error(`internal error: a successful PTC run was rendered as a failure`);let n=rr(e),r=n.length===0?``:`\nCaptured output:\n${n.join(`
25
+ `)}`,i=Error(U(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function ar(e){let{outcome:t,surface:n}=e,r=[...e.warnings??[]],i=t.images??[],a=[];t.phases.length>0&&a.push(`Phases: ${t.phases.map(e=>U(e)).join(` → `)}`),t.narrations.length>0&&a.push(t.narrations.map(e=>U(e)).join(`
26
26
  `)),t.logs.length>0&&a.push(t.logs.map(e=>U(e)).join(`
27
- `)),t.value!==void 0&&a.push(Wn(t.value));for(let e of r)a.push(`Warning: ${U(e)}`);let o=Mn(a.length>0?a.join(`
28
- `):`(${Jn[n]} completed with no output)`),s=o.text,c=o.truncated?o.fullPath:void 0;return{content:[{type:`text`,text:s},...i.map(e=>({type:`image`,data:e.data,mimeType:e.mimeType}))],details:{surface:n,logs:[...t.logs],narrations:[...t.narrations],phases:[...t.phases],warnings:r,...t.value===void 0?{}:{result:t.value},durationMs:e.durationMs,imageCount:i.length,...c===void 0?{}:{fullOutputPath:c},...t.subCalls===void 0?{}:{subCalls:t.subCalls}}}}const er=/^(.*?)(└─ |├─ | )(?:PTC(?: workflow)?)([ ].*)$/;function tr(e){return e.replace(/\x1b\[[0-9;]*m|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[\?[0-9;]*[a-zA-Z]/g,``)}function nr(e,t){if(e.charCodeAt(t)!==27)return t;let n=e.charCodeAt(t+1);if(n===93){let n=t+2;for(;n<e.length;){let t=e.charCodeAt(n);if(t===7)return n+1;if(t===27&&e.charCodeAt(n+1)===92)return n+2;n+=1}return n}if(n===91){let n=t+2;for(;n<e.length;){let t=e.charCodeAt(n);if(t>=64&&t<=126)return n+1;n+=1}return n}return t+2}function rr(e,t){let n=0,r=0;for(;r<t&&n<e.length;)e.charCodeAt(n)===27?n=nr(e,n):(n+=1,r+=1);return n}function ir(e,t){let n=t.intervalMs??150,{state:r}=t;t.isPartial?(r.startedAt??=Date.now(),r.interval??=setInterval(()=>t.requestInvalidate(),n)):(r.interval!==void 0&&(clearInterval(r.interval),r.interval=void 0),r.startedAt=void 0);let i=e.render.bind(e),a=e;return a.render=e=>{let a=i(e);return r.startedAt===void 0?a:ar(a,Math.floor((Date.now()-r.startedAt)/n),t.theme)},a.dispose=()=>{r.interval!==void 0&&(clearInterval(r.interval),r.interval=void 0)},e}function ar(e,t,n){return e.map(e=>{let r=tr(e),i=er.exec(r);if(i===null)return e;let a=(i[3]??``).slice(1);if(a.length===0)return e;let o=t%(a.length+1),s=i[0].length-a.length,c=rr(e,s),l=rr(e,s+a.length),u=o>=a.length?n.fg(`dim`,a):`${o>0?n.fg(`dim`,a.slice(0,o)):``}${n.fg(`accent`,a.slice(o,o+1))}${n.fg(`dim`,a.slice(o+1))}`;return`${e.slice(0,c)}${u}${e.slice(l)}`})}const or={run_code:`PTC`,workflow:`PTC workflow`},sr=`├─ `,cr=`└─ `,lr=`│ `;var ur=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>dr(e,t))}};function dr(e,t){let{left:n,right:r}=e;if(r===void 0)return P(n,t,`…`);let i=F(r);if(i>=t)return P(r,t,`…`);let a=P(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-F(a));return a+` `.repeat(o)+r}function G(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function fr(e){return G((U(e).split(`
29
- `).find(e=>e.trim().length>0)??``).trim(),120)}function pr(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2).replace(/\.?0+$/,``)}s`}function K(e,t){return`${e} ${t}${e===1?``:`s`}`}function mr(e){for(let t of e.split(`
30
- `)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return G(e.replace(/\s*\/\/.*$/,``),120)}}function hr(e){if(e===void 0)return;if(typeof e==`string`){let t=U(e).split(`
31
- `),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:G(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=Wn(e);if(!t.includes(`
32
- `)&&t.length<=60)return t;if(Array.isArray(e))return`Array(${e.length})`;let n=Object.keys(e);return n.length===0?`{}`:`{${n.slice(0,4).join(`, `)}${n.length>4?`, +${n.length-4}`:``}}`}function gr(e,t){if(e===void 0)return;let n=[],r=e.logs.length+e.narrations.length;if(r>0&&n.push(t.fg(`dim`,K(r,`output line`))),e.imageCount>0&&n.push(t.fg(`toolOutput`,K(e.imageCount,`image`))),e.surface===`workflow`&&e.phases.length>0&&n.push(t.fg(`dim`,K(e.phases.length,`phase`))),e.warnings.length>0&&n.push(t.fg(`warning`,K(e.warnings.length,`warning`))),e.fullOutputPath!==void 0&&n.push(t.fg(`warning`,`truncated`)),e.durationMs>0&&n.push(t.fg(`dim`,pr(e.durationMs))),n.length!==0)return`${t.fg(`dim`,`•`)} ${n.join(t.fg(`dim`,` · `))}`}function _r(e){if(e!==void 0)return{surface:e.surface??`run_code`,logs:e.logs??[],narrations:e.narrations??[],phases:e.phases??[],warnings:e.warnings??[],durationMs:e.durationMs??0,imageCount:e.imageCount??0,...e.result===void 0?{}:{result:e.result},...e.fullOutputPath===void 0?{}:{fullOutputPath:e.fullOutputPath},...e.subCalls===void 0?{}:{subCalls:e.subCalls}}}function vr(e,t,n){let r=` `+(t?cr:sr),i=` `+(t?` `:lr),a=` `.repeat(8),o=[],s=e.lines[0]??``;o.push({left:`${r}${e.label.padEnd(8)}${n.fg(`dim`,s)}`});for(let t=1;t<e.lines.length;t++)o.push({left:`${i}${a}${n.fg(`dim`,e.lines[t]??``)}`});return e.more!==void 0&&e.more>0&&o.push({left:`${i}${a}…+${e.more} more lines`}),o}function yr(e){return typeof e!=`object`||!e?!1:Array.isArray(e)?e.length>0:Object.keys(e).length>0}const br=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function xr(e){return br.test(e)?e:JSON.stringify(e)}function Sr(e,t){if(e===null)return`null`;if(typeof e==`boolean`||typeof e==`number`)return String(e);if(typeof e==`string`){let n=U(e);if(n.length===0)return`""`;if(n.includes(`
33
- `)){let e=G(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(G(n,Math.max(2,t-5)))+`…`}return`?`}function Cr(e){return typeof e!=`object`||!e}function wr(e,t){if(t<8)return;if(Array.isArray(e)){if(e.length===0)return`[]`;if(e.length>5||!e.every(Cr))return;let n=`[`+e.map(e=>Sr(e,Math.max(2,Math.floor(t/4)))).join(`, `)+`]`;return n.length<=t?n:void 0}if(typeof e!=`object`||!e)return;let n=Object.keys(e);if(n.length===0)return`{}`;if(n.length>5||!Object.values(e).every(Cr))return;let r=`{`+n.map(n=>{let r=e[n]??null;return xr(n)+`: `+Sr(r,Math.max(2,Math.floor(t/4)))}).join(`, `)+`}`;return r.length<=t?r:void 0}function Tr(e,t,n,r,i,a,o,s,c){let l=n+(r?`└─ `:`├─ `),u=n+(r?` `:`│ `);if(s>=i){c.push(q(l+t+`…`,o));return}if(Array.isArray(e)&&e.length===0){c.push(q(l+t+`[]`,o));return}if(!Array.isArray(e)&&typeof e==`object`&&e&&Object.keys(e).length===0){c.push(q(l+t+`{}`,o));return}if(typeof e!=`object`||!e){let n=Math.max(0,o-F(l)-t.length);c.push(q(l+t+Sr(e,n),o));return}let d=wr(e,Math.max(0,o-F(l)-t.length));if(d!==void 0){c.push(q(l+t+d,o));return}let f=Array.isArray(e),p=f?e.length:Object.keys(e).length,m;m=f?`Array(`+p+`)`:p>a?`{`+a+` of `+p+`}`:`{`+p+` keys}`,c.push(q(l+t+m,o));let h=Math.min(a,p);if(f)for(let t=0;t<h;t+=1){let n=t===h-1&&p<=h;Tr(e[t]??null,`[`+t+`] `,u,n,i,a,o,s+1,c)}else{let t=Object.keys(e);for(let n=0;n<h;n+=1){let r=n===h-1&&p<=h,l=t[n];Tr(e[l]??null,xr(l)+`: `,u,r,i,a,o,s+1,c)}}if(p>h){let e=f?`items`:`keys`;c.push(q(u+`└─ …+`+(p-h)+` more `+e,o))}}function q(e,t){if(F(e)<=t)return e;let n=e.match(/^([\s│├└─]*)/),r=n&&n[1]?n[1]:``,i=F(r),a=Math.max(0,t-i-1),o=``,s=0;for(let t of e.slice(r.length)){let e=F(t);if(s+e>a)break;o+=t,s+=e}return r+o+`…`}function Er(e,t={}){let n=t.maxDepth??4,r=t.maxChildren??6,i=t.maxLineChars??120,a=t.moreAfter===!0;if(!yr(e))return typeof e==`object`&&e?[Array.isArray(e)?`[]`:`{}`]:[Sr(e,i)];let o=[];if(Array.isArray(e)){let t=e.length,s=Math.min(r,t);for(let c=0;c<s;c+=1){let l=!a&&c===s-1&&t<=s;Tr(e[c]??null,`[`+c+`] `,``,l,n,r,i,0,o)}return t>s&&o.push((a?`├─ `:`└─ `)+`…+`+(t-s)+` more items`),o}let s=Object.keys(e),c=s.length,l=Math.min(r,c);for(let t=0;t<l;t+=1){let u=!a&&t===l-1&&c<=l,d=s[t];Tr(e[d]??null,xr(d)+`: `,``,u,n,r,i,0,o)}return c>l&&o.push((a?`├─ `:`└─ `)+`…+`+(c-l)+` more keys`),o}const Dr=`child report`;function Or(e){return e===0?`[]`:`Array(${e})`}function kr(e){let t=U(e).split(`
34
- `).find(e=>e.trim().length>0)?.trim()??``;return t.length===0?`""`:G(t,200)}function Ar(e){let t=Number(e.cost.toFixed(4));return`in ${e.input} · out ${e.output} · cost ${t} · ${K(e.turns,`turn`)}`}function jr(e,t,n){let r=U(n).replace(/\n/g,` `).trim();return r.length<=150?`${e}${t}evidence: ${r}`:`${e}${t}evidence: ${r.slice(0,150)}… (truncated at 150 chars)`}function Mr(e,t){let n=[];return e.forEach((r,i)=>{let a=i===e.length-1&&t===0,o=`[${i}]`;n.push(`${a?`└─ `:`├─ `}${o} ${U(r.what).trim()}`.trimEnd()),n.push(jr(a?` `:`│ `,` `.repeat(o.length+2),r.evidence))}),t>0&&n.push(`└─ …+${t} more findings withheld (a report renders at most 20)`),n}function Nr(e,t){let n=e.map((n,r)=>`${r===e.length-1&&t===0?`└─ `:`├─ `}[${r}] `+`${U(n).trim()}`.trimEnd());return t>0&&n.push(`└─ …+${t} more files withheld (a report renders at most 20)`),n}function Pr(e){let t=e===`none`?`no child report was returned — the child did not comply with the contract, so its prose below is unbacked by a report`:e===`opted-out`?`this agent opts out of the report contract, so none was asked for — the prose below is the whole of what it produced, and nothing is missing`:`the ${e} channel was announced but no report reached the host; the child's prose below is everything it produced`;return`${Dr} (channel: ${e})\n${cr}${t}`}function Fr(e,t){if(e===void 0)return Pr(t);let n=e.findings.slice(0,20),r=e.findings.length-n.length,i=e.files_touched.slice(0,20),a=e.files_touched.length-i.length,o=[{label:`summary`,head:kr(e.summary),rows:[]},{label:`findings`,head:Or(e.findings.length),rows:Mr(n,r)},{label:`files`,head:Or(e.files_touched.length),rows:Nr(i,a)},{label:`usage`,head:Ar(e.usage),rows:[]}],s=[`${Dr} (channel: ${t})`];return o.forEach((e,t)=>{let n=t===o.length-1,r=e.label.length>=8?`${e.label} `:e.label.padEnd(8);s.push(q(`${n?cr:sr}${r}${e.head}`,200));let i=n?` `:lr;for(let t of e.rows)s.push(q(`${i}${t}`,200))}),s.join(`
35
- `)}function Ir(e,t,n=`run_code`,r={}){let i=(typeof e.description==`string`&&e.description.trim().length>0?e.description.trim():e.meta?.name)??``,a=mr(e.code??e.script??``),o=i.length>0?i:a??`(no description)`;return ir(new ur([{left:`└─ ${`${t.fg(`toolTitle`,t.bold(or[n]))} ${t.fg(`accent`,o)}`}`}]),{intervalMs:150,isPartial:r.isPartial??!1,theme:t,requestInvalidate:r.requestInvalidate??Lr,state:r.state??{}})}function Lr(){}function Rr(e){let t=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0);return fr(t?.text??``)||`failed`}function zr(e,t){if(e===`pi.dispatch`&&typeof t==`object`&&t){let e=t.agent;return typeof e==`string`&&e.trim().length>0?`→ ${e}`:e===void 0?`→ (generalist)`:`→ ${JSON.stringify(e)}`}if(typeof t==`object`&&t){let n=t,r=e=>typeof n[e]==`string`?n[e]:void 0,i=e===`read`?r(`path`):e===`bash`?r(`command`):e===`grep`||e===`find`?r(`pattern`):e===`ls`||e===`edit`||e===`write`?r(`path`):void 0;if(typeof i==`string`)return i}try{let e=JSON.stringify(t).replace(/\n/g,` `);return e.length>40?`${e.slice(0,39)}…`:e}catch{return String(t).slice(0,40)}}const Br={running:{text:()=>`running`,themeSlot:`muted`},ok:{text:e=>e.durationMs===void 0?`ok`:`ok ${pr(e.durationMs)}`,themeSlot:`accent`},error:{text:e=>`failed: ${e.errorMessage??`error`}`,themeSlot:`error`},cancelled:{text:()=>`cancelled`,themeSlot:`muted`},rejected:{text:e=>`rejected: ${e.errorMessage??`concurrency`}`,themeSlot:`warning`}};function Vr(e,t){if(e.length===0)return[];let n=e.slice(0,32),r=e.length>32?e.length-32:0,i=[];return n.forEach((e,a)=>{let o=a===n.length-1&&r===0?`└─ `:`├─ `,s=e.name.length>=8?`${e.name} `:e.name.padEnd(8),c=zr(e.name,e.args),l=Br[e.status];i.push({left:` ${o}${t.fg(`toolTitle`,s)}${t.fg(l.themeSlot,l.text(e))}${t.fg(`dim`,` `+c)}`})}),r>0&&i.push({left:` └─ …+${r} more calls`}),i}function Hr(e,t,n,r=!1,i=!1){let a=gr(e.details,n),o=e=>a===void 0?e:{...e,right:a};if(t)return[o({left:` ${n.fg(`error`,`failed: ${Rr(e)}`)}`})];if(i&&e.details?.result===void 0)return[];let s=e.details?.result;if(s===void 0)return[o({left:` ${n.fg(`muted`,`done`)}`})];if(yr(s))return Er(s,{maxDepth:4,maxChildren:6,maxLineChars:120,moreAfter:r}).map((e,t)=>{let n={left:` ${e}`};return t===0&&a!==void 0?{...n,right:a}:n});let c=hr(s);return c===void 0?[o({left:` ${n.fg(`muted`,`done`)}`})]:[o({left:` ${n.fg(`dim`,`→ ${c}`)}`})]}function Ur(e,t,n,r={}){let i=_r(e.details),a=[...Hr({...e,details:i},t,n,!1,r.isPartial===!0)];return i?.subCalls!==void 0&&a.push(...Vr(i.subCalls,n)),new ur(a)}function Wr(e,t,n,r,i={}){let a=_r(e.details);if(n){let t=[...Hr({...e,details:a},!0,r)];a?.subCalls!==void 0&&t.push(...Vr(a.subCalls,r));let n=U(e.content?.find(e=>e.type===`text`)?.text??Rr(e));for(let e of n.split(`
36
- `).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new ur(t)}let o=[],s=t.code??t.script??``;if(s.length>0){let e=s.split(`
37
- `).map(e=>G(e,120)),t=e.slice(0,3);o.push({label:`code`,lines:t,...e.length>t.length?{more:e.length-t.length}:{}})}if(a!==void 0&&a.surface===`workflow`&&a.phases.length>0){let e=a.phases.slice(0,8),t=a.phases.length-e.length,n=t>0?` …+${t} more phases`:``;o.push({label:`phases`,lines:[`${e.join(` → `)}${n}`]})}if(a!==void 0&&a.narrations.length>0){let e=a.narrations.slice(0,12);o.push({label:`log`,lines:e.map(e=>U(e)),...a.narrations.length>e.length?{more:a.narrations.length-e.length}:{}})}if(a!==void 0&&a.logs.length>0){let e=a.logs.slice(0,12);o.push({label:`out`,lines:e.map(e=>U(e)),...a.logs.length>e.length?{more:a.logs.length-e.length}:{}})}if(a!==void 0&&a.warnings.length>0){let e=a.warnings.slice(0,4);o.push({label:`warn`,lines:e.map(e=>U(e)),...a.warnings.length>e.length?{more:a.warnings.length-e.length}:{}})}if(a!==void 0&&a.imageCount>0){let e=a.imageCount===1?`1 image attached`:`${a.imageCount} images attached`;o.push({label:`image`,lines:[e]})}let c=a?.subCalls,l=c!==void 0&&c.length>0||o.length>0,u=Hr({...e,details:a},!1,r,l,i.isPartial===!0);c!==void 0&&u.push(...Vr(c,r));for(let e=0;e<o.length;e+=1){let t=e===o.length-1;u.push(...vr(o[e]??{label:``,lines:[]},t,r))}return new ur(u)}function Gr(e){return{renderCall(t,n,r){return Ir(t,n,e,{...r?.invalidate===void 0?{}:{requestInvalidate:r.invalidate},...r?.isPartial===void 0?{}:{isPartial:r.isPartial},...r?.state===void 0?{}:{state:r.state}})},renderResult(e,t,n,r){let i=t.isPartial===!0;return t.expanded===!0?Wr(e,r?.args??{},r?.isError===!0,n,{isPartial:i}):Ur(e,r?.isError===!0,n,{isPartial:i})}}}const Kr=["Run a TypeScript program that composes pi's tools in one shot. Required arguments: `code` —","the body of an async function (top-level `return` and `await` work; type annotations are","advisory, the code runs type-stripped) — and `description`, a 5-10 word summary of what the",`program does.`,``,"Inside the program, call this session's enabled built-in tools as `tools.<name>(args)` — e.g.",'`await tools.read({ path: "src/index.ts" })`.',`The bound names are this session's active built-in tools, less any binding the install has not`,`explicitly opted in — this surface is narrower than the session's tool list on purpose;`,"independent calls may overlap under `Promise.all`.",``,"The parallel binding `pi.dispatch` is always available, registered under its literal dot name —",'call it with string indexing, e.g. `await tools["pi.dispatch"]({ agent: "reviewer", task: "..." })`;',"`tools.pi.dispatch` does not exist. It fans work out to child pi agents, and independent","foreground dispatches compose under `Promise.all` exactly like the built-in calls. The run's","actual bound names (this run, not a static list) are on the `ptcBindings` global, so the program",`never has to guess what is bound.`,``,On,``,"Only the program's return value and its `console.log` output come back. This surface has no","helpers: `log` / `phase` / `parallel` / `pipeline` exist only in `ptc_workflow`.",``,"Image-bearing tool results inside the program (a `tools.read` on a PNG, say) are attached to you",`after the run, so never return image data as the completion value — that only spends your context`,`on base64.`].join(`
38
- `),qr=x.Object({code:x.String({description:`The program: the body of an async TypeScript function.`}),description:x.String({description:`Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI).`}),timeoutMs:x.Optional(x.Number({description:`Elapsed deadline in milliseconds for the whole run, including tool calls. Omit it (or pass 0) for the default of ${L.timeoutMs/1e3} s; anything above ${L.maxTimeoutMs/1e3} s is capped. The deadline bounds the whole run: if it expires, in-flight foreground dispatches spawned by the program are terminated with it.`}))});function Jr(e={}){return I({name:`ptc_run_code`,label:`PTC Run Code`,exposure:e.exposure,description:Kr,promptSnippet:`Run a TypeScript program that composes pi's tools in one shot (tools.<name>(args)); only its return value and console.log come back`,promptGuidelines:[...qn],parameters:qr,async execute(t,n,r,i,a){let o=Yn(a),s=W(e.getBindingSourceNames?.(),e.getOptInBindings?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=Xn({surface:`run_code`,startedAt:c,onUpdate:i}),p;try{p=await Tn({code:n.code,surface:`run_code`,cwd:o,bindings:pn({cwd:o,names:s,includeDispatch:!0}),...u===void 0?{}:{sessionDir:u},...d===void 0?{}:{dispatchDeps:d},...e.depth===void 0?{}:{depth:e.depth},...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...n.timeoutMs===void 0?{}:{timeoutMs:n.timeoutMs},...r===void 0?{}:{signal:r},...e.config===void 0?{}:{config:e.config},...l===void 0?{}:{pool:l},onSubCallChange:e=>f.update(e)})}finally{f.cancel()}if(p.error!==void 0)throw Qn(p);return $n({outcome:p,surface:`run_code`,durationMs:Date.now()-c})},...Gr(`run_code`)})}const Yr=[`Run a structured TypeScript workflow: a named plan that reports phases and narration as it`,"goes. `script` is the body of an async function, `meta` names it (`{ name, description, phases? }`,","where `phases` is the ordered plan), and optional `args` is plain-JSON input bound to the","program's `args` global.",``,"Helpers inside the script: `log(message)` narrates progress; `phase(title)` frames the workflow","(titles outside `meta.phases` are reported as warnings); `parallel(thunks)` runs thunks","concurrently, a failed item becoming `null`; `pipeline(items, ...stages)` chains stages per item","with the same per-item `null` on failure. There is no `agent()` helper.",``,"Tools are reachable as `tools.<name>(args)` exactly as in `ptc_run_code`, and the bound names",`are this session's enabled built-ins less any binding the install has not opted in. The parallel`,"binding `pi.dispatch` is always available under",'its literal dot name — call it with string indexing: `await tools["pi.dispatch"]({ agent, task })`;',"the run's actual bound names are on the `ptcBindings` global. What comes back is the script's","return value, its `log`/`phase` narration and its `console.log` output.",``,On,``,`Image-bearing tool results inside the script are attached to you after the run — never return`,`image data as the script's value.`].join(`
39
- `),Xr=x.Object({meta:x.Object({name:x.String({description:`Short workflow name, shown in the UI.`}),description:x.String({description:`What this workflow does, in active voice.`}),phases:x.Optional(x.Array(x.Object({name:x.String({description:`Phase title, matched against phase(title) calls.`})}),{description:`Ordered plan of the workflow's phases. phase() titles outside this list are reported as warnings.`}))},{description:`Workflow metadata: what this run is and which phases it declares.`}),script:x.String({description:`The program: the body of an async TypeScript function.`}),args:x.Optional(x.Record(x.String(),x.Unknown(),{description:"Plain-JSON input bound to the program's `args` global. No functions, symbols, undefined values or cycles."}))});function Zr(t){if(t!==void 0){if(typeof t!=`object`||!t||Array.isArray(t))throw TypeError(`ptc_workflow args must be a plain JSON object, received ${e(t)}`);for(let e of Object.keys(t)){let n=Qr(t[e],`args.${e}`,/* @__PURE__ */ new Set);if(n!==void 0)throw TypeError(`ptc_workflow args must be plain JSON: ${n}`)}}}function Qr(t,n,r){if(t===null||typeof t==`string`||typeof t==`boolean`)return;if(t===void 0)return`${n} is undefined`;if(typeof t==`number`)return Number.isFinite(t)?void 0:`${n} is ${String(t)}, which is not representable as JSON`;if(typeof t!=`object`)return`${n} is ${e(t)}`;let i=t;if(r.has(i))return`${n} is a circular reference`;r.add(i);try{if(Array.isArray(i)){for(let e=0;e<i.length;e+=1){let t=Qr(i[e],`${n}[${e}]`,r);if(t!==void 0)return t}return}let e=Object.getPrototypeOf(i);if(e!==Object.prototype&&e!==null){let e=i.constructor?.name;return`${n} is a ${typeof e==`string`&&e.length>0?e:`non-plain object`}, not plain JSON`}for(let e of Object.keys(i)){let t=Qr(i[e],`${n}.${e}`,r);if(t!==void 0)return t}return}finally{r.delete(i)}}function $r(e,t){if(t===void 0||t.length===0)return[];let n=new Set(t),r=/* @__PURE__ */ new Set,i=[];for(let t of e.phases)n.has(t)||r.has(t)||(r.add(t),i.push(`phase "${t}" is not listed in meta.phases (declared: ${[...n].join(`, `)})`));return i}function ei(e={}){return I({name:`ptc_workflow`,label:`PTC Workflow`,exposure:e.exposure,description:Yr,promptSnippet:`Run a structured TypeScript workflow with named phases, narration (log/phase) and structured concurrency (parallel/pipeline)`,promptGuidelines:[...qn],parameters:Xr,async execute(t,n,r,i,a){Zr(n.args);let o=Yn(a),s=W(e.getBindingSourceNames?.(),e.getOptInBindings?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=Xn({surface:`workflow`,startedAt:c,onUpdate:i}),p;try{p=await Tn({code:n.script,surface:`workflow`,cwd:o,bindings:pn({cwd:o,names:s,includeDispatch:!0}),...u===void 0?{}:{sessionDir:u},...d===void 0?{}:{dispatchDeps:d},...n.args===void 0?{}:{args:n.args},...e.depth===void 0?{}:{depth:e.depth},...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...r===void 0?{}:{signal:r},...e.config===void 0?{}:{config:e.config},...l===void 0?{}:{pool:l},onSubCallChange:e=>f.update(e)})}finally{f.cancel()}if(p.error!==void 0)throw Qn(p);let m=n.meta.phases?.map(e=>e.name);return $n({outcome:p,surface:`workflow`,warnings:$r(p,m),durationMs:Date.now()-c})},...Gr(`workflow`)})}var ti=class{#e;constructor(e){this.#e=new Map(e??[])}async readOutput(e){let t=this.#e.get(e);return t===void 0?null:t}async writeOutput(e,t){this.#e.set(e,t)}outputRef(e){return`memory:tasks/${e}/output.log`}};function ni(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}var ri=class{#e;constructor(e){if(e.length===0)throw TypeError(`FileOutputStorage: baseDir is required`);this.#e=e}async readOutput(e){try{return await ge(this.#t(e),`utf8`)}catch(e){if(ni(e))return null;throw e}}async writeOutput(e,t){let n=A(this.#e,`tasks`,e);await he(n,{recursive:!0}),await be(A(n,`output.log`),t,`utf8`)}outputRef(e){return this.#t(e)}#t(e){return A(this.#e,`tasks`,e,`output.log`)}};function ii(e,t){return Mn(e,`pi-ptc-task-output-`,t===void 0?{}:{fullText:t})}const ai={running:`accent`,stopping:`warning`,succeeded:`success`,failed:`error`,lost:`dim`,canceled:`muted`},oi={running:`●`,stopping:`◐`,succeeded:`✓`,failed:`✗`,lost:`◌`,canceled:`⊘`};var J=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>si(e,t))}};function si(e,t){let{left:n,right:r}=e;if(r===void 0)return P(n,t,`…`);let i=F(r);if(i>=t)return P(r,t,`…`);let a=P(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-F(a));return a+` `.repeat(o)+r}function ci(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function li(e){return ci((U(e).split(`
40
- `).find(e=>e.trim().length>0)??``).trim(),120)}function ui(e){return typeof e==`object`&&e?e:{}}function di(e){return e===`running`||e===`stopping`}function fi(e){let t=Math.max(0,Math.floor(e));if(t<1e3)return`${t}ms`;let n=Math.floor(t/1e3);if(n<60)return`${n}s`;let r=Math.floor(n/60),i=n%60;return r<60?`${r}m${i}s`:`${Math.floor(r/60)}h${String(r%60).padStart(2,`0`)}m`}function pi(e,t){if(di(e.status))return fi(t-e.createdAt);if(e.durationMs!==void 0)return fi(e.durationMs);if(e.finishedAt!==void 0)return fi(e.finishedAt-e.createdAt)}function mi(e,t){let{state:n}=t;t.isLive?n.interval??=setInterval(()=>t.requestInvalidate(),1e3):n.interval!==void 0&&(clearInterval(n.interval),n.interval=void 0);let r=e;return r.dispose=()=>{n.interval!==void 0&&(clearInterval(n.interval),n.interval=void 0)},e}function hi(){}function gi(e,t,n){return new J([{left:`└─ ${n.fg(`toolTitle`,n.bold(e))}${t.length>0?` ${t}`:``}`}])}function _i(e,t,n){let r=ui(t);switch(e){case`task-list`:{let e=Array.isArray(r.status)?r.status:void 0,t=e!==void 0&&e.length>0?e.join(`,`):`all`,i=typeof r.limit==`number`?` · limit=${r.limit}`:``;return gi(`PTC task list`,n.fg(`dim`,`status=${t}${i}`),n)}case`task-output`:{let e=typeof r.taskId==`string`&&r.taskId.length>0?r.taskId:void 0,t=typeof r.sinceBytes==`number`?` · since=${r.sinceBytes}B`:``;return gi(`PTC task output`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}case`task-stop`:{let e=typeof r.taskId==`string`&&r.taskId.length>0?r.taskId:void 0,t=typeof r.reason==`string`&&r.reason.length>0?` · reason=${U(r.reason)}`:``;return gi(`PTC task stop`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}}}function vi(e,t,n,r){let i=ai[e.status]??`muted`,a=n.fg(i,oi[e.status]??`?`),o=ci(U(e.label),48),s=[`${a} ${n.fg(`text`,o)}`,n.fg(`dim`,U(e.agentName))],c=pi(e,r);return c!==void 0&&s.push(n.fg(`dim`,c)),e.outputBytes!==void 0&&s.push(n.fg(`dim`,`${e.outputBytes}B`)),{left:` ${t?`└─ `:`├─ `}${s.join(n.fg(`dim`,` · `))}`}}function yi(e,t){let n=ui(e),r=Array.isArray(n.tasks)?n.tasks:[];if(r.length===0)return mi(new J([{left:` ${t.theme.fg(`muted`,`(no background tasks)`)}`}]),{isLive:!1,state:t.state,requestInvalidate:t.requestInvalidate});let i=r.some(e=>di(e.status)),a=r.slice(0,32),o=r.length-a.length,s=a.map((e,n)=>vi(e,n===a.length-1&&o===0,t.theme,t.now));return o>0&&s.push({left:` └─ ${t.theme.fg(`dim`,`…+${o} more tasks`)}`}),mi(new J(s),{isLive:t.partial&&i,state:t.state,requestInvalidate:t.requestInvalidate})}function bi(e,t,n){let r=[];if(e!==void 0&&r.push(n.fg(`dim`,`${e}B`)),t&&r.push(n.fg(`warning`,`truncated`)),r.length!==0)return`${n.fg(`dim`,`•`)} ${r.join(n.fg(`dim`,` · `))}`}function xi(e,t){return` ${t.fg(`dim`,`full output: `)}${t.fg(`accent`,e)}`}function Si(e,t){let n=ui(e),r=typeof n.output==`string`?n.output:``,i=typeof n.outputBytes==`number`?n.outputBytes:void 0,a=n.outputTruncated===!0,o=typeof n.outputFullPath==`string`&&n.outputFullPath.length>0?n.outputFullPath:void 0,s=bi(i,a,t.theme),c=[];if(r.length>0){let e=U(r).split(`
41
- `),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,ci(e,160));c.push(n===0&&s!==void 0?{left:` ${r}`,right:s}:{left:` ${r}`})}),e.length>n.length&&c.push({left:` ${t.theme.fg(`dim`,`…+${e.length-n.length} more lines`)}`}),a&&o!==void 0&&c.push({left:xi(o,t.theme)})}else o===void 0?c.push({left:` ${t.theme.fg(`muted`,`(no output yet)`)}`,...s===void 0?{}:{right:s}}):c.push({left:xi(o,t.theme),...s===void 0?{}:{right:s}});return new J(c)}function Ci(e,t){let n=ui(e),r=n.task;if(typeof r!=`object`||!r)return new J([{left:` ${t.theme.fg(`muted`,`(no task)`)}`}]);let i=ai[r.status]??`muted`,a=t.theme.fg(i,oi[r.status]??`?`),o=typeof n.fromStatus==`string`?n.fromStatus:void 0,s=o===void 0?r.status===`stopping`?`running → stopping`:`→ ${String(r.status)}`:`${o} → ${r.status}`,c=[`${a} ${t.theme.fg(`text`,U(r.id))}`,t.theme.fg(i,s)];return typeof r.stopReason==`string`&&r.stopReason.length>0&&c.push(t.theme.fg(`dim`,`reason=${U(r.stopReason)}`)),new J([{left:` ${c.join(` `)}`}])}function wi(e,t){let n=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0),r=li(n?.text??``)||`failed`;return new J([{left:` ${t.fg(`error`,`failed: ${r}`)}`}])}function Ti(e,t,n){switch(e){case`task-list`:return yi(t.details,n);case`task-output`:return Si(t.details,n);case`task-stop`:return Ci(t.details,n)}}function Ei(e){return{renderCall(t,n){return _i(e,t,n)},renderResult(t,n,r,i){return i?.isError===!0?wi(t,r):Ti(e,t,{theme:r,partial:n?.isPartial===!0||i?.isPartial===!0,requestInvalidate:i?.invalidate??hi,state:i?.state??{},now:Date.now()})}}}const Di=[`Use ptc_task_list to see the background tasks this session dispatched and their live status.`,`Use ptc_task_output to read a task's captured output (it is tail-truncated; the footer names the full-output file). A succeeded task's child report is rendered there, ahead of the prose.`,`Use ptc_task_stop to ask a running task to stop; the dispatcher delivers the actual signal, so the task transitions through stopping to canceled.`,`These background-task tools stay callable when PTC mode is off — /ptc off only blocks new dispatches.`],Oi=x.Union([x.Literal(`running`),x.Literal(`stopping`),x.Literal(`succeeded`),x.Literal(`failed`),x.Literal(`canceled`),x.Literal(`lost`)]),ki=x.Object({status:x.Optional(x.Array(Oi,{description:`Only return tasks in these states. Omit for all six states (running, stopping, succeeded, failed, canceled, lost).`})),limit:x.Optional(x.Number({description:`Maximum number of tasks to return, newest first. Defaults to 100.`}))}),Ai=x.Object({tasks:x.Array(x.Object({id:x.String({description:`The task's ULID — the id ptc_task_output and ptc_task_stop take.`}),status:x.String({description:`One of running, stopping, succeeded, failed, canceled, lost (ADR-0022 §2).`}),agent:x.String({description:`The agent the task was dispatched with (the record's agentName).`}),depth:x.Number({description:`0 for a direct child of the session, 1 for a grandchild, and so on (ADR-0016).`}),label:x.String({description:`The label the task was dispatched with.`}),output_bytes:x.Optional(x.Number({description:`Captured output size; absent while the task has flushed no output.`})),error_message:x.Optional(x.String({description:`Failure text; absent unless the record carries an error.`}))}),{description:`One row per task, newest first — the same order as details.tasks.`}),count:x.Number({description:"Number of rows in `tasks`."})});function ji(e){return{id:e.id,status:e.status,agent:e.agentName,depth:e.depth,label:e.label,...e.outputBytes===void 0?{}:{output_bytes:e.outputBytes},...e.errorMessage===void 0?{}:{error_message:e.errorMessage}}}function Mi(e){let t=[e.id,e.status,`${e.agentName} depth=${e.depth}`,U(e.label)];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.errorMessage!==void 0&&t.push(`error=${U(e.errorMessage)}`),t.join(` `)}function Ni(e){return I({name:`ptc_task_list`,label:`PTC Task List`,description:[`List the background tasks this session has dispatched (from pi.dispatch({ background: true })).`,`Returns each task's id, status, agent, depth, label and output size, newest first.`,`Filter with status (e.g. ["running"]); limit caps the row count (default 100).`].join(`
42
- `),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...Di],parameters:ki,outputSchema:Ai,async execute(t,n){let r=await e.query({...n.status===void 0?{}:{status:n.status},limit:n.limit??100,orderBy:`createdAt-desc`}),i=r.length===0?`(no background tasks)`:r.map(e=>Mi(e)).join(`
43
- `),a={tasks:r.map(e=>ji(e)),count:r.length};return{content:[{type:`text`,text:i}],details:{tasks:r,count:r.length},structuredContent:a}},...Ei(`task-list`)})}async function Pi(e,t,n){let r=await e.get(t);if(r===null)throw Error(`${n}: unknown taskId ${t}`);return r}function Fi(e){let t=e.reportChannel;if(t===void 0)return;if(t===`none`)return`<child-report channel="none">the child produced no report; it did not comply with the report contract. What follows is its prose, unbacked by a report.</child-report>`;if(t===`opted-out`)return`<child-report channel="opted-out">this agent opts out of the report contract, so none was asked for; the prose below is the whole of what it produced, and nothing is missing.</child-report>`;let n=e.report;if(n===void 0)return`<child-report channel="${t}">the record names channel ${t} but carries no report.</child-report>`;let r=[`<child-report channel="${t}">`,`summary: ${n.summary}`],i=n.findings.slice(0,20),a=n.findings.length-i.length;r.push(`findings (${String(n.findings.length)}):`);for(let[e,t]of i.entries())r.push(` ${String(e+1)}. ${t.what} — evidence: ${t.evidence}`);return a>0&&r.push(` …+${String(a)} more findings not shown`),r.push(n.files_touched.length===0?`files_touched: (none)`:`files_touched: ${n.files_touched.join(`, `)}`),r.push(`usage: input=${String(n.usage.input)} output=${String(n.usage.output)} cost=${String(n.usage.cost)} turns=${String(n.usage.turns)}`),r.push(`</child-report>`),r.join(`
44
- `)}const Ii=x.Object({taskId:x.String({description:`The background task's id (as returned by ptc_task_list or the dispatch handle).`}),sinceBytes:x.Optional(x.Number({description:`Skip this many bytes of the stored output before returning it. Use for paging larger logs; defaults to 0.`}))}),Li=x.Object({task_id:x.String({description:`The background task id that was asked for.`}),status:x.String({description:`The task's status at read time (ADR-0022 §2's six states), so a polling script does not need a second ptc_task_list call.`}),output:x.String({description:`The page the model reads: the stored output's tail, ADR-0015-truncated.`}),output_bytes:x.Number({description:`Total bytes stored for the task, regardless of sinceBytes or ADR-0015 truncation.`}),output_preview:x.Optional(x.String({description:`The complete stored output; present only at or below the 2048-byte preview ceiling (ADR-0022 §7).`})),output_truncated:x.Boolean({description:"Whether ADR-0015 cut anything out of `output`."}),output_full_path:x.Optional(x.String({description:"A file holding the complete output; present only when `output_truncated` is true (ADR-0015 §2)."})),report_channel:x.Optional(x.String({description:"Which channel delivered the child's report: `tool`, `prompt-json`, or `none` when the child ignored the contract (ADR-0032). Absent until the task succeeds — a running or failed task carries no report claim at all."})),report:x.Optional(x.Object({summary:x.String({description:`The child's own one-line summary.`}),findings:x.Array(x.Object({what:x.String({description:`The claim the child makes.`}),evidence:x.String({description:`The evidence that claim rests on.`})}),{description:`One entry per claim the child made.`}),files_touched:x.Array(x.String(),{description:`Paths the child says it touched.`}),usage:x.Object({input:x.Number({description:`Host-observed input tokens (never the child's claim).`}),output:x.Number({description:`Host-observed output tokens.`}),cost:x.Number({description:`Host-observed cost.`}),turns:x.Number({description:`Host-observed assistant turns.`})})}))});function Ri(e,t){return I({name:`ptc_task_output`,label:`PTC Task Output`,description:[`Read a background task's captured output.`,`A succeeded task also renders its child report (summary, findings, files touched, usage) ahead of the prose, and says which channel delivered it; a channel of "none" means the child ignored the report contract.`,`The text is tail-truncated to pi's ADR-0015 limits (50 KB / 2000 lines); when anything is cut, outputFullPath names a file with the complete output.`,`Pass sinceBytes to skip a prefix of the stored output when paging.`].join(`
45
- `),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...Di],parameters:Ii,outputSchema:Li,async execute(n,r){let i=r.taskId,a=await Pi(e,i,`ptc_task_output`),o=await t.readOutput(i)??``,s=Buffer.byteLength(o,`utf8`),c=r.sinceBytes??0;if(!Number.isInteger(c)||c<0)throw Error(`ptc_task_output: sinceBytes must be a non-negative integer, got ${String(r.sinceBytes)}`);if(c>s)throw Error(`ptc_task_output: sinceBytes ${c} exceeds the ${s}-byte output of task ${i}`);let l=Buffer.from(o,`utf8`);if(c<s&&((l[c]??0)&192)==128)throw Error(`ptc_task_output: sinceBytes ${c} splits a UTF-8 character in task ${i}; use a byte offset on a character boundary`);let u=ii(c===0?o:l.subarray(c).toString(`utf8`),o),d=s<=2048?o:void 0,f=Fi(a),p={taskId:i,output:u.text,outputBytes:s,...d===void 0?{}:{outputPreview:d},outputTruncated:u.truncated,...u.fullPath===void 0?{}:{outputFullPath:u.fullPath},...a.report===void 0?{}:{report:a.report},...a.reportChannel===void 0?{}:{reportChannel:a.reportChannel}},m=p.output.length>0?p.output:`(no output yet; task ${i} is ${a.status})`,h=f===void 0?m:`${f}\n${m}`,g={task_id:i,status:a.status,output:u.text,output_bytes:s,...d===void 0?{}:{output_preview:d},output_truncated:u.truncated,...u.fullPath===void 0?{}:{output_full_path:u.fullPath},...a.reportChannel===void 0?{}:{report_channel:a.reportChannel},...a.report===void 0?{}:{report:a.report}};return{content:[{type:`text`,text:h}],details:p,structuredContent:g}},...Ei(`task-output`)})}const zi=x.Object({taskId:x.String({description:`The running task's id (as returned by ptc_task_list or the dispatch handle).`}),reason:x.Optional(x.String({description:`Why the task is being stopped; recorded as the task's stopReason. Defaults to "model stop".`}))}),Bi=x.Object({task_id:x.String({description:`The background task id that was asked to stop.`}),status:x.String({description:"The task's status AFTER the stop command — `stopping`, not the terminal `canceled`; the dispatcher pump owns the latter (ADR-0022 §8)."}),from_status:x.String({description:"The status observed before the stop: `running` for a fresh stop, `stopping` for the idempotent late-arrival path (ADR-0022 §8)."}),stop_reason:x.Optional(x.String({description:`The reason recorded as the task's stopReason; absent when the record carries none.`}))});function Vi(e,t,n={}){if(t==null)throw TypeError(`createPtcTaskStopTool: lifecycle is required`);let r=n.clock??(()=>Date.now());return I({name:`ptc_task_stop`,label:`PTC Task Stop`,description:[`Ask a running background task to stop.`,`The task moves to "stopping"; the dispatcher sends the signal and records the terminal "canceled" state when the child exits.`,`The call is idempotent when the task is already stopping, and errors when the task is already terminal.`].join(`
46
- `),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...Di],parameters:zi,outputSchema:Bi,async execute(t,n){let i=n.taskId,a=await Pi(e,i,`ptc_task_stop`),o=a.spawnSource.callerId.length>0?a.spawnSource.callerId:`ptc_task_stop`,{record:s,fromStatus:c}=await e.transition({kind:`stop`,taskId:i,reason:n.reason??`model stop`},{clock:r,callerId:o}),l=s.stopReason===void 0?``:` reason=${U(s.stopReason)}`,u=c??a.status,d={task_id:i,status:s.status,from_status:u,...s.stopReason===void 0?{}:{stop_reason:s.stopReason}};return{content:[{type:`text`,text:`${s.id} ${s.status}${l}`}],details:{task:s,fromStatus:u},structuredContent:d}},...Ei(`task-stop`)})}var Hi=class{#e;#t=/* @__PURE__ */ new Map;constructor(e={}){this.#e=Be(e.config)}get(e){let t=this.#t.get(e);if(t!==void 0)return t;let n=ze(),r=new gn({buildWorkerUrl:yn,size:this.#e.poolSize,acquireTimeoutMs:this.#e.poolAcquireTimeoutMs,drainGraceMs:this.#e.drainGraceMs,workerOptions:hn({surface:e,env:n,limits:this.#e})});return this.#t.set(e,r),r}async drain(){let e=[...this.#t.values()];this.#t.clear(),await Promise.all(e.map(e=>e.drain()))}};const Ui={warn:e=>{console.warn(`[pi-ptc.notifications] `+e)}};var Wi=class{#e;#t;#n;#r;#i;constructor(e,t={}){this.#e=e,this.#t=t.now??Date.now,this.#n=t.logger??Ui,this.#r=[],this.#i=/* @__PURE__ */ new Map}async subscribe(e,t,n){let r=await this.#e.loadSubscription(e,t);if(r!==null)return r;let i={subscriberId:e,taskId:t,cursor:n??`00000000000000000000`,status:`active`,createdAt:this.#t()};return await this.#e.saveSubscription(i),i}async drainPending(e,t){let n=await this.#o(e,t,`drainPending`);return this.#s(n)}async acknowledgeEvents(e,t,n){await this.#a(e,t,async()=>{let r=await this.#o(e,t,`acknowledgeEvents`);n<=r.cursor||await this.#e.saveSubscription({...r,cursor:n})})}#a(e,t,n){let r=`${e}-${t}`,i=(this.#i.get(r)??Promise.resolve()).then(n),a=i.then(()=>void 0,()=>void 0);return this.#i.set(r,a),a.then(()=>{this.#i.get(r)===a&&this.#i.delete(r)}),i}onIdleWake(e){this.#r.push(e)}async pendingCount(e,t){let n=await this.#o(e,t,`pendingCount`);return(await this.#s(n)).length}async notifyIdle(e,t){let n=await this.drainPending(e,t);if(n.length===0)return n;let r=this.#r.slice();for(let i of r)try{i(e,n)}catch(n){let r=n instanceof Error?n.message:String(n);this.#n.warn(`notifyIdle: idle-wake handler for subscriber ${e} / task ${t} threw: ${r}`)}return n}async#o(e,t,n){let r=await this.#e.loadSubscription(e,t);if(r===null)throw Error(`${n}: unknown subscription for subscriber ${e} / task ${t}`);return r}async#s(e){let t=[];for await(let n of this.#e.loadEvents(e.subscriberId,e.cursor===`00000000000000000000`?void 0:e.cursor))n.taskId===e.taskId&&t.push(n);return t}};const Gi={mkdir:(e,t)=>he(e,t),readFile:(e,t)=>ge(e,t),writeFile:(e,t,n)=>be(e,t,n),appendFile:(e,t,n)=>me(e,t,n),rename:(e,t)=>ve(e,t),unlink:e=>ye(e),readdir:e=>_e(e)};function Ki(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}function qi(e){return e instanceof Error?e.message:String(e)}function Ji(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}var Yi=class{#e;#t;constructor(e,t={}){if(e.length===0)throw TypeError(`FileTaskStorage: baseDir is required`);this.#e=e,this.#t=t.fs??Gi}async loadTask(e){return await this.#r(this.#f(e))}async saveTask(e){N(e,`saveTask: record is required`),await this.#o(this.#f(e.id),e)}async deleteTask(e){let t=this.#f(e);if(!await this.#c(t))throw Error(`deleteTask: unknown taskId `+e);await this.#t.unlink(t)}async*listTasks(e){let t=this.#l();for(let n of(await this.#s(t)).sort()){if(!n.endsWith(`.json`))continue;let r=await this.#r(A(t,n));r!==null&&(e?.status===void 0||r.status===e.status)&&(e?.label===void 0||r.label===e.label)&&(yield r)}}async loadSubscription(e,t){return await this.#r(this.#p(e,t))}async saveSubscription(e){N(e,`saveSubscription: sub is required`),await this.#o(this.#p(e.subscriberId,e.taskId),e)}async appendEvents(e,t){if(t.length===0){if((await this.#n(e)).length===0)throw Error(`appendEvents: unknown subscriptionId `+e);return}let n=/* @__PURE__ */ new Map;for(let e of t){let t=n.get(e.taskId);t===void 0?n.set(e.taskId,[e]):t.push(e)}let r;for(let t of n.keys())if(await this.loadSubscription(e,t)===null){r=t;break}if(r!==void 0)throw(await this.#n(e)).length===0?Error(`appendEvents: unknown subscriptionId `+e):Error(`appendEvents: no subscription for subscriber `+e+` on task `+r);await this.#t.mkdir(this.#d(),{recursive:!0});for(let[t,r]of n){let n=(r.every((e,t)=>t===0||Ji(r[t-1],e)<=0)?r:[...r].sort(Ji)).map(e=>JSON.stringify(e)).join(`
27
+ `)),t.value!==void 0&&a.push(Xn(t.value));for(let e of r)a.push(`Warning: ${U(e)}`);let o=Rn(a.length>0?a.join(`
28
+ `):`(${er[n]} completed with no output)`),s=o.text,c=o.truncated?o.fullPath:void 0;return{content:[{type:`text`,text:s},...i.map(e=>({type:`image`,data:e.data,mimeType:e.mimeType}))],details:{surface:n,logs:[...t.logs],narrations:[...t.narrations],phases:[...t.phases],warnings:r,...t.value===void 0?{}:{result:t.value},durationMs:e.durationMs,imageCount:i.length,...c===void 0?{}:{fullOutputPath:c},...t.subCalls===void 0?{}:{subCalls:t.subCalls}}}}const or=`└─ `;function sr(e){return e===void 0?``:`read-only tier (${e})\n${or}${e===`strict`?`the child's tool list was narrowed to the read set, so it was never offered a write tool`:`the child's tool list is UNCHANGED — it was told to work without modifying anything, and nothing here prevents it from doing so`}`}const cr=/^(.*?)(└─ |├─ | )(?:PTC(?: workflow)?)([ ].*)$/;function lr(e){return e.replace(/\x1b\[[0-9;]*m|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[\?[0-9;]*[a-zA-Z]/g,``)}function ur(e,t){if(e.charCodeAt(t)!==27)return t;let n=e.charCodeAt(t+1);if(n===93){let n=t+2;for(;n<e.length;){let t=e.charCodeAt(n);if(t===7)return n+1;if(t===27&&e.charCodeAt(n+1)===92)return n+2;n+=1}return n}if(n===91){let n=t+2;for(;n<e.length;){let t=e.charCodeAt(n);if(t>=64&&t<=126)return n+1;n+=1}return n}return t+2}function dr(e,t){let n=0,r=0;for(;r<t&&n<e.length;)e.charCodeAt(n)===27?n=ur(e,n):(n+=1,r+=1);return n}function fr(e,t){let n=t.intervalMs??150,{state:r}=t;t.isPartial?(r.startedAt??=Date.now(),r.interval??=setInterval(()=>t.requestInvalidate(),n)):(r.interval!==void 0&&(clearInterval(r.interval),r.interval=void 0),r.startedAt=void 0);let i=e.render.bind(e),a=e;return a.render=e=>{let a=i(e);return r.startedAt===void 0?a:pr(a,Math.floor((Date.now()-r.startedAt)/n),t.theme)},a.dispose=()=>{r.interval!==void 0&&(clearInterval(r.interval),r.interval=void 0)},e}function pr(e,t,n){return e.map(e=>{let r=lr(e),i=cr.exec(r);if(i===null)return e;let a=(i[3]??``).slice(1);if(a.length===0)return e;let o=t%(a.length+1),s=i[0].length-a.length,c=dr(e,s),l=dr(e,s+a.length),u=o>=a.length?n.fg(`dim`,a):`${o>0?n.fg(`dim`,a.slice(0,o)):``}${n.fg(`accent`,a.slice(o,o+1))}${n.fg(`dim`,a.slice(o+1))}`;return`${e.slice(0,c)}${u}${e.slice(l)}`})}const mr={run_code:`PTC`,workflow:`PTC workflow`},hr=`├─ `,gr=`│ `;var _r=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>vr(e,t))}};function vr(e,t){let{left:n,right:r}=e;if(r===void 0)return P(n,t,`…`);let i=F(r);if(i>=t)return P(r,t,`…`);let a=P(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-F(a));return a+` `.repeat(o)+r}function G(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function yr(e){return G((U(e).split(`
29
+ `).find(e=>e.trim().length>0)??``).trim(),120)}function br(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2).replace(/\.?0+$/,``)}s`}function xr(e,t){return`${e} ${t}${e===1?``:`s`}`}function Sr(e){for(let t of e.split(`
30
+ `)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return G(e.replace(/\s*\/\/.*$/,``),120)}}function Cr(e){if(e===void 0)return;if(typeof e==`string`){let t=U(e).split(`
31
+ `),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:G(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=Xn(e);if(!t.includes(`
32
+ `)&&t.length<=60)return t;if(Array.isArray(e))return`Array(${e.length})`;let n=Object.keys(e);return n.length===0?`{}`:`{${n.slice(0,4).join(`, `)}${n.length>4?`, +${n.length-4}`:``}}`}function wr(e,t){if(e===void 0)return;let n=[],r=e.logs.length+e.narrations.length;if(r>0&&n.push(t.fg(`dim`,xr(r,`output line`))),e.imageCount>0&&n.push(t.fg(`toolOutput`,xr(e.imageCount,`image`))),e.surface===`workflow`&&e.phases.length>0&&n.push(t.fg(`dim`,xr(e.phases.length,`phase`))),e.warnings.length>0&&n.push(t.fg(`warning`,xr(e.warnings.length,`warning`))),e.fullOutputPath!==void 0&&n.push(t.fg(`warning`,`truncated`)),e.durationMs>0&&n.push(t.fg(`dim`,br(e.durationMs))),n.length!==0)return`${t.fg(`dim`,`•`)} ${n.join(t.fg(`dim`,` · `))}`}function Tr(e){if(e!==void 0)return{surface:e.surface??`run_code`,logs:e.logs??[],narrations:e.narrations??[],phases:e.phases??[],warnings:e.warnings??[],durationMs:e.durationMs??0,imageCount:e.imageCount??0,...e.result===void 0?{}:{result:e.result},...e.fullOutputPath===void 0?{}:{fullOutputPath:e.fullOutputPath},...e.subCalls===void 0?{}:{subCalls:e.subCalls}}}function Er(e,t,n){let r=` `+(t?or:hr),i=` `+(t?` `:gr),a=` `.repeat(8),o=[],s=e.lines[0]??``;o.push({left:`${r}${e.label.padEnd(8)}${n.fg(`dim`,s)}`});for(let t=1;t<e.lines.length;t++)o.push({left:`${i}${a}${n.fg(`dim`,e.lines[t]??``)}`});return e.more!==void 0&&e.more>0&&o.push({left:`${i}${a}…+${e.more} more lines`}),o}function Dr(e){return typeof e!=`object`||!e?!1:Array.isArray(e)?e.length>0:Object.keys(e).length>0}const Or=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function kr(e){return Or.test(e)?e:JSON.stringify(e)}function Ar(e,t){if(e===null)return`null`;if(typeof e==`boolean`||typeof e==`number`)return String(e);if(typeof e==`string`){let n=U(e);if(n.length===0)return`""`;if(n.includes(`
33
+ `)){let e=G(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(G(n,Math.max(2,t-5)))+`…`}return`?`}function jr(e){return typeof e!=`object`||!e}function Mr(e,t){if(t<8)return;if(Array.isArray(e)){if(e.length===0)return`[]`;if(e.length>5||!e.every(jr))return;let n=`[`+e.map(e=>Ar(e,Math.max(2,Math.floor(t/4)))).join(`, `)+`]`;return n.length<=t?n:void 0}if(typeof e!=`object`||!e)return;let n=Object.keys(e);if(n.length===0)return`{}`;if(n.length>5||!Object.values(e).every(jr))return;let r=`{`+n.map(n=>{let r=e[n]??null;return kr(n)+`: `+Ar(r,Math.max(2,Math.floor(t/4)))}).join(`, `)+`}`;return r.length<=t?r:void 0}function Nr(e,t,n,r,i,a,o,s,c){let l=n+(r?`└─ `:`├─ `),u=n+(r?` `:`│ `);if(s>=i){c.push(K(l+t+`…`,o));return}if(Array.isArray(e)&&e.length===0){c.push(K(l+t+`[]`,o));return}if(!Array.isArray(e)&&typeof e==`object`&&e&&Object.keys(e).length===0){c.push(K(l+t+`{}`,o));return}if(typeof e!=`object`||!e){let n=Math.max(0,o-F(l)-t.length);c.push(K(l+t+Ar(e,n),o));return}let d=Mr(e,Math.max(0,o-F(l)-t.length));if(d!==void 0){c.push(K(l+t+d,o));return}let f=Array.isArray(e),p=f?e.length:Object.keys(e).length,m;m=f?`Array(`+p+`)`:p>a?`{`+a+` of `+p+`}`:`{`+p+` keys}`,c.push(K(l+t+m,o));let h=Math.min(a,p);if(f)for(let t=0;t<h;t+=1){let n=t===h-1&&p<=h;Nr(e[t]??null,`[`+t+`] `,u,n,i,a,o,s+1,c)}else{let t=Object.keys(e);for(let n=0;n<h;n+=1){let r=n===h-1&&p<=h,l=t[n];Nr(e[l]??null,kr(l)+`: `,u,r,i,a,o,s+1,c)}}if(p>h){let e=f?`items`:`keys`;c.push(K(u+`└─ …+`+(p-h)+` more `+e,o))}}function K(e,t){if(F(e)<=t)return e;let n=e.match(/^([\s│├└─]*)/),r=n&&n[1]?n[1]:``,i=F(r),a=Math.max(0,t-i-1),o=``,s=0;for(let t of e.slice(r.length)){let e=F(t);if(s+e>a)break;o+=t,s+=e}return r+o+`…`}function Pr(e,t={}){let n=t.maxDepth??4,r=t.maxChildren??6,i=t.maxLineChars??120,a=t.moreAfter===!0;if(!Dr(e))return typeof e==`object`&&e?[Array.isArray(e)?`[]`:`{}`]:[Ar(e,i)];let o=[];if(Array.isArray(e)){let t=e.length,s=Math.min(r,t);for(let c=0;c<s;c+=1){let l=!a&&c===s-1&&t<=s;Nr(e[c]??null,`[`+c+`] `,``,l,n,r,i,0,o)}return t>s&&o.push((a?`├─ `:`└─ `)+`…+`+(t-s)+` more items`),o}let s=Object.keys(e),c=s.length,l=Math.min(r,c);for(let t=0;t<l;t+=1){let u=!a&&t===l-1&&c<=l,d=s[t];Nr(e[d]??null,kr(d)+`: `,``,u,n,r,i,0,o)}return c>l&&o.push((a?`├─ `:`└─ `)+`…+`+(c-l)+` more keys`),o}const Fr=`child report`;function Ir(e){return e===0?`[]`:`Array(${e})`}function Lr(e){let t=U(e).split(`
34
+ `).find(e=>e.trim().length>0)?.trim()??``;return t.length===0?`""`:G(t,200)}function Rr(e){let t=Number(e.cost.toFixed(4));return`in ${e.input} · out ${e.output} · cost ${t} · ${xr(e.turns,`turn`)}`}function zr(e,t,n){let r=U(n).replace(/\n/g,` `).trim();return r.length<=150?`${e}${t}evidence: ${r}`:`${e}${t}evidence: ${r.slice(0,150)}… (truncated at 150 chars)`}function Br(e,t){let n=[];return e.forEach((r,i)=>{let a=i===e.length-1&&t===0,o=`[${i}]`;n.push(`${a?`└─ `:`├─ `}${o} ${U(r.what).trim()}`.trimEnd()),n.push(zr(a?` `:`│ `,` `.repeat(o.length+2),r.evidence))}),t>0&&n.push(`└─ …+${t} more findings withheld (a report renders at most 20)`),n}function Vr(e,t){let n=e.map((n,r)=>`${r===e.length-1&&t===0?`└─ `:`├─ `}[${r}] `+`${U(n).trim()}`.trimEnd());return t>0&&n.push(`└─ …+${t} more files withheld (a report renders at most 20)`),n}function Hr(e,t){let n=e.label.length>=8?`${e.label} `:e.label.padEnd(8);return K(`${t?or:hr}${n}${e.head}`,200)}function Ur(e,t){let n=e===`none`?`no child report was returned — the child did not comply with the contract, so its prose below is unbacked by a report`:e===`opted-out`?`this agent opts out of the report contract, so none was asked for — the prose below is the whole of what it produced, and nothing is missing`:`the ${e} channel was announced but no report reached the host; the child's prose below is everything it produced`,r=`${Fr} (channel: ${e})`;return t===void 0?`${r}\n${or}${n}`:`${r}\n${hr}${n}\n${Hr({label:`usage`,head:Rr(t),rows:[]},!0)}`}function Wr(e,t,n){if(e===void 0)return Ur(t,n);let r=e.findings.slice(0,20),i=e.findings.length-r.length,a=e.files_touched.slice(0,20),o=e.files_touched.length-a.length,s=[{label:`summary`,head:Lr(e.summary),rows:[]},{label:`findings`,head:Ir(e.findings.length),rows:Br(r,i)},{label:`files`,head:Ir(e.files_touched.length),rows:Vr(a,o)},{label:`usage`,head:Rr(n??e.usage),rows:[]}],c=[`${Fr} (channel: ${t})`];return s.forEach((e,t)=>{let n=t===s.length-1;c.push(Hr(e,n));let r=n?` `:gr;for(let t of e.rows)c.push(K(`${r}${t}`,200))}),c.join(`
35
+ `)}function Gr(e,t,n=`run_code`,r={}){let i=(typeof e.description==`string`&&e.description.trim().length>0?e.description.trim():e.meta?.name)??``,a=Sr(e.code??e.script??``),o=i.length>0?i:a??`(no description)`;return fr(new _r([{left:`└─ ${`${t.fg(`toolTitle`,t.bold(mr[n]))} ${t.fg(`accent`,o)}`}`}]),{intervalMs:150,isPartial:r.isPartial??!1,theme:t,requestInvalidate:r.requestInvalidate??Kr,state:r.state??{}})}function Kr(){}function qr(e){let t=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0);return yr(t?.text??``)||`failed`}function Jr(e,t){if(e===`pi.dispatch`&&typeof t==`object`&&t){let e=t.agent;return typeof e==`string`&&e.trim().length>0?`→ ${e}`:e===void 0?`→ (generalist)`:`→ ${JSON.stringify(e)}`}if(typeof t==`object`&&t){let n=t,r=e=>typeof n[e]==`string`?n[e]:void 0,i=e===`read`?r(`path`):e===`bash`?r(`command`):e===`grep`||e===`find`?r(`pattern`):e===`ls`||e===`edit`||e===`write`?r(`path`):void 0;if(typeof i==`string`)return i}try{let e=JSON.stringify(t).replace(/\n/g,` `);return e.length>40?`${e.slice(0,39)}…`:e}catch{return String(t).slice(0,40)}}const Yr={running:{text:()=>`running`,themeSlot:`muted`},ok:{text:e=>e.durationMs===void 0?`ok`:`ok ${br(e.durationMs)}`,themeSlot:`accent`},error:{text:e=>`failed: ${e.errorMessage??`error`}`,themeSlot:`error`},cancelled:{text:()=>`cancelled`,themeSlot:`muted`},rejected:{text:e=>`rejected: ${e.errorMessage??`concurrency`}`,themeSlot:`warning`}};function Xr(e,t){if(e.length===0)return[];let n=e.slice(0,32),r=e.length>32?e.length-32:0,i=[];return n.forEach((e,a)=>{let o=a===n.length-1&&r===0?`└─ `:`├─ `,s=e.name.length>=8?`${e.name} `:e.name.padEnd(8),c=Jr(e.name,e.args),l=Yr[e.status];i.push({left:` ${o}${t.fg(`toolTitle`,s)}${t.fg(l.themeSlot,l.text(e))}${t.fg(`dim`,` `+c)}`})}),r>0&&i.push({left:` └─ …+${r} more calls`}),i}function Zr(e,t,n,r=!1,i=!1){let a=wr(e.details,n),o=e=>a===void 0?e:{...e,right:a};if(t)return[o({left:` ${n.fg(`error`,`failed: ${qr(e)}`)}`})];if(i&&e.details?.result===void 0)return[];let s=e.details?.result;if(s===void 0)return[o({left:` ${n.fg(`muted`,`done`)}`})];if(Dr(s))return Pr(s,{maxDepth:4,maxChildren:6,maxLineChars:120,moreAfter:r}).map((e,t)=>{let n={left:` ${e}`};return t===0&&a!==void 0?{...n,right:a}:n});let c=Cr(s);return c===void 0?[o({left:` ${n.fg(`muted`,`done`)}`})]:[o({left:` ${n.fg(`dim`,`→ ${c}`)}`})]}function Qr(e,t,n,r={}){let i=Tr(e.details),a=[...Zr({...e,details:i},t,n,!1,r.isPartial===!0)];return i?.subCalls!==void 0&&a.push(...Xr(i.subCalls,n)),new _r(a)}function $r(e,t,n,r,i={}){let a=Tr(e.details);if(n){let t=[...Zr({...e,details:a},!0,r)];a?.subCalls!==void 0&&t.push(...Xr(a.subCalls,r));let n=U(e.content?.find(e=>e.type===`text`)?.text??qr(e));for(let e of n.split(`
36
+ `).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new _r(t)}let o=[],s=t.code??t.script??``;if(s.length>0){let e=s.split(`
37
+ `).map(e=>G(e,120)),t=e.slice(0,3);o.push({label:`code`,lines:t,...e.length>t.length?{more:e.length-t.length}:{}})}if(a!==void 0&&a.surface===`workflow`&&a.phases.length>0){let e=a.phases.slice(0,8),t=a.phases.length-e.length,n=t>0?` …+${t} more phases`:``;o.push({label:`phases`,lines:[`${e.join(` → `)}${n}`]})}if(a!==void 0&&a.narrations.length>0){let e=a.narrations.slice(0,12);o.push({label:`log`,lines:e.map(e=>U(e)),...a.narrations.length>e.length?{more:a.narrations.length-e.length}:{}})}if(a!==void 0&&a.logs.length>0){let e=a.logs.slice(0,12);o.push({label:`out`,lines:e.map(e=>U(e)),...a.logs.length>e.length?{more:a.logs.length-e.length}:{}})}if(a!==void 0&&a.warnings.length>0){let e=a.warnings.slice(0,4);o.push({label:`warn`,lines:e.map(e=>U(e)),...a.warnings.length>e.length?{more:a.warnings.length-e.length}:{}})}if(a!==void 0&&a.imageCount>0){let e=a.imageCount===1?`1 image attached`:`${a.imageCount} images attached`;o.push({label:`image`,lines:[e]})}let c=a?.subCalls,l=c!==void 0&&c.length>0||o.length>0,u=Zr({...e,details:a},!1,r,l,i.isPartial===!0);c!==void 0&&u.push(...Xr(c,r));for(let e=0;e<o.length;e+=1){let t=e===o.length-1;u.push(...Er(o[e]??{label:``,lines:[]},t,r))}return new _r(u)}function ei(e){return{renderCall(t,n,r){return Gr(t,n,e,{...r?.invalidate===void 0?{}:{requestInvalidate:r.invalidate},...r?.isPartial===void 0?{}:{isPartial:r.isPartial},...r?.state===void 0?{}:{state:r.state}})},renderResult(e,t,n,r){let i=t.isPartial===!0;return t.expanded===!0?$r(e,r?.args??{},r?.isError===!0,n,{isPartial:i}):Qr(e,r?.isError===!0,n,{isPartial:i})}}}const ti=["Run a TypeScript program that composes pi's tools in one shot. Required arguments: `code` —","the body of an async function (top-level `return` and `await` work; type annotations are","advisory, the code runs type-stripped) — and `description`, a 5-10 word summary of what the",`program does.`,``,"Inside the program, call this session's enabled built-in tools as `tools.<name>(args)` — e.g.",'`await tools.read({ path: "src/index.ts" })`.',`The bound names are this session's active built-in tools, less any binding the install has not`,`explicitly opted in — this surface is narrower than the session's tool list on purpose;`,"independent calls may overlap under `Promise.all`.",``,"The parallel binding `pi.dispatch` is always available, registered under its literal dot name —",'call it with string indexing, e.g. `await tools["pi.dispatch"]({ agent: "reviewer", task: "..." })`;',"`tools.pi.dispatch` does not exist. It fans work out to child pi agents, and independent","foreground dispatches compose under `Promise.all` exactly like the built-in calls. The run's","actual bound names (this run, not a static list) are on the `ptcBindings` global, so the program",`never has to guess what is bound.`,``,Pn,``,"Only the program's return value and its `console.log` output come back. This surface has no","helpers: `log` / `phase` / `parallel` / `pipeline` exist only in `ptc_workflow`.",``,"Image-bearing tool results inside the program (a `tools.read` on a PNG, say) are attached to you",`after the run, so never return image data as the completion value — that only spends your context`,`on base64.`].join(`
38
+ `),ni=x.Object({code:x.String({description:`The program: the body of an async TypeScript function.`}),description:x.String({description:`Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI).`}),timeoutMs:x.Optional(x.Number({description:`Elapsed deadline in milliseconds for the whole run, including tool calls. Omit it (or pass 0) for the default of ${L.timeoutMs/1e3} s; anything above ${L.maxTimeoutMs/1e3} s is capped. The deadline bounds the whole run: if it expires, in-flight foreground dispatches spawned by the program are terminated with it.`}))});function ri(e={}){return I({name:`ptc_run_code`,label:`PTC Run Code`,exposure:e.exposure,description:ti,promptSnippet:`Run a TypeScript program that composes pi's tools in one shot (tools.<name>(args)); only its return value and console.log come back`,promptGuidelines:[...$n],parameters:ni,async execute(t,n,r,i,a){let o=tr(a),s=W(e.getBindingSourceNames?.(),e.getOptInBindings?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=nr({surface:`run_code`,startedAt:c,onUpdate:i}),p;try{p=await jn({code:n.code,surface:`run_code`,cwd:o,bindings:_n({cwd:o,names:s,includeDispatch:!0}),...u===void 0?{}:{sessionDir:u},...d===void 0?{}:{dispatchDeps:d},...e.depth===void 0?{}:{depth:e.depth},...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...n.timeoutMs===void 0?{}:{timeoutMs:n.timeoutMs},...r===void 0?{}:{signal:r},...e.config===void 0?{}:{config:e.config},...l===void 0?{}:{pool:l},onSubCallChange:e=>f.update(e)})}finally{f.cancel()}if(p.error!==void 0)throw ir(p);return ar({outcome:p,surface:`run_code`,durationMs:Date.now()-c})},...ei(`run_code`)})}const ii=[`Run a structured TypeScript workflow: a named plan that reports phases and narration as it`,"goes. `script` is the body of an async function, `meta` names it (`{ name, description, phases? }`,","where `phases` is the ordered plan), and optional `args` is plain-JSON input bound to the","program's `args` global.",``,"Helpers inside the script: `log(message)` narrates progress; `phase(title)` frames the workflow","(titles outside `meta.phases` are reported as warnings); `parallel(thunks)` runs thunks","concurrently, a failed item becoming `null`; `pipeline(items, ...stages)` chains stages per item","with the same per-item `null` on failure. There is no `agent()` helper.",``,"Tools are reachable as `tools.<name>(args)` exactly as in `ptc_run_code`, and the bound names",`are this session's enabled built-ins less any binding the install has not opted in. The parallel`,"binding `pi.dispatch` is always available under",'its literal dot name — call it with string indexing: `await tools["pi.dispatch"]({ agent, task })`;',"the run's actual bound names are on the `ptcBindings` global. What comes back is the script's","return value, its `log`/`phase` narration and its `console.log` output.",``,Pn,``,`Image-bearing tool results inside the script are attached to you after the run — never return`,`image data as the script's value.`].join(`
39
+ `),ai=x.Object({meta:x.Object({name:x.String({description:`Short workflow name, shown in the UI.`}),description:x.String({description:`What this workflow does, in active voice.`}),phases:x.Optional(x.Array(x.Object({name:x.String({description:`Phase title, matched against phase(title) calls.`})}),{description:`Ordered plan of the workflow's phases. phase() titles outside this list are reported as warnings.`}))},{description:`Workflow metadata: what this run is and which phases it declares.`}),script:x.String({description:`The program: the body of an async TypeScript function.`}),args:x.Optional(x.Record(x.String(),x.Unknown(),{description:"Plain-JSON input bound to the program's `args` global. No functions, symbols, undefined values or cycles."}))});function oi(t){if(t!==void 0){if(typeof t!=`object`||!t||Array.isArray(t))throw TypeError(`ptc_workflow args must be a plain JSON object, received ${e(t)}`);for(let e of Object.keys(t)){let n=si(t[e],`args.${e}`,/* @__PURE__ */ new Set);if(n!==void 0)throw TypeError(`ptc_workflow args must be plain JSON: ${n}`)}}}function si(t,n,r){if(t===null||typeof t==`string`||typeof t==`boolean`)return;if(t===void 0)return`${n} is undefined`;if(typeof t==`number`)return Number.isFinite(t)?void 0:`${n} is ${String(t)}, which is not representable as JSON`;if(typeof t!=`object`)return`${n} is ${e(t)}`;let i=t;if(r.has(i))return`${n} is a circular reference`;r.add(i);try{if(Array.isArray(i)){for(let e=0;e<i.length;e+=1){let t=si(i[e],`${n}[${e}]`,r);if(t!==void 0)return t}return}let e=Object.getPrototypeOf(i);if(e!==Object.prototype&&e!==null){let e=i.constructor?.name;return`${n} is a ${typeof e==`string`&&e.length>0?e:`non-plain object`}, not plain JSON`}for(let e of Object.keys(i)){let t=si(i[e],`${n}.${e}`,r);if(t!==void 0)return t}return}finally{r.delete(i)}}function ci(e,t){if(t===void 0||t.length===0)return[];let n=new Set(t),r=/* @__PURE__ */ new Set,i=[];for(let t of e.phases)n.has(t)||r.has(t)||(r.add(t),i.push(`phase "${t}" is not listed in meta.phases (declared: ${[...n].join(`, `)})`));return i}function li(e={}){return I({name:`ptc_workflow`,label:`PTC Workflow`,exposure:e.exposure,description:ii,promptSnippet:`Run a structured TypeScript workflow with named phases, narration (log/phase) and structured concurrency (parallel/pipeline)`,promptGuidelines:[...$n],parameters:ai,async execute(t,n,r,i,a){oi(n.args);let o=tr(a),s=W(e.getBindingSourceNames?.(),e.getOptInBindings?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=nr({surface:`workflow`,startedAt:c,onUpdate:i}),p;try{p=await jn({code:n.script,surface:`workflow`,cwd:o,bindings:_n({cwd:o,names:s,includeDispatch:!0}),...u===void 0?{}:{sessionDir:u},...d===void 0?{}:{dispatchDeps:d},...n.args===void 0?{}:{args:n.args},...e.depth===void 0?{}:{depth:e.depth},...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...r===void 0?{}:{signal:r},...e.config===void 0?{}:{config:e.config},...l===void 0?{}:{pool:l},onSubCallChange:e=>f.update(e)})}finally{f.cancel()}if(p.error!==void 0)throw ir(p);let m=n.meta.phases?.map(e=>e.name);return ar({outcome:p,surface:`workflow`,warnings:ci(p,m),durationMs:Date.now()-c})},...ei(`workflow`)})}var ui=class{#e;constructor(e){this.#e=new Map(e??[])}async readOutput(e){let t=this.#e.get(e);return t===void 0?null:t}async writeOutput(e,t){this.#e.set(e,t)}outputRef(e){return`memory:tasks/${e}/output.log`}};function di(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}var fi=class{#e;constructor(e){if(e.length===0)throw TypeError(`FileOutputStorage: baseDir is required`);this.#e=e}async readOutput(e){try{return await ge(this.#t(e),`utf8`)}catch(e){if(di(e))return null;throw e}}async writeOutput(e,t){let n=j(this.#e,`tasks`,e);await he(n,{recursive:!0}),await be(j(n,`output.log`),t,`utf8`)}outputRef(e){return this.#t(e)}#t(e){return j(this.#e,`tasks`,e,`output.log`)}};function pi(e,t){return Rn(e,`pi-ptc-task-output-`,t===void 0?{}:{fullText:t})}const mi={running:`accent`,stopping:`warning`,succeeded:`success`,failed:`error`,lost:`dim`,canceled:`muted`},hi={running:`●`,stopping:`◐`,succeeded:`✓`,failed:`✗`,lost:`◌`,canceled:`⊘`};var q=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>gi(e,t))}};function gi(e,t){let{left:n,right:r}=e;if(r===void 0)return P(n,t,`…`);let i=F(r);if(i>=t)return P(r,t,`…`);let a=P(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-F(a));return a+` `.repeat(o)+r}function _i(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function vi(e){return _i((U(e).split(`
40
+ `).find(e=>e.trim().length>0)??``).trim(),120)}function yi(e){return typeof e==`object`&&e?e:{}}function bi(e){return e===`running`||e===`stopping`}function xi(e){let t=Math.max(0,Math.floor(e));if(t<1e3)return`${t}ms`;let n=Math.floor(t/1e3);if(n<60)return`${n}s`;let r=Math.floor(n/60),i=n%60;return r<60?`${r}m${i}s`:`${Math.floor(r/60)}h${String(r%60).padStart(2,`0`)}m`}function Si(e,t){if(bi(e.status))return xi(t-e.createdAt);if(e.durationMs!==void 0)return xi(e.durationMs);if(e.finishedAt!==void 0)return xi(e.finishedAt-e.createdAt)}function Ci(e,t){let{state:n}=t;t.isLive?n.interval??=setInterval(()=>t.requestInvalidate(),1e3):n.interval!==void 0&&(clearInterval(n.interval),n.interval=void 0);let r=e;return r.dispose=()=>{n.interval!==void 0&&(clearInterval(n.interval),n.interval=void 0)},e}function wi(){}function Ti(e,t,n){return new q([{left:`└─ ${n.fg(`toolTitle`,n.bold(e))}${t.length>0?` ${t}`:``}`}])}function Ei(e,t,n){let r=yi(t);switch(e){case`task-list`:{let e=Array.isArray(r.status)?r.status:void 0,t=e!==void 0&&e.length>0?e.join(`,`):`all`,i=typeof r.limit==`number`?` · limit=${r.limit}`:``;return Ti(`PTC task list`,n.fg(`dim`,`status=${t}${i}`),n)}case`task-output`:{let e=typeof r.taskId==`string`&&r.taskId.length>0?r.taskId:void 0,t=typeof r.sinceBytes==`number`?` · since=${r.sinceBytes}B`:``;return Ti(`PTC task output`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}case`task-stop`:{let e=typeof r.taskId==`string`&&r.taskId.length>0?r.taskId:void 0,t=typeof r.reason==`string`&&r.reason.length>0?` · reason=${U(r.reason)}`:``;return Ti(`PTC task stop`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}}}function Di(e,t,n,r){let i=mi[e.status]??`muted`,a=n.fg(i,hi[e.status]??`?`),o=_i(U(e.label),48),s=[`${a} ${n.fg(`text`,o)}`,n.fg(`dim`,U(e.agentName))],c=Si(e,r);return c!==void 0&&s.push(n.fg(`dim`,c)),e.outputBytes!==void 0&&s.push(n.fg(`dim`,`${e.outputBytes}B`)),{left:` ${t?`└─ `:`├─ `}${s.join(n.fg(`dim`,` · `))}`}}function Oi(e,t){let n=yi(e),r=Array.isArray(n.tasks)?n.tasks:[];if(r.length===0)return Ci(new q([{left:` ${t.theme.fg(`muted`,`(no background tasks)`)}`}]),{isLive:!1,state:t.state,requestInvalidate:t.requestInvalidate});let i=r.some(e=>bi(e.status)),a=r.slice(0,32),o=r.length-a.length,s=a.map((e,n)=>Di(e,n===a.length-1&&o===0,t.theme,t.now));return o>0&&s.push({left:` └─ ${t.theme.fg(`dim`,`…+${o} more tasks`)}`}),Ci(new q(s),{isLive:t.partial&&i,state:t.state,requestInvalidate:t.requestInvalidate})}function ki(e,t,n){let r=[];if(e!==void 0&&r.push(n.fg(`dim`,`${e}B`)),t&&r.push(n.fg(`warning`,`truncated`)),r.length!==0)return`${n.fg(`dim`,`•`)} ${r.join(n.fg(`dim`,` · `))}`}function Ai(e,t){return` ${t.fg(`dim`,`full output: `)}${t.fg(`accent`,e)}`}function ji(e,t){let n=yi(e),r=typeof n.output==`string`?n.output:``,i=typeof n.outputBytes==`number`?n.outputBytes:void 0,a=n.outputTruncated===!0,o=typeof n.outputFullPath==`string`&&n.outputFullPath.length>0?n.outputFullPath:void 0,s=ki(i,a,t.theme),c=[];if(r.length>0){let e=U(r).split(`
41
+ `),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,_i(e,160));c.push(n===0&&s!==void 0?{left:` ${r}`,right:s}:{left:` ${r}`})}),e.length>n.length&&c.push({left:` ${t.theme.fg(`dim`,`…+${e.length-n.length} more lines`)}`}),a&&o!==void 0&&c.push({left:Ai(o,t.theme)})}else o===void 0?c.push({left:` ${t.theme.fg(`muted`,`(no output yet)`)}`,...s===void 0?{}:{right:s}}):c.push({left:Ai(o,t.theme),...s===void 0?{}:{right:s}});return new q(c)}function Mi(e,t){let n=yi(e),r=n.task;if(typeof r!=`object`||!r)return new q([{left:` ${t.theme.fg(`muted`,`(no task)`)}`}]);let i=mi[r.status]??`muted`,a=t.theme.fg(i,hi[r.status]??`?`),o=typeof n.fromStatus==`string`?n.fromStatus:void 0,s=o===void 0?r.status===`stopping`?`running → stopping`:`→ ${String(r.status)}`:`${o} → ${r.status}`,c=[`${a} ${t.theme.fg(`text`,U(r.id))}`,t.theme.fg(i,s)];return typeof r.stopReason==`string`&&r.stopReason.length>0&&c.push(t.theme.fg(`dim`,`reason=${U(r.stopReason)}`)),new q([{left:` ${c.join(` `)}`}])}function Ni(e,t){let n=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0),r=vi(n?.text??``)||`failed`;return new q([{left:` ${t.fg(`error`,`failed: ${r}`)}`}])}function Pi(e,t,n){switch(e){case`task-list`:return Oi(t.details,n);case`task-output`:return ji(t.details,n);case`task-stop`:return Mi(t.details,n)}}function Fi(e){return{renderCall(t,n){return Ei(e,t,n)},renderResult(t,n,r,i){return i?.isError===!0?Ni(t,r):Pi(e,t,{theme:r,partial:n?.isPartial===!0||i?.isPartial===!0,requestInvalidate:i?.invalidate??wi,state:i?.state??{},now:Date.now()})}}}const Ii=[`Use ptc_task_list to see the background tasks this session dispatched and their live status.`,`Use ptc_task_output to read a task's captured output (it is tail-truncated; the footer names the full-output file). A succeeded task's child report is rendered there, ahead of the prose.`,`Use ptc_task_stop to ask a running task to stop; the dispatcher delivers the actual signal, so the task transitions through stopping to canceled.`,`These background-task tools stay callable when PTC mode is off — /ptc off only blocks new dispatches.`],Li=x.Union([x.Literal(`running`),x.Literal(`stopping`),x.Literal(`succeeded`),x.Literal(`failed`),x.Literal(`canceled`),x.Literal(`lost`)]),Ri=x.Object({status:x.Optional(x.Array(Li,{description:`Only return tasks in these states. Omit for all six states (running, stopping, succeeded, failed, canceled, lost).`})),limit:x.Optional(x.Number({description:`Maximum number of tasks to return, newest first. Defaults to 100.`}))}),zi=x.Object({tasks:x.Array(x.Object({id:x.String({description:`The task's ULID — the id ptc_task_output and ptc_task_stop take.`}),status:x.String({description:`One of running, stopping, succeeded, failed, canceled, lost (ADR-0022 §2).`}),agent:x.String({description:`The agent the task was dispatched with (the record's agentName).`}),depth:x.Number({description:`0 for a direct child of the session, 1 for a grandchild, and so on (ADR-0016).`}),label:x.String({description:`The label the task was dispatched with.`}),output_bytes:x.Optional(x.Number({description:`Captured output size; absent while the task has flushed no output.`})),error_message:x.Optional(x.String({description:`Failure text; absent unless the record carries an error.`}))}),{description:`One row per task, newest first — the same order as details.tasks.`}),count:x.Number({description:"Number of rows in `tasks`."})});function Bi(e){return{id:e.id,status:e.status,agent:e.agentName,depth:e.depth,label:e.label,...e.outputBytes===void 0?{}:{output_bytes:e.outputBytes},...e.errorMessage===void 0?{}:{error_message:e.errorMessage}}}function Vi(e){let t=[e.id,e.status,`${e.agentName} depth=${e.depth}`,U(e.label)];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.errorMessage!==void 0&&t.push(`error=${U(e.errorMessage)}`),t.join(` `)}function Hi(e){return I({name:`ptc_task_list`,label:`PTC Task List`,description:[`List the background tasks this session has dispatched (from pi.dispatch({ background: true })).`,`Returns each task's id, status, agent, depth, label and output size, newest first.`,`Filter with status (e.g. ["running"]); limit caps the row count (default 100).`].join(`
42
+ `),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...Ii],parameters:Ri,outputSchema:zi,async execute(t,n){let r=await e.query({...n.status===void 0?{}:{status:n.status},limit:n.limit??100,orderBy:`createdAt-desc`}),i=r.length===0?`(no background tasks)`:r.map(e=>Vi(e)).join(`
43
+ `),a={tasks:r.map(e=>Bi(e)),count:r.length};return{content:[{type:`text`,text:i}],details:{tasks:r,count:r.length},structuredContent:a}},...Fi(`task-list`)})}async function Ui(e,t,n){let r=await e.get(t);if(r===null)throw Error(`${n}: unknown taskId ${t}`);return r}function Wi(e){return{input:e.input,output:e.output,cost:e.cost,turns:e.turns}}function Gi(e){return`usage: input=${String(e.input)} output=${String(e.output)} cost=${String(e.cost)} turns=${String(e.turns)}`}function Ki(e,t,n){let r=`<child-report channel="${e}">${t}`;return n===void 0?`${r}</child-report>`:`${r}\n${Gi(n)}\n</child-report>`}function qi(e){let t=e.reportChannel;if(t===void 0)return;let n=e.usage===void 0?void 0:Wi(e.usage);if(t===`none`)return Ki(t,`the child produced no report; it did not comply with the report contract. What follows is its prose, unbacked by a report.`,n);if(t===`opted-out`)return Ki(t,`this agent opts out of the report contract, so none was asked for; the prose below is the whole of what it produced, and nothing is missing.`,n);let r=e.report;if(r===void 0)return Ki(t,`the record names channel ${t} but carries no report.`,n);let i=[`<child-report channel="${t}">`,`summary: ${r.summary}`],a=r.findings.slice(0,20),o=r.findings.length-a.length;i.push(`findings (${String(r.findings.length)}):`);for(let[e,t]of a.entries())i.push(` ${String(e+1)}. ${t.what} — evidence: ${t.evidence}`);return o>0&&i.push(` …+${String(o)} more findings not shown`),i.push(r.files_touched.length===0?`files_touched: (none)`:`files_touched: ${r.files_touched.join(`, `)}`),i.push(Gi(r.usage)),i.push(`</child-report>`),i.join(`
44
+ `)}const Ji=x.Object({taskId:x.String({description:`The background task's id (as returned by ptc_task_list or the dispatch handle).`}),sinceBytes:x.Optional(x.Number({description:`Skip this many bytes of the stored output before returning it. Use for paging larger logs; defaults to 0.`}))}),Yi=x.Object({task_id:x.String({description:`The background task id that was asked for.`}),status:x.String({description:`The task's status at read time (ADR-0022 §2's six states), so a polling script does not need a second ptc_task_list call.`}),output:x.String({description:`The page the model reads: the stored output's tail, ADR-0015-truncated.`}),output_bytes:x.Number({description:`Total bytes stored for the task, regardless of sinceBytes or ADR-0015 truncation.`}),output_preview:x.Optional(x.String({description:`The complete stored output; present only at or below the 2048-byte preview ceiling (ADR-0022 §7).`})),output_truncated:x.Boolean({description:"Whether ADR-0015 cut anything out of `output`."}),output_full_path:x.Optional(x.String({description:"A file holding the complete output; present only when `output_truncated` is true (ADR-0015 §2)."})),report_channel:x.Optional(x.String({description:"Which channel delivered the child's report: `tool`, `prompt-json`, or `none` when the child ignored the contract (ADR-0032). Absent until the task succeeds — a running or failed task carries no report claim at all."})),read_only_tier:x.Optional(x.String({description:"The read-only tier the dispatch resolved to: `strict` or `lenient` (ADR-0041). Absent when the dispatch asked for no tier. Present from spawn onwards, including for a task that later failed — a failed read-only child was still dispatched read-only."})),report:x.Optional(x.Object({summary:x.String({description:`The child's own one-line summary.`}),findings:x.Array(x.Object({what:x.String({description:`The claim the child makes.`}),evidence:x.String({description:`The evidence that claim rests on.`})}),{description:`One entry per claim the child made.`}),files_touched:x.Array(x.String(),{description:`Paths the child says it touched.`}),usage:x.Object({input:x.Number({description:`Host-observed input tokens (never the child's claim).`}),output:x.Number({description:`Host-observed output tokens.`}),cost:x.Number({description:`Host-observed cost.`}),turns:x.Number({description:`Host-observed assistant turns.`})})})),usage:x.Optional(x.Object({input:x.Number({description:`Host-observed input tokens (never the child's claim).`}),output:x.Number({description:`Host-observed output tokens.`}),cost:x.Number({description:`Host-observed cost.`}),turns:x.Number({description:`Host-observed assistant turns.`})},{description:"The host's own count for this child, in the same four fields `report.usage` carries (ADR-0032, issue #199). ABSENT when no top-level count was recorded: a `running` / `stopping` task has not closed yet, a `lost` record was never observed closing, and a record written before the field existed carries none — a pre-change record that has a report still renders the report's own host-stamped numbers. Present on every close outcome including `failed` and `canceled`, and independent of `report_channel` — so a child that reported nothing still accounts for what it cost. The text block states the same four numbers on the `usage: …` line."}))});function Xi(e,t){return I({name:`ptc_task_output`,label:`PTC Task Output`,description:[`Read a background task's captured output.`,`A succeeded task also renders its child report (summary, findings, files touched, usage) ahead of the prose, and says which channel delivered it; a channel of "none" means the child ignored the report contract.`,`The text is tail-truncated to pi's ADR-0015 limits (50 KB / 2000 lines); when anything is cut, outputFullPath names a file with the complete output.`,`Pass sinceBytes to skip a prefix of the stored output when paging.`].join(`
45
+ `),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...Ii],parameters:Ji,outputSchema:Yi,async execute(n,r){let i=r.taskId,a=await Ui(e,i,`ptc_task_output`),o=await t.readOutput(i)??``,s=Buffer.byteLength(o,`utf8`),c=r.sinceBytes??0;if(!Number.isInteger(c)||c<0)throw Error(`ptc_task_output: sinceBytes must be a non-negative integer, got ${String(r.sinceBytes)}`);if(c>s)throw Error(`ptc_task_output: sinceBytes ${c} exceeds the ${s}-byte output of task ${i}`);let l=Buffer.from(o,`utf8`);if(c<s&&((l[c]??0)&192)==128)throw Error(`ptc_task_output: sinceBytes ${c} splits a UTF-8 character in task ${i}; use a byte offset on a character boundary`);let u=pi(c===0?o:l.subarray(c).toString(`utf8`),o),d=s<=2048?o:void 0,f=qi(a),p=a.usage===void 0?void 0:Wi(a.usage),m={taskId:i,output:u.text,outputBytes:s,...d===void 0?{}:{outputPreview:d},outputTruncated:u.truncated,...u.fullPath===void 0?{}:{outputFullPath:u.fullPath},...a.report===void 0?{}:{report:a.report},...a.reportChannel===void 0?{}:{reportChannel:a.reportChannel},...a.readOnlyTier===void 0?{}:{readOnlyTier:a.readOnlyTier}},h=m.output.length>0?m.output:`(no output yet; task ${i} is ${a.status})`,g=f??(p===void 0?void 0:Gi(p)),_=g===void 0?h:`${g}\n${h}`,v=sr(a.readOnlyTier),y=v.length===0?_:`${v}\n${_}`,b={task_id:i,status:a.status,output:u.text,output_bytes:s,...d===void 0?{}:{output_preview:d},output_truncated:u.truncated,...u.fullPath===void 0?{}:{output_full_path:u.fullPath},...a.reportChannel===void 0?{}:{report_channel:a.reportChannel},...a.readOnlyTier===void 0?{}:{read_only_tier:a.readOnlyTier},...a.report===void 0?{}:{report:a.report},...p===void 0?{}:{usage:p}};return{content:[{type:`text`,text:y}],details:m,structuredContent:b}},...Fi(`task-output`)})}const Zi=x.Object({taskId:x.String({description:`The running task's id (as returned by ptc_task_list or the dispatch handle).`}),reason:x.Optional(x.String({description:`Why the task is being stopped; recorded as the task's stopReason. Defaults to "model stop".`}))}),Qi=x.Object({task_id:x.String({description:`The background task id that was asked to stop.`}),status:x.String({description:"The task's status AFTER the stop command — `stopping`, not the terminal `canceled`; the dispatcher pump owns the latter (ADR-0022 §8)."}),from_status:x.String({description:"The status observed before the stop: `running` for a fresh stop, `stopping` for the idempotent late-arrival path (ADR-0022 §8)."}),stop_reason:x.Optional(x.String({description:`The reason recorded as the task's stopReason; absent when the record carries none.`}))});function $i(e,t,n={}){if(t==null)throw TypeError(`createPtcTaskStopTool: lifecycle is required`);let r=n.clock??(()=>Date.now());return I({name:`ptc_task_stop`,label:`PTC Task Stop`,description:[`Ask a running background task to stop.`,`The task moves to "stopping"; the dispatcher sends the signal and records the terminal "canceled" state when the child exits.`,`The call is idempotent when the task is already stopping, and errors when the task is already terminal.`].join(`
46
+ `),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...Ii],parameters:Zi,outputSchema:Qi,async execute(t,n){let i=n.taskId,a=await Ui(e,i,`ptc_task_stop`),o=a.spawnSource.callerId.length>0?a.spawnSource.callerId:`ptc_task_stop`,{record:s,fromStatus:c}=await e.transition({kind:`stop`,taskId:i,reason:n.reason??`model stop`},{clock:r,callerId:o}),l=s.stopReason===void 0?``:` reason=${U(s.stopReason)}`,u=c??a.status,d={task_id:i,status:s.status,from_status:u,...s.stopReason===void 0?{}:{stop_reason:s.stopReason}};return{content:[{type:`text`,text:`${s.id} ${s.status}${l}`}],details:{task:s,fromStatus:u},structuredContent:d}},...Fi(`task-stop`)})}var ea=class{#e;#t=/* @__PURE__ */ new Map;constructor(e={}){this.#e=Be(e.config)}get(e){let t=this.#t.get(e);if(t!==void 0)return t;let n=ze(),r=new Sn({buildWorkerUrl:Tn,size:this.#e.poolSize,acquireTimeoutMs:this.#e.poolAcquireTimeoutMs,drainGraceMs:this.#e.drainGraceMs,workerOptions:yn({surface:e,env:n,limits:this.#e})});return this.#t.set(e,r),r}async drain(){let e=[...this.#t.values()];this.#t.clear(),await Promise.all(e.map(e=>e.drain()))}};const ta={warn:e=>{console.warn(`[pi-ptc.notifications] `+e)}};var na=class{#e;#t;#n;#r;#i;constructor(e,t={}){this.#e=e,this.#t=t.now??Date.now,this.#n=t.logger??ta,this.#r=[],this.#i=/* @__PURE__ */ new Map}async subscribe(e,t,n){let r=await this.#e.loadSubscription(e,t);if(r!==null)return r;let i={subscriberId:e,taskId:t,cursor:n??`00000000000000000000`,status:`active`,createdAt:this.#t()};return await this.#e.saveSubscription(i),i}async drainPending(e,t){let n=await this.#o(e,t,`drainPending`);return this.#s(n)}async acknowledgeEvents(e,t,n){await this.#a(e,t,async()=>{let r=await this.#o(e,t,`acknowledgeEvents`);n<=r.cursor||await this.#e.saveSubscription({...r,cursor:n})})}#a(e,t,n){let r=`${e}-${t}`,i=(this.#i.get(r)??Promise.resolve()).then(n),a=i.then(()=>void 0,()=>void 0);return this.#i.set(r,a),a.then(()=>{this.#i.get(r)===a&&this.#i.delete(r)}),i}onIdleWake(e){this.#r.push(e)}async pendingCount(e,t){let n=await this.#o(e,t,`pendingCount`);return(await this.#s(n)).length}async notifyIdle(e,t){let n=await this.drainPending(e,t);if(n.length===0)return n;let r=this.#r.slice();for(let i of r)try{i(e,n)}catch(n){let r=n instanceof Error?n.message:String(n);this.#n.warn(`notifyIdle: idle-wake handler for subscriber ${e} / task ${t} threw: ${r}`)}return n}async#o(e,t,n){let r=await this.#e.loadSubscription(e,t);if(r===null)throw Error(`${n}: unknown subscription for subscriber ${e} / task ${t}`);return r}async#s(e){let t=[];for await(let n of this.#e.loadEvents(e.subscriberId,e.cursor===`00000000000000000000`?void 0:e.cursor))n.taskId===e.taskId&&t.push(n);return t}};const ra={mkdir:(e,t)=>he(e,t),readFile:(e,t)=>ge(e,t),writeFile:(e,t,n)=>be(e,t,n),appendFile:(e,t,n)=>me(e,t,n),rename:(e,t)=>ve(e,t),unlink:e=>ye(e),readdir:e=>_e(e)};function ia(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}function aa(e){return e instanceof Error?e.message:String(e)}function oa(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}var sa=class{#e;#t;constructor(e,t={}){if(e.length===0)throw TypeError(`FileTaskStorage: baseDir is required`);this.#e=e,this.#t=t.fs??ra}async loadTask(e){return await this.#r(this.#f(e))}async saveTask(e){N(e,`saveTask: record is required`),await this.#o(this.#f(e.id),e)}async deleteTask(e){let t=this.#f(e);if(!await this.#c(t))throw Error(`deleteTask: unknown taskId `+e);await this.#t.unlink(t)}async*listTasks(e){let t=this.#l();for(let n of(await this.#s(t)).sort()){if(!n.endsWith(`.json`))continue;let r=await this.#r(j(t,n));r!==null&&(e?.status===void 0||r.status===e.status)&&(e?.label===void 0||r.label===e.label)&&(yield r)}}async loadSubscription(e,t){return await this.#r(this.#p(e,t))}async saveSubscription(e){N(e,`saveSubscription: sub is required`),await this.#o(this.#p(e.subscriberId,e.taskId),e)}async appendEvents(e,t){if(t.length===0){if((await this.#n(e)).length===0)throw Error(`appendEvents: unknown subscriptionId `+e);return}let n=/* @__PURE__ */ new Map;for(let e of t){let t=n.get(e.taskId);t===void 0?n.set(e.taskId,[e]):t.push(e)}let r;for(let t of n.keys())if(await this.loadSubscription(e,t)===null){r=t;break}if(r!==void 0)throw(await this.#n(e)).length===0?Error(`appendEvents: unknown subscriptionId `+e):Error(`appendEvents: no subscription for subscriber `+e+` on task `+r);await this.#t.mkdir(this.#d(),{recursive:!0});for(let[t,r]of n){let n=(r.every((e,t)=>t===0||oa(r[t-1],e)<=0)?r:[...r].sort(oa)).map(e=>JSON.stringify(e)).join(`
47
47
  `)+`
48
- `;await this.#t.appendFile(this.#m(e,t),n,{encoding:`utf8`})}}async*loadEvents(e,t){let n=await this.#n(e);if(n.length===0)throw Error(`loadEvents: unknown subscriptionId `+e);let r=[];for(let t of n)r.push(...await this.#a(this.#m(e,t.taskId)));r.sort(Ji);for(let e of r)t!==void 0&&e.eventId<=t||(yield e)}async#n(e){let t=this.#u(),n=[];for(let r of await this.#s(t)){if(!r.endsWith(`.json`))continue;let i=await this.#r(A(t,r));i!==null&&i.subscriberId===e&&n.push(i)}return n}async#r(e){let t;try{t=await this.#t.readFile(e,{encoding:`utf8`})}catch(e){if(Ki(e))return null;throw e}return this.#i(e,t)}#i(e,t){let n;try{n=JSON.parse(t)}catch(t){throw Error(`FileTaskStorage: corrupt JSON in `+e+`: `+qi(t))}if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`FileTaskStorage: corrupt JSON in `+e+`: expected a JSON object`);return n}async#a(e){let t;try{t=await this.#t.readFile(e,{encoding:`utf8`})}catch(e){if(Ki(e))return[];throw e}let n=[];for(let r of t.split(`
49
- `)){let t=r.trim();if(t.length===0)continue;let i;try{i=JSON.parse(t)}catch(t){throw Error(`FileTaskStorage: corrupt event JSON in `+e+`: `+qi(t))}if(typeof i!=`object`||!i||Array.isArray(i))throw Error(`FileTaskStorage: corrupt event JSON in `+e+`: expected a JSON object`);n.push(i)}return n}async#o(e,t){await this.#t.mkdir(k(e),{recursive:!0});let n=e+`.tmp-`+ce();await this.#t.writeFile(n,JSON.stringify(t,null,2),{encoding:`utf8`}),await this.#t.rename(n,e)}async#s(e){try{return await this.#t.readdir(e)}catch(e){if(Ki(e))return[];throw e}}async#c(e){try{return await this.#t.readFile(e,{encoding:`utf8`}),!0}catch(e){if(Ki(e))return!1;throw e}}#l(){return A(this.#e,`tasks`)}#u(){return A(this.#e,`subscriptions`)}#d(){return A(this.#e,`events`)}#f(e){return A(this.#l(),e+`.json`)}#p(e,t){return A(this.#u(),e+`-`+t+`.json`)}#m(e,t){return A(this.#d(),e+`-`+t+`.jsonl`)}};function Xi(e,t){return new Yi(e,t)}const Zi=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Qi=/* @__PURE__ */ new Set([`running`,`stopping`]),$i=2**53-1,ea={info:()=>void 0,warn:e=>{console.warn(`[pi-ptc.background] `+e)}};function Y(e){return e instanceof Error?e.message:String(e)}function ta(e){return e===void 0||e.length===0?`<in-memory>`:e}function na(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}var ra=class{#e;#t=/* @__PURE__ */ new Map;constructor(e){this.#e=e}setCurrent(e){this.#e=e}async transition(e,t){let n=e.kind===`spawn`?this.#e:this.#t.get(e.taskId)??this.#e,r=await n.transition(e,t);return e.kind===`spawn`&&this.#t.set(r.record.id,n),r}query(e){return this.#e.query(e)}get(e){return this.#e.get(e)}onTransition(e){return this.#e.onTransition(e)}reconcileLostTasks(){return this.#e.reconcileLostTasks()}},ia=class{#e;constructor(e){this.#e=e}setCurrent(e){this.#e=e}readOutput(e){return this.#e.readOutput(e)}writeOutput(e,t){return this.#e.writeOutput(e,t)}outputRef(e){return this.#e.outputRef(e)}},aa=class{#e;#t=[];constructor(e){this.#e=e}setCurrent(e){this.#e=e;for(let t of this.#t)e.onIdleWake(t)}current(){return this.#e}subscribe(e,t,n){return this.#e.subscribe(e,t,n)}drainPending(e,t){return this.#e.drainPending(e,t)}acknowledgeEvents(e,t,n){return this.#e.acknowledgeEvents(e,t,n)}onIdleWake(e){this.#t.push(e),this.#e.onIdleWake(e)}pendingCount(e,t){return this.#e.pendingCount(e,t)}notifyIdle(e,t){return this.#e.notifyIdle(e,t)}},oa=class{#e;#t=/* @__PURE__ */ new Set;#n=/* @__PURE__ */ new Map;constructor(e){this.#e=e}isLive(e){return this.#t.has(e)}trackReapCancel(e,t){this.#n.set(e,t)}spawn(e,t){let n=this.#e.spawn(e,t);return this.#t.add(n),n}kill(e,t){this.#e.kill(e,t)}events(e){return this.#e.events(e)}async exit(e){try{return await this.#e.exit(e)}finally{this.#t.delete(e);let t=this.#n.get(e);t!==void 0&&(this.#n.delete(e),t())}}stderr(e){return this.#e.stderr(e)}liveHandles(){return[...this.#t]}},sa=class{registry;outputStorage;pipeline;slots;lifecycle;dispatchDeps;clock;#e;#t;#n;#r;#i;#a=!1;constructor(e){this.clock=e.clock??(()=>Date.now()),this.#e=e.logger??ea,this.#r=e.owner??{pid:process.pid,bootMs:this.clock()},this.#i=e.isPidAlive??Ze,this.#t=e.createStorage??(e=>e===void 0||e.length===0?new rt:Xi(e)),this.#n=e.createOutputStorage??(e=>e===void 0||e.length===0?new ti:new ri(e));let t=(e.createInitialStorage??(()=>new rt))(),n=et(t,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),r=new Wi(t,{now:this.clock,logger:this.#e});this.registry=new ra(n),this.outputStorage=new ia(new ti),this.pipeline=new aa(r),this.lifecycle=new oa((e.createLifecycle??(()=>new Ie({logger:this.#e})))()),this.slots=new at(e.concurrency??L.dispatchConcurrency),this.dispatchDeps={taskRegistry:this.registry,lifecycle:this.lifecycle,slots:this.slots,outputStorage:this.outputStorage,clock:this.clock,logger:this.#e},this.registry.onTransition(this.#o)}#o=(e,t)=>{this.#a||Zi.has(e.status)&&this.pipeline.notifyIdle(t.subscriptionId,e.id).catch(t=>{this.#e.warn(`terminal notification wake for task `+e.id+` failed: `+Y(t))})};async bindSession(e,t){let n,r;try{n=this.#t(e),r=this.#n(e)}catch(n){return this.#s(`background runtime: session storage for `+ta(e)+` is unavailable: `+Y(n),t),[]}let i=et(n,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),a=new Wi(n,{now:this.clock,logger:this.#e});this.registry.setCurrent(i),this.outputStorage.setCurrent(r),this.pipeline.setCurrent(a),this.#a=!1;try{return await i.reconcileLostTasks()}catch(e){return this.#s(`background runtime: startup reconcile failed; stale running tasks were not all marked lost (reconcile is not per-record tolerant yet): `+Y(e),t),[]}finally{this.registry.onTransition(this.#o)}}async drainNotifications(e){let t;try{t=await this.registry.query({limit:$i})}catch(t){return this.#e.warn(`drainNotifications: could not list tasks for subscriber `+e+`: `+Y(t)),{items:[],acks:[]}}let n=[],r=[],i=this.pipeline.current();for(let a of t){if(a.spawnSource.callerId!==e)continue;let t;try{t=await i.drainPending(e,a.id)}catch(t){this.#e.warn(`drainNotifications: task `+a.id+` for subscriber `+e+`: `+Y(t));continue}for(let e of t)n.push({event:e,record:a});let o=t[t.length-1];o!==void 0&&r.push({subscriberId:e,taskId:a.id,cursor:o.eventId,sink:i})}return{items:n,acks:r}}async acknowledgeNotifications(e){for(let t of e)try{await t.sink.acknowledgeEvents(t.subscriberId,t.taskId,t.cursor)}catch(e){this.#e.warn(`acknowledgeNotifications: could not acknowledge task `+t.taskId+`: `+Y(e))}}async shutdown(e){if(this.#a)return[];this.#a=!0;let t;try{t=await this.registry.query({limit:$i})}catch(e){this.#e.warn(`shutdown: could not list tasks: `+Y(e)),t=[]}let n=[];for(let r of t)if(Qi.has(r.status)&&Xe(r,this.#r))try{let t=await this.registry.transition({kind:`reconcile-lost`,taskId:r.id,reason:e},{clock:this.clock,callerId:na(r),logger:this.#e});n.push(t.record)}catch(e){this.#e.warn(`shutdown: could not mark task `+r.id+` lost: `+Y(e))}for(let e of this.lifecycle.liveHandles()){let t=mt(this.lifecycle,e,{isDone:()=>!this.lifecycle.isLive(e),unref:!0});this.lifecycle.trackReapCancel(e,t)}for(let e of n)this.slots.release(e.id);return n}#s(e,t){if(this.#e.warn(e),t!==void 0)try{t(e)}catch(e){this.#e.warn(`bindSession reporter threw: `+Y(e))}}};function ca(e={}){return new sa(e)}const la=/* @__PURE__ */ new Set([`succeeded`,`failed`,`lost`]);function ua(e){return la.has(e.status)}function da(e,t){if(e.length===0)return``;let n=e.map(pa).join(`
50
- `);return`${`<bg-task-notifications batch-id="${X(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function fa(e,t=102400){let n=[],r=[],i=0,a=t-ha;for(let t of e){let e=ma(t);r.length>0&&i+1+e>a&&(n.push(r),r=[],i=0),r.length>0&&(i+=1),r.push(t),i+=e}return r.length>0&&n.push(r),n}function pa(e){let{event:t,record:n}=e,r=t.outputBytes??n.outputBytes,i=r??0,a=t.outputPreview??n.outputPreview,o=[` <bg-task-notification`,` id="${X(t.type)}"`,` task-id="${X(t.taskId)}"`,` subscription-id="${X(t.subscriptionId)}"`,` status="${X(t.status)}"`,` label="${X(n.label)}"`,` agent-name="${X(n.agentName)}"`,` depth="${n.depth}"`,` duration-ms="${n.durationMs??0}"`,` transition-at-ms="${t.transitionAtMs}">`,` <output-bytes>${i}</output-bytes>`];return n.outputRef!==void 0&&o.push(` <output-ref>${X(n.outputRef)}</output-ref>`),r!==void 0&&r<=2048&&a!==void 0&&o.push(` <output-preview>${X(a)}</output-preview>`),o.push(` </bg-task-notification>`),o.join(`
51
- `)}function X(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`"`,`&quot;`).replaceAll(` `,`&#9;`).replaceAll(`
52
- `,`&#10;`).replaceAll(`\r`,`&#13;`)}function ma(e){return Buffer.byteLength(pa(e),`utf8`)}const ha=Buffer.byteLength(`<bg-task-notifications batch-id="${`0`.repeat(26)}" delivered-at-ms="${`9`.repeat(13)}">\n\n</bg-task-notifications>`,`utf8`),ga=[`ptc_run_code`,`ptc_workflow`],_a=[`read`,`bash`,`edit`,`write`],va=`ptc-mode`,ya=`ptc-mode`,ba=`ptc.json`,xa=`builtins-only`;function Sa(){return{enabled:!1,base:void 0,ourLoadout:void 0}}function Ca(e){let t=A(e,ba),n;try{n=T(t,`utf8`)}catch{return{defaultMode:!0,source:`default`}}let r;try{r=JSON.parse(n)}catch(e){return{defaultMode:!0,source:`invalid`,error:`${t} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof r!=`object`||!r||Array.isArray(r))return{defaultMode:!0,source:`invalid`,error:`${t} must contain a JSON object`};let i=r.defaultMode;return i===void 0?{defaultMode:!0,source:`default`}:typeof i==`boolean`?{defaultMode:i,source:`file`}:{defaultMode:!0,source:`invalid`,error:`${t}: "defaultMode" must be a boolean, received ${typeof i}`}}function wa(e){let t=A(e,ba),n;try{n=T(t,`utf8`)}catch{return{optInBindings:[],source:`default`}}let r;try{r=JSON.parse(n)}catch{return{optInBindings:[],source:`default`}}if(typeof r!=`object`||!r||Array.isArray(r))return{optInBindings:[],source:`default`};let i=r.optInBindings;if(i===void 0)return{optInBindings:[],source:`default`};if(!Array.isArray(i))return{optInBindings:[],source:`invalid`,error:`${t}: "optInBindings" must be an array of binding names, received ${typeof i}`};let a=i.find(e=>typeof e!=`string`);if(a!==void 0)return{optInBindings:[],source:`invalid`,error:`${t}: "optInBindings" entries must be strings, received ${typeof a}`};try{return{optInBindings:sn(i),source:`file`}}catch(e){return{optInBindings:[],source:`invalid`,error:`${t}: ${e instanceof Error?e.message:String(e)}`}}}const Z=`builtin:codemode`;function Q(e){return e.split(oe).join(`/`)}function Ta(e){return e===`~`?E():e.startsWith(`~/`)?A(E(),e.slice(2)):e.startsWith(`file://`)?fe(e):e}function Ea(e){return Q(Ta(e.startsWith(`./`)||e.startsWith(`.\\`)?e.slice(2):e))}function Da(e,t,n){let r=Q(ae(n,e)),i=ie(e),a=Q(e);return t.some(e=>{let t=Q(Ta(e));return xe(r,t)||xe(i,t)||xe(a,t)})}function Oa(e,t,n){if(t.length===0)return!1;let r=Q(ae(n,e)),i=Q(e);return t.some(e=>{let t=Ea(e);return t===r||t===i})}function ka(e){let t=[];for(let n of e){if(typeof n!=`string`)continue;let e=n[0];(e===`+`||e===`-`||e===`!`)&&t.push({sign:e,target:n.slice(1)})}return t}function Aa(e,t){if(!Array.isArray(e))return;let n;for(let{sign:r,target:i}of ka(e)){let e=r!==`-`&&r!==`!`;(r===`+`||r===`-`?Oa(Z,[i],t):Da(Z,[i],t))&&(n=e?`enabled`:`disabled`)}return n}function ja(e,t){if(!Array.isArray(e))return;let n=ka(e),r=e=>n.filter(t=>t.sign===e).map(e=>e.target),i=r(`!`),a=r(`+`),o=r(`-`),s;return Da(Z,i,t)&&(s=`disabled`),Oa(Z,a,t)&&(s=`enabled`),Oa(Z,o,t)&&(s=`disabled`),s}function Ma(e){for(let t=0;t<e.length;t+=1){let n=e[t];if((n===`-e`||n===`--extension`)&&e[t+1]===Z)return!0}return!1}function Na(e){let t;try{t=T(e,`utf8`)}catch{return{value:void 0}}try{let n=JSON.parse(t);return typeof n!=`object`||!n||Array.isArray(n)?{value:void 0,error:`${e} must contain a JSON object`}:{value:n}}catch(t){return{value:void 0,error:`${e} is not valid JSON (${t instanceof Error?t.message:String(t)})`}}}function Pa(e,t,n,r={project:process.cwd(),user:process.cwd()}){let i=e.slice(1);if(Ma(i))return{switch:`enabled`,source:`cli`};if(i.some(e=>e===`-ne`||e===`--no-extensions`))return{switch:`disabled`,source:`cli`};let a=t?.extensions,o=Aa(a,r.project);if(o!==void 0)return{switch:o,source:`project`};let s=n?.extensions,c=ja(s,r.user);return c===void 0?{switch:`absent`,source:`default`}:{switch:c,source:`user`}}function Fa(e,t,n=process.argv){let r=Na(A(t,`.pi`,`settings.json`)),i=Na(A(e,`settings.json`)),a=Pa(n,r.value,i.value,{project:A(t,`.pi`),user:e}),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}function Ia(e){return{activation:e.includes(`codemode`)?`active`:`inactive`,source:`loadout`}}function La(e,t,n){return Xa(Ia(n),Ya(e,t))}const Ra=[`codemode`,`deferred`,`direct`,`hidden`],za={"codemode-deferred":`codemode`},Ba=/^[A-Za-z0-9_-]+$/;function Va(e){return typeof e==`string`?za[e]??e:e}function Ha(e){return typeof e==`string`&&Ra.includes(e)}function $(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ua(e){return $(e)&&Object.values(e).every(e=>typeof e==`string`)}function Wa(e){return URL.canParse(e)?/^https?:$/.test(new URL(e).protocol):!1}function Ga(e,t){if(!Ba.test(e)||!$(t))return;let n=Va(t.exposure),r=$(t.toolExposure)?Object.fromEntries(Object.entries(t.toolExposure).map(([e,t])=>[e,Va(t)])):t.toolExposure;if(n!==void 0&&!Ha(n)||r!==void 0&&(!$(r)||!Object.values(r).every(e=>Ha(e)))||t.enabled!==void 0&&typeof t.enabled!=`boolean`||t.description!==void 0&&typeof t.description!=`string`||t.timeout!==void 0&&(typeof t.timeout!=`number`||!(t.timeout>0))||t.type===`sse`)return;let i={enabled:t.enabled,exposure:n,toolExposure:r},a=t.type;if(typeof t.url==`string`&&(a===void 0||a===`http`||a===`streamable-http`))return!Wa(t.url)||t.headers!==void 0&&!Ua(t.headers)?void 0:i;if(typeof t.command==`string`&&(a===void 0||a===`stdio`))return t.args!==void 0&&!(Array.isArray(t.args)&&t.args.every(e=>typeof e==`string`))||t.env!==void 0&&!Ua(t.env)||t.cwd!==void 0&&typeof t.cwd!=`string`?void 0:i}function Ka(e,t){e.error=e.error===void 0?t:`${e.error}; ${t}`}function qa(e,t,n,r,i){if(t===void 0){n!==void 0&&Ka(i,n);return}let a;try{a=JSON.parse(t)}catch(t){Ka(i,`${e} is not valid JSON (${t instanceof Error?t.message:String(t)})`);return}if(!$(a)||a.mcpServers!==void 0&&!$(a.mcpServers)){Ka(i,`${e} must contain a JSON object with an "mcpServers" object`);return}typeof a.autoEnableCodemode==`boolean`?i.autoEnableCodemode=a.autoEnableCodemode:a.autoEnableCodemode!==void 0&&Ka(i,`${e}: autoEnableCodemode must be a boolean`);for(let[e,t]of Object.entries(a.mcpServers??{})){let n=Ga(e,t);if(n===void 0||r===`project`&&$(t)&&`url`in t&&t.auth)continue;let a=`mcp__${e.replace(/-/g,`_`)}`;[...i.servers.entries()].some(([t,n])=>t!==e&&n.namespace===a)||i.servers.set(e,{namespace:a,server:n})}}function Ja(e,t){let n={autoEnableCodemode:void 0,servers:/* @__PURE__ */ new Map,error:void 0};qa(e.path,e.raw,e.readError,`global`,n),qa(t.path,t.raw,t.readError,`project`,n);let r=[...n.servers.values()].some(({server:e})=>e.enabled!==!1&&(/* @__PURE__ */ new Set([e.exposure??`codemode`,...Object.values(e.toolExposure??{})])).has(`codemode`));return{autoEnablesCodemode:n.autoEnableCodemode!==!1&&r,...n.error===void 0?{}:{error:n.error}}}function Ya(e,t){let n=e=>{try{return{path:e,raw:T(e,`utf8`)}}catch(t){return t.code===`ENOENT`?{path:e,raw:void 0}:{path:e,raw:void 0,readError:`${e} could not be read (${t instanceof Error?t.message:String(t)})`}}};return Ja(n(A(e,`mcp.json`)),n(A(t,`.pi`,`mcp.json`)))}function Xa(e,t){let n=t.error===void 0?e:{...e,mcpError:t.error};return e.activation===`active`||!t.autoEnablesCodemode?n:{...e,activation:`active`,source:`mcp`,...t.error===void 0?{}:{mcpError:t.error}}}function Za(e,t,n){return!e.present||t===`disabled`||n!==`active`?`full`:`subagents`}function Qa(e=process.argv){let t=e[1];if(t===void 0||t===``)return{present:!1,how:`no-entry`};let n;try{n=ee(t)}catch{return{present:!1,how:`unresolvable-entry`}}let r=k(n);for(let e of $a){let t=A(r,...e);try{if(te(t).isDirectory())return{present:!0,how:`found`}}catch{}}return{present:!1,how:`not-found`}}const $a=[[`..`,`extensions`,`codemode`],[`..`,`..`,`extensions`,`codemode`],[`extensions`,`codemode`]];function eo(e,t,n,r,i,a=process.cwd()){let o=n??Qa(),s=r??Fa(e,a),c=i??La(e,a,t);return{surfaceMode:Za(o,s.switch,c.activation),codemode:o,codemodeSwitch:s,codemodeActivation:c}}function to(e){let t=A(e,ba),n;try{n=T(t,`utf8`)}catch{return}let r;try{r=JSON.parse(n)}catch{return}if(typeof r!=`object`||!r||Array.isArray(r))return;let i=r.surfaceMode;return i===void 0?void 0:{path:t,value:i}}function no(e){return[...new Set(e)]}function ro(e,t){if(e.length!==t.length)return!1;let n=[...e].sort(),r=[...t].sort();return n.every((e,t)=>e===r[t])}function io(e,t){let n=e=>ga.includes(e);if(t===`all-but-ptc`)return no(e.filter(n));let r=new Set(R);return no(e.filter(e=>n(e)||!r.has(e)))}function ao(e){let{mode:t,defaultMode:n,active:r,manual:i}=e;return t===`tui`?!n&&!i?{enter:!1,reason:`config-off`}:ga.some(e=>r.includes(e))?!i&&_a.filter(e=>!r.includes(e)).length>0?{enter:!1,reason:`restricted-session`}:{enter:!0,base:no(r),loadout:io(r,e.hide??`builtins-only`)}:{enter:!1,reason:`tools-unavailable`}:{enter:!1,reason:`not-tui`}}function oo(e,t){return e.enabled&&e.base!==void 0?e.base:t}function so(e,t){return!e.enabled||e.ourLoadout===void 0?!1:!ro(e.ourLoadout,t)}function co(e,t){let n=t.length>0&&t.every(e=>ga.includes(e));return e?.enabled===!0&&n&&e.base!==void 0?{base:e.base,restoreFirst:!0}:{base:t,restoreFirst:!1}}function lo(e,t){let n=t===`all-but-ptc`?`Every built-in tool is hidden from you, and so are other extensions' tools.`:`The built-in tools (read, bash, edit, write, grep, find, ls) are hidden from you.`,r=e.map(e=>`tools.${e}(args)`),i=e.slice(0,2).map(e=>e===`read`?`await tools.read({ path: "src/index.ts" })`:e===`bash`?`await tools.bash({ command: "pnpm test" })`:`await tools.${e}({ /* … */ })`).join(`
48
+ `;await this.#t.appendFile(this.#m(e,t),n,{encoding:`utf8`})}}async*loadEvents(e,t){let n=await this.#n(e);if(n.length===0)throw Error(`loadEvents: unknown subscriptionId `+e);let r=[];for(let t of n)r.push(...await this.#a(this.#m(e,t.taskId)));r.sort(oa);for(let e of r)t!==void 0&&e.eventId<=t||(yield e)}async#n(e){let t=this.#u(),n=[];for(let r of await this.#s(t)){if(!r.endsWith(`.json`))continue;let i=await this.#r(j(t,r));i!==null&&i.subscriberId===e&&n.push(i)}return n}async#r(e){let t;try{t=await this.#t.readFile(e,{encoding:`utf8`})}catch(e){if(ia(e))return null;throw e}return this.#i(e,t)}#i(e,t){let n;try{n=JSON.parse(t)}catch(t){throw Error(`FileTaskStorage: corrupt JSON in `+e+`: `+aa(t))}if(typeof n!=`object`||!n||Array.isArray(n))throw Error(`FileTaskStorage: corrupt JSON in `+e+`: expected a JSON object`);return n}async#a(e){let t;try{t=await this.#t.readFile(e,{encoding:`utf8`})}catch(e){if(ia(e))return[];throw e}let n=[];for(let r of t.split(`
49
+ `)){let t=r.trim();if(t.length===0)continue;let i;try{i=JSON.parse(t)}catch(t){throw Error(`FileTaskStorage: corrupt event JSON in `+e+`: `+aa(t))}if(typeof i!=`object`||!i||Array.isArray(i))throw Error(`FileTaskStorage: corrupt event JSON in `+e+`: expected a JSON object`);n.push(i)}return n}async#o(e,t){await this.#t.mkdir(A(e),{recursive:!0});let n=e+`.tmp-`+ce();await this.#t.writeFile(n,JSON.stringify(t,null,2),{encoding:`utf8`}),await this.#t.rename(n,e)}async#s(e){try{return await this.#t.readdir(e)}catch(e){if(ia(e))return[];throw e}}async#c(e){try{return await this.#t.readFile(e,{encoding:`utf8`}),!0}catch(e){if(ia(e))return!1;throw e}}#l(){return j(this.#e,`tasks`)}#u(){return j(this.#e,`subscriptions`)}#d(){return j(this.#e,`events`)}#f(e){return j(this.#l(),e+`.json`)}#p(e,t){return j(this.#u(),e+`-`+t+`.json`)}#m(e,t){return j(this.#d(),e+`-`+t+`.jsonl`)}};function ca(e,t){return new sa(e,t)}const la=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),ua=/* @__PURE__ */ new Set([`running`,`stopping`]),da=2**53-1,fa={info:()=>void 0,warn:e=>{console.warn(`[pi-ptc.background] `+e)}};function J(e){return e instanceof Error?e.message:String(e)}function pa(e){return e===void 0||e.length===0?`<in-memory>`:e}function ma(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}var ha=class{#e;#t=/* @__PURE__ */ new Map;constructor(e){this.#e=e}setCurrent(e){this.#e=e}async transition(e,t){let n=e.kind===`spawn`?this.#e:this.#t.get(e.taskId)??this.#e,r=await n.transition(e,t);return e.kind===`spawn`&&this.#t.set(r.record.id,n),r}query(e){return this.#e.query(e)}get(e){return this.#e.get(e)}onTransition(e){return this.#e.onTransition(e)}reconcileLostTasks(){return this.#e.reconcileLostTasks()}},ga=class{#e;constructor(e){this.#e=e}setCurrent(e){this.#e=e}readOutput(e){return this.#e.readOutput(e)}writeOutput(e,t){return this.#e.writeOutput(e,t)}outputRef(e){return this.#e.outputRef(e)}},_a=class{#e;#t=[];constructor(e){this.#e=e}setCurrent(e){this.#e=e;for(let t of this.#t)e.onIdleWake(t)}current(){return this.#e}subscribe(e,t,n){return this.#e.subscribe(e,t,n)}drainPending(e,t){return this.#e.drainPending(e,t)}acknowledgeEvents(e,t,n){return this.#e.acknowledgeEvents(e,t,n)}onIdleWake(e){this.#t.push(e),this.#e.onIdleWake(e)}pendingCount(e,t){return this.#e.pendingCount(e,t)}notifyIdle(e,t){return this.#e.notifyIdle(e,t)}},va=class{#e;#t=/* @__PURE__ */ new Set;#n=/* @__PURE__ */ new Map;constructor(e){this.#e=e}isLive(e){return this.#t.has(e)}trackReapCancel(e,t){this.#n.set(e,t)}spawn(e,t){let n=this.#e.spawn(e,t);return this.#t.add(n),n}kill(e,t){this.#e.kill(e,t)}events(e){return this.#e.events(e)}async exit(e){try{return await this.#e.exit(e)}finally{this.#t.delete(e);let t=this.#n.get(e);t!==void 0&&(this.#n.delete(e),t())}}stderr(e){return this.#e.stderr(e)}liveHandles(){return[...this.#t]}},ya=class{registry;outputStorage;pipeline;slots;lifecycle;dispatchDeps;clock;#e;#t;#n;#r;#i;#a=!1;constructor(e){this.clock=e.clock??(()=>Date.now()),this.#e=e.logger??fa,this.#r=e.owner??{pid:process.pid,bootMs:this.clock()},this.#i=e.isPidAlive??Ze,this.#t=e.createStorage??(e=>e===void 0||e.length===0?new rt:ca(e)),this.#n=e.createOutputStorage??(e=>e===void 0||e.length===0?new ui:new fi(e));let t=(e.createInitialStorage??(()=>new rt))(),n=et(t,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),r=new na(t,{now:this.clock,logger:this.#e});this.registry=new ha(n),this.outputStorage=new ga(new ui),this.pipeline=new _a(r),this.lifecycle=new va((e.createLifecycle??(()=>new Ie({logger:this.#e})))()),this.slots=new at(e.concurrency??L.dispatchConcurrency),this.dispatchDeps={taskRegistry:this.registry,lifecycle:this.lifecycle,slots:this.slots,outputStorage:this.outputStorage,clock:this.clock,logger:this.#e},this.registry.onTransition(this.#o)}#o=(e,t)=>{this.#a||la.has(e.status)&&this.pipeline.notifyIdle(t.subscriptionId,e.id).catch(t=>{this.#e.warn(`terminal notification wake for task `+e.id+` failed: `+J(t))})};async bindSession(e,t){let n,r;try{n=this.#t(e),r=this.#n(e)}catch(n){return this.#s(`background runtime: session storage for `+pa(e)+` is unavailable: `+J(n),t),[]}let i=et(n,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),a=new na(n,{now:this.clock,logger:this.#e});this.registry.setCurrent(i),this.outputStorage.setCurrent(r),this.pipeline.setCurrent(a),this.#a=!1;try{return await i.reconcileLostTasks()}catch(e){return this.#s(`background runtime: startup reconcile failed; stale running tasks were not all marked lost (reconcile is not per-record tolerant yet): `+J(e),t),[]}finally{this.registry.onTransition(this.#o)}}async drainNotifications(e){let t;try{t=await this.registry.query({limit:da})}catch(t){return this.#e.warn(`drainNotifications: could not list tasks for subscriber `+e+`: `+J(t)),{items:[],acks:[]}}let n=[],r=[],i=this.pipeline.current();for(let a of t){if(a.spawnSource.callerId!==e)continue;let t;try{t=await i.drainPending(e,a.id)}catch(t){this.#e.warn(`drainNotifications: task `+a.id+` for subscriber `+e+`: `+J(t));continue}for(let e of t)n.push({event:e,record:a});let o=t[t.length-1];o!==void 0&&r.push({subscriberId:e,taskId:a.id,cursor:o.eventId,sink:i})}return{items:n,acks:r}}async acknowledgeNotifications(e){for(let t of e)try{await t.sink.acknowledgeEvents(t.subscriberId,t.taskId,t.cursor)}catch(e){this.#e.warn(`acknowledgeNotifications: could not acknowledge task `+t.taskId+`: `+J(e))}}async shutdown(e){if(this.#a)return[];this.#a=!0;let t;try{t=await this.registry.query({limit:da})}catch(e){this.#e.warn(`shutdown: could not list tasks: `+J(e)),t=[]}let n=[];for(let r of t)if(ua.has(r.status)&&Xe(r,this.#r))try{let t=await this.registry.transition({kind:`reconcile-lost`,taskId:r.id,reason:e},{clock:this.clock,callerId:ma(r),logger:this.#e});n.push(t.record)}catch(e){this.#e.warn(`shutdown: could not mark task `+r.id+` lost: `+J(e))}for(let e of this.lifecycle.liveHandles()){let t=_t(this.lifecycle,e,{isDone:()=>!this.lifecycle.isLive(e),unref:!0});this.lifecycle.trackReapCancel(e,t)}for(let e of n)this.slots.release(e.id);return n}#s(e,t){if(this.#e.warn(e),t!==void 0)try{t(e)}catch(e){this.#e.warn(`bindSession reporter threw: `+J(e))}}};function ba(e={}){return new ya(e)}const xa=/* @__PURE__ */ new Set([`succeeded`,`failed`,`lost`]);function Sa(e){return xa.has(e.status)}function Ca(e,t){if(e.length===0)return``;let n=e.map(Ta).join(`
50
+ `);return`${`<bg-task-notifications batch-id="${Y(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function wa(e,t=102400){let n=[],r=[],i=0,a=t-Da;for(let t of e){let e=Ea(t);r.length>0&&i+1+e>a&&(n.push(r),r=[],i=0),r.length>0&&(i+=1),r.push(t),i+=e}return r.length>0&&n.push(r),n}function Ta(e){let{event:t,record:n}=e,r=t.outputBytes??n.outputBytes,i=r??0,a=t.outputPreview??n.outputPreview,o=[` <bg-task-notification`,` id="${Y(t.type)}"`,` task-id="${Y(t.taskId)}"`,` subscription-id="${Y(t.subscriptionId)}"`,` status="${Y(t.status)}"`,` label="${Y(n.label)}"`,` agent-name="${Y(n.agentName)}"`,` depth="${n.depth}"`,` duration-ms="${n.durationMs??0}"`,` transition-at-ms="${t.transitionAtMs}">`,` <output-bytes>${i}</output-bytes>`];return n.outputRef!==void 0&&o.push(` <output-ref>${Y(n.outputRef)}</output-ref>`),r!==void 0&&r<=2048&&a!==void 0&&o.push(` <output-preview>${Y(a)}</output-preview>`),o.push(` </bg-task-notification>`),o.join(`
51
+ `)}function Y(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`"`,`&quot;`).replaceAll(` `,`&#9;`).replaceAll(`
52
+ `,`&#10;`).replaceAll(`\r`,`&#13;`)}function Ea(e){return Buffer.byteLength(Ta(e),`utf8`)}const Da=Buffer.byteLength(`<bg-task-notifications batch-id="${`0`.repeat(26)}" delivered-at-ms="${`9`.repeat(13)}">\n\n</bg-task-notifications>`,`utf8`),Oa=[`ptc_run_code`,`ptc_workflow`],ka=[`read`,`bash`,`edit`,`write`],Aa=`ptc-mode`,ja=`ptc-mode`,Ma=`ptc.json`,Na=`builtins-only`;function Pa(){return{enabled:!1,base:void 0,ourLoadout:void 0}}function Fa(e){let t=j(e,Ma),n;try{n=T(t,`utf8`)}catch{return{defaultMode:!0,source:`default`}}let r;try{r=JSON.parse(n)}catch(e){return{defaultMode:!0,source:`invalid`,error:`${t} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof r!=`object`||!r||Array.isArray(r))return{defaultMode:!0,source:`invalid`,error:`${t} must contain a JSON object`};let i=r.defaultMode;return i===void 0?{defaultMode:!0,source:`default`}:typeof i==`boolean`?{defaultMode:i,source:`file`}:{defaultMode:!0,source:`invalid`,error:`${t}: "defaultMode" must be a boolean, received ${typeof i}`}}function Ia(e){let t=j(e,Ma),n;try{n=T(t,`utf8`)}catch{return{optInBindings:[],source:`default`}}let r;try{r=JSON.parse(n)}catch{return{optInBindings:[],source:`default`}}if(typeof r!=`object`||!r||Array.isArray(r))return{optInBindings:[],source:`default`};let i=r.optInBindings;if(i===void 0)return{optInBindings:[],source:`default`};if(!Array.isArray(i))return{optInBindings:[],source:`invalid`,error:`${t}: "optInBindings" must be an array of binding names, received ${typeof i}`};let a=i.find(e=>typeof e!=`string`);if(a!==void 0)return{optInBindings:[],source:`invalid`,error:`${t}: "optInBindings" entries must be strings, received ${typeof a}`};try{return{optInBindings:un(i),source:`file`}}catch(e){return{optInBindings:[],source:`invalid`,error:`${t}: ${e instanceof Error?e.message:String(e)}`}}}const X=`builtin:codemode`;function Z(e){return e.split(ae).join(`/`)}function La(e){return e===`~`?ne():e.startsWith(`~/`)?j(ne(),e.slice(2)):e.startsWith(`file://`)?fe(e):e}function Ra(e){return Z(La(e.startsWith(`./`)||e.startsWith(`.\\`)?e.slice(2):e))}function za(e,t,n){let r=Z(ie(n,e)),i=re(e),a=Z(e);return t.some(e=>{let t=Z(La(e));return xe(r,t)||xe(i,t)||xe(a,t)})}function Ba(e,t,n){if(t.length===0)return!1;let r=Z(ie(n,e)),i=Z(e);return t.some(e=>{let t=Ra(e);return t===r||t===i})}function Va(e){let t=[];for(let n of e){if(typeof n!=`string`)continue;let e=n[0];(e===`+`||e===`-`||e===`!`)&&t.push({sign:e,target:n.slice(1)})}return t}function Ha(e,t){if(!Array.isArray(e))return;let n;for(let{sign:r,target:i}of Va(e)){let e=r!==`-`&&r!==`!`;(r===`+`||r===`-`?Ba(X,[i],t):za(X,[i],t))&&(n=e?`enabled`:`disabled`)}return n}function Ua(e,t){if(!Array.isArray(e))return;let n=Va(e),r=e=>n.filter(t=>t.sign===e).map(e=>e.target),i=r(`!`),a=r(`+`),o=r(`-`),s;return za(X,i,t)&&(s=`disabled`),Ba(X,a,t)&&(s=`enabled`),Ba(X,o,t)&&(s=`disabled`),s}function Wa(e){for(let t=0;t<e.length;t+=1){let n=e[t];if((n===`-e`||n===`--extension`)&&e[t+1]===X)return!0}return!1}function Ga(e){let t;try{t=T(e,`utf8`)}catch{return{value:void 0}}try{let n=JSON.parse(t);return typeof n!=`object`||!n||Array.isArray(n)?{value:void 0,error:`${e} must contain a JSON object`}:{value:n}}catch(t){return{value:void 0,error:`${e} is not valid JSON (${t instanceof Error?t.message:String(t)})`}}}function Ka(e,t,n,r={project:process.cwd(),user:process.cwd()}){let i=e.slice(1);if(Wa(i))return{switch:`enabled`,source:`cli`};if(i.some(e=>e===`-ne`||e===`--no-extensions`))return{switch:`disabled`,source:`cli`};let a=t?.extensions,o=Ha(a,r.project);if(o!==void 0)return{switch:o,source:`project`};let s=n?.extensions,c=Ua(s,r.user);return c===void 0?{switch:`absent`,source:`default`}:{switch:c,source:`user`}}function qa(e,t,n=process.argv){let r=Ga(j(t,`.pi`,`settings.json`)),i=Ga(j(e,`settings.json`)),a=Ka(n,r.value,i.value,{project:j(t,`.pi`),user:e}),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}function Ja(e){return{activation:e.includes(`codemode`)?`active`:`inactive`,source:`loadout`}}function Ya(e,t,n){return co(Ja(n),so(e,t))}const Xa=[`codemode`,`deferred`,`direct`,`hidden`],Za={"codemode-deferred":`codemode`},Qa=/^[A-Za-z0-9_-]+$/;function $a(e){return typeof e==`string`?Za[e]??e:e}function eo(e){return typeof e==`string`&&Xa.includes(e)}function Q(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function to(e){return Q(e)&&Object.values(e).every(e=>typeof e==`string`)}function no(e){return URL.canParse(e)?/^https?:$/.test(new URL(e).protocol):!1}function ro(e,t){if(!Qa.test(e)||!Q(t))return;let n=$a(t.exposure),r=Q(t.toolExposure)?Object.fromEntries(Object.entries(t.toolExposure).map(([e,t])=>[e,$a(t)])):t.toolExposure;if(n!==void 0&&!eo(n)||r!==void 0&&(!Q(r)||!Object.values(r).every(e=>eo(e)))||t.enabled!==void 0&&typeof t.enabled!=`boolean`||t.description!==void 0&&typeof t.description!=`string`||t.timeout!==void 0&&(typeof t.timeout!=`number`||!(t.timeout>0))||t.type===`sse`)return;let i={enabled:t.enabled,exposure:n,toolExposure:r},a=t.type;if(typeof t.url==`string`&&(a===void 0||a===`http`||a===`streamable-http`))return!no(t.url)||t.headers!==void 0&&!to(t.headers)?void 0:i;if(typeof t.command==`string`&&(a===void 0||a===`stdio`))return t.args!==void 0&&!(Array.isArray(t.args)&&t.args.every(e=>typeof e==`string`))||t.env!==void 0&&!to(t.env)||t.cwd!==void 0&&typeof t.cwd!=`string`?void 0:i}function io(e,t){e.error=e.error===void 0?t:`${e.error}; ${t}`}function ao(e,t,n,r,i){if(t===void 0){n!==void 0&&io(i,n);return}let a;try{a=JSON.parse(t)}catch(t){io(i,`${e} is not valid JSON (${t instanceof Error?t.message:String(t)})`);return}if(!Q(a)||a.mcpServers!==void 0&&!Q(a.mcpServers)){io(i,`${e} must contain a JSON object with an "mcpServers" object`);return}typeof a.autoEnableCodemode==`boolean`?i.autoEnableCodemode=a.autoEnableCodemode:a.autoEnableCodemode!==void 0&&io(i,`${e}: autoEnableCodemode must be a boolean`);for(let[e,t]of Object.entries(a.mcpServers??{})){let n=ro(e,t);if(n===void 0||r===`project`&&Q(t)&&`url`in t&&t.auth)continue;let a=`mcp__${e.replace(/-/g,`_`)}`;[...i.servers.entries()].some(([t,n])=>t!==e&&n.namespace===a)||i.servers.set(e,{namespace:a,server:n})}}function oo(e,t){let n={autoEnableCodemode:void 0,servers:/* @__PURE__ */ new Map,error:void 0};ao(e.path,e.raw,e.readError,`global`,n),ao(t.path,t.raw,t.readError,`project`,n);let r=[...n.servers.values()].some(({server:e})=>e.enabled!==!1&&(/* @__PURE__ */ new Set([e.exposure??`codemode`,...Object.values(e.toolExposure??{})])).has(`codemode`));return{autoEnablesCodemode:n.autoEnableCodemode!==!1&&r,...n.error===void 0?{}:{error:n.error}}}function so(e,t){let n=e=>{try{return{path:e,raw:T(e,`utf8`)}}catch(t){return t.code===`ENOENT`?{path:e,raw:void 0}:{path:e,raw:void 0,readError:`${e} could not be read (${t instanceof Error?t.message:String(t)})`}}};return oo(n(j(e,`mcp.json`)),n(j(t,`.pi`,`mcp.json`)))}function co(e,t){let n=t.error===void 0?e:{...e,mcpError:t.error};return e.activation===`active`||!t.autoEnablesCodemode?n:{...e,activation:`active`,source:`mcp`,...t.error===void 0?{}:{mcpError:t.error}}}function lo(e,t,n){return!e.present||t===`disabled`||n!==`active`?`full`:`subagents`}function uo(e=process.argv){let t=e[1];if(t===void 0||t===``)return{present:!1,how:`no-entry`};let n;try{n=ee(t)}catch{return{present:!1,how:`unresolvable-entry`}}let r=A(n);for(let e of fo){let t=j(r,...e);try{if(te(t).isDirectory())return{present:!0,how:`found`}}catch{}}return{present:!1,how:`not-found`}}const fo=[[`..`,`extensions`,`codemode`],[`..`,`..`,`extensions`,`codemode`],[`extensions`,`codemode`]];function po(e,t,n,r,i,a=process.cwd()){let o=n??uo(),s=r??qa(e,a),c=i??Ya(e,a,t);return{surfaceMode:lo(o,s.switch,c.activation),codemode:o,codemodeSwitch:s,codemodeActivation:c}}function mo(e){let t=j(e,Ma),n;try{n=T(t,`utf8`)}catch{return}let r;try{r=JSON.parse(n)}catch{return}if(typeof r!=`object`||!r||Array.isArray(r))return;let i=r.surfaceMode;return i===void 0?void 0:{path:t,value:i}}function ho(e){return[...new Set(e)]}function go(e,t){if(e.length!==t.length)return!1;let n=[...e].sort(),r=[...t].sort();return n.every((e,t)=>e===r[t])}function _o(e,t){let n=e=>Oa.includes(e);if(t===`all-but-ptc`)return ho(e.filter(n));let r=new Set(B);return ho(e.filter(e=>n(e)||!r.has(e)))}function vo(e){let{mode:t,defaultMode:n,active:r,manual:i}=e;return t===`tui`?!n&&!i?{enter:!1,reason:`config-off`}:Oa.some(e=>r.includes(e))?!i&&ka.filter(e=>!r.includes(e)).length>0?{enter:!1,reason:`restricted-session`}:{enter:!0,base:ho(r),loadout:_o(r,e.hide??`builtins-only`)}:{enter:!1,reason:`tools-unavailable`}:{enter:!1,reason:`not-tui`}}function yo(e,t){return e.enabled&&e.base!==void 0?e.base:t}function bo(e,t){return!e.enabled||e.ourLoadout===void 0?!1:!go(e.ourLoadout,t)}function xo(e,t){let n=t.length>0&&t.every(e=>Oa.includes(e));return e?.enabled===!0&&n&&e.base!==void 0?{base:e.base,restoreFirst:!0}:{base:t,restoreFirst:!1}}function So(e,t){let n=t===`all-but-ptc`?`Every built-in tool is hidden from you, and so are other extensions' tools.`:`The built-in tools (read, bash, edit, write, grep, find, ls) are hidden from you.`,r=e.map(e=>`tools.${e}(args)`),i=e.slice(0,2).map(e=>e===`read`?`await tools.read({ path: "src/index.ts" })`:e===`bash`?`await tools.bash({ command: "pnpm test" })`:`await tools.${e}({ /* … */ })`).join(`
53
53
  `);return[`[PTC MODE ACTIVE]`,`This session runs in PTC mode. `+n,``,`Work by writing one TypeScript program per task and running it:`,` - ptc_run_code for a plain program (its return value and console.log come back to you)`,` - ptc_workflow when the task has named phases and you want narration (log / phase /`,` parallel / pipeline are available there)`,``,`The program body is an async function. Available inside it: ${r.join(`, `)}, plus the`,'parallel binding `tools["pi.dispatch"](args)` — always bound, and its dot name needs string',"indexing (`tools.pi.dispatch` does not exist). The run's actual bound names are on the","`ptcBindings` global, so a program never has to guess what is bound this run.",i.length>0?`Examples:\n${i}`:``,``,`Batch a task's steps into ONE program instead of issuing many tool calls — gathering`,`intermediate output yourself and returning only what matters is the point of this mode.`,`Image-bearing tool results inside a program are attached to you after the run — never return`,`base64 image data as your program's value.`,`If the PTC surfaces cannot express what you need, say so and the user can run /ptc off.`].filter(e=>e.length>0).join(`
54
- `)}const uo=[`read`,`bash`],fo=`Use the read tool to load a skill's file when the task matches its description.`,po=`Use tools.read({ path }) inside a ptc_run_code program to load a skill's file when the task matches its description.`;function mo(e){return!uo.some(t=>e.includes(t))}function ho(e,t=v){let n=t([...e],`read`).trim();return n.length===0?``:n.includes(fo)?n.replace(fo,po):`${po}\n\n${n}`}const go=x.Object({task_id:x.Optional(x.String({description:`Id of the background task to poll with ptc_task_output. Present ONLY for a background call; absent once the call has already finished.`})),status:x.String({description:`"background" when this call returned a handle to poll, otherwise the dispatcher's own outcome status ("fulfilled").`}),report_channel:x.String({description:'Which channel delivered the child report: "prompt-json" (a fenced JSON block on the child\'s final message), "tool" (the child called the report tool), "none" (no report arrived — either the child did not comply with the contract, or this is a background handle that has not finished), or "opted-out" (the agent\'s frontmatter set `childReport: false`, so it was never asked). ALWAYS present, so an absent `report` key is never ambiguous — "none" and "opted-out" are different claims about the child.'}),exit_code:x.Optional(x.Number({description:`The child's exit code. Present ONLY for a call that already finished.`})),report:x.Optional(x.Object({summary:x.String({description:`One line, in the child's own words, of what it concluded.`}),findings:x.Array(x.Object({what:x.String({description:`The claim this finding makes.`}),evidence:x.String({description:`The independent thing that supports the claim.`})})),files_touched:x.Array(x.String({description:`A path the child created or modified.`})),usage:x.Object({input:x.Number({description:`Input tokens, counted by the host.`}),output:x.Number({description:`Output tokens, counted by the host.`}),cost:x.Number({description:`Total cost, counted by the host.`}),turns:x.Number({description:`Assistant turns, counted by the host.`})})}))});function _o(e){let t=e.taskId;return typeof t==`string`?t:void 0}function vo(e){return I({name:`ptc_subagent`,label:`PTC Subagent`,description:[`Start a fresh pi agent as a child process: it gets its own context, its own model and its own tools, and it cannot see or change this session except through what it returns. Use it for work that would otherwise flood this context: a survey, a second opinion, or a task that can run while you do something else.`,"`agent` is optional — omit it and the child is a fresh generalist pi, with pi's own system prompt and pi's full toolset. Name one to narrow the child instead: an agent is a markdown file at ~/.pi/agent/agents/<name>.md for your machine, or <project>/.pi/agents/<name>.md for one project, and naming one can restrict the child's tools, pin its model, or append a role. A name with no file behind it is refused; the refusal lists what IS registered and how to write one.",Nt({cwd:e.cwd,agentScope:e.agentRosterScope??`both`,...e.homeDir===void 0?{}:{homeDir:e.homeDir}})].join(`
55
- `),promptSnippet:`Start a fresh pi agent as a child process (foreground or background)`,promptGuidelines:[`Prefer one subagent over many tool calls when the work is a question with an answer rather than a fact you can look up, or when the raw output would be larger than the answer.`],parameters:un,outputSchema:go,async execute(t,n){let r=await rn(n,{callId:0,cwd:n.cwd??e.cwd,depth:e.depth,maxDispatchDepth:e.maxDispatchDepth,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId}},e.getDispatchDeps?.()??{}),i=_o(r),a=i===void 0?{taskId:void 0,status:r.status,exitCode:r.exitCode}:{taskId:i,status:`background`,exitCode:void 0};if(i!==void 0){let e={task_id:i,status:a.status,report_channel:`none`};return{content:[{type:`text`,text:`Started background task `+i}],details:a,structuredContent:e}}if(r.status===`rejected`)throw Error(`ptc_subagent refused the call: `+r.errorMessage);let o=r.report,s=a.exitCode===void 0?{status:a.status,report_channel:r.reportChannel}:o===void 0?{status:a.status,exit_code:a.exitCode,report_channel:r.reportChannel}:{status:a.status,exit_code:a.exitCode,report_channel:r.reportChannel,report:o};return{content:[{type:`text`,text:[Fr(o,r.reportChannel),r.text].filter(e=>e.length>0).join(`
54
+ `)}const Co=[`read`,`bash`],wo=`Use the read tool to load a skill's file when the task matches its description.`,To=`Use tools.read({ path }) inside a ptc_run_code program to load a skill's file when the task matches its description.`;function Eo(e){return!Co.some(t=>e.includes(t))}function Do(e,t=v){let n=t([...e],`read`).trim();return n.length===0?``:n.includes(wo)?n.replace(wo,To):`${To}\n\n${n}`}const Oo=x.Object({task_id:x.Optional(x.String({description:`Id of the background task to poll with ptc_task_output. Present ONLY for a background call; absent once the call has already finished.`})),status:x.String({description:`"background" when this call returned a handle to poll, otherwise the dispatcher's own outcome status ("fulfilled").`}),report_channel:x.String({description:'Which channel delivered the child report: "prompt-json" (a fenced JSON block on the child\'s final message), "tool" (the child called the report tool), "none" (no report arrived — either the child did not comply with the contract, or this is a background handle that has not finished), or "opted-out" (the agent\'s frontmatter set `childReport: false`, so it was never asked). ALWAYS present, so an absent `report` key is never ambiguous — "none" and "opted-out" are different claims about the child.'}),exit_code:x.Optional(x.Number({description:`The child's exit code. Present ONLY for a call that already finished.`})),read_only_tier:x.Optional(x.String({description:`The read-only tier the dispatch resolved to: "strict" or "lenient" (ADR-0041). Absent when no tier was asked for, so an absent key means "no tier" rather than "tier unknown".`})),report:x.Optional(x.Object({summary:x.String({description:`One line, in the child's own words, of what it concluded.`}),findings:x.Array(x.Object({what:x.String({description:`The claim this finding makes.`}),evidence:x.String({description:`The independent thing that supports the claim.`})})),files_touched:x.Array(x.String({description:`A path the child created or modified.`})),usage:x.Object({input:x.Number({description:`Input tokens, counted by the host.`}),output:x.Number({description:`Output tokens, counted by the host.`}),cost:x.Number({description:`Total cost, counted by the host.`}),turns:x.Number({description:`Assistant turns, counted by the host.`})})})),usage:x.Optional(x.Object({input:x.Number({description:`Input tokens, counted by the host.`}),output:x.Number({description:`Output tokens, counted by the host.`}),cost:x.Number({description:`Total cost, counted by the host.`}),turns:x.Number({description:`Assistant turns, counted by the host.`})},{description:"The host's own count for this child: the same four fields `report.usage` carries, projected from the `DispatchResult.usage` accumulator (ADR-0032, issue #199). ABSENT for a background handle, which has measured nothing yet, and for a child that emitted no usage block. Present on every settled call REGARDLESS of `report_channel`, so a child that reported nothing still accounts for what it cost — the text render states the same four numbers on its `usage` row."}))});function ko(e){let t=e.taskId;return typeof t==`string`?t:void 0}function Ao(e){return I({name:`ptc_subagent`,label:`PTC Subagent`,description:[`Start a fresh pi agent as a child process: it gets its own context, its own model and its own tools, and it cannot see or change this session except through what it returns. Use it for work that would otherwise flood this context: a survey, a second opinion, or a task that can run while you do something else.`,"`agent` is optional — omit it and the child is a fresh generalist pi, with pi's own system prompt and pi's full toolset. Name one to narrow the child instead: an agent is a markdown file at ~/.pi/agent/agents/<name>.md for your machine, or <project>/.pi/agents/<name>.md for one project, and naming one can restrict the child's tools, pin its model, or append a role. A name with no file behind it is refused; the refusal lists what IS registered and how to write one.",It({cwd:e.cwd,agentScope:e.agentRosterScope??`both`,...e.homeDir===void 0?{}:{homeDir:e.homeDir}})].join(`
55
+ `),promptSnippet:`Start a fresh pi agent as a child process (foreground or background)`,promptGuidelines:[`Prefer one subagent over many tool calls when the work is a question with an answer rather than a fact you can look up, or when the raw output would be larger than the answer.`],parameters:pn,outputSchema:Oo,async execute(t,n){let r=await sn(n,{callId:0,cwd:n.cwd??e.cwd,depth:e.depth,maxDispatchDepth:e.maxDispatchDepth,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId}},e.getDispatchDeps?.()??{}),i=ko(r),a=i===void 0?{taskId:void 0,status:r.status,exitCode:r.exitCode}:{taskId:i,status:`background`,exitCode:void 0};if(i!==void 0){let e=R(n.readOnly),t={task_id:i,status:a.status,report_channel:`none`,...e===void 0?{}:{read_only_tier:e}};return{content:[{type:`text`,text:[`Started background task `+i,sr(e)].filter(e=>e.length>0).join(`
56
56
 
57
- `)}],details:a,structuredContent:s}}})}function yo(e){return e.length<=200?e:`…`+e.slice(-199)}const bo=x.Object({summary:x.String({description:`One line, in your own words, of what you concluded.`}),findings:x.Array(x.Object({what:x.String({description:`The claim this finding makes.`}),evidence:x.String({description:`The independent thing that supports the claim — what you read, ran or checked. Not the claim restated.`})})),files_touched:x.Array(x.String({description:`A path you created or modified. Empty if you touched nothing.`}))}),xo=[`Hand the host a child report: what you did in this run, in the shape it can read without parsing English.`,`Call it once, at the end. The exact shape is stated in your instructions, which also tell you what to do if this tool is unavailable to you.`,`Evidence is the point of a finding. Put in the independent thing you read, ran or checked — the claim restated is not evidence, and a finding with none is worse than no finding.`,`files_touched lists only paths you actually created or modified; leave it empty rather than guessing.`,`Your prose answer is kept alongside this report and is never replaced by it, so still answer in words.`,`Do not report usage or token counts — those are measured by the host, and anything you send under them is discarded.`].join(`
58
- `);function So(e){return I({name:Le,label:`Child Report`,description:xo,promptSnippet:`Hand the host a child report when you finish`,promptGuidelines:[`Call ptc_child_report once before you finish, even when the answer is "I changed nothing": a child that reports an empty result is a different thing from a child that never reported, and only the first one says so.`],parameters:bo,outputSchema:bo,defaultActive:e,renderCall(e,t){let n=e,r=typeof n?.summary==`string`?n.summary:``;return new J([{left:t.fg(`toolTitle`,t.bold(`Child report`))+(r===``?``:` `+t.fg(`dim`,yo(r)))}])},renderResult(){return new J([{left:`child report recorded`}])},async execute(e,t){let n={summary:t.summary,findings:t.findings.map(e=>({what:e.what,evidence:e.evidence})),files_touched:[...t.files_touched]};return{content:[{type:`text`,text:`child report recorded (`+String(n.findings.length)+` findings)`}],details:void 0,structuredContent:n}}})}const Co=xa;function wo(e,t,n){return[`PTC mode on — ${t===`all-but-ptc`?`all other tools`:`built-in tools (now reachable only as tools.<name> inside a program)`} hidden.`,`Bindings available inside a program: ${W(e,n).join(`, `)||`(none)`}.`,`Run /ptc off to restore the normal tool set.`].join(`
59
- `)}function To(e,t={}){let n=Sa(),r,i=!1,a=new Hi,o=()=>oo(n,e.getActiveTools()),s=wa(y()),c=s.optInBindings,l=()=>c,u=Gn(),d=Kn(),f=t.backgroundRuntime??ca({concurrency:Be({}).dispatchConcurrency}),p=!1,m=e=>{console.warn(`[pi-ptc.background] `+e)},h=t=>{if(t.length!==0){if(p){e.sendMessage({customType:`bg-task-notification`,content:t,display:!1},{deliverAs:`steer`});return}e.sendUserMessage(t)}},g=async e=>{let{items:t,acks:n}=await f.drainNotifications(e),r=t.filter(e=>ua(e.record));for(let e of fa(r))h(da(e,{batchId:Oe(),deliveredAtMs:f.clock()}));await f.acknowledgeNotifications(n)},_=async()=>{let e=await f.registry.query({limit:2**53-1}),t=/* @__PURE__ */ new Set;for(let n of e){let e=n.spawnSource.callerId;e.length>0&&t.add(e)}return[...t]},v=async()=>{for(let e of await _())await g(e)},b=async e=>{let t=/* @__PURE__ */ new Set;for(let n of e){let e=n.spawnSource.callerId;e.length>0&&t.add(e)}for(let e of t)await g(e)};f.pipeline.onIdleWake(e=>{g(e).catch(e=>{m(`notification delivery failed: `+(e instanceof Error?e.message:String(e)))})});function x(t){if(t.surfaceMode===`full`||t.surfaceMode===`subagents`){let n=t.surfaceMode===`full`?`direct`:`codemode`;e.registerTool(Jr({getBindingSourceNames:o,getOptInBindings:l,getPool:()=>a.get(`run_code`),depth:u,exposure:n,...d===void 0?{}:{parentTaskId:d},getDispatchDeps:()=>f.dispatchDeps})),e.registerTool(ei({getBindingSourceNames:o,getOptInBindings:l,getPool:()=>a.get(`workflow`),depth:u,exposure:n,...d===void 0?{}:{parentTaskId:d},getDispatchDeps:()=>f.dispatchDeps}))}t.surfaceMode===`subagents`&&e.registerTool(vo({cwd:process.cwd(),depth:u,maxDispatchDepth:L.maxDispatchDepth,...d===void 0?{}:{parentTaskId:d},getDispatchDeps:()=>f.dispatchDeps})),e.registerTool(Ni(f.registry)),e.registerTool(Ri(f.registry,f.outputStorage)),e.registerTool(Vi(f.registry,f.lifecycle,{clock:f.clock})),e.registerTool(So(u>0))}let S=!1,C=t=>{S||r.codemodeActivation.activation===`inactive`&&e.getActiveTools().includes(`codemode`)&&(S=!0,t.ui.notify(`pi-ptc-subagents: pi's codemode is active in this session, but nothing this package reads predicted it — no tool list names it and no readable mcp.json auto-enables it — so the surface defaulted to full, and your model is being offered two orchestration tools. pi activates codemode at runtime in ways no settings file records (its MCP extension is one). Run pi with codemode active (-t codemode, or add it to defaultTools) to get the subagents surface instead.`,`warning`))};e.on(`turn_start`,async(e,t)=>{p=!0,C(t)}),e.on(`agent_settled`,async()=>{p=!1;try{await v()}catch(e){m(`agent_settled delivery failed: `+(e instanceof Error?e.message:String(e)))}}),e.on(`turn_end`,async()=>{let e=a;a=new Hi,await e.drain()});let w=e=>{let t=[];n.enabled&&t.push(e.ui.theme.fg(`accent`,`PTC`)),e.ui.setStatus(ya,t.length>0?t.join(` `):void 0)},T=(t,r,a,o)=>{n.enabled=!0,n.base=t,n.ourLoadout=r,e.setActiveTools([...r]),i=!0,e.appendEntry(va,{enabled:!0,base:[...t]}),w(a),a.ui.notify(o,`info`)},ee=(t,r)=>{let a=n.base;n.enabled=!1,n.base=void 0,n.ourLoadout=void 0,i=!1,a!==void 0&&e.setActiveTools([...a]),e.appendEntry(r.customType,{enabled:!1}),w(t),r.announce&&t.ui.notify(`PTC mode off — built-in tools are directly callable again.`,`info`)},te=e=>{let t=e.sessionManager.getEntries();for(let e=t.length-1;e>=0;--e){let n=t[e];if(n?.type!==`custom`||n.customType!==`ptc-mode`)continue;let r=n.data,i=Array.isArray(r?.base)?r.base.filter(e=>typeof e==`string`):void 0;return{enabled:r?.enabled===!0,...i===void 0?{}:{base:i}}}};e.registerCommand(`ptc`,{description:`Show or toggle PTC mode`,handler:async(t,r)=>{let i=t.trim().toLowerCase();if(i===`off`){if(!n.enabled){r.ui.notify(`PTC mode is already off.`,`info`);return}ee(r,{announce:!0,customType:va});return}if(i!==`on`){r.ui.notify(n.enabled?`PTC mode is ON — run /ptc off to restore built-in tools.\nBindings: ${W(n.base,c).join(`, `)||`(none)`}`:`PTC mode is OFF — run /ptc on to enter it.`,`info`);return}if(n.enabled){r.ui.notify(`PTC mode is already on.`,`info`);return}let a=ao({mode:r.mode,defaultMode:!0,active:e.getActiveTools(),manual:!0,hide:Co});if(!a.enter){r.ui.notify(a.reason===`tools-unavailable`?`Cannot enter PTC mode: ptc_run_code / ptc_workflow are not active in this session.`:`Cannot enter PTC mode in this run mode.`,`warning`);return}T(a.base,a.loadout,r,wo(a.base,Co,c))}}),e.on(`session_start`,async(n,i)=>{r=eo(y(),e.getActiveTools(),t.codemode,t.codemodeSwitch,t.codemodeActivation),x(r),p=!1;let a=await f.bindSession(i.sessionManager?.getSessionDir?.(),e=>i.ui.notify(e,`warning`));try{await b(a)}catch(e){m(`startup reconcile delivery failed: `+(e instanceof Error?e.message:String(e)))}let o=Ca(y());o.error!==void 0&&i.ui.notify(`pi-ptc-subagents: ${o.error}`,`warning`),s.error!==void 0&&i.ui.notify(`pi-ptc-subagents: ${s.error}. No opt-in binding was granted, so the PTC surface stays narrowed. Opt-in bindings: ${an.join(`, `)}.`,`warning`);let l=to(y());l!==void 0&&i.ui.notify(`pi-ptc-subagents: `+l.path+` still has a "surfaceMode" key (`+JSON.stringify(l.value)+"), and it is no longer read: the surface is detected from what pi is, and no key pins it. To keep this package out of your sessions entirely, turn it off in pi -- run `pi config` and disable this package's extensions there (its `extensions` entry set to [] stops pi loading it at all). To silence this notice, delete the key.",`warning`);let u=r.codemode;u.present||i.ui.notify(`pi-ptc-subagents: the codemode probe reported `+u.how+`, so the surface is full. That is the safe direction, not an error.`,`info`),r.codemodeSwitch?.error!==void 0&&i.ui.notify(`pi-ptc-subagents: ${r.codemodeSwitch.error}`,`warning`),r.codemodeActivation?.mcpError!==void 0&&i.ui.notify(`pi-ptc-subagents: ${r.codemodeActivation.mcpError}`,`warning`);{let t=e.getAllTools().some(e=>e.name===`codemode`);!u.present&&t&&i.ui.notify(`pi-ptc-subagents: this session registers pi's codemode, but the probe did not find it (`+u.how+`), so the surface defaulted to full, and your model is being offered two orchestration tools. Enable codemode for real (-t codemode) to get the subagents surface instead.`,`warning`),u.present&&!t&&i.ui.notify(`pi-ptc-subagents: the codemode probe found pi's codemode on disk, but this session does not register it (--no-extensions), so the surface is `+JSON.stringify(r.surfaceMode)+(r.surfaceMode===`subagents`?` with no orchestrator: ptc_run_code and ptc_workflow are reachable only from codemode, and this session has none. Launch with codemode active (pi -t codemode), or turn this package off with pi config.`:`.`),`warning`)}if(r.surfaceMode===`subagents`&&!e.getActiveTools().includes(`codemode`)){let t=e.getActiveTools();t.includes(`ptc_run_code`)||t.includes(`ptc_workflow`)||i.ui.notify(`pi-ptc-subagents: the detected surface is subagents, but codemode is not active in this session, so there is no orchestration tool. Add codemode to your pi tool list (the --tools flag or the default tools setting), or turn this package off with pi config.`,`warning`)}C(i);let d=te(i),{base:h,restoreFirst:g}=co(d,e.getActiveTools());g&&e.setActiveTools([...h]);let _=ao({mode:i.mode,defaultMode:o.defaultMode,active:h,manual:!1,hide:Co}),v=d?.enabled??_.enter;if(_.enter&&v){T(h,_.loadout,i,wo(h,Co,c));return}w(i),!_.enter&&_.reason!==`not-tui`&&d===void 0&&_.reason===`restricted-session`&&i.ui.notify(`PTC mode skipped: this session was launched with an explicit tool restriction.`,`info`)}),e.on(`session_shutdown`,async()=>{p=!1;try{await f.shutdown(`session_ended_while_running`)}catch(e){m(`session shutdown failed: `+(e instanceof Error?e.message:String(e)))}});let ne=!1,re=(e,t)=>{if(e===void 0)return;if(!n.enabled||!t){ne&&=(delete e.sections.skills,!1);return}let r=ho(e.skills);r.length!==0&&(e.sections.skills=r,ne=!0)};e.on(`before_agent_start`,async(t,r)=>{let a=t.systemPromptOptions;if(re(a,mo(e.getActiveTools())),n.enabled){if(so(n,e.getActiveTools())){ee(r,{announce:!1,customType:va}),re(a,mo(e.getActiveTools())),r.ui.notify(`PTC mode off — another extension changed the active tool set.`,`warning`);return}if(i)return i=!1,{message:{customType:`ptc-mode-briefing`,content:lo(W(n.base,c),Co),display:!1}}}})}export{R as BUILTIN_BINDING_NAMES,cn as DEFAULT_BINDING_NAMES,L as DEFAULT_CONFIG,xa as DEFAULT_HIDE_STRATEGY,o as HOST_FRAME_KIND,Nn as MAX_LINE_CHARS,_a as MODE_REQUIRED_TOOL_NAMES,an as OPT_IN_BINDING_NAMES,n as PTC_ERROR_KIND,i as PTC_LOG_LEVEL,ba as PTC_MODE_CONFIG_FILE,va as PTC_MODE_ENTRY_TYPE,ya as PTC_MODE_STATUS_KEY,ga as PTC_MODE_TOOL_NAMES,po as PTC_SKILL_LOAD_INSTRUCTION,uo as SKILL_READING_TOOL_NAMES,Hi as TurnPools,Re as WORKER_ENV_ALLOW_LIST,t as WORKER_FRAME_KIND,gn as WorkerPool,oo as bindingSource,lo as buildModeInstruction,ho as buildPtcSkillsSection,pn as createBuiltinBindings,ze as createWorkerEnv,ao as decideModeEntry,To as default,so as detectExternalLoadoutChange,eo as detectSurfaceMode,Za as detectedSurfaceMode,Ve as effectiveTimeoutMs,Sa as initialModeState,on as isOptInBindingName,io as modeLoadout,Qa as probeCodemodePresence,Fa as readCodemodeSwitch,Ca as readDefaultModeConfig,to as readLegacySurfaceKey,wa as readOptInBindingsConfig,Wn as renderModelValue,co as resolveBaseOnStart,Ia as resolveCodemodeActivation,Pa as resolveCodemodeSwitch,Be as resolveConfig,sn as resolveOptInBindingNames,Tn as runPtcProgram,ro as sameToolSet,U as sanitizeText,mo as skillsSectionDropped,Fn as stripAnsi};
57
+ `)}],details:a,structuredContent:t}}if(r.status===`rejected`)throw Error(`ptc_subagent refused the call: `+r.errorMessage);let o=r.report,s=r.readOnlyTier===void 0?{}:{read_only_tier:r.readOnlyTier},c=r.usage===void 0?{}:{usage:{input:r.usage.input,output:r.usage.output,cost:r.usage.cost,turns:r.usage.turns}},l=a.exitCode===void 0?{status:a.status,report_channel:r.reportChannel,...s,...c}:o===void 0?{status:a.status,exit_code:a.exitCode,report_channel:r.reportChannel,...s,...c}:{status:a.status,exit_code:a.exitCode,report_channel:r.reportChannel,report:o,...s,...c},u=Wr(o,r.reportChannel,r.usage);return{content:[{type:`text`,text:[sr(r.readOnlyTier),u,r.text].filter(e=>e.length>0).join(`
58
+
59
+ `)}],details:a,structuredContent:l}}})}function jo(e){return e.length<=200?e:`…`+e.slice(-199)}const Mo=x.Object({summary:x.String({description:`One line, in your own words, of what you concluded.`}),findings:x.Array(x.Object({what:x.String({description:`The claim this finding makes.`}),evidence:x.String({description:`The independent thing that supports the claim — what you read, ran or checked. Not the claim restated.`})})),files_touched:x.Array(x.String({description:`A path you created or modified. Empty if you touched nothing.`}))}),No=[`Hand the host a child report: what you did in this run, in the shape it can read without parsing English.`,`Call it once, at the end. The exact shape is stated in your instructions, which also tell you what to do if this tool is unavailable to you.`,`Evidence is the point of a finding. Put in the independent thing you read, ran or checked — the claim restated is not evidence, and a finding with none is worse than no finding.`,`files_touched lists only paths you actually created or modified; leave it empty rather than guessing.`,`Your prose answer is kept alongside this report and is never replaced by it, so still answer in words.`,`Do not report usage or token counts — those are measured by the host, and anything you send under them is discarded.`].join(`
60
+ `);function Po(e){return I({name:Le,label:`Child Report`,description:No,promptSnippet:`Hand the host a child report when you finish`,promptGuidelines:[`Call ptc_child_report once before you finish, even when the answer is "I changed nothing": a child that reports an empty result is a different thing from a child that never reported, and only the first one says so.`],parameters:Mo,outputSchema:Mo,defaultActive:e,renderCall(e,t){let n=e,r=typeof n?.summary==`string`?n.summary:``;return new q([{left:t.fg(`toolTitle`,t.bold(`Child report`))+(r===``?``:` `+t.fg(`dim`,jo(r)))}])},renderResult(){return new q([{left:`child report recorded`}])},async execute(e,t){let n={summary:t.summary,findings:t.findings.map(e=>({what:e.what,evidence:e.evidence})),files_touched:[...t.files_touched]};return{content:[{type:`text`,text:`child report recorded (`+String(n.findings.length)+` findings)`}],details:void 0,structuredContent:n}}})}const $=Na;function Fo(e,t,n){return[`PTC mode on — ${t===`all-but-ptc`?`all other tools`:`built-in tools (now reachable only as tools.<name> inside a program)`} hidden.`,`Bindings available inside a program: ${W(e,n).join(`, `)||`(none)`}.`,`Run /ptc off to restore the normal tool set.`].join(`
61
+ `)}function Io(e,t={}){let n=Pa(),r,i=!1,a=new ea,o=()=>yo(n,e.getActiveTools()),s=Ia(y()),c=s.optInBindings,l=()=>c,u=Zn(),d=Qn(),f=t.backgroundRuntime??ba({concurrency:Be({}).dispatchConcurrency}),p=!1,m=e=>{console.warn(`[pi-ptc.background] `+e)},h=t=>{if(t.length!==0){if(p){e.sendMessage({customType:`bg-task-notification`,content:t,display:!1},{deliverAs:`steer`});return}e.sendUserMessage(t)}},g=async e=>{let{items:t,acks:n}=await f.drainNotifications(e),r=t.filter(e=>Sa(e.record));for(let e of wa(r))h(Ca(e,{batchId:Oe(),deliveredAtMs:f.clock()}));await f.acknowledgeNotifications(n)},_=async()=>{let e=await f.registry.query({limit:2**53-1}),t=/* @__PURE__ */ new Set;for(let n of e){let e=n.spawnSource.callerId;e.length>0&&t.add(e)}return[...t]},v=async()=>{for(let e of await _())await g(e)},b=async e=>{let t=/* @__PURE__ */ new Set;for(let n of e){let e=n.spawnSource.callerId;e.length>0&&t.add(e)}for(let e of t)await g(e)};f.pipeline.onIdleWake(e=>{g(e).catch(e=>{m(`notification delivery failed: `+(e instanceof Error?e.message:String(e)))})});function x(t){if(t.surfaceMode===`full`||t.surfaceMode===`subagents`){let n=t.surfaceMode===`full`?`direct`:`codemode`;e.registerTool(ri({getBindingSourceNames:o,getOptInBindings:l,getPool:()=>a.get(`run_code`),depth:u,exposure:n,...d===void 0?{}:{parentTaskId:d},getDispatchDeps:()=>f.dispatchDeps})),e.registerTool(li({getBindingSourceNames:o,getOptInBindings:l,getPool:()=>a.get(`workflow`),depth:u,exposure:n,...d===void 0?{}:{parentTaskId:d},getDispatchDeps:()=>f.dispatchDeps}))}t.surfaceMode===`subagents`&&e.registerTool(Ao({cwd:process.cwd(),depth:u,maxDispatchDepth:L.maxDispatchDepth,...d===void 0?{}:{parentTaskId:d},getDispatchDeps:()=>f.dispatchDeps})),e.registerTool(Hi(f.registry)),e.registerTool(Xi(f.registry,f.outputStorage)),e.registerTool($i(f.registry,f.lifecycle,{clock:f.clock})),e.registerTool(Po(u>0))}let S=!1,C=t=>{S||r.codemodeActivation.activation===`inactive`&&e.getActiveTools().includes(`codemode`)&&(S=!0,t.ui.notify(`pi-ptc-subagents: pi's codemode is active in this session, but nothing this package reads predicted it — no tool list names it and no readable mcp.json auto-enables it — so the surface defaulted to full, and your model is being offered two orchestration tools. pi activates codemode at runtime in ways no settings file records (its MCP extension is one). Run pi with codemode active (-t codemode, or add it to defaultTools) to get the subagents surface instead.`,`warning`))};e.on(`turn_start`,async(e,t)=>{p=!0,C(t)}),e.on(`agent_settled`,async()=>{p=!1;try{await v()}catch(e){m(`agent_settled delivery failed: `+(e instanceof Error?e.message:String(e)))}}),e.on(`turn_end`,async()=>{let e=a;a=new ea,await e.drain()});let w=e=>{let t=[];n.enabled&&t.push(e.ui.theme.fg(`accent`,`PTC`)),e.ui.setStatus(ja,t.length>0?t.join(` `):void 0)},T=(t,r,a,o)=>{n.enabled=!0,n.base=t,n.ourLoadout=r,e.setActiveTools([...r]),i=!0,e.appendEntry(Aa,{enabled:!0,base:[...t]}),w(a),a.ui.notify(o,`info`)},ee=(t,r)=>{let a=n.base;n.enabled=!1,n.base=void 0,n.ourLoadout=void 0,i=!1,a!==void 0&&e.setActiveTools([...a]),e.appendEntry(r.customType,{enabled:!1}),w(t),r.announce&&t.ui.notify(`PTC mode off — built-in tools are directly callable again.`,`info`)},te=e=>{let t=e.sessionManager.getEntries();for(let e=t.length-1;e>=0;--e){let n=t[e];if(n?.type!==`custom`||n.customType!==`ptc-mode`)continue;let r=n.data,i=Array.isArray(r?.base)?r.base.filter(e=>typeof e==`string`):void 0;return{enabled:r?.enabled===!0,...i===void 0?{}:{base:i}}}};e.registerCommand(`ptc`,{description:`Show or toggle PTC mode`,handler:async(t,r)=>{let i=t.trim().toLowerCase();if(i===`off`){if(!n.enabled){r.ui.notify(`PTC mode is already off.`,`info`);return}ee(r,{announce:!0,customType:Aa});return}if(i!==`on`){r.ui.notify(n.enabled?`PTC mode is ON — run /ptc off to restore built-in tools.\nBindings: ${W(n.base,c).join(`, `)||`(none)`}`:`PTC mode is OFF — run /ptc on to enter it.`,`info`);return}if(n.enabled){r.ui.notify(`PTC mode is already on.`,`info`);return}let a=vo({mode:r.mode,defaultMode:!0,active:e.getActiveTools(),manual:!0,hide:$});if(!a.enter){r.ui.notify(a.reason===`tools-unavailable`?`Cannot enter PTC mode: ptc_run_code / ptc_workflow are not active in this session.`:`Cannot enter PTC mode in this run mode.`,`warning`);return}T(a.base,a.loadout,r,Fo(a.base,$,c))}}),e.on(`session_start`,async(n,i)=>{r=po(y(),e.getActiveTools(),t.codemode,t.codemodeSwitch,t.codemodeActivation),x(r),p=!1;let a=await f.bindSession(i.sessionManager?.getSessionDir?.(),e=>i.ui.notify(e,`warning`));try{await b(a)}catch(e){m(`startup reconcile delivery failed: `+(e instanceof Error?e.message:String(e)))}let o=Fa(y());o.error!==void 0&&i.ui.notify(`pi-ptc-subagents: ${o.error}`,`warning`),s.error!==void 0&&i.ui.notify(`pi-ptc-subagents: ${s.error}. No opt-in binding was granted, so the PTC surface stays narrowed. Opt-in bindings: ${cn.join(`, `)}.`,`warning`);let l=mo(y());l!==void 0&&i.ui.notify(`pi-ptc-subagents: `+l.path+` still has a "surfaceMode" key (`+JSON.stringify(l.value)+"), and it is no longer read: the surface is detected from what pi is, and no key pins it. To keep this package out of your sessions entirely, turn it off in pi -- run `pi config` and disable this package's extensions there (its `extensions` entry set to [] stops pi loading it at all). To silence this notice, delete the key.",`warning`);let u=r.codemode;u.present||i.ui.notify(`pi-ptc-subagents: the codemode probe reported `+u.how+`, so the surface is full. That is the safe direction, not an error.`,`info`),r.codemodeSwitch?.error!==void 0&&i.ui.notify(`pi-ptc-subagents: ${r.codemodeSwitch.error}`,`warning`),r.codemodeActivation?.mcpError!==void 0&&i.ui.notify(`pi-ptc-subagents: ${r.codemodeActivation.mcpError}`,`warning`);{let t=e.getAllTools().some(e=>e.name===`codemode`);!u.present&&t&&i.ui.notify(`pi-ptc-subagents: this session registers pi's codemode, but the probe did not find it (`+u.how+`), so the surface defaulted to full, and your model is being offered two orchestration tools. Enable codemode for real (-t codemode) to get the subagents surface instead.`,`warning`),u.present&&!t&&i.ui.notify(`pi-ptc-subagents: the codemode probe found pi's codemode on disk, but this session does not register it (--no-extensions), so the surface is `+JSON.stringify(r.surfaceMode)+(r.surfaceMode===`subagents`?` with no orchestrator: ptc_run_code and ptc_workflow are reachable only from codemode, and this session has none. Launch with codemode active (pi -t codemode), or turn this package off with pi config.`:`.`),`warning`)}if(r.surfaceMode===`subagents`&&!e.getActiveTools().includes(`codemode`)){let t=e.getActiveTools();t.includes(`ptc_run_code`)||t.includes(`ptc_workflow`)||i.ui.notify(`pi-ptc-subagents: the detected surface is subagents, but codemode is not active in this session, so there is no orchestration tool. Add codemode to your pi tool list (the --tools flag or the default tools setting), or turn this package off with pi config.`,`warning`)}C(i);let d=te(i),{base:h,restoreFirst:g}=xo(d,e.getActiveTools());g&&e.setActiveTools([...h]);let _=vo({mode:i.mode,defaultMode:o.defaultMode,active:h,manual:!1,hide:$}),v=d?.enabled??_.enter;if(_.enter&&v){T(h,_.loadout,i,Fo(h,$,c));return}w(i),!_.enter&&_.reason!==`not-tui`&&d===void 0&&_.reason===`restricted-session`&&i.ui.notify(`PTC mode skipped: this session was launched with an explicit tool restriction.`,`info`)}),e.on(`session_shutdown`,async()=>{p=!1;try{await f.shutdown(`session_ended_while_running`)}catch(e){m(`session shutdown failed: `+(e instanceof Error?e.message:String(e)))}});let E=!1,D=(e,t)=>{if(e===void 0)return;if(!n.enabled||!t){E&&=(delete e.sections.skills,!1);return}let r=Do(e.skills);r.length!==0&&(e.sections.skills=r,E=!0)};e.on(`before_agent_start`,async(t,r)=>{let a=t.systemPromptOptions;if(D(a,Eo(e.getActiveTools())),n.enabled){if(bo(n,e.getActiveTools())){ee(r,{announce:!1,customType:Aa}),D(a,Eo(e.getActiveTools())),r.ui.notify(`PTC mode off — another extension changed the active tool set.`,`warning`);return}if(i)return i=!1,{message:{customType:`ptc-mode-briefing`,content:So(W(n.base,c),$),display:!1}}}})}export{B as BUILTIN_BINDING_NAMES,dn as DEFAULT_BINDING_NAMES,L as DEFAULT_CONFIG,Na as DEFAULT_HIDE_STRATEGY,o as HOST_FRAME_KIND,zn as MAX_LINE_CHARS,ka as MODE_REQUIRED_TOOL_NAMES,cn as OPT_IN_BINDING_NAMES,n as PTC_ERROR_KIND,i as PTC_LOG_LEVEL,Ma as PTC_MODE_CONFIG_FILE,Aa as PTC_MODE_ENTRY_TYPE,ja as PTC_MODE_STATUS_KEY,Oa as PTC_MODE_TOOL_NAMES,To as PTC_SKILL_LOAD_INSTRUCTION,Co as SKILL_READING_TOOL_NAMES,ea as TurnPools,Re as WORKER_ENV_ALLOW_LIST,t as WORKER_FRAME_KIND,Sn as WorkerPool,yo as bindingSource,So as buildModeInstruction,Do as buildPtcSkillsSection,_n as createBuiltinBindings,ze as createWorkerEnv,vo as decideModeEntry,Io as default,bo as detectExternalLoadoutChange,po as detectSurfaceMode,lo as detectedSurfaceMode,Ve as effectiveTimeoutMs,Pa as initialModeState,ln as isOptInBindingName,_o as modeLoadout,uo as probeCodemodePresence,qa as readCodemodeSwitch,Fa as readDefaultModeConfig,mo as readLegacySurfaceKey,Ia as readOptInBindingsConfig,Xn as renderModelValue,xo as resolveBaseOnStart,Ja as resolveCodemodeActivation,Ka as resolveCodemodeSwitch,Be as resolveConfig,un as resolveOptInBindingNames,jn as runPtcProgram,go as sameToolSet,U as sanitizeText,Eo as skillsSectionDropped,Vn as stripAnsi};
60
62
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ptc-subagents",
3
- "version": "3.1.0",
3
+ "version": "3.3.0",
4
4
  "description": "Programmable tool calling (PTC) and subagent fan-out for pi — the model writes JS/TS programs that call pi's tools, or fans out to a fresh pi subprocess per subagent task",
5
5
  "keywords": [
6
6
  "pi",