pi-herdsman 0.7.1 → 0.7.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/SKILL.md +17 -4
- package/dist/index.js +19 -6
- package/docs/concepts/delegation.md +22 -8
- package/docs/concepts/lifecycle.md +37 -14
- package/docs/development/smoke-testing.md +26 -9
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -73,10 +73,23 @@ assignment when practical. If genuinely new follow-up work emerges after
|
|
|
73
73
|
completion and previous context is valuable, continue the exact returned session
|
|
74
74
|
only when the completion is not marked retired. A retired session requires a
|
|
75
75
|
fresh delegation; pass its resultRef/handoff and relevant files instead.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
Each active delegated assignment has one executor: that agent. Do not repeat
|
|
77
|
+
its assigned work locally or delegate substantially overlapping work elsewhere.
|
|
78
|
+
|
|
79
|
+
After starting an agent assignment or receiving an agent result or attention
|
|
80
|
+
event, reassess the remaining work. Handle required agent control when needed.
|
|
81
|
+
If another concrete, necessary objective is independent of active agent
|
|
82
|
+
assignments and an authorized agent is the right owner, delegate it. If a
|
|
83
|
+
concrete, necessary independent objective is best handled locally and doing it
|
|
84
|
+
now materially advances the task, do that work, then reassess.
|
|
85
|
+
|
|
86
|
+
If further useful progress depends on active agents, or no other concrete,
|
|
87
|
+
necessary independent work remains, end your turn without concluding the task.
|
|
88
|
+
Agent results or attention will resume this session automatically. Do not
|
|
89
|
+
conclude or produce the final synthesis while unresolved agent work remains.
|
|
90
|
+
Do not invent side work, broaden scope, perform speculative or precautionary
|
|
91
|
+
exploration, list or inspect merely for progress, steer merely for status, sleep,
|
|
92
|
+
poll, or otherwise keep the turn alive while agent results are pending.
|
|
80
93
|
|
|
81
94
|
If list reports result_error, do not start a new delegation over unresolved
|
|
82
95
|
work. Resolve mailbox persistence first, then close the exact agent before
|
package/dist/index.js
CHANGED
|
@@ -104,10 +104,23 @@ assignment when practical. If genuinely new follow-up work emerges after
|
|
|
104
104
|
completion and previous context is valuable, continue the exact returned session
|
|
105
105
|
only when the completion is not marked retired. A retired session requires a
|
|
106
106
|
fresh delegation; pass its resultRef/handoff and relevant files instead.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
107
|
+
Each active delegated assignment has one executor: that agent. Do not repeat
|
|
108
|
+
its assigned work locally or delegate substantially overlapping work elsewhere.
|
|
109
|
+
|
|
110
|
+
After starting an agent assignment or receiving an agent result or attention
|
|
111
|
+
event, reassess the remaining work. Handle required agent control when needed.
|
|
112
|
+
If another concrete, necessary objective is independent of active agent
|
|
113
|
+
assignments and an authorized agent is the right owner, delegate it. If a
|
|
114
|
+
concrete, necessary independent objective is best handled locally and doing it
|
|
115
|
+
now materially advances the task, do that work, then reassess.
|
|
116
|
+
|
|
117
|
+
If further useful progress depends on active agents, or no other concrete,
|
|
118
|
+
necessary independent work remains, end your turn without concluding the task.
|
|
119
|
+
Agent results or attention will resume this session automatically. Do not
|
|
120
|
+
conclude or produce the final synthesis while unresolved agent work remains.
|
|
121
|
+
Do not invent side work, broaden scope, perform speculative or precautionary
|
|
122
|
+
exploration, list or inspect merely for progress, steer merely for status, sleep,
|
|
123
|
+
poll, or otherwise keep the turn alive while agent results are pending.
|
|
111
124
|
|
|
112
125
|
If list reports result_error, do not start a new delegation over unresolved
|
|
113
126
|
work. Resolve mailbox persistence first, then close the exact agent before
|
|
@@ -261,7 +274,7 @@ ${e.kind==="lead"?Ep:Rp}`}async function Sc(e,n){let t=(await Es(e)).definitions
|
|
|
261
274
|
|
|
262
275
|
${i.question}
|
|
263
276
|
|
|
264
|
-
Reply using agent action "reply" for this agent.`,display:!0,details:{askId:i.askId,question:i.question,requestId:i.requestId,runId:i.runId,agentLabel:i.agentLabel,workspaceId:i.workspaceId,paneId:i.paneId,piSessionId:i.piSessionId}},{triggerTurn:!0}),!0}function bm(e,n,t,s,i,r){if(!cn)return;let a=`${n.mailboxPath}:${i.askId}`;if(!Cr.has(a)){Cr.add(a);try{if(!Im(e,n,t,s,i))return;Sm(n,i.askId),Dp(n.label)}catch(o){Uc(e,n,t,s,i,r,o)}finally{Cr.delete(a)}}}function Sm(e,n){let t=`${e.mailboxPath}:${n}`,s=zn.get(t);s&&(clearTimeout(s),zn.delete(t))}function Uc(e,n,t,s,i,r,a){zs(a);let o=`${n.mailboxPath}:${i.askId}`;if(zn.has(o))return;let d=setTimeout(()=>{if(zn.delete(o),!(!cn||ve.get(n.label)!==n))try{Ca(e,n,t,r)}catch(c){Uc(e,n,t,s,i,r,c)}},250);zn.set(o,d),xe.set(n.label,`Ask delivery failed; retrying: ${String(a)}`)}function Ca(e,n,t,s){let i=be(n.mailboxPath);if(!i?.pendingAskId)return;let r=ys(n.mailboxPath,i);r&&bm(e,n,t,i,r,s)}function $i(e,n,t,s){let i=ho(n.mailboxPath);Wr(n),Bc(i,Mi,At,()=>{try{Ca(e,n,t,s)}catch(a){Y(e,t,"pi_herdsman_cleanup_error",a),At.has(i)||At.set(i,setTimeout(()=>{At.delete(i),ve.get(n.label)===n&&cn&&$i(e,n,t,s)},250))}},()=>{ve.get(n.label)===n&&cn&&$i(e,n,t,s)},a=>Y(e,t,"pi_herdsman_cleanup_error",a))}function vm(e,n,t){let s;try{s=n.sessionManager.getSessionId()}catch{return}for(let i of[...ve.values()])if(i.ownerSessionId===s)try{Ca(e,i,n,t)}catch(r){Y(e,n,"pi_herdsman_cleanup_error",r)}}function Ps(e){let n=ve.get(e);if(!n)return;let t=new Set([n.activeRequestId,n.completedRequestId].filter(s=>!!s));for(let s of t)Ms(n,s);Wr(n),Pa(n),Jc(n),n.startedAt=void 0,ve.delete(e),qr(e)}function Kr(e,n,t){return e.runId===n.runId&&e.ownerSessionId===n.ownerSessionId&&e.workspaceId===t.workspace_id&&e.paneId===t.pane_id&&e.piSessionId===n.piSessionId&&Jn(e.piSessionFile,n.piSessionFile)&&Xe(e.cwd,t.cwd)}function Wc(e,n,t){return n.agentDefinition!==void 0?ts(n):t&&Kr(t,n,e)?t.agentDefinition:ts(n)}function hc(e,n,t,s){let i=a=>$t(e,a)?(s&&$("agent_label_exists",`Agent mailbox contains an unacknowledged request: ${n}`,t),!0):!1,r;try{r=be(e)}catch(a){if(i())return!0;$("internal_failure",`Agent mailbox state is malformed or oversized: ${String(a)}`,t)}return i(r)?!0:r?(s&&$("agent_label_exists",`Agent label already exists: ${n}`,t),!0):!1}function Ia(e){let n=Gn(e,"rollback");try{$t(e)||Ks(e)}finally{n()}}function $a(e,n,t,s,i=n.activeRequestId){if(!i)return;let r=Dc(n,i);Ms(n,i),Bc(r,Ri,xi,()=>{try{let o=Hn(n.mailboxPath,i);o&&Ur(e,n,t,o,s).catch(()=>{})}catch{}},()=>{n.activeRequestId===i&&cn&&$a(e,n,t,s,i)},o=>Y(e,t,"pi_herdsman_cleanup_error",o))}async function km(e,n,t,s,i){let a=(await an(e,n,i)).agents.filter(({listed:u})=>u.label===t);a.length===0&&$("target_not_found","No exact Herdr agent identity matched",s),a.length>1&&$("target_ambiguous","The agent identity matched multiple live agents",s);let{listed:o}=a[0],d=o.label?be(Fe(o.workspace_id,o.label)):void 0;d||$("target_not_found","No valid managed state matched the agent",s),d.ownerSessionId!==n.sessionManager.getSessionId()&&$("target_not_found","Agent belongs to another owner session",s);let c=ve.get(o.label);c&&!Kr(c,d,o)&&(Ps(o.label),c=void 0),c&&c.activeRequestId&&c.activeRequestId!==d.activeRequestId&&Ms(c,c.activeRequestId),c&&c.completedRequestId&&c.completedRequestId!==d.completedRequestId&&Ms(c,c.completedRequestId);let g=Wc(o,d,c),l=c??{label:o.label,herdrAgent:kn(o.workspace_id,o.label,d.runId),workspaceId:o.workspace_id,paneId:o.pane_id,cwd:o.cwd,runId:d.runId,ownerSessionId:d.ownerSessionId,mailboxPath:Fe(o.workspace_id,o.label),piSessionId:d.piSessionId,piSessionFile:d.piSessionFile,activeRequestId:d.activeRequestId,completedRequestId:d.completedRequestId,agentDefinition:g};return Object.assign(l,{herdrAgent:kn(o.workspace_id,o.label,d.runId),workspaceId:o.workspace_id,paneId:o.pane_id,cwd:o.cwd,runId:d.runId,ownerSessionId:d.ownerSessionId,mailboxPath:Fe(o.workspace_id,o.label),piSessionId:d.piSessionId,piSessionFile:d.piSessionFile,activeRequestId:d.activeRequestId,completedRequestId:d.completedRequestId,agentDefinition:g}),ve.set(l.label,l),Xn(l,d,o),await Ti(e,l,n,{signal:i}),{runtime:l,agent:o,controlState:o.state}}function _m(e,n,t){let s=t!==void 0&&Kr(t,n,e),i=n.agentDefinition!==void 0?ts(n):s?t.agentDefinition:ts(n),r=(s?t:void 0)??{label:e.label,herdrAgent:kn(e.workspace_id,e.label,n.runId),workspaceId:e.workspace_id,paneId:e.pane_id,cwd:e.cwd,runId:n.runId,ownerSessionId:n.ownerSessionId,mailboxPath:Fe(e.workspace_id,e.label),piSessionId:n.piSessionId,piSessionFile:n.piSessionFile,activeRequestId:n.activeRequestId,completedRequestId:n.completedRequestId,agentDefinition:i};return r.agentDefinition=i,r}function Cs(e,n,t={}){return e instanceof Pe?new Pe({...e.detail,operation:"close",ids:{...n,...e.detail.ids},details:{...e.detail.details,...t}}):new Pe({category:"internal_failure",message:String(e),operation:"close",rollbackOccurred:!1,retryAttempted:!1,ids:n,details:t})}async function Kc(e,n,t,s,i,r=!1){(!t.label||!t.pane_id)&&$("target_not_found","Agent has no exact close identity","close");let a={label:t.label,paneId:t.pane_id},o=[...ve.values()].find(c=>c.label===t.label||c.paneId===t.pane_id||c.piSessionId===t.pi_session_id||t.pi_session_path!==void 0&&c.piSessionFile!==void 0&&Jn(t.pi_session_path,c.piSessionFile)),d;try{d=_m(t,s,o),Xn(d,s,t,{requireLiveSession:!0})}catch(c){throw Cs(c,a)}try{await Ti(e,d,n,{signal:i}),await pl(e,n,d.herdrAgent,{paneId:t.pane_id,workspaceId:d.workspaceId,cwd:d.cwd,session:ss(d.piSessionId,d.piSessionFile),...r?{allowPostCompletionTransition:!0}:{}},i)}catch(c){throw Cs(c,a)}return d}async function Am(e,n,t,s,i,r,a=!1){let o=Fe(s.workspaceId,s.agentLabel),d=a?void 0:Gn(o,"close",{label:s.agentLabel,paneId:s.paneId});try{let c=be(o);(!c||!Re(c,s))&&$("target_ambiguous","Managed agent changed before close","close"),xs(o,c)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close");let g=ve.get(s.agentLabel),l=await Kc(e,n,t,c,i),u=be(o);(!u||!Re(u,c)||xs(o,u))&&$("target_ambiguous","Managed agent produced a durable result during close","close");try{Ks(o),qr(l.label)}catch(f){let p=`Agent pane closed but mailbox cleanup failed: ${String(f)}`;xe.set(l.label,p),Y(e,n,"pi_herdsman_cleanup_error",f),r?.onCleanupFailure?.(l.label,p);return}g&&(Ms(l),Wr(l),Pa(l),Jc(l),l.startedAt=void 0,ve.delete(l.label),qr(l.label)),r?.onClosed?.(l.label)}finally{d?.()}}async function ba(e,n,t,s,i,r=!1){t.presence.kind==="unknown"&&$("target_ambiguous","Managed agent presence cannot be proved safely","close");let a=Fe(t.state.workspaceId,t.state.agentLabel),o=r?void 0:Gn(a,"close",{label:t.state.agentLabel,paneId:t.state.paneId});try{let d=be(a);(!d||!Re(d,t.state))&&$("target_ambiguous","Managed agent changed before close","close"),xs(a,d)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close");let c=Fr(d,await tt(e,n,s));if(c.kind==="unknown"&&$("target_ambiguous","Managed agent presence cannot be proved safely","close"),c.kind==="live"){await Am(e,n,{...c.agent,label:d.agentLabel},d,s,i,!0);return}d=be(a),(!d||!Re(d,t.state))&&$("target_ambiguous","Managed agent changed before close","close"),xs(a,d)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close"),Ks(a),Ps(d.agentLabel),i?.onClosed?.(d.agentLabel)}finally{o?.()}}async function Em(e,n,t,s,i){Zi().length&&$("target_ambiguous","A managed mailbox has unresolved state","close");let r=await tt(e,n,s),a=await an(e,n,s,!1,!0,r);lm(a.mailboxes.map(({state:u})=>u));let o=u=>{let f=a.agents.filter(({state:p})=>Re(p,u));return f.length!==1&&$("target_ambiguous","Managed agent identity could not be proven for cascade close","close",{ids:{label:u.agentLabel,paneId:u.paneId}}),f[0]},d=o(t),c=[],g=new Set,l=u=>{let f=a.mailboxes.filter(({state:p})=>p.workspaceId===t.workspaceId&&p.ownerSessionId===u.piSessionId);for(let{state:p}of f){let b=`${p.workspaceId}\0${p.piSessionId}`;g.has(b)&&$("target_ambiguous","Managed agent ancestry could not be proven for cascade close","close"),g.add(b);let v=o(p);l(p),c.push(v)}};return l(t),Sa([d,...c],i),{parent:d,descendants:c}}function Sa(e,n){for(let[t,s]of e.entries()){s.presence.kind==="unknown"&&$("target_ambiguous","Managed agent presence cannot be proved safely","close");let i;try{i=be(Fe(s.state.workspaceId,s.state.agentLabel))}catch{$("target_ambiguous","A managed mailbox has unresolved state","close")}(!i||!Re(i,s.state))&&$("target_ambiguous","Managed agent changed before close","close"),xs(Fe(s.state.workspaceId,s.state.agentLabel),i,t===0?n:void 0)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close")}}function Ta(e,n=On()){return n.filter(({state:t})=>t.workspaceId===e.workspaceId&&t.ownerSessionId===e.piSessionId)}function zc(e,n=On()){return Ta(e,n).some(({path:t,state:s})=>s.resultError||s.activeRequestId?!0:s.completedRequestId?jr(t,s.completedRequestId):!1)}function yc(e,n=On()){return Ta(e,n).every(({path:t,state:s})=>{if(s.resultError)return!1;if(!s.activeRequestId)return!s.completedRequestId||!jr(t,s.completedRequestId);if(!s.pendingAskId)return!1;try{return!!ys(t,s)}catch{return!1}})}function wc(e,n){return Gc(e,n).unresolvedDirectChildCount>0}function Gc(e,n,t){let s=0,i=0;for(let{path:r,state:a}of Ta(e)){if(a.resultError){i++;continue}if(!(t&&[a.activeRequestId,a.completedRequestId].filter(o=>!!o).some(o=>Lc(Et(a,o),t)))){if(a.activeRequestId){s++;continue}a.completedRequestId&&!Di(n,Et(a,a.completedRequestId))&&i++}}return{activeDirectChildCount:s,pendingDirectResultCount:i,unresolvedDirectChildCount:s+i}}function Da(e,n){return pm(Et(e,n))}function Jc(e){for(let n of[e.activeRequestId,e.completedRequestId])n&&Pi.delete(Da(e,n))}function Rm({activeDirectChildCount:e,pendingDirectResultCount:n,unresolvedDirectChildCount:t}){let s=`${e} active direct agent${e===1?"":"s"}`,i=`${n} pending direct result${n===1?"":"s"}`,r=t===0?"all direct agent assignments are resolved":`${t} direct agent assignment${t===1?"":"s"} remain${t===1?"s":""} unresolved`;return`Delegation status: ${s}; ${i}; ${r}. ${t===0?"You may conclude if your own acceptance criteria are satisfied.":"You may make useful decisions or take useful actions based on partial agent results, but do not conclude or produce the final synthesis while unresolved agent work remains."}`}function xm(e,n,t){try{let s=On().find(({state:a})=>a.workspaceId===e.workspaceId&&a.piSessionId===e.ownerSessionId)?.state;if(!s&&process.env.PI_HERDSMAN_MAILBOX!==void 0)return;let i=s??{workspaceId:e.workspaceId,piSessionId:e.ownerSessionId},r=Gc(i,t,Et(e,n));return{content:Rm(r),...r}}catch{return}}async function Na(e,n,t,s,i,r={},a){let o=Aa(s.workspaceId,s.piSessionId),d=Fe(s.workspaceId,s.agentLabel),c;try{c=Gn(d,"close",{label:s.agentLabel,paneId:s.paneId});let g=await Em(e,n,s,i,r.deliveredRootResultId);Sa([g.parent,...g.descendants],r.deliveredRootResultId);for(let[u,f]of g.descendants.entries()){Sa([g.parent,...g.descendants.slice(u)],r.deliveredRootResultId);try{await ba(e,n,f,i,a)}catch(p){throw Cs(p,{label:f.state.agentLabel,paneId:f.state.paneId},{parentLabel:s.agentLabel})}}if(r.deliveredRootResultId){await qc(e,n,s,r.deliveredRootResultId,i,!0);return}let l=(await an(e,n,i)).agents.find(({state:u})=>Re(u,s));l||$("target_not_found","Parent agent changed before close","close"),await ba(e,n,l,i,a,!0)}catch(g){throw Cs(g,{label:t?.label,paneId:t?.pane_id},{parentLabel:s.agentLabel})}finally{c?.(),o()}}async function Mm(e,n,t){let s=n.sessionManager.getSessionId(),i=await an(e,n,t),r=$c(i,{kind:"lead"},s),a=[...r].sort((p,b)=>p.state.agentLabel.localeCompare(b.state.agentLabel)).filter(p=>p.presence.kind!=="unknown"&&(p.presence.kind==="lost"||p.listed.recovery_only!==!0)),o=r.filter(p=>p.presence.kind!=="unknown"&&p.state.ownerSessionId===s).filter((p,b,v)=>v.findIndex(k=>k.state.agentLabel===p.state.agentLabel)===b),d=[];for(let p of a){let b=Fe(p.state.workspaceId,p.state.agentLabel);(p.state.activeRequestId||$t(b,p.state))&&d.push(`${p.state.agentLabel}: active assignment`),jr(b,p.state.completedRequestId)&&d.push(`${p.state.agentLabel}: pending result`)}let c=[],g=new Map,l=(p,b)=>{g.has(p)||g.set(p,{label:p,message:b})};for(let p of o)try{let v=(await an(e,n,t)).agents.filter(W=>W.state.agentLabel===p.state.agentLabel);v.length!==1&&$("target_not_found","No exact agent identity matched","close",{ids:{label:p.state.agentLabel,paneId:p.state.paneId}});let k=v[0],T=k.state;(T.workspaceId!==p.state.workspaceId||T.runId!==p.state.runId||T.paneId!==p.state.paneId||T.piSessionId!==p.state.piSessionId||!Jn(T.piSessionFile,p.state.piSessionFile))&&$("target_not_found","Agent identity changed after stop inventory","close",{ids:{label:T.agentLabel,paneId:T.paneId}}),T.ownerSessionId===s||$("target_not_found","Agent belongs to another owner session","close",{ids:{label:T.agentLabel,paneId:T.paneId}});let j={onClosed:W=>{c.includes(W)||c.push(W)},onCleanupFailure:(W,fe)=>{l(W,fe)}};await Na(e,n,k.listed,T,t,{},j)}catch(b){let v=Cs(b,{label:p.state.agentLabel,paneId:p.state.paneId}),k=v.detail.ids?.label??p.state.agentLabel;l(k,v.detail.message),k!==p.state.agentLabel&&l(p.state.agentLabel,`not closed: ${v.detail.message}`),xe.set(p.state.agentLabel,v.detail.message),Y(e,n,"pi_herdsman_cleanup_error",v)}let u=new Set(c);for(let p of a)!u.has(p.state.agentLabel)&&!g.has(p.state.agentLabel)&&l(p.state.agentLabel,"not closed");if(je?.(),o.length===0)return"No owned agents running.";let f=c.length===a.length&&g.size===0?[`Stopped ${c.length} agents`]:[`Stopped ${c.length} of ${a.length} agents`];return f.push(...c.map(p=>`\u2713 ${p}`)),f.push(...[...g.values()].map(({label:p,message:b})=>`\u2717 ${p}: ${b}`)),d.length&&f.push("Discarded:",...d.map(p=>` ${p}`)),f.join(`
|
|
277
|
+
Reply using agent action "reply" for this agent.`,display:!0,details:{askId:i.askId,question:i.question,requestId:i.requestId,runId:i.runId,agentLabel:i.agentLabel,workspaceId:i.workspaceId,paneId:i.paneId,piSessionId:i.piSessionId}},{triggerTurn:!0}),!0}function bm(e,n,t,s,i,r){if(!cn)return;let a=`${n.mailboxPath}:${i.askId}`;if(!Cr.has(a)){Cr.add(a);try{if(!Im(e,n,t,s,i))return;Sm(n,i.askId),Dp(n.label)}catch(o){Uc(e,n,t,s,i,r,o)}finally{Cr.delete(a)}}}function Sm(e,n){let t=`${e.mailboxPath}:${n}`,s=zn.get(t);s&&(clearTimeout(s),zn.delete(t))}function Uc(e,n,t,s,i,r,a){zs(a);let o=`${n.mailboxPath}:${i.askId}`;if(zn.has(o))return;let d=setTimeout(()=>{if(zn.delete(o),!(!cn||ve.get(n.label)!==n))try{Ca(e,n,t,r)}catch(c){Uc(e,n,t,s,i,r,c)}},250);zn.set(o,d),xe.set(n.label,`Ask delivery failed; retrying: ${String(a)}`)}function Ca(e,n,t,s){let i=be(n.mailboxPath);if(!i?.pendingAskId)return;let r=ys(n.mailboxPath,i);r&&bm(e,n,t,i,r,s)}function $i(e,n,t,s){let i=ho(n.mailboxPath);Wr(n),Bc(i,Mi,At,()=>{try{Ca(e,n,t,s)}catch(a){Y(e,t,"pi_herdsman_cleanup_error",a),At.has(i)||At.set(i,setTimeout(()=>{At.delete(i),ve.get(n.label)===n&&cn&&$i(e,n,t,s)},250))}},()=>{ve.get(n.label)===n&&cn&&$i(e,n,t,s)},a=>Y(e,t,"pi_herdsman_cleanup_error",a))}function vm(e,n,t){let s;try{s=n.sessionManager.getSessionId()}catch{return}for(let i of[...ve.values()])if(i.ownerSessionId===s)try{Ca(e,i,n,t)}catch(r){Y(e,n,"pi_herdsman_cleanup_error",r)}}function Ps(e){let n=ve.get(e);if(!n)return;let t=new Set([n.activeRequestId,n.completedRequestId].filter(s=>!!s));for(let s of t)Ms(n,s);Wr(n),Pa(n),Jc(n),n.startedAt=void 0,ve.delete(e),qr(e)}function Kr(e,n,t){return e.runId===n.runId&&e.ownerSessionId===n.ownerSessionId&&e.workspaceId===t.workspace_id&&e.paneId===t.pane_id&&e.piSessionId===n.piSessionId&&Jn(e.piSessionFile,n.piSessionFile)&&Xe(e.cwd,t.cwd)}function Wc(e,n,t){return n.agentDefinition!==void 0?ts(n):t&&Kr(t,n,e)?t.agentDefinition:ts(n)}function hc(e,n,t,s){let i=a=>$t(e,a)?(s&&$("agent_label_exists",`Agent mailbox contains an unacknowledged request: ${n}`,t),!0):!1,r;try{r=be(e)}catch(a){if(i())return!0;$("internal_failure",`Agent mailbox state is malformed or oversized: ${String(a)}`,t)}return i(r)?!0:r?(s&&$("agent_label_exists",`Agent label already exists: ${n}`,t),!0):!1}function Ia(e){let n=Gn(e,"rollback");try{$t(e)||Ks(e)}finally{n()}}function $a(e,n,t,s,i=n.activeRequestId){if(!i)return;let r=Dc(n,i);Ms(n,i),Bc(r,Ri,xi,()=>{try{let o=Hn(n.mailboxPath,i);o&&Ur(e,n,t,o,s).catch(()=>{})}catch{}},()=>{n.activeRequestId===i&&cn&&$a(e,n,t,s,i)},o=>Y(e,t,"pi_herdsman_cleanup_error",o))}async function km(e,n,t,s,i){let a=(await an(e,n,i)).agents.filter(({listed:u})=>u.label===t);a.length===0&&$("target_not_found","No exact Herdr agent identity matched",s),a.length>1&&$("target_ambiguous","The agent identity matched multiple live agents",s);let{listed:o}=a[0],d=o.label?be(Fe(o.workspace_id,o.label)):void 0;d||$("target_not_found","No valid managed state matched the agent",s),d.ownerSessionId!==n.sessionManager.getSessionId()&&$("target_not_found","Agent belongs to another owner session",s);let c=ve.get(o.label);c&&!Kr(c,d,o)&&(Ps(o.label),c=void 0),c&&c.activeRequestId&&c.activeRequestId!==d.activeRequestId&&Ms(c,c.activeRequestId),c&&c.completedRequestId&&c.completedRequestId!==d.completedRequestId&&Ms(c,c.completedRequestId);let g=Wc(o,d,c),l=c??{label:o.label,herdrAgent:kn(o.workspace_id,o.label,d.runId),workspaceId:o.workspace_id,paneId:o.pane_id,cwd:o.cwd,runId:d.runId,ownerSessionId:d.ownerSessionId,mailboxPath:Fe(o.workspace_id,o.label),piSessionId:d.piSessionId,piSessionFile:d.piSessionFile,activeRequestId:d.activeRequestId,completedRequestId:d.completedRequestId,agentDefinition:g};return Object.assign(l,{herdrAgent:kn(o.workspace_id,o.label,d.runId),workspaceId:o.workspace_id,paneId:o.pane_id,cwd:o.cwd,runId:d.runId,ownerSessionId:d.ownerSessionId,mailboxPath:Fe(o.workspace_id,o.label),piSessionId:d.piSessionId,piSessionFile:d.piSessionFile,activeRequestId:d.activeRequestId,completedRequestId:d.completedRequestId,agentDefinition:g}),ve.set(l.label,l),Xn(l,d,o),await Ti(e,l,n,{signal:i}),{runtime:l,agent:o,controlState:o.state}}function _m(e,n,t){let s=t!==void 0&&Kr(t,n,e),i=n.agentDefinition!==void 0?ts(n):s?t.agentDefinition:ts(n),r=(s?t:void 0)??{label:e.label,herdrAgent:kn(e.workspace_id,e.label,n.runId),workspaceId:e.workspace_id,paneId:e.pane_id,cwd:e.cwd,runId:n.runId,ownerSessionId:n.ownerSessionId,mailboxPath:Fe(e.workspace_id,e.label),piSessionId:n.piSessionId,piSessionFile:n.piSessionFile,activeRequestId:n.activeRequestId,completedRequestId:n.completedRequestId,agentDefinition:i};return r.agentDefinition=i,r}function Cs(e,n,t={}){return e instanceof Pe?new Pe({...e.detail,operation:"close",ids:{...n,...e.detail.ids},details:{...e.detail.details,...t}}):new Pe({category:"internal_failure",message:String(e),operation:"close",rollbackOccurred:!1,retryAttempted:!1,ids:n,details:t})}async function Kc(e,n,t,s,i,r=!1){(!t.label||!t.pane_id)&&$("target_not_found","Agent has no exact close identity","close");let a={label:t.label,paneId:t.pane_id},o=[...ve.values()].find(c=>c.label===t.label||c.paneId===t.pane_id||c.piSessionId===t.pi_session_id||t.pi_session_path!==void 0&&c.piSessionFile!==void 0&&Jn(t.pi_session_path,c.piSessionFile)),d;try{d=_m(t,s,o),Xn(d,s,t,{requireLiveSession:!0})}catch(c){throw Cs(c,a)}try{await Ti(e,d,n,{signal:i}),await pl(e,n,d.herdrAgent,{paneId:t.pane_id,workspaceId:d.workspaceId,cwd:d.cwd,session:ss(d.piSessionId,d.piSessionFile),...r?{allowPostCompletionTransition:!0}:{}},i)}catch(c){throw Cs(c,a)}return d}async function Am(e,n,t,s,i,r,a=!1){let o=Fe(s.workspaceId,s.agentLabel),d=a?void 0:Gn(o,"close",{label:s.agentLabel,paneId:s.paneId});try{let c=be(o);(!c||!Re(c,s))&&$("target_ambiguous","Managed agent changed before close","close"),xs(o,c)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close");let g=ve.get(s.agentLabel),l=await Kc(e,n,t,c,i),u=be(o);(!u||!Re(u,c)||xs(o,u))&&$("target_ambiguous","Managed agent produced a durable result during close","close");try{Ks(o),qr(l.label)}catch(f){let p=`Agent pane closed but mailbox cleanup failed: ${String(f)}`;xe.set(l.label,p),Y(e,n,"pi_herdsman_cleanup_error",f),r?.onCleanupFailure?.(l.label,p);return}g&&(Ms(l),Wr(l),Pa(l),Jc(l),l.startedAt=void 0,ve.delete(l.label),qr(l.label)),r?.onClosed?.(l.label)}finally{d?.()}}async function ba(e,n,t,s,i,r=!1){t.presence.kind==="unknown"&&$("target_ambiguous","Managed agent presence cannot be proved safely","close");let a=Fe(t.state.workspaceId,t.state.agentLabel),o=r?void 0:Gn(a,"close",{label:t.state.agentLabel,paneId:t.state.paneId});try{let d=be(a);(!d||!Re(d,t.state))&&$("target_ambiguous","Managed agent changed before close","close"),xs(a,d)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close");let c=Fr(d,await tt(e,n,s));if(c.kind==="unknown"&&$("target_ambiguous","Managed agent presence cannot be proved safely","close"),c.kind==="live"){await Am(e,n,{...c.agent,label:d.agentLabel},d,s,i,!0);return}d=be(a),(!d||!Re(d,t.state))&&$("target_ambiguous","Managed agent changed before close","close"),xs(a,d)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close"),Ks(a),Ps(d.agentLabel),i?.onClosed?.(d.agentLabel)}finally{o?.()}}async function Em(e,n,t,s,i){Zi().length&&$("target_ambiguous","A managed mailbox has unresolved state","close");let r=await tt(e,n,s),a=await an(e,n,s,!1,!0,r);lm(a.mailboxes.map(({state:u})=>u));let o=u=>{let f=a.agents.filter(({state:p})=>Re(p,u));return f.length!==1&&$("target_ambiguous","Managed agent identity could not be proven for cascade close","close",{ids:{label:u.agentLabel,paneId:u.paneId}}),f[0]},d=o(t),c=[],g=new Set,l=u=>{let f=a.mailboxes.filter(({state:p})=>p.workspaceId===t.workspaceId&&p.ownerSessionId===u.piSessionId);for(let{state:p}of f){let b=`${p.workspaceId}\0${p.piSessionId}`;g.has(b)&&$("target_ambiguous","Managed agent ancestry could not be proven for cascade close","close"),g.add(b);let v=o(p);l(p),c.push(v)}};return l(t),Sa([d,...c],i),{parent:d,descendants:c}}function Sa(e,n){for(let[t,s]of e.entries()){s.presence.kind==="unknown"&&$("target_ambiguous","Managed agent presence cannot be proved safely","close");let i;try{i=be(Fe(s.state.workspaceId,s.state.agentLabel))}catch{$("target_ambiguous","A managed mailbox has unresolved state","close")}(!i||!Re(i,s.state))&&$("target_ambiguous","Managed agent changed before close","close"),xs(Fe(s.state.workspaceId,s.state.agentLabel),i,t===0?n:void 0)&&$("target_ambiguous","Managed agent has a durable result; close result delivery first","close")}}function Ta(e,n=On()){return n.filter(({state:t})=>t.workspaceId===e.workspaceId&&t.ownerSessionId===e.piSessionId)}function zc(e,n=On()){return Ta(e,n).some(({path:t,state:s})=>s.resultError||s.activeRequestId?!0:s.completedRequestId?jr(t,s.completedRequestId):!1)}function yc(e,n=On()){return Ta(e,n).every(({path:t,state:s})=>{if(s.resultError)return!1;if(!s.activeRequestId)return!s.completedRequestId||!jr(t,s.completedRequestId);if(!s.pendingAskId)return!1;try{return!!ys(t,s)}catch{return!1}})}function wc(e,n){return Gc(e,n).unresolvedDirectChildCount>0}function Gc(e,n,t){let s=0,i=0;for(let{path:r,state:a}of Ta(e)){if(a.resultError){i++;continue}if(!(t&&[a.activeRequestId,a.completedRequestId].filter(o=>!!o).some(o=>Lc(Et(a,o),t)))){if(a.activeRequestId){s++;continue}a.completedRequestId&&!Di(n,Et(a,a.completedRequestId))&&i++}}return{activeDirectChildCount:s,pendingDirectResultCount:i,unresolvedDirectChildCount:s+i}}function Da(e,n){return pm(Et(e,n))}function Jc(e){for(let n of[e.activeRequestId,e.completedRequestId])n&&Pi.delete(Da(e,n))}function Rm({activeDirectChildCount:e,pendingDirectResultCount:n,unresolvedDirectChildCount:t}){let s=`${e} active direct agent${e===1?"":"s"}`,i=`${n} pending direct result${n===1?"":"s"}`,r=t===0?"all direct agent assignments are resolved":`${t} direct agent assignment${t===1?"":"s"} remain${t===1?"s":""} unresolved`;return`Delegation status: ${s}; ${i}; ${r}. ${t===0?"You may conclude if your own acceptance criteria are satisfied.":"Handle required agent control if needed, then reassess the remaining work. If another concrete, necessary objective is independent of unresolved agent assignments and an authorized agent is the right owner, delegate it. If a concrete, necessary independent objective is best handled locally and doing it now materially advances the task, do that work, then reassess. Otherwise end your turn; agent results or attention will resume this session automatically. Do not repeat unresolved assignments, invent side work merely to remain active, or conclude or produce the final synthesis while unresolved agent work remains."}`}function xm(e,n,t){try{let s=On().find(({state:a})=>a.workspaceId===e.workspaceId&&a.piSessionId===e.ownerSessionId)?.state;if(!s&&process.env.PI_HERDSMAN_MAILBOX!==void 0)return;let i=s??{workspaceId:e.workspaceId,piSessionId:e.ownerSessionId},r=Gc(i,t,Et(e,n));return{content:Rm(r),...r}}catch{return}}async function Na(e,n,t,s,i,r={},a){let o=Aa(s.workspaceId,s.piSessionId),d=Fe(s.workspaceId,s.agentLabel),c;try{c=Gn(d,"close",{label:s.agentLabel,paneId:s.paneId});let g=await Em(e,n,s,i,r.deliveredRootResultId);Sa([g.parent,...g.descendants],r.deliveredRootResultId);for(let[u,f]of g.descendants.entries()){Sa([g.parent,...g.descendants.slice(u)],r.deliveredRootResultId);try{await ba(e,n,f,i,a)}catch(p){throw Cs(p,{label:f.state.agentLabel,paneId:f.state.paneId},{parentLabel:s.agentLabel})}}if(r.deliveredRootResultId){await qc(e,n,s,r.deliveredRootResultId,i,!0);return}let l=(await an(e,n,i)).agents.find(({state:u})=>Re(u,s));l||$("target_not_found","Parent agent changed before close","close"),await ba(e,n,l,i,a,!0)}catch(g){throw Cs(g,{label:t?.label,paneId:t?.pane_id},{parentLabel:s.agentLabel})}finally{c?.(),o()}}async function Mm(e,n,t){let s=n.sessionManager.getSessionId(),i=await an(e,n,t),r=$c(i,{kind:"lead"},s),a=[...r].sort((p,b)=>p.state.agentLabel.localeCompare(b.state.agentLabel)).filter(p=>p.presence.kind!=="unknown"&&(p.presence.kind==="lost"||p.listed.recovery_only!==!0)),o=r.filter(p=>p.presence.kind!=="unknown"&&p.state.ownerSessionId===s).filter((p,b,v)=>v.findIndex(k=>k.state.agentLabel===p.state.agentLabel)===b),d=[];for(let p of a){let b=Fe(p.state.workspaceId,p.state.agentLabel);(p.state.activeRequestId||$t(b,p.state))&&d.push(`${p.state.agentLabel}: active assignment`),jr(b,p.state.completedRequestId)&&d.push(`${p.state.agentLabel}: pending result`)}let c=[],g=new Map,l=(p,b)=>{g.has(p)||g.set(p,{label:p,message:b})};for(let p of o)try{let v=(await an(e,n,t)).agents.filter(W=>W.state.agentLabel===p.state.agentLabel);v.length!==1&&$("target_not_found","No exact agent identity matched","close",{ids:{label:p.state.agentLabel,paneId:p.state.paneId}});let k=v[0],T=k.state;(T.workspaceId!==p.state.workspaceId||T.runId!==p.state.runId||T.paneId!==p.state.paneId||T.piSessionId!==p.state.piSessionId||!Jn(T.piSessionFile,p.state.piSessionFile))&&$("target_not_found","Agent identity changed after stop inventory","close",{ids:{label:T.agentLabel,paneId:T.paneId}}),T.ownerSessionId===s||$("target_not_found","Agent belongs to another owner session","close",{ids:{label:T.agentLabel,paneId:T.paneId}});let j={onClosed:W=>{c.includes(W)||c.push(W)},onCleanupFailure:(W,fe)=>{l(W,fe)}};await Na(e,n,k.listed,T,t,{},j)}catch(b){let v=Cs(b,{label:p.state.agentLabel,paneId:p.state.paneId}),k=v.detail.ids?.label??p.state.agentLabel;l(k,v.detail.message),k!==p.state.agentLabel&&l(p.state.agentLabel,`not closed: ${v.detail.message}`),xe.set(p.state.agentLabel,v.detail.message),Y(e,n,"pi_herdsman_cleanup_error",v)}let u=new Set(c);for(let p of a)!u.has(p.state.agentLabel)&&!g.has(p.state.agentLabel)&&l(p.state.agentLabel,"not closed");if(je?.(),o.length===0)return"No owned agents running.";let f=c.length===a.length&&g.size===0?[`Stopped ${c.length} agents`]:[`Stopped ${c.length} of ${a.length} agents`];return f.push(...c.map(p=>`\u2713 ${p}`)),f.push(...[...g.values()].map(({label:p,message:b})=>`\u2717 ${p}: ${b}`)),d.length&&f.push("Discarded:",...d.map(p=>` ${p}`)),f.join(`
|
|
265
278
|
`)}async function Pm(e,n,t,s,i,r,a){let o=kn(i,s,r);if(t.herdrAgent!==o||t.agent&&!lt(t.agent,o))throw new Error("Started agent returned conflicting Herdr agent aliases");if(await hl(e,n,t),(await pr(e,n)).agents.some(c=>c.workspace_id===i&&c.pane_id===t.paneId&<(c,o)))throw new Error("Rolled-back agent remained live");Ia(a)}async function Cm(e,n,t,s){let i;try{i=be(s)}catch(l){throw new Error(`Agent disappeared with malformed mailbox state; retaining cleanup resources: ${String(l)}`)}let r=i?(await pr(e,n)).agents.find(l=>l.workspace_id===i.workspaceId&&l.pane_id===i.paneId&<(l,kn(i.workspaceId,i.agentLabel,i.runId))&&Ma(l,ss(i.piSessionId,i.piSessionFile))):void 0;if(!i){Ia(s);return}if(!r)throw new Error("Agent disappeared after Herdr failure while its mailbox still proves an owned pane; retaining cleanup resources");let a=ln(r.agent_session),o={workspace_id:r.workspace_id,pane_id:r.pane_id,tab_id:r.tab_id,cwd:r.cwd,pi_session_id:a?.kind==="id"?a.value:void 0,pi_session_path:a?.kind==="path"?a.value:void 0,agent_session:r.agent_session,label:t};if(i.ownerSessionId!==n.sessionManager.getSessionId())throw new Error("Agent Herdr failure belongs to another owner session");let d={label:t,herdrAgent:kn(o.workspace_id,t,i.runId),workspaceId:o.workspace_id,paneId:o.pane_id,cwd:o.cwd,runId:i.runId,ownerSessionId:i.ownerSessionId,mailboxPath:s,piSessionId:i.piSessionId,piSessionFile:i.piSessionFile,agentDefinition:ts(i)};Xn(d,i,o),await ml(e,n,d.herdrAgent,{paneId:d.paneId,workspaceId:d.workspaceId,cwd:d.cwd,session:ss(d.piSessionId,d.piSessionFile)});let c=kn(i.workspaceId,i.agentLabel,i.runId);if((await pr(e,n)).agents.some(l=>l.workspace_id===i.workspaceId&&l.pane_id===i.paneId&<(l,c)))throw new Error("Agent ownership remained uncertain after internal failure");Ia(s)}function ua(e,n,t,s,i,r){return ms({version:4,runId:e.runId,requestId:r,ownerSessionId:e.ownerSessionId,workspaceId:e.workspaceId,agentLabel:e.label,paneId:e.paneId,kind:n,...n==="reply"?{askId:s}:{},text:t,createdAt:i})}function $m(e,n,t,s,i,r,a,o,d){return ms({version:4,runId:e,requestId:o,ownerSessionId:n,workspaceId:t,agentLabel:s,paneId:r,kind:"task",text:i,createdAt:a})<=d}function Tm(e,n,t,s){return ms({version:4,askId:n,requestId:e.activeRequestId,runId:e.runId,ownerSessionId:e.ownerSessionId,workspaceId:e.workspaceId,agentLabel:e.agentLabel,paneId:e.paneId,piSessionId:e.piSessionId,question:t,createdAt:s})}async function fa(e,n,t,s,i,r){if(t.action==="list")return gm(e,n,s,i);if(t.action==="close"){let k=t.agent,U=(await Br(e,n,i,s)).visible.filter(({listed:me})=>me.label===k);U.length===0&&$("target_not_found","No exact agent identity matched","close"),U.length>1&&$("target_ambiguous","Agent identity matched multiple live agents","close");let j=U[0],W=j.listed,fe=W.label?Fe(W.workspace_id,W.label):void 0;fe||$("target_not_found","Agent has no managed mailbox","close");let _e;try{_e=be(fe)}catch(me){$("internal_failure",`Agent mailbox state is malformed or oversized: ${String(me)}`,"close",{ids:{label:W.label,paneId:W.pane_id}})}_e||$("target_not_found","No valid managed state matched the agent","close");let Le=n.sessionManager.getSessionId(),Ue=_e.ownerSessionId===Le;Ue||$("target_not_found","Agent belongs to another owner session","close");try{Ue&&i?.kind==="lead"?await Na(e,n,W,_e,s):await ba(e,n,j,s)}catch(me){let re=Cs(me,{label:W.label,paneId:W.pane_id});throw re.detail.category!=="agent_busy"&&(xe.set(W.label,re.detail.message),Y(e,n,"pi_herdsman_cleanup_error",re)),re}return{ok:!0,action:"close",agent:k,presentation_agent_definition:ts(_e),...xe.has(W.label)?{cleanup_error:xe.get(W.label)}:{}}}let a=await Ci(n),o=t.action==="delegate"||t.action==="continue"?{createdAt:Date.now(),requestId:bn(),runId:bn(),ownerSessionId:n.sessionManager.getSessionId(),workspaceId:process.env.HERDR_WORKSPACE_ID??""}:void 0,d;if(t.action==="delegate"||t.action==="continue"){i||$("not_running_inside_herdr","Only a Herdr controller may start agent assignments",t.action);let k=t.action==="continue"?await cc("continue",()=>Gp(n,t.session)):void 0;await Yp(e,n,s);let T=k?k.definition:t.definition,U=k?k.cwd:t.cwd??n.cwd,j=k?.label??(t.action==="delegate"?t.label:void 0),W=await Es(n),fe=W.definitions.find(se=>se.name===T);if(!fe)throw new Error(`agent ${T} not found`);i.kind==="managed-agent"&&!i.allowedAgentDefinitions.has(T)&&$("invalid_request",`Agent definition ${T} is not allowed for this delegating agent`,t.action);let _e=t.action==="delegate"&&t.fork?await cc("delegate",async()=>{let se=await Ec(n,t.fork),ye=Pn.open(se.path);if(Bn().contextRetirement&&Ra(ye))throw new Mn(`Managed agent session ${ye.getSessionId()} is retired after context pressure. Delegate a fresh agent without fork and pass the previous handoff/resultRef and relevant files.`);return se.path}):void 0;fe.projectSource&&!Xe(U,n.cwd)&&$("invalid_request",`Project agent ${fe.name} belongs to ${dt(n.cwd)}`,t.action),i.kind==="managed-agent"&&!Xe(U,n.cwd)&&$("invalid_request",`Delegated agents must use the delegating agent cwd ${dt(n.cwd)}`,t.action),k&&k.id===n.sessionManager.getSessionId()&&$("invalid_request","Cannot continue the controller's currently active Pi session. Use delegate with fork=<session> for a separate derived context.",t.action);let Le=k?(()=>{try{return Or(k.path)}catch(se){$("invalid_request",se instanceof Error?se.message:String(se),t.action)}})():void 0,Ue=k?["--session",Le]:_e?["--fork",_e]:[],me,re=await um(e,n,void 0,s);qt(fe)||$("invalid_request",`Agent definition ${T} is disabled; enable it through /agents \u2192 Definitions or choose another enabled definition`,t.action,{nextAction:`Enable ${T} through /agents \u2192 Definitions or choose another enabled definition.`});try{Ro(fe,W.definitions)}catch(se){$("invalid_request",se instanceof Error?se.message:String(se),t.action)}let Me=new Set(re.map(se=>se.label).filter(se=>typeof se=="string"));if(k){me=Op(Le);try{let se=await an(e,n,s),ye=On().filter(({state:Se})=>Se.piSessionId===k.id||Se.piSessionFile!==void 0&&zp(Se.piSessionFile,Le)),he=new Set(ye.map(({state:Se})=>`${Se.workspaceId}\0${Se.agentLabel}\0${Se.runId}\0${Se.paneId}`)),qe=new Set(ye.map(({state:Se})=>`${Se.workspaceId}\0${Se.paneId}`));for(let Se of se.liveAgents)Ma(Se,ss(k.id,Le))&&!qe.has(`${Se.workspace_id??""}\0${Se.pane_id??""}`)&&he.add(`${Se.workspace_id??""}\0${Se.name??""}\0${Se.pane_id??""}`);he.size>1&&$("target_ambiguous","The assignment session matched multiple managed agents",t.action),he.size===1&&$("agent_busy","The exact Pi session is already represented by active managed work",t.action,{nextAction:"Let that assignment finish, or close its exact agent if abandoning it, then retry."})}catch(se){throw me(),me=void 0,se}}j&&Me.has(j)&&$("agent_label_exists",`Agent label already exists: ${j}`,t.action);let ae=o.workspaceId,Z=j??rr(T,Me);Dr(Z)||$("invalid_request",'Agent label must start with a lowercase letter, contain only lowercase letters, digits, "_" or "-", and be at most 32 characters',t.action);let oe=se=>Tt(t.task,t.files??[],n.cwd,t.action,"Task",{inlineLimitBytes:a.inline.bytes,fits:ye=>$m(o.runId,o.ownerSessionId,o.workspaceId,se,ye,"",o.createdAt,o.requestId,a.mailbox.bytes)});d=oe(Z);let Ae=Po(fe.body,d.canonicalPaths,t.action),Rt=Ae===fe.body?fe:{...fe,body:Ae},Yn=xo(Rt,i.kind==="managed-agent"?"leaf":"delegating"),Vn=zd(Yn),Qn=o.runId,Cn=o.ownerSessionId,$s=i.kind==="managed-agent"?process.env.PI_SUBAGENT_PARENT_SESSION??Cn:Cn,is=(await _i(n)).effective,Ni=await Wp(e,n,Z,i,is,s),Ts=i?.kind!=="managed-agent"&&is==="tab"?async se=>{if(se.kind!=="tab")return se;let ye=await _c(e,n,s);return{kind:"tab",label:se.label,...ye?{tabId:ye}:{}}}:void 0,Ve=Fe(ae,Z),$n;for(;;){try{$n=ud(Ve)}catch(se){if(!(se instanceof Bs))throw me?.(),me=void 0,se;j&&(me?.(),me=void 0,$("agent_label_exists",`Agent label already exists: ${Z}`,t.action));try{Me.add(Z),Z=rr(T,Me),Dr(Z)||$("invalid_request",'Agent label must start with a lowercase letter, contain only lowercase letters, digits, "_" or "-", and be at most 32 characters',t.action),d=oe(Z),Ve=Fe(ae,Z);continue}catch(ye){throw me?.(),me=void 0,ye}}try{if(!j&&hc(Ve,Z,t.action,!1)){$n(),$n=void 0,Me.add(Z),Z=rr(T,Me),Dr(Z)||$("invalid_request",'Agent label must start with a lowercase letter, contain only lowercase letters, digits, "_" or "-", and be at most 32 characters',t.action),d=oe(Z),Ve=Fe(ae,Z);continue}j&&hc(Ve,Z,t.action,!0);break}catch(se){throw $n&&$n(),$n=void 0,me?.(),me=void 0,se}}let Ke={label:Z,definition:T,...t.task!==void 0?{task:t.task}:{},startedAt:Date.now(),...i.kind==="managed-agent"&&process.env.PI_HERDSMAN_LABEL?{parentLabel:process.env.PI_HERDSMAN_LABEL}:{}};r?.set(Z,Ke),je?.();let ct=[],Li=!1,ke,xt=!1;try{try{ct=Kd([...Rt.body?[Rt.body]:[],Mp])}catch(en){throw Li=!0,en}Ps(Z);let se=Gn(Ve,t.action,{label:Z});try{fd(Ve)}finally{se()}let ye=[`PI_HERDSMAN_MAILBOX=${Ve}`,`PI_HERDSMAN_RUN_ID=${Qn}`,`PI_HERDSMAN_OWNER_SESSION_ID=${Cn}`,`PI_SUBAGENT_PARENT_SESSION=${$s}`,`PI_HERDSMAN_LABEL=${Z}`,`PI_HERDSMAN_WORKSPACE_ID=${ae}`,`PI_HERDSMAN_AGENT_DEFINITION=${T}`,`PI_HERDSMAN_ALLOWED_AGENT_DEFINITIONS=${JSON.stringify(Vn?Yn.frontmatter.agents:[])}`,"PI_OFFLINE=1"],he=Gd(Yn,{...Yn.body?{bodyPromptPath:ct[0]}:{},sharedPromptPath:ct[Yn.body?1:0],cwd:U,managedAgent:!0,approveProject:W.projectTrusted&&Xe(U,n.cwd),...t.action==="delegate"?{inheritedModel:n.model?at(n.model):void 0,inheritedThinking:e.getThinkingLevel()}:{}});ke=await ll(e,n,{label:Z,runId:Qn,cwd:U,extensionPath:Ip,placement:Ni,...Ts?{placementRevalidator:Ts}:{},agentArgs:[...he,...Ue],env:ye,timeoutMs:t.timeoutMs,signal:s});let qe=await sr(Ve,en=>en.runId===Qn&&en.ownerSessionId===Cn,{timeoutMs:5e3,signal:s}).catch(()=>{});qe||$("pane_not_ready","Agent did not initialize its mailbox",t.action);let Se=kn(ae,Z,qe.runId);ke.herdrAgent!==Se&&$("target_not_found","Agent launch returned an unexpected Herdr agent alias",t.action,{ids:{label:Z,paneId:ke.paneId}}),ke.agent&&!lt(ke.agent,Se)&&$("target_not_found","Agent launch returned conflicting Herdr agent aliases",t.action,{ids:{label:Z,paneId:ke.paneId}});let We={label:Z,herdrAgent:Se,workspaceId:ae,paneId:ke.paneId,cwd:ke.cwd,runId:qe.runId,ownerSessionId:Cn,mailboxPath:Ve,piSessionId:qe.piSessionId,piSessionFile:qe.piSessionFile,agentDefinition:T,model:ke.agent?.model??null,thinking:ke.agent?.thinking??null};Xn(We,qe,{workspace_id:ae,label:Z,pane_id:ke.paneId,cwd:ke.cwd,pi_session_id:qe.piSessionId,pi_session_path:qe.piSessionFile}),d=Tt(t.task,t.files??[],n.cwd,t.action,"Task",{inlineLimitBytes:a.inline.bytes,mailboxLimitBytes:a.mailbox.bytes,serializedBytes:en=>ua(We,"task",en,void 0,o.createdAt,o.requestId)}),await Ti(e,We,n,{signal:s,waitForSession:!0}),ve.set(Z,We),je?.();let ut=await ca(e,We,"task",d.text,n,s,void 0,o.createdAt,o.requestId,t.action);return Ke.requestId=ut,xt=!0,je?.(),{ok:!0,action:t.action,agent:Z,definition:T,pane_id:We.paneId,session_id:We.piSessionId,request_id:We.activeRequestId}}catch(se){if(Li)throw se;let ye=se instanceof Xs?se:void 0,he=ye?.cause??se;ye&&(ke=ye.attempt,he instanceof Pe&&(he.detail.details={...he.detail.details,stage:ye.stage}),ye.retryAttempted&&he instanceof Pe&&(he.detail.retryAttempted=!0));let qe,Se=he instanceof Pe&&he.detail.details?he.detail.details:void 0,We=Se?.primary,ut=We?.category&&We.message?{category:We.category,message:We.message,operation:We.operation??t.action}:he instanceof Pe?{category:he.detail.category,message:he.detail.message,operation:he.detail.operation}:{category:"internal_failure",message:String(he),operation:t.action},en=Se?.ids,rs={label:Z,...ke?.paneId?{paneId:ke.paneId}:{},...ke?.tabId?{tabId:ke.tabId}:{},...en?.paneId?{paneId:en.paneId}:{},...en?.tabId?{tabId:en.tabId}:{}};ve.delete(Z);try{ke?await Pm(e,n,ke,Z,ae,Qn,Ve):await Cm(e,n,Z,Ve)}catch(ft){qe=ft,zs(ft);let un={category:"internal_failure",message:String(ft),operation:"rollback"},Ds=JSON.stringify({primary:ut,cleanup:un,ids:rs});xe.set(Z,Ds),Y(e,n,"pi_herdsman_cleanup_error",Ds)}if(qe&&(je?.(),$("rollback_failure",`Agent launch failed and rollback was incomplete. Primary: ${ut.message}. Cleanup: ${String(qe)}`,t.action,{rollbackOccurred:!0,retryAttempted:!0,ids:rs,primary:ut,cleanup:{category:"internal_failure",message:String(qe),operation:"rollback"},...he instanceof Pe&&he.detail.details?{details:he.detail.details}:ye?{details:{stage:ye.stage}}:{},nextAction:"Inspect cleanup_errors before retrying cleanup"})),je?.(),Se&&!qe){let ft=JSON.stringify({primary:ut,cleanup:Se.cleanup,ids:rs});xe.set(Z,ft),Y(e,n,"pi_herdsman_cleanup_error",ft)}if(he instanceof Pe)throw he.detail.rollbackOccurred=!0,ye?.retryAttempted&&(he.detail.retryAttempted=!0),he.detail.ids=rs,he;$("internal_failure",String(he),t.action,{rollbackOccurred:!0,retryAttempted:ye?.retryAttempted??!1,ids:{label:Z,...ke?.paneId?{paneId:ke.paneId}:{},...ke?.tabId?{tabId:ke.tabId}:{}},...ye?{details:{stage:ye.stage}}:{}})}finally{!xt&&r?.get(Z)===Ke&&(r.delete(Z),je?.());for(let se of ct)Ic(se,{throwIfNoEntry:!1})&&bc(se);try{$n&&$n()}finally{me&&me()}}}let c=t.agent,g=await km(e,n,c,t.action,s),l=g.runtime,u=l.agentDefinition;if(t.action==="inspect"){let k=await fr(e,n,{workspaceId:l.workspaceId,paneId:l.paneId,piSessionId:l.piSessionId,piSessionFile:l.piSessionFile},s,T=>{let U=be(l.mailboxPath);return!!U&&Kr(l,U,T)&&U.agentLabel===l.label&<(T,l.herdrAgent)});return{ok:!0,action:"inspect",agent:l.label,presentation_agent_definition:u,session_id:l.piSessionId,pane_id:l.paneId,captured_at:k.capturedAt,recent_output_truncated:k.recentOutputTruncated,...k.recentOutput?{recent_output:k.recentOutput}:{},...k.process?{process:k.process}:{}}}if(t.action==="steer"&&g.agent.steerable!==!0&&$("agent_busy",`Agent is not currently accepting steering: ${g.controlState}`,"steer",{nextAction:"Refresh list and use steer only when available_actions includes steer."}),t.action==="steer"&&!l.activeRequestId&&$("agent_busy","Agent has no active assignment","steer"),t.action==="reply"){let k=be(l.mailboxPath),T=k?.pendingAskId,U;try{U=k?ys(l.mailboxPath,k):void 0}catch(Le){$("internal_failure",`Agent ask is malformed or oversized: ${String(Le)}`,"reply")}(!k?.activeRequestId||!T||!U)&&$("agent_busy","Agent is not waiting for an owner reply","reply",{nextAction:"Use reply only for an outstanding ask_owner question; otherwise continue normal control or refresh list."}),(U.askId!==T||U.requestId!==k.activeRequestId||U.runId!==k.runId||U.ownerSessionId!==k.ownerSessionId||U.workspaceId!==k.workspaceId||U.agentLabel!==k.agentLabel||U.paneId!==k.paneId||U.piSessionId!==k.piSessionId)&&$("target_not_found","Agent ask identity did not match","reply"),Xn(l,k);let j=Date.now(),W=bn(),fe=Tt(t.message,t.files??[],n.cwd,"reply","Reply",{inlineLimitBytes:a.inline.bytes,mailboxLimitBytes:a.mailbox.bytes,serializedBytes:Le=>ua(l,"reply",Le,T,j,W)}),_e=await ca(e,l,"reply",fe.text,n,s,T,j,W,"reply");return{ok:!0,action:"reply",agent:l.label,presentation_agent_definition:u,request_id:_e,ask_id:T,assignment_request_id:k.activeRequestId,session_id:l.piSessionId}}let f=Date.now(),p=t.action==="steer"?bn():void 0,b=t.action==="steer"?Tt(t.message,t.files??[],n.cwd,"steer","Steer",{inlineLimitBytes:a.inline.bytes,mailboxLimitBytes:a.mailbox.bytes,serializedBytes:k=>ua(l,"steer",k,void 0,f,p)}):d,v=await ca(e,l,"steer",b.text,n,s,void 0,f,p,t.action);return{ok:!0,action:t.action,agent:l.label,presentation_agent_definition:u,request_id:v,session_id:l.piSessionId,assignment_request_id:l.activeRequestId}}async function Dm(e,n,t,s,i,r){i||$("invalid_request","The agent tool is available only to the lead controller or a delegation-enabled agent controller","controller",{nextAction:"Run this action from the lead controller or an authorized delegation-enabled agent controller"});let a=Tp(t);if(!i||i.kind==="lead"||(As||$("target_not_found","Delegation controller is not initialized as an exact managed agent","controller"),a.action==="list"||a.action==="inspect"))return fa(e,n,a,s,i,r);let o=Aa(process.env.PI_HERDSMAN_WORKSPACE_ID,n.sessionManager.getSessionId());try{return await fa(e,n,a,s,i,r)}finally{o()}}function by(e){let n=Promise.resolve(),t=(h,w)=>{n=n.catch(()=>{}).then(()=>dl(e,h,w)).catch(()=>{})},s=process.env.PI_HERDSMAN_MAILBOX!==void 0?Ea():void 0;if(s){e.on("session_start",(h,w)=>{Y(e,w,"pi_herdsman_state_error",new Error("invalid agent environment: "+s))});return}e.registerEntryRenderer(lc,(h,w,A)=>{let _=h?.data?.definitions;if(!Array.isArray(_)||!_.every(z=>z!==null&&typeof z=="object"&&!Array.isArray(z)))return;let M=typeof h?.data?.instructions=="string"?h.data.instructions:void 0;return Ql(_,A,{...w,instructions:M})}),e.registerEntryRenderer(Pr,(h,w,A)=>ec(h,A)),e.registerMessageRenderer("pi-herdsman-stop-summary",(h,w,A)=>Zl(h,A)),e.registerMessageRenderer("pi-herdsman-agent-result",(h,w,A)=>ic(h,w,A)),e.registerMessageRenderer("pi-herdsman-agent-ask",(h,w,A)=>rc(h,w,A)),e.registerMessageRenderer("pi-herdsman-agent-stale",(h,w,A)=>oc(h,w,A)),e.registerMessageRenderer("pi-herdsman-agent-lost",(h,w,A)=>ac(h,w,A));let i=Fp();if(i==="unmanaged"){e.registerCommand("agents",{description:"Show Pi Herdsman setup guidance",handler:async(h,w)=>{w.hasUI&&w.ui.notify(`Pi Herdsman is inactive because this Pi session is not running inside Herdr.
|
|
266
279
|
|
|
267
280
|
Start Herdr in this project, then run Pi in a Herdr pane:
|
|
@@ -308,7 +321,7 @@ Last qualifying progress: ${Math.floor(B/6e4)}m ${Math.floor(B%6e4/1e3)}s ago
|
|
|
308
321
|
Streaming tool output does not reset progress.
|
|
309
322
|
This is an advisory, not proof of a hang.
|
|
310
323
|
Inspect once, then leave the agent alone or close the exact agent only when evidence shows it remains wedged;
|
|
311
|
-
do not close solely because progress is stale.`,display:!0,details:{runId:q.runId,requestId:q.activeRequestId,agentLabel:q.agentLabel,ownerSessionId:q.ownerSessionId,workspaceId:q.workspaceId,paneId:q.paneId,piSessionId:q.piSessionId,lastActivityAt:q.lastActivityAt,inactiveMs:B,thresholdMs:Ai}},{triggerTurn:!0,deliverAs:"steer"}),I===Sn&&!y.aborted&&Ge.set(D,q.lastActivityAt)}catch{}}},hu=(m,y)=>{let I=++Sn,R=!1,P=!1,S=()=>{P=!0,!(R||y.aborted)&&(R=!0,(async()=>{for(;P&&!y.aborted;)P=!1,await mu(m,y,I)})().catch(()=>{}).finally(()=>{R=!1,P&&!y.aborted&&S()}))};gn&&clearTimeout(gn);let L=()=>{y.aborted||I!==Sn||(gn=setTimeout(()=>{y.aborted||I!==Sn||(gn=void 0,S(),I===Sn&&L())},Sp),gn.unref?.())};S(),process.env.HERDR_SOCKET_PATH&&al(process.env.HERDR_SOCKET_PATH,y,()=>{je?.(),S()}),L()};a.kind==="managed-agent"&&(Ha=Qa),Xr=hu,Cn=m=>{if(m.mode!=="tui"||!m.hasUI)return;let y=++K;ee=m,m.ui.setWidget("pi-herdsman",(I,R)=>{let P=ta(()=>I.requestRender(),R);return a.kind==="managed-agent"&&P.setSnapshot({agents:[],stale:!1,unavailable:!0,breadcrumb:so,...js()}),y===K&&m===ee?(h=P,Ee=y):P.dispose(),P}),je=()=>{ee===m&&Gi(m,y)},J=setInterval(()=>{Gi(m,y)},2e3),Gi(m,y)},e.on("session_start",async(m,y)=>{me(),l=void 0,++v;let I=u,R=p;++b,I==="active"&&R&&await ye(R,"suspended",b);let P,S=O=>{try{O()}catch(D){P??=D}};if(Ke&&S(()=>ke()),p=y,u="inactive",S(()=>f?.release()),f=void 0,Ue(),P&&Y(e,y,"pi_herdsman_role_error",P),a.kind==="lead"){let O=y.sessionManager.getSessionId();A=void 0,_=Bp(y.sessionManager.getEntries(),O),M=_===void 0,Tr=G}if(a.kind==="lead"){rs(y);let O="lead",D=!1;try{O=Il(y.sessionManager.getEntries())}catch(q){D=!0,Y(e,y,"pi_herdsman_role_error",q),he("lead"),ae=!1;try{Wt(ue(),y.sessionManager.getSessionId(),Me)}catch(B){Y(e,y,"pi_herdsman_state_error",B)}We(y,!1),e.setActiveTools(e.getActiveTools().filter(B=>B!=="chief"))}if(O==="chief")try{await Oa(y,!0),u==="active"&&ye(y,u,b)}catch(q){q instanceof Oe?en(y):(Y(e,y,"pi_herdsman_role_error",q),Hi?Hi=!1:We(y))}else!D&&!Ke&&ct("inactive")}Te?.abort(),w.clear(),Te=new AbortController;let L=Te.signal;a.kind==="lead"&&process.env.HERDR_SOCKET_PATH&&(u==="inactive"||u==="active")&&(u==="active"||ae)&&Zc(y),J&&clearInterval(J),J=void 0,ie=!1,H=!1,h&&(ee?.ui.setWidget("pi-herdsman",void 0),h.dispose(),h=void 0),Vn?.(I==="active"),Ee=0,ee=void 0,je=void 0;let E=++K;if(cn=!0,ee=y,a.kind==="lead"&&process.env.HERDR_PANE_ID&&u==="inactive"&&t(y,{paneId:process.env.HERDR_PANE_ID,name:e.getSessionName(),...re?{pendingAskId:re.askId}:{}}),io=a.kind==="managed-agent"?e.getActiveTools():void 0,Pt={agents:[],stale:!1,unavailable:!0,breadcrumb:so,...js()},a.kind==="lead"&&u==="active"?is?.(y):Cn?.(y),!(a.kind==="lead"&&u==="active"))try{l={sessionId:y.sessionManager.getSessionId(),definitions:await Sc(y,a)}}catch(O){l=void 0,Y(e,y,"pi_herdsman_definition_error",O)}if(a.kind==="managed-agent"){je?.();return}await Qa(y,L),a.kind==="lead"&&_!==void 0&&y.isIdle()&&(M=!0,G(y)),Xr(y,L)}),a.kind==="lead"&&e.on("session_info_changed",(m,y)=>{u==="inactive"&&process.env.HERDR_PANE_ID&&t(y,{paneId:process.env.HERDR_PANE_ID,name:m?.name??e.getSessionName(),...re?{pendingAskId:re.askId}:{}})}),e.on("session_tree",(m,y)=>{if(cn)for(let I of ve.values())I.activeRequestId&&$i(e,I,y,Te?.signal)}),e.on("session_shutdown",async()=>{if(++v,l=void 0,++Ae,oe&&clearTimeout(oe),oe=void 0,++b,a.kind==="lead"&&u==="active")en(p);else if(a.kind==="lead"){try{let m=p?.sessionManager.getSessionId();m&&Wt(ue(),m,Me)}catch(m){p&&Y(e,p,"pi_herdsman_state_error",m)}We(void 0,!1)}Te?.abort(),w.clear(),Te=void 0,++K,cn=!1,J&&clearInterval(J),J=void 0,gn&&clearTimeout(gn),gn=void 0,++Sn,Ge.clear(),ie=!1,H=!1,h&&(ee?.ui.setWidget("pi-herdsman",void 0),h.dispose(),h=void 0),Vn?.(),Ee=0,ee=void 0,p=void 0,je=void 0,a.kind==="lead"&&(A=void 0,_=void 0,M=!0,Tr=void 0);for(let[m,y]of Ri)Lr(m,y);Ri.clear();for(let[m,y]of Mi)Lr(m,y);Mi.clear();for(let m of xi.values())clearTimeout(m);xi.clear();for(let m of At.values())clearTimeout(m);At.clear();for(let m of es.values())clearTimeout(m);es.clear();for(let m of zn.values())clearTimeout(m);zn.clear();for(let m of ns.values())clearTimeout(m);ns.clear(),$r.clear(),Pi.clear(),Cr.clear(),ve.clear(),xe.clear()}),e.registerTool({name:"agent",label:"agent",description:$p(a),executionMode:"sequential",parameters:o,execute:async(m,y,I,R,P)=>{try{if(!d.Check(y))throw Mr(typeof y?.action=="string"?y.action:"agent","Invalid agent input");let S=await Dm(e,P,y,I,a,w);if(je?.(),a.kind==="lead"&&(y.action==="delegate"||y.action==="continue")&&S.ok===!0&&z(P),(y.action==="delegate"||y.action==="continue")&&S.ok===!0&&!Jr)try{e.sendMessage({customType:"pi-herdsman-delegation-guidance",content:"Agent work is asynchronous. Delegate any other useful independent work now. If no useful independent work remains, end your turn; do not poll, sleep, or actively wait. Agent results and attention will resume it automatically. Do not conclude or produce the final synthesis while unresolved agent work remains.",display:!1},{triggerTurn:!0,deliverAs:"steer"}),Jr=!0}catch{}xe.size&&(S.cleanup_errors=Object.fromEntries(xe));let L=typeof S.presentation_agent_definition=="string"?S.presentation_agent_definition:typeof S.definition=="string"?S.definition:void 0,E=wi(na(y.action,S),{keep:"head",sessionId:P.sessionManager.getSessionId(),key:m});return{content:[{type:"text",text:E.content}],details:{...S,...L?{presentation_agent_definition:L}:{},truncated:E.truncated,...E.fullOutputPath?{full_output_path:E.fullOutputPath}:{}}}}catch(S){if(!(S instanceof Pe))throw S;let L=S.detail,E=wi(na(y.action,{ok:!1,error:L}),{keep:"head",sessionId:P.sessionManager.getSessionId(),key:m});return{content:[{type:"text",text:E.content}],details:{ok:!1,error:L,truncated:E.truncated,...E.fullOutputPath?{full_output_path:E.fullOutputPath}:{}}}}},renderCall:(m,y,I)=>{let R=I?.args??m??{},P=R.action!=="delegate"&&typeof R.agent=="string"?ve.get(R.agent)?.agentDefinition:void 0;return yi("agent",m,y,{...I,agentDefinition:P})},renderResult:(m,y,I,R)=>Er("agent",m,y,I,R)}),a.kind==="lead"&&process.env.HERDR_PANE_ID&&e.registerTool(Rt)}if(i!=="managed-agent")return;As=!1;let C,os=!1,Tn="",dn,as=0,ze,fn,Ns,ji=!1,gt=!1,pt=!1,Yr=!1,Vr=!1,Ls,qs,Dn=r.length>0,ds,Fi,mt,Mt=0,Bi=!1,Ui,Qr=!1,Zr=h=>{if(!C)return;let w=process.env.PI_HERDSMAN_MAILBOX,A=vi(w);if(A)try{let _=be(w);if(!_||!Re(_,C))return;let M=h(_);return wt(w,M),C=M,Qr=!1,M}catch(_){Ls&&!Qr&&Y(e,Ls,"pi_herdsman_state_error",_),Qr=!0;return}finally{A()}},ja=(h,w)=>{gt||Y(e,h,"pi_herdsman_state_error",w),gt=!0},eo=()=>Ui?{ownTools:Ui}:{},Os=(h=Date.now(),w=!1)=>{!C?.activeRequestId||dn||!w&&C.lastActivityAt!==void 0&&h>=C.lastActivityAt&&h-C.lastActivityAt<vp||Zr(A=>({...A,lastActivityAt:h,updatedAt:h}))},Wi,Fa=()=>{++Mt,Fi&&clearInterval(Fi),Fi=void 0,ds&&(mt?.ui.setWidget("pi-herdsman",void 0),ds.dispose(),ds=void 0),mt=void 0,Bi=!1},Ba=async(h,w)=>{if(!(w!==Mt||h!==mt||Bi)){Bi=!0;try{let A=await an(e,h,kt?.signal,!0);if(w!==Mt||h!==mt)return;Wi=pc(A,h),ds?.setSnapshot({agents:[],stale:!1,unavailable:!1,breadcrumb:Wi,...eo(),identityOnly:!0,refreshedAt:Date.now()})}catch{w===Mt&&h===mt&&ds?.setSnapshot({agents:[],stale:!1,unavailable:!0,breadcrumb:Wi??["?",process.env.PI_HERDSMAN_AGENT_DEFINITION&&process.env.PI_HERDSMAN_LABEL?Dt(process.env.PI_HERDSMAN_AGENT_DEFINITION,process.env.PI_HERDSMAN_LABEL):process.env.PI_HERDSMAN_AGENT_DEFINITION??"?"],...eo(),identityOnly:!0})}finally{w===Mt&&h===mt&&(Bi=!1)}}},no=()=>{for(let h of[...ve.values()])Ps(h.label);ve.clear()},tu=(h,w,A,_)=>C&&Zr(z=>({...z,lastAck:{requestId:h,accepted:w,...A?{code:A}:{},..._?{message:_}:{},acknowledgedAt:Date.now()},updatedAt:Date.now()}))?(gt=!1,!0):!1,Zn=(h,w,A,_,M)=>{if(!C)return;let z=process.env.PI_HERDSMAN_MAILBOX,G=vi(z);if(G)try{let J=be(z);if(!J||!Re(J,C))return;let ie={...J,lastAck:{requestId:h,accepted:w,..._?{code:_}:{},...M?{message:M}:{},acknowledgedAt:Date.now()},updatedAt:Date.now()};wt(z,ie),tr(z,h),C=ie,gt=!1,ma(J.agentLabel)}catch(J){Ls&&ja(Ls,J)}finally{G()}},Ua=h=>{if(!(!os||!C))try{let w=hs(process.env.PI_HERDSMAN_MAILBOX,C);if(!w){ji=!1,gt=!1;return}e.sendUserMessage(yd(w.requestId),{deliverAs:"steer"})}catch(w){ji||(ji=!0,Y(e,h,"pi_herdsman_state_error",w))}},Wa=()=>{Ns&&clearInterval(Ns),Ns=void 0,ji=!1,gt=!1},su=()=>!!C?.activeRequestId&&!C.pendingAskId&&!C.completedRequestId&&!dn&&!pt&&!$t(process.env.PI_HERDSMAN_MAILBOX,C)&&yc(C),iu=()=>C?.activeRequestId?C.pendingAskId?"already waiting for an owner reply":C.completedRequestId||dn?"assignment is settling":pt?"assignment state is settling":$t(process.env.PI_HERDSMAN_MAILBOX,C)?"a control request is still pending":yc(C)?"agent state is not eligible":"direct agent work is still active":"no active assignment";e.registerTool({name:"ask_owner",label:"Ask owner",description:"Ask your direct owner for a decision that is required to continue. Call this alone as the final tool call of the turn, then stop and wait for the reply. Only one question may be outstanding.",executionMode:"sequential",parameters:F.Object({question:F.String({minLength:1,description:"Non-empty decision question required to continue."}),files:F.Optional(F.Array(F.String({description:"Readable regular local file path or result:<request-id>."}),{description:"Supporting files, including result:<request-id>. Complete strict UTF-8 text may be embedded when it fits; other files are canonical local references. Files do not grant capabilities."}))},{additionalProperties:!1}),execute:async(h,w,A,_,M)=>{if(typeof w.question!="string"||!w.question.trim())throw new Error("Question must contain non-whitespace text");if(!em(M))throw new Error("Call ask_owner alone as the final tool call of the turn, with no other tool calls, then wait for the reply.");let z=Rc(M);if(!C||!Re(C,z))throw new Error("Agent identity is not eligible to ask its owner");if(!su())throw new Error(`Agent cannot ask its owner: ${iu()}`);let G=bn(),J=Date.now(),ie=await Ci(M),H={version:4,askId:G,requestId:C.activeRequestId,runId:C.runId,ownerSessionId:C.ownerSessionId,workspaceId:C.workspaceId,agentLabel:C.agentLabel,paneId:C.paneId,piSessionId:C.piSessionId,question:Tt(w.question,w.files??[],C.cwd,"ask_owner","Question",{inlineLimitBytes:ie.inline.bytes,mailboxLimitBytes:ie.mailbox.bytes,serializedBytes:Ge=>Tm(C,G,Ge,J)}).text,createdAt:J},ee=ms(H);ee>ie.mailbox.bytes&&$("invalid_request",`Mailbox payload is ${ee} bytes; configured limit is ${ie.mailbox.bytes} bytes`,"ask_owner");let K=process.env.PI_HERDSMAN_MAILBOX,Ee=Gn(K,"ask_owner",{label:C.agentLabel,paneId:C.paneId});try{let Ge=be(K);if(!Ge||!Re(Ge,C))throw new Error("Agent identity changed while asking its owner");pd(K,H);let gn={...Ge,pendingAskId:G,updatedAt:Date.now()};wt(K,gn),C=gn}catch(Ge){try{wo(K)}catch{}throw Ge}finally{Ee()}return Tn="",{content:[{type:"text",text:"Question sent to your owner. This assignment is blocked until the reply; the reply will resume it automatically."}],details:{askId:G,assignmentRequestId:H.requestId},terminate:!0}}}),e.on("session_before_compact",(h,w)=>{if(!Bn().contextRetirement||!C?.activeRequestId||h.reason==="manual")return;let A=w.sessionManager.getSessionId(),_=w.sessionManager.getEntries();if(ha(_,A)||e.appendEntry(ga,{sessionId:A}),h.reason==="threshold")return{cancel:!0}}),e.on("context",(h,w)=>{if(!Bn().contextRetirement||!C?.activeRequestId)return;let A=w.sessionManager.getSessionId();if(ha(w.sessionManager.getEntries(),A))return{messages:[...h.messages,{role:"custom",customType:ga,content:bp,display:!1,timestamp:Date.now()}]}}),e.on("session_before_switch",()=>({cancel:!0})),e.on("session_before_fork",()=>({cancel:!0})),e.on("session_start",async(h,w)=>{Wa(),Fa(),Ui=void 0,Dn&&no(),os=!1,As=!1,C=void 0,qs=void 0,Wi=void 0,kt?.abort(),kt=new AbortController;try{let A=!1;Ls=w;let _=Pc(w);if(!_)throw new Error("invalid agent environment");Dn||(Ui=e.getActiveTools()),Kp(e,w,process.env.PI_HERDSMAN_AGENT_DEFINITION,process.env.PI_HERDSMAN_LABEL);let M=be(process.env.PI_HERDSMAN_MAILBOX);if(M&&!Re(M,_))throw new Error("agent session identity changed while state existed");if(C=_,M&&Re(M,_)&&(C={..._,...M,updatedAt:Date.now()},A=!!C.activeRequestId,C.activeRequestId&&!C.pendingAskId))try{let H=Hn(process.env.PI_HERDSMAN_MAILBOX,C.activeRequestId);H&&H.runId===C.runId&&H.ownerSessionId===C.ownerSessionId&&H.workspaceId===C.workspaceId&&H.agentLabel===C.agentLabel&&H.paneId===C.paneId&&H.requestId===C.activeRequestId?(C={...C,activeRequestId:void 0,completedRequestId:H.requestId,lastActivityAt:void 0,updatedAt:Date.now()},A=!1):H&&Y(e,w,"pi_herdsman_state_error",new Error("active agent result identity did not match state"))}catch(H){Y(e,w,"pi_herdsman_state_error",H)}if(!M){let{definitions:H}=await Es(w),ee=H.find(K=>K.name===process.env.PI_HERDSMAN_AGENT_DEFINITION);if(!ee)throw new Error(`agent ${process.env.PI_HERDSMAN_AGENT_DEFINITION} not found`);if(!qt(ee))throw new Error(`agent ${ee.name} is disabled; enable it through /agents \u2192 Definitions before starting a new agent`);Ro(ee,H)}let z=process.env.PI_HERDSMAN_MAILBOX,G=Gn(z,"session_start",{label:C.agentLabel,paneId:C.paneId});try{let H=be(z);if(H&&!Re(H,C))throw new Error("agent session identity changed while state existed");if(M!==void 0&&H===void 0)throw new Error("agent mailbox disappeared while state existed");if(M!==void 0&&H!==void 0&&!dm(H,M))throw new Error("agent mailbox changed while session start was preparing");M===void 0&&H!==void 0&&(C={..._,...H,updatedAt:Date.now()}),wt(z,C)}finally{G()}if(Dn){let H=a;if(!H||H.kind!=="managed-agent")throw new Error("delegation controller scope is unavailable");nm(w),await Ha?.(w,kt.signal),As=!0}if(C.activeRequestId&&Os(Date.now(),A),Dn&&Xr?.(w,kt.signal),os=!0,Ua(w),Ns=setInterval(()=>Ua(w),250),Ns.unref?.(),!Dn&&w.mode==="tui"&&w.hasUI){let H=Mt;mt=w,w.ui.setWidget("pi-herdsman",(ee,K)=>{let Ee=ta(()=>ee.requestRender(),K);return Ee.setSnapshot({agents:[],stale:!1,unavailable:!0,breadcrumb:["?",process.env.PI_HERDSMAN_AGENT_DEFINITION&&process.env.PI_HERDSMAN_LABEL?Dt(process.env.PI_HERDSMAN_AGENT_DEFINITION,process.env.PI_HERDSMAN_LABEL):process.env.PI_HERDSMAN_AGENT_DEFINITION??"?"],...eo(),identityOnly:!0}),H===Mt&&w===mt?ds=Ee:Ee.dispose(),Ee}),Fi=setInterval(()=>{Ba(w,H)},2e3),Ba(w,H)}let J=w.model?`${w.model.provider}/${w.model.id}`:void 0,ie=w.thinkingLevel;Qt(e,w,Zt(C,w),{activity:null,context:null,model:J||null,thinking:ie||null},!0)}catch(A){os=!1,As=!1,C=void 0,Dn&&no(),Y(e,w,"pi_herdsman_state_error",A),w.ui.notify(`pi_herdsman_state_error: ${String(A)}`,"error")}}),e.on("input",(h,w)=>{let A=h.text;if(typeof A!="string"||!A.startsWith(yp))return{action:"continue"};let _=wd(A);if(!_)return{action:"handled"};let M;try{M=yo(process.env.PI_HERDSMAN_MAILBOX,_)}catch{return Zn(_,!1,w,"invalid","Malformed or oversized request"),{action:"handled"}}if(!M)return{action:"handled"};if(!os||!C)return{action:"handled"};if(C.lastAck?.requestId===_)return{action:"handled"};if(M.runId!==C.runId||M.ownerSessionId!==C.ownerSessionId||M.workspaceId!==C.workspaceId||M.agentLabel!==C.agentLabel||M.paneId!==C.paneId)return Zn(_,!1,w,"identity","Request identity did not match agent state"),{action:"handled"};if(M.kind==="reply"){let G;try{G=ys(process.env.PI_HERDSMAN_MAILBOX,C)}catch(ee){return Y(e,w,"pi_herdsman_state_error",ee),Zn(_,!1,w,"identity","Malformed or oversized owner ask"),{action:"handled"}}if(!C.activeRequestId||!C.pendingAskId||M.askId!==C.pendingAskId||!G||G.askId!==C.pendingAskId||G.requestId!==C.activeRequestId||G.runId!==C.runId||G.ownerSessionId!==C.ownerSessionId||G.workspaceId!==C.workspaceId||G.agentLabel!==C.agentLabel||G.paneId!==C.paneId||G.piSessionId!==C.piSessionId)return Zn(_,!1,w,"identity","Owner reply did not match the pending ask"),{action:"handled"};let J={...C,pendingAskId:void 0,lastAck:{requestId:_,accepted:!0,acknowledgedAt:Date.now()},updatedAt:Date.now()},ie=process.env.PI_HERDSMAN_MAILBOX,H=vi(ie);if(!H)return{action:"handled"};try{let ee=be(ie);if(!ee||!Re(ee,C)||ee.pendingAskId!==C.pendingAskId)return{action:"handled"};wt(ie,J),wo(ie)}catch(ee){return ja(w,ee),{action:"handled"}}finally{H()}return C=J,gt=!1,Tn="",{action:"transform",text:`Owner reply:
|
|
324
|
+
do not close solely because progress is stale.`,display:!0,details:{runId:q.runId,requestId:q.activeRequestId,agentLabel:q.agentLabel,ownerSessionId:q.ownerSessionId,workspaceId:q.workspaceId,paneId:q.paneId,piSessionId:q.piSessionId,lastActivityAt:q.lastActivityAt,inactiveMs:B,thresholdMs:Ai}},{triggerTurn:!0,deliverAs:"steer"}),I===Sn&&!y.aborted&&Ge.set(D,q.lastActivityAt)}catch{}}},hu=(m,y)=>{let I=++Sn,R=!1,P=!1,S=()=>{P=!0,!(R||y.aborted)&&(R=!0,(async()=>{for(;P&&!y.aborted;)P=!1,await mu(m,y,I)})().catch(()=>{}).finally(()=>{R=!1,P&&!y.aborted&&S()}))};gn&&clearTimeout(gn);let L=()=>{y.aborted||I!==Sn||(gn=setTimeout(()=>{y.aborted||I!==Sn||(gn=void 0,S(),I===Sn&&L())},Sp),gn.unref?.())};S(),process.env.HERDR_SOCKET_PATH&&al(process.env.HERDR_SOCKET_PATH,y,()=>{je?.(),S()}),L()};a.kind==="managed-agent"&&(Ha=Qa),Xr=hu,Cn=m=>{if(m.mode!=="tui"||!m.hasUI)return;let y=++K;ee=m,m.ui.setWidget("pi-herdsman",(I,R)=>{let P=ta(()=>I.requestRender(),R);return a.kind==="managed-agent"&&P.setSnapshot({agents:[],stale:!1,unavailable:!0,breadcrumb:so,...js()}),y===K&&m===ee?(h=P,Ee=y):P.dispose(),P}),je=()=>{ee===m&&Gi(m,y)},J=setInterval(()=>{Gi(m,y)},2e3),Gi(m,y)},e.on("session_start",async(m,y)=>{me(),l=void 0,++v;let I=u,R=p;++b,I==="active"&&R&&await ye(R,"suspended",b);let P,S=O=>{try{O()}catch(D){P??=D}};if(Ke&&S(()=>ke()),p=y,u="inactive",S(()=>f?.release()),f=void 0,Ue(),P&&Y(e,y,"pi_herdsman_role_error",P),a.kind==="lead"){let O=y.sessionManager.getSessionId();A=void 0,_=Bp(y.sessionManager.getEntries(),O),M=_===void 0,Tr=G}if(a.kind==="lead"){rs(y);let O="lead",D=!1;try{O=Il(y.sessionManager.getEntries())}catch(q){D=!0,Y(e,y,"pi_herdsman_role_error",q),he("lead"),ae=!1;try{Wt(ue(),y.sessionManager.getSessionId(),Me)}catch(B){Y(e,y,"pi_herdsman_state_error",B)}We(y,!1),e.setActiveTools(e.getActiveTools().filter(B=>B!=="chief"))}if(O==="chief")try{await Oa(y,!0),u==="active"&&ye(y,u,b)}catch(q){q instanceof Oe?en(y):(Y(e,y,"pi_herdsman_role_error",q),Hi?Hi=!1:We(y))}else!D&&!Ke&&ct("inactive")}Te?.abort(),w.clear(),Te=new AbortController;let L=Te.signal;a.kind==="lead"&&process.env.HERDR_SOCKET_PATH&&(u==="inactive"||u==="active")&&(u==="active"||ae)&&Zc(y),J&&clearInterval(J),J=void 0,ie=!1,H=!1,h&&(ee?.ui.setWidget("pi-herdsman",void 0),h.dispose(),h=void 0),Vn?.(I==="active"),Ee=0,ee=void 0,je=void 0;let E=++K;if(cn=!0,ee=y,a.kind==="lead"&&process.env.HERDR_PANE_ID&&u==="inactive"&&t(y,{paneId:process.env.HERDR_PANE_ID,name:e.getSessionName(),...re?{pendingAskId:re.askId}:{}}),io=a.kind==="managed-agent"?e.getActiveTools():void 0,Pt={agents:[],stale:!1,unavailable:!0,breadcrumb:so,...js()},a.kind==="lead"&&u==="active"?is?.(y):Cn?.(y),!(a.kind==="lead"&&u==="active"))try{l={sessionId:y.sessionManager.getSessionId(),definitions:await Sc(y,a)}}catch(O){l=void 0,Y(e,y,"pi_herdsman_definition_error",O)}if(a.kind==="managed-agent"){je?.();return}await Qa(y,L),a.kind==="lead"&&_!==void 0&&y.isIdle()&&(M=!0,G(y)),Xr(y,L)}),a.kind==="lead"&&e.on("session_info_changed",(m,y)=>{u==="inactive"&&process.env.HERDR_PANE_ID&&t(y,{paneId:process.env.HERDR_PANE_ID,name:m?.name??e.getSessionName(),...re?{pendingAskId:re.askId}:{}})}),e.on("session_tree",(m,y)=>{if(cn)for(let I of ve.values())I.activeRequestId&&$i(e,I,y,Te?.signal)}),e.on("session_shutdown",async()=>{if(++v,l=void 0,++Ae,oe&&clearTimeout(oe),oe=void 0,++b,a.kind==="lead"&&u==="active")en(p);else if(a.kind==="lead"){try{let m=p?.sessionManager.getSessionId();m&&Wt(ue(),m,Me)}catch(m){p&&Y(e,p,"pi_herdsman_state_error",m)}We(void 0,!1)}Te?.abort(),w.clear(),Te=void 0,++K,cn=!1,J&&clearInterval(J),J=void 0,gn&&clearTimeout(gn),gn=void 0,++Sn,Ge.clear(),ie=!1,H=!1,h&&(ee?.ui.setWidget("pi-herdsman",void 0),h.dispose(),h=void 0),Vn?.(),Ee=0,ee=void 0,p=void 0,je=void 0,a.kind==="lead"&&(A=void 0,_=void 0,M=!0,Tr=void 0);for(let[m,y]of Ri)Lr(m,y);Ri.clear();for(let[m,y]of Mi)Lr(m,y);Mi.clear();for(let m of xi.values())clearTimeout(m);xi.clear();for(let m of At.values())clearTimeout(m);At.clear();for(let m of es.values())clearTimeout(m);es.clear();for(let m of zn.values())clearTimeout(m);zn.clear();for(let m of ns.values())clearTimeout(m);ns.clear(),$r.clear(),Pi.clear(),Cr.clear(),ve.clear(),xe.clear()}),e.registerTool({name:"agent",label:"agent",description:$p(a),executionMode:"sequential",parameters:o,execute:async(m,y,I,R,P)=>{try{if(!d.Check(y))throw Mr(typeof y?.action=="string"?y.action:"agent","Invalid agent input");let S=await Dm(e,P,y,I,a,w);if(je?.(),a.kind==="lead"&&(y.action==="delegate"||y.action==="continue")&&S.ok===!0&&z(P),(y.action==="delegate"||y.action==="continue")&&S.ok===!0&&!Jr)try{e.sendMessage({customType:"pi-herdsman-delegation-guidance",content:"An agent assignment started. Reassess the remaining work. Handle required agent control if needed. If another concrete, necessary objective is independent of active agent assignments and an authorized agent is the right owner, delegate it. If a concrete, necessary independent objective is best handled locally and doing it now materially advances the task, do that work, then reassess. Otherwise end your turn without concluding the task; agent results or attention will resume this session automatically. Do not conclude or produce the final synthesis while unresolved agent work remains. Do not invent side work, repeat delegated work, create substantially overlapping assignments, poll, sleep, inspect for progress, steer for status, or otherwise keep the turn alive merely because agents are running.",display:!1},{triggerTurn:!0,deliverAs:"steer"}),Jr=!0}catch{}xe.size&&(S.cleanup_errors=Object.fromEntries(xe));let L=typeof S.presentation_agent_definition=="string"?S.presentation_agent_definition:typeof S.definition=="string"?S.definition:void 0,E=wi(na(y.action,S),{keep:"head",sessionId:P.sessionManager.getSessionId(),key:m});return{content:[{type:"text",text:E.content}],details:{...S,...L?{presentation_agent_definition:L}:{},truncated:E.truncated,...E.fullOutputPath?{full_output_path:E.fullOutputPath}:{}}}}catch(S){if(!(S instanceof Pe))throw S;let L=S.detail,E=wi(na(y.action,{ok:!1,error:L}),{keep:"head",sessionId:P.sessionManager.getSessionId(),key:m});return{content:[{type:"text",text:E.content}],details:{ok:!1,error:L,truncated:E.truncated,...E.fullOutputPath?{full_output_path:E.fullOutputPath}:{}}}}},renderCall:(m,y,I)=>{let R=I?.args??m??{},P=R.action!=="delegate"&&typeof R.agent=="string"?ve.get(R.agent)?.agentDefinition:void 0;return yi("agent",m,y,{...I,agentDefinition:P})},renderResult:(m,y,I,R)=>Er("agent",m,y,I,R)}),a.kind==="lead"&&process.env.HERDR_PANE_ID&&e.registerTool(Rt)}if(i!=="managed-agent")return;As=!1;let C,os=!1,Tn="",dn,as=0,ze,fn,Ns,ji=!1,gt=!1,pt=!1,Yr=!1,Vr=!1,Ls,qs,Dn=r.length>0,ds,Fi,mt,Mt=0,Bi=!1,Ui,Qr=!1,Zr=h=>{if(!C)return;let w=process.env.PI_HERDSMAN_MAILBOX,A=vi(w);if(A)try{let _=be(w);if(!_||!Re(_,C))return;let M=h(_);return wt(w,M),C=M,Qr=!1,M}catch(_){Ls&&!Qr&&Y(e,Ls,"pi_herdsman_state_error",_),Qr=!0;return}finally{A()}},ja=(h,w)=>{gt||Y(e,h,"pi_herdsman_state_error",w),gt=!0},eo=()=>Ui?{ownTools:Ui}:{},Os=(h=Date.now(),w=!1)=>{!C?.activeRequestId||dn||!w&&C.lastActivityAt!==void 0&&h>=C.lastActivityAt&&h-C.lastActivityAt<vp||Zr(A=>({...A,lastActivityAt:h,updatedAt:h}))},Wi,Fa=()=>{++Mt,Fi&&clearInterval(Fi),Fi=void 0,ds&&(mt?.ui.setWidget("pi-herdsman",void 0),ds.dispose(),ds=void 0),mt=void 0,Bi=!1},Ba=async(h,w)=>{if(!(w!==Mt||h!==mt||Bi)){Bi=!0;try{let A=await an(e,h,kt?.signal,!0);if(w!==Mt||h!==mt)return;Wi=pc(A,h),ds?.setSnapshot({agents:[],stale:!1,unavailable:!1,breadcrumb:Wi,...eo(),identityOnly:!0,refreshedAt:Date.now()})}catch{w===Mt&&h===mt&&ds?.setSnapshot({agents:[],stale:!1,unavailable:!0,breadcrumb:Wi??["?",process.env.PI_HERDSMAN_AGENT_DEFINITION&&process.env.PI_HERDSMAN_LABEL?Dt(process.env.PI_HERDSMAN_AGENT_DEFINITION,process.env.PI_HERDSMAN_LABEL):process.env.PI_HERDSMAN_AGENT_DEFINITION??"?"],...eo(),identityOnly:!0})}finally{w===Mt&&h===mt&&(Bi=!1)}}},no=()=>{for(let h of[...ve.values()])Ps(h.label);ve.clear()},tu=(h,w,A,_)=>C&&Zr(z=>({...z,lastAck:{requestId:h,accepted:w,...A?{code:A}:{},..._?{message:_}:{},acknowledgedAt:Date.now()},updatedAt:Date.now()}))?(gt=!1,!0):!1,Zn=(h,w,A,_,M)=>{if(!C)return;let z=process.env.PI_HERDSMAN_MAILBOX,G=vi(z);if(G)try{let J=be(z);if(!J||!Re(J,C))return;let ie={...J,lastAck:{requestId:h,accepted:w,..._?{code:_}:{},...M?{message:M}:{},acknowledgedAt:Date.now()},updatedAt:Date.now()};wt(z,ie),tr(z,h),C=ie,gt=!1,ma(J.agentLabel)}catch(J){Ls&&ja(Ls,J)}finally{G()}},Ua=h=>{if(!(!os||!C))try{let w=hs(process.env.PI_HERDSMAN_MAILBOX,C);if(!w){ji=!1,gt=!1;return}e.sendUserMessage(yd(w.requestId),{deliverAs:"steer"})}catch(w){ji||(ji=!0,Y(e,h,"pi_herdsman_state_error",w))}},Wa=()=>{Ns&&clearInterval(Ns),Ns=void 0,ji=!1,gt=!1},su=()=>!!C?.activeRequestId&&!C.pendingAskId&&!C.completedRequestId&&!dn&&!pt&&!$t(process.env.PI_HERDSMAN_MAILBOX,C)&&yc(C),iu=()=>C?.activeRequestId?C.pendingAskId?"already waiting for an owner reply":C.completedRequestId||dn?"assignment is settling":pt?"assignment state is settling":$t(process.env.PI_HERDSMAN_MAILBOX,C)?"a control request is still pending":yc(C)?"agent state is not eligible":"direct agent work is still active":"no active assignment";e.registerTool({name:"ask_owner",label:"Ask owner",description:"Ask your direct owner for a decision that is required to continue. Call this alone as the final tool call of the turn, then stop and wait for the reply. Only one question may be outstanding.",executionMode:"sequential",parameters:F.Object({question:F.String({minLength:1,description:"Non-empty decision question required to continue."}),files:F.Optional(F.Array(F.String({description:"Readable regular local file path or result:<request-id>."}),{description:"Supporting files, including result:<request-id>. Complete strict UTF-8 text may be embedded when it fits; other files are canonical local references. Files do not grant capabilities."}))},{additionalProperties:!1}),execute:async(h,w,A,_,M)=>{if(typeof w.question!="string"||!w.question.trim())throw new Error("Question must contain non-whitespace text");if(!em(M))throw new Error("Call ask_owner alone as the final tool call of the turn, with no other tool calls, then wait for the reply.");let z=Rc(M);if(!C||!Re(C,z))throw new Error("Agent identity is not eligible to ask its owner");if(!su())throw new Error(`Agent cannot ask its owner: ${iu()}`);let G=bn(),J=Date.now(),ie=await Ci(M),H={version:4,askId:G,requestId:C.activeRequestId,runId:C.runId,ownerSessionId:C.ownerSessionId,workspaceId:C.workspaceId,agentLabel:C.agentLabel,paneId:C.paneId,piSessionId:C.piSessionId,question:Tt(w.question,w.files??[],C.cwd,"ask_owner","Question",{inlineLimitBytes:ie.inline.bytes,mailboxLimitBytes:ie.mailbox.bytes,serializedBytes:Ge=>Tm(C,G,Ge,J)}).text,createdAt:J},ee=ms(H);ee>ie.mailbox.bytes&&$("invalid_request",`Mailbox payload is ${ee} bytes; configured limit is ${ie.mailbox.bytes} bytes`,"ask_owner");let K=process.env.PI_HERDSMAN_MAILBOX,Ee=Gn(K,"ask_owner",{label:C.agentLabel,paneId:C.paneId});try{let Ge=be(K);if(!Ge||!Re(Ge,C))throw new Error("Agent identity changed while asking its owner");pd(K,H);let gn={...Ge,pendingAskId:G,updatedAt:Date.now()};wt(K,gn),C=gn}catch(Ge){try{wo(K)}catch{}throw Ge}finally{Ee()}return Tn="",{content:[{type:"text",text:"Question sent to your owner. This assignment is blocked until the reply; the reply will resume it automatically."}],details:{askId:G,assignmentRequestId:H.requestId},terminate:!0}}}),e.on("session_before_compact",(h,w)=>{if(!Bn().contextRetirement||!C?.activeRequestId||h.reason==="manual")return;let A=w.sessionManager.getSessionId(),_=w.sessionManager.getEntries();if(ha(_,A)||e.appendEntry(ga,{sessionId:A}),h.reason==="threshold")return{cancel:!0}}),e.on("context",(h,w)=>{if(!Bn().contextRetirement||!C?.activeRequestId)return;let A=w.sessionManager.getSessionId();if(ha(w.sessionManager.getEntries(),A))return{messages:[...h.messages,{role:"custom",customType:ga,content:bp,display:!1,timestamp:Date.now()}]}}),e.on("session_before_switch",()=>({cancel:!0})),e.on("session_before_fork",()=>({cancel:!0})),e.on("session_start",async(h,w)=>{Wa(),Fa(),Ui=void 0,Dn&&no(),os=!1,As=!1,C=void 0,qs=void 0,Wi=void 0,kt?.abort(),kt=new AbortController;try{let A=!1;Ls=w;let _=Pc(w);if(!_)throw new Error("invalid agent environment");Dn||(Ui=e.getActiveTools()),Kp(e,w,process.env.PI_HERDSMAN_AGENT_DEFINITION,process.env.PI_HERDSMAN_LABEL);let M=be(process.env.PI_HERDSMAN_MAILBOX);if(M&&!Re(M,_))throw new Error("agent session identity changed while state existed");if(C=_,M&&Re(M,_)&&(C={..._,...M,updatedAt:Date.now()},A=!!C.activeRequestId,C.activeRequestId&&!C.pendingAskId))try{let H=Hn(process.env.PI_HERDSMAN_MAILBOX,C.activeRequestId);H&&H.runId===C.runId&&H.ownerSessionId===C.ownerSessionId&&H.workspaceId===C.workspaceId&&H.agentLabel===C.agentLabel&&H.paneId===C.paneId&&H.requestId===C.activeRequestId?(C={...C,activeRequestId:void 0,completedRequestId:H.requestId,lastActivityAt:void 0,updatedAt:Date.now()},A=!1):H&&Y(e,w,"pi_herdsman_state_error",new Error("active agent result identity did not match state"))}catch(H){Y(e,w,"pi_herdsman_state_error",H)}if(!M){let{definitions:H}=await Es(w),ee=H.find(K=>K.name===process.env.PI_HERDSMAN_AGENT_DEFINITION);if(!ee)throw new Error(`agent ${process.env.PI_HERDSMAN_AGENT_DEFINITION} not found`);if(!qt(ee))throw new Error(`agent ${ee.name} is disabled; enable it through /agents \u2192 Definitions before starting a new agent`);Ro(ee,H)}let z=process.env.PI_HERDSMAN_MAILBOX,G=Gn(z,"session_start",{label:C.agentLabel,paneId:C.paneId});try{let H=be(z);if(H&&!Re(H,C))throw new Error("agent session identity changed while state existed");if(M!==void 0&&H===void 0)throw new Error("agent mailbox disappeared while state existed");if(M!==void 0&&H!==void 0&&!dm(H,M))throw new Error("agent mailbox changed while session start was preparing");M===void 0&&H!==void 0&&(C={..._,...H,updatedAt:Date.now()}),wt(z,C)}finally{G()}if(Dn){let H=a;if(!H||H.kind!=="managed-agent")throw new Error("delegation controller scope is unavailable");nm(w),await Ha?.(w,kt.signal),As=!0}if(C.activeRequestId&&Os(Date.now(),A),Dn&&Xr?.(w,kt.signal),os=!0,Ua(w),Ns=setInterval(()=>Ua(w),250),Ns.unref?.(),!Dn&&w.mode==="tui"&&w.hasUI){let H=Mt;mt=w,w.ui.setWidget("pi-herdsman",(ee,K)=>{let Ee=ta(()=>ee.requestRender(),K);return Ee.setSnapshot({agents:[],stale:!1,unavailable:!0,breadcrumb:["?",process.env.PI_HERDSMAN_AGENT_DEFINITION&&process.env.PI_HERDSMAN_LABEL?Dt(process.env.PI_HERDSMAN_AGENT_DEFINITION,process.env.PI_HERDSMAN_LABEL):process.env.PI_HERDSMAN_AGENT_DEFINITION??"?"],...eo(),identityOnly:!0}),H===Mt&&w===mt?ds=Ee:Ee.dispose(),Ee}),Fi=setInterval(()=>{Ba(w,H)},2e3),Ba(w,H)}let J=w.model?`${w.model.provider}/${w.model.id}`:void 0,ie=w.thinkingLevel;Qt(e,w,Zt(C,w),{activity:null,context:null,model:J||null,thinking:ie||null},!0)}catch(A){os=!1,As=!1,C=void 0,Dn&&no(),Y(e,w,"pi_herdsman_state_error",A),w.ui.notify(`pi_herdsman_state_error: ${String(A)}`,"error")}}),e.on("input",(h,w)=>{let A=h.text;if(typeof A!="string"||!A.startsWith(yp))return{action:"continue"};let _=wd(A);if(!_)return{action:"handled"};let M;try{M=yo(process.env.PI_HERDSMAN_MAILBOX,_)}catch{return Zn(_,!1,w,"invalid","Malformed or oversized request"),{action:"handled"}}if(!M)return{action:"handled"};if(!os||!C)return{action:"handled"};if(C.lastAck?.requestId===_)return{action:"handled"};if(M.runId!==C.runId||M.ownerSessionId!==C.ownerSessionId||M.workspaceId!==C.workspaceId||M.agentLabel!==C.agentLabel||M.paneId!==C.paneId)return Zn(_,!1,w,"identity","Request identity did not match agent state"),{action:"handled"};if(M.kind==="reply"){let G;try{G=ys(process.env.PI_HERDSMAN_MAILBOX,C)}catch(ee){return Y(e,w,"pi_herdsman_state_error",ee),Zn(_,!1,w,"identity","Malformed or oversized owner ask"),{action:"handled"}}if(!C.activeRequestId||!C.pendingAskId||M.askId!==C.pendingAskId||!G||G.askId!==C.pendingAskId||G.requestId!==C.activeRequestId||G.runId!==C.runId||G.ownerSessionId!==C.ownerSessionId||G.workspaceId!==C.workspaceId||G.agentLabel!==C.agentLabel||G.paneId!==C.paneId||G.piSessionId!==C.piSessionId)return Zn(_,!1,w,"identity","Owner reply did not match the pending ask"),{action:"handled"};let J={...C,pendingAskId:void 0,lastAck:{requestId:_,accepted:!0,acknowledgedAt:Date.now()},updatedAt:Date.now()},ie=process.env.PI_HERDSMAN_MAILBOX,H=vi(ie);if(!H)return{action:"handled"};try{let ee=be(ie);if(!ee||!Re(ee,C)||ee.pendingAskId!==C.pendingAskId)return{action:"handled"};wt(ie,J),wo(ie)}catch(ee){return ja(w,ee),{action:"handled"}}finally{H()}return C=J,gt=!1,Tn="",{action:"transform",text:`Owner reply:
|
|
312
325
|
|
|
313
326
|
${M.text}
|
|
314
327
|
|
|
@@ -84,21 +84,35 @@ Do not:
|
|
|
84
84
|
|
|
85
85
|
- delegate overlapping writers to one worktree;
|
|
86
86
|
- delegate review before the writer finishes;
|
|
87
|
-
-
|
|
88
|
-
-
|
|
87
|
+
- repeat work already assigned to an active agent;
|
|
88
|
+
- delegate substantially overlapping work to multiple active agents;
|
|
89
|
+
- continue work that depends on an active agent result;
|
|
90
|
+
- inspect, list, or steer active agents merely to check progress or completion.
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
Direct ownership grants lifecycle and control authority. It does not make the
|
|
93
|
+
owner a second executor of an active delegated assignment.
|
|
94
|
+
|
|
95
|
+
A useful parallel pattern is:
|
|
91
96
|
|
|
92
97
|
```text
|
|
93
|
-
|
|
94
|
-
├──
|
|
95
|
-
|
|
98
|
+
controller
|
|
99
|
+
├── agent A: independent reconnaissance
|
|
100
|
+
├── agent B: separate independent analysis
|
|
101
|
+
└── local: bounded independent controller work
|
|
102
|
+
|
|
103
|
+
local work becomes sufficiently complete
|
|
104
|
+
↓
|
|
105
|
+
controller ends its turn
|
|
96
106
|
|
|
97
|
-
agent result
|
|
107
|
+
agent result or attention resumes the controller
|
|
98
108
|
↓
|
|
99
|
-
|
|
109
|
+
controller integrates and reassesses
|
|
100
110
|
```
|
|
101
111
|
|
|
112
|
+
Parallelism is optional. Do not create additional assignments or local side work
|
|
113
|
+
merely to keep the controller active. For the full turn-navigation model, see
|
|
114
|
+
[Asynchronous orchestration](lifecycle.md#asynchronous-orchestration).
|
|
115
|
+
|
|
102
116
|
## Clarification across ownership edges
|
|
103
117
|
|
|
104
118
|
An agent may ask its exact direct owner through `ask_owner`.
|
|
@@ -77,26 +77,49 @@ restart recovery. The agent then runs independently in its managed Pi session
|
|
|
77
77
|
while the owner remains available for other useful work and, for a lead Pi
|
|
78
78
|
session, continued user interaction.
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
Each active delegated assignment has one executor: that agent. The owner retains
|
|
81
|
+
lifecycle and control authority but does not repeat the delegated assignment
|
|
82
|
+
locally or assign substantially overlapping work elsewhere.
|
|
83
|
+
|
|
84
|
+
After starting an agent assignment or receiving an agent result or attention
|
|
85
|
+
event, the owner reassesses the remaining work:
|
|
86
|
+
|
|
87
|
+
1. Handle required agent control when needed.
|
|
88
|
+
2. Delegate another concrete, necessary objective when it is independent of
|
|
89
|
+
active assignments and an authorized agent is the right owner.
|
|
90
|
+
3. Continue concrete, necessary independent work locally when the owner is the
|
|
91
|
+
right owner and doing it now materially advances the task.
|
|
92
|
+
4. Otherwise end the turn.
|
|
93
|
+
|
|
94
|
+
After control, delegation, or local parallel work, the owner reassesses again.
|
|
95
|
+
Once further useful progress depends on active agents, or no other concrete,
|
|
96
|
+
necessary independent work remains, it ends the turn. Agent results,
|
|
97
|
+
clarifications, and recovery attention resume the session automatically.
|
|
98
|
+
|
|
99
|
+
The owner does not invent side work merely because agents are running. It does
|
|
100
|
+
not poll, sleep, inspect merely for progress, send status steering, or use
|
|
101
|
+
another mechanism to keep the turn alive.
|
|
84
102
|
|
|
85
103
|
Conceptually:
|
|
86
104
|
|
|
87
105
|
```text
|
|
88
|
-
assignment
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
106
|
+
assignment or agent event
|
|
107
|
+
↓
|
|
108
|
+
reassess remaining work
|
|
109
|
+
↙ ↓ ↘
|
|
110
|
+
control parallel no useful
|
|
111
|
+
work action
|
|
112
|
+
↙ ↘ ↓
|
|
113
|
+
delegate local end turn
|
|
114
|
+
\ / ↓
|
|
115
|
+
reassess agent event resumes
|
|
95
116
|
```
|
|
96
117
|
|
|
97
|
-
This is asynchronous but not fire-and-forget. The owner retains
|
|
98
|
-
|
|
99
|
-
requests, and remains responsible for
|
|
118
|
+
This is asynchronous but not fire-and-forget. The owner retains lifecycle and
|
|
119
|
+
control authority: it can steer eligible active work when the assignment
|
|
120
|
+
actually changes, receives clarification requests, and remains responsible for
|
|
121
|
+
result delivery and cleanup. The delegated agent remains the executor of its
|
|
122
|
+
active assignment.
|
|
100
123
|
|
|
101
124
|
## Exactly-once assignment result
|
|
102
125
|
|
|
@@ -155,25 +155,42 @@ Verify:
|
|
|
155
155
|
6. agent produces exactly one final result;
|
|
156
156
|
7. no agent/mailbox leak remains.
|
|
157
157
|
|
|
158
|
-
## Delegating-agent
|
|
158
|
+
## Delegating-agent turn ending
|
|
159
159
|
|
|
160
|
-
Ask a
|
|
161
|
-
|
|
160
|
+
Ask a delegation-enabled controller to delegate required reconnaissance when no
|
|
161
|
+
other concrete, necessary independent work is known.
|
|
162
162
|
|
|
163
163
|
Inspect the actual transcript and verify the delegating agent:
|
|
164
164
|
|
|
165
|
-
- ends its turn
|
|
165
|
+
- ends its turn after the assignment when nothing else useful is independently actionable;
|
|
166
|
+
- does not repeat the delegated reconnaissance locally;
|
|
167
|
+
- does not manufacture adjacent analysis merely to remain active;
|
|
168
|
+
- does not delegate substantially overlapping reconnaissance to another agent;
|
|
166
169
|
- does not poll `agent list`;
|
|
167
|
-
- does not
|
|
168
|
-
-
|
|
170
|
+
- does not use `agent inspect` or `agent steer` merely to check progress;
|
|
171
|
+
- does not send "finish", "status", or equivalent progress nudges to a healthy
|
|
172
|
+
agent;
|
|
173
|
+
- does not sleep or use another mechanism to keep the turn alive;
|
|
174
|
+
- the agent result resumes the controller session;
|
|
169
175
|
- integrates the result into one final delegating agent outcome.
|
|
170
176
|
|
|
171
177
|
## Useful concurrency
|
|
172
178
|
|
|
173
|
-
|
|
179
|
+
Delegate bounded task A and give the controller concrete, necessary independent
|
|
180
|
+
local task B.
|
|
174
181
|
|
|
175
|
-
Verify
|
|
176
|
-
|
|
182
|
+
Verify:
|
|
183
|
+
|
|
184
|
+
- B proceeds while A is active;
|
|
185
|
+
- B does not repeat A's assigned scope;
|
|
186
|
+
- once B is sufficiently complete, the controller reassesses instead of
|
|
187
|
+
manufacturing more work;
|
|
188
|
+
- if further useful progress depends on A, the controller ends its turn;
|
|
189
|
+
- A's result resumes the controller and is integrated.
|
|
190
|
+
|
|
191
|
+
Also verify a controller with two already-known independent delegated objectives
|
|
192
|
+
may delegate A and B before ending its turn. It must not create a third
|
|
193
|
+
assignment merely to increase concurrency.
|
|
177
194
|
|
|
178
195
|
## Lead `/agents` commands
|
|
179
196
|
|
package/package.json
CHANGED