pi-ptc-subagents 1.0.0 → 1.1.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 +35 -0
- package/README.md +1 -1
- package/dist/index.d.ts +21 -4
- package/dist/index.js +36 -36
- package/dist/worker.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,41 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.0] - 2026-09-29
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Background dispatch children no longer reap their parent's tasks (field
|
|
13
|
+
report, 2026-09-29).** Background children share the session's task storage
|
|
14
|
+
via `--session-dir`; a child's startup reconcile and exit sweep used to be
|
|
15
|
+
directory-wide, so a dispatch child — or any `pi` process started in the same
|
|
16
|
+
directory — flipped every running task to `lost`. Task records now carry an
|
|
17
|
+
owner identity (`ownerPid` / `ownerBootMs`) and reaping is owner-scoped
|
|
18
|
+
(ADR-0023); `lost_on_session_restart` now means the owner process died
|
|
19
|
+
before the task finished, or the record predates ownership (pre-upgrade
|
|
20
|
+
ownerless rows, which any process binding the directory reaps).
|
|
21
|
+
- **`pi.dispatch` refusals are actionable.** A missing `agent` argument is
|
|
22
|
+
reported distinctly (`agent is required (there is no default agent)`) and
|
|
23
|
+
both the missing- and unknown-agent results list the agents registered under
|
|
24
|
+
the effective scope plus the two lookup paths and the agent-file shape. The
|
|
25
|
+
binding now runs its arguments through pi's own `validateToolArguments`
|
|
26
|
+
(the same validation the built-in bindings use) and a validation failure
|
|
27
|
+
comes back as a `rejected` DispatchResult instead of reaching the
|
|
28
|
+
subprocess layer.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- **PTC program prompts name the dispatch binding precisely.** The
|
|
33
|
+
`ptc_run_code` / `ptc_workflow` descriptions and the `/ptc` briefing state
|
|
34
|
+
that `pi.dispatch` is always bound under its literal dot name (call it as
|
|
35
|
+
`tools["pi.dispatch"](...)`; `tools.pi.dispatch` does not exist), and each
|
|
36
|
+
run exposes its actual bound names on the new `ptcBindings` global so
|
|
37
|
+
programs never guess the binding surface.
|
|
38
|
+
- **Docs**: `ptc_run_code`'s `timeoutMs` description and `docs/usage/bgdispatch.md`
|
|
39
|
+
now state that a run timeout terminates in-flight foreground dispatches, and
|
|
40
|
+
the guide gains prerequisites (no default agent) and an output-compactness
|
|
41
|
+
convention (page via `ptc_task_output` instead of truncating).
|
|
42
|
+
|
|
8
43
|
## [1.0.0] - 2026-09-24
|
|
9
44
|
|
|
10
45
|
### Added
|
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ const handle = await tools["pi.dispatch"]({
|
|
|
105
105
|
|
|
106
106
|
(The binding's name is `pi.dispatch`; a program reaches it as `tools["pi.dispatch"]`.)
|
|
107
107
|
|
|
108
|
-
A detached pump drives the task's lifecycle (`running` -> `succeeded` / `failed` / `canceled` / `lost`), and the model observes it with three always-on tools — they are not part of the PTC-mode loadout, so `/ptc off` (which only blocks new spawns) does not remove them:
|
|
108
|
+
A detached pump drives the task's lifecycle (`running` -> `succeeded` / `failed` / `canceled` / `lost`), and the model observes it with three always-on tools — they are not part of the PTC-mode loadout, so `/ptc off` (which only blocks new spawns) does not remove them. A background task is owned by the dispatching pi process (ADR-0023): it survives programs, turns, and `/ptc off`, ends when that session ends or the process dies, and no other pi process in the same directory can reap it (background dispatch children share the session's task storage, so pre-ADR-0023 any same-directory pi process — including a dispatch child itself — could reap every task on startup). Known edges: pre-upgrade ownerless records are still reaped by whichever process binds the directory first; a recycled pid can leave a record `running` after its owner died; and `ptc_task_stop` from another process can write a `stopping` state into your record even though the stop signal itself never crosses the process boundary:
|
|
109
109
|
|
|
110
110
|
- `ptc_task_list({ status?, limit? })` — list this session's tasks, newest first (default limit 100).
|
|
111
111
|
- `ptc_task_output({ taskId, sinceBytes? })` — read a task's captured output, tail-truncated to pi's 50 KB / 2000-line contract (ADR-0015).
|
package/dist/index.d.ts
CHANGED
|
@@ -123,9 +123,12 @@ interface TaskSpawnSource {
|
|
|
123
123
|
callerId: string;
|
|
124
124
|
}
|
|
125
125
|
/**
|
|
126
|
-
* Session-level row tracking the lifecycle of one background child.
|
|
127
|
-
*
|
|
128
|
-
*
|
|
126
|
+
* Session-level row tracking the lifecycle of one background child. 19 ADR-0022 §3 fields (its
|
|
127
|
+
* "21 fields" heading is an authoring miscount) plus two optional ADR-0023 owner-identity
|
|
128
|
+
* fields — 21 today, persisted as-is. Optional fields are absent on
|
|
129
|
+
* records still `running` (e.g. `finishedAt` / `exitCode` / `outputRef` are written at
|
|
130
|
+
* transition time, not at spawn) and `ownerPid` / `ownerBootMs` are absent on pre-upgrade
|
|
131
|
+
* legacy records.
|
|
129
132
|
*/
|
|
130
133
|
interface TaskRecord {
|
|
131
134
|
id: ULID;
|
|
@@ -153,6 +156,16 @@ interface TaskRecord {
|
|
|
153
156
|
parentTaskId?: ULID;
|
|
154
157
|
/** `<sessionDir>/tasks/<id>.pi-*` session file (R1). */
|
|
155
158
|
sessionFile?: string;
|
|
159
|
+
/**
|
|
160
|
+
* ADR-0023 (task ownership): pid of the extension-runtime instance that created this record.
|
|
161
|
+
* Absent on pre-upgrade legacy records. The only writer is the registry's spawn command,
|
|
162
|
+
* stamping its configured owner; reaping is owner-scoped (startup reconcile sweeps a record
|
|
163
|
+
* only when this pid is dead; the shutdown sweep reaps only records that also match
|
|
164
|
+
* `ownerBootMs`).
|
|
165
|
+
*/
|
|
166
|
+
ownerPid?: number;
|
|
167
|
+
/** ADR-0023: wall-clock ms when the owning runtime instance started; pairs with `ownerPid`. */
|
|
168
|
+
ownerBootMs?: number;
|
|
156
169
|
}
|
|
157
170
|
/**
|
|
158
171
|
* Per-subscriber cursor for one TaskRecord (ADR-0022 §5). Cursor is per-subscriber (not per-task)
|
|
@@ -457,7 +470,11 @@ interface BackgroundTaskRuntime {
|
|
|
457
470
|
* where it was so the next drain re-delivers the event.
|
|
458
471
|
*/
|
|
459
472
|
acknowledgeNotifications(acks: readonly NotificationAck[]): Promise<void>;
|
|
460
|
-
/**
|
|
473
|
+
/**
|
|
474
|
+
* Mark every non-terminal task this runtime OWNS lost (given reason) and release resources.
|
|
475
|
+
* ADR-0023: records owned by another runtime instance — e.g. a sibling pi process sharing
|
|
476
|
+
* the session dir — are never reaped here, and their children are never signaled.
|
|
477
|
+
*/
|
|
461
478
|
shutdown(reason: LostReason): Promise<TaskRecord[]>;
|
|
462
479
|
}
|
|
463
480
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
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,writeFileSync as ee}from"node:fs";import*as E from"node:os";import{tmpdir as te}from"node:os";import*as D from"node:path";import{dirname as O,join as k,resolve as A}from"node:path";import{spawn as ne}from"node:child_process";import{randomBytes as re,randomUUID as j}from"node:crypto";import{ok as M}from"node:assert/strict";import{MessageChannel as ie,Worker as N}from"node:worker_threads";import P from"node:diagnostics_channel";import{fileURLToPath as ae,pathToFileURL as F}from"node:url";import{truncateToWidth as I,visibleWidth as L}from"@earendil-works/pi-tui";import{appendFile as oe,mkdir as se,readFile as R,readdir as ce,rename as le,unlink as ue,writeFile as
|
|
2
|
-
`);for(;t>=0;){let e=o.lineBuffer.slice(0,t);o.lineBuffer=o.lineBuffer.slice(t+1);let n=
|
|
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=
|
|
4
|
-
`,o.exited||xe(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;ye(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): `+we(t))}};const B=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}),Ee=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function De(e=process.env){let t={};for(let n of Ee){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function Oe(e={}){let t={...B};for(let n of Object.keys(B)){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 ke(e,t=B){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const Ae={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},je=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Me=/* @__PURE__ */ new Set([`running`,`stopping`]);function Ne(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function Pe(e){return typeof e==`string`&&e.length>0}const Fe=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function Ie(e){return typeof e==`string`&&Fe.has(e)}function Le(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var Re=class{#e;#t;#n;#r;#i=/* @__PURE__ */ new Set;#a=Promise.resolve();constructor(e,t){this.#e=e,this.#t=t.clock,this.#n=t.logger,this.#r=he({now:()=>this.#t()})}async transition(e,t){let n=await this.#p(()=>this.#o(e,t)),r=n.events[n.events.length-1];return r!==void 0&&this.#m(n.record,r,t.logger),n}onTransition(e){this.#i.add(e);let t=!0;return()=>{t&&(t=!1,this.#i.delete(e))}}async#o(e,t){switch(e.kind){case`spawn`:return this.#s(e,t);case`transition`:return this.#c(e,t);case`stop`:return this.#l(e,t);case`reconcile-lost`:return this.#d(e,t);case`resolve-exit`:return this.#u(e,t)}throw Error(`transition: unknown command kind ${String(e.kind)}`)}async get(e){return Pe(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())Me.has(t.status)&&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.#y(n),logger:this.#n});t.push(e.record)}return this.#n?.info(`reconcileLostTasks: marked ${t.length} task(s) lost`),t}async#s(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=Pe(r.taskId),a=i?r.taskId:this.#r.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};i||(r.taskId=a);let s=t.callerId,c=this.#v(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#c(e,t){if(!Ne(e.to))throw Error(`transition: unknown target state ${String(e.to)}`);let n=await this.#g(e.taskId);if(this.#h(n,e.to),e.to===`lost`&&!Ie(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.#f(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#l(e,t){let n=await this.#g(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.#h(n,`stopping`),this.#f(n,`stopping`,t,{stopReason:e.reason}))}async#u(e,t){let n=await this.#g(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=n.status===`stopping`?`canceled`:e.exitCode===0?`succeeded`:`failed`;return this.#h(n,r),this.#f(n,r,t,{exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview})}async#d(e,t){let n=await this.#g(e.taskId);if(!Me.has(n.status))throw Error(`reconcile-lost: task ${n.id} is terminal (${n.status}); only running/stopping tasks can be reconciled`);return this.#f(n,`lost`,t,{errorMessage:e.reason})}async#f(e,t,n,r){let i=Math.max(0,Math.floor(n.clock())),a={...e,status:t,transitionAt:i};je.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.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.#v(e.id,o,t,i,a);return await this.#_(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#p(e){let t=this.#a.then(e,e);return this.#a=t.then(()=>void 0,()=>void 0),await t}#m(e,t,n){for(let r of this.#i)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)}}#h(e,t){let n=Ae[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#g(e){if(!Pe(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#_(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}`))}#v(e,t,n,r,i){let a=i.outputBytes,o=a!==void 0&&a<=2048?i.outputPreview:void 0;return{eventId:this.#r.next(),subscriptionId:t,taskId:e,type:Le(e,n),status:n,transitionAtMs:r,outputBytes:a,outputPreview:o}}#y(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}};function ze(e,t){return new Re(e,t)}function Be(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function Ve(e){for(let t=1;t<e.length;t++)if(Be(e[t-1],e[t])>0)return!1;return!0}var He=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=Ve(t)?[...t]:[...t].sort(Be),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(Be),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 V=new Te;var Ue=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 We=new Ue(B.dispatchConcurrency);let Ge;function Ke(e,t){return e.taskRegistry===void 0?(Ge??=new Re(new He,{clock:t}),Ge):e.taskRegistry}const qe={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}};function Je(e,t,n){let r=[`<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" }.`,`</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,writeFileSync as ee}from"node:fs";import*as E from"node:os";import{tmpdir as te}from"node:os";import*as D from"node:path";import{dirname as O,join as k,resolve as A}from"node:path";import{spawn as ne}from"node:child_process";import{randomBytes as re,randomUUID as j}from"node:crypto";import{ok as M}from"node:assert/strict";import{MessageChannel as ie,Worker as N}from"node:worker_threads";import P from"node:diagnostics_channel";import{fileURLToPath as ae,pathToFileURL as F}from"node:url";import{truncateToWidth as I,visibleWidth as L}from"@earendil-works/pi-tui";import{appendFile as oe,mkdir as se,readFile as R,readdir as ce,rename as le,unlink as ue,writeFile as de}from"node:fs/promises";const fe=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`;function pe(e){let t=``,n=Math.max(0,Math.floor(e));for(let e=0;e<10;e++)t=(fe[n%32]??`0`)+t,n=Math.floor(n/32);return t}function me(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+=fe[n>>>r&31];return t.padEnd(16,`0`)}function he(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 ge(e){let t=e.randomBytes??(e=>new Uint8Array(re(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?he(r):t(10);return n=a,r=o,pe(a)+me(o)}}}const _e=ge({now:()=>Date.now()});function ve(){return _e.next()}function ye(e){let t=e.trim();if(t.length===0)return null;try{return JSON.parse(t)}catch{return null}}function be(e,t){if(e.pid===void 0)return!1;try{return e.kill(t),!0}catch{return!1}}function xe(e,t){if(e.eventWaiters.length>0){let n=e.eventWaiters.shift();n&&n(t);return}e.events.push(t)}function Se(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 Ce(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 we={warn:e=>{console.warn(`[pi-ptc.lifecycle] `+e)}};function Te(e){return e.length<=200?e:e.slice(0,200)+`…`}var Ee=class{#e;constructor(e={}){this.#e=e.logger??we}spawn(e,t){if(e.length===0)throw TypeError(`RealChildProcessLifecycle.spawn: argv must include the command`);let n=Ce(e,t),r=n[0],i=n.slice(1),a=ne(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:ve(),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=ye(e);n?xe(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=ye(n);e?xe(o,e):this.#t(s,n),o.lineBuffer=``}Se(o,{code:e,signal:t})}),a.on(`error`,e=>{o.stderr+=`[spawn-error] `+e.message+`
|
|
4
|
+
`,o.exited||Se(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;be(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): `+Te(t))}};const z=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}),De=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function Oe(e=process.env){let t={};for(let n of De){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function ke(e={}){let t={...z};for(let n of Object.keys(z)){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 Ae(e,t=z){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const je={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},Me=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Ne=/* @__PURE__ */ new Set([`running`,`stopping`]);function Pe(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function Fe(e){return typeof e==`string`&&e.length>0}const Ie=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function Le(e){return typeof e==`string`&&Ie.has(e)}function Re(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 Be(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var Ve=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=ge({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 Fe(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())Ne.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=Fe(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(!Pe(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`&&!Le(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=n.status===`stopping`?`canceled`:e.exitCode===0?`succeeded`:`failed`;return this.#v(n,r),this.#m(n,r,t,{exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview})}async#p(e,t){let n=await this.#y(e.taskId);if(!Ne.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};Me.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.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=je[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(!Fe(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:Be(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 He(e,t){return new Ve(e,t)}function Ue(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function We(e){for(let t=1;t<e.length;t++)if(Ue(e[t-1],e[t])>0)return!1;return!0}var Ge=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=We(t)?[...t]:[...t].sort(Ue),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(Ue),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 B=new Ee;var Ke=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 qe=new Ke(z.dispatchConcurrency);let Je;function Ye(e,t){return e.taskRegistry===void 0?(Je??=new Ve(new Ge,{clock:t}),Je):e.taskRegistry}const Xe={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}};function Ze(e,t,n){let r=[`<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" }.`,`</pi-ptc-context>`].join(`
|
|
5
5
|
`);return e.length===0?r:e+`
|
|
6
6
|
|
|
7
|
-
`+r}function Ye(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:`dispatch depth limit reached`}}const Xe=`dispatch concurrency limit reached`;function Ze(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:Xe}}function Qe(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 $e(){return{...Ye(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function et(){return{...Ze(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function tt(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 nt(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 rt(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 it(e){let t=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!t)return null;let n=t[1]??``,r=t[2]??``,i=nt(n,`name`);if(!i)return null;let a=nt(n,`description`)??``,o=nt(n,`model`)??``,s=rt(n,`tools`),c={name:i,systemPrompt:r.trim()};return a!==void 0&&(c.description=a),o!==void 0&&(c.model=o),s!==void 0&&(c.tools=s),c}function at(e,t,n){let r=D.join(E.homedir(),`.pi`,`agent`,`agents`),i=D.join(t,`.pi`,`agents`),a=[];(n===`user`||n===`both`)&&a.push({path:D.join(r,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&a.push({path:D.join(i,e+`.md`),source:`project`});for(let t of a){let n;try{n=C.readFileSync(t.path,`utf-8`)}catch{continue}let r=it(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),e}}return null}function ot(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`;return r.push(`--thinking`,a),t.tools&&t.tools.length>0&&r.push(`--tools`,t.tools.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}async function st(e,t){let n=await C.promises.mkdtemp(D.join(E.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 ct(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function lt(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}async function ut(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return $e();let i=_e(),a=n.slots??We;if(!a.tryAcquire(i))return et();let o=n.clock??(()=>Date.now()),s=n.logger??qe,c=e.cwd??t.cwd,l=e.agentScope??`user`,u=n.lifecycle??V,d=t.callerId??`dispatch:`+String(t.callId),f=Ke(n,o),p=n.outputStorage,m,h;try{let n=at(e.agent,c,l);if(!n)return a.release(i),{text:``,status:`rejected`,started:!1,agentName:e.agent,durationMs:0,exitCode:1,errorMessage:`unknown agent: `+e.agent+` (agentScope=`+l+`, cwd=`+c+`)`};let g=e.label??e.task.slice(0,64),_=Je(n.systemPrompt,r,t.maxDispatchDepth),v=await st(n.name,_);h=v;let y=ot(e,n,v.filePath),b={cwd:c,env:{...process.env,PI_PTC_DEPTH:String(r),PI_PTC_TASK_ID:i},promptFile:v.filePath};t.sessionDir!==void 0&&(b.sessionDir=t.sessionDir,b.sessionId=i,b.sessionName=`bgdispatch:`+i),m=u.spawn([`pi`,...y],b);let x=m,S={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:S,parentTaskId:t.parentTaskId}},{clock:o,callerId:d,logger:s});let C=!1,w,T=f.onTransition((e,t)=>{e.id===i&&t.status===`stopping`&&(C||w!==void 0||(w=Qe(u,x,{isDone:()=>C,unref:!0})))});return(async()=>{let e=``;try{for await(let t of u.events(x)){let n=lt(t);n!==void 0&&(e=n)}C=!0,w?.();let t=(await u.exit(x)).code??-1,n=Buffer.byteLength(e,`utf8`),r=n<=2048?e:void 0,a;if(p!==void 0)try{await p.writeOutput(i,e),a=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)}await f.transition({kind:`resolve-exit`,taskId:i,exitCode:t,outputRef:a,outputBytes:n,outputPreview:r},{clock:o,callerId:d,logger:s})}catch(t){let n=t instanceof Error?t.message:String(t);s.warn(`background dispatch pump for task `+i+` failed after `+String(e.length)+` chars of buffered output: `+n)}finally{T(),w?.(),ct(v),a.release(i)}})(),{taskId:i,label:g,status:`running`}}catch(t){let n=t instanceof Error?t.message:String(t);return m!==void 0&&Qe(u,m,{unref:!0}),h!==void 0&&ct(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,errorMessage:`background dispatch failed: `+n}}}async function dt(e,t,n={}){if(e.background===!0)return await ut(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return Ye();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now(),s=at(e.agent,i,a);if(!s)return{text:``,status:`rejected`,started:!1,agentName:e.agent,durationMs:Date.now()-o,exitCode:1,errorMessage:`unknown agent: `+e.agent+` (agentScope=`+a+`, cwd=`+i+`)`};let c=Je(s.systemPrompt,r,t.maxDispatchDepth),l=await st(s.name,c),u=ot(e,s,l.filePath);return await new Promise(e=>{let n=``,a,c=-1,d=``,f=!1,p,m,h=!1,g=(r,i,u=!0)=>{if(f)return;f=!0,p?.(),t.signal&&t.signal.removeEventListener(`abort`,_),ct(l);let m={text:n,status:r,started:u,agentName:s.name,durationMs:Date.now()-o,exitCode:c};a&&(m.usage=a),d.length>0&&(m.stderr=d),i&&(m.errorMessage=i),e(m)},_=()=>{m&&!f&&(h=!0,p=Qe(V,m,{isDone:()=>f}))};try{m=V.spawn([`pi`,...u],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:l.filePath})}catch(e){g(`rejected`,`failed to spawn pi: `+(e instanceof Error?e.message:String(e)),!1);return}t.signal&&(t.signal.aborted?_():t.signal.addEventListener(`abort`,_,{once:!0})),(async()=>{if(!m)return;let e=m;try{for await(let t of V.events(e))if(t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(e.usage){let t=a??{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,turns:0};t.input+=e.usage.input??0,t.output+=e.usage.output??0,t.cacheRead+=e.usage.cacheRead??0,t.cacheWrite+=e.usage.cacheWrite??0,t.cost+=e.usage.cost?.total??0,t.turns+=1,a=t}if(Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(n=t.text)}let t=await V.exit(e);c=t.code??-1,d=await V.stderr(e);let r=d.match(/^\[spawn-error\] (.+)$/m);if(r&&t.code===null&&t.signal===null){g(`rejected`,`failed to spawn pi: `+r[1],!1);return}let{status:i,errorMessage:o}=tt({exitCode:c,finalText:n,aborted:h});g(i,o)}catch(e){let t=e instanceof Error?e.message:String(e);g(`rejected`,`dispatch internal error: `+t)}})()})}const H=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],ft=`pi.dispatch`,pt=H,mt={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p};function ht(e){let t=e.names??pt,n=e.includeDispatch??e.names===void 0,r=/* @__PURE__ */ new Map;for(let n of t){let t=mt[n];if(!t)throw TypeError(`unknown PTC binding "${n}"; known bindings: ${H.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);return{content:o.content,details:o.details===void 0?null:o.details}}})}return n&&r.set(ft,{name:ft,execute:async(t,n)=>dt(t,{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 gt(){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 _t(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 U={acquireLatency:P.channel(`ptc:pool:acquire-latency`),resetTime:P.channel(`ptc:worker:reset-time`),imageBytes:P.channel(`ptc:image:hoist-bytes`)};function W(e,t){e.publish(t)}var vt=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(),W(U.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),W(U.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),W(U.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 N(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 yt(e){W(U.imageBytes,{byteLength:e})}function bt(e){W(U.resetTime,{durationMs:e})}function xt(){let e=O(ae(import.meta.url)),t=[A(e,`worker.js`),A(e,`worker-entry.ts`)];for(let e of t)if(w(e))return F(e);throw Error(`worker entry not found; tried: ${t.join(`, `)}`)}function St(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 Ct(e){return typeof e==`object`&&!!e&&e.background===!0}function G(e){return e instanceof Error?e.message:String(e)}function wt(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(`
|
|
8
|
-
`);return e===-1?t:t.slice(0,e)}}}}function
|
|
9
|
-
`)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=
|
|
10
|
-
`))r.push(e.length===0?``:`${i} ${e}`);continue}let o=
|
|
11
|
-
`):typeof e!=`object`||!e?[String(e)]:
|
|
7
|
+
`+r}function Qe(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:`dispatch depth limit reached`}}const $e=`dispatch concurrency limit reached`;function et(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:$e}}function tt(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 nt(){return{...Qe(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function rt(){return{...et(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function it(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 at(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 ot(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 st(e){let t=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!t)return null;let n=t[1]??``,r=t[2]??``,i=at(n,`name`);if(!i)return null;let a=at(n,`description`)??``,o=at(n,`model`)??``,s=ot(n,`tools`),c={name:i,systemPrompt:r.trim()};return a!==void 0&&(c.description=a),o!==void 0&&(c.model=o),s!==void 0&&(c.tools=s),c}function ct(e,t,n,r){let{userDir:i,projectDir:a}=lt({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=st(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),e}}return null}function lt(e){let t=e.homeDir??E.homedir();return{userDir:D.join(t,`.pi`,`agent`,`agents`),projectDir:D.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function ut(e){let t=e?.code;return typeof t==`string`?t:String(e)}function dt(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function ft(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(pt(e))return!0;return!1}return a===r&&pt(r)}function pt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function mt(e,t,n){let r=ut(n);return r!==`ENOENT`&&r!==`ENOTDIR`||dt(e)?!1:!ft(e,t)}function ht(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=lt(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(!mt(e,t,n)){let t=ut(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=st(i)?.name??n;a.length>0&&o.add(a)}}return[...o].sort()}function gt(e){let{userDir:t,projectDir:n}=lt(e),r=ht(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 _t(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,errorMessage:`agent is required (there is no default agent) — `+gt(e)}}function vt(e){return typeof e!=`string`||e.trim().length===0}function yt(e,t,n,r=0){return{text:``,status:`rejected`,started:!1,agentName:e,durationMs:r,exitCode:1,errorMessage:`unknown agent: `+e+` (agentScope=`+t+`, cwd=`+n+`). `+gt({cwd:n,agentScope:t})}}function bt(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`;return r.push(`--thinking`,a),t.tools&&t.tools.length>0&&r.push(`--tools`,t.tools.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}async function xt(e,t){let n=await C.promises.mkdtemp(D.join(E.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 St(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Ct(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}async function wt(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return nt();if(vt(e.agent))return _t({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`});let i=ve(),a=n.slots??qe;if(!a.tryAcquire(i))return rt();let o=n.clock??(()=>Date.now()),s=n.logger??Xe,c=e.cwd??t.cwd,l=e.agentScope??`user`,u=n.lifecycle??B,d=t.callerId??`dispatch:`+String(t.callId),f=Ye(n,o),p=n.outputStorage,m,h;try{let n=ct(e.agent,c,l);if(!n)return a.release(i),yt(e.agent,l,c);let g=e.label??e.task.slice(0,64),_=Ze(n.systemPrompt,r,t.maxDispatchDepth),v=await xt(n.name,_);h=v;let y=bt(e,n,v.filePath),b={cwd:c,env:{...process.env,PI_PTC_DEPTH:String(r),PI_PTC_TASK_ID:i},promptFile:v.filePath};t.sessionDir!==void 0&&(b.sessionDir=t.sessionDir,b.sessionId=i,b.sessionName=`bgdispatch:`+i),m=u.spawn([`pi`,...y],b);let x=m,S={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:S,parentTaskId:t.parentTaskId}},{clock:o,callerId:d,logger:s});let C=!1,w,T=f.onTransition((e,t)=>{e.id===i&&t.status===`stopping`&&(C||w!==void 0||(w=tt(u,x,{isDone:()=>C,unref:!0})))});return(async()=>{let e=``;try{for await(let t of u.events(x)){let n=Ct(t);n!==void 0&&(e=n)}C=!0,w?.();let t=(await u.exit(x)).code??-1,n=Buffer.byteLength(e,`utf8`),r=n<=2048?e:void 0,a;if(p!==void 0)try{await p.writeOutput(i,e),a=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)}await f.transition({kind:`resolve-exit`,taskId:i,exitCode:t,outputRef:a,outputBytes:n,outputPreview:r},{clock:o,callerId:d,logger:s})}catch(t){let n=t instanceof Error?t.message:String(t);s.warn(`background dispatch pump for task `+i+` failed after `+String(e.length)+` chars of buffered output: `+n)}finally{T(),w?.(),St(v),a.release(i)}})(),{taskId:i,label:g,status:`running`}}catch(t){let n=t instanceof Error?t.message:String(t);return m!==void 0&&tt(u,m,{unref:!0}),h!==void 0&&St(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,errorMessage:`background dispatch failed: `+n}}}async function Tt(e,t,n={}){if(e.background===!0)return await wt(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return Qe();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now();if(vt(e.agent))return _t({cwd:i,agentScope:a});let s=ct(e.agent,i,a);if(!s)return yt(e.agent,a,i,Date.now()-o);let c=Ze(s.systemPrompt,r,t.maxDispatchDepth),l=await xt(s.name,c),u=bt(e,s,l.filePath);return await new Promise(e=>{let n=``,a,c=-1,d=``,f=!1,p,m,h=!1,g=(r,i,u=!0)=>{if(f)return;f=!0,p?.(),t.signal&&t.signal.removeEventListener(`abort`,_),St(l);let m={text:n,status:r,started:u,agentName:s.name,durationMs:Date.now()-o,exitCode:c};a&&(m.usage=a),d.length>0&&(m.stderr=d),i&&(m.errorMessage=i),e(m)},_=()=>{m&&!f&&(h=!0,p=tt(B,m,{isDone:()=>f}))};try{m=B.spawn([`pi`,...u],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:l.filePath})}catch(e){g(`rejected`,`failed to spawn pi: `+(e instanceof Error?e.message:String(e)),!1);return}t.signal&&(t.signal.aborted?_():t.signal.addEventListener(`abort`,_,{once:!0})),(async()=>{if(!m)return;let e=m;try{for await(let t of B.events(e))if(t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(e.usage){let t=a??{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,turns:0};t.input+=e.usage.input??0,t.output+=e.usage.output??0,t.cacheRead+=e.usage.cacheRead??0,t.cacheWrite+=e.usage.cacheWrite??0,t.cost+=e.usage.cost?.total??0,t.turns+=1,a=t}if(Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(n=t.text)}let t=await B.exit(e);c=t.code??-1,d=await B.stderr(e);let r=d.match(/^\[spawn-error\] (.+)$/m);if(r&&t.code===null&&t.signal===null){g(`rejected`,`failed to spawn pi: `+r[1],!1);return}let{status:i,errorMessage:o}=it({exitCode:c,finalText:n,aborted:h});g(i,o)}catch(e){let t=e instanceof Error?e.message:String(e);g(`rejected`,`dispatch internal error: `+t)}})()})}const V=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],H=`pi.dispatch`,Et=V,Dt={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},Ot={name:H,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters: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())})};function kt(e){let t=e.names??Et,n=e.includeDispatch??e.names===void 0,r=/* @__PURE__ */ new Map;for(let n of t){let t=Dt[n];if(!t)throw TypeError(`unknown PTC binding "${n}"; known bindings: ${V.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);return{content:o.content,details:o.details===void 0?null:o.details}}})}return n&&r.set(H,{name:H,execute:async(t,n)=>{let r={type:`toolCall`,id:`ptc:${n.callId}`,name:H,arguments:t},i;try{i=S(Ot,r)}catch(n){let r=typeof t==`object`&&t&&!Array.isArray(t)?t:void 0,i=r?.agent,a=r?.agentScope;return vt(i)?_t({cwd:e.cwd,agentScope:a===`user`||a===`project`||a===`both`?a:`user`}):{text:``,status:`rejected`,started:!1,agentName:i,durationMs:0,exitCode:1,errorMessage:n instanceof Error?n.message:String(n)}}return Tt(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 At(){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 jt(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 U={acquireLatency:P.channel(`ptc:pool:acquire-latency`),resetTime:P.channel(`ptc:worker:reset-time`),imageBytes:P.channel(`ptc:image:hoist-bytes`)};function W(e,t){e.publish(t)}var Mt=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(),W(U.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),W(U.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),W(U.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 N(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 Nt(e){W(U.imageBytes,{byteLength:e})}function Pt(e){W(U.resetTime,{durationMs:e})}function Ft(){let e=O(ae(import.meta.url)),t=[A(e,`worker.js`),A(e,`worker-entry.ts`)];for(let e of t)if(w(e))return F(e);throw Error(`worker entry not found; tried: ${t.join(`, `)}`)}function It(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 Lt(e){return typeof e==`object`&&!!e&&e.background===!0}function G(e){return e instanceof Error?e.message:String(e)}function Rt(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(`
|
|
8
|
+
`);return e===-1?t:t.slice(0,e)}}}}function zt(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function Bt(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 Vt(e){try{let t=Buffer.byteLength(JSON.stringify(e,(e,t)=>zt(t)?null:t)??``,`utf8`),n=0;return Bt(e,e=>{n+=e.byteLength}),t+n}catch{return 1/0}}async function Ht(e){let i=ke(e.config),s=Oe(),c=e.runId??j(),l=Ae(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 N(Ft(),jt({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: ${G(e)}`}}}return await new Promise(s=>{let m=new ie,h=m.port1,g=m.port2,_=new AbortController,v=!1,y=At(),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 Ke(i.dispatchConcurrency),E=0,te=[],D=e.depth??0,O,k,A=[],ne=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},re=e=>e===`timeout`?`run timed out after ${l} ms`:`run cancelled`,j=e=>e===`timeout`?n.timeout:n.abort,M=t=>{if(v)return;v=!0,O&&clearTimeout(O),k&&clearTimeout(k),e.signal?.removeEventListener(`abort`,ue),_.abort(),h.close(),e.pool?e.pool.release(p):p.terminate();let n=x.snapshot();s(n.length>0?{...t,subCalls:n}:t)},N=(e,t,n)=>{M({logs:u,narrations:d,phases:f,error:n===void 0?{kind:e,message:t}:{kind:e,message:t,stack:n}})},P=e=>{if(!v){if(!r(e)){N(n.protocol,`internal error: malformed host frame`);return}h.postMessage(e)}},ae=()=>{let t={kind:o.init,runId:c,surface:e.surface,code:e.code,bindings:[...e.bindings.keys()],bindingCandidates:[...V],maxItemsPerCall:i.maxItemsPerCall,maxPendingCalls:i.maxPendingCalls,...e.args===void 0?{}:{args:e.args}};if(!r(t)){N(n.protocol,`internal error: malformed init frame`);return}let a=Vt(t);if(a>i.maxMessageBytes){N(n.protocol,`init frame of ${a} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}P(t)},F=(e,t)=>(T+=e,T<=i.maxOutputBytes||(N(n.outputLimit,`${t} exceeded the output budget: logs + result reached ${T} bytes (maxOutputBytes=${i.maxOutputBytes}); ${u.length} log line(s) retained`),!1)),I=async()=>{if(E<i.maxParallelSubCalls){E+=1;return}await new Promise(e=>{te.push(e)})},L=()=>{let e=te.shift();if(e){e();return}--E},oe=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`}),N(n.protocol,`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`);return}se(e).finally(()=>{--w})},se=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)`)}),R({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===H,s=a&&Lt(t.args);if(a){if(!s&&!ee.tryAcquire()){x.recordEnd(t.callId,`rejected`,{errorMessage:$e}),R({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:et()});return}}else if(await I(),v){x.recordEnd(t.callId,`cancelled`,{errorMessage:`run settled before binding started`}),L();return}try{let s=await r.execute(t.args,{signal:_.signal,callId:t.callId,depth:D,maxDispatchDepth:i.maxDispatchDepth,callerId:c,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...e.sessionDir===void 0?{}:{sessionDir:e.sessionDir},dispatchDeps:{...e.dispatchDeps,slots:e.dispatchDeps?.slots??ee}}),l=ne(s),u={kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:s},d=Vt(u);if(d>i.maxMessageBytes){x.recordEnd(t.callId,`error`,{errorMessage:`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`}),N(n.protocol,`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}if(R(u))for(let e of l)A.push(e),Nt(Buffer.byteLength(e.data,`base64`));if(_.signal.aborted)x.recordEnd(t.callId,`cancelled`,{errorMessage:`binding aborted by run cancellation`});else{let e=a?It(s):void 0;e===void 0?x.recordEnd(t.callId,`ok`,{resultSummary:Rt(s)}):x.recordEnd(t.callId,e.kind===`refused`?`rejected`:`error`,{errorMessage:e.message})}}catch(e){_.signal.aborted?x.recordEnd(t.callId,`cancelled`,{errorMessage:G(e)}):x.recordEnd(t.callId,`error`,{errorMessage:G(e)}),R({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:G(e)})}finally{a?s||ee.release():L()}},R=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: ${G(t)}`})}catch{N(n.protocol,`binding result is not transferable`)}return!1}},ce=e=>S?{logs:u,narrations:d,phases:f,error:{kind:j(S),message:re(S)}}:e,le=r=>{if(v)return;if(!a(r)){N(n.protocol,`malformed worker frame`);return}let o=r.kind===t.ready?0:Vt(r);if(!Number.isFinite(o)){N(n.protocol,`worker frame could not be serialized for accounting`);return}if(o>i.maxMessageBytes){N(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&&Pt(Date.now()-t)}if(!C&&(C=!0,S)){de(S);return}ae();return;case t.call:oe(r);return;case t.log:F(o,`console output`)&&u.push(r.text);return;case t.narration:F(o,`workflow narration`)&&d.push(r.message);return;case t.phase:F(o,`workflow phase`)&&f.push(r.title);return;case t.result:{if(!F(o,`completion value`))return;let e={logs:u,narrations:d,phases:f,...A.length>0?{images:A}:{}};M(ce(r.value===void 0?e:{...e,value:r.value}));return}case t.error:M(ce({logs:u,narrations:d,phases:f,error:r.error}));return;default:N(n.protocol,`unknown worker frame`)}};function ue(){fe(`abort`)}let de=e=>{k&&clearTimeout(k),k=setTimeout(()=>{N(j(e),re(e))},i.graceMs)};function fe(e){if(!v){if(S){N(j(S),re(S));return}S=e,_.abort(),P({kind:o.cancel,reason:e}),de(e)}}p.on(`error`,e=>{N(n.workerExit,`worker failed: ${G(e)}`)}),p.on(`exit`,e=>{N(n.workerExit,`worker exited with code ${e} before the run completed`)}),h.on(`message`,le),h.on(`messageerror`,()=>{N(n.protocol,`worker sent a frame that could not be deserialized`)}),e.signal?.addEventListener(`abort`,ue,{once:!0}),O=setTimeout(()=>{fe(`timeout`)},l);let pe={kind:o.connect,port:g};r(pe)?p.postMessage(pe,[g]):N(n.protocol,`internal error: malformed connect frame`)})}const Ut=`pi-ptc-output-`;function Wt(e,t=Ut){let n=k(te(),`${t}${j()}.txt`);return ee(n,e,`utf8`),n}function Gt(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 Kt(e,t=Ut,n={}){let r=b(e,{maxLines:c,maxBytes:s});if(!r.truncated)return{text:e,truncated:!1};let i=Wt(n.fullText??e,t);return{text:`${r.content}\n\n${Gt(r,i)}`,truncated:!0,fullPath:i}}const qt=200,Jt=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 Yt(e){return!e.includes(`\x1B`)&&!e.includes(``)?e:e.replace(Jt,``)}function K(e){let t=Yt(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 Xt=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function Zt(e){return Xt.test(e)?e:JSON.stringify(e)}function Qt(e){if(e===null)return`null`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(typeof e==`string`){let t=K(e);return t.includes(`
|
|
9
|
+
`)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=Qt(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=Qt(e[r]??null);if(t===void 0)return;n.push(`${Zt(r)}: ${t}`)}return`{${n.join(`, `)}}`}function $t(e){let t=Qt(e);if(t!==void 0)return t.length<=100?t:void 0}function en(e){return e===null?`null`:typeof e==`string`?K(e):String(e)}function tn(e,t){if(typeof e!=`object`||!e)return[`${t}${en(e)}`];if(Array.isArray(e)){if(e.length===0)return[`${t}[]`];let n=[`${t}[`];for(let r of e){let e=$t(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=$t(n);if(a!==void 0){r.push(`${i}${Zt(t)}: ${a}`);continue}if(typeof n==`string`){r.push(`${i}${Zt(t)}:`);for(let e of K(n).split(`
|
|
10
|
+
`))r.push(e.length===0?``:`${i} ${e}`);continue}let o=tn(n,i);r.push(`${i}${Zt(t)}: ${(o[0]??``).trimStart()}`.trimEnd(),...o.slice(1))}return r.push(`${t}}`),r}function nn(e,t){return typeof e==`string`?K(e).split(`
|
|
11
|
+
`):typeof e!=`object`||!e?[String(e)]:tn(e,t)}function rn(e){return e.split(`
|
|
12
12
|
`).map(e=>e.length>200?`${e.slice(0,199)}…`:e).join(`
|
|
13
|
-
`)}function
|
|
14
|
-
`))}function
|
|
15
|
-
`)}`,i=Error(K(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function
|
|
13
|
+
`)}function an(e){if(typeof e==`string`)return rn(K(e));if(typeof e!=`object`||!e)return String(e);let t=$t(e);return rn((t===void 0?nn(e,``):[t]).join(`
|
|
14
|
+
`))}function on(e=process.env){let t=e.PI_PTC_DEPTH;return t===void 0||!/^\d+$/.test(t)?0:Number.parseInt(t,10)}function sn(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 q(e){if(e===void 0)return V;let t=new Set(e);return V.filter(e=>t.has(e))}const cn=["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.`],ln={run_code:`ptc_run_code`,workflow:`ptc_workflow`};function un(e){let t=e?.cwd;return typeof t==`string`&&t.length>0?t:process.cwd()}function dn(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 fn(e){return[...e.phases.map(e=>`[phase] ${K(e)}`),...e.narrations.map(e=>`[log] ${K(e)}`),...e.logs.map(e=>K(e))]}function pn(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=fn(e),r=n.length===0?``:`\nCaptured output:\n${n.join(`
|
|
15
|
+
`)}`,i=Error(K(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function mn(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=>K(e)).join(` → `)}`),t.narrations.length>0&&a.push(t.narrations.map(e=>K(e)).join(`
|
|
16
16
|
`)),t.logs.length>0&&a.push(t.logs.map(e=>K(e)).join(`
|
|
17
|
-
`)),t.value!==void 0&&a.push(
|
|
18
|
-
`):`(${
|
|
19
|
-
`).find(e=>e.trim().length>0)??``).trim(),120)}function
|
|
20
|
-
`)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return J(e.replace(/\s*\/\/.*$/,``),120)}}function
|
|
21
|
-
`),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:J(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=
|
|
22
|
-
`)&&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
|
|
23
|
-
`)){let e=J(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(J(n,Math.max(2,t-5)))+`…`}return`?`}function
|
|
24
|
-
`).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new
|
|
25
|
-
`).map(e=>J(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?` …`:``;o.push({label:`phases`,lines:[`${e.join(` → `)}${t}`]})}if(a!==void 0&&a.narrations.length>0){let e=a.narrations.slice(0,12);o.push({label:`log`,lines:e.map(e=>K(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=>K(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=>K(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=
|
|
26
|
-
`),
|
|
27
|
-
`),
|
|
28
|
-
`).find(e=>e.trim().length>0)??``).trim(),120)}function
|
|
29
|
-
`),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,
|
|
30
|
-
`),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...
|
|
31
|
-
`)}],details:{tasks:r,count:r.length}}},...
|
|
32
|
-
`),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...
|
|
33
|
-
`),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...
|
|
17
|
+
`)),t.value!==void 0&&a.push(an(t.value));for(let e of r)a.push(`Warning: ${K(e)}`);let o=Kt(a.length>0?a.join(`
|
|
18
|
+
`):`(${ln[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 hn=/^(.*?)(└─ |├─ | )(?: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 _n(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 vn(e,t){let n=0,r=0;for(;r<t&&n<e.length;)e.charCodeAt(n)===27?n=_n(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:bn(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 bn(e,t,n){return e.map(e=>{let r=gn(e),i=hn.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=vn(e,s),l=vn(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`};var Sn=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>Cn(e,t))}};function Cn(e,t){let{left:n,right:r}=e;if(r===void 0)return I(n,t,`…`);let i=L(r);if(i>=t)return I(r,t,`…`);let a=I(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-L(a));return a+` `.repeat(o)+r}function J(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function wn(e){return J((K(e).split(`
|
|
19
|
+
`).find(e=>e.trim().length>0)??``).trim(),120)}function Tn(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2).replace(/\.?0+$/,``)}s`}function En(e,t){return`${e} ${t}${e===1?``:`s`}`}function Dn(e){for(let t of e.split(`
|
|
20
|
+
`)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return J(e.replace(/\s*\/\/.*$/,``),120)}}function On(e){if(e===void 0)return;if(typeof e==`string`){let t=K(e).split(`
|
|
21
|
+
`),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:J(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=an(e);if(!t.includes(`
|
|
22
|
+
`)&&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 kn(e,t){if(e===void 0)return;let n=[],r=e.logs.length+e.narrations.length;if(r>0&&n.push(t.fg(`dim`,En(r,`output line`))),e.imageCount>0&&n.push(t.fg(`toolOutput`,En(e.imageCount,`image`))),e.surface===`workflow`&&e.phases.length>0&&n.push(t.fg(`dim`,En(e.phases.length,`phase`))),e.warnings.length>0&&n.push(t.fg(`warning`,En(e.warnings.length,`warning`))),e.fullOutputPath!==void 0&&n.push(t.fg(`warning`,`truncated`)),e.durationMs>0&&n.push(t.fg(`dim`,Tn(e.durationMs))),n.length!==0)return`${t.fg(`dim`,`•`)} ${n.join(t.fg(`dim`,` · `))}`}function An(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 jn(e,t,n){let r=` `+(t?`└─ `:`├─ `),i=` `+(t?` `:`│ `),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 Mn(e){return typeof e!=`object`||!e?!1:Array.isArray(e)?e.length>0:Object.keys(e).length>0}const Nn=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function Pn(e){return Nn.test(e)?e:JSON.stringify(e)}function Fn(e,t){if(e===null)return`null`;if(typeof e==`boolean`||typeof e==`number`)return String(e);if(typeof e==`string`){let n=K(e);if(n.length===0)return`""`;if(n.includes(`
|
|
23
|
+
`)){let e=J(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(J(n,Math.max(2,t-5)))+`…`}return`?`}function In(e){return typeof e!=`object`||!e}function Ln(e,t){if(t<8)return;if(Array.isArray(e)){if(e.length===0)return`[]`;if(e.length>5||!e.every(In))return;let n=`[`+e.map(e=>Fn(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(In))return;let r=`{`+n.map(n=>{let r=e[n]??null;return Pn(n)+`: `+Fn(r,Math.max(2,Math.floor(t/4)))}).join(`, `)+`}`;return r.length<=t?r:void 0}function Rn(e,t,n,r,i,a,o,s,c){let l=n+(r?`└─ `:`├─ `),u=n+(r?` `:`│ `);if(s>=i){c.push(Y(l+t+`…`,o));return}if(Array.isArray(e)&&e.length===0){c.push(Y(l+t+`[]`,o));return}if(!Array.isArray(e)&&typeof e==`object`&&e&&Object.keys(e).length===0){c.push(Y(l+t+`{}`,o));return}if(typeof e!=`object`||!e){let n=Math.max(0,o-L(l)-t.length);c.push(Y(l+t+Fn(e,n),o));return}let d=Ln(e,Math.max(0,o-L(l)-t.length));if(d!==void 0){c.push(Y(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(Y(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;Rn(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];Rn(e[l]??null,Pn(l)+`: `,u,r,i,a,o,s+1,c)}}if(p>h){let e=f?`items`:`keys`;c.push(Y(u+`└─ …+`+(p-h)+` more `+e,o))}}function Y(e,t){if(L(e)<=t)return e;let n=e.match(/^([\s│├└─]*)/),r=n&&n[1]?n[1]:``,i=L(r),a=Math.max(0,t-i-1),o=``,s=0;for(let t of e.slice(r.length)){let e=L(t);if(s+e>a)break;o+=t,s+=e}return r+o+`…`}function zn(e,t={}){let n=t.maxDepth??4,r=t.maxChildren??6,i=t.maxLineChars??120,a=t.moreAfter===!0;if(!Mn(e))return typeof e==`object`&&e?[Array.isArray(e)?`[]`:`{}`]:[Fn(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;Rn(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];Rn(e[d]??null,Pn(d)+`: `,``,u,n,r,i,0,o)}return c>l&&o.push((a?`├─ `:`└─ `)+`…+`+(c-l)+` more keys`),o}function Bn(e,t,n=`run_code`,r={}){let i=(typeof e.description==`string`&&e.description.trim().length>0?e.description.trim():e.meta?.name)??``,a=Dn(e.code??e.script??``),o=i.length>0?i:a??`(no description)`;return yn(new Sn([{left:`└─ ${`${t.fg(`toolTitle`,t.bold(xn[n]))} ${t.fg(`accent`,o)}`}`}]),{intervalMs:150,isPartial:r.isPartial??!1,theme:t,requestInvalidate:r.requestInvalidate??Vn,state:r.state??{}})}function Vn(){}function Hn(e){let t=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0);return wn(t?.text??``)||`failed`}function Un(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 Wn={running:{text:()=>`running`,themeSlot:`muted`},ok:{text:e=>e.durationMs===void 0?`ok`:`ok ${Tn(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 Gn(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=Un(e.name,e.args),l=Wn[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 Kn(e,t,n,r=!1,i=!1){let a=kn(e.details,n),o=e=>a===void 0?e:{...e,right:a};if(t)return[o({left:` ${n.fg(`error`,`failed: ${Hn(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(Mn(s))return zn(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=On(s);return c===void 0?[o({left:` ${n.fg(`muted`,`done`)}`})]:[o({left:` ${n.fg(`dim`,`→ ${c}`)}`})]}function qn(e,t,n,r={}){let i=An(e.details),a=[...Kn({...e,details:i},t,n,!1,r.isPartial===!0)];return i?.subCalls!==void 0&&a.push(...Gn(i.subCalls,n)),new Sn(a)}function Jn(e,t,n,r,i={}){let a=An(e.details);if(n){let t=[...Kn({...e,details:a},!0,r)];a?.subCalls!==void 0&&t.push(...Gn(a.subCalls,r));let n=K(e.content?.find(e=>e.type===`text`)?.text??Hn(e));for(let e of n.split(`
|
|
24
|
+
`).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new Sn(t)}let o=[],s=t.code??t.script??``;if(s.length>0){let e=s.split(`
|
|
25
|
+
`).map(e=>J(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?` …`:``;o.push({label:`phases`,lines:[`${e.join(` → `)}${t}`]})}if(a!==void 0&&a.narrations.length>0){let e=a.narrations.slice(0,12);o.push({label:`log`,lines:e.map(e=>K(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=>K(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=>K(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=Kn({...e,details:a},!1,r,l,i.isPartial===!0);c!==void 0&&u.push(...Gn(c,r));for(let e=0;e<o.length;e+=1){let t=e===o.length-1;u.push(...jn(o[e]??{label:``,lines:[]},t,r))}return new Sn(u)}function Yn(e){return{renderCall(t,n,r){return Bn(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?Jn(e,r?.args??{},r?.isError===!0,n,{isPartial:i}):qn(e,r?.isError===!0,n,{isPartial:i})}}}const Xn=["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`); calling a name that is not bound rejects with an error the program can catch, and","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.`,``,"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(`
|
|
26
|
+
`),Zn=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 ${z.timeoutMs/1e3} s; anything above ${z.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 Qn(e={}){return g({name:`ptc_run_code`,label:`PTC Run Code`,description:Xn,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:[...cn],parameters:Zn,async execute(t,n,r,i,a){let o=un(a),s=q(e.getBindingSourceNames?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=dn({surface:`run_code`,startedAt:c,onUpdate:i}),p;try{p=await Ht({code:n.code,surface:`run_code`,cwd:o,bindings:kt({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 pn(p);return mn({outcome:p,surface:`run_code`,durationMs:Date.now()-c})},...Yn(`run_code`)})}const $n=[`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.",``,`Image-bearing tool results inside the script are attached to you after the run — never return`,`image data as the script's value.`].join(`
|
|
27
|
+
`),er=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 tr(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=nr(t[e],`args.${e}`,/* @__PURE__ */ new Set);if(n!==void 0)throw TypeError(`ptc_workflow args must be plain JSON: ${n}`)}}}function nr(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=nr(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=nr(i[e],`${n}.${e}`,r);if(t!==void 0)return t}return}finally{r.delete(i)}}function rr(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 ir(e={}){return g({name:`ptc_workflow`,label:`PTC Workflow`,description:$n,promptSnippet:`Run a structured TypeScript workflow with named phases, narration (log/phase) and structured concurrency (parallel/pipeline)`,promptGuidelines:[...cn],parameters:er,async execute(t,n,r,i,a){tr(n.args);let o=un(a),s=q(e.getBindingSourceNames?.()),c=Date.now(),l=e.getPool?.(),u=a.sessionManager?.getSessionDir?.(),d=e.getDispatchDeps?.(),f=dn({surface:`workflow`,startedAt:c,onUpdate:i}),p;try{p=await Ht({code:n.script,surface:`workflow`,cwd:o,bindings:kt({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 pn(p);let m=n.meta.phases?.map(e=>e.name);return mn({outcome:p,surface:`workflow`,warnings:rr(p,m),durationMs:Date.now()-c})},...Yn(`workflow`)})}var ar=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 or(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}var sr=class{#e;constructor(e){if(e.length===0)throw TypeError(`FileOutputStorage: baseDir is required`);this.#e=e}async readOutput(e){try{return await R(this.#t(e),`utf8`)}catch(e){if(or(e))return null;throw e}}async writeOutput(e,t){let n=k(this.#e,`tasks`,e);await se(n,{recursive:!0}),await de(k(n,`output.log`),t,`utf8`)}outputRef(e){return this.#t(e)}#t(e){return k(this.#e,`tasks`,e,`output.log`)}};function cr(e,t){return Kt(e,`pi-ptc-task-output-`,t===void 0?{}:{fullText:t})}const lr={running:`accent`,stopping:`warning`,succeeded:`success`,failed:`error`,lost:`dim`,canceled:`muted`},ur={running:`●`,stopping:`◐`,succeeded:`✓`,failed:`✗`,lost:`◌`,canceled:`⊘`};var X=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>dr(e,t))}};function dr(e,t){let{left:n,right:r}=e;if(r===void 0)return I(n,t,`…`);let i=L(r);if(i>=t)return I(r,t,`…`);let a=I(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-L(a));return a+` `.repeat(o)+r}function fr(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function pr(e){return fr((K(e).split(`
|
|
28
|
+
`).find(e=>e.trim().length>0)??``).trim(),120)}function mr(e){return typeof e==`object`&&e?e:{}}function hr(e){return e===`running`||e===`stopping`}function gr(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 _r(e,t){if(hr(e.status))return gr(t-e.createdAt);if(e.durationMs!==void 0)return gr(e.durationMs);if(e.finishedAt!==void 0)return gr(e.finishedAt-e.createdAt)}function vr(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 yr(){}function br(e,t,n){return new X([{left:`└─ ${n.fg(`toolTitle`,n.bold(e))}${t.length>0?` ${t}`:``}`}])}function xr(e,t,n){let r=mr(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 br(`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 br(`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=${K(r.reason)}`:``;return br(`PTC task stop`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}}}function Sr(e,t,n,r){let i=lr[e.status]??`muted`,a=n.fg(i,ur[e.status]??`?`),o=fr(K(e.label),48),s=[`${a} ${n.fg(`text`,o)}`,n.fg(`dim`,K(e.agentName))],c=_r(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 Cr(e,t){let n=mr(e),r=Array.isArray(n.tasks)?n.tasks:[];if(r.length===0)return vr(new X([{left:` ${t.theme.fg(`muted`,`(no background tasks)`)}`}]),{isLive:!1,state:t.state,requestInvalidate:t.requestInvalidate});let i=r.some(e=>hr(e.status)),a=r.slice(0,32),o=r.length-a.length,s=a.map((e,n)=>Sr(e,n===a.length-1&&o===0,t.theme,t.now));return o>0&&s.push({left:` └─ ${t.theme.fg(`dim`,`…+${o} more tasks`)}`}),vr(new X(s),{isLive:t.partial&&i,state:t.state,requestInvalidate:t.requestInvalidate})}function wr(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 Tr(e,t){return` ${t.fg(`dim`,`full output: `)}${t.fg(`accent`,e)}`}function Er(e,t){let n=mr(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=wr(i,a,t.theme),c=[];if(r.length>0){let e=K(r).split(`
|
|
29
|
+
`),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,fr(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:Tr(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:Tr(o,t.theme),...s===void 0?{}:{right:s}});return new X(c)}function Dr(e,t){let n=mr(e),r=n.task;if(typeof r!=`object`||!r)return new X([{left:` ${t.theme.fg(`muted`,`(no task)`)}`}]);let i=lr[r.status]??`muted`,a=t.theme.fg(i,ur[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`,K(r.id))}`,t.theme.fg(i,s)];return typeof r.stopReason==`string`&&r.stopReason.length>0&&c.push(t.theme.fg(`dim`,`reason=${K(r.stopReason)}`)),new X([{left:` ${c.join(` `)}`}])}function Or(e,t){let n=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0),r=pr(n?.text??``)||`failed`;return new X([{left:` ${t.fg(`error`,`failed: ${r}`)}`}])}function kr(e,t,n){switch(e){case`task-list`:return Cr(t.details,n);case`task-output`:return Er(t.details,n);case`task-stop`:return Dr(t.details,n)}}function Ar(e){return{renderCall(t,n){return xr(e,t,n)},renderResult(t,n,r,i){return i?.isError===!0?Or(t,r):kr(e,t,{theme:r,partial:n?.isPartial===!0||i?.isPartial===!0,requestInvalidate:i?.invalidate??yr,state:i?.state??{},now:Date.now()})}}}const jr=[`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).`,`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.`],Mr=x.Union([x.Literal(`running`),x.Literal(`stopping`),x.Literal(`succeeded`),x.Literal(`failed`),x.Literal(`canceled`),x.Literal(`lost`)]),Nr=x.Object({status:x.Optional(x.Array(Mr,{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.`}))});function Pr(e){let t=[e.id,e.status,`${e.agentName} depth=${e.depth}`,K(e.label)];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.errorMessage!==void 0&&t.push(`error=${K(e.errorMessage)}`),t.join(` `)}function Fr(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(`
|
|
30
|
+
`),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...jr],parameters:Nr,async execute(t,n){let r=await e.query({...n.status===void 0?{}:{status:n.status},limit:n.limit??100,orderBy:`createdAt-desc`});return{content:[{type:`text`,text:r.length===0?`(no background tasks)`:r.map(e=>Pr(e)).join(`
|
|
31
|
+
`)}],details:{tasks:r,count:r.length}}},...Ar(`task-list`)})}async function Ir(e,t,n){let r=await e.get(t);if(r===null)throw Error(`${n}: unknown taskId ${t}`);return r}const Lr=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.`}))});function Rr(e,t){return g({name:`ptc_task_output`,label:`PTC Task Output`,description:[`Read a background task's captured output.`,`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(`
|
|
32
|
+
`),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...jr],parameters:Lr,async execute(n,r){let i=r.taskId,a=await Ir(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=cr(c===0?o:l.subarray(c).toString(`utf8`),o),d=s<=2048?o:void 0,f={taskId:i,output:u.text,outputBytes:s,...d===void 0?{}:{outputPreview:d},outputTruncated:u.truncated,...u.fullPath===void 0?{}:{outputFullPath:u.fullPath}};return{content:[{type:`text`,text:f.output.length>0?f.output:`(no output yet; task ${i} is ${a.status})`}],details:f}},...Ar(`task-output`)})}const zr=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".`}))});function Br(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(`
|
|
33
|
+
`),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...jr],parameters:zr,async execute(t,n){let i=n.taskId,a=await Ir(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=${K(s.stopReason)}`;return{content:[{type:`text`,text:`${s.id} ${s.status}${l}`}],details:{task:s,fromStatus:c??a.status}}},...Ar(`task-stop`)})}var Vr=class{#e;#t=/* @__PURE__ */ new Map;constructor(e={}){this.#e=ke(e.config)}get(e){let t=this.#t.get(e);if(t!==void 0)return t;let n=Oe(),r=new Mt({buildWorkerUrl:Ft,size:this.#e.poolSize,acquireTimeoutMs:this.#e.poolAcquireTimeoutMs,drainGraceMs:this.#e.drainGraceMs,workerOptions:jt({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 Hr={warn:e=>{console.warn(`[pi-ptc.notifications] `+e)}};var Ur=class{#e;#t;#n;#r;#i;constructor(e,t={}){this.#e=e,this.#t=t.now??Date.now,this.#n=t.logger??Hr,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 Wr={mkdir:(e,t)=>se(e,t),readFile:(e,t)=>R(e,t),writeFile:(e,t,n)=>de(e,t,n),appendFile:(e,t,n)=>oe(e,t,n),rename:(e,t)=>le(e,t),unlink:e=>ue(e),readdir:e=>ce(e)};function Gr(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}function Kr(e){return e instanceof Error?e.message:String(e)}function qr(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}var Jr=class{#e;#t;constructor(e,t={}){if(e.length===0)throw TypeError(`FileTaskStorage: baseDir is required`);this.#e=e,this.#t=t.fs??Wr}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(k(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||qr(r[t-1],e)<=0)?r:[...r].sort(qr)).map(e=>JSON.stringify(e)).join(`
|
|
34
34
|
`)+`
|
|
35
|
-
`;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(
|
|
36
|
-
`)){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+`: `+
|
|
37
|
-
`);return`${`<bg-task-notifications batch-id="${Q(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function
|
|
35
|
+
`;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(qr);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(k(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(Gr(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+`: `+Kr(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(Gr(e))return[];throw e}let n=[];for(let r of t.split(`
|
|
36
|
+
`)){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+`: `+Kr(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(O(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(Gr(e))return[];throw e}}async#c(e){try{return await this.#t.readFile(e,{encoding:`utf8`}),!0}catch(e){if(Gr(e))return!1;throw e}}#l(){return k(this.#e,`tasks`)}#u(){return k(this.#e,`subscriptions`)}#d(){return k(this.#e,`events`)}#f(e){return k(this.#l(),e+`.json`)}#p(e,t){return k(this.#u(),e+`-`+t+`.json`)}#m(e,t){return k(this.#d(),e+`-`+t+`.jsonl`)}};function Yr(e,t){return new Jr(e,t)}const Xr=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Zr=/* @__PURE__ */ new Set([`running`,`stopping`]),Qr=2**53-1,$r={info:()=>void 0,warn:e=>{console.warn(`[pi-ptc.background] `+e)}};function Z(e){return e instanceof Error?e.message:String(e)}function ei(e){return e===void 0||e.length===0?`<in-memory>`:e}function ti(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}var ni=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()}},ri=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)}},ii=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)}},ai=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]}},oi=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??$r,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 Ge:Yr(e)),this.#n=e.createOutputStorage??(e=>e===void 0||e.length===0?new ar:new sr(e));let t=new Ge,n=He(t,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),r=new Ur(t,{now:this.clock,logger:this.#e});this.registry=new ni(n),this.outputStorage=new ri(new ar),this.pipeline=new ii(r),this.lifecycle=new ai((e.createLifecycle??(()=>new Ee({logger:this.#e})))()),this.slots=new Ke(e.concurrency??z.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||Xr.has(e.status)&&this.pipeline.notifyIdle(t.subscriptionId,e.id).catch(t=>{this.#e.warn(`terminal notification wake for task `+e.id+` failed: `+Z(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 `+ei(e)+` is unavailable: `+Z(n),t),[]}let i=He(n,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),a=new Ur(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): `+Z(e),t),[]}finally{this.registry.onTransition(this.#o)}}async drainNotifications(e){let t;try{t=await this.registry.query({limit:Qr})}catch(t){return this.#e.warn(`drainNotifications: could not list tasks for subscriber `+e+`: `+Z(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+`: `+Z(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+`: `+Z(e))}}async shutdown(e){if(this.#a)return[];this.#a=!0;let t;try{t=await this.registry.query({limit:Qr})}catch(e){this.#e.warn(`shutdown: could not list tasks: `+Z(e)),t=[]}let n=[];for(let r of t)if(Zr.has(r.status)&&Re(r,this.#r))try{let t=await this.registry.transition({kind:`reconcile-lost`,taskId:r.id,reason:e},{clock:this.clock,callerId:ti(r),logger:this.#e});n.push(t.record)}catch(e){this.#e.warn(`shutdown: could not mark task `+r.id+` lost: `+Z(e))}for(let e of this.lifecycle.liveHandles()){let t=tt(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: `+Z(e))}}};function si(e={}){return new oi(e)}const ci=/* @__PURE__ */ new Set([`succeeded`,`failed`,`lost`]);function li(e){return ci.has(e.status)}function ui(e,t){if(e.length===0)return``;let n=e.map(fi).join(`
|
|
37
|
+
`);return`${`<bg-task-notifications batch-id="${Q(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function di(e,t=102400){let n=[],r=[],i=0,a=t-mi;for(let t of e){let e=pi(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 fi(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="${Q(t.type)}"`,` task-id="${Q(t.taskId)}"`,` subscription-id="${Q(t.subscriptionId)}"`,` status="${Q(t.status)}"`,` label="${Q(n.label)}"`,` agent-name="${Q(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>${Q(n.outputRef)}</output-ref>`),r!==void 0&&r<=2048&&a!==void 0&&o.push(` <output-preview>${Q(a)}</output-preview>`),o.push(` </bg-task-notification>`),o.join(`
|
|
38
38
|
`)}function Q(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`"`,`"`).replaceAll(` `,`	`).replaceAll(`
|
|
39
|
-
`,` `).replaceAll(`\r`,` `)}function
|
|
40
|
-
`);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(`, `)}
|
|
41
|
-
`)}const
|
|
42
|
-
`)}function
|
|
39
|
+
`,` `).replaceAll(`\r`,` `)}function pi(e){return Buffer.byteLength(fi(e),`utf8`)}const mi=Buffer.byteLength(`<bg-task-notifications batch-id="${`0`.repeat(26)}" delivered-at-ms="${`9`.repeat(13)}">\n\n</bg-task-notifications>`,`utf8`),hi=[`ptc_run_code`,`ptc_workflow`],gi=[`read`,`bash`,`edit`,`write`],_i=`ptc-mode`,vi=`ptc-mode`,yi=`ptc.json`,bi=`builtins-only`;function xi(){return{enabled:!1,base:void 0,ourLoadout:void 0}}function Si(e){let t=k(e,yi),n;try{n=T(t,`utf8`)}catch{return{defaultMode:!0,source:`default`}}let r;try{r=JSON.parse(n)}catch(e){return{defaultMode:!0,source:`invalid`,error:`${t} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof r!=`object`||!r||Array.isArray(r))return{defaultMode:!0,source:`invalid`,error:`${t} must contain a JSON object`};let i=r.defaultMode;return i===void 0?{defaultMode:!0,source:`default`}:typeof i==`boolean`?{defaultMode:i,source:`file`}:{defaultMode:!0,source:`invalid`,error:`${t}: "defaultMode" must be a boolean, received ${typeof i}`}}function Ci(e){return[...new Set(e)]}function wi(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 Ti(e,t){let n=e=>hi.includes(e);if(t===`all-but-ptc`)return Ci(e.filter(n));let r=new Set(V);return Ci(e.filter(e=>n(e)||!r.has(e)))}function Ei(e){let{mode:t,defaultMode:n,active:r,manual:i}=e;return t===`tui`?!n&&!i?{enter:!1,reason:`config-off`}:hi.some(e=>r.includes(e))?!i&&gi.filter(e=>!r.includes(e)).length>0?{enter:!1,reason:`restricted-session`}:{enter:!0,base:Ci(r),loadout:Ti(r,e.hide??`builtins-only`)}:{enter:!1,reason:`tools-unavailable`}:{enter:!1,reason:`not-tui`}}function Di(e,t){return e.enabled&&e.base!==void 0?e.base:t}function Oi(e,t){return!e.enabled||e.ourLoadout===void 0?!1:!wi(e.ourLoadout,t)}function ki(e,t){let n=t.length>0&&t.every(e=>hi.includes(e));return e?.enabled===!0&&n&&e.base!==void 0?{base:e.base,restoreFirst:!0}:{base:t,restoreFirst:!1}}function Ai(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(`
|
|
40
|
+
`);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(`
|
|
41
|
+
`)}const ji=[`read`,`bash`],Mi=`Use the read tool to load a skill's file when the task matches its description.`,Ni=`Use tools.read({ path }) inside a ptc_run_code program to load a skill's file when the task matches its description.`;function Pi(e){return!ji.some(t=>e.includes(t))}function Fi(e,t=v){let n=t([...e],`read`).trim();return n.length===0?``:n.includes(Mi)?n.replace(Mi,Ni):`${Ni}\n\n${n}`}const $=bi;function Ii(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: ${q(e).join(`, `)||`(none)`}.`,`Run /ptc off to restore the normal tool set.`].join(`
|
|
42
|
+
`)}function Li(e,t={}){let n=xi(),r=!1,i=new Vr,a=()=>Di(n,e.getActiveTools()),o=on(),s=sn(),c=t.backgroundRuntime??si(),l=!1,u=e=>{console.warn(`[pi-ptc.background] `+e)},d=t=>{if(t.length!==0){if(l){e.sendMessage({customType:`bg-task-notification`,content:t,display:!1},{deliverAs:`steer`});return}e.sendUserMessage(t)}},f=async e=>{let{items:t,acks:n}=await c.drainNotifications(e),r=t.filter(e=>li(e.record));for(let e of di(r))d(ui(e,{batchId:ve(),deliveredAtMs:c.clock()}));await c.acknowledgeNotifications(n)},p=async()=>{let e=await c.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]},m=async()=>{for(let e of await p())await f(e)},h=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 f(e)};c.pipeline.onIdleWake(e=>{f(e).catch(e=>{u(`notification delivery failed: `+(e instanceof Error?e.message:String(e)))})}),e.registerTool(Qn({getBindingSourceNames:a,getPool:()=>i.get(`run_code`),depth:o,...s===void 0?{}:{parentTaskId:s},getDispatchDeps:()=>c.dispatchDeps})),e.registerTool(ir({getBindingSourceNames:a,getPool:()=>i.get(`workflow`),depth:o,...s===void 0?{}:{parentTaskId:s},getDispatchDeps:()=>c.dispatchDeps})),e.registerTool(Fr(c.registry)),e.registerTool(Rr(c.registry,c.outputStorage)),e.registerTool(Br(c.registry,c.lifecycle,{clock:c.clock})),e.on(`turn_start`,async()=>{l=!0}),e.on(`agent_settled`,async()=>{l=!1;try{await m()}catch(e){u(`agent_settled delivery failed: `+(e instanceof Error?e.message:String(e)))}}),e.on(`turn_end`,async()=>{let e=i;i=new Vr,await e.drain()});let g=e=>{e.ui.setStatus(vi,n.enabled?e.ui.theme.fg(`accent`,`PTC`):void 0)},_=(t,i,a,o)=>{n.enabled=!0,n.base=t,n.ourLoadout=i,e.setActiveTools([...i]),r=!0,e.appendEntry(_i,{enabled:!0,base:[...t]}),g(a),a.ui.notify(o,`info`)},v=(t,i)=>{let a=n.base;n.enabled=!1,n.base=void 0,n.ourLoadout=void 0,r=!1,a!==void 0&&e.setActiveTools([...a]),e.appendEntry(i.customType,{enabled:!1}),g(t),i.announce&&t.ui.notify(`PTC mode off — built-in tools are directly callable again.`,`info`)},b=e=>{let t=e.sessionManager.getEntries();for(let e=t.length-1;e>=0;--e){let n=t[e];if(n?.type!==`custom`||n.customType!==`ptc-mode`)continue;let r=n.data,i=Array.isArray(r?.base)?r.base.filter(e=>typeof e==`string`):void 0;return{enabled:r?.enabled===!0,...i===void 0?{}:{base:i}}}};e.registerCommand(`ptc`,{description:`Show or toggle PTC mode (built-in tools reachable only from inside a PTC program)`,handler:async(t,r)=>{let i=t.trim().toLowerCase();if(i===`off`){if(!n.enabled){r.ui.notify(`PTC mode is already off.`,`info`);return}v(r,{announce:!0,customType:_i});return}if(i!==`on`){r.ui.notify(n.enabled?`PTC mode is ON — run /ptc off to restore built-in tools.\nBindings: ${q(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=Ei({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}_(a.base,a.loadout,r,Ii(a.base,$))}}),e.on(`session_start`,async(t,n)=>{l=!1;let r=await c.bindSession(n.sessionManager?.getSessionDir?.(),e=>n.ui.notify(e,`warning`));try{await h(r)}catch(e){u(`startup reconcile delivery failed: `+(e instanceof Error?e.message:String(e)))}let i=Si(y());i.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${i.error}`,`warning`);let a=b(n),{base:o,restoreFirst:s}=ki(a,e.getActiveTools());s&&e.setActiveTools([...o]);let d=Ei({mode:n.mode,defaultMode:i.defaultMode,active:o,manual:!1,hide:$}),f=a?.enabled??d.enter;if(d.enter&&f){_(o,d.loadout,n,Ii(o,$));return}g(n),!d.enter&&d.reason!==`not-tui`&&a===void 0&&d.reason===`restricted-session`&&n.ui.notify(`PTC mode skipped: this session was launched with an explicit tool restriction.`,`info`)}),e.on(`session_shutdown`,async()=>{l=!1;try{await c.shutdown(`session_ended_while_running`)}catch(e){u(`session shutdown failed: `+(e instanceof Error?e.message:String(e)))}});let x=!1,S=(e,t)=>{if(e===void 0)return;if(!n.enabled||!t){x&&=(delete e.sections.skills,!1);return}let r=Fi(e.skills);r.length!==0&&(e.sections.skills=r,x=!0)};e.on(`before_agent_start`,async(t,i)=>{let a=t.systemPromptOptions;if(S(a,Pi(e.getActiveTools())),n.enabled){if(Oi(n,e.getActiveTools())){v(i,{announce:!1,customType:_i}),S(a,Pi(e.getActiveTools())),i.ui.notify(`PTC mode off — another extension changed the active tool set.`,`warning`);return}if(r)return r=!1,{message:{customType:`ptc-mode-briefing`,content:Ai(q(n.base),$),display:!1}}}})}export{V as BUILTIN_BINDING_NAMES,Et as DEFAULT_BINDING_NAMES,z as DEFAULT_CONFIG,bi as DEFAULT_HIDE_STRATEGY,o as HOST_FRAME_KIND,qt as MAX_LINE_CHARS,gi as MODE_REQUIRED_TOOL_NAMES,n as PTC_ERROR_KIND,i as PTC_LOG_LEVEL,yi as PTC_MODE_CONFIG_FILE,_i as PTC_MODE_ENTRY_TYPE,vi as PTC_MODE_STATUS_KEY,hi as PTC_MODE_TOOL_NAMES,Ni as PTC_SKILL_LOAD_INSTRUCTION,ji as SKILL_READING_TOOL_NAMES,Vr as TurnPools,De as WORKER_ENV_ALLOW_LIST,t as WORKER_FRAME_KIND,Mt as WorkerPool,Di as bindingSource,Ai as buildModeInstruction,Fi as buildPtcSkillsSection,kt as createBuiltinBindings,Oe as createWorkerEnv,Ei as decideModeEntry,Li as default,Oi as detectExternalLoadoutChange,Ae as effectiveTimeoutMs,xi as initialModeState,Ti as modeLoadout,Si as readDefaultModeConfig,an as renderModelValue,ki as resolveBaseOnStart,ke as resolveConfig,Ht as runPtcProgram,wi as sameToolSet,K as sanitizeText,Pi as skillsSectionDropped,Yt as stripAnsi};
|
|
43
43
|
//# sourceMappingURL=index.js.map
|
package/dist/worker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{a as e,c as t}from"./protocol-CfOgxz3u.js";import{stripTypeScriptTypes as n}from"node:module";import{parentPort as r,workerData as i}from"node:worker_threads";import{inspect as a}from"node:util";function o(t){let n=t.protocol.hostFrame,r=t.protocol.workerFrame,i=t.protocol.logLevel,a=t.protocol.errorKind,o=`__ptcProgram`,s=`CREATED`,c=0,l,u,d=1,f=0,p=1/0,m=[],h=/* @__PURE__ */ new Map,g,_=()=>globalThis;class v extends Error{toolName;constructor(e,t){super(t),this.name=`ToolCallError`,this.toolName=e}}let y=e=>e instanceof Error?e.message:String(e),b=e=>{if(!(e instanceof Error)||typeof e.stack!=`string`)return;let t=e.stack.split(`
|
|
2
2
|
`),n=[t[0]??``];for(let e of t.slice(1))if(n.push(e),n.length>=6)break;return n.join(`
|
|
3
|
-
`)},x=(e,t=l)=>{if(!t)return!1;try{return t.postMessage(e),!0}catch{return!1}},S=(e,t,n)=>{x({kind:r.log,level:e,text:t},n)},C=(e,t,n,i)=>{x(n===void 0?{kind:r.error,error:{kind:e,message:t}}:{kind:r.error,error:{kind:e,message:t,stack:n}},i)},w=e=>{let t=/* @__PURE__ */ Error(e===`timeout`?`PTC run timed out`:`PTC run was cancelled`);return t.name=`AbortError`,t},T=()=>{let e=/* @__PURE__ */ Error(`the PTC control channel closed before the call completed`);return e.name=`AbortError`,e},E=async()=>{if(f<p){f+=1;return}await new Promise((e,t)=>{m.push({resolve:e,reject:t})})},D=()=>{let e=m.shift();if(e){e.resolve();return}--f},O=e=>{for(;m.length>0;){let t=m.shift();t&&t.reject(e)}},k=e=>{O(e);for(let[t,n]of h)h.delete(t),n.reject(e)},A=()=>{let e=t.workerData;if(typeof e!=`object`||!e)return;let n=e.env;if(typeof n!=`object`||!n||Array.isArray(n))return;let r=n;for(let e of Object.keys(process.env))e in r||delete process.env[e];for(let e of Object.keys(r)){let t=r[e];typeof t==`string`&&(process.env[e]=t)}},j=t=>{let n=/* @__PURE__ */ new Set,r=(t,i)=>{if(t===null)return{ok:!0,value:null};if(typeof t==`string`||typeof t==`boolean`)return{ok:!0,value:t};if(t===void 0)return{ok:!0,value:void 0};if(typeof t==`number`)return Number.isFinite(t)?{ok:!0,value:t}:{ok:!1,reason:`${i} is ${String(t)}, which is not representable as JSON`};if(typeof t!=`object`)return{ok:!1,reason:`${i} is ${e(t)}; results must be lossless JSON`};if(Array.isArray(t)){if(n.has(t))return{ok:!1,reason:`${i} is a circular reference`};n.add(t);let e=[];for(let n=0;n<t.length;n+=1){let a=r(t[n],`${i}[${n}]`);if(!a.ok)return a;e.push(a.value===void 0?null:a.value)}return n.delete(t),{ok:!0,value:e}}let a=Object.getPrototypeOf(t);if(a!==Object.prototype&&a!==null){let e=t.constructor;return{ok:!1,reason:`${i} is a ${e&&typeof e.name==`string`&&e.name.length>0?e.name:`an object`}; results must be plain JSON objects`}}if(n.has(t))return{ok:!1,reason:`${i} is a circular reference`};n.add(t);let o={};for(let e of Object.keys(t)){let n=r(t[e],`${i}.${e}`);if(!n.ok)return n;n.value!==void 0&&(o[e]=n.value)}return n.delete(t),{ok:!0,value:o}};return r(t,`result`)},M=e=>e.map(e=>typeof e==`string`?e:t.inspect(e,{depth:4,breakLength:1/0,colors:!1})).join(` `),N=e=>{let t=t=>(...n)=>{S(t,M(n),e)};_().console={log:t(i.log),info:t(i.info),warn:t(i.warn),error:t(i.error),debug:t(i.debug)}},P=()=>{typeof process.removeAllListeners==`function`&&typeof process.on==`function`&&(process.removeAllListeners(`warning`),process.on(`warning`,e=>{let t=typeof e==`object`&&e?e:void 0,n=t&&typeof t.name==`string`?t.name:`Warning`;if(n===`ExperimentalWarning`)return;let r=t&&typeof t.message==`string`?t.message:String(e);S(i.warn,`${n}: ${r}`)}))},F=e=>{let n=`async function ${o}() {\n${e}\n}`,r=n;try{r=t.stripTypes(n,{mode:`strip`})}catch{r=n}return Function(`${r}\nreturn ${o}();`)},I=async(e,t,n)=>{try{let t;try{t=F(e)}catch(e){C(a.exception,`program failed to compile: ${y(e)}`,b(e),n);return}try{let e=await t(),i=j(e);if(!i.ok){C(a.invalidOutput,i.reason,void 0,n);return}x(i.value===void 0?{kind:r.result}:{kind:r.result,value:i.value},n)}catch(e){C(u??a.exception,y(e),b(e),n)}}finally{await W(t,n)}},L=(e,t)=>async n=>{if(u)throw w(u);await E();try{if(u)throw w(u);let i=d;d+=1;let a=new Promise((e,t)=>{h.set(i,{resolve:e,reject:t})});if(!x({kind:r.call,callId:i,tool:e,args:n},t))throw h.delete(i),new v(e,`${e}() could not be called: the arguments are not transferable or the run has ended`);return await a}finally{D()}},R=e=>{let t=e.callId;if(typeof t!=`number`)return;let n=h.get(t);if(n){if(h.delete(t),e.ok===!0){n.resolve(e.value);return}n.reject(new v(typeof e.tool==`string`?e.tool:`unknown`,typeof e.message==`string`?e.message:`binding call failed`))}},z=e=>{u=e,k(w(e))},B=(e,t)=>{u=void 0;let n=w(e);C(e,n.message,void 0,t)},V=(e,t,n)=>{if(t>n)throw RangeError(`${e}() received ${t} items, exceeding maxItemsPerCall (${n})`)},H=(t,n,i)=>{let a=_();a.args=t===void 0?null:t,a.log=t=>{if(typeof t!=`string`)throw TypeError(`log(message) expects a string, received ${e(t)}`);x({kind:r.narration,message:t},i)},a.phase=t=>{if(typeof t!=`string`)throw TypeError(`phase(title) expects a string, received ${e(t)}`);x({kind:r.phase,title:t},i)},a.parallel=async t=>{if(!Array.isArray(t))throw TypeError(`parallel(thunks) expects an array of functions, received ${e(t)}`);V(`parallel`,t.length,n);for(let n=0;n<t.length;n+=1)if(typeof t[n]!=`function`)throw TypeError(`parallel(thunks) expects functions; item ${n} is ${e(t[n])}`);return await Promise.all(t.map(async e=>{try{return await e()}catch{return null}}))},a.pipeline=async(t,...r)=>{if(!Array.isArray(t))throw TypeError(`pipeline(items, ...stages) expects an array of items, received ${e(t)}`);if(V(`pipeline`,t.length,n),r.length===0)throw TypeError(`pipeline(items, ...stages) requires at least one stage function`);for(let t=0;t<r.length;t+=1)if(typeof r[t]!=`function`)throw TypeError(`pipeline(items, ...stages) expects stage functions; stage ${t} is ${e(r[t])}`);let i=r;return await Promise.all(t.map(async(e,t)=>{try{let n=e;for(let r of i)n=await r(n,e,t);return n}catch{return null}}))}},U=()=>{if(!g)return;let e=_();for(let t of Object.keys(e))g.has(t)||delete e[t];for(let[t,n]of g){let r=Object.getOwnPropertyDescriptor(e,t);if(r===void 0||r.writable!==!1)try{e[t]=n}catch{}}},W=async(e,t)=>{s===`RUNNING`&&e===c&&(k(T()),f=0,u=void 0,d=1,h.clear(),U(),A(),s=`READY`,x({kind:r.ready},t))},G=(e,t,n)=>{U(),u=void 0,f=0,h.clear(),A(),N(n),p=typeof e.maxPendingCalls==`number`&&Number.isFinite(e.maxPendingCalls)&&e.maxPendingCalls>0?e.maxPendingCalls:1/0;let r={},i=Array.isArray(e.bindings)?e.bindings.filter(e=>typeof e==`string`):[];for(let e of i)r[e]=L(e,n);let a=i.join(`, `)||`(none)`,o=Array.isArray(e.bindingCandidates)?e.bindingCandidates:[];for(let e of o)typeof e!=`string`||r[e]||(r[e]=async()=>{throw new v(e,`no binding named "${e}" in this run; available bindings: ${a}`)});if(_().tools=r,e.surface===`workflow`){let t=typeof e.maxItemsPerCall==`number`?e.maxItemsPerCall:0;H(e.args,t,n)}I(typeof e.code==`string`?e.code:``,t,n)},K=(e,t)=>{if(typeof e!=`object`||!e||Array.isArray(e))return;let r=e;if(r.kind===n.init){if(s!==`READY`)return;c+=1;let e=c;s=`RUNNING`,G(r,e,t);return}if(r.kind===n.callResult){R(r);return}if(r.kind===n.cancel){let e=r.reason===`timeout`?`timeout`:`abort`;if(s===`READY`){B(e,t);return}z(e)}};s=`BOOTING`,t.parentPort.on(`message`,e=>{if(typeof e!=`object`||!e)return;let t=e;if(t.kind!==n.connect)return;let i=t.port;if(typeof i!=`object`||!i||typeof i.on!=`function`)return;let a=i;l=a,a.on(`message`,e=>{K(e,a)}),a.on(`close`,()=>{l===a&&k(T())}),P();let o=g===void 0;if(o&&(g=new Map(Object.entries(_()))),s=`READY`,u!==void 0){if(o){B(u,a);return}u=void 0}x({kind:r.ready},a)})}o({parentPort:r,workerData:i,inspect:a,stripTypes:n,protocol:t()});export{};
|
|
3
|
+
`)},x=(e,t=l)=>{if(!t)return!1;try{return t.postMessage(e),!0}catch{return!1}},S=(e,t,n)=>{x({kind:r.log,level:e,text:t},n)},C=(e,t,n,i)=>{x(n===void 0?{kind:r.error,error:{kind:e,message:t}}:{kind:r.error,error:{kind:e,message:t,stack:n}},i)},w=e=>{let t=/* @__PURE__ */ Error(e===`timeout`?`PTC run timed out`:`PTC run was cancelled`);return t.name=`AbortError`,t},T=()=>{let e=/* @__PURE__ */ Error(`the PTC control channel closed before the call completed`);return e.name=`AbortError`,e},E=async()=>{if(f<p){f+=1;return}await new Promise((e,t)=>{m.push({resolve:e,reject:t})})},D=()=>{let e=m.shift();if(e){e.resolve();return}--f},O=e=>{for(;m.length>0;){let t=m.shift();t&&t.reject(e)}},k=e=>{O(e);for(let[t,n]of h)h.delete(t),n.reject(e)},A=()=>{let e=t.workerData;if(typeof e!=`object`||!e)return;let n=e.env;if(typeof n!=`object`||!n||Array.isArray(n))return;let r=n;for(let e of Object.keys(process.env))e in r||delete process.env[e];for(let e of Object.keys(r)){let t=r[e];typeof t==`string`&&(process.env[e]=t)}},j=t=>{let n=/* @__PURE__ */ new Set,r=(t,i)=>{if(t===null)return{ok:!0,value:null};if(typeof t==`string`||typeof t==`boolean`)return{ok:!0,value:t};if(t===void 0)return{ok:!0,value:void 0};if(typeof t==`number`)return Number.isFinite(t)?{ok:!0,value:t}:{ok:!1,reason:`${i} is ${String(t)}, which is not representable as JSON`};if(typeof t!=`object`)return{ok:!1,reason:`${i} is ${e(t)}; results must be lossless JSON`};if(Array.isArray(t)){if(n.has(t))return{ok:!1,reason:`${i} is a circular reference`};n.add(t);let e=[];for(let n=0;n<t.length;n+=1){let a=r(t[n],`${i}[${n}]`);if(!a.ok)return a;e.push(a.value===void 0?null:a.value)}return n.delete(t),{ok:!0,value:e}}let a=Object.getPrototypeOf(t);if(a!==Object.prototype&&a!==null){let e=t.constructor;return{ok:!1,reason:`${i} is a ${e&&typeof e.name==`string`&&e.name.length>0?e.name:`an object`}; results must be plain JSON objects`}}if(n.has(t))return{ok:!1,reason:`${i} is a circular reference`};n.add(t);let o={};for(let e of Object.keys(t)){let n=r(t[e],`${i}.${e}`);if(!n.ok)return n;n.value!==void 0&&(o[e]=n.value)}return n.delete(t),{ok:!0,value:o}};return r(t,`result`)},M=e=>e.map(e=>typeof e==`string`?e:t.inspect(e,{depth:4,breakLength:1/0,colors:!1})).join(` `),N=e=>{let t=t=>(...n)=>{S(t,M(n),e)};_().console={log:t(i.log),info:t(i.info),warn:t(i.warn),error:t(i.error),debug:t(i.debug)}},P=()=>{typeof process.removeAllListeners==`function`&&typeof process.on==`function`&&(process.removeAllListeners(`warning`),process.on(`warning`,e=>{let t=typeof e==`object`&&e?e:void 0,n=t&&typeof t.name==`string`?t.name:`Warning`;if(n===`ExperimentalWarning`)return;let r=t&&typeof t.message==`string`?t.message:String(e);S(i.warn,`${n}: ${r}`)}))},F=e=>{let n=`async function ${o}() {\n${e}\n}`,r=n;try{r=t.stripTypes(n,{mode:`strip`})}catch{r=n}return Function(`${r}\nreturn ${o}();`)},I=async(e,t,n)=>{try{let t;try{t=F(e)}catch(e){C(a.exception,`program failed to compile: ${y(e)}`,b(e),n);return}try{let e=await t(),i=j(e);if(!i.ok){C(a.invalidOutput,i.reason,void 0,n);return}x(i.value===void 0?{kind:r.result}:{kind:r.result,value:i.value},n)}catch(e){C(u??a.exception,y(e),b(e),n)}}finally{await W(t,n)}},L=(e,t)=>async n=>{if(u)throw w(u);await E();try{if(u)throw w(u);let i=d;d+=1;let a=new Promise((e,t)=>{h.set(i,{resolve:e,reject:t})});if(!x({kind:r.call,callId:i,tool:e,args:n},t))throw h.delete(i),new v(e,`${e}() could not be called: the arguments are not transferable or the run has ended`);return await a}finally{D()}},R=e=>{let t=e.callId;if(typeof t!=`number`)return;let n=h.get(t);if(n){if(h.delete(t),e.ok===!0){n.resolve(e.value);return}n.reject(new v(typeof e.tool==`string`?e.tool:`unknown`,typeof e.message==`string`?e.message:`binding call failed`))}},z=e=>{u=e,k(w(e))},B=(e,t)=>{u=void 0;let n=w(e);C(e,n.message,void 0,t)},V=(e,t,n)=>{if(t>n)throw RangeError(`${e}() received ${t} items, exceeding maxItemsPerCall (${n})`)},H=(t,n,i)=>{let a=_();a.args=t===void 0?null:t,a.log=t=>{if(typeof t!=`string`)throw TypeError(`log(message) expects a string, received ${e(t)}`);x({kind:r.narration,message:t},i)},a.phase=t=>{if(typeof t!=`string`)throw TypeError(`phase(title) expects a string, received ${e(t)}`);x({kind:r.phase,title:t},i)},a.parallel=async t=>{if(!Array.isArray(t))throw TypeError(`parallel(thunks) expects an array of functions, received ${e(t)}`);V(`parallel`,t.length,n);for(let n=0;n<t.length;n+=1)if(typeof t[n]!=`function`)throw TypeError(`parallel(thunks) expects functions; item ${n} is ${e(t[n])}`);return await Promise.all(t.map(async e=>{try{return await e()}catch{return null}}))},a.pipeline=async(t,...r)=>{if(!Array.isArray(t))throw TypeError(`pipeline(items, ...stages) expects an array of items, received ${e(t)}`);if(V(`pipeline`,t.length,n),r.length===0)throw TypeError(`pipeline(items, ...stages) requires at least one stage function`);for(let t=0;t<r.length;t+=1)if(typeof r[t]!=`function`)throw TypeError(`pipeline(items, ...stages) expects stage functions; stage ${t} is ${e(r[t])}`);let i=r;return await Promise.all(t.map(async(e,t)=>{try{let n=e;for(let r of i)n=await r(n,e,t);return n}catch{return null}}))}},U=()=>{if(!g)return;let e=_();for(let t of Object.keys(e))g.has(t)||delete e[t];for(let[t,n]of g){let r=Object.getOwnPropertyDescriptor(e,t);if(r===void 0||r.writable!==!1)try{e[t]=n}catch{}}},W=async(e,t)=>{s===`RUNNING`&&e===c&&(k(T()),f=0,u=void 0,d=1,h.clear(),U(),A(),s=`READY`,x({kind:r.ready},t))},G=(e,t,n)=>{U(),u=void 0,f=0,h.clear(),A(),N(n),p=typeof e.maxPendingCalls==`number`&&Number.isFinite(e.maxPendingCalls)&&e.maxPendingCalls>0?e.maxPendingCalls:1/0;let r={},i=Array.isArray(e.bindings)?e.bindings.filter(e=>typeof e==`string`):[];for(let e of i)r[e]=L(e,n);let a=i.join(`, `)||`(none)`,o=Array.isArray(e.bindingCandidates)?e.bindingCandidates:[];for(let e of o)typeof e!=`string`||r[e]||(r[e]=async()=>{throw new v(e,`no binding named "${e}" in this run; available bindings: ${a}`)});if(_().tools=r,_().ptcBindings=Object.freeze([...i]),e.surface===`workflow`){let t=typeof e.maxItemsPerCall==`number`?e.maxItemsPerCall:0;H(e.args,t,n)}I(typeof e.code==`string`?e.code:``,t,n)},K=(e,t)=>{if(typeof e!=`object`||!e||Array.isArray(e))return;let r=e;if(r.kind===n.init){if(s!==`READY`)return;c+=1;let e=c;s=`RUNNING`,G(r,e,t);return}if(r.kind===n.callResult){R(r);return}if(r.kind===n.cancel){let e=r.reason===`timeout`?`timeout`:`abort`;if(s===`READY`){B(e,t);return}z(e)}};s=`BOOTING`,t.parentPort.on(`message`,e=>{if(typeof e!=`object`||!e)return;let t=e;if(t.kind!==n.connect)return;let i=t.port;if(typeof i!=`object`||!i||typeof i.on!=`function`)return;let a=i;l=a,a.on(`message`,e=>{K(e,a)}),a.on(`close`,()=>{l===a&&k(T())}),P();let o=g===void 0;if(o&&(g=new Map(Object.entries(_()))),s=`READY`,u!==void 0){if(o){B(u,a);return}u=void 0}x({kind:r.ready},a)})}o({parentPort:r,workerData:i,inspect:a,stripTypes:n,protocol:t()});export{};
|
|
4
4
|
//# sourceMappingURL=worker.js.map
|