pi-ptc-subagents 1.5.0 → 1.6.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
@@ -9,6 +9,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  (nothing yet)
11
11
 
12
+ ## [1.6.0] - 2026-10-08
13
+
14
+ ### Fixed
15
+
16
+ - **On pi 1.0, a session with MCP servers was offered two orchestration tools at once.** pi's MCP
17
+ extension activates pi's own `codemode` tool by itself — MCP tools default to `codemode`
18
+ exposure so that they are reachable only from scripts — and it does that with a
19
+ `pi.setActiveTools` call that no settings file records. This package's surface detection
20
+ ([ADR-0025](./docs/adr/0025-extension-surface-is-a-setting.md)) asked whether `codemode` would
21
+ be _active_ by mirroring pi's loadout resolution alone ([ADR-0029](./docs/adr/0029-surface-follows-codemode-activation.md)),
22
+ so on exactly the sessions pi 1.0 is built around it answered _not active_, registered
23
+ `ptc_run_code` + `ptc_workflow` as well, and handed the model two ways to compose tools. Detection
24
+ now reads pi's MCP configuration (`<agentDir>/mcp.json`, then `<cwd>/.pi/mcp.json`) as a second
25
+ evidence source and unions the two, so those sessions resolve `subagents`: `codemode` for
26
+ orchestration, `ptc_subagent` and the task lifecycle for fan-out.
27
+ [ADR-0033](./docs/adr/0033-mcp-auto-enable-evidence.md) records the mirror, what it deliberately
28
+ does not mirror, and the one under-report path that stays open (a server registered through
29
+ `pi.registerMcpServer()`, which no file records — the drift notice below is what covers it).
30
+
31
+ ### Added
32
+
33
+ - **A session start warning for an active `codemode` the probes did not predict.** Once per
34
+ session, and only on a detected surface: if nothing in `settings.json` or a readable `mcp.json`
35
+ said codemode would be active, the surface defaulted to `full`, and pi's real tool loadout
36
+ contains `codemode` anyway, the session is now told it is carrying two orchestration surfaces and
37
+ which `surfaceMode` key picks one. Checked at session start and again on the first turn, because
38
+ pi's MCP extension may activate codemode after this package's own `session_start` runs. It is
39
+ `TUI`-only, like every other notice in this package.
40
+ - **A named report for an `mcp.json` this package could not read.** A file that is absent is
41
+ silent, matching pi; a file that exists and cannot be parsed or read is named at session start
42
+ with its path, and when both files are broken both are named in the one line.
43
+
44
+ ### Changed
45
+
46
+ - **`CONTEXT.md` gains a `codemode activation` entry** defining the question surface detection asks
47
+ and its two evidence classes, so "is codemode active" no longer has to be reconstructed from an
48
+ ADR.
49
+ - ADR-0029 carries an amendment: its under-reporting bound still holds, but the premise it rested
50
+ on — that the loadout is the only way pi activates codemode — did not.
51
+
52
+ ## [1.5.1] - 2026-10-08
53
+
54
+ ### Fixed
55
+
56
+ - **Two claims 1.5.0's changelog made about this repository were false, and are now corrected in
57
+ the repository itself.** 1.5.0's tarball still carries the original wording — published tarballs
58
+ are immutable — so the correction lives here, in `main`, and in
59
+ [ADR-0031](./docs/adr/0031-open-source-and-publish-authority.md)'s amendment blocks:
60
+ - _"The repository is public … release authority is enforced by a `refs/tags/v*` ruleset."_ The
61
+ repository was still private at 1.5.0's release, and no ruleset existed. Both were done
62
+ 2026-10-08, hours after the gap was measured: the flip, then an active ruleset (id 24698892)
63
+ on `refs/heads/main` — no pushes, no merges, no deletions, no force-pushes except by
64
+ `a1121611810` as sole bypass actor, with one approving review and green `format` / `oxlint` /
65
+ `test` checks required for everyone else.
66
+ - _"The next version published from here carries an npm provenance attestation."_ No published
67
+ version through 1.5.0 has one, because the provenance precondition (a public source
68
+ repository) only became true with the flip above. **1.5.1 is the first version whose
69
+ precondition held** — see `dist.attestations` on the registry.
70
+
71
+ How the false claims shipped: they were written as decisions in an earlier session
72
+ (`c1dda59`), recorded as facts, and every gate in this repository checks the shape of a claim —
73
+ that a `file:line` resolves, that a constant matches a rule — not whether the thing a sentence
74
+ describes exists. Five review rounds and a green release gate passed them. The same class of
75
+ gap is recorded in `docs/testing-constraints.md` §"What the gate does not check".
76
+
77
+ ### Added
78
+
79
+ - **`docs/prototypes/` — the bgdispatch design records, recovered from research branches.** The
80
+ ten research branches deleted in the run-up to going public carried twelve verdict /
81
+ measurement / prototype files that had never been merged to `main`: the records of _why_ the
82
+ background-dispatch design is what it is. They were recovered before the branches were deleted;
83
+ `AGENTS.md` treats records as load-bearing.
84
+ - **`.mailmap`**, so the public commit history displays `a1121611810` instead of the 224-character
85
+ padded name that authored 309 commits. No history rewrite.
86
+
87
+ ### Changed
88
+
89
+ - **`.gitignore` gains `.zcode/` and `.scratch/`.** `.zcode/` was previously protected only by two
90
+ nested self-ignoring `.gitignore` files that are themselves untracked. `.scratch/` (local ticket
91
+ drafts, content duplicated on GitHub Issues) is removed from tracking.
92
+ - **Twelve research / feature branches and two `backup/undo-*` tags deleted from the remote.**
93
+ They carried the developer's machine-local paths (`/Users/lilianda`) that `main` had already
94
+ scrubbed; GitHub publishes every ref, not just `main`, so a public reader could have clicked
95
+ into them. Content was verified present in `main` (or recovered above) before each deletion.
96
+ Four routine `dependabot/*` bumps remain as open branches for the maintainer to review.
97
+ - **`docs/prototypes/**` excluded from oxlint.** The recovered files are measurement scripts and
98
+ were never part of the linted source; they are records, not production code.
99
+ - **The npm mirror noted during the audit turned out to be local configuration, not the
100
+ lockfile** — `pnpm-lock.yaml` carries no registry URLs at all.
101
+
12
102
  ## [1.5.0] - 2026-10-08
13
103
 
14
104
  ### Added
@@ -50,10 +140,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
50
140
  `refs/tags/v*` ruleset plus the npm package's "Require two-factor authentication and disallow
51
141
  tokens" setting, so it no longer depends on where a credential file is kept
52
142
  ([ADR-0031](./docs/adr/0031-open-source-and-publish-authority.md) §A–§B).
143
+ ~~**Measured 2026-10-08: this did not happen.** The repository is still private and no ruleset
144
+ exists — see §Unreleased above and ADR-0031's correction block. The npm 2FA setting is unverified
145
+ and is not claimed here.~~
53
146
  - **The next version published from here carries an npm provenance attestation.** Under trusted
54
147
  publishing npm generates it automatically once the source repository is public, with no workflow
55
148
  change — so the `homepage` and `repository` fields that pointed at a private GitHub now resolve,
56
149
  and the missing provenance badge that ADR-0018 §7 recorded as expected is no longer expected.
150
+ ~~**Measured 2026-10-08: this is false and always was.** `dist.attestations` is empty for every
151
+ published version including 1.5.0; the repository was never public, so the precondition never
152
+ held and ADR-0018 §7 stands unamended.~~
57
153
  - **`node scripts/preview-ptc-render.mjs` requires `PI_ROOT`.** It imported pi's theme from a hard-coded
58
154
  path on one developer's machine, so following the README from anywhere else failed inside a
59
155
  module loader. It now reads the install directory from the environment and, when it is missing or
package/dist/index.d.ts CHANGED
@@ -719,27 +719,40 @@ export declare function readCodemodeSwitch(agentDir: string, cwd: string, argv?:
719
719
  * Whether `codemode` will be CALLABLE, as a third question distinct from whether pi ships the
720
720
  * directory (ADR-0026) and whether it will load the extension (ADR-0027).
721
721
  *
722
- * - `"active"` — a loadout names it, so the model can call it.
723
- * - `"inactive"` — nothing names it, which on a real install is the DEFAULT: pi registers
724
- * `codemode` with `defaultActive: false` and activates it only when a loadout says so.
722
+ * - `"active"` — a loadout names it OR pi's MCP extension will auto-enable it from `mcp.json`
723
+ * (ADR-0033), so the model can call it.
724
+ * - `"inactive"` — nothing names it and nothing auto-enables it, which on a real install is the
725
+ * DEFAULT: pi registers `codemode` with `defaultActive: false`
726
+ * (`dist/extensions/codemode/index.js:26`).
725
727
  *
726
728
  * `"inactive"` is what every failure of this probe on the positive side resolves to, and that is
727
729
  * the design rather than a fallback: `subagents` is chosen only on positive evidence that the tool
728
730
  * is callable. See ADR-0029, "The bound that makes the weaker guarantee sufficient".
729
731
  */
730
732
  type CodemodeActivation = "active" | "inactive";
731
- /** How the answer was decided, so a test can tell a configured answer from pi's default. */
732
- type CodemodeActivationSource = "cli" | "project" | "user" | "default" | "invalid";
733
+ /**
734
+ * How the answer was decided, so a test can tell a configured answer from pi's default.
735
+ * `"mcp"` is ADR-0033: the loadout mirror said `inactive` and the MCP auto-enable evidence
736
+ * said pi will activate `codemode` anyway.
737
+ */
738
+ type CodemodeActivationSource = "cli" | "project" | "user" | "default" | "invalid" | "mcp";
733
739
  /** The answer plus enough provenance to explain it in a notice. */
734
740
  interface CodemodeActivationResolution {
735
741
  activation: CodemodeActivation;
736
742
  source: CodemodeActivationSource;
737
743
  /** Set when a settings file could not be read as a JSON object; the answer still resolves. */
738
744
  error?: string;
745
+ /**
746
+ * Set when an `mcp.json` could not be read as a JSON object (ADR-0033); that file contributed
747
+ * nothing to the answer, and the answer still resolves.
748
+ */
749
+ mcpError?: string;
739
750
  }
740
751
  /**
741
- * Resolve whether `codemode` will be in the model's tool list, in the order pi resolves the
742
- * loadout: the command-line allowlist, then the merged `defaultTools`, then pi's own default.
752
+ * Resolve the LOADOUT half of whether `codemode` will be in the model's tool list: the
753
+ * command-line allowlist, then the merged `defaultTools`, then pi's own default. This is the
754
+ * ADR-0029 mirror; the MCP auto-enable evidence (ADR-0033) is unioned on top by
755
+ * {@link applyMcpAutoEnableEvidence}, which {@link readCodemodeActivation} calls.
743
756
  *
744
757
  * The last of those is the load-bearing one and is what makes absence of evidence mean
745
758
  * `inactive`: pi registers `codemode` inactive, so a session that configured nothing does not get
@@ -826,8 +839,16 @@ interface SurfaceModeConfig {
826
839
  * them and the real probes answer, but only on a path that actually needs the answer: they are
827
840
  * resolved inside the fallback branches rather than in a default parameter, because a default
828
841
  * parameter is evaluated on EVERY call -- including the ones an explicit `surfaceMode` key
829
- * short-circuits, where the user paid a `realpathSync` plus up to three `statSync` and two
830
- * settings reads to set one line of JSON and get a constant.
842
+ * short-circuits, where the user paid a `realpathSync` plus up to three `statSync` and the
843
+ * settings reads below to set one line of JSON and get a constant.
844
+ *
845
+ * The probes do NOT save an explicit key their reads, though, and the cost is worth naming exactly
846
+ * rather than in the round number it is usually quoted as: `detected()` runs the switch probe AND
847
+ * the activation probe, and each reads the SAME two settings files (`readCodemodeSwitch` and
848
+ * `readCodemodeActivation` each call `readSettingsObject` twice), so one detected surface costs
849
+ * four settings reads over two files, plus the two `mcp.json` reads ADR-0033 added. The
850
+ * duplication is pre-existing and deliberate — each probe is copied from pi whole and kept
851
+ * self-contained — so the number is recorded, not optimised.
831
852
  */
832
853
  export declare function readSurfaceModeConfig(agentDir: string, presence?: CodemodePresence, codemodeSwitch?: CodemodeSwitchResolution, codemodeActivation?: CodemodeActivationResolution, cwd?: string): SurfaceModeConfig;
833
854
  /** Outcome of writing `surfaceMode` for `/ptc surface`. */
package/dist/index.js CHANGED
@@ -1,58 +1,58 @@
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{tmpdir as ie}from"node:os";import*as E from"node:path";import{basename as ae,dirname as oe,join as D,relative as O,resolve as k,sep as A}from"node:path";import{spawn as se}from"node:child_process";import{randomBytes as ce,randomUUID as j}from"node:crypto";import{ok as M}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 N,visibleWidth as P}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";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(ce(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(`
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
- `)}});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`,F=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={...F};for(let n of Object.keys(F)){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=F){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.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){M(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){M(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(F.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)}};function ut(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" }.`,...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(`
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 E,statSync as ee,writeFileSync as te}from"node:fs";import*as ne from"node:os";import{tmpdir as re}from"node:os";import*as D from"node:path";import{basename as ie,dirname as ae,join as O,relative as k,resolve as A,sep as j}from"node:path";import{spawn as oe}from"node:child_process";import{randomBytes as se,randomUUID as M}from"node:crypto";import{ok as N}from"node:assert/strict";import{MessageChannel as ce,Worker as le}from"node:worker_threads";import ue from"node:diagnostics_channel";import{fileURLToPath as de,pathToFileURL as fe}from"node:url";import{truncateToWidth as P,visibleWidth as F}from"@earendil-works/pi-tui";import{appendFile as pe,mkdir as me,readFile as he,readdir as ge,rename as _e,unlink as ve,writeFile as ye}from"node:fs/promises";import{minimatch as be}from"minimatch";const xe=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`;function Se(e){let t=``,n=Math.max(0,Math.floor(e));for(let e=0;e<10;e++)t=(xe[n%32]??`0`)+t,n=Math.floor(n/32);return t}function Ce(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+=xe[n>>>r&31];return t.padEnd(16,`0`)}function we(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 Te(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?we(r):t(10);return n=a,r=o,Se(a)+Ce(o)}}}const Ee=Te({now:()=>Date.now()});function De(){return Ee.next()}function Oe(e){let t=e.trim();if(t.length===0)return null;try{return JSON.parse(t)}catch{return null}}function ke(e,t){if(e.pid===void 0)return!1;try{return e.kill(t),!0}catch{return!1}}function Ae(e,t){if(e.eventWaiters.length>0){let n=e.eventWaiters.shift();n&&n(t);return}e.events.push(t)}function je(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 Me(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 Ne={warn:e=>{console.warn(`[pi-ptc.lifecycle] `+e)}};function Pe(e){return e.length<=200?e:e.slice(0,200)+`…`}var Fe=class{#e;constructor(e={}){this.#e=e.logger??Ne}spawn(e,t){if(e.length===0)throw TypeError(`RealChildProcessLifecycle.spawn: argv must include the command`);let n=Me(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:De(),opaque:o},c=a.stdout;c&&c.on(`data`,e=>{o.lineBuffer+=e.toString(`utf-8`);let t=o.lineBuffer.indexOf(`
2
+ `);for(;t>=0;){let e=o.lineBuffer.slice(0,t);o.lineBuffer=o.lineBuffer.slice(t+1);let n=Oe(e);n?Ae(o,n):e.trim().length>0&&this.#t(s,e),t=o.lineBuffer.indexOf(`
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=Oe(n);e?Ae(o,e):this.#t(s,n),o.lineBuffer=``}je(o,{code:e,signal:t})}),a.on(`error`,e=>{o.stderr+=`[spawn-error] `+e.message+`
4
+ `,o.exited||je(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;ke(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): `+Pe(t))}};const Ie=`ptc_child_report`,I=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}),Le=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function Re(e=process.env){let t={};for(let n of Le){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function ze(e={}){let t={...I};for(let n of Object.keys(I)){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 Be(e,t=I){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const Ve={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},He=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Ue=/* @__PURE__ */ new Set([`running`,`stopping`]);function We(e,t,n,r){if(n!==`canceled`&&n!==`succeeded`){if(t.childError!==void 0)return t.childError;if(t.exitCode===0&&!r)return`dispatch produced no final text`}}function Ge(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function Ke(e){return typeof e==`string`&&e.length>0}const qe=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function Je(e){return typeof e==`string`&&qe.has(e)}function Ye(e,t){return e.ownerPid===t.pid&&e.ownerBootMs===t.bootMs}function Xe(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 Ze(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var Qe=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??Xe,this.#a=Te({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 Ke(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())Ue.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=Ke(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(!Ge(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`&&!Je(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:We(n,e,i,r),...i===`succeeded`?{report:e.report,reportChannel:e.reportChannel}:{}})}async#p(e,t){let n=await this.#y(e.taskId);if(!Ue.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};He.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=Ve[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(!Ke(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:Ze(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 $e(e,t){return new Qe(e,t)}function et(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function tt(e){for(let t=1;t<e.length;t++)if(et(e[t-1],e[t])>0)return!1;return!0}var nt=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=tt(t)?[...t]:[...t].sort(et),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(et),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 rt=new Fe;var it=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 at=new it(I.dispatchConcurrency);let ot;function st(e,t){return e.taskRegistry===void 0?(ot??=new Qe(new nt,{clock:t}),ot):e.taskRegistry}const ct={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}};function lt(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" }.`,...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
5
  `);return e.length===0?a:e+`
6
6
 
7
- `+a}function dt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch depth limit reached`}}function ft(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch concurrency limit reached`}}function pt(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 mt(){return{...dt(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function ht(){return{...ft(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function gt(e){return e.aborted?{status:`rejected`,errorMessage:`dispatch cancelled`}:e.exitCode===0&&e.finalText.length>0?{status:`fulfilled`}:e.exitCode===0?{status:`rejected`,errorMessage:`dispatch produced no final text`}:{status:`rejected`}}function _t(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 vt(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 yt(e){let t=_t(e,`childReport`);if(t!==void 0)return t.toLowerCase()!==`false`&&t.toLowerCase()!==`no`}function bt(e){return e.childReport!==!1}function xt(e){let t=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!t)return null;let n=t[1]??``,r=t[2]??``,i=_t(n,`name`);if(!i)return null;let a=_t(n,`description`)??``,o=_t(n,`model`)??``,s=vt(n,`tools`),c=yt(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 St(e,t,n,r){let{userDir:i,projectDir:a}=Ct({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:E.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:E.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=xt(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 Ct(e){let t=e.homeDir??re.homedir();return{userDir:E.join(t,`.pi`,`agent`,`agents`),projectDir:E.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function wt(e){let t=e?.code;return typeof t==`string`?t:String(e)}function Tt(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function Et(e,t){let n=E.resolve(e),r=E.resolve(t),i=e=>E.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(Dt(e))return!0;return!1}return a===r&&Dt(r)}function Dt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function Ot(e,t,n){let r=wt(n);return r!==`ENOENT`&&r!==`ENOTDIR`||Tt(e)?!1:!Et(e,t)}function kt(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=Ct(e),a=[];(e.agentScope===`user`||e.agentScope===`both`)&&a.push({dir:t,boundary:r}),(e.agentScope===`project`||e.agentScope===`both`)&&a.push({dir:n,boundary:i});let o=/* @__PURE__ */ new Set;for(let{dir:e,boundary:t}of a){let n;try{n=C.readdirSync(e)}catch(n){if(!Ot(e,t,n)){let t=wt(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of n){if(!t.endsWith(`.md`))continue;let n=t.slice(0,-3),r=E.join(e,t),i;try{i=C.readFileSync(r,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`pi.dispatch: cannot read agent file ${r}: ${t}; falling back to the filename`),o.add(n);continue}let a=xt(i)?.name??n;a.length>0&&o.add(a)}}return[...o].sort()}function At(e){let{userDir:t,projectDir:n}=Ct(e),r=kt(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 jt(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:`agent is required (there is no default agent) — `+At(e)}}function Mt(e){return typeof e!=`string`||e.trim().length===0}function Nt(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+`). `+At({cwd:n,agentScope:t})}}function Pt(e){let t=e.tools??[];if(!bt(e))return t.length>0?t:void 0;if(t.length!==0)return t.includes(`ptc_child_report`)?t:[...t,Le]}function Ft(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=Pt(t);return o!==void 0&&r.push(`--tools`,o.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}let It=Lt;async function Lt(e,t){let n=await C.promises.mkdtemp(E.join(re.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=E.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function Rt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function zt(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 Bt(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 Vt(e){let t=[],n;for(let r of e.split(`
7
+ `+a}function ut(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch depth limit reached`}}function dt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch concurrency limit reached`}}function ft(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 pt(){return{...ut(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function mt(){return{...dt(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function ht(e){return e.aborted?{status:`rejected`,errorMessage:`dispatch cancelled`}:e.exitCode===0&&e.finalText.length>0?{status:`fulfilled`}:e.exitCode===0?{status:`rejected`,errorMessage:`dispatch produced no final text`}:{status:`rejected`}}function gt(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 _t(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 vt(e){let t=gt(e,`childReport`);if(t!==void 0)return t.toLowerCase()!==`false`&&t.toLowerCase()!==`no`}function yt(e){return e.childReport!==!1}function bt(e){let t=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!t)return null;let n=t[1]??``,r=t[2]??``,i=gt(n,`name`);if(!i)return null;let a=gt(n,`description`)??``,o=gt(n,`model`)??``,s=_t(n,`tools`),c=vt(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 xt(e,t,n,r){let{userDir:i,projectDir:a}=St({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:D.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:D.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=bt(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 St(e){let t=e.homeDir??ne.homedir();return{userDir:D.join(t,`.pi`,`agent`,`agents`),projectDir:D.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function Ct(e){let t=e?.code;return typeof t==`string`?t:String(e)}function wt(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function Tt(e,t){let n=D.resolve(e),r=D.resolve(t),i=e=>D.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(Et(e))return!0;return!1}return a===r&&Et(r)}function Et(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function Dt(e,t,n){let r=Ct(n);return r!==`ENOENT`&&r!==`ENOTDIR`||wt(e)?!1:!Tt(e,t)}function Ot(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=St(e),a=[];(e.agentScope===`user`||e.agentScope===`both`)&&a.push({dir:t,boundary:r}),(e.agentScope===`project`||e.agentScope===`both`)&&a.push({dir:n,boundary:i});let o=/* @__PURE__ */ new Set;for(let{dir:e,boundary:t}of a){let n;try{n=C.readdirSync(e)}catch(n){if(!Dt(e,t,n)){let t=Ct(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of n){if(!t.endsWith(`.md`))continue;let n=t.slice(0,-3),r=D.join(e,t),i;try{i=C.readFileSync(r,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`pi.dispatch: cannot read agent file ${r}: ${t}; falling back to the filename`),o.add(n);continue}let a=bt(i)?.name??n;a.length>0&&o.add(a)}}return[...o].sort()}function kt(e){let{userDir:t,projectDir:n}=St(e),r=Ot(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 At(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:`agent is required (there is no default agent) — `+kt(e)}}function jt(e){return typeof e!=`string`||e.trim().length===0}function Mt(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+`). `+kt({cwd:n,agentScope:t})}}function Nt(e){let t=e.tools??[];if(!yt(e))return t.length>0?t:void 0;if(t.length!==0)return t.includes(`ptc_child_report`)?t:[...t,Ie]}function Pt(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=Nt(t);return o!==void 0&&r.push(`--tools`,o.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}let Ft=It;async function It(e,t){let n=await C.promises.mkdtemp(D.join(ne.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=D.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function Lt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Rt(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 zt(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 Bt(e){let t=[],n;for(let r of e.split(`
8
8
  `)){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(`
9
9
  `)}),n=void 0):n.body.push(r)}return n!==void 0&&t.push({info:n.info,body:n.body.join(`
10
- `)}),t}function Ht(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ut(e){if(!Ht(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(!Ht(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 Wt(e){let t=Vt(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=Ut(r);return i===void 0?{reportChannel:`none`}:{report:i,reportChannel:`prompt-json`}}function Gt(e){if(e.type===`tool_execution_end`&&e.toolName===`ptc_child_report`&&e.isError!==!0)return Ut(e.result?.structuredContent)}function Kt(){return{prompt:{reportChannel:`none`},tool:void 0}}function qt(e,t){let n=Gt(t);n!==void 0&&(e.tool=n)}function Jt(e){return e.tool===void 0?e.prompt:{report:e.tool,reportChannel:`tool`}}function Yt(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 Xt(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return mt();if(Mt(e.agent))return jt({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`});let i=Oe(),a=n.slots??ot;if(!a.tryAcquire(i))return ht();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,h;try{let n=St(e.agent,c,l);if(!n)return a.release(i),Nt(e.agent,l,c);let g=e.label??e.task.slice(0,64),_=bt(n),v=ut(n.systemPrompt,r,t.maxDispatchDepth,{reportContract:_}),y=await It(n.name,v);h=y;let b=Ft(e,n,y.filePath),x={cwd:c,env:{...process.env,PI_PTC_DEPTH:String(r),PI_PTC_TASK_ID:i},promptFile:y.filePath};t.sessionDir!==void 0&&(x.sessionDir=t.sessionDir,x.sessionId=i,x.sessionName=`bgdispatch:`+i),m=u.spawn([`pi`,...b],x);let S=m,C={kind:`ptc-program`,callerId:d};await f.transition({kind:`spawn`,handle:{taskId:i,label:g,status:`running`},record:{label:g,agentName:n.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:C,parentTaskId:t.parentTaskId}},{clock:o,callerId:d,logger:s});let w=!1,T,ee=f.onTransition((e,t)=>{e.id===i&&t.status===`stopping`&&(w||T!==void 0||(T=pt(u,S,{isDone:()=>w,unref:!0})))});return(async()=>{let e=``,t,n=Kt(),r;try{for await(let i of u.events(S)){qt(n,i);let a=zt(i);a!==void 0&&(e=a,n.prompt=Wt(a)),r=Bt(r,i);let o=Yt(i);o!==void 0&&(t=o)}w=!0,T?.();let a=(await u.exit(S)).code??-1,c=Buffer.byteLength(e,`utf8`),l=c<=2048?e:void 0,m;if(p!==void 0)try{await p.writeOutput(i,e),m=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 h=_?Jt(n):{reportChannel:`opted-out`};await f.transition({kind:`resolve-exit`,taskId:i,exitCode:a,reportChannel:h.reportChannel,...h.report===void 0?{}:{report:{...h.report,usage:{input:r?.input??0,output:r?.output??0,cost:r?.cost??0,turns:r?.turns??0}}},outputRef:m,outputBytes:c,outputPreview:l,childError:t},{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{ee(),T?.(),Rt(y),a.release(i)}})(),{taskId:i,label:g,status:`running`}}catch(t){let n=t instanceof Error?t.message:String(t);return m!==void 0&&pt(u,m,{unref:!0}),h!==void 0&&Rt(h),a.release(i),s.warn(`background dispatch failed for agent `+e.agent+`: `+n),{text:``,status:`rejected`,started:m!==void 0,agentName:e.agent,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`background dispatch failed: `+n}}}async function Zt(e,t,n={}){if(e.background===!0)return await Xt(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return dt();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now();if(Mt(e.agent))return jt({cwd:i,agentScope:a});let s=n.slots??ot;if(!s.tryAcquire())return ft();let c=St(e.agent,i,a);if(!c)return s.release(),Nt(e.agent,a,i,Date.now()-o);let l=bt(c),u=ut(c.systemPrompt,r,t.maxDispatchDepth,{reportContract:l}),d,f=n.lifecycle??it,p;try{d=await It(c.name,u),p=Ft(e,c,d.filePath)}catch(e){throw s.release(),e}return await new Promise(e=>{let a=``,u,m=Kt(),h=-1,g=``,_=!1,v,y,b=!1,x=(r,i,p=!0)=>{if(_)return;_=!0,s.release(),y!==void 0&&f.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),Rt(d);let b=l?Jt(m):{reportChannel:`opted-out`},x={text:a,status:r,started:p,agentName:c.name,durationMs:Date.now()-o,exitCode:h,reportChannel:b.reportChannel};b.report&&(x.report={...b.report,usage:{input:u?.input??0,output:u?.output??0,cost:u?.cost??0,turns:u?.turns??0}}),u&&(x.usage=u),g.length>0&&(x.stderr=g),i&&(x.errorMessage=i),e(x)},S=()=>{y&&!_&&(b=!0,v=pt(f,y,{isDone:()=>_}))};try{y=f.spawn([`pi`,...p],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:d.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 f.events(e))if(qt(m,t),t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(u=Bt(u,t),Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(a=t.text,m.prompt=Wt(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}=gt({exitCode:h,finalText:a,aborted:b});x(r,i)}catch(e){let t=e instanceof Error?e.message:String(e);x(`rejected`,`dispatch internal error: `+t)}})()})}const I=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],L=`pi.dispatch`,Qt=I,$t={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},en=x.Object({agent:x.String({minLength:1}),task:x.String({minLength:1}),cwd:x.Optional(x.String()),agentScope:x.Optional(x.Union([x.Literal(`user`),x.Literal(`project`),x.Literal(`both`)])),model:x.Optional(x.String()),thinkingLevel:x.Optional(x.String()),background:x.Optional(x.Boolean()),label:x.Optional(x.String())}),tn={name:L,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters:en};function nn(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 rn(e){let t=e.names??Qt,n=e.includeDispatch??e.names===void 0,r=/* @__PURE__ */ new Map;for(let n of t){let t=$t[n];if(!t)throw TypeError(`unknown PTC binding "${n}"; known bindings: ${I.join(`, `)}`);let i=t(e.cwd);r.set(n,{name:n,execute:async(e,t)=>{let n=`ptc:${t.callId}`,r={type:`toolCall`,id:n,name:i.name,arguments:e},a=S(i,r),o=await i.execute(n,a,t.signal,void 0);if(o.isError===!0)throw Error(nn(i.name,(o.content??[]).filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text??``).join(`
11
- `)));return{content:o.content,details:o.details===void 0?null:o.details}}})}return n&&r.set(L,{name:L,execute:async(t,n)=>{let r={type:`toolCall`,id:`ptc:${n.callId}`,name:L,arguments:t},i;try{i=S(tn,r)}catch(n){let r=typeof t==`object`&&t&&!Array.isArray(t)?t:void 0,i=r?.agent,a=r?.agentScope;return Mt(i)?jt({cwd:e.cwd,agentScope:a===`user`||a===`project`||a===`both`?a:`user`}):{text:``,status:`rejected`,started:!1,agentName:i,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:n instanceof Error?n.message:String(n)}}return Zt(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)}}),r}function an(){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 on(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 R={acquireLatency:de.channel(`ptc:pool:acquire-latency`),resetTime:de.channel(`ptc:worker:reset-time`),imageBytes:de.channel(`ptc:image:hoist-bytes`)};function z(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(),z(R.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),z(R.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),z(R.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){z(R.imageBytes,{byteLength:e})}function ln(e){z(R.resetTime,{durationMs:e})}function un(){let e=oe(fe(import.meta.url)),t=[k(e,`worker.js`),k(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 dn(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 B(e){return e instanceof Error?e.message:String(e)}function fn(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(`
12
- `);return e===-1?t:t.slice(0,e)}}}}function pn(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function mn(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 hn(e){try{let t=Buffer.byteLength(JSON.stringify(e,(e,t)=>pn(t)?null:t)??``,`utf8`),n=0;return mn(e,e=>{n+=e.byteLength}),t+n}catch{return 1/0}}async function gn(e){let i=Be(e.config),s=ze(),c=e.runId??j(),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(un(),on({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: ${B(e)}`}}}return await new Promise(s=>{let m=new le,h=m.port1,g=m.port2,_=new AbortController,v=!1,y=an(),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,ie,E,ae=[],oe=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},D=e=>e===`timeout`?`run timed out after ${l} ms`:`run cancelled`,O=e=>e===`timeout`?n.timeout:n.abort,k=t=>{if(v)return;v=!0,ie&&clearTimeout(ie),E&&clearTimeout(E),e.signal?.removeEventListener(`abort`,me),_.abort(),h.close(),e.pool?e.pool.release(p):p.terminate();let n=x.snapshot();s(n.length>0?{...t,subCalls:n}:t)},A=(e,t,n)=>{k({logs:u,narrations:d,phases:f,error:n===void 0?{kind:e,message:t}:{kind:e,message:t,stack:n}})},se=e=>{if(!v){if(!r(e)){A(n.protocol,`internal error: malformed host frame`);return}h.postMessage(e)}},ce=()=>{let t={kind:o.init,runId:c,surface:e.surface,code:e.code,bindings:[...e.bindings.keys()],bindingCandidates:[...I],maxItemsPerCall:i.maxItemsPerCall,maxPendingCalls:i.maxPendingCalls,...e.args===void 0?{}:{args:e.args}};if(!r(t)){A(n.protocol,`internal error: malformed init frame`);return}let a=hn(t);if(a>i.maxMessageBytes){A(n.protocol,`init frame of ${a} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}se(t)},j=(e,t)=>(T+=e,T<=i.maxOutputBytes||(A(n.outputLimit,`${t} exceeded the output budget: logs + result reached ${T} bytes (maxOutputBytes=${i.maxOutputBytes}); ${u.length} log line(s) retained`),!1)),M=async()=>{if(te<i.maxParallelSubCalls){te+=1;return}await new Promise(e=>{ne.push(e)})},ue=()=>{let e=ne.shift();if(e){e();return}--te},de=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`}),A(n.protocol,`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`);return}fe(e).finally(()=>{--w})},fe=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)`)}),pe({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===L;if(!a&&(await M(),v)){x.recordEnd(t.callId,`cancelled`,{errorMessage:`run settled before binding started`}),ue();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=oe(s),u={kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:s},d=hn(u);if(d>i.maxMessageBytes){x.recordEnd(t.callId,`error`,{errorMessage:`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`}),A(n.protocol,`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}if(pe(u))for(let e of l)ae.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?dn(s):void 0;e===void 0?x.recordEnd(t.callId,`ok`,{resultSummary:fn(s)}):x.recordEnd(t.callId,e.kind===`refused`?`rejected`:`error`,{errorMessage:e.message})}}catch(e){_.signal.aborted?x.recordEnd(t.callId,`cancelled`,{errorMessage:B(e)}):x.recordEnd(t.callId,`error`,{errorMessage:B(e)}),pe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:B(e)})}finally{a||ue()}},pe=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: ${B(t)}`})}catch{A(n.protocol,`binding result is not transferable`)}return!1}},N=e=>S?{logs:u,narrations:d,phases:f,error:{kind:O(S),message:D(S)}}:e,P=r=>{if(v)return;if(!a(r)){A(n.protocol,`malformed worker frame`);return}let o=r.kind===t.ready?0:hn(r);if(!Number.isFinite(o)){A(n.protocol,`worker frame could not be serialized for accounting`);return}if(o>i.maxMessageBytes){A(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&&ln(Date.now()-t)}if(!C&&(C=!0,S)){he(S);return}ce();return;case t.call:de(r);return;case t.log:j(o,`console output`)&&u.push(r.text);return;case t.narration:j(o,`workflow narration`)&&d.push(r.message);return;case t.phase:j(o,`workflow phase`)&&f.push(r.title);return;case t.result:{if(!j(o,`completion value`))return;let e={logs:u,narrations:d,phases:f,...ae.length>0?{images:ae}:{}};k(N(r.value===void 0?e:{...e,value:r.value}));return}case t.error:k(N({logs:u,narrations:d,phases:f,error:r.error}));return;default:A(n.protocol,`unknown worker frame`)}};function me(){ge(`abort`)}let he=e=>{E&&clearTimeout(E),E=setTimeout(()=>{A(O(e),D(e))},i.graceMs)};function ge(e){if(!v){if(S){A(O(S),D(S));return}S=e,_.abort(),se({kind:o.cancel,reason:e}),he(e)}}p.on(`error`,e=>{A(n.workerExit,`worker failed: ${B(e)}`)}),p.on(`exit`,e=>{A(n.workerExit,`worker exited with code ${e} before the run completed`)}),h.on(`message`,P),h.on(`messageerror`,()=>{A(n.protocol,`worker sent a frame that could not be deserialized`)}),e.signal?.addEventListener(`abort`,me,{once:!0}),ie=setTimeout(()=>{ge(`timeout`)},l);let _e={kind:o.connect,port:g};r(_e)?p.postMessage(_e,[g]):A(n.protocol,`internal error: malformed connect frame`)})}const _n=["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.`],vn=/* @__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`."],[L,'`tools["pi.dispatch"]` is the exception: it resolves to `{ text, status, ... }` with no `content` and never throws, so read `status`.']]),yn=[_n.join(`
13
- `),`Exceptions: `+[...vn.values()].join(` `)].join(`
14
- `),bn=`pi-ptc-output-`;function xn(e,t=bn){let n=D(ie(),`${t}${j()}.txt`);return ne(n,e,`utf8`),n}function Sn(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 Cn(e,t=bn,n={}){let r=b(e,{maxLines:c,maxBytes:s});if(!r.truncated)return{text:e,truncated:!1};let i=xn(n.fullText??e,t);return{text:`${r.content}\n\n${Sn(r,i)}`,truncated:!0,fullPath:i}}const wn=200,Tn=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 En(e){return!e.includes(`\x1B`)&&!e.includes(`›`)?e:e.replace(Tn,``)}function V(e){let t=En(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 Dn=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function On(e){return Dn.test(e)?e:JSON.stringify(e)}function kn(e){if(e===null)return`null`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(typeof e==`string`){let t=V(e);return t.includes(`
15
- `)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=kn(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=kn(e[r]??null);if(t===void 0)return;n.push(`${On(r)}: ${t}`)}return`{${n.join(`, `)}}`}function An(e){let t=kn(e);if(t!==void 0)return t.length<=100?t:void 0}function jn(e){return e===null?`null`:typeof e==`string`?V(e):String(e)}function Mn(e,t){if(typeof e!=`object`||!e)return[`${t}${jn(e)}`];if(Array.isArray(e)){if(e.length===0)return[`${t}[]`];let n=[`${t}[`];for(let r of e){let e=An(r);if(e!==void 0){n.push(`${t} ${e}`);continue}n.push(...Nn(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=An(n);if(a!==void 0){r.push(`${i}${On(t)}: ${a}`);continue}if(typeof n==`string`){r.push(`${i}${On(t)}:`);for(let e of V(n).split(`
16
- `))r.push(e.length===0?``:`${i} ${e}`);continue}let o=Mn(n,i);r.push(`${i}${On(t)}: ${(o[0]??``).trimStart()}`.trimEnd(),...o.slice(1))}return r.push(`${t}}`),r}function Nn(e,t){return typeof e==`string`?V(e).split(`
17
- `):typeof e!=`object`||!e?[String(e)]:Mn(e,t)}function Pn(e){return e.split(`
10
+ `)}),t}function Vt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ht(e){if(!Vt(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(!Vt(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 Ut(e){let t=Bt(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=Ht(r);return i===void 0?{reportChannel:`none`}:{report:i,reportChannel:`prompt-json`}}function Wt(e){if(e.type===`tool_execution_end`&&e.toolName===`ptc_child_report`&&e.isError!==!0)return Ht(e.result?.structuredContent)}function Gt(){return{prompt:{reportChannel:`none`},tool:void 0}}function Kt(e,t){let n=Wt(t);n!==void 0&&(e.tool=n)}function qt(e){return e.tool===void 0?e.prompt:{report:e.tool,reportChannel:`tool`}}function Jt(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 Yt(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return pt();if(jt(e.agent))return At({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`});let i=De(),a=n.slots??at;if(!a.tryAcquire(i))return mt();let o=n.clock??(()=>Date.now()),s=n.logger??ct,c=e.cwd??t.cwd,l=e.agentScope??`user`,u=n.lifecycle??rt,d=t.callerId??`dispatch:`+String(t.callId),f=st(n,o),p=n.outputStorage,m,h;try{let n=xt(e.agent,c,l);if(!n)return a.release(i),Mt(e.agent,l,c);let g=e.label??e.task.slice(0,64),_=yt(n),v=lt(n.systemPrompt,r,t.maxDispatchDepth,{reportContract:_}),y=await Ft(n.name,v);h=y;let b=Pt(e,n,y.filePath),x={cwd:c,env:{...process.env,PI_PTC_DEPTH:String(r),PI_PTC_TASK_ID:i},promptFile:y.filePath};t.sessionDir!==void 0&&(x.sessionDir=t.sessionDir,x.sessionId=i,x.sessionName=`bgdispatch:`+i),m=u.spawn([`pi`,...b],x);let S=m,C={kind:`ptc-program`,callerId:d};await f.transition({kind:`spawn`,handle:{taskId:i,label:g,status:`running`},record:{label:g,agentName:n.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:C,parentTaskId:t.parentTaskId}},{clock:o,callerId:d,logger:s});let w=!1,T,E=f.onTransition((e,t)=>{e.id===i&&t.status===`stopping`&&(w||T!==void 0||(T=ft(u,S,{isDone:()=>w,unref:!0})))});return(async()=>{let e=``,t,n=Gt(),r;try{for await(let i of u.events(S)){Kt(n,i);let a=Rt(i);a!==void 0&&(e=a,n.prompt=Ut(a)),r=zt(r,i);let o=Jt(i);o!==void 0&&(t=o)}w=!0,T?.();let a=(await u.exit(S)).code??-1,c=Buffer.byteLength(e,`utf8`),l=c<=2048?e:void 0,m;if(p!==void 0)try{await p.writeOutput(i,e),m=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 h=_?qt(n):{reportChannel:`opted-out`};await f.transition({kind:`resolve-exit`,taskId:i,exitCode:a,reportChannel:h.reportChannel,...h.report===void 0?{}:{report:{...h.report,usage:{input:r?.input??0,output:r?.output??0,cost:r?.cost??0,turns:r?.turns??0}}},outputRef:m,outputBytes:c,outputPreview:l,childError:t},{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{E(),T?.(),Lt(y),a.release(i)}})(),{taskId:i,label:g,status:`running`}}catch(t){let n=t instanceof Error?t.message:String(t);return m!==void 0&&ft(u,m,{unref:!0}),h!==void 0&&Lt(h),a.release(i),s.warn(`background dispatch failed for agent `+e.agent+`: `+n),{text:``,status:`rejected`,started:m!==void 0,agentName:e.agent,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`background dispatch failed: `+n}}}async function Xt(e,t,n={}){if(e.background===!0)return await Yt(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return ut();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now();if(jt(e.agent))return At({cwd:i,agentScope:a});let s=n.slots??at;if(!s.tryAcquire())return dt();let c=xt(e.agent,i,a);if(!c)return s.release(),Mt(e.agent,a,i,Date.now()-o);let l=yt(c),u=lt(c.systemPrompt,r,t.maxDispatchDepth,{reportContract:l}),d,f=n.lifecycle??rt,p;try{d=await Ft(c.name,u),p=Pt(e,c,d.filePath)}catch(e){throw s.release(),e}return await new Promise(e=>{let a=``,u,m=Gt(),h=-1,g=``,_=!1,v,y,b=!1,x=(r,i,p=!0)=>{if(_)return;_=!0,s.release(),y!==void 0&&f.exit(y).catch(e=>{(n.logger??ct).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),Lt(d);let b=l?qt(m):{reportChannel:`opted-out`},x={text:a,status:r,started:p,agentName:c.name,durationMs:Date.now()-o,exitCode:h,reportChannel:b.reportChannel};b.report&&(x.report={...b.report,usage:{input:u?.input??0,output:u?.output??0,cost:u?.cost??0,turns:u?.turns??0}}),u&&(x.usage=u),g.length>0&&(x.stderr=g),i&&(x.errorMessage=i),e(x)},S=()=>{y&&!_&&(b=!0,v=ft(f,y,{isDone:()=>_}))};try{y=f.spawn([`pi`,...p],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:d.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 f.events(e))if(Kt(m,t),t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(u=zt(u,t),Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(a=t.text,m.prompt=Ut(t.text))}let t=await rt.exit(e);h=t.code??-1,g=await rt.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}=ht({exitCode:h,finalText:a,aborted:b});x(r,i)}catch(e){let t=e instanceof Error?e.message:String(e);x(`rejected`,`dispatch internal error: `+t)}})()})}const L=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],R=`pi.dispatch`,Zt=L,Qt={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},$t=x.Object({agent:x.String({minLength:1}),task:x.String({minLength:1}),cwd:x.Optional(x.String()),agentScope:x.Optional(x.Union([x.Literal(`user`),x.Literal(`project`),x.Literal(`both`)])),model:x.Optional(x.String()),thinkingLevel:x.Optional(x.String()),background:x.Optional(x.Boolean()),label:x.Optional(x.String())}),en={name:R,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters:$t};function tn(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 nn(e){let t=e.names??Zt,n=e.includeDispatch??e.names===void 0,r=/* @__PURE__ */ new Map;for(let n of t){let t=Qt[n];if(!t)throw TypeError(`unknown PTC binding "${n}"; known bindings: ${L.join(`, `)}`);let i=t(e.cwd);r.set(n,{name:n,execute:async(e,t)=>{let n=`ptc:${t.callId}`,r={type:`toolCall`,id:n,name:i.name,arguments:e},a=S(i,r),o=await i.execute(n,a,t.signal,void 0);if(o.isError===!0)throw Error(tn(i.name,(o.content??[]).filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text??``).join(`
11
+ `)));return{content:o.content,details:o.details===void 0?null:o.details}}})}return n&&r.set(R,{name:R,execute:async(t,n)=>{let r={type:`toolCall`,id:`ptc:${n.callId}`,name:R,arguments:t},i;try{i=S(en,r)}catch(n){let r=typeof t==`object`&&t&&!Array.isArray(t)?t:void 0,i=r?.agent,a=r?.agentScope;return jt(i)?At({cwd:e.cwd,agentScope:a===`user`||a===`project`||a===`both`?a:`user`}):{text:``,status:`rejected`,started:!1,agentName:i,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:n instanceof Error?n.message:String(n)}}return Xt(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)}}),r}function rn(){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 an(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 z={acquireLatency:ue.channel(`ptc:pool:acquire-latency`),resetTime:ue.channel(`ptc:worker:reset-time`),imageBytes:ue.channel(`ptc:image:hoist-bytes`)};function B(e,t){e.publish(t)}var on=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(),B(z.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),B(z.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),B(z.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 le(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 sn(e){B(z.imageBytes,{byteLength:e})}function cn(e){B(z.resetTime,{durationMs:e})}function ln(){let e=ae(de(import.meta.url)),t=[A(e,`worker.js`),A(e,`worker-entry.ts`)];for(let e of t)if(w(e))return fe(e);throw Error(`worker entry not found; tried: ${t.join(`, `)}`)}function un(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 V(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(`
12
+ `);return e===-1?t:t.slice(0,e)}}}}function fn(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function pn(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 mn(e){try{let t=Buffer.byteLength(JSON.stringify(e,(e,t)=>fn(t)?null:t)??``,`utf8`),n=0;return pn(e,e=>{n+=e.byteLength}),t+n}catch{return 1/0}}async function hn(e){let i=ze(e.config),s=Re(),c=e.runId??M(),l=Be(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 le(ln(),an({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: ${V(e)}`}}}return await new Promise(s=>{let m=new ce,h=m.port1,g=m.port2,_=new AbortController,v=!1,y=rn(),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,E=new it(i.dispatchConcurrency),ee=0,te=[],ne=e.depth??0,re,D,ie=[],ae=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},O=e=>e===`timeout`?`run timed out after ${l} ms`:`run cancelled`,k=e=>e===`timeout`?n.timeout:n.abort,A=t=>{if(v)return;v=!0,re&&clearTimeout(re),D&&clearTimeout(D),e.signal?.removeEventListener(`abort`,pe),_.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)=>{A({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:[...L],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=mn(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)),N=async()=>{if(ee<i.maxParallelSubCalls){ee+=1;return}await new Promise(e=>{te.push(e)})},le=()=>{let e=te.shift();if(e){e();return}--ee},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===R;if(!a&&(await N(),v)){x.recordEnd(t.callId,`cancelled`,{errorMessage:`run settled before binding started`}),le();return}try{let s=await r.execute(t.args,{signal:_.signal,callId:t.callId,depth:ne,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??E}}),l=ae(s),u={kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:s},d=mn(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)ie.push(e),sn(Buffer.byteLength(e.data,`base64`));if(_.signal.aborted)x.recordEnd(t.callId,`cancelled`,{errorMessage:`binding aborted by run cancellation`});else{let e=a?un(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:V(e)}):x.recordEnd(t.callId,`error`,{errorMessage:V(e)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:V(e)})}finally{a||le()}},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: ${V(t)}`})}catch{j(n.protocol,`binding result is not transferable`)}return!1}},P=e=>S?{logs:u,narrations:d,phases:f,error:{kind:k(S),message:O(S)}}:e,F=r=>{if(v)return;if(!a(r)){j(n.protocol,`malformed worker frame`);return}let o=r.kind===t.ready?0:mn(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&&cn(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,...ie.length>0?{images:ie}:{}};A(P(r.value===void 0?e:{...e,value:r.value}));return}case t.error:A(P({logs:u,narrations:d,phases:f,error:r.error}));return;default:j(n.protocol,`unknown worker frame`)}};function pe(){he(`abort`)}let me=e=>{D&&clearTimeout(D),D=setTimeout(()=>{j(k(e),O(e))},i.graceMs)};function he(e){if(!v){if(S){j(k(S),O(S));return}S=e,_.abort(),oe({kind:o.cancel,reason:e}),me(e)}}p.on(`error`,e=>{j(n.workerExit,`worker failed: ${V(e)}`)}),p.on(`exit`,e=>{j(n.workerExit,`worker exited with code ${e} before the run completed`)}),h.on(`message`,F),h.on(`messageerror`,()=>{j(n.protocol,`worker sent a frame that could not be deserialized`)}),e.signal?.addEventListener(`abort`,pe,{once:!0}),re=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 gn=["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.`],_n=/* @__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`."],[R,'`tools["pi.dispatch"]` is the exception: it resolves to `{ text, status, ... }` with no `content` and never throws, so read `status`.']]),vn=[gn.join(`
13
+ `),`Exceptions: `+[..._n.values()].join(` `)].join(`
14
+ `),yn=`pi-ptc-output-`;function bn(e,t=yn){let n=O(re(),`${t}${M()}.txt`);return te(n,e,`utf8`),n}function xn(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 Sn(e,t=yn,n={}){let r=b(e,{maxLines:c,maxBytes:s});if(!r.truncated)return{text:e,truncated:!1};let i=bn(n.fullText??e,t);return{text:`${r.content}\n\n${xn(r,i)}`,truncated:!0,fullPath:i}}const Cn=200,wn=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 Tn(e){return!e.includes(`\x1B`)&&!e.includes(`›`)?e:e.replace(wn,``)}function H(e){let t=Tn(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 En=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function Dn(e){return En.test(e)?e:JSON.stringify(e)}function On(e){if(e===null)return`null`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(typeof e==`string`){let t=H(e);return t.includes(`
15
+ `)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=On(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=On(e[r]??null);if(t===void 0)return;n.push(`${Dn(r)}: ${t}`)}return`{${n.join(`, `)}}`}function kn(e){let t=On(e);if(t!==void 0)return t.length<=100?t:void 0}function An(e){return e===null?`null`:typeof e==`string`?H(e):String(e)}function jn(e,t){if(typeof e!=`object`||!e)return[`${t}${An(e)}`];if(Array.isArray(e)){if(e.length===0)return[`${t}[]`];let n=[`${t}[`];for(let r of e){let e=kn(r);if(e!==void 0){n.push(`${t} ${e}`);continue}n.push(...Mn(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=kn(n);if(a!==void 0){r.push(`${i}${Dn(t)}: ${a}`);continue}if(typeof n==`string`){r.push(`${i}${Dn(t)}:`);for(let e of H(n).split(`
16
+ `))r.push(e.length===0?``:`${i} ${e}`);continue}let o=jn(n,i);r.push(`${i}${Dn(t)}: ${(o[0]??``).trimStart()}`.trimEnd(),...o.slice(1))}return r.push(`${t}}`),r}function Mn(e,t){return typeof e==`string`?H(e).split(`
17
+ `):typeof e!=`object`||!e?[String(e)]:jn(e,t)}function Nn(e){return e.split(`
18
18
  `).map(e=>e.length>200?`${e.slice(0,199)}…`:e).join(`
19
- `)}function Fn(e){if(typeof e==`string`)return Pn(V(e));if(typeof e!=`object`||!e)return String(e);let t=An(e);return Pn((t===void 0?Nn(e,``):[t]).join(`
20
- `))}function In(e=process.env){let t=e.PI_PTC_DEPTH;return t===void 0||!/^\d+$/.test(t)?0:Number.parseInt(t,10)}function Ln(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 H(e){if(e===void 0)return I;let t=new Set(e);return I.filter(e=>t.has(e))}const Rn=["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.`],zn={run_code:`ptc_run_code`,workflow:`ptc_workflow`};function Bn(e){let t=e?.cwd;return typeof t==`string`&&t.length>0?t:process.cwd()}function Vn(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 Hn(e){return[...e.phases.map(e=>`[phase] ${V(e)}`),...e.narrations.map(e=>`[log] ${V(e)}`),...e.logs.map(e=>V(e))]}function Un(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=Hn(e),r=n.length===0?``:`\nCaptured output:\n${n.join(`
21
- `)}`,i=Error(V(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function Wn(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=>V(e)).join(` → `)}`),t.narrations.length>0&&a.push(t.narrations.map(e=>V(e)).join(`
22
- `)),t.logs.length>0&&a.push(t.logs.map(e=>V(e)).join(`
23
- `)),t.value!==void 0&&a.push(Fn(t.value));for(let e of r)a.push(`Warning: ${V(e)}`);let o=Cn(a.length>0?a.join(`
24
- `):`(${zn[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 Gn=/^(.*?)(└─ |├─ | )(?:PTC(?: workflow)?)([ ].*)$/;function Kn(e){return e.replace(/\x1b\[[0-9;]*m|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[\?[0-9;]*[a-zA-Z]/g,``)}function qn(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 Jn(e,t){let n=0,r=0;for(;r<t&&n<e.length;)e.charCodeAt(n)===27?n=qn(e,n):(n+=1,r+=1);return n}function Yn(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:Xn(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 Xn(e,t,n){return e.map(e=>{let r=Kn(e),i=Gn.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=Jn(e,s),l=Jn(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 Zn={run_code:`PTC`,workflow:`PTC workflow`},Qn=`├─ `,$n=`└─ `,er=`│ `;var tr=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>nr(e,t))}};function nr(e,t){let{left:n,right:r}=e;if(r===void 0)return N(n,t,`…`);let i=P(r);if(i>=t)return N(r,t,`…`);let a=N(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-P(a));return a+` `.repeat(o)+r}function U(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function rr(e){return U((V(e).split(`
25
- `).find(e=>e.trim().length>0)??``).trim(),120)}function ir(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2).replace(/\.?0+$/,``)}s`}function W(e,t){return`${e} ${t}${e===1?``:`s`}`}function ar(e){for(let t of e.split(`
26
- `)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return U(e.replace(/\s*\/\/.*$/,``),120)}}function or(e){if(e===void 0)return;if(typeof e==`string`){let t=V(e).split(`
27
- `),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:U(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=Fn(e);if(!t.includes(`
28
- `)&&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 sr(e,t){if(e===void 0)return;let n=[],r=e.logs.length+e.narrations.length;if(r>0&&n.push(t.fg(`dim`,W(r,`output line`))),e.imageCount>0&&n.push(t.fg(`toolOutput`,W(e.imageCount,`image`))),e.surface===`workflow`&&e.phases.length>0&&n.push(t.fg(`dim`,W(e.phases.length,`phase`))),e.warnings.length>0&&n.push(t.fg(`warning`,W(e.warnings.length,`warning`))),e.fullOutputPath!==void 0&&n.push(t.fg(`warning`,`truncated`)),e.durationMs>0&&n.push(t.fg(`dim`,ir(e.durationMs))),n.length!==0)return`${t.fg(`dim`,`•`)} ${n.join(t.fg(`dim`,` · `))}`}function cr(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 lr(e,t,n){let r=` `+(t?$n:Qn),i=` `+(t?` `:er),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 ur(e){return typeof e!=`object`||!e?!1:Array.isArray(e)?e.length>0:Object.keys(e).length>0}const dr=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function fr(e){return dr.test(e)?e:JSON.stringify(e)}function pr(e,t){if(e===null)return`null`;if(typeof e==`boolean`||typeof e==`number`)return String(e);if(typeof e==`string`){let n=V(e);if(n.length===0)return`""`;if(n.includes(`
29
- `)){let e=U(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(U(n,Math.max(2,t-5)))+`…`}return`?`}function mr(e){return typeof e!=`object`||!e}function hr(e,t){if(t<8)return;if(Array.isArray(e)){if(e.length===0)return`[]`;if(e.length>5||!e.every(mr))return;let n=`[`+e.map(e=>pr(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(mr))return;let r=`{`+n.map(n=>{let r=e[n]??null;return fr(n)+`: `+pr(r,Math.max(2,Math.floor(t/4)))}).join(`, `)+`}`;return r.length<=t?r:void 0}function gr(e,t,n,r,i,a,o,s,c){let l=n+(r?`└─ `:`├─ `),u=n+(r?` `:`│ `);if(s>=i){c.push(G(l+t+`…`,o));return}if(Array.isArray(e)&&e.length===0){c.push(G(l+t+`[]`,o));return}if(!Array.isArray(e)&&typeof e==`object`&&e&&Object.keys(e).length===0){c.push(G(l+t+`{}`,o));return}if(typeof e!=`object`||!e){let n=Math.max(0,o-P(l)-t.length);c.push(G(l+t+pr(e,n),o));return}let d=hr(e,Math.max(0,o-P(l)-t.length));if(d!==void 0){c.push(G(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(G(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;gr(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];gr(e[l]??null,fr(l)+`: `,u,r,i,a,o,s+1,c)}}if(p>h){let e=f?`items`:`keys`;c.push(G(u+`└─ …+`+(p-h)+` more `+e,o))}}function G(e,t){if(P(e)<=t)return e;let n=e.match(/^([\s│├└─]*)/),r=n&&n[1]?n[1]:``,i=P(r),a=Math.max(0,t-i-1),o=``,s=0;for(let t of e.slice(r.length)){let e=P(t);if(s+e>a)break;o+=t,s+=e}return r+o+`…`}function _r(e,t={}){let n=t.maxDepth??4,r=t.maxChildren??6,i=t.maxLineChars??120,a=t.moreAfter===!0;if(!ur(e))return typeof e==`object`&&e?[Array.isArray(e)?`[]`:`{}`]:[pr(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;gr(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];gr(e[d]??null,fr(d)+`: `,``,u,n,r,i,0,o)}return c>l&&o.push((a?`├─ `:`└─ `)+`…+`+(c-l)+` more keys`),o}const vr=`child report`;function yr(e){return e===0?`[]`:`Array(${e})`}function br(e){let t=V(e).split(`
30
- `).find(e=>e.trim().length>0)?.trim()??``;return t.length===0?`""`:U(t,200)}function xr(e){let t=Number(e.cost.toFixed(4));return`in ${e.input} · out ${e.output} · cost ${t} · ${W(e.turns,`turn`)}`}function Sr(e,t,n){let r=V(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 Cr(e,t){let n=[];return e.forEach((r,i)=>{let a=i===e.length-1&&t===0,o=`[${i}]`;n.push(`${a?`└─ `:`├─ `}${o} ${V(r.what).trim()}`.trimEnd()),n.push(Sr(a?` `:`│ `,` `.repeat(o.length+2),r.evidence))}),t>0&&n.push(`└─ …+${t} more findings withheld (a report renders at most 20)`),n}function wr(e,t){let n=e.map((n,r)=>`${r===e.length-1&&t===0?`└─ `:`├─ `}[${r}] `+`${V(n).trim()}`.trimEnd());return t>0&&n.push(`└─ …+${t} more files withheld (a report renders at most 20)`),n}function Tr(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`${vr} (channel: ${e})\n${$n}${t}`}function Er(e,t){if(e===void 0)return Tr(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:br(e.summary),rows:[]},{label:`findings`,head:yr(e.findings.length),rows:Cr(n,r)},{label:`files`,head:yr(e.files_touched.length),rows:wr(i,a)},{label:`usage`,head:xr(e.usage),rows:[]}],s=[`${vr} (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(G(`${n?$n:Qn}${r}${e.head}`,200));let i=n?` `:er;for(let t of e.rows)s.push(G(`${i}${t}`,200))}),s.join(`
31
- `)}function Dr(e,t,n=`run_code`,r={}){let i=(typeof e.description==`string`&&e.description.trim().length>0?e.description.trim():e.meta?.name)??``,a=ar(e.code??e.script??``),o=i.length>0?i:a??`(no description)`;return Yn(new tr([{left:`└─ ${`${t.fg(`toolTitle`,t.bold(Zn[n]))} ${t.fg(`accent`,o)}`}`}]),{intervalMs:150,isPartial:r.isPartial??!1,theme:t,requestInvalidate:r.requestInvalidate??Or,state:r.state??{}})}function Or(){}function kr(e){let t=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0);return rr(t?.text??``)||`failed`}function Ar(e,t){if(e===`pi.dispatch`&&typeof t==`object`&&t&&`agent`in t)return`→ ${String(t.agent)}`;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 jr={running:{text:()=>`running`,themeSlot:`muted`},ok:{text:e=>e.durationMs===void 0?`ok`:`ok ${ir(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 Mr(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=Ar(e.name,e.args),l=jr[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 Nr(e,t,n,r=!1,i=!1){let a=sr(e.details,n),o=e=>a===void 0?e:{...e,right:a};if(t)return[o({left:` ${n.fg(`error`,`failed: ${kr(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(ur(s))return _r(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=or(s);return c===void 0?[o({left:` ${n.fg(`muted`,`done`)}`})]:[o({left:` ${n.fg(`dim`,`→ ${c}`)}`})]}function Pr(e,t,n,r={}){let i=cr(e.details),a=[...Nr({...e,details:i},t,n,!1,r.isPartial===!0)];return i?.subCalls!==void 0&&a.push(...Mr(i.subCalls,n)),new tr(a)}function Fr(e,t,n,r,i={}){let a=cr(e.details);if(n){let t=[...Nr({...e,details:a},!0,r)];a?.subCalls!==void 0&&t.push(...Mr(a.subCalls,r));let n=V(e.content?.find(e=>e.type===`text`)?.text??kr(e));for(let e of n.split(`
32
- `).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new tr(t)}let o=[],s=t.code??t.script??``;if(s.length>0){let e=s.split(`
33
- `).map(e=>U(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=>V(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=>V(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=>V(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=Nr({...e,details:a},!1,r,l,i.isPartial===!0);c!==void 0&&u.push(...Mr(c,r));for(let e=0;e<o.length;e+=1){let t=e===o.length-1;u.push(...lr(o[e]??{label:``,lines:[]},t,r))}return new tr(u)}function Ir(e){return{renderCall(t,n,r){return Dr(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?Fr(e,r?.args??{},r?.isError===!0,n,{isPartial:i}):Pr(e,r?.isError===!0,n,{isPartial:i})}}}const Lr=["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" })` or `await tools.bash({ command: "npm test" })`.',"The bound names mirror the session's active tools (a default session has `read`, `bash`, `edit`,","`write`); 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.`,``,yn,``,"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(`
34
- `),Rr=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 ${F.timeoutMs/1e3} s; anything above ${F.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 zr(e={}){return g({name:`ptc_run_code`,label:`PTC Run Code`,description:Lr,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:[...Rn],parameters:Rr,async execute(t,n,r,i,a){let o=Bn(a),s=H(e.getBindingSourceNames?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=Vn({surface:`run_code`,startedAt:c,onUpdate:i}),p;try{p=await gn({code:n.code,surface:`run_code`,cwd:o,bindings:rn({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 Un(p);return Wn({outcome:p,surface:`run_code`,durationMs:Date.now()-c})},...Ir(`run_code`)})}const Br=[`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","mirror the session's enabled tools. 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.",``,yn,``,`Image-bearing tool results inside the script are attached to you after the run — never return`,`image data as the script's value.`].join(`
35
- `),Vr=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 Hr(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=Ur(t[e],`args.${e}`,/* @__PURE__ */ new Set);if(n!==void 0)throw TypeError(`ptc_workflow args must be plain JSON: ${n}`)}}}function Ur(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=Ur(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=Ur(i[e],`${n}.${e}`,r);if(t!==void 0)return t}return}finally{r.delete(i)}}function Wr(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 Gr(e={}){return g({name:`ptc_workflow`,label:`PTC Workflow`,description:Br,promptSnippet:`Run a structured TypeScript workflow with named phases, narration (log/phase) and structured concurrency (parallel/pipeline)`,promptGuidelines:[...Rn],parameters:Vr,async execute(t,n,r,i,a){Hr(n.args);let o=Bn(a),s=H(e.getBindingSourceNames?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=Vn({surface:`workflow`,startedAt:c,onUpdate:i}),p;try{p=await gn({code:n.script,surface:`workflow`,cwd:o,bindings:rn({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 Un(p);let m=n.meta.phases?.map(e=>e.name);return Wn({outcome:p,surface:`workflow`,warnings:Wr(p,m),durationMs:Date.now()-c})},...Ir(`workflow`)})}var Kr=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 qr(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}var Jr=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(qr(e))return null;throw e}}async writeOutput(e,t){let n=D(this.#e,`tasks`,e);await he(n,{recursive:!0}),await be(D(n,`output.log`),t,`utf8`)}outputRef(e){return this.#t(e)}#t(e){return D(this.#e,`tasks`,e,`output.log`)}};function Yr(e,t){return Cn(e,`pi-ptc-task-output-`,t===void 0?{}:{fullText:t})}const Xr={running:`accent`,stopping:`warning`,succeeded:`success`,failed:`error`,lost:`dim`,canceled:`muted`},Zr={running:`●`,stopping:`◐`,succeeded:`✓`,failed:`✗`,lost:`◌`,canceled:`⊘`};var K=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>Qr(e,t))}};function Qr(e,t){let{left:n,right:r}=e;if(r===void 0)return N(n,t,`…`);let i=P(r);if(i>=t)return N(r,t,`…`);let a=N(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-P(a));return a+` `.repeat(o)+r}function $r(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function ei(e){return $r((V(e).split(`
36
- `).find(e=>e.trim().length>0)??``).trim(),120)}function ti(e){return typeof e==`object`&&e?e:{}}function ni(e){return e===`running`||e===`stopping`}function ri(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 ii(e,t){if(ni(e.status))return ri(t-e.createdAt);if(e.durationMs!==void 0)return ri(e.durationMs);if(e.finishedAt!==void 0)return ri(e.finishedAt-e.createdAt)}function ai(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 oi(){}function si(e,t,n){return new K([{left:`└─ ${n.fg(`toolTitle`,n.bold(e))}${t.length>0?` ${t}`:``}`}])}function ci(e,t,n){let r=ti(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 si(`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 si(`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=${V(r.reason)}`:``;return si(`PTC task stop`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}}}function li(e,t,n,r){let i=Xr[e.status]??`muted`,a=n.fg(i,Zr[e.status]??`?`),o=$r(V(e.label),48),s=[`${a} ${n.fg(`text`,o)}`,n.fg(`dim`,V(e.agentName))],c=ii(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 ui(e,t){let n=ti(e),r=Array.isArray(n.tasks)?n.tasks:[];if(r.length===0)return ai(new K([{left:` ${t.theme.fg(`muted`,`(no background tasks)`)}`}]),{isLive:!1,state:t.state,requestInvalidate:t.requestInvalidate});let i=r.some(e=>ni(e.status)),a=r.slice(0,32),o=r.length-a.length,s=a.map((e,n)=>li(e,n===a.length-1&&o===0,t.theme,t.now));return o>0&&s.push({left:` └─ ${t.theme.fg(`dim`,`…+${o} more tasks`)}`}),ai(new K(s),{isLive:t.partial&&i,state:t.state,requestInvalidate:t.requestInvalidate})}function di(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 fi(e,t){return` ${t.fg(`dim`,`full output: `)}${t.fg(`accent`,e)}`}function pi(e,t){let n=ti(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=di(i,a,t.theme),c=[];if(r.length>0){let e=V(r).split(`
37
- `),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,$r(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:fi(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:fi(o,t.theme),...s===void 0?{}:{right:s}});return new K(c)}function mi(e,t){let n=ti(e),r=n.task;if(typeof r!=`object`||!r)return new K([{left:` ${t.theme.fg(`muted`,`(no task)`)}`}]);let i=Xr[r.status]??`muted`,a=t.theme.fg(i,Zr[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`,V(r.id))}`,t.theme.fg(i,s)];return typeof r.stopReason==`string`&&r.stopReason.length>0&&c.push(t.theme.fg(`dim`,`reason=${V(r.stopReason)}`)),new K([{left:` ${c.join(` `)}`}])}function hi(e,t){let n=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0),r=ei(n?.text??``)||`failed`;return new K([{left:` ${t.fg(`error`,`failed: ${r}`)}`}])}function gi(e,t,n){switch(e){case`task-list`:return ui(t.details,n);case`task-output`:return pi(t.details,n);case`task-stop`:return mi(t.details,n)}}function _i(e){return{renderCall(t,n){return ci(e,t,n)},renderResult(t,n,r,i){return i?.isError===!0?hi(t,r):gi(e,t,{theme:r,partial:n?.isPartial===!0||i?.isPartial===!0,requestInvalidate:i?.invalidate??oi,state:i?.state??{},now:Date.now()})}}}const vi=[`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.`],yi=x.Union([x.Literal(`running`),x.Literal(`stopping`),x.Literal(`succeeded`),x.Literal(`failed`),x.Literal(`canceled`),x.Literal(`lost`)]),bi=x.Object({status:x.Optional(x.Array(yi,{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.`}))}),xi=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 Si(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 Ci(e){let t=[e.id,e.status,`${e.agentName} depth=${e.depth}`,V(e.label)];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.errorMessage!==void 0&&t.push(`error=${V(e.errorMessage)}`),t.join(` `)}function wi(e){return g({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(`
38
- `),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...vi],parameters:bi,outputSchema:xi,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=>Ci(e)).join(`
39
- `),a={tasks:r.map(e=>Si(e)),count:r.length};return{content:[{type:`text`,text:i}],details:{tasks:r,count:r.length},structuredContent:a}},..._i(`task-list`)})}async function Ti(e,t,n){let r=await e.get(t);if(r===null)throw Error(`${n}: unknown taskId ${t}`);return r}function Ei(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(`
40
- `)}const Di=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.`}))}),Oi=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 ki(e,t){return g({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(`
41
- `),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...vi],parameters:Di,outputSchema:Oi,async execute(n,r){let i=r.taskId,a=await Ti(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=Yr(c===0?o:l.subarray(c).toString(`utf8`),o),d=s<=2048?o:void 0,f=Ei(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}},..._i(`task-output`)})}const Ai=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".`}))}),ji=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 Mi(e,t,n={}){if(t==null)throw TypeError(`createPtcTaskStopTool: lifecycle is required`);let r=n.clock??(()=>Date.now());return g({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(`
42
- `),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...vi],parameters:Ai,outputSchema:ji,async execute(t,n){let i=n.taskId,a=await Ti(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=${V(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}},..._i(`task-stop`)})}var Ni=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:un,size:this.#e.poolSize,acquireTimeoutMs:this.#e.poolAcquireTimeoutMs,drainGraceMs:this.#e.drainGraceMs,workerOptions:on({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 Pi={warn:e=>{console.warn(`[pi-ptc.notifications] `+e)}};var Fi=class{#e;#t;#n;#r;#i;constructor(e,t={}){this.#e=e,this.#t=t.now??Date.now,this.#n=t.logger??Pi,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 Ii={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 Li(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}function Ri(e){return e instanceof Error?e.message:String(e)}function zi(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}var Bi=class{#e;#t;constructor(e,t={}){if(e.length===0)throw TypeError(`FileTaskStorage: baseDir is required`);this.#e=e,this.#t=t.fs??Ii}async loadTask(e){return await this.#r(this.#f(e))}async saveTask(e){M(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(D(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){M(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||zi(r[t-1],e)<=0)?r:[...r].sort(zi)).map(e=>JSON.stringify(e)).join(`
19
+ `)}function Pn(e){if(typeof e==`string`)return Nn(H(e));if(typeof e!=`object`||!e)return String(e);let t=kn(e);return Nn((t===void 0?Mn(e,``):[t]).join(`
20
+ `))}function Fn(e=process.env){let t=e.PI_PTC_DEPTH;return t===void 0||!/^\d+$/.test(t)?0:Number.parseInt(t,10)}function In(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 U(e){if(e===void 0)return L;let t=new Set(e);return L.filter(e=>t.has(e))}const Ln=["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.`],Rn={run_code:`ptc_run_code`,workflow:`ptc_workflow`};function zn(e){let t=e?.cwd;return typeof t==`string`&&t.length>0?t:process.cwd()}function Bn(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 Vn(e){return[...e.phases.map(e=>`[phase] ${H(e)}`),...e.narrations.map(e=>`[log] ${H(e)}`),...e.logs.map(e=>H(e))]}function Hn(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=Vn(e),r=n.length===0?``:`\nCaptured output:\n${n.join(`
21
+ `)}`,i=Error(H(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function Un(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=>H(e)).join(` → `)}`),t.narrations.length>0&&a.push(t.narrations.map(e=>H(e)).join(`
22
+ `)),t.logs.length>0&&a.push(t.logs.map(e=>H(e)).join(`
23
+ `)),t.value!==void 0&&a.push(Pn(t.value));for(let e of r)a.push(`Warning: ${H(e)}`);let o=Sn(a.length>0?a.join(`
24
+ `):`(${Rn[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 Wn=/^(.*?)(└─ |├─ | )(?:PTC(?: workflow)?)([ ].*)$/;function Gn(e){return e.replace(/\x1b\[[0-9;]*m|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[\?[0-9;]*[a-zA-Z]/g,``)}function Kn(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 qn(e,t){let n=0,r=0;for(;r<t&&n<e.length;)e.charCodeAt(n)===27?n=Kn(e,n):(n+=1,r+=1);return n}function Jn(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:Yn(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 Yn(e,t,n){return e.map(e=>{let r=Gn(e),i=Wn.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=qn(e,s),l=qn(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 Xn={run_code:`PTC`,workflow:`PTC workflow`},Zn=`├─ `,Qn=`└─ `,$n=`│ `;var er=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>tr(e,t))}};function tr(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 W(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function nr(e){return W((H(e).split(`
25
+ `).find(e=>e.trim().length>0)??``).trim(),120)}function rr(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2).replace(/\.?0+$/,``)}s`}function G(e,t){return`${e} ${t}${e===1?``:`s`}`}function ir(e){for(let t of e.split(`
26
+ `)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return W(e.replace(/\s*\/\/.*$/,``),120)}}function ar(e){if(e===void 0)return;if(typeof e==`string`){let t=H(e).split(`
27
+ `),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:W(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=Pn(e);if(!t.includes(`
28
+ `)&&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 or(e,t){if(e===void 0)return;let n=[],r=e.logs.length+e.narrations.length;if(r>0&&n.push(t.fg(`dim`,G(r,`output line`))),e.imageCount>0&&n.push(t.fg(`toolOutput`,G(e.imageCount,`image`))),e.surface===`workflow`&&e.phases.length>0&&n.push(t.fg(`dim`,G(e.phases.length,`phase`))),e.warnings.length>0&&n.push(t.fg(`warning`,G(e.warnings.length,`warning`))),e.fullOutputPath!==void 0&&n.push(t.fg(`warning`,`truncated`)),e.durationMs>0&&n.push(t.fg(`dim`,rr(e.durationMs))),n.length!==0)return`${t.fg(`dim`,`•`)} ${n.join(t.fg(`dim`,` · `))}`}function sr(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 cr(e,t,n){let r=` `+(t?Qn:Zn),i=` `+(t?` `:$n),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 lr(e){return typeof e!=`object`||!e?!1:Array.isArray(e)?e.length>0:Object.keys(e).length>0}const ur=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function dr(e){return ur.test(e)?e:JSON.stringify(e)}function fr(e,t){if(e===null)return`null`;if(typeof e==`boolean`||typeof e==`number`)return String(e);if(typeof e==`string`){let n=H(e);if(n.length===0)return`""`;if(n.includes(`
29
+ `)){let e=W(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(W(n,Math.max(2,t-5)))+`…`}return`?`}function pr(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(pr))return;let n=`[`+e.map(e=>fr(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(pr))return;let r=`{`+n.map(n=>{let r=e[n]??null;return dr(n)+`: `+fr(r,Math.max(2,Math.floor(t/4)))}).join(`, `)+`}`;return r.length<=t?r:void 0}function hr(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+fr(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;hr(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];hr(e[l]??null,dr(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 gr(e,t={}){let n=t.maxDepth??4,r=t.maxChildren??6,i=t.maxLineChars??120,a=t.moreAfter===!0;if(!lr(e))return typeof e==`object`&&e?[Array.isArray(e)?`[]`:`{}`]:[fr(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;hr(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];hr(e[d]??null,dr(d)+`: `,``,u,n,r,i,0,o)}return c>l&&o.push((a?`├─ `:`└─ `)+`…+`+(c-l)+` more keys`),o}const _r=`child report`;function vr(e){return e===0?`[]`:`Array(${e})`}function yr(e){let t=H(e).split(`
30
+ `).find(e=>e.trim().length>0)?.trim()??``;return t.length===0?`""`:W(t,200)}function br(e){let t=Number(e.cost.toFixed(4));return`in ${e.input} · out ${e.output} · cost ${t} · ${G(e.turns,`turn`)}`}function xr(e,t,n){let r=H(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 Sr(e,t){let n=[];return e.forEach((r,i)=>{let a=i===e.length-1&&t===0,o=`[${i}]`;n.push(`${a?`└─ `:`├─ `}${o} ${H(r.what).trim()}`.trimEnd()),n.push(xr(a?` `:`│ `,` `.repeat(o.length+2),r.evidence))}),t>0&&n.push(`└─ …+${t} more findings withheld (a report renders at most 20)`),n}function Cr(e,t){let n=e.map((n,r)=>`${r===e.length-1&&t===0?`└─ `:`├─ `}[${r}] `+`${H(n).trim()}`.trimEnd());return t>0&&n.push(`└─ …+${t} more files withheld (a report renders at most 20)`),n}function wr(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`${_r} (channel: ${e})\n${Qn}${t}`}function Tr(e,t){if(e===void 0)return wr(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:yr(e.summary),rows:[]},{label:`findings`,head:vr(e.findings.length),rows:Sr(n,r)},{label:`files`,head:vr(e.files_touched.length),rows:Cr(i,a)},{label:`usage`,head:br(e.usage),rows:[]}],s=[`${_r} (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(K(`${n?Qn:Zn}${r}${e.head}`,200));let i=n?` `:$n;for(let t of e.rows)s.push(K(`${i}${t}`,200))}),s.join(`
31
+ `)}function Er(e,t,n=`run_code`,r={}){let i=(typeof e.description==`string`&&e.description.trim().length>0?e.description.trim():e.meta?.name)??``,a=ir(e.code??e.script??``),o=i.length>0?i:a??`(no description)`;return Jn(new er([{left:`└─ ${`${t.fg(`toolTitle`,t.bold(Xn[n]))} ${t.fg(`accent`,o)}`}`}]),{intervalMs:150,isPartial:r.isPartial??!1,theme:t,requestInvalidate:r.requestInvalidate??Dr,state:r.state??{}})}function Dr(){}function Or(e){let t=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0);return nr(t?.text??``)||`failed`}function kr(e,t){if(e===`pi.dispatch`&&typeof t==`object`&&t&&`agent`in t)return`→ ${String(t.agent)}`;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 Ar={running:{text:()=>`running`,themeSlot:`muted`},ok:{text:e=>e.durationMs===void 0?`ok`:`ok ${rr(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 jr(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=kr(e.name,e.args),l=Ar[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 Mr(e,t,n,r=!1,i=!1){let a=or(e.details,n),o=e=>a===void 0?e:{...e,right:a};if(t)return[o({left:` ${n.fg(`error`,`failed: ${Or(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(lr(s))return gr(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=ar(s);return c===void 0?[o({left:` ${n.fg(`muted`,`done`)}`})]:[o({left:` ${n.fg(`dim`,`→ ${c}`)}`})]}function Nr(e,t,n,r={}){let i=sr(e.details),a=[...Mr({...e,details:i},t,n,!1,r.isPartial===!0)];return i?.subCalls!==void 0&&a.push(...jr(i.subCalls,n)),new er(a)}function Pr(e,t,n,r,i={}){let a=sr(e.details);if(n){let t=[...Mr({...e,details:a},!0,r)];a?.subCalls!==void 0&&t.push(...jr(a.subCalls,r));let n=H(e.content?.find(e=>e.type===`text`)?.text??Or(e));for(let e of n.split(`
32
+ `).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new er(t)}let o=[],s=t.code??t.script??``;if(s.length>0){let e=s.split(`
33
+ `).map(e=>W(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=>H(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=>H(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=>H(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=Mr({...e,details:a},!1,r,l,i.isPartial===!0);c!==void 0&&u.push(...jr(c,r));for(let e=0;e<o.length;e+=1){let t=e===o.length-1;u.push(...cr(o[e]??{label:``,lines:[]},t,r))}return new er(u)}function Fr(e){return{renderCall(t,n,r){return Er(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?Pr(e,r?.args??{},r?.isError===!0,n,{isPartial:i}):Nr(e,r?.isError===!0,n,{isPartial:i})}}}const Ir=["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" })` or `await tools.bash({ command: "npm test" })`.',"The bound names mirror the session's active tools (a default session has `read`, `bash`, `edit`,","`write`); 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.`,``,vn,``,"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(`
34
+ `),Lr=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 ${I.timeoutMs/1e3} s; anything above ${I.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 Rr(e={}){return g({name:`ptc_run_code`,label:`PTC Run Code`,description:Ir,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:[...Ln],parameters:Lr,async execute(t,n,r,i,a){let o=zn(a),s=U(e.getBindingSourceNames?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=Bn({surface:`run_code`,startedAt:c,onUpdate:i}),p;try{p=await hn({code:n.code,surface:`run_code`,cwd:o,bindings:nn({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 Hn(p);return Un({outcome:p,surface:`run_code`,durationMs:Date.now()-c})},...Fr(`run_code`)})}const zr=[`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","mirror the session's enabled tools. 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.",``,vn,``,`Image-bearing tool results inside the script are attached to you after the run — never return`,`image data as the script's value.`].join(`
35
+ `),Br=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 Vr(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=Hr(t[e],`args.${e}`,/* @__PURE__ */ new Set);if(n!==void 0)throw TypeError(`ptc_workflow args must be plain JSON: ${n}`)}}}function Hr(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=Hr(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=Hr(i[e],`${n}.${e}`,r);if(t!==void 0)return t}return}finally{r.delete(i)}}function Ur(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 Wr(e={}){return g({name:`ptc_workflow`,label:`PTC Workflow`,description:zr,promptSnippet:`Run a structured TypeScript workflow with named phases, narration (log/phase) and structured concurrency (parallel/pipeline)`,promptGuidelines:[...Ln],parameters:Br,async execute(t,n,r,i,a){Vr(n.args);let o=zn(a),s=U(e.getBindingSourceNames?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=Bn({surface:`workflow`,startedAt:c,onUpdate:i}),p;try{p=await hn({code:n.script,surface:`workflow`,cwd:o,bindings:nn({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 Hn(p);let m=n.meta.phases?.map(e=>e.name);return Un({outcome:p,surface:`workflow`,warnings:Ur(p,m),durationMs:Date.now()-c})},...Fr(`workflow`)})}var Gr=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 Kr(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}var qr=class{#e;constructor(e){if(e.length===0)throw TypeError(`FileOutputStorage: baseDir is required`);this.#e=e}async readOutput(e){try{return await he(this.#t(e),`utf8`)}catch(e){if(Kr(e))return null;throw e}}async writeOutput(e,t){let n=O(this.#e,`tasks`,e);await me(n,{recursive:!0}),await ye(O(n,`output.log`),t,`utf8`)}outputRef(e){return this.#t(e)}#t(e){return O(this.#e,`tasks`,e,`output.log`)}};function Jr(e,t){return Sn(e,`pi-ptc-task-output-`,t===void 0?{}:{fullText:t})}const Yr={running:`accent`,stopping:`warning`,succeeded:`success`,failed:`error`,lost:`dim`,canceled:`muted`},Xr={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=>Zr(e,t))}};function Zr(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 Qr(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function $r(e){return Qr((H(e).split(`
36
+ `).find(e=>e.trim().length>0)??``).trim(),120)}function ei(e){return typeof e==`object`&&e?e:{}}function ti(e){return e===`running`||e===`stopping`}function ni(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 ri(e,t){if(ti(e.status))return ni(t-e.createdAt);if(e.durationMs!==void 0)return ni(e.durationMs);if(e.finishedAt!==void 0)return ni(e.finishedAt-e.createdAt)}function ii(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 ai(){}function oi(e,t,n){return new q([{left:`└─ ${n.fg(`toolTitle`,n.bold(e))}${t.length>0?` ${t}`:``}`}])}function si(e,t,n){let r=ei(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 oi(`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 oi(`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=${H(r.reason)}`:``;return oi(`PTC task stop`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}}}function ci(e,t,n,r){let i=Yr[e.status]??`muted`,a=n.fg(i,Xr[e.status]??`?`),o=Qr(H(e.label),48),s=[`${a} ${n.fg(`text`,o)}`,n.fg(`dim`,H(e.agentName))],c=ri(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 li(e,t){let n=ei(e),r=Array.isArray(n.tasks)?n.tasks:[];if(r.length===0)return ii(new q([{left:` ${t.theme.fg(`muted`,`(no background tasks)`)}`}]),{isLive:!1,state:t.state,requestInvalidate:t.requestInvalidate});let i=r.some(e=>ti(e.status)),a=r.slice(0,32),o=r.length-a.length,s=a.map((e,n)=>ci(e,n===a.length-1&&o===0,t.theme,t.now));return o>0&&s.push({left:` └─ ${t.theme.fg(`dim`,`…+${o} more tasks`)}`}),ii(new q(s),{isLive:t.partial&&i,state:t.state,requestInvalidate:t.requestInvalidate})}function ui(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 di(e,t){return` ${t.fg(`dim`,`full output: `)}${t.fg(`accent`,e)}`}function fi(e,t){let n=ei(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=ui(i,a,t.theme),c=[];if(r.length>0){let e=H(r).split(`
37
+ `),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,Qr(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:di(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:di(o,t.theme),...s===void 0?{}:{right:s}});return new q(c)}function pi(e,t){let n=ei(e),r=n.task;if(typeof r!=`object`||!r)return new q([{left:` ${t.theme.fg(`muted`,`(no task)`)}`}]);let i=Yr[r.status]??`muted`,a=t.theme.fg(i,Xr[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`,H(r.id))}`,t.theme.fg(i,s)];return typeof r.stopReason==`string`&&r.stopReason.length>0&&c.push(t.theme.fg(`dim`,`reason=${H(r.stopReason)}`)),new q([{left:` ${c.join(` `)}`}])}function mi(e,t){let n=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0),r=$r(n?.text??``)||`failed`;return new q([{left:` ${t.fg(`error`,`failed: ${r}`)}`}])}function hi(e,t,n){switch(e){case`task-list`:return li(t.details,n);case`task-output`:return fi(t.details,n);case`task-stop`:return pi(t.details,n)}}function gi(e){return{renderCall(t,n){return si(e,t,n)},renderResult(t,n,r,i){return i?.isError===!0?mi(t,r):hi(e,t,{theme:r,partial:n?.isPartial===!0||i?.isPartial===!0,requestInvalidate:i?.invalidate??ai,state:i?.state??{},now:Date.now()})}}}const _i=[`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.`],vi=x.Union([x.Literal(`running`),x.Literal(`stopping`),x.Literal(`succeeded`),x.Literal(`failed`),x.Literal(`canceled`),x.Literal(`lost`)]),yi=x.Object({status:x.Optional(x.Array(vi,{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.`}))}),bi=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 xi(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 Si(e){let t=[e.id,e.status,`${e.agentName} depth=${e.depth}`,H(e.label)];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.errorMessage!==void 0&&t.push(`error=${H(e.errorMessage)}`),t.join(` `)}function Ci(e){return g({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(`
38
+ `),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[..._i],parameters:yi,outputSchema:bi,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=>Si(e)).join(`
39
+ `),a={tasks:r.map(e=>xi(e)),count:r.length};return{content:[{type:`text`,text:i}],details:{tasks:r,count:r.length},structuredContent:a}},...gi(`task-list`)})}async function wi(e,t,n){let r=await e.get(t);if(r===null)throw Error(`${n}: unknown taskId ${t}`);return r}function Ti(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(`
40
+ `)}const Ei=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.`}))}),Di=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 Oi(e,t){return g({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(`
41
+ `),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[..._i],parameters:Ei,outputSchema:Di,async execute(n,r){let i=r.taskId,a=await wi(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=Jr(c===0?o:l.subarray(c).toString(`utf8`),o),d=s<=2048?o:void 0,f=Ti(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}},...gi(`task-output`)})}const ki=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".`}))}),Ai=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 ji(e,t,n={}){if(t==null)throw TypeError(`createPtcTaskStopTool: lifecycle is required`);let r=n.clock??(()=>Date.now());return g({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(`
42
+ `),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[..._i],parameters:ki,outputSchema:Ai,async execute(t,n){let i=n.taskId,a=await wi(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=${H(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}},...gi(`task-stop`)})}var Mi=class{#e;#t=/* @__PURE__ */ new Map;constructor(e={}){this.#e=ze(e.config)}get(e){let t=this.#t.get(e);if(t!==void 0)return t;let n=Re(),r=new on({buildWorkerUrl:ln,size:this.#e.poolSize,acquireTimeoutMs:this.#e.poolAcquireTimeoutMs,drainGraceMs:this.#e.drainGraceMs,workerOptions:an({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 Ni={warn:e=>{console.warn(`[pi-ptc.notifications] `+e)}};var Pi=class{#e;#t;#n;#r;#i;constructor(e,t={}){this.#e=e,this.#t=t.now??Date.now,this.#n=t.logger??Ni,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 Fi={mkdir:(e,t)=>me(e,t),readFile:(e,t)=>he(e,t),writeFile:(e,t,n)=>ye(e,t,n),appendFile:(e,t,n)=>pe(e,t,n),rename:(e,t)=>_e(e,t),unlink:e=>ve(e),readdir:e=>ge(e)};function Ii(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}function Li(e){return e instanceof Error?e.message:String(e)}function Ri(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}var zi=class{#e;#t;constructor(e,t={}){if(e.length===0)throw TypeError(`FileTaskStorage: baseDir is required`);this.#e=e,this.#t=t.fs??Fi}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(O(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||Ri(r[t-1],e)<=0)?r:[...r].sort(Ri)).map(e=>JSON.stringify(e)).join(`
43
43
  `)+`
44
- `;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(zi);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(D(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(Li(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+`: `+Ri(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(Li(e))return[];throw e}let n=[];for(let r of t.split(`
45
- `)){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+`: `+Ri(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(oe(e),{recursive:!0});let n=e+`.tmp-`+j();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(Li(e))return[];throw e}}async#c(e){try{return await this.#t.readFile(e,{encoding:`utf8`}),!0}catch(e){if(Li(e))return!1;throw e}}#l(){return D(this.#e,`tasks`)}#u(){return D(this.#e,`subscriptions`)}#d(){return D(this.#e,`events`)}#f(e){return D(this.#l(),e+`.json`)}#p(e,t){return D(this.#u(),e+`-`+t+`.json`)}#m(e,t){return D(this.#d(),e+`-`+t+`.jsonl`)}};function Vi(e,t){return new Bi(e,t)}const Hi=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Ui=/* @__PURE__ */ new Set([`running`,`stopping`]),Wi=2**53-1,Gi={info:()=>void 0,warn:e=>{console.warn(`[pi-ptc.background] `+e)}};function q(e){return e instanceof Error?e.message:String(e)}function Ki(e){return e===void 0||e.length===0?`<in-memory>`:e}function qi(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}var Ji=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()}},Yi=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)}},Xi=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)}},Zi=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]}},Qi=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??Gi,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:Vi(e)),this.#n=e.createOutputStorage??(e=>e===void 0||e.length===0?new Kr:new Jr(e));let t=(e.createInitialStorage??(()=>new rt))(),n=et(t,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),r=new Fi(t,{now:this.clock,logger:this.#e});this.registry=new Ji(n),this.outputStorage=new Yi(new Kr),this.pipeline=new Xi(r),this.lifecycle=new Zi((e.createLifecycle??(()=>new Ie({logger:this.#e})))()),this.slots=new at(e.concurrency??F.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||Hi.has(e.status)&&this.pipeline.notifyIdle(t.subscriptionId,e.id).catch(t=>{this.#e.warn(`terminal notification wake for task `+e.id+` failed: `+q(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 `+Ki(e)+` is unavailable: `+q(n),t),[]}let i=et(n,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),a=new Fi(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): `+q(e),t),[]}finally{this.registry.onTransition(this.#o)}}async drainNotifications(e){let t;try{t=await this.registry.query({limit:Wi})}catch(t){return this.#e.warn(`drainNotifications: could not list tasks for subscriber `+e+`: `+q(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+`: `+q(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+`: `+q(e))}}async shutdown(e){if(this.#a)return[];this.#a=!0;let t;try{t=await this.registry.query({limit:Wi})}catch(e){this.#e.warn(`shutdown: could not list tasks: `+q(e)),t=[]}let n=[];for(let r of t)if(Ui.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:qi(r),logger:this.#e});n.push(t.record)}catch(e){this.#e.warn(`shutdown: could not mark task `+r.id+` lost: `+q(e))}for(let e of this.lifecycle.liveHandles()){let t=pt(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: `+q(e))}}};function $i(e={}){return new Qi(e)}const ea=/* @__PURE__ */ new Set([`succeeded`,`failed`,`lost`]);function ta(e){return ea.has(e.status)}function na(e,t){if(e.length===0)return``;let n=e.map(ia).join(`
46
- `);return`${`<bg-task-notifications batch-id="${J(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function ra(e,t=102400){let n=[],r=[],i=0,a=t-oa;for(let t of e){let e=aa(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 ia(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="${J(t.type)}"`,` task-id="${J(t.taskId)}"`,` subscription-id="${J(t.subscriptionId)}"`,` status="${J(t.status)}"`,` label="${J(n.label)}"`,` agent-name="${J(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>${J(n.outputRef)}</output-ref>`),r!==void 0&&r<=2048&&a!==void 0&&o.push(` <output-preview>${J(a)}</output-preview>`),o.push(` </bg-task-notification>`),o.join(`
47
- `)}function J(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`"`,`&quot;`).replaceAll(` `,`&#9;`).replaceAll(`
48
- `,`&#10;`).replaceAll(`\r`,`&#13;`)}function aa(e){return Buffer.byteLength(ia(e),`utf8`)}const oa=Buffer.byteLength(`<bg-task-notifications batch-id="${`0`.repeat(26)}" delivered-at-ms="${`9`.repeat(13)}">\n\n</bg-task-notifications>`,`utf8`),sa=[`ptc_run_code`,`ptc_workflow`],ca=[`read`,`bash`,`edit`,`write`],la=`ptc-mode`,ua=`ptc-mode`,Y=`ptc.json`,da=`builtins-only`;function fa(){return{enabled:!1,base:void 0,ourLoadout:void 0}}function pa(e){let t=D(e,Y),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}`}}const X=[`off`,`subagents`,`full`],ma=`full`,Z=`builtin:codemode`;function Q(e){return e.split(A).join(`/`)}function ha(e){return Q(e.startsWith(`./`)||e.startsWith(`.\\`)?e.slice(2):e)}function ga(e,t,n){let r=Q(O(n,e)),i=ae(e),a=Q(e);return t.some(e=>{let t=Q(e);return xe(r,t)||xe(i,t)||xe(a,t)})}function _a(e,t,n){if(t.length===0)return!1;let r=Q(O(n,e)),i=Q(e);return t.some(e=>{let t=ha(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 ya(e,t){if(!Array.isArray(e))return;let n;for(let{sign:r,target:i}of va(e)){let e=r!==`-`&&r!==`!`;(r===`+`||r===`-`?_a(Z,[i],t):ga(Z,[i],t))&&(n=e?`enabled`:`disabled`)}return n}function ba(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 ga(Z,i,t)&&(s=`disabled`),_a(Z,a,t)&&(s=`enabled`),_a(Z,o,t)&&(s=`disabled`),s}function xa(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 Sa(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 Ca(e,t,n,r={project:process.cwd(),user:process.cwd()}){let i=e.slice(1);if(xa(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=ya(a,r.project);if(o!==void 0)return{switch:o,source:`project`};let s=n?.extensions,c=ba(s,r.user);return c===void 0?{switch:`absent`,source:`default`}:{switch:c,source:`user`}}function wa(e,t,n=process.argv){let r=Sa(D(t,`.pi`,`settings.json`)),i=Sa(D(e,`settings.json`)),a=Ca(n,r.value,i.value,{project:D(t,`.pi`),user:e}),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}const Ta=[`read`,`bash`,`edit`,`write`];function Ea(e){return typeof e==`string`&&(e.startsWith(`+`)||e.startsWith(`-`))}function Da(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function Oa(e,t){return t===void 0?e:!Array.isArray(e)||!Array.isArray(t)||!t.every(Ea)?t:[...e,...t]}function ka(e){let t=e.filter(e=>!Ea(e)),n=t.length>0||e.length===0?t:[...Ta];for(let t of e){if(!Ea(t))continue;let e=t.slice(1),r=n.indexOf(e);t.startsWith(`+`)&&r===-1&&e?n.push(e):t.startsWith(`-`)&&r!==-1&&n.splice(r,1)}return n}function Aa(e){for(let t=0;t<e.length;t+=1){if(e[t]!==`--tools`&&e[t]!==`-t`)continue;let n=e[t+1];return n===void 0?void 0:n.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}}function ja(e,t,n){let r=Aa(e.slice(1));if(r!==void 0)return{activation:r.includes(`codemode`)?`active`:`inactive`,source:`cli`};let i=t?.defaultTools,a=n?.defaultTools,o=Oa(a,i);return o===void 0?{activation:`inactive`,source:`default`}:{activation:ka(Da(o)).includes(`codemode`)?`active`:`inactive`,source:i===void 0?`user`:`project`}}function Ma(e,t,n=process.argv){let r=Sa(D(t,`.pi`,`settings.json`)),i=Sa(D(e,`settings.json`)),a=ja(n,r.value,i.value),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}function Na(e,t,n){return!e.present||t===`disabled`||n!==`active`?ma:`subagents`}function Pa(e,t){return e!==void 0&&e!==`off`&&e!==t}function Fa(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=oe(n);for(let e of Ia){let t=D(r,...e);try{if(te(t).isDirectory())return{present:!0,how:`found`}}catch{}}return{present:!1,how:`not-found`}}const Ia=[[`..`,`extensions`,`codemode`],[`..`,`..`,`extensions`,`codemode`],[`extensions`,`codemode`]];function La(e,t,n,r,i=process.cwd()){let a=D(e,Y),o=()=>{let a=t??Fa(),o=n??wa(e,i),s=r??Ma(e,i);return{surfaceMode:Na(a,o.switch,s.activation),codemode:a,codemodeSwitch:o,codemodeActivation:s}},s;try{s=T(a,`utf8`)}catch{return{...o(),source:`default`}}let c;try{c=JSON.parse(s)}catch(e){return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof c!=`object`||!c||Array.isArray(c))return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a} must contain a JSON object`};let l=c.surfaceMode;if(l===void 0)return{...o(),source:`default`};if(typeof l!=`string`)return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a}: "surfaceMode" must be a string, received ${typeof l}`};if(!X.includes(l))return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a}: "surfaceMode" must be one of ${X.join(` | `)}, received ${JSON.stringify(l)}`};let u=o();return{surfaceMode:l,source:`file`,detected:u.surfaceMode,codemode:u.codemode,codemodeSwitch:u.codemodeSwitch,codemodeActivation:u.codemodeActivation}}function Ra(e,t){let n=D(e,Y);if(typeof t!=`string`||!X.includes(t))return{ok:!1,path:n,error:`surfaceMode must be one of ${X.join(` | `)}`};let r=t,i;try{i=T(n,`utf8`)}catch{i=void 0}let a={};if(i!==void 0){let e;try{e=JSON.parse(i)}catch(e){return{ok:!1,path:n,error:`${n} is not valid JSON (${e instanceof Error?e.message:String(e)}), so it was left alone`}}if(typeof e!=`object`||!e||Array.isArray(e))return{ok:!1,path:n,error:`${n} must contain a JSON object, so it was left alone`};a=e}let o=a.surfaceMode,s=typeof o==`string`?o:void 0;if(s===r)return{ok:!0,path:n,previous:s,changed:!1};try{ne(n,JSON.stringify({...a,surfaceMode:r},null,2)+`
49
- `,`utf8`)}catch(e){return{ok:!1,path:n,error:`could not write ${n} (${e instanceof Error?e.message:String(e)})`}}return{ok:!0,path:n,previous:s,changed:!0}}function za(e){return[...new Set(e)]}function Ba(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 Va(e,t){let n=e=>sa.includes(e);if(t===`all-but-ptc`)return za(e.filter(n));let r=new Set(I);return za(e.filter(e=>n(e)||!r.has(e)))}function Ha(e){let{mode:t,defaultMode:n,active:r,manual:i}=e;return t===`tui`?!n&&!i?{enter:!1,reason:`config-off`}:sa.some(e=>r.includes(e))?!i&&ca.filter(e=>!r.includes(e)).length>0?{enter:!1,reason:`restricted-session`}:{enter:!0,base:za(r),loadout:Va(r,e.hide??`builtins-only`)}:{enter:!1,reason:`tools-unavailable`}:{enter:!1,reason:`not-tui`}}function Ua(e,t){return e.enabled&&e.base!==void 0?e.base:t}function Wa(e,t){return!e.enabled||e.ourLoadout===void 0?!1:!Ba(e.ourLoadout,t)}function Ga(e,t){let n=t.length>0&&t.every(e=>sa.includes(e));return e?.enabled===!0&&n&&e.base!==void 0?{base:e.base,restoreFirst:!0}:{base:t,restoreFirst:!1}}function Ka(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(`
44
+ `;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(Ri);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(O(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(Ii(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+`: `+Li(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(Ii(e))return[];throw e}let n=[];for(let r of t.split(`
45
+ `)){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+`: `+Li(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(ae(e),{recursive:!0});let n=e+`.tmp-`+M();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(Ii(e))return[];throw e}}async#c(e){try{return await this.#t.readFile(e,{encoding:`utf8`}),!0}catch(e){if(Ii(e))return!1;throw e}}#l(){return O(this.#e,`tasks`)}#u(){return O(this.#e,`subscriptions`)}#d(){return O(this.#e,`events`)}#f(e){return O(this.#l(),e+`.json`)}#p(e,t){return O(this.#u(),e+`-`+t+`.json`)}#m(e,t){return O(this.#d(),e+`-`+t+`.jsonl`)}};function Bi(e,t){return new zi(e,t)}const Vi=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Hi=/* @__PURE__ */ new Set([`running`,`stopping`]),Ui=2**53-1,Wi={info:()=>void 0,warn:e=>{console.warn(`[pi-ptc.background] `+e)}};function J(e){return e instanceof Error?e.message:String(e)}function Gi(e){return e===void 0||e.length===0?`<in-memory>`:e}function Ki(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}var qi=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()}},Ji=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)}},Yi=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)}},Xi=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]}},Zi=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??Wi,this.#r=e.owner??{pid:process.pid,bootMs:this.clock()},this.#i=e.isPidAlive??Xe,this.#t=e.createStorage??(e=>e===void 0||e.length===0?new nt:Bi(e)),this.#n=e.createOutputStorage??(e=>e===void 0||e.length===0?new Gr:new qr(e));let t=(e.createInitialStorage??(()=>new nt))(),n=$e(t,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),r=new Pi(t,{now:this.clock,logger:this.#e});this.registry=new qi(n),this.outputStorage=new Ji(new Gr),this.pipeline=new Yi(r),this.lifecycle=new Xi((e.createLifecycle??(()=>new Fe({logger:this.#e})))()),this.slots=new it(e.concurrency??I.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||Vi.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 `+Gi(e)+` is unavailable: `+J(n),t),[]}let i=$e(n,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),a=new Pi(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:Ui})}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:Ui})}catch(e){this.#e.warn(`shutdown: could not list tasks: `+J(e)),t=[]}let n=[];for(let r of t)if(Hi.has(r.status)&&Ye(r,this.#r))try{let t=await this.registry.transition({kind:`reconcile-lost`,taskId:r.id,reason:e},{clock:this.clock,callerId:Ki(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=ft(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 Qi(e={}){return new Zi(e)}const $i=/* @__PURE__ */ new Set([`succeeded`,`failed`,`lost`]);function ea(e){return $i.has(e.status)}function ta(e,t){if(e.length===0)return``;let n=e.map(ra).join(`
46
+ `);return`${`<bg-task-notifications batch-id="${Y(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function na(e,t=102400){let n=[],r=[],i=0,a=t-aa;for(let t of e){let e=ia(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 ra(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(`
47
+ `)}function Y(e){return e.replaceAll(`&`,`&amp;`).replaceAll(`<`,`&lt;`).replaceAll(`"`,`&quot;`).replaceAll(` `,`&#9;`).replaceAll(`
48
+ `,`&#10;`).replaceAll(`\r`,`&#13;`)}function ia(e){return Buffer.byteLength(ra(e),`utf8`)}const aa=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`],sa=[`read`,`bash`,`edit`,`write`],ca=`ptc-mode`,la=`ptc-mode`,ua=`ptc.json`,da=`builtins-only`;function fa(){return{enabled:!1,base:void 0,ourLoadout:void 0}}function pa(e){let t=O(e,ua),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}`}}const X=[`off`,`subagents`,`full`],ma=`full`,Z=`builtin:codemode`;function Q(e){return e.split(j).join(`/`)}function ha(e){return Q(e.startsWith(`./`)||e.startsWith(`.\\`)?e.slice(2):e)}function ga(e,t,n){let r=Q(k(n,e)),i=ie(e),a=Q(e);return t.some(e=>{let t=Q(e);return be(r,t)||be(i,t)||be(a,t)})}function _a(e,t,n){if(t.length===0)return!1;let r=Q(k(n,e)),i=Q(e);return t.some(e=>{let t=ha(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 ya(e,t){if(!Array.isArray(e))return;let n;for(let{sign:r,target:i}of va(e)){let e=r!==`-`&&r!==`!`;(r===`+`||r===`-`?_a(Z,[i],t):ga(Z,[i],t))&&(n=e?`enabled`:`disabled`)}return n}function ba(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 ga(Z,i,t)&&(s=`disabled`),_a(Z,a,t)&&(s=`enabled`),_a(Z,o,t)&&(s=`disabled`),s}function xa(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 Sa(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 Ca(e,t,n,r={project:process.cwd(),user:process.cwd()}){let i=e.slice(1);if(xa(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=ya(a,r.project);if(o!==void 0)return{switch:o,source:`project`};let s=n?.extensions,c=ba(s,r.user);return c===void 0?{switch:`absent`,source:`default`}:{switch:c,source:`user`}}function wa(e,t,n=process.argv){let r=Sa(O(t,`.pi`,`settings.json`)),i=Sa(O(e,`settings.json`)),a=Ca(n,r.value,i.value,{project:O(t,`.pi`),user:e}),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}const Ta=[`read`,`bash`,`edit`,`write`];function Ea(e){return typeof e==`string`&&(e.startsWith(`+`)||e.startsWith(`-`))}function Da(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function Oa(e,t){return t===void 0?e:!Array.isArray(e)||!Array.isArray(t)||!t.every(Ea)?t:[...e,...t]}function ka(e){let t=e.filter(e=>!Ea(e)),n=t.length>0||e.length===0?t:[...Ta];for(let t of e){if(!Ea(t))continue;let e=t.slice(1),r=n.indexOf(e);t.startsWith(`+`)&&r===-1&&e?n.push(e):t.startsWith(`-`)&&r!==-1&&n.splice(r,1)}return n}function Aa(e){for(let t=0;t<e.length;t+=1){if(e[t]!==`--tools`&&e[t]!==`-t`)continue;let n=e[t+1];return n===void 0?void 0:n.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}}function ja(e,t,n){let r=Aa(e.slice(1));if(r!==void 0)return{activation:r.includes(`codemode`)?`active`:`inactive`,source:`cli`};let i=t?.defaultTools,a=n?.defaultTools,o=Oa(a,i);return o===void 0?{activation:`inactive`,source:`default`}:{activation:ka(Da(o)).includes(`codemode`)?`active`:`inactive`,source:i===void 0?`user`:`project`}}function Ma(e,t,n=process.argv){let r=Sa(O(t,`.pi`,`settings.json`)),i=Sa(O(e,`settings.json`)),a=Ga(ja(n,r.value,i.value),Wa(e,t)),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}const Na=[`codemode`,`deferred`,`direct`,`hidden`],Pa={"codemode-deferred":`codemode`},Fa=/^[A-Za-z0-9_-]+$/;function Ia(e){return typeof e==`string`?Pa[e]??e:e}function La(e){return typeof e==`string`&&Na.includes(e)}function $(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ra(e){return $(e)&&Object.values(e).every(e=>typeof e==`string`)}function za(e){return URL.canParse(e)?/^https?:$/.test(new URL(e).protocol):!1}function Ba(e,t){if(!Fa.test(e)||!$(t))return;let n=Ia(t.exposure),r=$(t.toolExposure)?Object.fromEntries(Object.entries(t.toolExposure).map(([e,t])=>[e,Ia(t)])):t.toolExposure;if(n!==void 0&&!La(n)||r!==void 0&&(!$(r)||!Object.values(r).every(e=>La(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!za(t.url)||t.headers!==void 0&&!Ra(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&&!Ra(t.env)||t.cwd!==void 0&&typeof t.cwd!=`string`?void 0:i}function Va(e,t){e.error=e.error===void 0?t:`${e.error}; ${t}`}function Ha(e,t,n,r,i){if(t===void 0){n!==void 0&&Va(i,n);return}let a;try{a=JSON.parse(t)}catch(t){Va(i,`${e} is not valid JSON (${t instanceof Error?t.message:String(t)})`);return}if(!$(a)||a.mcpServers!==void 0&&!$(a.mcpServers)){Va(i,`${e} must contain a JSON object with an "mcpServers" object`);return}typeof a.autoEnableCodemode==`boolean`?i.autoEnableCodemode=a.autoEnableCodemode:a.autoEnableCodemode!==void 0&&Va(i,`${e}: autoEnableCodemode must be a boolean`);for(let[e,t]of Object.entries(a.mcpServers??{})){let n=Ba(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 Ua(e,t){let n={autoEnableCodemode:void 0,servers:/* @__PURE__ */ new Map,error:void 0};Ha(e.path,e.raw,e.readError,`global`,n),Ha(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 Wa(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 Ua(n(O(e,`mcp.json`)),n(O(t,`.pi`,`mcp.json`)))}function Ga(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 Ka(e,t,n){return!e.present||t===`disabled`||n!==`active`?ma:`subagents`}function qa(e,t){return e!==void 0&&e!==`off`&&e!==t}function Ja(e=process.argv){let t=e[1];if(t===void 0||t===``)return{present:!1,how:`no-entry`};let n;try{n=E(t)}catch{return{present:!1,how:`unresolvable-entry`}}let r=ae(n);for(let e of Ya){let t=O(r,...e);try{if(ee(t).isDirectory())return{present:!0,how:`found`}}catch{}}return{present:!1,how:`not-found`}}const Ya=[[`..`,`extensions`,`codemode`],[`..`,`..`,`extensions`,`codemode`],[`extensions`,`codemode`]];function Xa(e,t,n,r,i=process.cwd()){let a=O(e,ua),o=()=>{let a=t??Ja(),o=n??wa(e,i),s=r??Ma(e,i);return{surfaceMode:Ka(a,o.switch,s.activation),codemode:a,codemodeSwitch:o,codemodeActivation:s}},s;try{s=T(a,`utf8`)}catch{return{...o(),source:`default`}}let c;try{c=JSON.parse(s)}catch(e){return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof c!=`object`||!c||Array.isArray(c))return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a} must contain a JSON object`};let l=c.surfaceMode;if(l===void 0)return{...o(),source:`default`};if(typeof l!=`string`)return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a}: "surfaceMode" must be a string, received ${typeof l}`};if(!X.includes(l))return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a}: "surfaceMode" must be one of ${X.join(` | `)}, received ${JSON.stringify(l)}`};let u=o();return{surfaceMode:l,source:`file`,detected:u.surfaceMode,codemode:u.codemode,codemodeSwitch:u.codemodeSwitch,codemodeActivation:u.codemodeActivation}}function Za(e,t){let n=O(e,ua);if(typeof t!=`string`||!X.includes(t))return{ok:!1,path:n,error:`surfaceMode must be one of ${X.join(` | `)}`};let r=t,i;try{i=T(n,`utf8`)}catch{i=void 0}let a={};if(i!==void 0){let e;try{e=JSON.parse(i)}catch(e){return{ok:!1,path:n,error:`${n} is not valid JSON (${e instanceof Error?e.message:String(e)}), so it was left alone`}}if(typeof e!=`object`||!e||Array.isArray(e))return{ok:!1,path:n,error:`${n} must contain a JSON object, so it was left alone`};a=e}let o=a.surfaceMode,s=typeof o==`string`?o:void 0;if(s===r)return{ok:!0,path:n,previous:s,changed:!1};try{te(n,JSON.stringify({...a,surfaceMode:r},null,2)+`
49
+ `,`utf8`)}catch(e){return{ok:!1,path:n,error:`could not write ${n} (${e instanceof Error?e.message:String(e)})`}}return{ok:!0,path:n,previous:s,changed:!0}}function Qa(e){return[...new Set(e)]}function $a(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 eo(e,t){let n=e=>oa.includes(e);if(t===`all-but-ptc`)return Qa(e.filter(n));let r=new Set(L);return Qa(e.filter(e=>n(e)||!r.has(e)))}function to(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&&sa.filter(e=>!r.includes(e)).length>0?{enter:!1,reason:`restricted-session`}:{enter:!0,base:Qa(r),loadout:eo(r,e.hide??`builtins-only`)}:{enter:!1,reason:`tools-unavailable`}:{enter:!1,reason:`not-tui`}}function no(e,t){return e.enabled&&e.base!==void 0?e.base:t}function ro(e,t){return!e.enabled||e.ourLoadout===void 0?!1:!$a(e.ourLoadout,t)}function io(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 ao(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(`
50
50
  `);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(`
51
- `)}const qa=[`read`,`bash`],Ja=`Use the read tool to load a skill's file when the task matches its description.`,Ya=`Use tools.read({ path }) inside a ptc_run_code program to load a skill's file when the task matches its description.`;function Xa(e){return!qa.some(t=>e.includes(t))}function Za(e,t=v){let n=t([...e],`read`).trim();return n.length===0?``:n.includes(Ja)?n.replace(Ja,Ya):`${Ya}\n\n${n}`}const Qa=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 $a(e){let t=e.taskId;return typeof t==`string`?t:void 0}function eo(e){return g({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.`].join(`
52
- `),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:en,outputSchema:Qa,async execute(t,n){let r=await Zt(n,{callId:0,cwd:n.cwd??e.cwd,depth:e.depth,maxDispatchDepth:e.maxDispatchDepth,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId}},e.getDispatchDeps?.()??{}),i=$a(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:[Er(o,r.reportChannel),r.text].filter(e=>e.length>0).join(`
51
+ `)}const oo=[`read`,`bash`],so=`Use the read tool to load a skill's file when the task matches its description.`,co=`Use tools.read({ path }) inside a ptc_run_code program to load a skill's file when the task matches its description.`;function lo(e){return!oo.some(t=>e.includes(t))}function uo(e,t=v){let n=t([...e],`read`).trim();return n.length===0?``:n.includes(so)?n.replace(so,co):`${co}\n\n${n}`}const fo=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 po(e){let t=e.taskId;return typeof t==`string`?t:void 0}function mo(e){return g({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.`].join(`
52
+ `),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:$t,outputSchema:fo,async execute(t,n){let r=await Xt(n,{callId:0,cwd:n.cwd??e.cwd,depth:e.depth,maxDispatchDepth:e.maxDispatchDepth,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId}},e.getDispatchDeps?.()??{}),i=po(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:[Tr(o,r.reportChannel),r.text].filter(e=>e.length>0).join(`
53
53
 
54
- `)}],details:a,structuredContent:s}}})}function to(e){return e.length<=200?e:`…`+e.slice(-199)}const no=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.`}))}),ro=[`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(`
55
- `);function io(e){return g({name:Le,label:`Child Report`,description:ro,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:no,outputSchema:no,defaultActive:e,renderCall(e,t){let n=e,r=typeof n?.summary==`string`?n.summary:``;return new K([{left:t.fg(`toolTitle`,t.bold(`Child report`))+(r===``?``:` `+t.fg(`dim`,to(r)))}])},renderResult(){return new K([{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 $=da;function ao(e,t){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: ${H(e).join(`, `)||`(none)`}.`,`Run /ptc off to restore the normal tool set.`].join(`
56
- `)}function oo(e,t={}){let n=fa(),r=t.surfaceMode===void 0?La(y(),t.codemode,t.codemodeSwitch):{surfaceMode:t.surfaceMode,source:`file`},i=!1,a=new Ni,o=()=>Ua(n,e.getActiveTools()),s=In(),c=Ln();if(r.surfaceMode===`off`)return;let l=t.backgroundRuntime??$i({concurrency:Be({}).dispatchConcurrency}),u=!1,d=e=>{console.warn(`[pi-ptc.background] `+e)},f=t=>{if(t.length!==0){if(u){e.sendMessage({customType:`bg-task-notification`,content:t,display:!1},{deliverAs:`steer`});return}e.sendUserMessage(t)}},p=async e=>{let{items:t,acks:n}=await l.drainNotifications(e),r=t.filter(e=>ta(e.record));for(let e of ra(r))f(na(e,{batchId:Oe(),deliveredAtMs:l.clock()}));await l.acknowledgeNotifications(n)},m=async()=>{let e=await l.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]},h=async()=>{for(let e of await m())await p(e)},g=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 p(e)};l.pipeline.onIdleWake(e=>{p(e).catch(e=>{d(`notification delivery failed: `+(e instanceof Error?e.message:String(e)))})}),r.surfaceMode===`full`&&(e.registerTool(zr({getBindingSourceNames:o,getPool:()=>a.get(`run_code`),depth:s,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps})),e.registerTool(Gr({getBindingSourceNames:o,getPool:()=>a.get(`workflow`),depth:s,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps}))),r.surfaceMode===`subagents`&&e.registerTool(eo({cwd:process.cwd(),depth:s,maxDispatchDepth:F.maxDispatchDepth,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps})),e.registerTool(wi(l.registry)),e.registerTool(ki(l.registry,l.outputStorage)),e.registerTool(Mi(l.registry,l.lifecycle,{clock:l.clock})),e.registerTool(io(s>0)),e.on(`turn_start`,async()=>{u=!0}),e.on(`agent_settled`,async()=>{u=!1;try{await h()}catch(e){d(`agent_settled delivery failed: `+(e instanceof Error?e.message:String(e)))}}),e.on(`turn_end`,async()=>{let e=a;a=new Ni,await e.drain()});let _=e=>{e.ui.setStatus(ua,n.enabled?e.ui.theme.fg(`accent`,`PTC`):void 0)},v=(t,r,a,o)=>{n.enabled=!0,n.base=t,n.ourLoadout=r,e.setActiveTools([...r]),i=!0,e.appendEntry(la,{enabled:!0,base:[...t]}),_(a),a.ui.notify(o,`info`)},b=(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}),_(t),r.announce&&t.ui.notify(`PTC mode off — built-in tools are directly callable again.`,`info`)},x=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}}}},S=async(e,t)=>{let r=y();if(e===``){let e=La(r),n=e.detected===void 0||e.detected===e.surfaceMode?``:` (detection would say `+JSON.stringify(e.detected)+`)`;t.ui.notify(`Extension surface: `+JSON.stringify(e.surfaceMode)+`, from `+e.source+n+`. Set it with /ptc surface `+X.join(`|`)+`; the change needs a reload, which this command performs.`,`info`);return}let i=Ra(r,e);if(!i.ok){t.ui.notify(`pi-ptc-subagents: `+i.error+`. Nothing was changed.`,`warning`);return}if(!i.changed){t.ui.notify(`The surface is already `+JSON.stringify(e)+` — nothing written, nothing reloaded.`,`info`);return}let a=[`Surface `+(i.previous===void 0?`(unset, so detected)`:JSON.stringify(i.previous))+` → `+JSON.stringify(e)+` in `+i.path+`. Reloading so it takes effect now.`];n.enabled&&e!==`full`&&a.push(`PTC mode was ON and cannot survive this surface — run /ptc on afterwards.`),e===`subagents`&&a.push(`subagents hands orchestration to pi's codemode, so it needs codemode in this session's tool list; if it is not there the startup warning will say so.`),t.ui.notify(a.join(`
57
- `),`info`),await t.reload()};e.registerCommand(`ptc`,{description:`Show or toggle PTC mode, or set the extension surface (/ptc surface off|subagents|full)`,handler:async(t,r)=>{let i=t.trim().toLowerCase();if(i===`surface`||i.startsWith(`surface `)){await S(i.slice(7).trim(),r);return}if(i===`off`){if(!n.enabled){r.ui.notify(`PTC mode is already off.`,`info`);return}b(r,{announce:!0,customType:la});return}if(i!==`on`){r.ui.notify(n.enabled?`PTC mode is ON — run /ptc off to restore built-in tools.\nBindings: ${H(n.base).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=Ha({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}v(a.base,a.loadout,r,ao(a.base,$))}}),e.on(`session_start`,async(t,n)=>{u=!1;let i=await l.bindSession(n.sessionManager?.getSessionDir?.(),e=>n.ui.notify(e,`warning`));try{await g(i)}catch(e){d(`startup reconcile delivery failed: `+(e instanceof Error?e.message:String(e)))}let a=pa(y());a.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${a.error}`,`warning`),r.error!==void 0&&r.error!==a.error&&n.ui.notify(`pi-ptc-subagents: ${r.error}`,`warning`);let o=r.codemode;if(o!==void 0&&!o.present&&n.ui.notify(`pi-ptc-subagents: no surfaceMode is set, and the codemode probe reported `+o.how+`, so the surface defaults to full. That is the safe direction, not an error. If this pi really does ship pi's own codemode, set "surfaceMode" in ptc.json -- an explicit key always wins over detection.`,`info`),r.codemodeSwitch?.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${r.codemodeSwitch.error}`,`warning`),r.source===`file`&&r.detected!==void 0&&Pa(r.surfaceMode,r.detected)){let e=r.codemodeSwitch;n.ui.notify(`pi-ptc-subagents: surfaceMode is pinned to `+JSON.stringify(r.surfaceMode)+`, but this pi resolves to `+JSON.stringify(r.detected)+(e===void 0?``:` (pi's codemode is on disk and its switch is `+e.switch+`)`)+`. The pinned value is in force. Change it in ptc.json if that is not what you meant.`,`info`)}if(o!==void 0&&r.source!==`file`){let t=e.getAllTools().some(e=>e.name===`codemode`);!o.present&&t&&n.ui.notify(`pi-ptc-subagents: this session registers pi's codemode, but the probe did not find it (`+o.how+`), so the surface defaulted to full, and your model is being offered two orchestration tools. Set an explicit "surfaceMode" in ptc.json to pick one.`,`warning`),o.present&&!t&&n.ui.notify(`pi-ptc-subagents: the codemode probe found pi's codemode on disk, but this session does not register it (--no-extensions or --exclude-tools codemode), so the surface is `+JSON.stringify(r.surfaceMode)+(r.surfaceMode===`subagents`?` with no orchestrator. Set `+JSON.stringify(`surfaceMode`)+` to `+JSON.stringify(ma)+` in ptc.json to use ptc_run_code instead.`:`.`),`warning`)}r.surfaceMode===`subagents`&&!e.getActiveTools().includes(`codemode`)&&n.ui.notify(`pi-ptc-subagents: surfaceMode 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 set surfaceMode to "full" to use ptc_run_code instead.`,`warning`);let s=x(n),{base:c,restoreFirst:f}=Ga(s,e.getActiveTools());f&&e.setActiveTools([...c]);let p=Ha({mode:n.mode,defaultMode:a.defaultMode,active:c,manual:!1,hide:$}),m=s?.enabled??p.enter;if(p.enter&&m){v(c,p.loadout,n,ao(c,$));return}_(n),!p.enter&&p.reason!==`not-tui`&&s===void 0&&p.reason===`restricted-session`&&n.ui.notify(`PTC mode skipped: this session was launched with an explicit tool restriction.`,`info`)}),e.on(`session_shutdown`,async()=>{u=!1;try{await l.shutdown(`session_ended_while_running`)}catch(e){d(`session shutdown failed: `+(e instanceof Error?e.message:String(e)))}});let C=!1,w=(e,t)=>{if(e===void 0)return;if(!n.enabled||!t){C&&=(delete e.sections.skills,!1);return}let r=Za(e.skills);r.length!==0&&(e.sections.skills=r,C=!0)};e.on(`before_agent_start`,async(t,r)=>{let a=t.systemPromptOptions;if(w(a,Xa(e.getActiveTools())),n.enabled){if(Wa(n,e.getActiveTools())){b(r,{announce:!1,customType:la}),w(a,Xa(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:Ka(H(n.base),$),display:!1}}}})}export{I as BUILTIN_BINDING_NAMES,Qt as DEFAULT_BINDING_NAMES,F as DEFAULT_CONFIG,da as DEFAULT_HIDE_STRATEGY,o as HOST_FRAME_KIND,wn as MAX_LINE_CHARS,ca as MODE_REQUIRED_TOOL_NAMES,n as PTC_ERROR_KIND,i as PTC_LOG_LEVEL,Y as PTC_MODE_CONFIG_FILE,la as PTC_MODE_ENTRY_TYPE,ua as PTC_MODE_STATUS_KEY,sa as PTC_MODE_TOOL_NAMES,Ya as PTC_SKILL_LOAD_INSTRUCTION,qa as SKILL_READING_TOOL_NAMES,X as SURFACE_MODES,Ni as TurnPools,Re as WORKER_ENV_ALLOW_LIST,t as WORKER_FRAME_KIND,sn as WorkerPool,Ua as bindingSource,Ka as buildModeInstruction,Za as buildPtcSkillsSection,rn as createBuiltinBindings,ze as createWorkerEnv,Ha as decideModeEntry,oo as default,Wa as detectExternalLoadoutChange,Ve as effectiveTimeoutMs,fa as initialModeState,Va as modeLoadout,Fa as probeCodemodePresence,wa as readCodemodeSwitch,pa as readDefaultModeConfig,La as readSurfaceModeConfig,Fn as renderModelValue,Ga as resolveBaseOnStart,ja as resolveCodemodeActivation,Ca as resolveCodemodeSwitch,Be as resolveConfig,gn as runPtcProgram,Ba as sameToolSet,V as sanitizeText,Ra as setSurfaceMode,Xa as skillsSectionDropped,En as stripAnsi,Pa as surfaceModeConflict};
54
+ `)}],details:a,structuredContent:s}}})}function ho(e){return e.length<=200?e:`…`+e.slice(-199)}const go=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.`}))}),_o=[`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(`
55
+ `);function vo(e){return g({name:Ie,label:`Child Report`,description:_o,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:go,outputSchema:go,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`,ho(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 yo=da;function bo(e,t){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: ${U(e).join(`, `)||`(none)`}.`,`Run /ptc off to restore the normal tool set.`].join(`
56
+ `)}function xo(e,t={}){let n=fa(),r=t.surfaceMode===void 0?Xa(y(),t.codemode,t.codemodeSwitch):{surfaceMode:t.surfaceMode,source:`file`},i=!1,a=new Mi,o=()=>no(n,e.getActiveTools()),s=Fn(),c=In();if(r.surfaceMode===`off`)return;let l=t.backgroundRuntime??Qi({concurrency:ze({}).dispatchConcurrency}),u=!1,d=e=>{console.warn(`[pi-ptc.background] `+e)},f=t=>{if(t.length!==0){if(u){e.sendMessage({customType:`bg-task-notification`,content:t,display:!1},{deliverAs:`steer`});return}e.sendUserMessage(t)}},p=async e=>{let{items:t,acks:n}=await l.drainNotifications(e),r=t.filter(e=>ea(e.record));for(let e of na(r))f(ta(e,{batchId:De(),deliveredAtMs:l.clock()}));await l.acknowledgeNotifications(n)},m=async()=>{let e=await l.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]},h=async()=>{for(let e of await m())await p(e)},g=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 p(e)};l.pipeline.onIdleWake(e=>{p(e).catch(e=>{d(`notification delivery failed: `+(e instanceof Error?e.message:String(e)))})}),r.surfaceMode===`full`&&(e.registerTool(Rr({getBindingSourceNames:o,getPool:()=>a.get(`run_code`),depth:s,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps})),e.registerTool(Wr({getBindingSourceNames:o,getPool:()=>a.get(`workflow`),depth:s,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps}))),r.surfaceMode===`subagents`&&e.registerTool(mo({cwd:process.cwd(),depth:s,maxDispatchDepth:I.maxDispatchDepth,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps})),e.registerTool(Ci(l.registry)),e.registerTool(Oi(l.registry,l.outputStorage)),e.registerTool(ji(l.registry,l.lifecycle,{clock:l.clock})),e.registerTool(vo(s>0));let _=!1,v=t=>{_||r.source!==`file`&&r.codemodeActivation?.activation===`inactive`&&e.getActiveTools().includes(`codemode`)&&(_=!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). Set an explicit "surfaceMode" in ptc.json to pick one.`,`warning`))};e.on(`turn_start`,async(e,t)=>{u=!0,v(t)}),e.on(`agent_settled`,async()=>{u=!1;try{await h()}catch(e){d(`agent_settled delivery failed: `+(e instanceof Error?e.message:String(e)))}}),e.on(`turn_end`,async()=>{let e=a;a=new Mi,await e.drain()});let b=e=>{e.ui.setStatus(la,n.enabled?e.ui.theme.fg(`accent`,`PTC`):void 0)},x=(t,r,a,o)=>{n.enabled=!0,n.base=t,n.ourLoadout=r,e.setActiveTools([...r]),i=!0,e.appendEntry(ca,{enabled:!0,base:[...t]}),b(a),a.ui.notify(o,`info`)},S=(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}),b(t),r.announce&&t.ui.notify(`PTC mode off — built-in tools are directly callable again.`,`info`)},C=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}}}},w=async(e,t)=>{let r=y();if(e===``){let e=Xa(r),n=e.detected===void 0||e.detected===e.surfaceMode?``:` (detection would say `+JSON.stringify(e.detected)+`)`;t.ui.notify(`Extension surface: `+JSON.stringify(e.surfaceMode)+`, from `+e.source+n+`. Set it with /ptc surface `+X.join(`|`)+`; the change needs a reload, which this command performs.`,`info`);return}let i=Za(r,e);if(!i.ok){t.ui.notify(`pi-ptc-subagents: `+i.error+`. Nothing was changed.`,`warning`);return}if(!i.changed){t.ui.notify(`The surface is already `+JSON.stringify(e)+` — nothing written, nothing reloaded.`,`info`);return}let a=[`Surface `+(i.previous===void 0?`(unset, so detected)`:JSON.stringify(i.previous))+` → `+JSON.stringify(e)+` in `+i.path+`. Reloading so it takes effect now.`];n.enabled&&e!==`full`&&a.push(`PTC mode was ON and cannot survive this surface — run /ptc on afterwards.`),e===`subagents`&&a.push(`subagents hands orchestration to pi's codemode, so it needs codemode in this session's tool list; if it is not there the startup warning will say so.`),t.ui.notify(a.join(`
57
+ `),`info`),await t.reload()};e.registerCommand(`ptc`,{description:`Show or toggle PTC mode, or set the extension surface (/ptc surface off|subagents|full)`,handler:async(t,r)=>{let i=t.trim().toLowerCase();if(i===`surface`||i.startsWith(`surface `)){await w(i.slice(7).trim(),r);return}if(i===`off`){if(!n.enabled){r.ui.notify(`PTC mode is already off.`,`info`);return}S(r,{announce:!0,customType:ca});return}if(i!==`on`){r.ui.notify(n.enabled?`PTC mode is ON — run /ptc off to restore built-in tools.\nBindings: ${U(n.base).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=to({mode:r.mode,defaultMode:!0,active:e.getActiveTools(),manual:!0,hide:yo});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}x(a.base,a.loadout,r,bo(a.base,yo))}}),e.on(`session_start`,async(t,n)=>{u=!1;let i=await l.bindSession(n.sessionManager?.getSessionDir?.(),e=>n.ui.notify(e,`warning`));try{await g(i)}catch(e){d(`startup reconcile delivery failed: `+(e instanceof Error?e.message:String(e)))}let a=pa(y());a.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${a.error}`,`warning`),r.error!==void 0&&r.error!==a.error&&n.ui.notify(`pi-ptc-subagents: ${r.error}`,`warning`);let o=r.codemode;if(o!==void 0&&!o.present&&n.ui.notify(`pi-ptc-subagents: no surfaceMode is set, and the codemode probe reported `+o.how+`, so the surface defaults to full. That is the safe direction, not an error. If this pi really does ship pi's own codemode, set "surfaceMode" in ptc.json -- an explicit key always wins over detection.`,`info`),r.codemodeSwitch?.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${r.codemodeSwitch.error}`,`warning`),r.codemodeActivation?.mcpError!==void 0&&n.ui.notify(`pi-ptc-subagents: ${r.codemodeActivation.mcpError}`,`warning`),r.source===`file`&&r.detected!==void 0&&qa(r.surfaceMode,r.detected)){let e=r.codemodeSwitch;n.ui.notify(`pi-ptc-subagents: surfaceMode is pinned to `+JSON.stringify(r.surfaceMode)+`, but this pi resolves to `+JSON.stringify(r.detected)+(e===void 0?``:` (pi's codemode is on disk and its switch is `+e.switch+`)`)+`. The pinned value is in force. Change it in ptc.json if that is not what you meant.`,`info`)}if(o!==void 0&&r.source!==`file`){let t=e.getAllTools().some(e=>e.name===`codemode`);!o.present&&t&&n.ui.notify(`pi-ptc-subagents: this session registers pi's codemode, but the probe did not find it (`+o.how+`), so the surface defaulted to full, and your model is being offered two orchestration tools. Set an explicit "surfaceMode" in ptc.json to pick one.`,`warning`),o.present&&!t&&n.ui.notify(`pi-ptc-subagents: the codemode probe found pi's codemode on disk, but this session does not register it (--no-extensions or --exclude-tools codemode), so the surface is `+JSON.stringify(r.surfaceMode)+(r.surfaceMode===`subagents`?` with no orchestrator. Set `+JSON.stringify(`surfaceMode`)+` to `+JSON.stringify(ma)+` in ptc.json to use ptc_run_code instead.`:`.`),`warning`)}r.surfaceMode===`subagents`&&!e.getActiveTools().includes(`codemode`)&&n.ui.notify(`pi-ptc-subagents: surfaceMode 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 set surfaceMode to "full" to use ptc_run_code instead.`,`warning`),v(n);let s=C(n),{base:c,restoreFirst:f}=io(s,e.getActiveTools());f&&e.setActiveTools([...c]);let p=to({mode:n.mode,defaultMode:a.defaultMode,active:c,manual:!1,hide:yo}),m=s?.enabled??p.enter;if(p.enter&&m){x(c,p.loadout,n,bo(c,yo));return}b(n),!p.enter&&p.reason!==`not-tui`&&s===void 0&&p.reason===`restricted-session`&&n.ui.notify(`PTC mode skipped: this session was launched with an explicit tool restriction.`,`info`)}),e.on(`session_shutdown`,async()=>{u=!1;try{await l.shutdown(`session_ended_while_running`)}catch(e){d(`session shutdown failed: `+(e instanceof Error?e.message:String(e)))}});let T=!1,E=(e,t)=>{if(e===void 0)return;if(!n.enabled||!t){T&&=(delete e.sections.skills,!1);return}let r=uo(e.skills);r.length!==0&&(e.sections.skills=r,T=!0)};e.on(`before_agent_start`,async(t,r)=>{let a=t.systemPromptOptions;if(E(a,lo(e.getActiveTools())),n.enabled){if(ro(n,e.getActiveTools())){S(r,{announce:!1,customType:ca}),E(a,lo(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:ao(U(n.base),yo),display:!1}}}})}export{L as BUILTIN_BINDING_NAMES,Zt as DEFAULT_BINDING_NAMES,I as DEFAULT_CONFIG,da as DEFAULT_HIDE_STRATEGY,o as HOST_FRAME_KIND,Cn as MAX_LINE_CHARS,sa as MODE_REQUIRED_TOOL_NAMES,n as PTC_ERROR_KIND,i as PTC_LOG_LEVEL,ua as PTC_MODE_CONFIG_FILE,ca as PTC_MODE_ENTRY_TYPE,la as PTC_MODE_STATUS_KEY,oa as PTC_MODE_TOOL_NAMES,co as PTC_SKILL_LOAD_INSTRUCTION,oo as SKILL_READING_TOOL_NAMES,X as SURFACE_MODES,Mi as TurnPools,Le as WORKER_ENV_ALLOW_LIST,t as WORKER_FRAME_KIND,on as WorkerPool,no as bindingSource,ao as buildModeInstruction,uo as buildPtcSkillsSection,nn as createBuiltinBindings,Re as createWorkerEnv,to as decideModeEntry,xo as default,ro as detectExternalLoadoutChange,Be as effectiveTimeoutMs,fa as initialModeState,eo as modeLoadout,Ja as probeCodemodePresence,wa as readCodemodeSwitch,pa as readDefaultModeConfig,Xa as readSurfaceModeConfig,Pn as renderModelValue,io as resolveBaseOnStart,ja as resolveCodemodeActivation,Ca as resolveCodemodeSwitch,ze as resolveConfig,hn as runPtcProgram,$a as sameToolSet,H as sanitizeText,Za as setSurfaceMode,lo as skillsSectionDropped,Tn as stripAnsi,qa as surfaceModeConflict};
58
58
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ptc-subagents",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "DSH PTC mode (ptc_run_code + ptc_workflow) for pi",
5
5
  "keywords": [
6
6
  "pi",