pi-ptc-subagents 3.3.1 → 3.3.2
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 +18 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.3.2] - 2026-10-18
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **The agent roster and agent discovery now name the same agents.** A `.md` file whose frontmatter
|
|
13
|
+
carried no `name:` was advertised by the roster under its file name and refused by dispatch as an
|
|
14
|
+
unknown agent — in the same message, because the refusal renders that roster. A model told an
|
|
15
|
+
agent exists could not dispatch it, and the self-contradicting refusal made the real cause hard to
|
|
16
|
+
read. Identity is the frontmatter `name:` and nothing else, which is what pi's own subagent loader
|
|
17
|
+
does: it skips a definition whose frontmatter has no string `name`, and never derives identity
|
|
18
|
+
from the file name. The roster now applies the same predicate `discoverAgent` applies, so the
|
|
19
|
+
invariant — for one scope, the names the roster lists are the names a dispatch resolves — holds by
|
|
20
|
+
construction rather than by two patches that happen to agree. A file that exists but cannot be
|
|
21
|
+
read is likewise no longer listed under its file name; it still emits a `console.warn`, so that
|
|
22
|
+
failure remains observable. **Behaviour change:** a file relying on the file-name fallback stops
|
|
23
|
+
appearing in the roster, in the refusal's registry listing, and in the `ptc_subagent` tool
|
|
24
|
+
description. Add a frontmatter `name:` to keep it dispatchable.
|
|
25
|
+
|
|
8
26
|
## [3.3.1] - 2026-10-16
|
|
9
27
|
|
|
10
28
|
### Changed
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./protocol-CfOgxz3u.js";
|
|
|
6
6
|
|
|
7
7
|
`+o}function ht(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch depth limit reached`}}function gt(){return{text:``,status:`rejected`,started:!1,agentName:`unknown`,durationMs:0,exitCode:-1,reportChannel:`none`,errorMessage:`dispatch concurrency limit reached`}}function _t(e,t,n={}){e.kill(t,`SIGTERM`);let r=setTimeout(()=>{n.isDone?.()!==!0&&e.kill(t,`SIGKILL`)},5e3);return n.unref===!0&&r.unref(),()=>clearTimeout(r)}function vt(){return{...ht(),errorMessage:`dispatch depth limit reached; next_step: call ptc_task_list to inspect the in-flight background tasks`}}function yt(){return{...gt(),errorMessage:`dispatch concurrency limit reached; next_step: call ptc_task_list to inspect running tasks and ptc_task_stop to free a slot`}}function bt(e){if(e!==void 0&&e.length!==0)return e.includes(`Response was truncated: the model reached its output token limit.`)?`child response was truncated at the model's output token limit (pi exited non-zero)`:void 0}function xt(e){if(e.aborted)return{status:`rejected`,errorMessage:`dispatch cancelled`};if(e.exitCode===0&&e.finalText.length>0)return{status:`fulfilled`};if(e.exitCode===0)return{status:`rejected`,errorMessage:`dispatch produced no final text`};let t=bt(e.stderr);return{status:`rejected`,...t===void 0?{}:{errorMessage:t}}}function St(e,t){let n=e.match(RegExp(`^`+t+`:\\s*(.+)$`,`m`));if(!n)return;let r=(n[1]??``).trim();if(r.length>=2){let e=r[0],t=r[r.length-1];(e===`"`&&t===`"`||e===`'`&&t===`'`)&&(r=r.slice(1,-1))}return r.length===0?void 0:r}function Ct(e,t){let n=e.match(RegExp(`^`+t+`:\\s*(.+)$`,`m`));if(!n)return;let r=(n[1]??``).trim();r.startsWith(`[`)&&r.endsWith(`]`)&&(r=r.slice(1,-1));let i=r.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);return i.length===0?void 0:i}function wt(e){let t=St(e,`childReport`);if(t!==void 0)return t.toLowerCase()!==`false`&&t.toLowerCase()!==`no`}function Tt(e){return e.childReport!==!1}function Et(e){let t=e.match(/^\uFEFF?[ \t]*(?:\r?\n)?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n([\s\S]*))?$/);if(!t)return null;let n=(t[1]??``).replace(/\r\n/g,`
|
|
8
8
|
`),r=(t[2]??``).replace(/\r\n/g,`
|
|
9
|
-
`),i=St(n,`name`);if(!i)return null;let a=St(n,`description`)??``,o=St(n,`model`)??``,s=Ct(n,`tools`),c=wt(n),l={name:i,systemPrompt:r.trim()};return a!==void 0&&(l.description=a),o!==void 0&&(l.model=o),s!==void 0&&(l.tools=s),c!==void 0&&(l.childReport=c),l}function Dt(e,t,n,r){let{userDir:i,projectDir:a}=Ot({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:O.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:O.join(a,e+`.md`),source:`project`});for(let t of o){let n;try{n=C.readFileSync(t.path,`utf-8`)}catch{continue}let r=Et(n);if(r&&r.name===e){let e={name:r.name,source:t.source,systemPrompt:r.systemPrompt};return r.model!==void 0&&(e.model=r.model),r.tools!==void 0&&(e.tools=r.tools),r.childReport!==void 0&&(e.childReport=r.childReport),e}}return null}function Ot(e){let t=e.homeDir??ne.homedir();return{userDir:O.join(t,`.pi`,`agent`,`agents`),projectDir:O.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function kt(e){let t=e?.code;return typeof t==`string`?t:String(e)}function At(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function jt(e,t){let n=O.resolve(e),r=O.resolve(t),i=e=>O.dirname(e),a=n,o=!1;for(let e=0;e<=8;e+=1){try{if(C.statSync(a).isDirectory()){o=!0;break}}catch{}if(a===r)break;let e=i(a);if(e===a)break;a=e}if(o){for(let e=n;e!==a&&e!==i(e);e=i(e))if(Mt(e))return!0;return!1}return a===r&&Mt(r)}function Mt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function Nt(e,t,n){let r=kt(n);return r!==`ENOENT`&&r!==`ENOTDIR`||At(e)?!1:!jt(e,t)}function Pt(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=Ot(e),a=[];(e.agentScope===`user`||e.agentScope===`both`)&&a.push({dir:t,boundary:r,source:`user`}),(e.agentScope===`project`||e.agentScope===`both`)&&a.push({dir:n,boundary:i,source:`project`});let o=/* @__PURE__ */ new Map;for(let{dir:e,boundary:t,source:n}of a){let r;try{r=C.readdirSync(e)}catch(n){if(!Nt(e,t,n)){let t=kt(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of r){if(!t.endsWith(`.md`))continue;let r=
|
|
9
|
+
`),i=St(n,`name`);if(!i)return null;let a=St(n,`description`)??``,o=St(n,`model`)??``,s=Ct(n,`tools`),c=wt(n),l={name:i,systemPrompt:r.trim()};return a!==void 0&&(l.description=a),o!==void 0&&(l.model=o),s!==void 0&&(l.tools=s),c!==void 0&&(l.childReport=c),l}function Dt(e,t,n,r){let{userDir:i,projectDir:a}=Ot({cwd:t,agentScope:n,homeDir:r?.homeDir}),o=[];(n===`user`||n===`both`)&&o.push({path:O.join(i,e+`.md`),source:`user`}),(n===`project`||n===`both`)&&o.push({path:O.join(a,e+`.md`),source:`project`});for(let t of o){let n;try{n=C.readFileSync(t.path,`utf-8`)}catch{continue}let r=Et(n);if(r&&r.name===e){let e={name:r.name,source:t.source,systemPrompt:r.systemPrompt};return r.model!==void 0&&(e.model=r.model),r.tools!==void 0&&(e.tools=r.tools),r.childReport!==void 0&&(e.childReport=r.childReport),e}}return null}function Ot(e){let t=e.homeDir??ne.homedir();return{userDir:O.join(t,`.pi`,`agent`,`agents`),projectDir:O.join(e.cwd,`.pi`,`agents`),userRoot:t,projectRoot:e.cwd}}function kt(e){let t=e?.code;return typeof t==`string`?t:String(e)}function At(e){try{return!C.statSync(e).isDirectory()}catch{try{return C.lstatSync(e),!0}catch{return!1}}}function jt(e,t){let n=O.resolve(e),r=O.resolve(t),i=e=>O.dirname(e),a=n,o=!1;for(let e=0;e<=8;e+=1){try{if(C.statSync(a).isDirectory()){o=!0;break}}catch{}if(a===r)break;let e=i(a);if(e===a)break;a=e}if(o){for(let e=n;e!==a&&e!==i(e);e=i(e))if(Mt(e))return!0;return!1}return a===r&&Mt(r)}function Mt(e){try{return C.lstatSync(e).isSymbolicLink()}catch{return!1}}function Nt(e,t,n){let r=kt(n);return r!==`ENOENT`&&r!==`ENOTDIR`||At(e)?!1:!jt(e,t)}function Pt(e){let{userDir:t,projectDir:n,userRoot:r,projectRoot:i}=Ot(e),a=[];(e.agentScope===`user`||e.agentScope===`both`)&&a.push({dir:t,boundary:r,source:`user`}),(e.agentScope===`project`||e.agentScope===`both`)&&a.push({dir:n,boundary:i,source:`project`});let o=/* @__PURE__ */ new Map;for(let{dir:e,boundary:t,source:n}of a){let r;try{r=C.readdirSync(e)}catch(n){if(!Nt(e,t,n)){let t=kt(n);console.warn(`pi.dispatch: cannot read agent directory ${e} (${t}); the agents registered there are not listed`)}continue}for(let t of r){if(!t.endsWith(`.md`))continue;let r=O.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}; skipping it`);continue}let a=Et(i);if(!a)continue;let s=a.name;s.length!==0&&(o.has(s)||o.set(s,{name:s,description:(a?.description??``).trim(),source:n}))}}return[...o.values()]}function Ft(e){return Pt(e).map(e=>e.name).sort()}function It(e){let t=Pt(e),n="`agent` is optional: omit it for a fresh generalist pi with pi's own system prompt and its full toolset. Name a definition to NARROW the child instead.";if(t.length===0)return n+` None are registered here, so there is nothing to name.`;let r=t.map(e=>{let t=e.description.length>0?e.description:`(no description given)`;return`- ${e.name} (${e.source} scope): ${t}`});return n+"\nRegistered definitions — pass `agentScope` matching the scope shown, since it defaults "+`to "user" and does not see the others:
|
|
10
10
|
`+r.join(`
|
|
11
11
|
`)}function Lt(e){let{userDir:t,projectDir:n}=Ot(e),r=Ft(e);return`registered agents: ${r.length>0?`[`+r.join(`, `)+`]`:`(none)`} — agents load from ${t}/<name>.md (user scope) or ${n}/<name>.md (project scope); register one as an agent markdown file: frontmatter header (\`---\\nname: <agent-name>\\n---\`) followed by the system prompt body`}function Rt(e){return{text:``,status:`rejected`,started:!1,agentName:``,durationMs:0,exitCode:1,reportChannel:`none`,errorMessage:`agent, when given, must be a non-empty string — omit it entirely to dispatch a generalist child; `+Lt(e)}}function zt(e){return e!==void 0&&(typeof e!=`string`||e.trim().length===0)}function Bt(e){return e===void 0}function Vt(e,t,n){if(Bt(e.agent))return{kind:`resolved`,agent:pt};let r=Dt(e.agent,t,n);return r?{kind:`resolved`,agent:r}:{kind:`unknown`,name:e.agent}}function Ht(e,t,n,r=0){return{text:``,status:`rejected`,started:!1,agentName:e,durationMs:r,exitCode:1,reportChannel:`none`,errorMessage:`unknown agent: `+e+` (agentScope=`+t+`, cwd=`+n+`). `+Lt({cwd:n,agentScope:t})}}function Ut(e,t){if(R(t)===`strict`)return Tt(e)?[...ut,Le]:ut;let n=e.tools??[];if(!Tt(e))return n.length>0?n:void 0;if(n.length!==0)return n.includes(`ptc_child_report`)?n:[...n,Le]}function Wt(e,t,n){let r=[`--mode`,`json`,`-p`,`--no-session`],i=e.model??t.model;i&&r.push(`--model`,i);let a=e.thinkingLevel??`off`;r.push(`--thinking`,a);let o=Ut(t,e.readOnly);return o!==void 0&&r.push(`--tools`,o.join(`,`)),r.push(`--append-system-prompt`,n),r.push(`Task: `+e.task),r}let Gt=Kt;async function Kt(e,t){let n=await C.promises.mkdtemp(O.join(ne.tmpdir(),`pi-dispatch-`)),r=e.replace(/[^\w.-]+/g,`_`),i=O.join(n,`prompt-`+r+`.md`);return await C.promises.writeFile(i,t,{encoding:`utf-8`,mode:384}),{dir:n,filePath:i}}function qt(e){try{C.unlinkSync(e.filePath)}catch{}try{C.rmdirSync(e.dir)}catch{}}function Jt(e){if(e.type!==`message_end`||e.message?.role!==`assistant`)return;let t=e.message.content;if(!Array.isArray(t))return;let n;for(let e of t)e&&e.type===`text`&&typeof e.text==`string`&&(n=e.text);return n}function Yt(e,t){if(t.type!==`message_end`)return e;let n=t.message;if(n?.role!==`assistant`||n.usage===void 0)return e;let r=e??{input:0,output:0,cacheRead:0,cacheWrite:0,cost:0,turns:0};return r.input+=n.usage.input??0,r.output+=n.usage.output??0,r.cacheRead+=n.usage.cacheRead??0,r.cacheWrite+=n.usage.cacheWrite??0,r.cost+=n.usage.cost?.total??0,r.turns+=1,r}function Xt(e){let t=[],n;for(let r of e.split(`
|
|
12
12
|
`)){let e=r.trim();if(n===void 0){let t=/^(`{3,}|~{3,})(.*)$/.exec(e);t&&(n={marker:(t[1]??``)[0],info:(t[2]??``).trim(),body:[]});continue}RegExp(`^`+n.marker+`{3,}\\s*$`).test(e)?(t.push({info:n.info,body:n.body.join(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-ptc-subagents",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.2",
|
|
4
4
|
"description": "Programmable tool calling (PTC) and subagent fan-out for pi — the model writes JS/TS programs that call pi's tools, or fans out to a fresh pi subprocess per subagent task",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi",
|