pi-ptc-subagents 1.3.0 → 1.4.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 +34 -0
- package/README.md +56 -23
- package/dist/index.d.ts +68 -2
- package/dist/index.js +43 -41
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.4.0] - 2026-10-03
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`/ptc surface off|subagents|full` switches the extension surface without a new session.** The
|
|
15
|
+
surface was configurable only by hand-editing `~/.pi/agent/ptc.json` and restarting, because it is
|
|
16
|
+
read once in the extension factory and pi has no way to unregister a tool. The new subcommand
|
|
17
|
+
writes the key and then performs pi's own `/reload`, which clears pi's extension cache and
|
|
18
|
+
re-runs every factory — the same path the built-in takes, from inside the extension. A malformed
|
|
19
|
+
`ptc.json` is reported and left byte-for-byte alone, `defaultMode` in the same file survives, and
|
|
20
|
+
setting the value that is already there writes nothing and does not reload
|
|
21
|
+
([ADR-0030](./docs/adr/0030-surface-switch-reloads.md)).
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- **A default pi session no longer starts with no orchestration tool at all.** The detected surface
|
|
26
|
+
followed two questions — does this pi ship a `codemode` directory, and will pi load it — and on a
|
|
27
|
+
stock pi 1.0.0 install the answer to both is yes, so the surface resolved to `subagents`. But pi
|
|
28
|
+
registers `codemode` with `defaultActive: false`: it joins the model's tool list only when a
|
|
29
|
+
loadout names it, and a session that configured nothing has no such loadout. Since the
|
|
30
|
+
`subagents` surface deliberately does not register `ptc_run_code`, the result was a session
|
|
31
|
+
holding `ptc_subagent` and three `ptc_task_*` tools with no way to compose any of them, plus a
|
|
32
|
+
startup warning on **every** session. The detection now asks a third question — whether `codemode`
|
|
33
|
+
will actually be in the tool list, read from `--tools` and from `defaultTools` in the project and
|
|
34
|
+
user settings the way pi resolves them — and `subagents` is chosen only on positive evidence that
|
|
35
|
+
the model can call the tool. The default on an unconfigured install is now `full`, with no
|
|
36
|
+
warning. To opt into `subagents`, add `codemode` to `defaultTools` or `--tools`
|
|
37
|
+
([ADR-0029](./docs/adr/0029-surface-follows-codemode-activation.md)).
|
|
38
|
+
- **The "pi does not register codemode" startup notice no longer hard-codes the wrong surface.** With
|
|
39
|
+
a fifth cell in the table, the detected surface is not always `subagents` in that branch, and the
|
|
40
|
+
message named `SurfaceModeConfig.detected` — a field populated only when an explicit `surfaceMode`
|
|
41
|
+
overrode detection, so on the very path the notice fires from it would have printed `undefined`.
|
|
42
|
+
It reports the surface the session actually built.
|
|
43
|
+
|
|
10
44
|
## [1.3.0] - 2026-10-02
|
|
11
45
|
|
|
12
46
|
### Fixed
|
package/README.md
CHANGED
|
@@ -201,8 +201,12 @@ the session. The mode's rationale and rejected alternatives are in [ADR-0010](./
|
|
|
201
201
|
```
|
|
202
202
|
|
|
203
203
|
**Choosing the surface.** `defaultMode` decides whether the session _enters_ PTC mode; `surfaceMode`
|
|
204
|
-
decides which model-facing tools this package registers at all
|
|
205
|
-
|
|
204
|
+
decides which model-facing tools this package registers at all ([ADR-0025](./docs/adr/0025-extension-surface-is-a-setting.md)):
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
/ptc surface # report the current surface and where it came from
|
|
208
|
+
/ptc surface subagents # write the key and reload so it applies now
|
|
209
|
+
```
|
|
206
210
|
|
|
207
211
|
```jsonc
|
|
208
212
|
// ~/.pi/agent/ptc.json
|
|
@@ -214,31 +218,60 @@ surface change needs a new session ([ADR-0025](./docs/adr/0025-extension-surface
|
|
|
214
218
|
doing the orchestration; warns at startup when `codemode` is not in the active tool set.
|
|
215
219
|
- `full` — today's set: `ptc_run_code` / `ptc_workflow` plus the three `ptc_task_*` tools.
|
|
216
220
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
221
|
+
The command exists because the alternative is editing JSON by hand and starting a new session: the
|
|
222
|
+
surface is read once in the extension factory and pi has no way to unregister a tool, so a change
|
|
223
|
+
cannot apply in place. `/ptc surface` writes the key and then performs pi's own `/reload`, which
|
|
224
|
+
re-runs every extension factory ([ADR-0030](./docs/adr/0030-surface-switch-reloads.md)). Two things
|
|
225
|
+
it will not do silently: a malformed `ptc.json` is reported and left exactly as it was, and an
|
|
226
|
+
unchanged value does not reload — a reload replaces every extension instance in the session, so
|
|
227
|
+
retyping the value you already have costs you in-flight state for nothing. Switching to
|
|
228
|
+
`subagents` or `off` also ends a running PTC mode, which the command says before it does it.
|
|
229
|
+
|
|
230
|
+
**The default is detected, and it follows three questions, not one**
|
|
231
|
+
([ADR-0026](./docs/adr/0026-surface-default-is-detected.md),
|
|
232
|
+
[ADR-0027](./docs/adr/0027-codemode-switch-decides-surface.md),
|
|
233
|
+
[ADR-0029](./docs/adr/0029-surface-follows-codemode-activation.md)). With no `surfaceMode` key:
|
|
234
|
+
|
|
235
|
+
| does this pi ship `codemode`? | will pi load it? | can the model call it? | surface |
|
|
236
|
+
| ----------------------------- | ---------------------------------------------- | --------------------------------------------- | ----------- |
|
|
237
|
+
| yes | yes (default, or `+builtin:codemode`) | yes (`--tools …,codemode`, or `defaultTools`) | `subagents` |
|
|
238
|
+
| yes | yes (default, or `+builtin:codemode`) | no — **the default on a stock install** | `full` |
|
|
239
|
+
| yes | no (`-builtin:codemode`, or `--no-extensions`) | — | `full` |
|
|
240
|
+
| no | — | — | `full` |
|
|
241
|
+
|
|
242
|
+
The third column is the one that decides most sessions, and it is why the default is `full` on a pi
|
|
243
|
+
that has never been configured. pi ships `codemode` and loads it by default, but registers it
|
|
244
|
+
**inactive** (`defaultActive: false`) — it joins the model's tool list only when a loadout names it.
|
|
245
|
+
Handing orchestration to a tool the model cannot call is the failure this avoids, so `subagents` is
|
|
246
|
+
chosen only on positive evidence.
|
|
226
247
|
|
|
227
248
|
Setting the key always wins. A probe that cannot answer falls back to `full` — the safe direction,
|
|
228
249
|
since `subagents` as a failure mode would take away the orchestration tool the session was relying
|
|
229
250
|
on.
|
|
230
251
|
|
|
231
|
-
>
|
|
232
|
-
>
|
|
233
|
-
>
|
|
234
|
-
>
|
|
252
|
+
> **To use the `subagents` surface, put `codemode` in your tool list.** Without that you get
|
|
253
|
+
> `ptc_run_code` / `ptc_workflow` and no startup warning, which is the correct answer for a session
|
|
254
|
+
> that never asked for delegation:
|
|
255
|
+
>
|
|
256
|
+
> ```jsonc
|
|
257
|
+
> // ~/.pi/agent/settings.json
|
|
258
|
+
> { "defaultTools": ["read", "bash", "edit", "write", "+codemode"] }
|
|
259
|
+
> ```
|
|
260
|
+
>
|
|
261
|
+
> or per launch, `pi --tools read,bash,edit,write,codemode`. A list made only of modifiers starts
|
|
262
|
+
> from pi's four defaults, so `{ "defaultTools": ["+codemode"] }` means the same thing. If you would
|
|
263
|
+
> rather pin the surface regardless of what pi is doing, set `{ "surfaceMode": "subagents" }` —
|
|
264
|
+
> and note that pinning it does not activate `codemode`, so a pinned `subagents` on a session that
|
|
265
|
+
> never configured it still warns, by design ([ADR-0025](./docs/adr/0025-extension-surface-is-a-setting.md)
|
|
266
|
+
> decision 4).
|
|
235
267
|
|
|
236
268
|
> Turning pi's `codemode` **off** — `"extensions": ["-builtin:codemode"]`, or launching with
|
|
237
269
|
> `--no-extensions` — brings the PTC surfaces back on its own. Before ADR-0027 it did not: the
|
|
238
270
|
> detection asked only whether the extension directory exists, so a pi told not to load it still
|
|
239
271
|
> counted as an orchestrator and you got `ptc_subagent` with nothing to compose with. The switch is
|
|
240
272
|
> read from the same three places pi reads it — the command line, `<cwd>/.pi/settings.json`, and
|
|
241
|
-
> `<agentDir>/settings.json` — in the same order
|
|
273
|
+
> `<agentDir>/settings.json` — in the same order, and the activation probe reads the first two plus
|
|
274
|
+
> `--tools`.
|
|
242
275
|
|
|
243
276
|
No file, or a value outside that set, falls back to the detected default and says so at startup
|
|
244
277
|
rather than half-applying: which tools exist is not something to change on a guess.
|
|
@@ -246,13 +279,13 @@ rather than half-applying: which tools exist is not something to change on a gue
|
|
|
246
279
|
**A detection you cannot see is the failure this design has**, so the result is reported. With no
|
|
247
280
|
`surfaceMode` key, the outcome is issued through the TUI notification channel at session start —
|
|
248
281
|
how the probe came out and which surface the default therefore is — but only when the probe could
|
|
249
|
-
not answer. A pi that ships `codemode
|
|
250
|
-
nothing. A second notice is issued when the probe and pi's own tool registry disagree, which
|
|
251
|
-
case the probe structurally cannot see: it walks the filesystem, so under
|
|
252
|
-
it answers `present` for a tool this session does not have (and the
|
|
253
|
-
answers `not-found` for one pi plainly registers). A third notice
|
|
254
|
-
that could not be read, and an explicit `surfaceMode` that
|
|
255
|
-
value still wins, and the notice only says so. What is **not**
|
|
282
|
+
not answer. A pi that ships `codemode`, loads it, and has it in the tool list is the expected case
|
|
283
|
+
and says nothing. A second notice is issued when the probe and pi's own tool registry disagree, which
|
|
284
|
+
is the case the probe structurally cannot see: it walks the filesystem, so under
|
|
285
|
+
`--exclude-tools codemode` it answers `present` for a tool this session does not have (and the
|
|
286
|
+
mirror: a restructured `dist` answers `not-found` for one pi plainly registers). A third notice
|
|
287
|
+
covers ADR-0027: a settings file that could not be read, and an explicit `surfaceMode` that
|
|
288
|
+
disagrees with the table — the pinned value still wins, and the notice only says so. What is **not**
|
|
256
289
|
established is that either line actually paints in a real pi TUI: a pty capture at review time
|
|
257
290
|
showed neither the notice nor a control marker, and a TUI quits on stdin EOF before a toast
|
|
258
291
|
renders, so that is an unmeasured end to end rather than a broken one. No test in this repository
|
package/dist/index.d.ts
CHANGED
|
@@ -556,7 +556,7 @@ export declare function readDefaultModeConfig(agentDir: string): DefaultModeConf
|
|
|
556
556
|
* orchestration question back to pi, `subagents` keeps only the subagent face and lets pi's
|
|
557
557
|
* `codemode` orchestrate, `full` keeps today's set.
|
|
558
558
|
*/
|
|
559
|
-
declare const SURFACE_MODES: readonly ["off", "subagents", "full"];
|
|
559
|
+
export declare const SURFACE_MODES: readonly ["off", "subagents", "full"];
|
|
560
560
|
type SurfaceMode = (typeof SURFACE_MODES)[number];
|
|
561
561
|
/**
|
|
562
562
|
* Whether the pi that launched us will actually LOAD its `codemode` extension.
|
|
@@ -602,6 +602,38 @@ export declare function resolveCodemodeSwitch(argv: readonly string[], projectSe
|
|
|
602
602
|
* `join(this.cwd, CONFIG_DIR_NAME)` and `this.agentDir`.
|
|
603
603
|
*/
|
|
604
604
|
export declare function readCodemodeSwitch(agentDir: string, cwd: string, argv?: readonly string[]): CodemodeSwitchResolution;
|
|
605
|
+
/**
|
|
606
|
+
* Whether `codemode` will be CALLABLE, as a third question distinct from whether pi ships the
|
|
607
|
+
* directory (ADR-0026) and whether it will load the extension (ADR-0027).
|
|
608
|
+
*
|
|
609
|
+
* - `"active"` — a loadout names it, so the model can call it.
|
|
610
|
+
* - `"inactive"` — nothing names it, which on a real install is the DEFAULT: pi registers
|
|
611
|
+
* `codemode` with `defaultActive: false` and activates it only when a loadout says so.
|
|
612
|
+
*
|
|
613
|
+
* `"inactive"` is what every failure of this probe on the positive side resolves to, and that is
|
|
614
|
+
* the design rather than a fallback: `subagents` is chosen only on positive evidence that the tool
|
|
615
|
+
* is callable. See ADR-0029, "The bound that makes the weaker guarantee sufficient".
|
|
616
|
+
*/
|
|
617
|
+
type CodemodeActivation = "active" | "inactive";
|
|
618
|
+
/** How the answer was decided, so a test can tell a configured answer from pi's default. */
|
|
619
|
+
type CodemodeActivationSource = "cli" | "project" | "user" | "default" | "invalid";
|
|
620
|
+
/** The answer plus enough provenance to explain it in a notice. */
|
|
621
|
+
interface CodemodeActivationResolution {
|
|
622
|
+
activation: CodemodeActivation;
|
|
623
|
+
source: CodemodeActivationSource;
|
|
624
|
+
/** Set when a settings file could not be read as a JSON object; the answer still resolves. */
|
|
625
|
+
error?: string;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Resolve whether `codemode` will be in the model's tool list, in the order pi resolves the
|
|
629
|
+
* loadout: the command-line allowlist, then the merged `defaultTools`, then pi's own default.
|
|
630
|
+
*
|
|
631
|
+
* The last of those is the load-bearing one and is what makes absence of evidence mean
|
|
632
|
+
* `inactive`: pi registers `codemode` inactive, so a session that configured nothing does not get
|
|
633
|
+
* it, and delegating orchestration to a tool the model cannot call is the failure this exists to
|
|
634
|
+
* prevent.
|
|
635
|
+
*/
|
|
636
|
+
export declare function resolveCodemodeActivation(argv: readonly string[], projectSettings: unknown, userSettings: unknown): CodemodeActivationResolution;
|
|
605
637
|
/**
|
|
606
638
|
* Whether an explicit `surfaceMode` disagrees with what the table above decided.
|
|
607
639
|
*
|
|
@@ -656,6 +688,11 @@ interface SurfaceModeConfig {
|
|
|
656
688
|
* {@link codemode}: an explicit key short-circuits the probe, so there is nothing to report.
|
|
657
689
|
*/
|
|
658
690
|
codemodeSwitch?: CodemodeSwitchResolution;
|
|
691
|
+
/**
|
|
692
|
+
* Whether `codemode` will be in the model's tool list (ADR-0029), the third axis of the
|
|
693
|
+
* detected table. Absent for the same reason as {@link codemodeSwitch}.
|
|
694
|
+
*/
|
|
695
|
+
codemodeActivation?: CodemodeActivationResolution;
|
|
659
696
|
/**
|
|
660
697
|
* What the four-case table decided, carried even when an explicit key overrode it — that
|
|
661
698
|
* difference is exactly what {@link surfaceModeConflict} reports on.
|
|
@@ -679,7 +716,36 @@ interface SurfaceModeConfig {
|
|
|
679
716
|
* short-circuits, where the user paid a `realpathSync` plus up to three `statSync` and two
|
|
680
717
|
* settings reads to set one line of JSON and get a constant.
|
|
681
718
|
*/
|
|
682
|
-
export declare function readSurfaceModeConfig(agentDir: string, presence?: CodemodePresence, codemodeSwitch?: CodemodeSwitchResolution, cwd?: string): SurfaceModeConfig;
|
|
719
|
+
export declare function readSurfaceModeConfig(agentDir: string, presence?: CodemodePresence, codemodeSwitch?: CodemodeSwitchResolution, codemodeActivation?: CodemodeActivationResolution, cwd?: string): SurfaceModeConfig;
|
|
720
|
+
/** Outcome of writing `surfaceMode` for `/ptc surface`. */
|
|
721
|
+
type SurfaceModeWrite = {
|
|
722
|
+
ok: true;
|
|
723
|
+
path: string;
|
|
724
|
+
/** The value already in the file, or `undefined` when there was none. */
|
|
725
|
+
previous: SurfaceMode | undefined;
|
|
726
|
+
/** False when the file already said this, in which case NOTHING was written. */
|
|
727
|
+
changed: boolean;
|
|
728
|
+
} | {
|
|
729
|
+
ok: false;
|
|
730
|
+
path: string;
|
|
731
|
+
error: string;
|
|
732
|
+
};
|
|
733
|
+
/**
|
|
734
|
+
* Write one `surfaceMode` key into the agent-dir config, preserving every other key.
|
|
735
|
+
*
|
|
736
|
+
* Three rules, each of which is a way a naive rewrite goes wrong:
|
|
737
|
+
*
|
|
738
|
+
* - **A malformed file is never overwritten.** An unparseable `ptc.json` is a file the user may
|
|
739
|
+
* be mid-edit on, and this command is not a licence to replace it with something valid that
|
|
740
|
+
* drops whatever was in it. The read side already reports that shape rather than acting on it
|
|
741
|
+
* ({@link readSurfaceModeConfig}), and the write side has to agree.
|
|
742
|
+
* - **Other keys survive.** `defaultMode` lives in the same file (ADR-0010), and a command that
|
|
743
|
+
* wrote `{"surfaceMode": …}` wholesale would silently reset the user's mode preference.
|
|
744
|
+
* - **An unchanged value writes nothing.** `/ptc surface full` on a session already at `full`
|
|
745
|
+
* should not touch the file's mtime, and — more to the point — should not trigger the reload
|
|
746
|
+
* that would follow, since a reload replaces every extension instance for no reason.
|
|
747
|
+
*/
|
|
748
|
+
export declare function setSurfaceMode(agentDir: string, value: unknown): SurfaceModeWrite;
|
|
683
749
|
/** Why the mode declined to turn on. Surfaced in the entry notification / debug logs. */
|
|
684
750
|
type ModeBlockReason = "not-tui" | "config-off" | "tools-unavailable" | "restricted-session";
|
|
685
751
|
/** Either the loadout to apply, or the reason the mode stayed off. */
|
package/dist/index.js
CHANGED
|
@@ -1,47 +1,49 @@
|
|
|
1
|
-
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./protocol-CfOgxz3u.js";import{DEFAULT_MAX_BYTES as s,DEFAULT_MAX_LINES as c,createBashTool as l,createEditTool as u,createFindTool as d,createGrepTool as f,createLsTool as p,createReadTool as m,createWriteTool as h,defineTool as g,formatSize as _,formatSkillsForPrompt as v,getAgentDir as y,truncateTail as b}from"@earendil-works/pi-coding-agent";import{Type as x}from"typebox";import{validateToolArguments as S}from"@earendil-works/pi-ai";import*as C from"node:fs";import{existsSync as w,readFileSync as T,realpathSync as ee,statSync as
|
|
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||Ae(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;Oe(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): `+Ne(t))}};const L=Object.freeze({timeoutMs:12e4,maxTimeoutMs:6e5,maxOutputBytes:67108864,maxMessageBytes:134217728,maxPendingCalls:128,maxParallelSubCalls:10,dispatchConcurrency:8,maxDispatchDepth:3,maxItemsPerCall:4096,graceMs:3e3,maxOldGenerationSizeMb:512,maxYoungGenerationSizeMb:64,poolSize:4,poolAcquireTimeoutMs:3e4,drainGraceMs:5e3}),Fe=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function Ie(e=process.env){let t={};for(let n of Fe){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function Le(e={}){let t={...L};for(let n of Object.keys(L)){let r=e[n];if(r!==void 0){if(typeof r!=`number`||!Number.isFinite(r)||r<=0)throw TypeError(`invalid PTC config override for ${n}: ${String(r)}`);t[n]=r}}return t}function Re(e,t=L){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const ze={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},Be=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),Ve=/* @__PURE__ */ new Set([`running`,`stopping`]);function He(e,t,n,r){if(n!==`canceled`&&n!==`succeeded`){if(t.childError!==void 0)return t.childError;if(t.exitCode===0&&!r)return`dispatch produced no final text`}}function Ue(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function We(e){return typeof e==`string`&&e.length>0}const Ge=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function Ke(e){return typeof e==`string`&&Ge.has(e)}function qe(e,t){return e.ownerPid===t.pid&&e.ownerBootMs===t.bootMs}function Je(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 Ye(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var Xe=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??Je,this.#a=we({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 We(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())Ve.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=We(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(!Ue(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`&&!Ke(e.reason))throw Error(`transition: to "lost" requires a LostReason (session_ended_while_running | user_killed_via_esc | lost_on_session_restart)`+(e.reason===void 0?``:`, got ${String(e.reason)}`));return this.#m(n,e.to,t,{reason:e.reason,stopReason:e.stopReason,errorMessage:e.errorMessage,exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview})}async#d(e,t){let n=await this.#y(e.taskId);return n.status===`stopping`?{record:n,events:[],cursor:(await this.#e.loadSubscription(t.callerId,n.id))?.cursor??n.id,fromStatus:n.status}:(this.#v(n,`stopping`),this.#m(n,`stopping`,t,{stopReason:e.reason}))}async#f(e,t){let n=await this.#y(e.taskId);if(n.status!==`running`&&n.status!==`stopping`)throw Error(`resolve-exit: task ${n.id} is terminal (${n.status}); the single terminal writer refuses to overwrite it`);let r=(e.outputBytes??0)>0,i=n.status===`stopping`?`canceled`:e.exitCode===0&&r?`succeeded`:`failed`;return this.#v(n,i),this.#m(n,i,t,{exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview,errorMessage:He(n,e,i,r)})}async#p(e,t){let n=await this.#y(e.taskId);if(!Ve.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};Be.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=ze[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(!We(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:Ye(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 Ze(e,t){return new Xe(e,t)}function Qe(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function $e(e){for(let t=1;t<e.length;t++)if(Qe(e[t-1],e[t])>0)return!1;return!0}var et=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=$e(t)?[...t]:[...t].sort(Qe),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(Qe),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 tt=new Pe;var nt=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 rt=new nt(L.dispatchConcurrency);let it;function at(e,t){return e.taskRegistry===void 0?(it??=new Xe(new et,{clock:t}),it):e.taskRegistry}const ot={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}};function st(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,realpathSync as ee,statSync as E,writeFileSync as te}from"node:fs";import*as ne from"node:os";import{tmpdir as re}from"node:os";import*as D from"node:path";import{basename as ie,dirname as ae,join as O,relative as k,resolve as A,sep as j}from"node:path";import{spawn as oe}from"node:child_process";import{randomBytes as se,randomUUID as M}from"node:crypto";import{ok as N}from"node:assert/strict";import{MessageChannel as ce,Worker as le}from"node:worker_threads";import ue from"node:diagnostics_channel";import{fileURLToPath as de,pathToFileURL as fe}from"node:url";import{truncateToWidth as P,visibleWidth as F}from"@earendil-works/pi-tui";import{appendFile as pe,mkdir as me,readFile as he,readdir as ge,rename as _e,unlink as ve,writeFile as ye}from"node:fs/promises";import{minimatch as be}from"minimatch";const xe=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`;function Se(e){let t=``,n=Math.max(0,Math.floor(e));for(let e=0;e<10;e++)t=(xe[n%32]??`0`)+t,n=Math.floor(n/32);return t}function Ce(e){let t=``,n=0,r=0;for(let i=0;i<e.length&&t.length<16;i++)for(n=n<<8|(e[i]??0),r+=8;r>=5&&t.length<16;)r-=5,t+=xe[n>>>r&31];return t.padEnd(16,`0`)}function we(e){let t=new Uint8Array(e);for(let e=t.length-1;e>=0;e--){if((t[e]??0)<255)return t[e]=(t[e]??0)+1,t;t[e]=0}return t}function Te(e){let t=e.randomBytes??(e=>new Uint8Array(se(e))),n=-1,r=/* @__PURE__ */ new Uint8Array(10);return{next(){let i=Math.max(0,Math.floor(e.now())),a=i>n?i:n,o=a===n?we(r):t(10);return n=a,r=o,Se(a)+Ce(o)}}}const Ee=Te({now:()=>Date.now()});function De(){return Ee.next()}function Oe(e){let t=e.trim();if(t.length===0)return null;try{return JSON.parse(t)}catch{return null}}function ke(e,t){if(e.pid===void 0)return!1;try{return e.kill(t),!0}catch{return!1}}function Ae(e,t){if(e.eventWaiters.length>0){let n=e.eventWaiters.shift();n&&n(t);return}e.events.push(t)}function je(e,t){if(e.exited)return;e.exited=!0,e.exitValue=t;for(let n of e.exitWaiters)n(t);e.exitWaiters=[];let n=e.eventWaiters;e.eventWaiters=[];for(let e of n)e(null);for(let t of e.stderrWaiters)t(e.stderr);e.stderrWaiters=[]}function Me(e,t){let n=t.sessionDir===void 0?[...e]:e.filter(e=>e!==`--no-session`);return t.sessionDir!==void 0&&(n.push(`--session-dir`,t.sessionDir),t.sessionId!==void 0&&n.push(`--session-id`,t.sessionId),t.sessionName!==void 0&&n.push(`--name`,t.sessionName)),n}const Ne={warn:e=>{console.warn(`[pi-ptc.lifecycle] `+e)}};function Pe(e){return e.length<=200?e:e.slice(0,200)+`…`}var Fe=class{#e;constructor(e={}){this.#e=e.logger??Ne}spawn(e,t){if(e.length===0)throw TypeError(`RealChildProcessLifecycle.spawn: argv must include the command`);let n=Me(e,t),r=n[0],i=n.slice(1),a=oe(r,i,{cwd:t.cwd,shell:!1,stdio:[`ignore`,`pipe`,`pipe`],env:t.env}),o={proc:a,events:[],eventWaiters:[],exited:!1,exitValue:null,stderrWaiters:[],exitWaiters:[],stderr:``,lineBuffer:``},s={id:De(),opaque:o},c=a.stdout;c&&c.on(`data`,e=>{o.lineBuffer+=e.toString(`utf-8`);let t=o.lineBuffer.indexOf(`
|
|
2
|
+
`);for(;t>=0;){let e=o.lineBuffer.slice(0,t);o.lineBuffer=o.lineBuffer.slice(t+1);let n=Oe(e);n?Ae(o,n):e.trim().length>0&&this.#t(s,e),t=o.lineBuffer.indexOf(`
|
|
3
|
+
`)}});let l=a.stderr;return l&&l.on(`data`,e=>{o.stderr+=e.toString(`utf-8`)}),a.on(`close`,(e,t)=>{let n=o.lineBuffer.trim();if(n.length>0){let e=Oe(n);e?Ae(o,e):this.#t(s,n),o.lineBuffer=``}je(o,{code:e,signal:t})}),a.on(`error`,e=>{o.stderr+=`[spawn-error] `+e.message+`
|
|
4
|
+
`,o.exited||je(o,{code:null,signal:null})}),s}kill(e,t){let n=e.opaque;ke(n.proc,t)}events(e){let t=e.opaque;return{async*[Symbol.asyncIterator](){for(;;){if(t.events.length>0){let e=t.events.shift();e!==void 0&&(yield e);continue}if(t.exited)return;let e=await new Promise(e=>{t.eventWaiters.push(e)});if(e===null)return;yield e}}}}exit(e){let t=e.opaque;return t.exited&&t.exitValue?Promise.resolve(t.exitValue):new Promise(e=>{t.exitWaiters.push(e)})}stderr(e){let t=e.opaque;return t.exited?Promise.resolve(t.stderr):new Promise(e=>{t.stderrWaiters.push(e)})}#t(e,t){this.#e.warn(`child ${e.id}: dropped a non-JSON stdout line (${t.length} chars): `+Pe(t))}};const I=Object.freeze({timeoutMs:12e4,maxTimeoutMs:6e5,maxOutputBytes:67108864,maxMessageBytes:134217728,maxPendingCalls:128,maxParallelSubCalls:10,dispatchConcurrency:8,maxDispatchDepth:3,maxItemsPerCall:4096,graceMs:3e3,maxOldGenerationSizeMb:512,maxYoungGenerationSizeMb:64,poolSize:4,poolAcquireTimeoutMs:3e4,drainGraceMs:5e3}),Ie=Object.freeze([`PATH`,`PATHEXT`,`SYSTEMROOT`,`WINDIR`,`TEMP`,`TMP`]);function Le(e=process.env){let t={};for(let n of Ie){let r=e[n];typeof r==`string`&&r.length>0&&(t[n]=r)}return t}function Re(e={}){let t={...I};for(let n of Object.keys(I)){let r=e[n];if(r!==void 0){if(typeof r!=`number`||!Number.isFinite(r)||r<=0)throw TypeError(`invalid PTC config override for ${n}: ${String(r)}`);t[n]=r}}return t}function ze(e,t=I){return e===void 0||!Number.isFinite(e)||e<=0?t.timeoutMs:Math.min(e,t.maxTimeoutMs)}const Be={running:[`stopping`,`succeeded`,`failed`,`canceled`,`lost`],stopping:[`succeeded`,`failed`,`canceled`],succeeded:[],failed:[],canceled:[],lost:[]},Ve=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),He=/* @__PURE__ */ new Set([`running`,`stopping`]);function Ue(e,t,n,r){if(n!==`canceled`&&n!==`succeeded`){if(t.childError!==void 0)return t.childError;if(t.exitCode===0&&!r)return`dispatch produced no final text`}}function We(e){return e===`running`||e===`stopping`||e===`succeeded`||e===`failed`||e===`canceled`||e===`lost`}function Ge(e){return typeof e==`string`&&e.length>0}const Ke=/* @__PURE__ */ new Set([`session_ended_while_running`,`user_killed_via_esc`,`lost_on_session_restart`]);function qe(e){return typeof e==`string`&&Ke.has(e)}function Je(e,t){return e.ownerPid===t.pid&&e.ownerBootMs===t.bootMs}function Ye(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 Xe(e,t){let n=`task:${e}`;return t===`running`||t===`stopping`?`${n}:${t}`:`${n}:->${t}`}var Ze=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??Ye,this.#a=Te({now:()=>this.#t()})}async transition(e,t){let n=await this.#h(()=>this.#c(e,t)),r=n.events[n.events.length-1];return r!==void 0&&this.#g(n.record,r,t.logger),n}onTransition(e){this.#o.add(e);let t=!0;return()=>{t&&(t=!1,this.#o.delete(e))}}async#c(e,t){switch(e.kind){case`spawn`:return this.#l(e,t);case`transition`:return this.#u(e,t);case`stop`:return this.#d(e,t);case`reconcile-lost`:return this.#p(e,t);case`resolve-exit`:return this.#f(e,t)}throw Error(`transition: unknown command kind ${String(e.kind)}`)}async get(e){return Ge(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())He.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=Ge(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(!We(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`&&!qe(e.reason))throw Error(`transition: to "lost" requires a LostReason (session_ended_while_running | user_killed_via_esc | lost_on_session_restart)`+(e.reason===void 0?``:`, got ${String(e.reason)}`));return this.#m(n,e.to,t,{reason:e.reason,stopReason:e.stopReason,errorMessage:e.errorMessage,exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview})}async#d(e,t){let n=await this.#y(e.taskId);return n.status===`stopping`?{record:n,events:[],cursor:(await this.#e.loadSubscription(t.callerId,n.id))?.cursor??n.id,fromStatus:n.status}:(this.#v(n,`stopping`),this.#m(n,`stopping`,t,{stopReason:e.reason}))}async#f(e,t){let n=await this.#y(e.taskId);if(n.status!==`running`&&n.status!==`stopping`)throw Error(`resolve-exit: task ${n.id} is terminal (${n.status}); the single terminal writer refuses to overwrite it`);let r=(e.outputBytes??0)>0,i=n.status===`stopping`?`canceled`:e.exitCode===0&&r?`succeeded`:`failed`;return this.#v(n,i),this.#m(n,i,t,{exitCode:e.exitCode,outputRef:e.outputRef,outputBytes:e.outputBytes,outputPreview:e.outputPreview,errorMessage:Ue(n,e,i,r)})}async#p(e,t){let n=await this.#y(e.taskId);if(!He.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};Ve.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=Be[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(!Ge(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:Xe(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 Qe(e,t){return new Ze(e,t)}function $e(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}function et(e){for(let t=1;t<e.length;t++)if($e(e[t-1],e[t])>0)return!1;return!0}var tt=class e{#e;#t;#n;#r;constructor(){this.#e=/* @__PURE__ */ new Map,this.#t=/* @__PURE__ */ new Map,this.#n=/* @__PURE__ */ new Set,this.#r=/* @__PURE__ */ new Map}static#i(e,t){return`${e}-${t}`}#a(e){return this.#n.has(e)}async loadTask(e){let t=this.#e.get(e);return t===void 0?null:structuredClone(t)}async saveTask(e){N(e,`saveTask: record is required`),this.#e.set(e.id,structuredClone(e))}async deleteTask(e){if(!this.#e.has(e))throw Error(`deleteTask: unknown taskId ${e}`);this.#e.delete(e)}async*listTasks(e){for(let t of this.#e.values())(e?.status===void 0||t.status===e.status)&&(e?.label===void 0||t.label===e.label)&&(yield structuredClone(t))}async loadSubscription(t,n){let r=this.#t.get(e.#i(t,n));return r===void 0?null:structuredClone(r)}async saveSubscription(t){N(t,`saveSubscription: sub is required`);let n=e.#i(t.subscriberId,t.taskId);this.#t.set(n,structuredClone(t)),this.#n.add(t.subscriberId)}async appendEvents(e,t){if(!this.#a(e))throw Error(`appendEvents: unknown subscriptionId ${e}`);if(t.length===0)return;let n=this.#r.get(e)??[],r=et(t)?[...t]:[...t].sort($e),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($e),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 nt=new Fe;var rt=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 it=new rt(I.dispatchConcurrency);let at;function ot(e,t){return e.taskRegistry===void 0?(at??=new Ze(new tt,{clock:t}),at):e.taskRegistry}const st={info:()=>void 0,warn:e=>{console.warn(`[pi.dispatch] `+e)}};function ct(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 ct(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:`dispatch depth limit reached`}}function lt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:`dispatch concurrency limit reached`}}function R(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 ut(){return{...ct(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function dt(){return{...lt(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function ft(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 pt(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 mt(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 ht(e){let t=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!t)return null;let n=t[1]??``,r=t[2]??``,i=pt(n,`name`);if(!i)return null;let a=pt(n,`description`)??``,o=pt(n,`model`)??``,s=mt(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 gt(e,t,n,r){let{userDir:i,projectDir:a}=_t({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:E.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:E.join(a,e+`.md`),source:`project`});for(let t of o){let n;try{n=C.readFileSync(t.path,`utf-8`)}catch{continue}let r=ht(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 _t(e){let t=e.homeDir??re.homedir();return{userDir:E.join(t,`.pi`,`agent`,`agents`),projectDir:E.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function vt(e){let t=e?.code;return typeof t==`string`?t:String(e)}function yt(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function bt(e,t){let n=E.resolve(e),r=E.resolve(t),i=e=>E.dirname(e),a=n,o=!1;for(let e=0;e<=8;e+=1){try{if(C.statSync(a).isDirectory()){o=!0;break}}catch{}if(a===r)break;let e=i(a);if(e===a)break;a=e}if(o){for(let e=n;e!==a&&e!==i(e);e=i(e))if(xt(e))return!0;return!1}return a===r&&xt(r)}function xt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function St(e,t,n){let r=vt(n);return r!==`ENOENT`&&r!==`ENOTDIR`||yt(e)?!1:!bt(e,t)}function Ct(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=_t(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(!St(e,t,n)){let t=vt(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of n){if(!t.endsWith(`.md`))continue;let n=t.slice(0,-3),r=E.join(e,t),i;try{i=C.readFileSync(r,`utf-8`)}catch(e){let t=e instanceof Error?e.message:String(e);console.warn(`pi.dispatch: cannot read agent file ${r}: ${t}; falling back to the filename`),o.add(n);continue}let a=ht(i)?.name??n;a.length>0&&o.add(a)}}return[...o].sort()}function wt(e){let{userDir:t,projectDir:n}=_t(e),r=Ct(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 Tt(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,errorMessage:`agent is required (there is no default agent) — `+wt(e)}}function Et(e){return typeof e!=`string`||e.trim().length===0}function Dt(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+`). `+wt({cwd:n,agentScope:t})}}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}let kt=At;async function At(e,t){let n=await C.promises.mkdtemp(E.join(re.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=E.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function jt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Mt(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message.content;if(!Array.isArray(t))return;let n;for(let e of t)e&&e.type===`text`&&typeof e.text==`string`&&(n=e.text);return n}function Nt(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message;if(t.stopReason!==`error`)return;let n=t.errorMessage;return typeof n==`string`&&n.trim().length>0?n.trim():`child reported stopReason: error`}async function Pt(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return ut();if(Et(e.agent))return Tt({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`});let i=Ee(),a=n.slots??rt;if(!a.tryAcquire(i))return dt();let o=n.clock??(()=>Date.now()),s=n.logger??ot,c=e.cwd??t.cwd,l=e.agentScope??`user`,u=n.lifecycle??tt,d=t.callerId??`dispatch:`+String(t.callId),f=at(n,o),p=n.outputStorage,m,h;try{let n=gt(e.agent,c,l);if(!n)return a.release(i),Dt(e.agent,l,c);let g=e.label??e.task.slice(0,64),_=st(n.systemPrompt,r,t.maxDispatchDepth),v=await kt(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=R(u,x,{isDone:()=>C,unref:!0})))});return(async()=>{let e=``,t;try{for await(let n of u.events(x)){let r=Mt(n);r!==void 0&&(e=r);let i=Nt(n);i!==void 0&&(t=i)}C=!0,w?.();let n=(await u.exit(x)).code??-1,r=Buffer.byteLength(e,`utf8`),a=r<=2048?e:void 0,c;if(p!==void 0)try{await p.writeOutput(i,e),c=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:n,outputRef:c,outputBytes:r,outputPreview:a,childError:t},{clock:o,callerId:d,logger:s})}catch(t){let n=t instanceof Error?t.message:String(t);s.warn(`background dispatch pump for task `+i+` failed after `+String(e.length)+` chars of buffered output: `+n)}finally{T(),w?.(),jt(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&&R(u,m,{unref:!0}),h!==void 0&&jt(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 Ft(e,t,n={}){if(e.background===!0)return await Pt(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return ct();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now();if(Et(e.agent))return Tt({cwd:i,agentScope:a});let s=n.slots??rt;if(!s.tryAcquire())return lt();let c=gt(e.agent,i,a);if(!c)return s.release(),Dt(e.agent,a,i,Date.now()-o);let l=st(c.systemPrompt,r,t.maxDispatchDepth),u,d=n.lifecycle??tt,f;try{u=await kt(c.name,l),f=Ot(e,c,u.filePath)}catch(e){throw s.release(),e}return await new Promise(e=>{let a=``,l,p=-1,m=``,h=!1,g,_,v=!1,y=(r,i,f=!0)=>{if(h)return;h=!0,s.release(),_!==void 0&&d.exit(_).catch(e=>{(n.logger??ot).warn(`exit() failed for a foreground child; the session live set may retain it: `+(e instanceof Error?e.message:String(e)))}),g?.(),t.signal&&t.signal.removeEventListener(`abort`,b),jt(u);let v={text:a,status:r,started:f,agentName:c.name,durationMs:Date.now()-o,exitCode:p};l&&(v.usage=l),m.length>0&&(v.stderr=m),i&&(v.errorMessage=i),e(v)},b=()=>{_&&!h&&(v=!0,g=R(d,_,{isDone:()=>h}))};try{_=d.spawn([`pi`,...f],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:u.filePath})}catch(e){y(`rejected`,`failed to spawn pi: `+(e instanceof Error?e.message:String(e)),!1);return}t.signal&&(t.signal.aborted?b():t.signal.addEventListener(`abort`,b,{once:!0})),(async()=>{if(!_)return;let e=_;try{for await(let t of d.events(e))if(t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(e.usage){let t=l??{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,l=t}if(Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(a=t.text)}let t=await tt.exit(e);p=t.code??-1,m=await tt.stderr(e);let n=m.match(/^\[spawn-error\] (.+)$/m);if(n&&t.code===null&&t.signal===null){y(`rejected`,`failed to spawn pi: `+n[1],!1);return}let{status:r,errorMessage:i}=ft({exitCode:p,finalText:a,aborted:v});y(r,i)}catch(e){let t=e instanceof Error?e.message:String(e);y(`rejected`,`dispatch internal error: `+t)}})()})}const z=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],B=`pi.dispatch`,It=z,Lt={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},Rt=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())}),zt={name:B,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters:Rt};function Bt(e,t){let n=t.trim();return n.length===0?`${e} reported a failure with no message`:`${e} failed: ${n.length<=2e3?n:`…${n.slice(-2e3)}`}`}function Vt(e){let t=e.names??It,n=e.includeDispatch??e.names===void 0,r=/* @__PURE__ */ new Map;for(let n of t){let t=Lt[n];if(!t)throw TypeError(`unknown PTC binding "${n}"; known bindings: ${z.join(`, `)}`);let i=t(e.cwd);r.set(n,{name:n,execute:async(e,t)=>{let n=`ptc:${t.callId}`,r={type:`toolCall`,id:n,name:i.name,arguments:e},a=S(i,r),o=await i.execute(n,a,t.signal,void 0);if(o.isError===!0)throw Error(Bt(i.name,(o.content??[]).filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text??``).join(`
|
|
8
|
-
`)));return{content:o.content,details:o.details===void 0?null:o.details}}})}return n&&r.set(
|
|
9
|
-
`);return e===-1?t:t.slice(0,e)}}}}function
|
|
10
|
-
`),`Exceptions: `+[...
|
|
11
|
-
`),
|
|
12
|
-
`)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=
|
|
13
|
-
`))r.push(e.length===0?``:`${i} ${e}`);continue}let o=
|
|
14
|
-
`):typeof e!=`object`||!e?[String(e)]:
|
|
7
|
+
`+r}function lt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:`dispatch depth limit reached`}}function ut(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,errorMessage:`dispatch concurrency limit reached`}}function dt(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 ft(){return{...lt(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function pt(){return{...ut(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function mt(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 ht(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 gt(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 _t(e){let t=e.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);if(!t)return null;let n=t[1]??``,r=t[2]??``,i=ht(n,`name`);if(!i)return null;let a=ht(n,`description`)??``,o=ht(n,`model`)??``,s=gt(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 vt(e,t,n,r){let{userDir:i,projectDir:a}=yt({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=_t(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 yt(e){let t=e.homeDir??ne.homedir();return{userDir:D.join(t,`.pi`,`agent`,`agents`),projectDir:D.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function bt(e){let t=e?.code;return typeof t==`string`?t:String(e)}function xt(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function St(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(Ct(e))return!0;return!1}return a===r&&Ct(r)}function Ct(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function wt(e,t,n){let r=bt(n);return r!==`ENOENT`&&r!==`ENOTDIR`||xt(e)?!1:!St(e,t)}function Tt(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=yt(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(!wt(e,t,n)){let t=bt(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=_t(i)?.name??n;a.length>0&&o.add(a)}}return[...o].sort()}function Et(e){let{userDir:t,projectDir:n}=yt(e),r=Tt(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 Dt(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,errorMessage:`agent is required (there is no default agent) — `+Et(e)}}function Ot(e){return typeof e!=`string`||e.trim().length===0}function kt(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+`). `+Et({cwd:n,agentScope:t})}}function At(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}let jt=Mt;async function Mt(e,t){let n=await C.promises.mkdtemp(D.join(ne.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=D.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function Nt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Pt(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message.content;if(!Array.isArray(t))return;let n;for(let e of t)e&&e.type===`text`&&typeof e.text==`string`&&(n=e.text);return n}function Ft(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message;if(t.stopReason!==`error`)return;let n=t.errorMessage;return typeof n==`string`&&n.trim().length>0?n.trim():`child reported stopReason: error`}async function It(e,t,n){let r=t.depth+1;if(r>t.maxDispatchDepth)return ft();if(Ot(e.agent))return Dt({cwd:e.cwd??t.cwd,agentScope:e.agentScope??`user`});let i=De(),a=n.slots??it;if(!a.tryAcquire(i))return pt();let o=n.clock??(()=>Date.now()),s=n.logger??st,c=e.cwd??t.cwd,l=e.agentScope??`user`,u=n.lifecycle??nt,d=t.callerId??`dispatch:`+String(t.callId),f=ot(n,o),p=n.outputStorage,m,h;try{let n=vt(e.agent,c,l);if(!n)return a.release(i),kt(e.agent,l,c);let g=e.label??e.task.slice(0,64),_=ct(n.systemPrompt,r,t.maxDispatchDepth),v=await jt(n.name,_);h=v;let y=At(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=dt(u,x,{isDone:()=>C,unref:!0})))});return(async()=>{let e=``,t;try{for await(let n of u.events(x)){let r=Pt(n);r!==void 0&&(e=r);let i=Ft(n);i!==void 0&&(t=i)}C=!0,w?.();let n=(await u.exit(x)).code??-1,r=Buffer.byteLength(e,`utf8`),a=r<=2048?e:void 0,c;if(p!==void 0)try{await p.writeOutput(i,e),c=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:n,outputRef:c,outputBytes:r,outputPreview:a,childError:t},{clock:o,callerId:d,logger:s})}catch(t){let n=t instanceof Error?t.message:String(t);s.warn(`background dispatch pump for task `+i+` failed after `+String(e.length)+` chars of buffered output: `+n)}finally{T(),w?.(),Nt(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&&dt(u,m,{unref:!0}),h!==void 0&&Nt(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 Lt(e,t,n={}){if(e.background===!0)return await It(e,t,n);let r=t.depth+1;if(r>t.maxDispatchDepth)return lt();let i=e.cwd??t.cwd,a=e.agentScope??`user`,o=Date.now();if(Ot(e.agent))return Dt({cwd:i,agentScope:a});let s=n.slots??it;if(!s.tryAcquire())return ut();let c=vt(e.agent,i,a);if(!c)return s.release(),kt(e.agent,a,i,Date.now()-o);let l=ct(c.systemPrompt,r,t.maxDispatchDepth),u,d=n.lifecycle??nt,f;try{u=await jt(c.name,l),f=At(e,c,u.filePath)}catch(e){throw s.release(),e}return await new Promise(e=>{let a=``,l,p=-1,m=``,h=!1,g,_,v=!1,y=(r,i,f=!0)=>{if(h)return;h=!0,s.release(),_!==void 0&&d.exit(_).catch(e=>{(n.logger??st).warn(`exit() failed for a foreground child; the session live set may retain it: `+(e instanceof Error?e.message:String(e)))}),g?.(),t.signal&&t.signal.removeEventListener(`abort`,b),Nt(u);let v={text:a,status:r,started:f,agentName:c.name,durationMs:Date.now()-o,exitCode:p};l&&(v.usage=l),m.length>0&&(v.stderr=m),i&&(v.errorMessage=i),e(v)},b=()=>{_&&!h&&(v=!0,g=dt(d,_,{isDone:()=>h}))};try{_=d.spawn([`pi`,...f],{cwd:i,env:{...process.env,PI_PTC_DEPTH:String(r)},promptFile:u.filePath})}catch(e){y(`rejected`,`failed to spawn pi: `+(e instanceof Error?e.message:String(e)),!1);return}t.signal&&(t.signal.aborted?b():t.signal.addEventListener(`abort`,b,{once:!0})),(async()=>{if(!_)return;let e=_;try{for await(let t of d.events(e))if(t.type===`message_end`&&t.message&&t.message.role===`assistant`){let e=t.message;if(e.usage){let t=l??{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,l=t}if(Array.isArray(e.content))for(let t of e.content)t&&t.type===`text`&&typeof t.text==`string`&&(a=t.text)}let t=await nt.exit(e);p=t.code??-1,m=await nt.stderr(e);let n=m.match(/^\[spawn-error\] (.+)$/m);if(n&&t.code===null&&t.signal===null){y(`rejected`,`failed to spawn pi: `+n[1],!1);return}let{status:r,errorMessage:i}=mt({exitCode:p,finalText:a,aborted:v});y(r,i)}catch(e){let t=e instanceof Error?e.message:String(e);y(`rejected`,`dispatch internal error: `+t)}})()})}const L=[`read`,`bash`,`edit`,`write`,`grep`,`find`,`ls`],R=`pi.dispatch`,Rt=L,zt={read:m,bash:l,edit:u,write:h,grep:f,find:d,ls:p},Bt=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())}),Vt={name:R,description:`Dispatch a task to a registered pi agent as a child subprocess (foreground await or background task).`,parameters:Bt};function Ht(e,t){let n=t.trim();return n.length===0?`${e} reported a failure with no message`:`${e} failed: ${n.length<=2e3?n:`…${n.slice(-2e3)}`}`}function Ut(e){let t=e.names??Rt,n=e.includeDispatch??e.names===void 0,r=/* @__PURE__ */ new Map;for(let n of t){let t=zt[n];if(!t)throw TypeError(`unknown PTC binding "${n}"; known bindings: ${L.join(`, `)}`);let i=t(e.cwd);r.set(n,{name:n,execute:async(e,t)=>{let n=`ptc:${t.callId}`,r={type:`toolCall`,id:n,name:i.name,arguments:e},a=S(i,r),o=await i.execute(n,a,t.signal,void 0);if(o.isError===!0)throw Error(Ht(i.name,(o.content??[]).filter(e=>e.type===`text`&&typeof e.text==`string`).map(e=>e.text??``).join(`
|
|
8
|
+
`)));return{content:o.content,details:o.details===void 0?null:o.details}}})}return n&&r.set(R,{name:R,execute:async(t,n)=>{let r={type:`toolCall`,id:`ptc:${n.callId}`,name:R,arguments:t},i;try{i=S(Vt,r)}catch(n){let r=typeof t==`object`&&t&&!Array.isArray(t)?t:void 0,i=r?.agent,a=r?.agentScope;return Ot(i)?Dt({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 Lt(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 Wt(){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 Gt(e){return{name:`ptc-${e.surface}`,env:e.env,workerData:e.runId===void 0?{env:e.env}:{runId:e.runId,env:e.env},resourceLimits:{maxOldGenerationSizeMb:e.limits.maxOldGenerationSizeMb,maxYoungGenerationSizeMb:e.limits.maxYoungGenerationSizeMb}}}const z={acquireLatency:ue.channel(`ptc:pool:acquire-latency`),resetTime:ue.channel(`ptc:worker:reset-time`),imageBytes:ue.channel(`ptc:image:hoist-bytes`)};function B(e,t){e.publish(t)}var Kt=class{#e;#t;#n;#r;#i;#a=[];#o=/* @__PURE__ */ new Set;#s=[];#c=/* @__PURE__ */ new WeakMap;#l=0;#u=0;#d=!1;constructor(e){if(typeof e.buildWorkerUrl!=`function`)throw TypeError(`WorkerPool: buildWorkerUrl must be a function`);if(e.size!==void 0&&(typeof e.size!=`number`||!Number.isFinite(e.size)||e.size<=0))throw TypeError(`WorkerPool: size must be a positive finite number, received ${String(e.size)}`);if(e.acquireTimeoutMs!==void 0&&(typeof e.acquireTimeoutMs!=`number`||!Number.isFinite(e.acquireTimeoutMs)||e.acquireTimeoutMs<=0))throw TypeError(`WorkerPool: acquireTimeoutMs must be a positive finite number, received ${String(e.acquireTimeoutMs)}`);if(e.drainGraceMs!==void 0&&(typeof e.drainGraceMs!=`number`||!Number.isFinite(e.drainGraceMs)||e.drainGraceMs<=0))throw TypeError(`WorkerPool: drainGraceMs must be a positive finite number, received ${String(e.drainGraceMs)}`);this.#e=e.buildWorkerUrl,this.#t=e.size??4,this.#n=e.acquireTimeoutMs??3e4,this.#r=e.drainGraceMs??5e3,this.#i=e.workerOptions}async acquire(){if(this.#d)throw Error(`pool has been drained and can no longer serve workers`);this.#l+=1;let e=Date.now(),t=this.#a.shift();for(;t!==void 0&&!this.#p(t);)t=this.#a.shift();if(t!==void 0)return this.#o.add(t),t.ref(),B(z.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-e}),t;if(this.#o.size<this.#t){let t=this.#f();return this.#o.add(t),B(z.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-e}),t}return this.#u+=1,await new Promise((t,n)=>{let r=setTimeout(()=>{let e=this.#s.findIndex(e=>e.timer===r);e>=0&&this.#s.splice(e,1),n(/* @__PURE__ */ Error(`pool acquire timed out after ${this.#n} ms`))},this.#n);this.#s.push({resolve:t,reject:n,timer:r,startedAt:e})})}release(e){if(!this.#o.delete(e)||!this.#p(e))return;this.#c.set(e,Date.now());let t=this.#s.shift();if(t){clearTimeout(t.timer),this.#o.add(e),B(z.acquireLatency,{poolSize:this.#t,waiters:this.#s.length,durationMs:Date.now()-t.startedAt}),t.resolve(e);return}this.#a.push(e),e.unref()}lastSettledAt(e){return this.#c.get(e)}async drain(){for(;this.#s.length>0;){let e=this.#s.shift();if(!e)break;clearTimeout(e.timer),e.reject(/* @__PURE__ */ Error(`pool drained before acquire could be satisfied`))}let e=Date.now()+this.#r;for(;this.#o.size>0&&Date.now()<e;)await new Promise(e=>setTimeout(e,5));let t=[...this.#a,...this.#o];this.#a.length=0,this.#o.clear(),await Promise.all(t.map(e=>e.terminate().catch(()=>void 0))),this.#d=!0}stats(){return{resident:this.#o.size+this.#a.length,inFlight:this.#o.size,waiters:this.#s.length,totalAcquires:this.#l,poolExhaustions:this.#u}}#f(){let e=new le(this.#e(),this.#i);return e.once(`exit`,()=>{let t=this.#a.indexOf(e);if(t>=0){this.#a.splice(t,1);return}this.#o.delete(e)}),e}#p(e){return e.threadId!==-1}};function qt(e){B(z.imageBytes,{byteLength:e})}function Jt(e){B(z.resetTime,{durationMs:e})}function Yt(){let e=ae(de(import.meta.url)),t=[A(e,`worker.js`),A(e,`worker-entry.ts`)];for(let e of t)if(w(e))return fe(e);throw Error(`worker entry not found; tried: ${t.join(`, `)}`)}function Xt(e){if(typeof e!=`object`||!e)return;let t=e;if(t.status!==`rejected`)return;let n=typeof t.errorMessage==`string`?t.errorMessage:t.started===!1?`dispatch refused`:`dispatch failed`;return{kind:t.started===!1?`refused`:`failed`,message:n}}function V(e){return e instanceof Error?e.message:String(e)}function Zt(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(`
|
|
9
|
+
`);return e===-1?t:t.slice(0,e)}}}}function Qt(e){return e instanceof ArrayBuffer||ArrayBuffer.isView(e)}function $t(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 en(e){try{let t=Buffer.byteLength(JSON.stringify(e,(e,t)=>Qt(t)?null:t)??``,`utf8`),n=0;return $t(e,e=>{n+=e.byteLength}),t+n}catch{return 1/0}}async function tn(e){let i=Re(e.config),s=Le(),c=e.runId??M(),l=ze(e.timeoutMs,i),u=[],d=[],f=[];if(e.signal?.aborted)return{logs:u,narrations:d,phases:f,error:{kind:n.abort,message:`run cancelled before start`}};let p;try{p=e.pool?await e.pool.acquire():new le(Yt(),Gt({surface:e.surface,env:s,limits:i,runId:c}))}catch(e){return{logs:u,narrations:d,phases:f,error:{kind:n.workerExit,message:`pool acquire failed: ${V(e)}`}}}return await new Promise(s=>{let m=new ce,h=m.port1,g=m.port2,_=new AbortController,v=!1,y=Wt(),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 rt(i.dispatchConcurrency),E=0,te=[],ne=e.depth??0,re,D,ie=[],ae=e=>{let t=[],n=e?.content;if(!Array.isArray(n))return t;for(let e of n){if(typeof e!=`object`||!e)continue;let n=e;if(n.type!==`image`)continue;let r;typeof n.data==`string`&&n.data.length>0?r=n.data:n.bytes instanceof ArrayBuffer&&n.bytes.byteLength>0&&(r=Buffer.from(n.bytes).toString(`base64`)),r!==void 0&&t.push({data:r,mimeType:typeof n.mimeType==`string`?n.mimeType:`application/octet-stream`})}return t},O=e=>e===`timeout`?`run timed out after ${l} ms`:`run cancelled`,k=e=>e===`timeout`?n.timeout:n.abort,A=t=>{if(v)return;v=!0,re&&clearTimeout(re),D&&clearTimeout(D),e.signal?.removeEventListener(`abort`,pe),_.abort(),h.close(),e.pool?e.pool.release(p):p.terminate();let n=x.snapshot();s(n.length>0?{...t,subCalls:n}:t)},j=(e,t,n)=>{A({logs:u,narrations:d,phases:f,error:n===void 0?{kind:e,message:t}:{kind:e,message:t,stack:n}})},oe=e=>{if(!v){if(!r(e)){j(n.protocol,`internal error: malformed host frame`);return}h.postMessage(e)}},se=()=>{let t={kind:o.init,runId:c,surface:e.surface,code:e.code,bindings:[...e.bindings.keys()],bindingCandidates:[...L],maxItemsPerCall:i.maxItemsPerCall,maxPendingCalls:i.maxPendingCalls,...e.args===void 0?{}:{args:e.args}};if(!r(t)){j(n.protocol,`internal error: malformed init frame`);return}let a=en(t);if(a>i.maxMessageBytes){j(n.protocol,`init frame of ${a} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}oe(t)},M=(e,t)=>(T+=e,T<=i.maxOutputBytes||(j(n.outputLimit,`${t} exceeded the output budget: logs + result reached ${T} bytes (maxOutputBytes=${i.maxOutputBytes}); ${u.length} log line(s) retained`),!1)),N=async()=>{if(E<i.maxParallelSubCalls){E+=1;return}await new Promise(e=>{te.push(e)})},le=()=>{let e=te.shift();if(e){e();return}--E},ue=e=>{if(x.recordStart(e.callId,e.tool,e.args),w+=1,w>i.maxPendingCalls){x.recordEnd(e.callId,`error`,{errorMessage:`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`}),j(n.protocol,`more than maxPendingCalls (${i.maxPendingCalls}) binding calls in flight`);return}de(e).finally(()=>{--w})},de=async t=>{let r=e.bindings.get(t.tool);if(!r){x.recordEnd(t.callId,`error`,{errorMessage:`no binding named "${t.tool}" in this run; available bindings: `+([...e.bindings.keys()].join(`, `)||`(none)`)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:`no binding named "${t.tool}" in this run; available bindings: `+([...e.bindings.keys()].join(`, `)||`(none)`)});return}let a=t.tool===R;if(!a&&(await N(),v)){x.recordEnd(t.callId,`cancelled`,{errorMessage:`run settled before binding started`}),le();return}try{let s=await r.execute(t.args,{signal:_.signal,callId:t.callId,depth:ne,maxDispatchDepth:i.maxDispatchDepth,callerId:c,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId},...e.sessionDir===void 0?{}:{sessionDir:e.sessionDir},dispatchDeps:{...e.dispatchDeps,slots:e.dispatchDeps?.slots??ee}}),l=ae(s),u={kind:o.callResult,callId:t.callId,tool:t.tool,ok:!0,value:s},d=en(u);if(d>i.maxMessageBytes){x.recordEnd(t.callId,`error`,{errorMessage:`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`}),j(n.protocol,`callResult frame of ${d} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}if(fe(u))for(let e of l)ie.push(e),qt(Buffer.byteLength(e.data,`base64`));if(_.signal.aborted)x.recordEnd(t.callId,`cancelled`,{errorMessage:`binding aborted by run cancellation`});else{let e=a?Xt(s):void 0;e===void 0?x.recordEnd(t.callId,`ok`,{resultSummary:Zt(s)}):x.recordEnd(t.callId,e.kind===`refused`?`rejected`:`error`,{errorMessage:e.message})}}catch(e){_.signal.aborted?x.recordEnd(t.callId,`cancelled`,{errorMessage:V(e)}):x.recordEnd(t.callId,`error`,{errorMessage:V(e)}),fe({kind:o.callResult,callId:t.callId,tool:t.tool,ok:!1,message:V(e)})}finally{a||le()}},fe=e=>{if(v)return!1;try{return h.postMessage(e),!0}catch(t){try{h.postMessage({kind:o.callResult,callId:e.callId,tool:e.tool,ok:!1,message:`binding result could not be transferred: ${V(t)}`})}catch{j(n.protocol,`binding result is not transferable`)}return!1}},P=e=>S?{logs:u,narrations:d,phases:f,error:{kind:k(S),message:O(S)}}:e,F=r=>{if(v)return;if(!a(r)){j(n.protocol,`malformed worker frame`);return}let o=r.kind===t.ready?0:en(r);if(!Number.isFinite(o)){j(n.protocol,`worker frame could not be serialized for accounting`);return}if(o>i.maxMessageBytes){j(n.protocol,`control frame of ${o} bytes exceeds maxMessageBytes (${i.maxMessageBytes})`);return}switch(r.kind){case t.ready:if(e.pool){let t=e.pool.lastSettledAt(p);t!==void 0&&Jt(Date.now()-t)}if(!C&&(C=!0,S)){me(S);return}se();return;case t.call:ue(r);return;case t.log:M(o,`console output`)&&u.push(r.text);return;case t.narration:M(o,`workflow narration`)&&d.push(r.message);return;case t.phase:M(o,`workflow phase`)&&f.push(r.title);return;case t.result:{if(!M(o,`completion value`))return;let e={logs:u,narrations:d,phases:f,...ie.length>0?{images:ie}:{}};A(P(r.value===void 0?e:{...e,value:r.value}));return}case t.error:A(P({logs:u,narrations:d,phases:f,error:r.error}));return;default:j(n.protocol,`unknown worker frame`)}};function pe(){he(`abort`)}let me=e=>{D&&clearTimeout(D),D=setTimeout(()=>{j(k(e),O(e))},i.graceMs)};function he(e){if(!v){if(S){j(k(S),O(S));return}S=e,_.abort(),oe({kind:o.cancel,reason:e}),me(e)}}p.on(`error`,e=>{j(n.workerExit,`worker failed: ${V(e)}`)}),p.on(`exit`,e=>{j(n.workerExit,`worker exited with code ${e} before the run completed`)}),h.on(`message`,F),h.on(`messageerror`,()=>{j(n.protocol,`worker sent a frame that could not be deserialized`)}),e.signal?.addEventListener(`abort`,pe,{once:!0}),re=setTimeout(()=>{he(`timeout`)},l);let ge={kind:o.connect,port:g};r(ge)?p.postMessage(ge,[g]):j(n.protocol,`internal error: malformed connect frame`)})}const nn=["Return value: every `tools.<name>(args)` call above resolves to `{ content, details }`.","`content` is an ARRAY of content blocks, never a string, so a text result is","`result.content[0].text`; `details` is that tool's own detail object or `null`, never","`undefined`. No binding result has a `files`, `output`, `matches` or `entries` field:","`bash`, `grep`, `find` and `ls` hand back ONE text block of newline-separated rows that","you split yourself, and the empty answer is a sentinel string (`No matches found`,","`No files found matching pattern`, `(empty directory)`) rather than an empty list.","A failing call REJECTS with `ToolCallError` instead of resolving, so wrap the call in","`try`/`catch` (or `Promise.allSettled`): a path that is not there, a builtin this run did not",`bind. A name that is not a builtin is simply not a function.`],rn=/* @__PURE__ */ new Map([[`bash`,"`bash` rejects on a non-zero exit rather than resolving with its output."],[`write`,"`write` always reports `details: null`."],[`edit`,"`edit` always reports a `details` object carrying `diff` and `patch`."],[R,'`tools["pi.dispatch"]` is the exception: it resolves to `{ text, status, ... }` with no `content` and never throws, so read `status`.']]),an=[nn.join(`
|
|
10
|
+
`),`Exceptions: `+[...rn.values()].join(` `)].join(`
|
|
11
|
+
`),on=`pi-ptc-output-`;function sn(e,t=on){let n=O(re(),`${t}${M()}.txt`);return te(n,e,`utf8`),n}function cn(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 ln(e,t=on,n={}){let r=b(e,{maxLines:c,maxBytes:s});if(!r.truncated)return{text:e,truncated:!1};let i=sn(n.fullText??e,t);return{text:`${r.content}\n\n${cn(r,i)}`,truncated:!0,fullPath:i}}const un=200,dn=new RegExp([`(?:\\u001B\\][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))`,`[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]`].join(`|`),`g`);function fn(e){return!e.includes(`\x1B`)&&!e.includes(``)?e:e.replace(dn,``)}function H(e){let t=fn(e).replace(/\r/g,``);if(t.length===0)return t;let n=``;for(let e of t){let t=e.codePointAt(0);if(t!==void 0){if(t===10||t===9){n+=e;continue}t<=31||t>=65529&&t<=65531||(n+=e)}}return n}const pn=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function mn(e){return pn.test(e)?e:JSON.stringify(e)}function hn(e){if(e===null)return`null`;if(typeof e==`number`||typeof e==`boolean`)return String(e);if(typeof e==`string`){let t=H(e);return t.includes(`
|
|
12
|
+
`)?void 0:JSON.stringify(t)}if(Array.isArray(e)){let t=[];for(let n of e){let e=hn(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=hn(e[r]??null);if(t===void 0)return;n.push(`${mn(r)}: ${t}`)}return`{${n.join(`, `)}}`}function gn(e){let t=hn(e);if(t!==void 0)return t.length<=100?t:void 0}function _n(e){return e===null?`null`:typeof e==`string`?H(e):String(e)}function vn(e,t){if(typeof e!=`object`||!e)return[`${t}${_n(e)}`];if(Array.isArray(e)){if(e.length===0)return[`${t}[]`];let n=[`${t}[`];for(let r of e){let e=gn(r);if(e!==void 0){n.push(`${t} ${e}`);continue}n.push(...yn(r,t+` `))}return n.push(`${t}]`),n}let n=Object.keys(e);if(n.length===0)return[`${t}{}`];let r=[`${t}{`],i=t+` `;for(let t of n){let n=e[t]??null,a=gn(n);if(a!==void 0){r.push(`${i}${mn(t)}: ${a}`);continue}if(typeof n==`string`){r.push(`${i}${mn(t)}:`);for(let e of H(n).split(`
|
|
13
|
+
`))r.push(e.length===0?``:`${i} ${e}`);continue}let o=vn(n,i);r.push(`${i}${mn(t)}: ${(o[0]??``).trimStart()}`.trimEnd(),...o.slice(1))}return r.push(`${t}}`),r}function yn(e,t){return typeof e==`string`?H(e).split(`
|
|
14
|
+
`):typeof e!=`object`||!e?[String(e)]:vn(e,t)}function bn(e){return e.split(`
|
|
15
15
|
`).map(e=>e.length>200?`${e.slice(0,199)}…`:e).join(`
|
|
16
|
-
`)}function
|
|
17
|
-
`))}function
|
|
18
|
-
`)}`,i=Error(
|
|
19
|
-
`)),t.logs.length>0&&a.push(t.logs.map(e=>
|
|
20
|
-
`)),t.value!==void 0&&a.push(
|
|
21
|
-
`):`(${
|
|
22
|
-
`).find(e=>e.trim().length>0)??``).trim(),120)}function
|
|
23
|
-
`)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return
|
|
24
|
-
`),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:
|
|
25
|
-
`)&&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
|
|
26
|
-
`)){let e=
|
|
27
|
-
`).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new
|
|
28
|
-
`).map(e=>
|
|
29
|
-
`),
|
|
30
|
-
`),
|
|
31
|
-
`).find(e=>e.trim().length>0)??``).trim(),120)}function
|
|
32
|
-
`),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,
|
|
33
|
-
`),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...
|
|
34
|
-
`),a={tasks:r.map(e=>
|
|
35
|
-
`),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...
|
|
36
|
-
`),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...
|
|
16
|
+
`)}function xn(e){if(typeof e==`string`)return bn(H(e));if(typeof e!=`object`||!e)return String(e);let t=gn(e);return bn((t===void 0?yn(e,``):[t]).join(`
|
|
17
|
+
`))}function Sn(e=process.env){let t=e.PI_PTC_DEPTH;return t===void 0||!/^\d+$/.test(t)?0:Number.parseInt(t,10)}function Cn(e=process.env){let t=e.PI_PTC_TASK_ID;if(t!==void 0&&/^[0-9A-HJKMNP-TV-Z]{26}$/.test(t))return t}function U(e){if(e===void 0)return L;let t=new Set(e);return L.filter(e=>t.has(e))}const wn=["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.`],Tn={run_code:`ptc_run_code`,workflow:`ptc_workflow`};function En(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 On(e){return[...e.phases.map(e=>`[phase] ${H(e)}`),...e.narrations.map(e=>`[log] ${H(e)}`),...e.logs.map(e=>H(e))]}function kn(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=On(e),r=n.length===0?``:`\nCaptured output:\n${n.join(`
|
|
18
|
+
`)}`,i=Error(H(`code run failed (${t.kind}): ${t.message}${r}`));return i.name=`CodeRunFailedError`,i}function An(e){let{outcome:t,surface:n}=e,r=[...e.warnings??[]],i=t.images??[],a=[];t.phases.length>0&&a.push(`Phases: ${t.phases.map(e=>H(e)).join(` → `)}`),t.narrations.length>0&&a.push(t.narrations.map(e=>H(e)).join(`
|
|
19
|
+
`)),t.logs.length>0&&a.push(t.logs.map(e=>H(e)).join(`
|
|
20
|
+
`)),t.value!==void 0&&a.push(xn(t.value));for(let e of r)a.push(`Warning: ${H(e)}`);let o=ln(a.length>0?a.join(`
|
|
21
|
+
`):`(${Tn[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 jn=/^(.*?)(└─ |├─ | )(?:PTC(?: workflow)?)([ ].*)$/;function Mn(e){return e.replace(/\x1b\[[0-9;]*m|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b\[\?[0-9;]*[a-zA-Z]/g,``)}function Nn(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 Pn(e,t){let n=0,r=0;for(;r<t&&n<e.length;)e.charCodeAt(n)===27?n=Nn(e,n):(n+=1,r+=1);return n}function Fn(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:In(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 In(e,t,n){return e.map(e=>{let r=Mn(e),i=jn.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=Pn(e,s),l=Pn(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 Ln={run_code:`PTC`,workflow:`PTC workflow`};var Rn=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>zn(e,t))}};function zn(e,t){let{left:n,right:r}=e;if(r===void 0)return P(n,t,`…`);let i=F(r);if(i>=t)return P(r,t,`…`);let a=P(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-F(a));return a+` `.repeat(o)+r}function W(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function Bn(e){return W((H(e).split(`
|
|
22
|
+
`).find(e=>e.trim().length>0)??``).trim(),120)}function Vn(e){return e<1e3?`${e}ms`:`${(e/1e3).toFixed(2).replace(/\.?0+$/,``)}s`}function Hn(e,t){return`${e} ${t}${e===1?``:`s`}`}function Un(e){for(let t of e.split(`
|
|
23
|
+
`)){let e=t.trim();if(e.length!==0&&!e.startsWith(`//`)&&!e.startsWith(`/*`)&&!e.startsWith(`*`))return W(e.replace(/\s*\/\/.*$/,``),120)}}function Wn(e){if(e===void 0)return;if(typeof e==`string`){let t=H(e).split(`
|
|
24
|
+
`),n=t.find(e=>e.trim().length>0)?.trim()??``,r=t.length>1?` (+${t.length-1} lines)`:``;return n.length===0&&r.length===0?`""`:W(n,60)+r}if(typeof e!=`object`||!e)return String(e);let t=xn(e);if(!t.includes(`
|
|
25
|
+
`)&&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 Gn(e,t){if(e===void 0)return;let n=[],r=e.logs.length+e.narrations.length;if(r>0&&n.push(t.fg(`dim`,Hn(r,`output line`))),e.imageCount>0&&n.push(t.fg(`toolOutput`,Hn(e.imageCount,`image`))),e.surface===`workflow`&&e.phases.length>0&&n.push(t.fg(`dim`,Hn(e.phases.length,`phase`))),e.warnings.length>0&&n.push(t.fg(`warning`,Hn(e.warnings.length,`warning`))),e.fullOutputPath!==void 0&&n.push(t.fg(`warning`,`truncated`)),e.durationMs>0&&n.push(t.fg(`dim`,Vn(e.durationMs))),n.length!==0)return`${t.fg(`dim`,`•`)} ${n.join(t.fg(`dim`,` · `))}`}function Kn(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 qn(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 Jn(e){return typeof e!=`object`||!e?!1:Array.isArray(e)?e.length>0:Object.keys(e).length>0}const Yn=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function Xn(e){return Yn.test(e)?e:JSON.stringify(e)}function Zn(e,t){if(e===null)return`null`;if(typeof e==`boolean`||typeof e==`number`)return String(e);if(typeof e==`string`){let n=H(e);if(n.length===0)return`""`;if(n.includes(`
|
|
26
|
+
`)){let e=W(n.replace(/\n/g,` `),Math.max(2,t-5));return JSON.stringify(e)+`…`}return n.length+2<=t?JSON.stringify(n):JSON.stringify(W(n,Math.max(2,t-5)))+`…`}return`?`}function Qn(e){return typeof e!=`object`||!e}function $n(e,t){if(t<8)return;if(Array.isArray(e)){if(e.length===0)return`[]`;if(e.length>5||!e.every(Qn))return;let n=`[`+e.map(e=>Zn(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(Qn))return;let r=`{`+n.map(n=>{let r=e[n]??null;return Xn(n)+`: `+Zn(r,Math.max(2,Math.floor(t/4)))}).join(`, `)+`}`;return r.length<=t?r:void 0}function er(e,t,n,r,i,a,o,s,c){let l=n+(r?`└─ `:`├─ `),u=n+(r?` `:`│ `);if(s>=i){c.push(G(l+t+`…`,o));return}if(Array.isArray(e)&&e.length===0){c.push(G(l+t+`[]`,o));return}if(!Array.isArray(e)&&typeof e==`object`&&e&&Object.keys(e).length===0){c.push(G(l+t+`{}`,o));return}if(typeof e!=`object`||!e){let n=Math.max(0,o-F(l)-t.length);c.push(G(l+t+Zn(e,n),o));return}let d=$n(e,Math.max(0,o-F(l)-t.length));if(d!==void 0){c.push(G(l+t+d,o));return}let f=Array.isArray(e),p=f?e.length:Object.keys(e).length,m;m=f?`Array(`+p+`)`:p>a?`{`+a+` of `+p+`}`:`{`+p+` keys}`,c.push(G(l+t+m,o));let h=Math.min(a,p);if(f)for(let t=0;t<h;t+=1){let n=t===h-1&&p<=h;er(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];er(e[l]??null,Xn(l)+`: `,u,r,i,a,o,s+1,c)}}if(p>h){let e=f?`items`:`keys`;c.push(G(u+`└─ …+`+(p-h)+` more `+e,o))}}function G(e,t){if(F(e)<=t)return e;let n=e.match(/^([\s│├└─]*)/),r=n&&n[1]?n[1]:``,i=F(r),a=Math.max(0,t-i-1),o=``,s=0;for(let t of e.slice(r.length)){let e=F(t);if(s+e>a)break;o+=t,s+=e}return r+o+`…`}function tr(e,t={}){let n=t.maxDepth??4,r=t.maxChildren??6,i=t.maxLineChars??120,a=t.moreAfter===!0;if(!Jn(e))return typeof e==`object`&&e?[Array.isArray(e)?`[]`:`{}`]:[Zn(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;er(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];er(e[d]??null,Xn(d)+`: `,``,u,n,r,i,0,o)}return c>l&&o.push((a?`├─ `:`└─ `)+`…+`+(c-l)+` more keys`),o}function nr(e,t,n=`run_code`,r={}){let i=(typeof e.description==`string`&&e.description.trim().length>0?e.description.trim():e.meta?.name)??``,a=Un(e.code??e.script??``),o=i.length>0?i:a??`(no description)`;return Fn(new Rn([{left:`└─ ${`${t.fg(`toolTitle`,t.bold(Ln[n]))} ${t.fg(`accent`,o)}`}`}]),{intervalMs:150,isPartial:r.isPartial??!1,theme:t,requestInvalidate:r.requestInvalidate??rr,state:r.state??{}})}function rr(){}function ir(e){let t=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0);return Bn(t?.text??``)||`failed`}function ar(e,t){if(e===`pi.dispatch`&&typeof t==`object`&&t&&`agent`in t)return`→ ${String(t.agent)}`;if(typeof t==`object`&&t){let n=t,r=e=>typeof n[e]==`string`?n[e]:void 0,i=e===`read`?r(`path`):e===`bash`?r(`command`):e===`grep`||e===`find`?r(`pattern`):e===`ls`||e===`edit`||e===`write`?r(`path`):void 0;if(typeof i==`string`)return i}try{let e=JSON.stringify(t).replace(/\n/g,` `);return e.length>40?`${e.slice(0,39)}…`:e}catch{return String(t).slice(0,40)}}const or={running:{text:()=>`running`,themeSlot:`muted`},ok:{text:e=>e.durationMs===void 0?`ok`:`ok ${Vn(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 sr(e,t){if(e.length===0)return[];let n=e.slice(0,32),r=e.length>32?e.length-32:0,i=[];return n.forEach((e,a)=>{let o=a===n.length-1&&r===0?`└─ `:`├─ `,s=e.name.length>=8?`${e.name} `:e.name.padEnd(8),c=ar(e.name,e.args),l=or[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 cr(e,t,n,r=!1,i=!1){let a=Gn(e.details,n),o=e=>a===void 0?e:{...e,right:a};if(t)return[o({left:` ${n.fg(`error`,`failed: ${ir(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(Jn(s))return tr(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=Wn(s);return c===void 0?[o({left:` ${n.fg(`muted`,`done`)}`})]:[o({left:` ${n.fg(`dim`,`→ ${c}`)}`})]}function lr(e,t,n,r={}){let i=Kn(e.details),a=[...cr({...e,details:i},t,n,!1,r.isPartial===!0)];return i?.subCalls!==void 0&&a.push(...sr(i.subCalls,n)),new Rn(a)}function ur(e,t,n,r,i={}){let a=Kn(e.details);if(n){let t=[...cr({...e,details:a},!0,r)];a?.subCalls!==void 0&&t.push(...sr(a.subCalls,r));let n=H(e.content?.find(e=>e.type===`text`)?.text??ir(e));for(let e of n.split(`
|
|
27
|
+
`).slice(0,12))t.push({left:` ${r.fg(`error`,e)}`});return new Rn(t)}let o=[],s=t.code??t.script??``;if(s.length>0){let e=s.split(`
|
|
28
|
+
`).map(e=>W(e,120)),t=e.slice(0,3);o.push({label:`code`,lines:t,...e.length>t.length?{more:e.length-t.length}:{}})}if(a!==void 0&&a.surface===`workflow`&&a.phases.length>0){let e=a.phases.slice(0,8),t=a.phases.length-e.length,n=t>0?` …+${t} more phases`:``;o.push({label:`phases`,lines:[`${e.join(` → `)}${n}`]})}if(a!==void 0&&a.narrations.length>0){let e=a.narrations.slice(0,12);o.push({label:`log`,lines:e.map(e=>H(e)),...a.narrations.length>e.length?{more:a.narrations.length-e.length}:{}})}if(a!==void 0&&a.logs.length>0){let e=a.logs.slice(0,12);o.push({label:`out`,lines:e.map(e=>H(e)),...a.logs.length>e.length?{more:a.logs.length-e.length}:{}})}if(a!==void 0&&a.warnings.length>0){let e=a.warnings.slice(0,4);o.push({label:`warn`,lines:e.map(e=>H(e)),...a.warnings.length>e.length?{more:a.warnings.length-e.length}:{}})}if(a!==void 0&&a.imageCount>0){let e=a.imageCount===1?`1 image attached`:`${a.imageCount} images attached`;o.push({label:`image`,lines:[e]})}let c=a?.subCalls,l=c!==void 0&&c.length>0||o.length>0,u=cr({...e,details:a},!1,r,l,i.isPartial===!0);c!==void 0&&u.push(...sr(c,r));for(let e=0;e<o.length;e+=1){let t=e===o.length-1;u.push(...qn(o[e]??{label:``,lines:[]},t,r))}return new Rn(u)}function dr(e){return{renderCall(t,n,r){return nr(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?ur(e,r?.args??{},r?.isError===!0,n,{isPartial:i}):lr(e,r?.isError===!0,n,{isPartial:i})}}}const fr=["Run a TypeScript program that composes pi's tools in one shot. Required arguments: `code` —","the body of an async function (top-level `return` and `await` work; type annotations are","advisory, the code runs type-stripped) — and `description`, a 5-10 word summary of what the",`program does.`,``,"Inside the program, call this session's enabled built-in tools as `tools.<name>(args)` — e.g.",'`await tools.read({ path: "src/index.ts" })` or `await tools.bash({ command: "npm test" })`.',"The bound names mirror the session's active tools (a default session has `read`, `bash`, `edit`,","`write`); independent calls may overlap under `Promise.all`.",``,"The parallel binding `pi.dispatch` is always available, registered under its literal dot name —",'call it with string indexing, e.g. `await tools["pi.dispatch"]({ agent: "reviewer", task: "..." })`;',"`tools.pi.dispatch` does not exist. It fans work out to child pi agents, and independent","foreground dispatches compose under `Promise.all` exactly like the built-in calls. The run's","actual bound names (this run, not a static list) are on the `ptcBindings` global, so the program",`never has to guess what is bound.`,``,an,``,"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(`
|
|
29
|
+
`),pr=x.Object({code:x.String({description:`The program: the body of an async TypeScript function.`}),description:x.String({description:`Clear, concise description of what this program does in active voice, 5-10 words (shown in the UI).`}),timeoutMs:x.Optional(x.Number({description:`Elapsed deadline in milliseconds for the whole run, including tool calls. Omit it (or pass 0) for the default of ${I.timeoutMs/1e3} s; anything above ${I.maxTimeoutMs/1e3} s is capped. The deadline bounds the whole run: if it expires, in-flight foreground dispatches spawned by the program are terminated with it.`}))});function mr(e={}){return g({name:`ptc_run_code`,label:`PTC Run Code`,description:fr,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:[...wn],parameters:pr,async execute(t,n,r,i,a){let o=En(a),s=U(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 tn({code:n.code,surface:`run_code`,cwd:o,bindings:Ut({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 kn(p);return An({outcome:p,surface:`run_code`,durationMs:Date.now()-c})},...dr(`run_code`)})}const hr=[`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.",``,an,``,`Image-bearing tool results inside the script are attached to you after the run — never return`,`image data as the script's value.`].join(`
|
|
30
|
+
`),gr=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 _r(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=vr(t[e],`args.${e}`,/* @__PURE__ */ new Set);if(n!==void 0)throw TypeError(`ptc_workflow args must be plain JSON: ${n}`)}}}function vr(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=vr(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=vr(i[e],`${n}.${e}`,r);if(t!==void 0)return t}return}finally{r.delete(i)}}function yr(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 br(e={}){return g({name:`ptc_workflow`,label:`PTC Workflow`,description:hr,promptSnippet:`Run a structured TypeScript workflow with named phases, narration (log/phase) and structured concurrency (parallel/pipeline)`,promptGuidelines:[...wn],parameters:gr,async execute(t,n,r,i,a){_r(n.args);let o=En(a),s=U(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 tn({code:n.script,surface:`workflow`,cwd:o,bindings:Ut({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 kn(p);let m=n.meta.phases?.map(e=>e.name);return An({outcome:p,surface:`workflow`,warnings:yr(p,m),durationMs:Date.now()-c})},...dr(`workflow`)})}var xr=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 Sr(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}var Cr=class{#e;constructor(e){if(e.length===0)throw TypeError(`FileOutputStorage: baseDir is required`);this.#e=e}async readOutput(e){try{return await he(this.#t(e),`utf8`)}catch(e){if(Sr(e))return null;throw e}}async writeOutput(e,t){let n=O(this.#e,`tasks`,e);await me(n,{recursive:!0}),await ye(O(n,`output.log`),t,`utf8`)}outputRef(e){return this.#t(e)}#t(e){return O(this.#e,`tasks`,e,`output.log`)}};function wr(e,t){return ln(e,`pi-ptc-task-output-`,t===void 0?{}:{fullText:t})}const Tr={running:`accent`,stopping:`warning`,succeeded:`success`,failed:`error`,lost:`dim`,canceled:`muted`},Er={running:`●`,stopping:`◐`,succeeded:`✓`,failed:`✗`,lost:`◌`,canceled:`⊘`};var K=class{items;constructor(e){this.items=e}invalidate(){}render(e){let t=Math.max(1,Math.floor(e));return this.items.map(e=>Dr(e,t))}};function Dr(e,t){let{left:n,right:r}=e;if(r===void 0)return P(n,t,`…`);let i=F(r);if(i>=t)return P(r,t,`…`);let a=P(n,Math.max(0,t-i-1),`…`),o=Math.max(1,t-i-F(a));return a+` `.repeat(o)+r}function Or(e,t){return e.length>t?`${e.slice(0,t-1)}…`:e}function kr(e){return Or((H(e).split(`
|
|
31
|
+
`).find(e=>e.trim().length>0)??``).trim(),120)}function Ar(e){return typeof e==`object`&&e?e:{}}function jr(e){return e===`running`||e===`stopping`}function Mr(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 Nr(e,t){if(jr(e.status))return Mr(t-e.createdAt);if(e.durationMs!==void 0)return Mr(e.durationMs);if(e.finishedAt!==void 0)return Mr(e.finishedAt-e.createdAt)}function Pr(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 Fr(){}function Ir(e,t,n){return new K([{left:`└─ ${n.fg(`toolTitle`,n.bold(e))}${t.length>0?` ${t}`:``}`}])}function Lr(e,t,n){let r=Ar(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 Ir(`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 Ir(`PTC task output`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}case`task-stop`:{let e=typeof r.taskId==`string`&&r.taskId.length>0?r.taskId:void 0,t=typeof r.reason==`string`&&r.reason.length>0?` · reason=${H(r.reason)}`:``;return Ir(`PTC task stop`,e===void 0?n.fg(`muted`,`(unknown task)`):`${n.fg(`accent`,e)}${n.fg(`dim`,t)}`,n)}}}function Rr(e,t,n,r){let i=Tr[e.status]??`muted`,a=n.fg(i,Er[e.status]??`?`),o=Or(H(e.label),48),s=[`${a} ${n.fg(`text`,o)}`,n.fg(`dim`,H(e.agentName))],c=Nr(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 zr(e,t){let n=Ar(e),r=Array.isArray(n.tasks)?n.tasks:[];if(r.length===0)return Pr(new K([{left:` ${t.theme.fg(`muted`,`(no background tasks)`)}`}]),{isLive:!1,state:t.state,requestInvalidate:t.requestInvalidate});let i=r.some(e=>jr(e.status)),a=r.slice(0,32),o=r.length-a.length,s=a.map((e,n)=>Rr(e,n===a.length-1&&o===0,t.theme,t.now));return o>0&&s.push({left:` └─ ${t.theme.fg(`dim`,`…+${o} more tasks`)}`}),Pr(new K(s),{isLive:t.partial&&i,state:t.state,requestInvalidate:t.requestInvalidate})}function Br(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 Vr(e,t){return` ${t.fg(`dim`,`full output: `)}${t.fg(`accent`,e)}`}function Hr(e,t){let n=Ar(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=Br(i,a,t.theme),c=[];if(r.length>0){let e=H(r).split(`
|
|
32
|
+
`),n=e.slice(0,6);n.forEach((e,n)=>{let r=t.theme.fg(`toolOutput`,Or(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:Vr(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:Vr(o,t.theme),...s===void 0?{}:{right:s}});return new K(c)}function Ur(e,t){let n=Ar(e),r=n.task;if(typeof r!=`object`||!r)return new K([{left:` ${t.theme.fg(`muted`,`(no task)`)}`}]);let i=Tr[r.status]??`muted`,a=t.theme.fg(i,Er[r.status]??`?`),o=typeof n.fromStatus==`string`?n.fromStatus:void 0,s=o===void 0?r.status===`stopping`?`running → stopping`:`→ ${String(r.status)}`:`${o} → ${r.status}`,c=[`${a} ${t.theme.fg(`text`,H(r.id))}`,t.theme.fg(i,s)];return typeof r.stopReason==`string`&&r.stopReason.length>0&&c.push(t.theme.fg(`dim`,`reason=${H(r.stopReason)}`)),new K([{left:` ${c.join(` `)}`}])}function Wr(e,t){let n=e.content?.find(e=>e.type===`text`&&(e.text??``).length>0),r=kr(n?.text??``)||`failed`;return new K([{left:` ${t.fg(`error`,`failed: ${r}`)}`}])}function Gr(e,t,n){switch(e){case`task-list`:return zr(t.details,n);case`task-output`:return Hr(t.details,n);case`task-stop`:return Ur(t.details,n)}}function Kr(e){return{renderCall(t,n){return Lr(e,t,n)},renderResult(t,n,r,i){return i?.isError===!0?Wr(t,r):Gr(e,t,{theme:r,partial:n?.isPartial===!0||i?.isPartial===!0,requestInvalidate:i?.invalidate??Fr,state:i?.state??{},now:Date.now()})}}}const qr=[`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.`],Jr=x.Union([x.Literal(`running`),x.Literal(`stopping`),x.Literal(`succeeded`),x.Literal(`failed`),x.Literal(`canceled`),x.Literal(`lost`)]),Yr=x.Object({status:x.Optional(x.Array(Jr,{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.`}))}),Xr=x.Object({tasks:x.Array(x.Object({id:x.String({description:`The task's ULID — the id ptc_task_output and ptc_task_stop take.`}),status:x.String({description:`One of running, stopping, succeeded, failed, canceled, lost (ADR-0022 §2).`}),agent:x.String({description:`The agent the task was dispatched with (the record's agentName).`}),depth:x.Number({description:`0 for a direct child of the session, 1 for a grandchild, and so on (ADR-0016).`}),label:x.String({description:`The label the task was dispatched with.`}),output_bytes:x.Optional(x.Number({description:`Captured output size; absent while the task has flushed no output.`})),error_message:x.Optional(x.String({description:`Failure text; absent unless the record carries an error.`}))}),{description:`One row per task, newest first — the same order as details.tasks.`}),count:x.Number({description:"Number of rows in `tasks`."})});function Zr(e){return{id:e.id,status:e.status,agent:e.agentName,depth:e.depth,label:e.label,...e.outputBytes===void 0?{}:{output_bytes:e.outputBytes},...e.errorMessage===void 0?{}:{error_message:e.errorMessage}}}function Qr(e){let t=[e.id,e.status,`${e.agentName} depth=${e.depth}`,H(e.label)];return e.outputBytes!==void 0&&t.push(`${e.outputBytes}B`),e.errorMessage!==void 0&&t.push(`error=${H(e.errorMessage)}`),t.join(` `)}function $r(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(`
|
|
33
|
+
`),promptSnippet:`List background tasks and their live status (id, status, agent, label, output size)`,promptGuidelines:[...qr],parameters:Yr,outputSchema:Xr,async execute(t,n){let r=await e.query({...n.status===void 0?{}:{status:n.status},limit:n.limit??100,orderBy:`createdAt-desc`}),i=r.length===0?`(no background tasks)`:r.map(e=>Qr(e)).join(`
|
|
34
|
+
`),a={tasks:r.map(e=>Zr(e)),count:r.length};return{content:[{type:`text`,text:i}],details:{tasks:r,count:r.length},structuredContent:a}},...Kr(`task-list`)})}async function ei(e,t,n){let r=await e.get(t);if(r===null)throw Error(`${n}: unknown taskId ${t}`);return r}const ti=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.`}))}),ni=x.Object({task_id:x.String({description:`The background task id that was asked for.`}),status:x.String({description:`The task's status at read time (ADR-0022 §2's six states), so a polling script does not need a second ptc_task_list call.`}),output:x.String({description:`The page the model reads: the stored output's tail, ADR-0015-truncated.`}),output_bytes:x.Number({description:`Total bytes stored for the task, regardless of sinceBytes or ADR-0015 truncation.`}),output_preview:x.Optional(x.String({description:`The complete stored output; present only at or below the 2048-byte preview ceiling (ADR-0022 §7).`})),output_truncated:x.Boolean({description:"Whether ADR-0015 cut anything out of `output`."}),output_full_path:x.Optional(x.String({description:"A file holding the complete output; present only when `output_truncated` is true (ADR-0015 §2)."}))});function ri(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(`
|
|
35
|
+
`),promptSnippet:`Read a background task's output (tail-truncated, with the full-output file path)`,promptGuidelines:[...qr],parameters:ti,outputSchema:ni,async execute(n,r){let i=r.taskId,a=await ei(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=wr(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}},p=f.output.length>0?f.output:`(no output yet; task ${i} is ${a.status})`,m={task_id:i,status:a.status,output:u.text,output_bytes:s,...d===void 0?{}:{output_preview:d},output_truncated:u.truncated,...u.fullPath===void 0?{}:{output_full_path:u.fullPath}};return{content:[{type:`text`,text:p}],details:f,structuredContent:m}},...Kr(`task-output`)})}const ii=x.Object({taskId:x.String({description:`The running task's id (as returned by ptc_task_list or the dispatch handle).`}),reason:x.Optional(x.String({description:`Why the task is being stopped; recorded as the task's stopReason. Defaults to "model stop".`}))}),ai=x.Object({task_id:x.String({description:`The background task id that was asked to stop.`}),status:x.String({description:"The task's status AFTER the stop command — `stopping`, not the terminal `canceled`; the dispatcher pump owns the latter (ADR-0022 §8)."}),from_status:x.String({description:"The status observed before the stop: `running` for a fresh stop, `stopping` for the idempotent late-arrival path (ADR-0022 §8)."}),stop_reason:x.Optional(x.String({description:`The reason recorded as the task's stopReason; absent when the record carries none.`}))});function oi(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(`
|
|
36
|
+
`),promptSnippet:`Ask a background task to stop (dispatcher delivers the signal)`,promptGuidelines:[...qr],parameters:ii,outputSchema:ai,async execute(t,n){let i=n.taskId,a=await ei(e,i,`ptc_task_stop`),o=a.spawnSource.callerId.length>0?a.spawnSource.callerId:`ptc_task_stop`,{record:s,fromStatus:c}=await e.transition({kind:`stop`,taskId:i,reason:n.reason??`model stop`},{clock:r,callerId:o}),l=s.stopReason===void 0?``:` reason=${H(s.stopReason)}`,u=c??a.status,d={task_id:i,status:s.status,from_status:u,...s.stopReason===void 0?{}:{stop_reason:s.stopReason}};return{content:[{type:`text`,text:`${s.id} ${s.status}${l}`}],details:{task:s,fromStatus:u},structuredContent:d}},...Kr(`task-stop`)})}var si=class{#e;#t=/* @__PURE__ */ new Map;constructor(e={}){this.#e=Re(e.config)}get(e){let t=this.#t.get(e);if(t!==void 0)return t;let n=Le(),r=new Kt({buildWorkerUrl:Yt,size:this.#e.poolSize,acquireTimeoutMs:this.#e.poolAcquireTimeoutMs,drainGraceMs:this.#e.drainGraceMs,workerOptions:Gt({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 ci={warn:e=>{console.warn(`[pi-ptc.notifications] `+e)}};var li=class{#e;#t;#n;#r;#i;constructor(e,t={}){this.#e=e,this.#t=t.now??Date.now,this.#n=t.logger??ci,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 ui={mkdir:(e,t)=>me(e,t),readFile:(e,t)=>he(e,t),writeFile:(e,t,n)=>ye(e,t,n),appendFile:(e,t,n)=>pe(e,t,n),rename:(e,t)=>_e(e,t),unlink:e=>ve(e),readdir:e=>ge(e)};function di(e){return typeof e==`object`&&!!e&&e.code===`ENOENT`}function fi(e){return e instanceof Error?e.message:String(e)}function pi(e,t){return e.eventId<t.eventId?-1:+(e.eventId>t.eventId)}var mi=class{#e;#t;constructor(e,t={}){if(e.length===0)throw TypeError(`FileTaskStorage: baseDir is required`);this.#e=e,this.#t=t.fs??ui}async loadTask(e){return await this.#r(this.#f(e))}async saveTask(e){N(e,`saveTask: record is required`),await this.#o(this.#f(e.id),e)}async deleteTask(e){let t=this.#f(e);if(!await this.#c(t))throw Error(`deleteTask: unknown taskId `+e);await this.#t.unlink(t)}async*listTasks(e){let t=this.#l();for(let n of(await this.#s(t)).sort()){if(!n.endsWith(`.json`))continue;let r=await this.#r(O(t,n));r!==null&&(e?.status===void 0||r.status===e.status)&&(e?.label===void 0||r.label===e.label)&&(yield r)}}async loadSubscription(e,t){return await this.#r(this.#p(e,t))}async saveSubscription(e){N(e,`saveSubscription: sub is required`),await this.#o(this.#p(e.subscriberId,e.taskId),e)}async appendEvents(e,t){if(t.length===0){if((await this.#n(e)).length===0)throw Error(`appendEvents: unknown subscriptionId `+e);return}let n=/* @__PURE__ */ new Map;for(let e of t){let t=n.get(e.taskId);t===void 0?n.set(e.taskId,[e]):t.push(e)}let r;for(let t of n.keys())if(await this.loadSubscription(e,t)===null){r=t;break}if(r!==void 0)throw(await this.#n(e)).length===0?Error(`appendEvents: unknown subscriptionId `+e):Error(`appendEvents: no subscription for subscriber `+e+` on task `+r);await this.#t.mkdir(this.#d(),{recursive:!0});for(let[t,r]of n){let n=(r.every((e,t)=>t===0||pi(r[t-1],e)<=0)?r:[...r].sort(pi)).map(e=>JSON.stringify(e)).join(`
|
|
37
37
|
`)+`
|
|
38
|
-
`;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(
|
|
39
|
-
`)){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+`: `+
|
|
40
|
-
`);return`${`<bg-task-notifications batch-id="${
|
|
41
|
-
`)}function
|
|
42
|
-
`,` `).replaceAll(`\r`,` `)}function
|
|
38
|
+
`;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(pi);for(let e of r)t!==void 0&&e.eventId<=t||(yield e)}async#n(e){let t=this.#u(),n=[];for(let r of await this.#s(t)){if(!r.endsWith(`.json`))continue;let i=await this.#r(O(t,r));i!==null&&i.subscriberId===e&&n.push(i)}return n}async#r(e){let t;try{t=await this.#t.readFile(e,{encoding:`utf8`})}catch(e){if(di(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+`: `+fi(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(di(e))return[];throw e}let n=[];for(let r of t.split(`
|
|
39
|
+
`)){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+`: `+fi(t))}if(typeof i!=`object`||!i||Array.isArray(i))throw Error(`FileTaskStorage: corrupt event JSON in `+e+`: expected a JSON object`);n.push(i)}return n}async#o(e,t){await this.#t.mkdir(ae(e),{recursive:!0});let n=e+`.tmp-`+M();await this.#t.writeFile(n,JSON.stringify(t,null,2),{encoding:`utf8`}),await this.#t.rename(n,e)}async#s(e){try{return await this.#t.readdir(e)}catch(e){if(di(e))return[];throw e}}async#c(e){try{return await this.#t.readFile(e,{encoding:`utf8`}),!0}catch(e){if(di(e))return!1;throw e}}#l(){return O(this.#e,`tasks`)}#u(){return O(this.#e,`subscriptions`)}#d(){return O(this.#e,`events`)}#f(e){return O(this.#l(),e+`.json`)}#p(e,t){return O(this.#u(),e+`-`+t+`.json`)}#m(e,t){return O(this.#d(),e+`-`+t+`.jsonl`)}};function hi(e,t){return new mi(e,t)}const gi=/* @__PURE__ */ new Set([`succeeded`,`failed`,`canceled`,`lost`]),_i=/* @__PURE__ */ new Set([`running`,`stopping`]),vi=2**53-1,yi={info:()=>void 0,warn:e=>{console.warn(`[pi-ptc.background] `+e)}};function q(e){return e instanceof Error?e.message:String(e)}function bi(e){return e===void 0||e.length===0?`<in-memory>`:e}function xi(e){let t=e.spawnSource.callerId;return t.length>0?t:e.id}var Si=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()}},Ci=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)}},wi=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)}},Ti=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]}},Ei=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??yi,this.#r=e.owner??{pid:process.pid,bootMs:this.clock()},this.#i=e.isPidAlive??Ye,this.#t=e.createStorage??(e=>e===void 0||e.length===0?new tt:hi(e)),this.#n=e.createOutputStorage??(e=>e===void 0||e.length===0?new xr:new Cr(e));let t=(e.createInitialStorage??(()=>new tt))(),n=Qe(t,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),r=new li(t,{now:this.clock,logger:this.#e});this.registry=new Si(n),this.outputStorage=new Ci(new xr),this.pipeline=new wi(r),this.lifecycle=new Ti((e.createLifecycle??(()=>new Fe({logger:this.#e})))()),this.slots=new rt(e.concurrency??I.dispatchConcurrency),this.dispatchDeps={taskRegistry:this.registry,lifecycle:this.lifecycle,slots:this.slots,outputStorage:this.outputStorage,clock:this.clock,logger:this.#e},this.registry.onTransition(this.#o)}#o=(e,t)=>{this.#a||gi.has(e.status)&&this.pipeline.notifyIdle(t.subscriptionId,e.id).catch(t=>{this.#e.warn(`terminal notification wake for task `+e.id+` failed: `+q(t))})};async bindSession(e,t){let n,r;try{n=this.#t(e),r=this.#n(e)}catch(n){return this.#s(`background runtime: session storage for `+bi(e)+` is unavailable: `+q(n),t),[]}let i=Qe(n,{clock:this.clock,logger:this.#e,owner:this.#r,isPidAlive:this.#i}),a=new li(n,{now:this.clock,logger:this.#e});this.registry.setCurrent(i),this.outputStorage.setCurrent(r),this.pipeline.setCurrent(a),this.#a=!1;try{return await i.reconcileLostTasks()}catch(e){return this.#s(`background runtime: startup reconcile failed; stale running tasks were not all marked lost (reconcile is not per-record tolerant yet): `+q(e),t),[]}finally{this.registry.onTransition(this.#o)}}async drainNotifications(e){let t;try{t=await this.registry.query({limit:vi})}catch(t){return this.#e.warn(`drainNotifications: could not list tasks for subscriber `+e+`: `+q(t)),{items:[],acks:[]}}let n=[],r=[],i=this.pipeline.current();for(let a of t){if(a.spawnSource.callerId!==e)continue;let t;try{t=await i.drainPending(e,a.id)}catch(t){this.#e.warn(`drainNotifications: task `+a.id+` for subscriber `+e+`: `+q(t));continue}for(let e of t)n.push({event:e,record:a});let o=t[t.length-1];o!==void 0&&r.push({subscriberId:e,taskId:a.id,cursor:o.eventId,sink:i})}return{items:n,acks:r}}async acknowledgeNotifications(e){for(let t of e)try{await t.sink.acknowledgeEvents(t.subscriberId,t.taskId,t.cursor)}catch(e){this.#e.warn(`acknowledgeNotifications: could not acknowledge task `+t.taskId+`: `+q(e))}}async shutdown(e){if(this.#a)return[];this.#a=!0;let t;try{t=await this.registry.query({limit:vi})}catch(e){this.#e.warn(`shutdown: could not list tasks: `+q(e)),t=[]}let n=[];for(let r of t)if(_i.has(r.status)&&Je(r,this.#r))try{let t=await this.registry.transition({kind:`reconcile-lost`,taskId:r.id,reason:e},{clock:this.clock,callerId:xi(r),logger:this.#e});n.push(t.record)}catch(e){this.#e.warn(`shutdown: could not mark task `+r.id+` lost: `+q(e))}for(let e of this.lifecycle.liveHandles()){let t=dt(this.lifecycle,e,{isDone:()=>!this.lifecycle.isLive(e),unref:!0});this.lifecycle.trackReapCancel(e,t)}for(let e of n)this.slots.release(e.id);return n}#s(e,t){if(this.#e.warn(e),t!==void 0)try{t(e)}catch(e){this.#e.warn(`bindSession reporter threw: `+q(e))}}};function Di(e={}){return new Ei(e)}const Oi=/* @__PURE__ */ new Set([`succeeded`,`failed`,`lost`]);function ki(e){return Oi.has(e.status)}function Ai(e,t){if(e.length===0)return``;let n=e.map(Mi).join(`
|
|
40
|
+
`);return`${`<bg-task-notifications batch-id="${J(t.batchId)}" delivered-at-ms="${t.deliveredAtMs}">`}\n${n}\n</bg-task-notifications>`}function ji(e,t=102400){let n=[],r=[],i=0,a=t-Pi;for(let t of e){let e=Ni(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 Mi(e){let{event:t,record:n}=e,r=t.outputBytes??n.outputBytes,i=r??0,a=t.outputPreview??n.outputPreview,o=[` <bg-task-notification`,` id="${J(t.type)}"`,` task-id="${J(t.taskId)}"`,` subscription-id="${J(t.subscriptionId)}"`,` status="${J(t.status)}"`,` label="${J(n.label)}"`,` agent-name="${J(n.agentName)}"`,` depth="${n.depth}"`,` duration-ms="${n.durationMs??0}"`,` transition-at-ms="${t.transitionAtMs}">`,` <output-bytes>${i}</output-bytes>`];return n.outputRef!==void 0&&o.push(` <output-ref>${J(n.outputRef)}</output-ref>`),r!==void 0&&r<=2048&&a!==void 0&&o.push(` <output-preview>${J(a)}</output-preview>`),o.push(` </bg-task-notification>`),o.join(`
|
|
41
|
+
`)}function J(e){return e.replaceAll(`&`,`&`).replaceAll(`<`,`<`).replaceAll(`"`,`"`).replaceAll(` `,`	`).replaceAll(`
|
|
42
|
+
`,` `).replaceAll(`\r`,` `)}function Ni(e){return Buffer.byteLength(Mi(e),`utf8`)}const Pi=Buffer.byteLength(`<bg-task-notifications batch-id="${`0`.repeat(26)}" delivered-at-ms="${`9`.repeat(13)}">\n\n</bg-task-notifications>`,`utf8`),Fi=[`ptc_run_code`,`ptc_workflow`],Ii=[`read`,`bash`,`edit`,`write`],Li=`ptc-mode`,Ri=`ptc-mode`,Y=`ptc.json`,zi=`builtins-only`;function Bi(){return{enabled:!1,base:void 0,ourLoadout:void 0}}function Vi(e){let t=O(e,Y),n;try{n=T(t,`utf8`)}catch{return{defaultMode:!0,source:`default`}}let r;try{r=JSON.parse(n)}catch(e){return{defaultMode:!0,source:`invalid`,error:`${t} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof r!=`object`||!r||Array.isArray(r))return{defaultMode:!0,source:`invalid`,error:`${t} must contain a JSON object`};let i=r.defaultMode;return i===void 0?{defaultMode:!0,source:`default`}:typeof i==`boolean`?{defaultMode:i,source:`file`}:{defaultMode:!0,source:`invalid`,error:`${t}: "defaultMode" must be a boolean, received ${typeof i}`}}const X=[`off`,`subagents`,`full`],Hi=`full`,Z=`builtin:codemode`;function Q(e){return e.split(j).join(`/`)}function Ui(e){return Q(e.startsWith(`./`)||e.startsWith(`.\\`)?e.slice(2):e)}function Wi(e,t,n){let r=Q(k(n,e)),i=ie(e),a=Q(e);return t.some(e=>{let t=Q(e);return be(r,t)||be(i,t)||be(a,t)})}function Gi(e,t,n){if(t.length===0)return!1;let r=Q(k(n,e)),i=Q(e);return t.some(e=>{let t=Ui(e);return t===r||t===i})}function Ki(e){let t=[];for(let n of e){if(typeof n!=`string`)continue;let e=n[0];(e===`+`||e===`-`||e===`!`)&&t.push({sign:e,target:n.slice(1)})}return t}function qi(e,t){if(!Array.isArray(e))return;let n;for(let{sign:r,target:i}of Ki(e)){let e=r!==`-`&&r!==`!`;(r===`+`||r===`-`?Gi(Z,[i],t):Wi(Z,[i],t))&&(n=e?`enabled`:`disabled`)}return n}function Ji(e,t){if(!Array.isArray(e))return;let n=Ki(e),r=e=>n.filter(t=>t.sign===e).map(e=>e.target),i=r(`!`),a=r(`+`),o=r(`-`),s;return Wi(Z,i,t)&&(s=`disabled`),Gi(Z,a,t)&&(s=`enabled`),Gi(Z,o,t)&&(s=`disabled`),s}function Yi(e){for(let t=0;t<e.length;t+=1){let n=e[t];if((n===`-e`||n===`--extension`)&&e[t+1]===Z)return!0}return!1}function Xi(e){let t;try{t=T(e,`utf8`)}catch{return{value:void 0}}try{let n=JSON.parse(t);return typeof n!=`object`||!n||Array.isArray(n)?{value:void 0,error:`${e} must contain a JSON object`}:{value:n}}catch(t){return{value:void 0,error:`${e} is not valid JSON (${t instanceof Error?t.message:String(t)})`}}}function Zi(e,t,n,r={project:process.cwd(),user:process.cwd()}){let i=e.slice(1);if(Yi(i))return{switch:`enabled`,source:`cli`};if(i.some(e=>e===`-ne`||e===`--no-extensions`))return{switch:`disabled`,source:`cli`};let a=t?.extensions,o=qi(a,r.project);if(o!==void 0)return{switch:o,source:`project`};let s=n?.extensions,c=Ji(s,r.user);return c===void 0?{switch:`absent`,source:`default`}:{switch:c,source:`user`}}function Qi(e,t,n=process.argv){let r=Xi(O(t,`.pi`,`settings.json`)),i=Xi(O(e,`settings.json`)),a=Zi(n,r.value,i.value,{project:O(t,`.pi`),user:e}),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}const $i=[`read`,`bash`,`edit`,`write`];function ea(e){return typeof e==`string`&&(e.startsWith(`+`)||e.startsWith(`-`))}function ta(e){return Array.isArray(e)?e.filter(e=>typeof e==`string`):[]}function na(e,t){return t===void 0?e:!Array.isArray(e)||!Array.isArray(t)||!t.every(ea)?t:[...e,...t]}function ra(e){let t=e.filter(e=>!ea(e)),n=t.length>0||e.length===0?t:[...$i];for(let t of e){if(!ea(t))continue;let e=t.slice(1),r=n.indexOf(e);t.startsWith(`+`)&&r===-1&&e?n.push(e):t.startsWith(`-`)&&r!==-1&&n.splice(r,1)}return n}function ia(e){for(let t=0;t<e.length;t+=1){if(e[t]!==`--tools`&&e[t]!==`-t`)continue;let n=e[t+1];return n===void 0?void 0:n.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)}}function aa(e,t,n){let r=ia(e.slice(1));if(r!==void 0)return{activation:r.includes(`codemode`)?`active`:`inactive`,source:`cli`};let i=t?.defaultTools,a=n?.defaultTools,o=na(a,i);return o===void 0?{activation:`inactive`,source:`default`}:{activation:ra(ta(o)).includes(`codemode`)?`active`:`inactive`,source:i===void 0?`user`:`project`}}function oa(e,t,n=process.argv){let r=Xi(O(t,`.pi`,`settings.json`)),i=Xi(O(e,`settings.json`)),a=aa(n,r.value,i.value),o=r.error??i.error;return o===void 0?a:{...a,source:`invalid`,error:o}}function sa(e,t,n){return!e.present||t===`disabled`||n!==`active`?Hi:`subagents`}function ca(e,t){return e!==void 0&&e!==`off`&&e!==t}function la(e=process.argv){let t=e[1];if(t===void 0||t===``)return{present:!1,how:`no-entry`};let n;try{n=ee(t)}catch{return{present:!1,how:`unresolvable-entry`}}let r=ae(n);for(let e of ua){let t=O(r,...e);try{if(E(t).isDirectory())return{present:!0,how:`found`}}catch{}}return{present:!1,how:`not-found`}}const ua=[[`..`,`extensions`,`codemode`],[`..`,`..`,`extensions`,`codemode`],[`extensions`,`codemode`]];function da(e,t,n,r,i=process.cwd()){let a=O(e,Y),o=()=>{let a=t??la(),o=n??Qi(e,i),s=r??oa(e,i);return{surfaceMode:sa(a,o.switch,s.activation),codemode:a,codemodeSwitch:o,codemodeActivation:s}},s;try{s=T(a,`utf8`)}catch{return{...o(),source:`default`}}let c;try{c=JSON.parse(s)}catch(e){return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a} is not valid JSON (${e instanceof Error?e.message:String(e)})`}}if(typeof c!=`object`||!c||Array.isArray(c))return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a} must contain a JSON object`};let l=c.surfaceMode;if(l===void 0)return{...o(),source:`default`};if(typeof l!=`string`)return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a}: "surfaceMode" must be a string, received ${typeof l}`};if(!X.includes(l))return{surfaceMode:o().surfaceMode,source:`invalid`,error:`${a}: "surfaceMode" must be one of ${X.join(` | `)}, received ${JSON.stringify(l)}`};let u=o();return{surfaceMode:l,source:`file`,detected:u.surfaceMode,codemode:u.codemode,codemodeSwitch:u.codemodeSwitch,codemodeActivation:u.codemodeActivation}}function fa(e,t){let n=O(e,Y);if(typeof t!=`string`||!X.includes(t))return{ok:!1,path:n,error:`surfaceMode must be one of ${X.join(` | `)}`};let r=t,i;try{i=T(n,`utf8`)}catch{i=void 0}let a={};if(i!==void 0){let e;try{e=JSON.parse(i)}catch(e){return{ok:!1,path:n,error:`${n} is not valid JSON (${e instanceof Error?e.message:String(e)}), so it was left alone`}}if(typeof e!=`object`||!e||Array.isArray(e))return{ok:!1,path:n,error:`${n} must contain a JSON object, so it was left alone`};a=e}let o=a.surfaceMode,s=typeof o==`string`?o:void 0;if(s===r)return{ok:!0,path:n,previous:s,changed:!1};try{te(n,JSON.stringify({...a,surfaceMode:r},null,2)+`
|
|
43
|
+
`,`utf8`)}catch(e){return{ok:!1,path:n,error:`could not write ${n} (${e instanceof Error?e.message:String(e)})`}}return{ok:!0,path:n,previous:s,changed:!0}}function pa(e){return[...new Set(e)]}function ma(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 ha(e,t){let n=e=>Fi.includes(e);if(t===`all-but-ptc`)return pa(e.filter(n));let r=new Set(L);return pa(e.filter(e=>n(e)||!r.has(e)))}function ga(e){let{mode:t,defaultMode:n,active:r,manual:i}=e;return t===`tui`?!n&&!i?{enter:!1,reason:`config-off`}:Fi.some(e=>r.includes(e))?!i&&Ii.filter(e=>!r.includes(e)).length>0?{enter:!1,reason:`restricted-session`}:{enter:!0,base:pa(r),loadout:ha(r,e.hide??`builtins-only`)}:{enter:!1,reason:`tools-unavailable`}:{enter:!1,reason:`not-tui`}}function _a(e,t){return e.enabled&&e.base!==void 0?e.base:t}function va(e,t){return!e.enabled||e.ourLoadout===void 0?!1:!ma(e.ourLoadout,t)}function ya(e,t){let n=t.length>0&&t.every(e=>Fi.includes(e));return e?.enabled===!0&&n&&e.base!==void 0?{base:e.base,restoreFirst:!0}:{base:t,restoreFirst:!1}}function ba(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(`
|
|
43
44
|
`);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(`
|
|
44
|
-
`)}const
|
|
45
|
-
`),promptSnippet:`Start a fresh pi agent as a child process (foreground or background)`,promptGuidelines:[`Prefer one subagent over many tool calls when the work is a question with an answer rather than a fact you can look up, or when the raw output would be larger than the answer.`],parameters:
|
|
46
|
-
`)}function
|
|
45
|
+
`)}const xa=[`read`,`bash`],Sa=`Use the read tool to load a skill's file when the task matches its description.`,Ca=`Use tools.read({ path }) inside a ptc_run_code program to load a skill's file when the task matches its description.`;function wa(e){return!xa.some(t=>e.includes(t))}function Ta(e,t=v){let n=t([...e],`read`).trim();return n.length===0?``:n.includes(Sa)?n.replace(Sa,Ca):`${Ca}\n\n${n}`}const Ea=x.Object({task_id:x.Optional(x.String({description:`Id of the background task to poll with ptc_task_output. Present ONLY for a background call; absent once the call has already finished.`})),status:x.String({description:`"background" when this call returned a handle to poll, otherwise the dispatcher's own outcome status ("fulfilled").`}),exit_code:x.Optional(x.Number({description:`The child's exit code. Present ONLY for a call that already finished.`}))});function Da(e){let t=e.taskId;return typeof t==`string`?t:void 0}function Oa(e){return g({name:`ptc_subagent`,label:`PTC Subagent`,description:[`Start a fresh pi agent as a child process: it gets its own context, its own model and its own tools, and it cannot see or change this session except through what it returns. Use it for work that would otherwise flood this context: a survey, a second opinion, or a task that can run while you do something else.`].join(`
|
|
46
|
+
`),promptSnippet:`Start a fresh pi agent as a child process (foreground or background)`,promptGuidelines:[`Prefer one subagent over many tool calls when the work is a question with an answer rather than a fact you can look up, or when the raw output would be larger than the answer.`],parameters:Bt,outputSchema:Ea,async execute(t,n){let r=await Lt(n,{callId:0,cwd:n.cwd??e.cwd,depth:e.depth,maxDispatchDepth:e.maxDispatchDepth,...e.parentTaskId===void 0?{}:{parentTaskId:e.parentTaskId}},e.getDispatchDeps?.()??{}),i=Da(r),a=i===void 0?{taskId:void 0,status:r.status,exitCode:r.exitCode}:{taskId:i,status:`background`,exitCode:void 0};if(i!==void 0){let e={task_id:i,status:a.status};return{content:[{type:`text`,text:`Started background task `+i}],details:a,structuredContent:e}}if(r.status===`rejected`)throw Error(`ptc_subagent refused the call: `+r.errorMessage);let o=a.exitCode===void 0?{status:a.status}:{status:a.status,exit_code:a.exitCode};return{content:[{type:`text`,text:r.text}],details:a,structuredContent:o}}})}const $=zi;function ka(e,t){return[`PTC mode on — ${t===`all-but-ptc`?`all other tools`:`built-in tools (now reachable only as tools.<name> inside a program)`} hidden.`,`Bindings available inside a program: ${U(e).join(`, `)||`(none)`}.`,`Run /ptc off to restore the normal tool set.`].join(`
|
|
47
|
+
`)}function Aa(e,t={}){let n=Bi(),r=t.surfaceMode===void 0?da(y(),t.codemode,t.codemodeSwitch):{surfaceMode:t.surfaceMode,source:`file`},i=!1,a=new si,o=()=>_a(n,e.getActiveTools()),s=Sn(),c=Cn();if(r.surfaceMode===`off`)return;let l=t.backgroundRuntime??Di({concurrency:Re({}).dispatchConcurrency}),u=!1,d=e=>{console.warn(`[pi-ptc.background] `+e)},f=t=>{if(t.length!==0){if(u){e.sendMessage({customType:`bg-task-notification`,content:t,display:!1},{deliverAs:`steer`});return}e.sendUserMessage(t)}},p=async e=>{let{items:t,acks:n}=await l.drainNotifications(e),r=t.filter(e=>ki(e.record));for(let e of ji(r))f(Ai(e,{batchId:De(),deliveredAtMs:l.clock()}));await l.acknowledgeNotifications(n)},m=async()=>{let e=await l.registry.query({limit:2**53-1}),t=/* @__PURE__ */ new Set;for(let n of e){let e=n.spawnSource.callerId;e.length>0&&t.add(e)}return[...t]},h=async()=>{for(let e of await m())await p(e)},g=async e=>{let t=/* @__PURE__ */ new Set;for(let n of e){let e=n.spawnSource.callerId;e.length>0&&t.add(e)}for(let e of t)await p(e)};l.pipeline.onIdleWake(e=>{p(e).catch(e=>{d(`notification delivery failed: `+(e instanceof Error?e.message:String(e)))})}),r.surfaceMode===`full`&&(e.registerTool(mr({getBindingSourceNames:o,getPool:()=>a.get(`run_code`),depth:s,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps})),e.registerTool(br({getBindingSourceNames:o,getPool:()=>a.get(`workflow`),depth:s,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps}))),r.surfaceMode===`subagents`&&e.registerTool(Oa({cwd:process.cwd(),depth:s,maxDispatchDepth:I.maxDispatchDepth,...c===void 0?{}:{parentTaskId:c},getDispatchDeps:()=>l.dispatchDeps})),e.registerTool($r(l.registry)),e.registerTool(ri(l.registry,l.outputStorage)),e.registerTool(oi(l.registry,l.lifecycle,{clock:l.clock})),e.on(`turn_start`,async()=>{u=!0}),e.on(`agent_settled`,async()=>{u=!1;try{await h()}catch(e){d(`agent_settled delivery failed: `+(e instanceof Error?e.message:String(e)))}}),e.on(`turn_end`,async()=>{let e=a;a=new si,await e.drain()});let _=e=>{e.ui.setStatus(Ri,n.enabled?e.ui.theme.fg(`accent`,`PTC`):void 0)},v=(t,r,a,o)=>{n.enabled=!0,n.base=t,n.ourLoadout=r,e.setActiveTools([...r]),i=!0,e.appendEntry(Li,{enabled:!0,base:[...t]}),_(a),a.ui.notify(o,`info`)},b=(t,r)=>{let a=n.base;n.enabled=!1,n.base=void 0,n.ourLoadout=void 0,i=!1,a!==void 0&&e.setActiveTools([...a]),e.appendEntry(r.customType,{enabled:!1}),_(t),r.announce&&t.ui.notify(`PTC mode off — built-in tools are directly callable again.`,`info`)},x=e=>{let t=e.sessionManager.getEntries();for(let e=t.length-1;e>=0;--e){let n=t[e];if(n?.type!==`custom`||n.customType!==`ptc-mode`)continue;let r=n.data,i=Array.isArray(r?.base)?r.base.filter(e=>typeof e==`string`):void 0;return{enabled:r?.enabled===!0,...i===void 0?{}:{base:i}}}},S=async(e,t)=>{let r=y();if(e===``){let e=da(r),n=e.detected===void 0||e.detected===e.surfaceMode?``:` (detection would say `+JSON.stringify(e.detected)+`)`;t.ui.notify(`Extension surface: `+JSON.stringify(e.surfaceMode)+`, from `+e.source+n+`. Set it with /ptc surface `+X.join(`|`)+`; the change needs a reload, which this command performs.`,`info`);return}let i=fa(r,e);if(!i.ok){t.ui.notify(`pi-ptc-subagents: `+i.error+`. Nothing was changed.`,`warning`);return}if(!i.changed){t.ui.notify(`The surface is already `+JSON.stringify(e)+` — nothing written, nothing reloaded.`,`info`);return}let a=[`Surface `+(i.previous===void 0?`(unset, so detected)`:JSON.stringify(i.previous))+` → `+JSON.stringify(e)+` in `+i.path+`. Reloading so it takes effect now.`];n.enabled&&e!==`full`&&a.push(`PTC mode was ON and cannot survive this surface — run /ptc on afterwards.`),e===`subagents`&&a.push(`subagents hands orchestration to pi's codemode, so it needs codemode in this session's tool list; if it is not there the startup warning will say so.`),t.ui.notify(a.join(`
|
|
48
|
+
`),`info`),await t.reload()};e.registerCommand(`ptc`,{description:`Show or toggle PTC mode, or set the extension surface (/ptc surface off|subagents|full)`,handler:async(t,r)=>{let i=t.trim().toLowerCase();if(i===`surface`||i.startsWith(`surface `)){await S(i.slice(7).trim(),r);return}if(i===`off`){if(!n.enabled){r.ui.notify(`PTC mode is already off.`,`info`);return}b(r,{announce:!0,customType:Li});return}if(i!==`on`){r.ui.notify(n.enabled?`PTC mode is ON — run /ptc off to restore built-in tools.\nBindings: ${U(n.base).join(`, `)||`(none)`}`:`PTC mode is OFF — run /ptc on to enter it.`,`info`);return}if(n.enabled){r.ui.notify(`PTC mode is already on.`,`info`);return}let a=ga({mode:r.mode,defaultMode:!0,active:e.getActiveTools(),manual:!0,hide:$});if(!a.enter){r.ui.notify(a.reason===`tools-unavailable`?`Cannot enter PTC mode: ptc_run_code / ptc_workflow are not active in this session.`:`Cannot enter PTC mode in this run mode.`,`warning`);return}v(a.base,a.loadout,r,ka(a.base,$))}}),e.on(`session_start`,async(t,n)=>{u=!1;let i=await l.bindSession(n.sessionManager?.getSessionDir?.(),e=>n.ui.notify(e,`warning`));try{await g(i)}catch(e){d(`startup reconcile delivery failed: `+(e instanceof Error?e.message:String(e)))}let a=Vi(y());a.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${a.error}`,`warning`),r.error!==void 0&&r.error!==a.error&&n.ui.notify(`pi-ptc-subagents: ${r.error}`,`warning`);let o=r.codemode;if(o!==void 0&&!o.present&&n.ui.notify(`pi-ptc-subagents: no surfaceMode is set, and the codemode probe reported `+o.how+`, so the surface defaults to full. That is the safe direction, not an error. If this pi really does ship pi's own codemode, set "surfaceMode" in ptc.json -- an explicit key always wins over detection.`,`info`),r.codemodeSwitch?.error!==void 0&&n.ui.notify(`pi-ptc-subagents: ${r.codemodeSwitch.error}`,`warning`),r.source===`file`&&r.detected!==void 0&&ca(r.surfaceMode,r.detected)){let e=r.codemodeSwitch;n.ui.notify(`pi-ptc-subagents: surfaceMode is pinned to `+JSON.stringify(r.surfaceMode)+`, but this pi resolves to `+JSON.stringify(r.detected)+(e===void 0?``:` (pi's codemode is on disk and its switch is `+e.switch+`)`)+`. The pinned value is in force. Change it in ptc.json if that is not what you meant.`,`info`)}if(o!==void 0&&r.source!==`file`){let t=e.getAllTools().some(e=>e.name===`codemode`);!o.present&&t&&n.ui.notify(`pi-ptc-subagents: this session registers pi's codemode, but the probe did not find it (`+o.how+`), so the surface defaulted to full, and your model is being offered two orchestration tools. Set an explicit "surfaceMode" in ptc.json to pick one.`,`warning`),o.present&&!t&&n.ui.notify(`pi-ptc-subagents: the codemode probe found pi's codemode on disk, but this session does not register it (--no-extensions or --exclude-tools codemode), so the surface is `+JSON.stringify(r.surfaceMode)+(r.surfaceMode===`subagents`?` with no orchestrator. Set `+JSON.stringify(`surfaceMode`)+` to `+JSON.stringify(Hi)+` in ptc.json to use ptc_run_code instead.`:`.`),`warning`)}r.surfaceMode===`subagents`&&!e.getActiveTools().includes(`codemode`)&&n.ui.notify(`pi-ptc-subagents: surfaceMode is subagents, but codemode is not active in this session, so there is no orchestration tool. Add codemode to your pi tool list (the --tools flag or the default tools setting), or set surfaceMode to "full" to use ptc_run_code instead.`,`warning`);let s=x(n),{base:c,restoreFirst:f}=ya(s,e.getActiveTools());f&&e.setActiveTools([...c]);let p=ga({mode:n.mode,defaultMode:a.defaultMode,active:c,manual:!1,hide:$}),m=s?.enabled??p.enter;if(p.enter&&m){v(c,p.loadout,n,ka(c,$));return}_(n),!p.enter&&p.reason!==`not-tui`&&s===void 0&&p.reason===`restricted-session`&&n.ui.notify(`PTC mode skipped: this session was launched with an explicit tool restriction.`,`info`)}),e.on(`session_shutdown`,async()=>{u=!1;try{await l.shutdown(`session_ended_while_running`)}catch(e){d(`session shutdown failed: `+(e instanceof Error?e.message:String(e)))}});let C=!1,w=(e,t)=>{if(e===void 0)return;if(!n.enabled||!t){C&&=(delete e.sections.skills,!1);return}let r=Ta(e.skills);r.length!==0&&(e.sections.skills=r,C=!0)};e.on(`before_agent_start`,async(t,r)=>{let a=t.systemPromptOptions;if(w(a,wa(e.getActiveTools())),n.enabled){if(va(n,e.getActiveTools())){b(r,{announce:!1,customType:Li}),w(a,wa(e.getActiveTools())),r.ui.notify(`PTC mode off — another extension changed the active tool set.`,`warning`);return}if(i)return i=!1,{message:{customType:`ptc-mode-briefing`,content:ba(U(n.base),$),display:!1}}}})}export{L as BUILTIN_BINDING_NAMES,Rt as DEFAULT_BINDING_NAMES,I as DEFAULT_CONFIG,zi as DEFAULT_HIDE_STRATEGY,o as HOST_FRAME_KIND,un as MAX_LINE_CHARS,Ii as MODE_REQUIRED_TOOL_NAMES,n as PTC_ERROR_KIND,i as PTC_LOG_LEVEL,Y as PTC_MODE_CONFIG_FILE,Li as PTC_MODE_ENTRY_TYPE,Ri as PTC_MODE_STATUS_KEY,Fi as PTC_MODE_TOOL_NAMES,Ca as PTC_SKILL_LOAD_INSTRUCTION,xa as SKILL_READING_TOOL_NAMES,X as SURFACE_MODES,si as TurnPools,Ie as WORKER_ENV_ALLOW_LIST,t as WORKER_FRAME_KIND,Kt as WorkerPool,_a as bindingSource,ba as buildModeInstruction,Ta as buildPtcSkillsSection,Ut as createBuiltinBindings,Le as createWorkerEnv,ga as decideModeEntry,Aa as default,va as detectExternalLoadoutChange,ze as effectiveTimeoutMs,Bi as initialModeState,ha as modeLoadout,la as probeCodemodePresence,Qi as readCodemodeSwitch,Vi as readDefaultModeConfig,da as readSurfaceModeConfig,xn as renderModelValue,ya as resolveBaseOnStart,aa as resolveCodemodeActivation,Zi as resolveCodemodeSwitch,Re as resolveConfig,tn as runPtcProgram,ma as sameToolSet,H as sanitizeText,fa as setSurfaceMode,wa as skillsSectionDropped,fn as stripAnsi,ca as surfaceModeConflict};
|
|
47
49
|
//# sourceMappingURL=index.js.map
|