agentix-cli 0.54.0 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/mac-voice/Sources/AgentXVoice/AgentClient.swift +26 -0
- package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +55 -3
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +136 -13
- package/dist/{App-VRTLAPRF.js → App-4EM7IPB3.js} +2 -2
- package/dist/{ChatApp-YENWPZT4.js → ChatApp-FYTEEGSU.js} +2 -2
- package/dist/{agent-HVUGHYBF.js → agent-RZ46ZB4W.js} +2 -2
- package/dist/{board-dashboard-3XJVYDB3.js → board-dashboard-NRRYCDZW.js} +826 -180
- package/dist/board-dashboard-NRRYCDZW.js.map +1 -0
- package/dist/{chunk-M67AN4J7.js → chunk-4HEVSWO3.js} +2 -2
- package/dist/{chunk-KLDGJSR5.js → chunk-6AK6WKE5.js} +2 -2
- package/dist/{chunk-ENRJ2QEH.js → chunk-723K4SAW.js} +2 -2
- package/dist/{chunk-UYMK3XNB.js → chunk-76AHNHWC.js} +2 -2
- package/dist/{chunk-XWU7O3S5.js → chunk-C3VRBEJ7.js} +2 -2
- package/dist/{chunk-HQMISQ7L.js → chunk-CELYD5QW.js} +2 -2
- package/dist/{chunk-33QV5O6P.js → chunk-D3LSPFHK.js} +2 -2
- package/dist/chunk-EJ5ISSWW.js +151 -0
- package/dist/chunk-EJ5ISSWW.js.map +1 -0
- package/dist/{chunk-4HNHHKJF.js → chunk-EZN2YXRY.js} +2 -2
- package/dist/{chunk-BKDUCPZ3.js → chunk-GSOL2LW6.js} +2 -2
- package/dist/{chunk-TLFJVLVQ.js → chunk-JC5Q5MPI.js} +152 -151
- package/dist/chunk-JC5Q5MPI.js.map +1 -0
- package/dist/{chunk-6JHA3ZE6.js → chunk-K4RDE6YU.js} +211 -197
- package/dist/chunk-K4RDE6YU.js.map +1 -0
- package/dist/{chunk-WLRHL2P7.js → chunk-LKJSPO3S.js} +2 -2
- package/dist/{chunk-37EABIOJ.js → chunk-M4AG2YNX.js} +2 -2
- package/dist/{chunk-ZOJUHPD5.js → chunk-O3XG2NVR.js} +18 -18
- package/dist/{chunk-ZOJUHPD5.js.map → chunk-O3XG2NVR.js.map} +1 -1
- package/dist/{chunk-QYHABRLM.js → chunk-SA23V7WX.js} +2 -2
- package/dist/chunk-U4H35SJS.js +15 -0
- package/dist/chunk-U4H35SJS.js.map +1 -0
- package/dist/{chunk-3RCFUIYR.js → chunk-UIVHSYCN.js} +9 -9
- package/dist/chunk-UIVHSYCN.js.map +1 -0
- package/dist/{chunk-3W2KMI5O.js → chunk-W4YMMWJL.js} +2 -2
- package/dist/chunk-WOMQ2VGA.js +5 -0
- package/dist/{chunk-QX4R5WY7.js.map → chunk-WOMQ2VGA.js.map} +1 -1
- package/dist/chunk-X5C5W3E4.js +3 -0
- package/dist/chunk-X5C5W3E4.js.map +1 -0
- package/dist/{chunk-2TJYZF4E.js → chunk-XEOAKD5C.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-IA7ZPE56.js +2 -0
- package/dist/config-HPN2F7LH.js +2 -0
- package/dist/config-mutator-7GPTMTVB.js +2 -0
- package/dist/doctor-IBWQVQV4.js +2 -0
- package/dist/index.d.ts +185 -19
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/program-D5TAPSIH.js +2 -0
- package/dist/{promote-H6ZHJXTY.js → promote-T4UJROEH.js} +2 -2
- package/dist/query-VUJC4Y5O.js +2 -0
- package/dist/registry-DX2RI7I7.js +2 -0
- package/dist/{request-planner-ABD4WIGM.js → request-planner-B7DE7VJR.js} +2 -2
- package/dist/{review-candidates-B6574GOJ.js → review-candidates-4YJHIBAF.js} +2 -2
- package/dist/routing-MZG3UODH.js +2 -0
- package/dist/schedule-tool-A4OFQ4YZ.js +2 -0
- package/dist/scheduler-RHJW2V4M.js +2 -0
- package/dist/seat-2PEI7JRX.js +2 -0
- package/dist/{select-Y7SBUCGJ.js → select-4KIUR27O.js} +2 -2
- package/dist/{set-enabled-ARKMDLXN.js → set-enabled-SE7HQKPF.js} +2 -2
- package/dist/subscriptions-RYVPHVIV.js +2 -0
- package/dist/{tool-5EVYUN2G.js → tool-5VMD7IE4.js} +2 -2
- package/dist/wiki-2QFLAH4U.js +2 -0
- package/dist/wiki-2QFLAH4U.js.map +1 -0
- package/package.json +1 -1
- package/dist/board-dashboard-3XJVYDB3.js.map +0 -1
- package/dist/chunk-3RCFUIYR.js.map +0 -1
- package/dist/chunk-4FFWNPFX.js +0 -15
- package/dist/chunk-4FFWNPFX.js.map +0 -1
- package/dist/chunk-6JHA3ZE6.js.map +0 -1
- package/dist/chunk-BMSPRUEJ.js +0 -150
- package/dist/chunk-BMSPRUEJ.js.map +0 -1
- package/dist/chunk-QX4R5WY7.js +0 -5
- package/dist/chunk-TLFJVLVQ.js.map +0 -1
- package/dist/client-N4XQEAVL.js +0 -2
- package/dist/config-KHKIY6LI.js +0 -2
- package/dist/config-mutator-ZZKFQ7HJ.js +0 -2
- package/dist/doctor-QICAXIQB.js +0 -2
- package/dist/program-ZWNGK3RB.js +0 -2
- package/dist/query-FTE4FLYK.js +0 -2
- package/dist/registry-HDOFVNRK.js +0 -2
- package/dist/routing-BGKZOHOA.js +0 -2
- package/dist/schedule-tool-UDHXTKWV.js +0 -2
- package/dist/scheduler-NQM3HVUY.js +0 -2
- package/dist/seat-VGST5AQB.js +0 -2
- package/dist/wiki-GREI2TSP.js +0 -2
- /package/dist/{App-VRTLAPRF.js.map → App-4EM7IPB3.js.map} +0 -0
- /package/dist/{ChatApp-YENWPZT4.js.map → ChatApp-FYTEEGSU.js.map} +0 -0
- /package/dist/{agent-HVUGHYBF.js.map → agent-RZ46ZB4W.js.map} +0 -0
- /package/dist/{chunk-M67AN4J7.js.map → chunk-4HEVSWO3.js.map} +0 -0
- /package/dist/{chunk-KLDGJSR5.js.map → chunk-6AK6WKE5.js.map} +0 -0
- /package/dist/{chunk-ENRJ2QEH.js.map → chunk-723K4SAW.js.map} +0 -0
- /package/dist/{chunk-UYMK3XNB.js.map → chunk-76AHNHWC.js.map} +0 -0
- /package/dist/{chunk-XWU7O3S5.js.map → chunk-C3VRBEJ7.js.map} +0 -0
- /package/dist/{chunk-HQMISQ7L.js.map → chunk-CELYD5QW.js.map} +0 -0
- /package/dist/{chunk-33QV5O6P.js.map → chunk-D3LSPFHK.js.map} +0 -0
- /package/dist/{chunk-4HNHHKJF.js.map → chunk-EZN2YXRY.js.map} +0 -0
- /package/dist/{chunk-BKDUCPZ3.js.map → chunk-GSOL2LW6.js.map} +0 -0
- /package/dist/{chunk-WLRHL2P7.js.map → chunk-LKJSPO3S.js.map} +0 -0
- /package/dist/{chunk-37EABIOJ.js.map → chunk-M4AG2YNX.js.map} +0 -0
- /package/dist/{chunk-QYHABRLM.js.map → chunk-SA23V7WX.js.map} +0 -0
- /package/dist/{chunk-3W2KMI5O.js.map → chunk-W4YMMWJL.js.map} +0 -0
- /package/dist/{chunk-2TJYZF4E.js.map → chunk-XEOAKD5C.js.map} +0 -0
- /package/dist/{client-N4XQEAVL.js.map → client-IA7ZPE56.js.map} +0 -0
- /package/dist/{config-KHKIY6LI.js.map → config-HPN2F7LH.js.map} +0 -0
- /package/dist/{config-mutator-ZZKFQ7HJ.js.map → config-mutator-7GPTMTVB.js.map} +0 -0
- /package/dist/{doctor-QICAXIQB.js.map → doctor-IBWQVQV4.js.map} +0 -0
- /package/dist/{program-ZWNGK3RB.js.map → program-D5TAPSIH.js.map} +0 -0
- /package/dist/{promote-H6ZHJXTY.js.map → promote-T4UJROEH.js.map} +0 -0
- /package/dist/{query-FTE4FLYK.js.map → query-VUJC4Y5O.js.map} +0 -0
- /package/dist/{registry-HDOFVNRK.js.map → registry-DX2RI7I7.js.map} +0 -0
- /package/dist/{request-planner-ABD4WIGM.js.map → request-planner-B7DE7VJR.js.map} +0 -0
- /package/dist/{review-candidates-B6574GOJ.js.map → review-candidates-4YJHIBAF.js.map} +0 -0
- /package/dist/{routing-BGKZOHOA.js.map → routing-MZG3UODH.js.map} +0 -0
- /package/dist/{schedule-tool-UDHXTKWV.js.map → schedule-tool-A4OFQ4YZ.js.map} +0 -0
- /package/dist/{scheduler-NQM3HVUY.js.map → scheduler-RHJW2V4M.js.map} +0 -0
- /package/dist/{seat-VGST5AQB.js.map → seat-2PEI7JRX.js.map} +0 -0
- /package/dist/{select-Y7SBUCGJ.js.map → select-4KIUR27O.js.map} +0 -0
- /package/dist/{set-enabled-ARKMDLXN.js.map → set-enabled-SE7HQKPF.js.map} +0 -0
- /package/dist/{wiki-GREI2TSP.js.map → subscriptions-RYVPHVIV.js.map} +0 -0
- /package/dist/{tool-5EVYUN2G.js.map → tool-5VMD7IE4.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{q as _,r as W}from"./chunk-2AXFYDWF.js";import{b as Y,c as I,d as O}from"./chunk-AQASR6KR.js";import{b as F}from"./chunk-DP7RTNDM.js";import{e as E}from"./chunk-
|
|
1
|
+
import{q as _,r as W}from"./chunk-2AXFYDWF.js";import{b as Y,c as I,d as O}from"./chunk-AQASR6KR.js";import{b as F}from"./chunk-DP7RTNDM.js";import{e as E}from"./chunk-C3VRBEJ7.js";import{b as L}from"./chunk-64P4QHSZ.js";import{createHash as ee}from"crypto";import{existsSync as H,readdirSync as te,readFileSync as re,writeFileSync as ne}from"fs";import{resolve as P}from"path";function be(n,r,s,t,o,i,c=""){return Z(r,s,t,o,i,c)}function Z(n,r,s,t,o,i=""){let c=r?`
|
|
2
2
|
## Worldview
|
|
3
3
|
|
|
4
4
|
${r}
|
|
@@ -240,4 +240,4 @@ ${g}`}var x="memory-promoter",oe=["project","reference","feedback"],K="_memory-p
|
|
|
240
240
|
Re-emit the FULL corrected JSON object \u2014 same structure, fixed issues, valid JSON only.`:n,y=await t(`${a}/task`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent:r.viaAgent,message:h,freshSession:s===null,context:{channel:"api",chatId:r.chatId??"memory-promote"}}),signal:i.signal});if(!y.ok){let f=await y.text().catch(()=>"");throw new Error(`agent /task ${y.status}: ${f.slice(0,500)}`)}let w=await y.json();if(w.error)throw new Error(`agent reported error: ${w.error}`);let b=String(w.content??"").trim();if(!b)throw new Error("agent returned empty content");return b}if(!r.model)throw new Error("callPromotionLlm: viaAgent or model is required");let p=process.env.ANTHROPIC_API_KEY;if(!p)throw new Error("ANTHROPIC_API_KEY not set; use --via <agentId> instead");let u=[{role:"user",content:n}];s&&(u.push({role:"assistant",content:"(previous attempt; will retry with corrections)"}),u.push({role:"user",content:`Your previous response failed validation: ${s}
|
|
241
241
|
Re-emit the FULL corrected JSON object.`}));let g=await t(me,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":p,"anthropic-version":ge},body:JSON.stringify({model:r.model,max_tokens:8e3,messages:u}),signal:i.signal});if(!g.ok){let a=await g.text().catch(()=>"");throw new Error(`anthropic API ${g.status}: ${a.slice(0,500)}`)}let l=await g.json(),e=(Array.isArray(l.content)?l.content:[]).filter(a=>a?.type==="text").map(a=>a.text).join(`
|
|
242
242
|
`).trim();if(!e)throw new Error("anthropic API returned no text content");return e}finally{clearTimeout(c)}}async function Se(n={}){let r=n.wikiDir??P(process.cwd(),".agentx","wiki"),s=n.memoryRoot??P(process.cwd(),".agentx"),t=n.log??(()=>{}),o=n.now??Date.now(),i={candidates:[],clusters:[],proposed:[],skipped:[],gaps:[],warnings:[],errors:[],dryRun:!n.commit},c=new E(r,(...m)=>t(m.map(String).join(" "))),p=c.rebuildIndex(),u=z(r),g=[...ce(s),...n.extraCandidates??[]];if(i.candidates=de(g,p,u,{types:n.types,sinceMs:n.sinceMs,agentFilter:n.agentFilter,now:o,max:n.max}),i.candidates.length===0)return t("no unpromoted memories in window"),i;if(i.clusters=le(i.candidates),i.dryRun)return i;let l=p.articles.map(m=>({title:m.title,path:m.path,type:m.type})),d=c.getWorldview()??"",e=n.budgetTokens??ue,a=i.clusters,h=D(x,a,l,d);for(;R(h)>e&&a.length>1;)a=a.slice(0,-1),h=D(x,a,l,d);if(R(h)>e)return i.errors.push(`judge prompt (~${R(h)} tokens) exceeds the ${e}-token budget even with one cluster`),i;a.length<i.clusters.length&&i.warnings.push(`token budget: judged ${a.length} of ${i.clusters.length} clusters; the rest wait for the next run`);let y=a.flatMap(m=>m.candidates),w=new Set(y.map(m=>m.stamp)),b=n.chatId??`memory-promote-${new Date(o).toISOString().slice(0,10)}`,f=B(await G(h,{...n,chatId:b}),w);if("error"in f&&(t(`parse failed (${f.error}) \u2014 retrying with feedback`),f=B(await G(h,{...n,chatId:b},f.error),w)),"error"in f)return i.errors.push(`LLM response unusable after retry: ${f.error}`),i;i.warnings.push(...f.warnings),i.gaps=f.gaps;let v=new Date(o).toISOString(),k=[],T=new Map(y.map(m=>[m.stamp,m]));for(let m of f.articles){let A=c.readArticle(m.path);if(A&&!c.canWrite(A.meta,x)){i.errors.push(`write denied for "${m.path}" (owned by ${A.meta.owner??"?"})`);continue}let M=fe(m.promotedFrom,T),S={id:Y(o,m.path),createdAt:v,status:"pending",article:m,evidence:M,...A?{replaces:{lastUpdated:A.meta.lastUpdated,contentHash:V(A.content)}}:{}};I(r,S),i.proposed.push({id:S.id,path:m.path,title:m.title,type:m.type,stamps:m.promotedFrom,agents:M.agents,occurrences:M.occurrences});for(let X of m.promotedFrom)k.push({stamp:X,decision:"proposed",article:m.path,proposal:S.id,at:v})}for(let m of f.skipped)k.push({stamp:m.stamp,decision:"skipped",reason:m.reason,at:v}),i.skipped.push(m);return k.length&&C(r,k),i}var ue=6e4;function R(n){return Math.ceil(n.length/4)}function V(n){return ee("sha256").update(n).digest("hex").slice(0,16)}var he=600;function ye(n){return n.startsWith("review:")?"review":n.startsWith(j)?"failure":"memory"}function fe(n,r){let s=[];for(let t of n){let o=r.get(t);o&&s.push({stamp:t,kind:ye(t),agentId:o.agentId,type:o.memory.type,name:o.memory.name,description:o.memory.description,...o.occurrences?{occurrences:o.occurrences}:{},...o.sessions?.length?{sessions:o.sessions}:{},...o.tasks?.length?{tasks:o.tasks}:{},...o.failure?{failure:o.failure}:{},...o.memory.author?{author:o.memory.author}:{},...o.memory.taskId?{taskId:o.memory.taskId}:{},updatedAt:o.memory.updatedAt,excerpt:o.memory.body.slice(0,he)})}return{agents:[...new Set(s.map(t=>t.agentId))].sort(),occurrences:Math.max(1,...s.map(t=>t.occurrences??1)),sources:s}}function Ee(n,r,s={}){let t=O(n,r);if(!t)return{ok:!1,error:`no proposal "${r}"`};if(t.status!=="pending")return{ok:!1,error:`proposal "${r}" is already ${t.status}`};let o=s.log??(()=>{}),i=new E(n,(...a)=>o(a.map(String).join(" "))),{article:c}=t,p=i.readArticle(c.path);if(!s.force){if(p&&!t.replaces)return{ok:!1,error:`"${c.path}" was created after this proposal; review it, then approve with --force`};if(p&&t.replaces&&V(p.content)!==t.replaces.contentHash)return{ok:!1,error:`"${c.path}" changed since this proposal; review it, then approve with --force`}}let u=s.now??Date.now(),g=new Date(u).toISOString().slice(0,10);if(!i.writeArticle(c.path,{title:c.title,type:L(c.type)?c.type:void 0,related:c.related,tags:c.tags,owner:x,access:"public",created:p?.meta.created??g,lastUpdated:g,sources:ae(p?.meta.sources,c.promotedFrom)},c.content,x))return{ok:!1,error:`write denied for "${c.path}" (owned by ${p?.meta.owner??"?"})`};let d=new Date(u).toISOString();C(n,c.promotedFrom.map(a=>({stamp:a,decision:"promoted",article:c.path,proposal:r,at:d}))),i.rebuildIndex();let e={...t,status:"approved",decidedBy:s.by??"operator",decidedAt:d};return I(n,e),{ok:!0,proposal:e}}function Oe(n,r,s={}){let t=O(n,r);if(!t)return{ok:!1,error:`no proposal "${r}"`};if(t.status!=="pending")return{ok:!1,error:`proposal "${r}" is already ${t.status}`};let o=new Date(s.now??Date.now()).toISOString();C(n,t.article.promotedFrom.map(c=>({stamp:c,decision:"rejected",article:t.article.path,proposal:r,reason:s.reason,at:o})));let i={...t,status:"rejected",decidedBy:s.by??"operator",decidedAt:o,...s.reason?{reason:s.reason}:{}};return I(n,i),{ok:!0,proposal:i}}export{be as a,x as b,oe as c,K as d,q as e,ie as f,$ as g,ae as h,ce as i,z as j,C as k,le as l,B as m,de as n,G as o,Se as p,R as q,ye as r,fe as s,Ee as t,Oe as u};
|
|
243
|
-
//# sourceMappingURL=chunk-
|
|
243
|
+
//# sourceMappingURL=chunk-W4YMMWJL.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{n as m,q as b}from"./chunk-U4H35SJS.js";b();function w(t){let e=typeof t.node=="string"?t.node:"",n=typeof t.token=="string"?t.token:"";if(!e||!n)try{let o=m(t.config);e||(e=o.dashboard?.daemonUrl||""),n||(n=o.dashboard?.token||"")}catch{}return e||(e="http://localhost:18800"),{baseUrl:e.replace(/\/+$/,""),token:n}}async function d(t,e,n){let o={Accept:"application/json"};t.token&&(o.Authorization=`Bearer ${t.token}`);let r=await fetch(`${t.baseUrl}${e}`,{headers:o,signal:n});if(!r.ok)throw new Error(`GET ${e} \u2192 HTTP ${r.status}`);return await r.json()}function R(t,e){return d(t,"/agents",e)}async function S(t,e){return(await d(t,"/api/processes",e)).processes??[]}function P(t,e){return d(t,"/crons",e)}async function h(t,e,n,o){let r={Accept:"application/json","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}${e}`,{method:"POST",headers:r,body:JSON.stringify(n),signal:o}),a=await s.text(),i;try{i=a?JSON.parse(a):{}}catch{i={raw:a}}if(!s.ok)throw new Error(i?.error||`POST ${e} \u2192 HTTP ${s.status}`);return i}function A(t,e,n="tui"){return h(t,"/api/processes/kill",{...e,reason:n})}function C(t,e,n,o){return h(t,"/task",{agent:e,message:n,context:o??{channel:"tui",chatId:"tui:operator"}})}async function $(t,e,n,o={}){let r={Accept:"text/event-stream","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}/task`,{method:"POST",headers:r,body:JSON.stringify({agent:e,message:n,stream:!0,context:{channel:o.channel??"chat-cli",chatId:o.chatId??"chat-cli:operator"}}),signal:o.signal});if(!s.ok||!s.body){let g=await s.text().catch(()=>"");throw new Error(`POST /task (stream) \u2192 HTTP ${s.status}${g?`: ${g.slice(0,200)}`:""}`)}let a=s.body.getReader(),i=new TextDecoder,u={content:""},c="";try{for(;;){let{done:g,value:p}=await a.read();if(g)break;c+=i.decode(p,{stream:!0});let l;for(;(l=c.indexOf(`
|
|
2
|
+
|
|
3
|
+
`))>=0;){let k=c.slice(0,l);c=c.slice(l+2);let f=x(k);f&&T(f,o,u)}}}finally{try{a.releaseLock()}catch{}}return u}function T(t,e,n){let{event:o,data:r}=t;switch(o){case"text":r?.text&&(n.content+=r.text,e.onText?.(r.text));break;case"thinking":r?.text&&e.onThinking?.(r.text);break;case"tool":e.onTool?.(r);break;case"done":typeof r?.content=="string"&&(n.content=r.content),n.usage=r?.usage,n.duration=r?.duration;break;case"error":n.error=r?.error,n.errorKind=r?.errorKind;break}}function x(t){let e="message",n="";for(let r of t.split(`
|
|
4
|
+
`))r.startsWith("event: ")?e=r.slice(7).trim():r.startsWith("data: ")&&(n=r.slice(6));if(!n)return null;let o;try{o=JSON.parse(n)}catch{o=n}return{event:e,data:o}}export{w as a,R as b,S as c,P as d,A as e,C as f,$ as g};
|
|
5
|
+
//# sourceMappingURL=chunk-WOMQ2VGA.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/tui/client.ts"],"sourcesContent":["import { loadDaemonConfig } from \"@/daemon/config\"\n\n// Resolved connection details for the daemon, derived from --node/--token\n// CLI flags first, then daemon config's `dashboard` block, then localhost.\nexport interface DaemonConn {\n baseUrl: string\n token: string\n}\n\nexport function resolveConn(opts: { node?: string; token?: string; config?: string }): DaemonConn {\n let baseUrl = typeof opts.node === \"string\" ? opts.node : \"\"\n let token = typeof opts.token === \"string\" ? opts.token : \"\"\n if (!baseUrl || !token) {\n try {\n const cfg = loadDaemonConfig(opts.config)\n if (!baseUrl) baseUrl = cfg.dashboard?.daemonUrl || \"\"\n if (!token) token = cfg.dashboard?.token || \"\"\n } catch {\n // No config — fall back to localhost.\n }\n }\n if (!baseUrl) baseUrl = \"http://localhost:18800\"\n return { baseUrl: baseUrl.replace(/\\/+$/, \"\"), token }\n}\n\nasync function get<T>(conn: DaemonConn, path: string, signal?: AbortSignal): Promise<T> {\n const headers: Record<string, string> = { Accept: \"application/json\" }\n if (conn.token) headers[\"Authorization\"] = `Bearer ${conn.token}`\n const res = await fetch(`${conn.baseUrl}${path}`, { headers, signal })\n if (!res.ok) throw new Error(`GET ${path} → HTTP ${res.status}`)\n return (await res.json()) as T\n}\n\nexport interface AgentRow {\n id: string\n name: string\n tier: string\n model?: string\n workspace: string\n active: number\n total: number\n errors: number\n lastActive?: string\n}\n\nexport interface ProcessRow {\n key: { agentId: string; channel: string; chatId: string }\n pid: number | null\n state: string\n spawnedAt: number\n lastTurnAt: number\n turnCount: number\n}\n\nexport interface CronRow {\n id: string\n enabled: boolean\n schedule: string\n agent: string\n nextRun?: string\n lastError?: string\n consecutiveErrors: number\n}\n\nexport function fetchAgents(conn: DaemonConn, signal?: AbortSignal): Promise<AgentRow[]> {\n return get<AgentRow[]>(conn, \"/agents\", signal)\n}\n\nexport async function fetchProcesses(conn: DaemonConn, signal?: AbortSignal): Promise<ProcessRow[]> {\n const r = await get<{ processes: ProcessRow[] }>(conn, \"/api/processes\", signal)\n return r.processes ?? []\n}\n\nexport function fetchCrons(conn: DaemonConn, signal?: AbortSignal): Promise<CronRow[]> {\n return get<CronRow[]>(conn, \"/crons\", signal)\n}\n\nasync function post<T>(conn: DaemonConn, path: string, body: any, signal?: AbortSignal): Promise<T> {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n }\n if (conn.token) headers[\"Authorization\"] = `Bearer ${conn.token}`\n const res = await fetch(`${conn.baseUrl}${path}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal,\n })\n const text = await res.text()\n let parsed: any\n try { parsed = text ? JSON.parse(text) : {} } catch { parsed = { raw: text } }\n if (!res.ok) throw new Error(parsed?.error || `POST ${path} → HTTP ${res.status}`)\n return parsed as T\n}\n\nexport function killProcess(\n conn: DaemonConn,\n key: { agentId: string; channel: string; chatId: string },\n reason = \"tui\",\n): Promise<{ killed: { agentId: string; channel: string; chatId: string } }> {\n return post(conn, \"/api/processes/kill\", { ...key, reason })\n}\n\nexport interface TaskResponse {\n content?: string\n error?: string\n [k: string]: any\n}\n\nexport function sendTask(\n conn: DaemonConn,\n agentId: string,\n message: string,\n context?: { channel?: string; chatId?: string },\n): Promise<TaskResponse> {\n return post<TaskResponse>(conn, \"/task\", {\n agent: agentId,\n message,\n context: context ?? { channel: \"tui\", chatId: \"tui:operator\" },\n })\n}\n\n/** Live task events surfaced to a streaming client. Mirrors the daemon's\n * `POST /task` SSE wire (src/daemon/index.ts): `text` deltas, `thinking`\n * deltas, and `tool` badges (start/result). */\nexport interface StreamTaskHandlers {\n onText?: (text: string) => void\n onThinking?: (text: string) => void\n onTool?: (t: { status: \"start\" | \"result\"; id?: string; name?: string; error?: boolean; arg?: string }) => void\n}\n\nexport interface StreamTaskResult {\n content: string\n usage?: Record<string, number>\n duration?: number\n error?: string\n errorKind?: string\n}\n\n/**\n * Stream a task turn over SSE. POSTs `/task` with `Accept: text/event-stream`,\n * parses `event:/data:` frames, and invokes the handlers as tokens and tool\n * events arrive. Resolves with the final `done` payload (or an `error`).\n * Reuses the same (channel, chatId) warm-process semantics as sendTask.\n */\nexport async function streamTask(\n conn: DaemonConn,\n agentId: string,\n message: string,\n opts: { channel?: string; chatId?: string; signal?: AbortSignal } & StreamTaskHandlers = {},\n): Promise<StreamTaskResult> {\n const headers: Record<string, string> = {\n Accept: \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n }\n if (conn.token) headers[\"Authorization\"] = `Bearer ${conn.token}`\n\n const res = await fetch(`${conn.baseUrl}/task`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n agent: agentId,\n message,\n stream: true,\n context: { channel: opts.channel ?? \"chat-cli\", chatId: opts.chatId ?? \"chat-cli:operator\" },\n }),\n signal: opts.signal,\n })\n if (!res.ok || !res.body) {\n const body = await res.text().catch(() => \"\")\n throw new Error(`POST /task (stream) → HTTP ${res.status}${body ? `: ${body.slice(0, 200)}` : \"\"}`)\n }\n\n const reader = res.body.getReader()\n const dec = new TextDecoder()\n const result: StreamTaskResult = { content: \"\" }\n let buf = \"\"\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buf += dec.decode(value, { stream: true })\n let idx: number\n while ((idx = buf.indexOf(\"\\n\\n\")) >= 0) {\n const frame = buf.slice(0, idx)\n buf = buf.slice(idx + 2)\n const parsed = parseSseFrame(frame)\n if (!parsed) continue\n applyFrame(parsed, opts, result)\n }\n }\n } finally {\n try { reader.releaseLock() } catch { /* noop */ }\n }\n return result\n}\n\nfunction applyFrame(\n frame: { event: string; data: any },\n handlers: StreamTaskHandlers,\n result: StreamTaskResult,\n): void {\n const { event, data } = frame\n switch (event) {\n case \"text\":\n if (data?.text) { result.content += data.text; handlers.onText?.(data.text) }\n break\n case \"thinking\":\n if (data?.text) handlers.onThinking?.(data.text)\n break\n case \"tool\":\n handlers.onTool?.(data)\n break\n case \"done\":\n if (typeof data?.content === \"string\") result.content = data.content\n result.usage = data?.usage\n result.duration = data?.duration\n break\n case \"error\":\n result.error = data?.error\n result.errorKind = data?.errorKind\n break\n }\n}\n\n/** Parse one `event:/data:` SSE frame. Ignores comment/heartbeat lines. */\nfunction parseSseFrame(frame: string): { event: string; data: any } | null {\n let event = \"message\"\n let data = \"\"\n for (const line of frame.split(\"\\n\")) {\n if (line.startsWith(\"event: \")) event = line.slice(7).trim()\n else if (line.startsWith(\"data: \")) data = line.slice(6)\n }\n if (!data) return null\n let payload: any\n try { payload = JSON.parse(data) } catch { payload = data }\n return { event, data: payload }\n}\n"],"mappings":"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","names":["init_config","resolveConn","opts","baseUrl","token","cfg","loadDaemonConfig","get","conn","path","signal","headers","res","fetchAgents","fetchProcesses","fetchCrons","post","body","text","parsed","killProcess","key","reason","sendTask","agentId","message","context","streamTask","reader","dec","result","buf","done","value","idx","frame","parseSseFrame","applyFrame","handlers","event","data","line","payload"]}
|
|
1
|
+
{"version":3,"sources":["../src/tui/client.ts"],"sourcesContent":["import { loadDaemonConfig } from \"@/daemon/config\"\n\n// Resolved connection details for the daemon, derived from --node/--token\n// CLI flags first, then daemon config's `dashboard` block, then localhost.\nexport interface DaemonConn {\n baseUrl: string\n token: string\n}\n\nexport function resolveConn(opts: { node?: string; token?: string; config?: string }): DaemonConn {\n let baseUrl = typeof opts.node === \"string\" ? opts.node : \"\"\n let token = typeof opts.token === \"string\" ? opts.token : \"\"\n if (!baseUrl || !token) {\n try {\n const cfg = loadDaemonConfig(opts.config)\n if (!baseUrl) baseUrl = cfg.dashboard?.daemonUrl || \"\"\n if (!token) token = cfg.dashboard?.token || \"\"\n } catch {\n // No config — fall back to localhost.\n }\n }\n if (!baseUrl) baseUrl = \"http://localhost:18800\"\n return { baseUrl: baseUrl.replace(/\\/+$/, \"\"), token }\n}\n\nasync function get<T>(conn: DaemonConn, path: string, signal?: AbortSignal): Promise<T> {\n const headers: Record<string, string> = { Accept: \"application/json\" }\n if (conn.token) headers[\"Authorization\"] = `Bearer ${conn.token}`\n const res = await fetch(`${conn.baseUrl}${path}`, { headers, signal })\n if (!res.ok) throw new Error(`GET ${path} → HTTP ${res.status}`)\n return (await res.json()) as T\n}\n\nexport interface AgentRow {\n id: string\n name: string\n tier: string\n model?: string\n workspace: string\n active: number\n total: number\n errors: number\n lastActive?: string\n}\n\nexport interface ProcessRow {\n key: { agentId: string; channel: string; chatId: string }\n pid: number | null\n state: string\n spawnedAt: number\n lastTurnAt: number\n turnCount: number\n}\n\nexport interface CronRow {\n id: string\n enabled: boolean\n schedule: string\n agent: string\n nextRun?: string\n lastError?: string\n consecutiveErrors: number\n}\n\nexport function fetchAgents(conn: DaemonConn, signal?: AbortSignal): Promise<AgentRow[]> {\n return get<AgentRow[]>(conn, \"/agents\", signal)\n}\n\nexport async function fetchProcesses(conn: DaemonConn, signal?: AbortSignal): Promise<ProcessRow[]> {\n const r = await get<{ processes: ProcessRow[] }>(conn, \"/api/processes\", signal)\n return r.processes ?? []\n}\n\nexport function fetchCrons(conn: DaemonConn, signal?: AbortSignal): Promise<CronRow[]> {\n return get<CronRow[]>(conn, \"/crons\", signal)\n}\n\nasync function post<T>(conn: DaemonConn, path: string, body: any, signal?: AbortSignal): Promise<T> {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n }\n if (conn.token) headers[\"Authorization\"] = `Bearer ${conn.token}`\n const res = await fetch(`${conn.baseUrl}${path}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(body),\n signal,\n })\n const text = await res.text()\n let parsed: any\n try { parsed = text ? JSON.parse(text) : {} } catch { parsed = { raw: text } }\n if (!res.ok) throw new Error(parsed?.error || `POST ${path} → HTTP ${res.status}`)\n return parsed as T\n}\n\nexport function killProcess(\n conn: DaemonConn,\n key: { agentId: string; channel: string; chatId: string },\n reason = \"tui\",\n): Promise<{ killed: { agentId: string; channel: string; chatId: string } }> {\n return post(conn, \"/api/processes/kill\", { ...key, reason })\n}\n\nexport interface TaskResponse {\n content?: string\n error?: string\n [k: string]: any\n}\n\nexport function sendTask(\n conn: DaemonConn,\n agentId: string,\n message: string,\n context?: { channel?: string; chatId?: string },\n): Promise<TaskResponse> {\n return post<TaskResponse>(conn, \"/task\", {\n agent: agentId,\n message,\n context: context ?? { channel: \"tui\", chatId: \"tui:operator\" },\n })\n}\n\n/** Live task events surfaced to a streaming client. Mirrors the daemon's\n * `POST /task` SSE wire (src/daemon/index.ts): `text` deltas, `thinking`\n * deltas, and `tool` badges (start/result). */\nexport interface StreamTaskHandlers {\n onText?: (text: string) => void\n onThinking?: (text: string) => void\n onTool?: (t: { status: \"start\" | \"result\"; id?: string; name?: string; error?: boolean; arg?: string }) => void\n}\n\nexport interface StreamTaskResult {\n content: string\n usage?: Record<string, number>\n duration?: number\n error?: string\n errorKind?: string\n}\n\n/**\n * Stream a task turn over SSE. POSTs `/task` with `Accept: text/event-stream`,\n * parses `event:/data:` frames, and invokes the handlers as tokens and tool\n * events arrive. Resolves with the final `done` payload (or an `error`).\n * Reuses the same (channel, chatId) warm-process semantics as sendTask.\n */\nexport async function streamTask(\n conn: DaemonConn,\n agentId: string,\n message: string,\n opts: { channel?: string; chatId?: string; signal?: AbortSignal } & StreamTaskHandlers = {},\n): Promise<StreamTaskResult> {\n const headers: Record<string, string> = {\n Accept: \"text/event-stream\",\n \"Content-Type\": \"application/json\",\n }\n if (conn.token) headers[\"Authorization\"] = `Bearer ${conn.token}`\n\n const res = await fetch(`${conn.baseUrl}/task`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n agent: agentId,\n message,\n stream: true,\n context: { channel: opts.channel ?? \"chat-cli\", chatId: opts.chatId ?? \"chat-cli:operator\" },\n }),\n signal: opts.signal,\n })\n if (!res.ok || !res.body) {\n const body = await res.text().catch(() => \"\")\n throw new Error(`POST /task (stream) → HTTP ${res.status}${body ? `: ${body.slice(0, 200)}` : \"\"}`)\n }\n\n const reader = res.body.getReader()\n const dec = new TextDecoder()\n const result: StreamTaskResult = { content: \"\" }\n let buf = \"\"\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buf += dec.decode(value, { stream: true })\n let idx: number\n while ((idx = buf.indexOf(\"\\n\\n\")) >= 0) {\n const frame = buf.slice(0, idx)\n buf = buf.slice(idx + 2)\n const parsed = parseSseFrame(frame)\n if (!parsed) continue\n applyFrame(parsed, opts, result)\n }\n }\n } finally {\n try { reader.releaseLock() } catch { /* noop */ }\n }\n return result\n}\n\nfunction applyFrame(\n frame: { event: string; data: any },\n handlers: StreamTaskHandlers,\n result: StreamTaskResult,\n): void {\n const { event, data } = frame\n switch (event) {\n case \"text\":\n if (data?.text) { result.content += data.text; handlers.onText?.(data.text) }\n break\n case \"thinking\":\n if (data?.text) handlers.onThinking?.(data.text)\n break\n case \"tool\":\n handlers.onTool?.(data)\n break\n case \"done\":\n if (typeof data?.content === \"string\") result.content = data.content\n result.usage = data?.usage\n result.duration = data?.duration\n break\n case \"error\":\n result.error = data?.error\n result.errorKind = data?.errorKind\n break\n }\n}\n\n/** Parse one `event:/data:` SSE frame. Ignores comment/heartbeat lines. */\nfunction parseSseFrame(frame: string): { event: string; data: any } | null {\n let event = \"message\"\n let data = \"\"\n for (const line of frame.split(\"\\n\")) {\n if (line.startsWith(\"event: \")) event = line.slice(7).trim()\n else if (line.startsWith(\"data: \")) data = line.slice(6)\n }\n if (!data) return null\n let payload: any\n try { payload = JSON.parse(data) } catch { payload = data }\n return { event, data: payload }\n}\n"],"mappings":"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","names":["init_config","resolveConn","opts","baseUrl","token","cfg","loadDaemonConfig","get","conn","path","signal","headers","res","fetchAgents","fetchProcesses","fetchCrons","post","body","text","parsed","killProcess","key","reason","sendTask","agentId","message","context","streamTask","reader","dec","result","buf","done","value","idx","frame","parseSseFrame","applyFrame","handlers","event","data","line","payload"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
var m=50,v=20,g=10;function p(e,n,t){return n.agentId===t&&!e.agents?.includes(t)?!1:f(e,n)}function f(e,n){return!(!e.kinds.some(t=>t==="*"||t===n.kind||t===n.type)||e.agents?.length&&(!n.agentId||!e.agents.includes(n.agentId))||e.nodes?.length&&!e.nodes.includes(n.node)||e.match&&!n.summary.toLowerCase().includes(e.match.toLowerCase()))}function c(e,n){return e?.length?n==="pull"?e:e.filter(t=>(t.delivery??"pull")===n):[]}function E(e,n,t,i={}){let o=c(n,i.delivery??"pull");if(o.length===0)return[];let s=a(i.limit),l=t.filter(r=>o.some(u=>p(u,r,e)));return i.fromCursor?l.slice(0,s):l.slice(-s)}function a(e,n=20){return!e||!Number.isFinite(e)||e<1?n:Math.min(Math.floor(e),50)}function h(e,n,t){let i=c(n,"digest");if(i.length===0)return{shown:[],more:0};let o=0;for(let r=t.length-1;r>=0;r--)if(t[r].agentId===e&&t[r].type==="task:completed"){o=r+1;break}let s=t.slice(o).filter(r=>i.some(u=>p(u,r,e))),l=s.slice(-10);return{shown:l,more:s.length-l.length}}function d(e){let n=e.agentId?`${e.agentId}@${e.node}`:e.node,t=e.ref?` (ref ${e.ref})`:"";return`${e.at.slice(0,16).replace("T"," ")} ${e.type} ${n}: ${e.summary}${t}`}function y(e,n){return e.length===0?void 0:[`[Events since your last turn \u2014 ${e.length+n} matched your subscriptions${n?`, newest ${e.length} shown`:""}. Call agentx_events for details or newer ones:]`,...e.map(i=>`- ${d(i)}`)].join(`
|
|
2
|
+
`)}export{m as a,v as b,g as c,p as d,f as e,c as f,E as g,a as h,h as i,d as j,y as k};
|
|
3
|
+
//# sourceMappingURL=chunk-X5C5W3E4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/events/subscriptions.ts"],"sourcesContent":["import type { EventSubscription } from \"@/daemon/config\"\nimport type { EventEnvelope } from \"./envelope\"\n\n// --- Per-agent event subscriptions ---\n//\n// An agent lists the events it cares about in `agents.<id>.subscriptions`.\n// This module is the pure half: does an envelope match, which envelopes\n// does an agent get, and how a digest reads. Delivery lives elsewhere:\n// pull — GET /agents/:id/events, the agentx_events MCP tool and\n// `agentx events` read eventsForAgent()\n// digest — the registry injects renderDigest() into FRESH sessions only\n// wake — src/events/wake.ts starts a turn\n// Every answer is bounded: envelopes already cap their summary, and each\n// reader caps the count.\n\nexport type Delivery = EventSubscription[\"delivery\"]\n\n/** Most events one pull returns. */\nexport const PULL_MAX = 50\nexport const PULL_DEFAULT = 20\n/** Most events a fresh-session digest lists. */\nexport const DIGEST_MAX = 10\n\n/** Loose input shape: config output, or a hand-written object in tests. */\nexport type SubscriptionInput = Partial<EventSubscription> & { kinds: string[] }\n\n/** Does `e` match `sub` for `self`? An agent never matches its own events\n * unless the subscription names it in `agents` (and `wake` never does;\n * see wake.ts). */\nexport function matchesSubscription(sub: SubscriptionInput, e: EventEnvelope, self: string): boolean {\n if (e.agentId === self && !sub.agents?.includes(self)) return false\n return matchesFilters(sub, e)\n}\n\n/** The subscription's own filters, with no regard to who is asking. */\nexport function matchesFilters(sub: SubscriptionInput, e: EventEnvelope): boolean {\n if (!sub.kinds.some((k) => k === \"*\" || k === e.kind || k === e.type)) return false\n if (sub.agents?.length && (!e.agentId || !sub.agents.includes(e.agentId))) return false\n if (sub.nodes?.length && !sub.nodes.includes(e.node)) return false\n if (sub.match && !e.summary.toLowerCase().includes(sub.match.toLowerCase())) return false\n return true\n}\n\n/** Subscriptions of one delivery mode. `pull` reads every subscription:\n * digest and wake events can always be pulled too. */\nexport function subscriptionsFor(subs: SubscriptionInput[] | undefined, delivery: Delivery): SubscriptionInput[] {\n if (!subs?.length) return []\n return delivery === \"pull\" ? subs : subs.filter((s) => (s.delivery ?? \"pull\") === delivery)\n}\n\n/** Events from `events` (oldest first) that match any of `subs`. With no\n * cursor the newest `limit` are kept. When `events` was already read after\n * a cursor (`fromCursor`), the OLDEST `limit` are kept instead, so a reader\n * that passes the last returned id back as `since` pages through every\n * match without gaps. */\nexport function eventsForAgent(\n agentId: string,\n subs: SubscriptionInput[] | undefined,\n events: EventEnvelope[],\n opts: { delivery?: Delivery; limit?: number; fromCursor?: boolean } = {},\n): EventEnvelope[] {\n const active = subscriptionsFor(subs, opts.delivery ?? \"pull\")\n if (active.length === 0) return []\n const limit = clampLimit(opts.limit)\n const hits = events.filter((e) => active.some((s) => matchesSubscription(s, e, agentId)))\n return opts.fromCursor ? hits.slice(0, limit) : hits.slice(-limit)\n}\n\nexport function clampLimit(limit: number | undefined, fallback = PULL_DEFAULT): number {\n if (!limit || !Number.isFinite(limit) || limit < 1) return fallback\n return Math.min(Math.floor(limit), PULL_MAX)\n}\n\n/** The events a fresh session should hear about: digest subscriptions\n * matched since the agent's last finished turn (the whole buffer when it\n * has none), newest DIGEST_MAX. Returns the shown events and how many\n * more matched. */\nexport function digestEvents(\n agentId: string,\n subs: SubscriptionInput[] | undefined,\n events: EventEnvelope[],\n): { shown: EventEnvelope[]; more: number } {\n const active = subscriptionsFor(subs, \"digest\")\n if (active.length === 0) return { shown: [], more: 0 }\n let start = 0\n for (let i = events.length - 1; i >= 0; i--) {\n if (events[i].agentId === agentId && events[i].type === \"task:completed\") { start = i + 1; break }\n }\n const hits = events.slice(start).filter((e) => active.some((s) => matchesSubscription(s, e, agentId)))\n const shown = hits.slice(-DIGEST_MAX)\n return { shown, more: hits.length - shown.length }\n}\n\n/** One line per event: time, type, who and where, summary, ref. */\nexport function formatEventLine(e: EventEnvelope): string {\n const who = e.agentId ? `${e.agentId}@${e.node}` : e.node\n const ref = e.ref ? ` (ref ${e.ref})` : \"\"\n return `${e.at.slice(0, 16).replace(\"T\", \" \")} ${e.type} ${who}: ${e.summary}${ref}`\n}\n\n/** The context block for a fresh session, or undefined when nothing matched. */\nexport function renderDigest(shown: EventEnvelope[], more: number): string | undefined {\n if (shown.length === 0) return undefined\n const lines = [\n `[Events since your last turn — ${shown.length + more} matched your subscriptions${more ? `, newest ${shown.length} shown` : \"\"}. Call agentx_events for details or newer ones:]`,\n ...shown.map((e) => `- ${formatEventLine(e)}`),\n ]\n return lines.join(\"\\n\")\n}\n"],"mappings":"AAkBO,IAAMA,EAAW,GACXC,EAAe,GAEfC,EAAa,GAQnB,SAASC,EAAoBC,EAAwBC,EAAkBC,EAAuB,CACnG,OAAID,EAAE,UAAYC,GAAQ,CAACF,EAAI,QAAQ,SAASE,CAAI,EAAU,GACvDC,EAAeH,EAAKC,CAAC,CAC9B,CAGO,SAASE,EAAeH,EAAwBC,EAA2B,CAIhF,MAHI,GAACD,EAAI,MAAM,KAAMI,GAAMA,IAAM,KAAOA,IAAMH,EAAE,MAAQG,IAAMH,EAAE,IAAI,GAChED,EAAI,QAAQ,SAAW,CAACC,EAAE,SAAW,CAACD,EAAI,OAAO,SAASC,EAAE,OAAO,IACnED,EAAI,OAAO,QAAU,CAACA,EAAI,MAAM,SAASC,EAAE,IAAI,GAC/CD,EAAI,OAAS,CAACC,EAAE,QAAQ,YAAY,EAAE,SAASD,EAAI,MAAM,YAAY,CAAC,EAE5E,CAIO,SAASK,EAAiBC,EAAuCC,EAAyC,CAC/G,OAAKD,GAAM,OACJC,IAAa,OAASD,EAAOA,EAAK,OAAQE,IAAOA,EAAE,UAAY,UAAYD,CAAQ,EADhE,CAAC,CAE7B,CAOO,SAASE,EACdC,EACAJ,EACAK,EACAC,EAAsE,CAAC,EACtD,CACjB,IAAMC,EAASR,EAAiBC,EAAMM,EAAK,UAAY,MAAM,EAC7D,GAAIC,EAAO,SAAW,EAAG,MAAO,CAAC,EACjC,IAAMC,EAAQC,EAAWH,EAAK,KAAK,EAC7BI,EAAOL,EAAO,OAAQV,GAAMY,EAAO,KAAML,GAAMT,EAAoBS,EAAGP,EAAGS,CAAO,CAAC,CAAC,EACxF,OAAOE,EAAK,WAAaI,EAAK,MAAM,EAAGF,CAAK,EAAIE,EAAK,MAAM,CAACF,CAAK,CACnE,CAEO,SAASC,EAAWD,EAA2BG,EAAW,GAAsB,CACrF,MAAI,CAACH,GAAS,CAAC,OAAO,SAASA,CAAK,GAAKA,EAAQ,EAAUG,EACpD,KAAK,IAAI,KAAK,MAAMH,CAAK,EAAG,EAAQ,CAC7C,CAMO,SAASI,EACdR,EACAJ,EACAK,EAC0C,CAC1C,IAAME,EAASR,EAAiBC,EAAM,QAAQ,EAC9C,GAAIO,EAAO,SAAW,EAAG,MAAO,CAAE,MAAO,CAAC,EAAG,KAAM,CAAE,EACrD,IAAIM,EAAQ,EACZ,QAASC,EAAIT,EAAO,OAAS,EAAGS,GAAK,EAAGA,IACtC,GAAIT,EAAOS,CAAC,EAAE,UAAYV,GAAWC,EAAOS,CAAC,EAAE,OAAS,iBAAkB,CAAED,EAAQC,EAAI,EAAG,MAE7F,IAAMJ,EAAOL,EAAO,MAAMQ,CAAK,EAAE,OAAQlB,GAAMY,EAAO,KAAML,GAAMT,EAAoBS,EAAGP,EAAGS,CAAO,CAAC,CAAC,EAC/FW,EAAQL,EAAK,MAAM,GAAW,EACpC,MAAO,CAAE,MAAAK,EAAO,KAAML,EAAK,OAASK,EAAM,MAAO,CACnD,CAGO,SAASC,EAAgB,EAA0B,CACxD,IAAMC,EAAM,EAAE,QAAU,GAAG,EAAE,WAAW,EAAE,OAAS,EAAE,KAC/CC,EAAM,EAAE,IAAM,SAAS,EAAE,OAAS,GACxC,MAAO,GAAG,EAAE,GAAG,MAAM,EAAG,EAAE,EAAE,QAAQ,IAAK,GAAG,KAAK,EAAE,QAAQD,MAAQ,EAAE,UAAUC,GACjF,CAGO,SAASC,EAAaJ,EAAwBK,EAAkC,CACrF,OAAIL,EAAM,SAAW,EAAG,OACV,CACZ,uCAAkCA,EAAM,OAASK,+BAAkCA,EAAO,YAAYL,EAAM,eAAiB,qDAC7H,GAAGA,EAAM,IAAKpB,GAAM,KAAKqB,EAAgBrB,CAAC,GAAG,CAC/C,EACa,KAAK;AAAA,CAAI,CACxB","names":["PULL_MAX","PULL_DEFAULT","DIGEST_MAX","matchesSubscription","sub","e","self","matchesFilters","k","subscriptionsFor","subs","delivery","s","eventsForAgent","agentId","events","opts","active","limit","clampLimit","hits","fallback","digestEvents","start","i","shown","formatEventLine","who","ref","renderDigest","more"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{a as D,b as _}from"./chunk-RKPAVWXF.js";import{a as q,b as O,c as R,d as B,f as b,g as S,h as E,i as w,j as y}from"./chunk-
|
|
1
|
+
import{a as D,b as _}from"./chunk-RKPAVWXF.js";import{a as q,b as O,c as R,d as B,f as b,g as S,h as E,i as w,j as y}from"./chunk-SA23V7WX.js";import{a as T,b as C,c as I,d as x,e as P}from"./chunk-EZN2YXRY.js";import{existsSync as X,readFileSync as F}from"fs";var J=new Set(["cron","heartbeat","api","a2a","mesh"]),M=160;function s(n){return typeof n=="string"&&n.trim()?n.trim():void 0}function A(n,e=M){let t=n.replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e-1)}\u2026`:t}function V(n){let e=T(n);if(!X(e))throw new Error(`config not found at ${e}`);return JSON.parse(F(e,"utf-8"))}function W(n,e){return n?.agents?.[e]?.admin===!0}function Y(n,e,t){return W(n,t.agentId)||e?.createdBy===t.agentId}function Z(n,e){let t=e?.createdBy?`agent "${e.createdBy}"`:"the operator";return`Not allowed: "${n}" was created by ${t}. Agents manage only schedules they created (unless configured admin).`}function K(n,e){let t=s(n.notify);if(t!=="none"){if(t&&t!=="here"){let r=t.split(":");return r.length<2||!r[0]||!r[1]?"invalid":{channel:r[0],chatId:r.slice(1).join(":")}}if(e.channel&&e.chatId&&!J.has(e.channel))return{channel:e.channel,chatId:e.chatId,...e.accountId?{accountId:e.accountId}:{}}}}function Q(n,e,t){let r=e.timezone||"UTC",u=e.enabled&&!y(e)?w(E(e.schedule,r,t),r):"\u2014",h=e.approval?`pending ${e.approval.action} approval`:e.enabled?"active":"paused",p=[`- ${n} [${h}] ${e.schedule} \u2014 ${S(e.schedule)} (${r})`,` agent: ${e.agent}; created by: ${e.createdBy||"operator"}; next: ${u}`];return e.notify&&p.push(` notify: ${e.notify.channel} ${e.notify.chatId}`),e.command?p.push(` command: ${A(String(e.command))}`):e.prompt&&p.push(` prompt: ${A(String(e.prompt))}`),p.join(`
|
|
2
2
|
`)}async function k(n,e,t){let r=n?.notifications?.destination;if(!r?.channel||!r?.chatId)return"No operator notification destination is configured (notifications.destination); the operator must check `agentx schedule list`.";if(!e.notifyOperator)return"Operator notification is unavailable in this context.";try{return await e.notifyOperator({channel:r.channel,chatId:r.chatId,accountId:r.accountId},t),"The operator has been notified."}catch(u){return`Could not notify the operator (${u?.message??u}); the request is still recorded.`}}async function re(n,e,t={}){let r=(s(n.action)||"list").toLowerCase(),u=t.now?t.now():new Date,h;try{h=V(t.configPath)}catch(a){return`Error: ${a.message}`}let p=h.crons||{};if(r==="list"){let a=n.mine===!0,l=Object.entries(p).filter(([,i])=>!a||e&&i?.createdBy===e.agentId);return l.length?l.map(([i,f])=>Q(i,f,u)).join(`
|
|
3
3
|
`):a?"You have no schedules.":"No schedules."}if(!e?.agentId)return"Error: caller agent is unknown (AGENTX_AGENT_ID not set). Pass callerAgentId.";if(!h.agents?.[e.agentId])return`Error: caller "${e.agentId}" is not an agent on this node.`;let o=s(n.id),m=a=>C(a,{configPath:t.configPath,reload:t.reload});if(r==="create"){let a=s(n.when),l=s(n.prompt);if(!a||!l)return"Error: create needs `when` (plain English) and `prompt`.";let i=D(a);if(!i)return`Error: couldn't parse "${a}". ${O}.`;let f=s(n.agent)||e.agentId;if(!h.agents?.[f])return`Error: agent "${f}" not found on this node.`;let g=s(n.timezone)||q;if(!B(g))return`Error: unknown timezone "${g}".`;let d=o||_(i.matched,f);if(!R(d))return`Error: invalid id "${d}" (letters, digits, "-" and "_" only).`;if(p[d])return`Error: a schedule "${d}" already exists. Pick another \`id\`.`;let $=K(n,e);if($==="invalid")return'Error: `notify` must be "here", "none", or "channel:chatId".';let z={action:"create",requestedBy:e.agentId,requestedAt:u.toISOString()},L=b({parsed:i,agent:f,prompt:l,timezone:g,notify:$,enabled:!1,createdBy:e.agentId,approval:z}),v=await m(U=>I(U,`crons.${d}`,L));if(!v.success)return`Error: ${v.error}`;let N=w(E(i.cron,g,u),g),G=[`Schedule approval requested by ${e.agentId}`,`Create: ${d}`,`When: ${i.human} \u2014 cron \`${i.cron}\` (${g})`,`Next fire: ${N}`,`Agent: ${f}`,$?`Notify: ${$.channel} ${$.chatId}`:"Notify: none",`Prompt: ${A(l,400)}`,"",`Approve: agentx schedule approve ${d}`,`Reject: agentx schedule reject ${d}`].join(`
|
|
4
4
|
`),H=await k(h,t,G);return[`Requested schedule "${d}": ${i.human} (cron ${i.cron}, ${g}); next fire would be ${N}.`,"It is saved DISABLED and will not run until the operator approves it.",H].join(`
|
|
5
5
|
`)}if(!o)return`Error: ${r} needs \`id\`.`;let c=p[o];if(!c)return`Error: schedule "${o}" not found.`;if(!Y(h,c,e))return Z(o,c);if(r==="pause"||r==="resume"){let a=r==="resume";if(a&&y(c))return`"${o}" is still awaiting operator approval; it can't be resumed until approved.`;if(c.enabled===a)return`"${o}" is already ${a?"active":"paused"}.`;let l=await m(i=>I(i,`crons.${o}.enabled`,a));return l.success?`"${o}" ${a?"resumed":"paused"}.`:`Error: ${l.error}`}if(r==="delete"){if(y(c)&&c.approval.requestedBy===e.agentId){let d=await m($=>P($,`crons.${o}`));return d.success?`Withdrew the pending request "${o}".`:`Error: ${d.error}`}if(y(c))return`"${o}" is a creation request still awaiting approval; only its requester or the operator (\`agentx schedule reject ${o}\`) can drop it.`;if(c.approval?.action==="delete")return`Deletion of "${o}" is already awaiting approval.`;let a={action:"delete",requestedBy:e.agentId,requestedAt:u.toISOString()},l=await m(d=>{if(!x(d,`crons.${o}`))throw new Error(`schedule "${o}" not found`);I(d,`crons.${o}.approval`,a)});if(!l.success)return`Error: ${l.error}`;let i=c.timezone||"UTC",f=[`Schedule approval requested by ${e.agentId}`,`Delete: ${o}`,`When: ${S(c.schedule)} \u2014 cron \`${c.schedule}\` (${i})`,`Next fire: ${c.enabled?w(E(c.schedule,i,u),i):"\u2014 (paused)"}`,`Agent: ${c.agent}`,"",`Approve: agentx schedule approve ${o}`,`Reject: agentx schedule reject ${o}`].join(`
|
|
6
6
|
`),g=await k(h,t,f);return[`Deletion of "${o}" requested. It keeps its current state until the operator approves.`,g].join(`
|
|
7
7
|
`)}return`Error: unknown action "${r}". Use list, create, pause, resume or delete.`}function oe(n,e=process.env){let t=s(e.AGENTX_AGENT_ID)||s(n.callerAgentId);if(!t)return null;let r=!!(s(e.AGENTX_CHANNEL)&&s(e.AGENTX_CHAT_ID)),u=s(r?e.AGENTX_CHANNEL:n.channel),h=s(r?e.AGENTX_CHAT_ID:n.chatId),p=s(n.accountId);return{agentId:t,channel:u,chatId:h,...p?{accountId:p}:{}}}export{re as a,oe as b};
|
|
8
|
-
//# sourceMappingURL=chunk-
|
|
8
|
+
//# sourceMappingURL=chunk-XEOAKD5C.js.map
|
package/dist/cli.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as n}from"./chunk-
|
|
2
|
+
import{a as n}from"./chunk-JC5Q5MPI.js";import"./chunk-WOMQ2VGA.js";import"./chunk-D3LSPFHK.js";import"./chunk-76AHNHWC.js";import"./chunk-Z3IP66SL.js";import"./chunk-KAFO5QZR.js";import"./chunk-RKPAVWXF.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-SZDACK6O.js";import"./chunk-K4RDE6YU.js";import"./chunk-UIVHSYCN.js";import"./chunk-723K4SAW.js";import"./chunk-S7CVSKOX.js";import"./chunk-LQRBGQIR.js";import"./chunk-ZVP6GB4G.js";import"./chunk-SA23V7WX.js";import"./chunk-W4YMMWJL.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import"./chunk-2D3RYIDU.js";import"./chunk-L53FTKEP.js";import"./chunk-EJ5ISSWW.js";import"./chunk-CELYD5QW.js";import"./chunk-WP6KLXTP.js";import"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import"./chunk-O3XG2NVR.js";import"./chunk-EZN2YXRY.js";import"./chunk-6AK6WKE5.js";import"./chunk-SFQUP3BP.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import"./chunk-X5C5W3E4.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-4HEVSWO3.js";import"./chunk-DWADWDMU.js";import"./chunk-NO2HOK4B.js";import"./chunk-QD6IICK7.js";import"./chunk-VWTBHLMX.js";import"./chunk-LKJSPO3S.js";import"./chunk-C3VRBEJ7.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-GSOL2LW6.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import"./chunk-M4AG2YNX.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import"./chunk-SZJMS7K4.js";import"./chunk-7I7IEX4S.js";import"./chunk-VDMYBPYB.js";import"./chunk-DSYKYZMT.js";import"./chunk-U4H35SJS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";var r=["SIGINT","SIGTERM"];function o(t=process){for(let i of r)t.on(i,()=>{t.listenerCount(i)<=1&&t.exit(0)})}o();async function s(){let t=await n();if(process.argv.slice(2).length===0){t.outputHelp();return}t.parse()}s();
|
|
3
3
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/signal-exit.ts","../src/cli.ts"],"sourcesContent":["// --- Ctrl-C / SIGTERM for CLI commands ---\n//\n// Short commands should exit at once when stopped. Long-running ones (the\n// daemon above all) install their own handler to finish in-flight work first.\n// The CLI's quick exit used to be registered unconditionally, before the\n// daemon's, and Node runs listeners in registration order — so every stop\n// exited the process before the daemon's drain began and killed in-flight\n// agent tasks mid-turn (#103). Now the quick exit only fires when nobody\n// else handles the signal.\n\ntype SignalTarget = Pick<NodeJS.Process, \"on\" | \"listenerCount\" | \"exit\">\n\nexport const CLI_EXIT_SIGNALS = [\"SIGINT\", \"SIGTERM\"] as const\n\nexport function installCliSignalExit(proc: SignalTarget = process): void {\n for (const sig of CLI_EXIT_SIGNALS) {\n proc.on(sig, () => {\n // This listener is always one of them; anything more means a command\n // is handling the stop itself.\n if (proc.listenerCount(sig) <= 1) proc.exit(0)\n })\n }\n}\n","#!/usr/bin/env node\nimport { buildProgram } from \"@/program\"\nimport { installCliSignalExit } from \"@/utils/signal-exit\"\n\ninstallCliSignalExit()\n\nasync function main() {\n const program = await buildProgram()\n\n const args = process.argv.slice(2)\n if (args.length === 0) {\n program.outputHelp()\n return\n }\n\n program.parse()\n}\n\nmain()\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../src/utils/signal-exit.ts","../src/cli.ts"],"sourcesContent":["// --- Ctrl-C / SIGTERM for CLI commands ---\n//\n// Short commands should exit at once when stopped. Long-running ones (the\n// daemon above all) install their own handler to finish in-flight work first.\n// The CLI's quick exit used to be registered unconditionally, before the\n// daemon's, and Node runs listeners in registration order — so every stop\n// exited the process before the daemon's drain began and killed in-flight\n// agent tasks mid-turn (#103). Now the quick exit only fires when nobody\n// else handles the signal.\n\ntype SignalTarget = Pick<NodeJS.Process, \"on\" | \"listenerCount\" | \"exit\">\n\nexport const CLI_EXIT_SIGNALS = [\"SIGINT\", \"SIGTERM\"] as const\n\nexport function installCliSignalExit(proc: SignalTarget = process): void {\n for (const sig of CLI_EXIT_SIGNALS) {\n proc.on(sig, () => {\n // This listener is always one of them; anything more means a command\n // is handling the stop itself.\n if (proc.listenerCount(sig) <= 1) proc.exit(0)\n })\n }\n}\n","#!/usr/bin/env node\nimport { buildProgram } from \"@/program\"\nimport { installCliSignalExit } from \"@/utils/signal-exit\"\n\ninstallCliSignalExit()\n\nasync function main() {\n const program = await buildProgram()\n\n const args = process.argv.slice(2)\n if (args.length === 0) {\n program.outputHelp()\n return\n }\n\n program.parse()\n}\n\nmain()\n"],"mappings":";wrDAYO,IAAMA,EAAmB,CAAC,SAAU,SAAS,EAE7C,SAASC,EAAqBC,EAAqB,QAAe,CACvE,QAAWC,KAAOH,EAChBE,EAAK,GAAGC,EAAK,IAAM,CAGbD,EAAK,cAAcC,CAAG,GAAK,GAAGD,EAAK,KAAK,CAAC,CAC/C,CAAC,CAEL,CClBAE,EAAqB,EAErB,eAAeC,GAAO,CACpB,IAAMC,EAAU,MAAMC,EAAa,EAGnC,GADa,QAAQ,KAAK,MAAM,CAAC,EACxB,SAAW,EAAG,CACrBD,EAAQ,WAAW,EACnB,OAGFA,EAAQ,MAAM,CAChB,CAEAD,EAAK","names":["CLI_EXIT_SIGNALS","installCliSignalExit","proc","sig","installCliSignalExit","main","program","buildProgram"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{i as a,j as b,k as c,l as d,m as e,n as f,o as g,q as h}from"./chunk-U4H35SJS.js";import"./chunk-QIJLFPWE.js";h();export{a as INTEGRATION_KINDS,c as approvalsConfigSchema,d as daemonConfigSchema,b as eventSubscriptionSchema,e as expandEnvVars,f as loadDaemonConfig,g as validateWorkspaces};
|
|
2
|
+
//# sourceMappingURL=config-HPN2F7LH.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{b as a,c as b,d as c,e as d}from"./chunk-D3LSPFHK.js";import"./chunk-S7CVSKOX.js";import"./chunk-U4H35SJS.js";import"./chunk-QIJLFPWE.js";export{b as doctor,a as runDoctorChecks,c as runNotificationChecks,d as runReminderChecks};
|
|
2
|
+
//# sourceMappingURL=doctor-IBWQVQV4.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1635,6 +1635,35 @@ declare const agentConfigSchema: z.ZodObject<{
|
|
|
1635
1635
|
* agents or by the operator. It never approves anything: approval of a
|
|
1636
1636
|
* create/delete request stays operator-only (`agentx schedule approve`). */
|
|
1637
1637
|
admin: z.ZodOptional<z.ZodBoolean>;
|
|
1638
|
+
/** Events on the bus this agent wants to hear about (issue #165). */
|
|
1639
|
+
subscriptions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
1640
|
+
/** Envelope `kind` ("agent", "run") or `type` ("task:completed"); "*" matches all. */
|
|
1641
|
+
kinds: z.ZodArray<z.ZodString, "many">;
|
|
1642
|
+
/** Only events published for these agent ids. */
|
|
1643
|
+
agents: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1644
|
+
/** Only events published by these nodes (`node.name`). */
|
|
1645
|
+
nodes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1646
|
+
/** Only events whose summary contains this text (case-insensitive). */
|
|
1647
|
+
match: z.ZodOptional<z.ZodString>;
|
|
1648
|
+
delivery: z.ZodDefault<z.ZodEnum<["pull", "digest", "wake"]>>;
|
|
1649
|
+
/** wake only: no wake when the agent was already woken this many times
|
|
1650
|
+
* in the past hour. */
|
|
1651
|
+
maxPerHour: z.ZodDefault<z.ZodNumber>;
|
|
1652
|
+
}, "strip", z.ZodTypeAny, {
|
|
1653
|
+
kinds: string[];
|
|
1654
|
+
delivery: "pull" | "digest" | "wake";
|
|
1655
|
+
maxPerHour: number;
|
|
1656
|
+
match?: string | undefined;
|
|
1657
|
+
agents?: string[] | undefined;
|
|
1658
|
+
nodes?: string[] | undefined;
|
|
1659
|
+
}, {
|
|
1660
|
+
kinds: string[];
|
|
1661
|
+
match?: string | undefined;
|
|
1662
|
+
agents?: string[] | undefined;
|
|
1663
|
+
nodes?: string[] | undefined;
|
|
1664
|
+
delivery?: "pull" | "digest" | "wake" | undefined;
|
|
1665
|
+
maxPerHour?: number | undefined;
|
|
1666
|
+
}>, "many">>;
|
|
1638
1667
|
/** Per-agent third-party integrations registry. Declares which services
|
|
1639
1668
|
* this agent has credentials for (telegram-bot, hubspot, gitlab-user,
|
|
1640
1669
|
* gmail, etc.). Secrets stay in env vars / keyring; this block holds
|
|
@@ -1802,6 +1831,14 @@ declare const agentConfigSchema: z.ZodObject<{
|
|
|
1802
1831
|
intervalMinutes: number;
|
|
1803
1832
|
};
|
|
1804
1833
|
access: "private" | "public";
|
|
1834
|
+
subscriptions: {
|
|
1835
|
+
kinds: string[];
|
|
1836
|
+
delivery: "pull" | "digest" | "wake";
|
|
1837
|
+
maxPerHour: number;
|
|
1838
|
+
match?: string | undefined;
|
|
1839
|
+
agents?: string[] | undefined;
|
|
1840
|
+
nodes?: string[] | undefined;
|
|
1841
|
+
}[];
|
|
1805
1842
|
integrations: {
|
|
1806
1843
|
enabled: boolean;
|
|
1807
1844
|
credentials: {
|
|
@@ -1890,6 +1927,14 @@ declare const agentConfigSchema: z.ZodObject<{
|
|
|
1890
1927
|
} | undefined;
|
|
1891
1928
|
access?: "private" | "public" | undefined;
|
|
1892
1929
|
admin?: boolean | undefined;
|
|
1930
|
+
subscriptions?: {
|
|
1931
|
+
kinds: string[];
|
|
1932
|
+
match?: string | undefined;
|
|
1933
|
+
agents?: string[] | undefined;
|
|
1934
|
+
nodes?: string[] | undefined;
|
|
1935
|
+
delivery?: "pull" | "digest" | "wake" | undefined;
|
|
1936
|
+
maxPerHour?: number | undefined;
|
|
1937
|
+
}[] | undefined;
|
|
1893
1938
|
integrations?: {
|
|
1894
1939
|
label: string;
|
|
1895
1940
|
kind: string;
|
|
@@ -2357,6 +2402,35 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
2357
2402
|
* agents or by the operator. It never approves anything: approval of a
|
|
2358
2403
|
* create/delete request stays operator-only (`agentx schedule approve`). */
|
|
2359
2404
|
admin: z.ZodOptional<z.ZodBoolean>;
|
|
2405
|
+
/** Events on the bus this agent wants to hear about (issue #165). */
|
|
2406
|
+
subscriptions: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
2407
|
+
/** Envelope `kind` ("agent", "run") or `type` ("task:completed"); "*" matches all. */
|
|
2408
|
+
kinds: z.ZodArray<z.ZodString, "many">;
|
|
2409
|
+
/** Only events published for these agent ids. */
|
|
2410
|
+
agents: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
2411
|
+
/** Only events published by these nodes (`node.name`). */
|
|
2412
|
+
nodes: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
2413
|
+
/** Only events whose summary contains this text (case-insensitive). */
|
|
2414
|
+
match: z.ZodOptional<z.ZodString>;
|
|
2415
|
+
delivery: z.ZodDefault<z.ZodEnum<["pull", "digest", "wake"]>>;
|
|
2416
|
+
/** wake only: no wake when the agent was already woken this many times
|
|
2417
|
+
* in the past hour. */
|
|
2418
|
+
maxPerHour: z.ZodDefault<z.ZodNumber>;
|
|
2419
|
+
}, "strip", z.ZodTypeAny, {
|
|
2420
|
+
kinds: string[];
|
|
2421
|
+
delivery: "pull" | "digest" | "wake";
|
|
2422
|
+
maxPerHour: number;
|
|
2423
|
+
match?: string | undefined;
|
|
2424
|
+
agents?: string[] | undefined;
|
|
2425
|
+
nodes?: string[] | undefined;
|
|
2426
|
+
}, {
|
|
2427
|
+
kinds: string[];
|
|
2428
|
+
match?: string | undefined;
|
|
2429
|
+
agents?: string[] | undefined;
|
|
2430
|
+
nodes?: string[] | undefined;
|
|
2431
|
+
delivery?: "pull" | "digest" | "wake" | undefined;
|
|
2432
|
+
maxPerHour?: number | undefined;
|
|
2433
|
+
}>, "many">>;
|
|
2360
2434
|
/** Per-agent third-party integrations registry. Declares which services
|
|
2361
2435
|
* this agent has credentials for (telegram-bot, hubspot, gitlab-user,
|
|
2362
2436
|
* gmail, etc.). Secrets stay in env vars / keyring; this block holds
|
|
@@ -2524,6 +2598,14 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
2524
2598
|
intervalMinutes: number;
|
|
2525
2599
|
};
|
|
2526
2600
|
access: "private" | "public";
|
|
2601
|
+
subscriptions: {
|
|
2602
|
+
kinds: string[];
|
|
2603
|
+
delivery: "pull" | "digest" | "wake";
|
|
2604
|
+
maxPerHour: number;
|
|
2605
|
+
match?: string | undefined;
|
|
2606
|
+
agents?: string[] | undefined;
|
|
2607
|
+
nodes?: string[] | undefined;
|
|
2608
|
+
}[];
|
|
2527
2609
|
integrations: {
|
|
2528
2610
|
enabled: boolean;
|
|
2529
2611
|
credentials: {
|
|
@@ -2612,6 +2694,14 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
2612
2694
|
} | undefined;
|
|
2613
2695
|
access?: "private" | "public" | undefined;
|
|
2614
2696
|
admin?: boolean | undefined;
|
|
2697
|
+
subscriptions?: {
|
|
2698
|
+
kinds: string[];
|
|
2699
|
+
match?: string | undefined;
|
|
2700
|
+
agents?: string[] | undefined;
|
|
2701
|
+
nodes?: string[] | undefined;
|
|
2702
|
+
delivery?: "pull" | "digest" | "wake" | undefined;
|
|
2703
|
+
maxPerHour?: number | undefined;
|
|
2704
|
+
}[] | undefined;
|
|
2615
2705
|
integrations?: {
|
|
2616
2706
|
label: string;
|
|
2617
2707
|
kind: string;
|
|
@@ -3967,10 +4057,6 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
3967
4057
|
} | undefined;
|
|
3968
4058
|
}>>;
|
|
3969
4059
|
}, "strip", z.ZodTypeAny, {
|
|
3970
|
-
defaultExpiryDays: number;
|
|
3971
|
-
maxExpiryDays: number;
|
|
3972
|
-
laterHours: number;
|
|
3973
|
-
notifyAgent: boolean;
|
|
3974
4060
|
digest: {
|
|
3975
4061
|
enabled: boolean;
|
|
3976
4062
|
time: string;
|
|
@@ -3981,11 +4067,11 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
3981
4067
|
accountId?: string | undefined;
|
|
3982
4068
|
} | undefined;
|
|
3983
4069
|
};
|
|
4070
|
+
defaultExpiryDays: number;
|
|
4071
|
+
maxExpiryDays: number;
|
|
4072
|
+
laterHours: number;
|
|
4073
|
+
notifyAgent: boolean;
|
|
3984
4074
|
}, {
|
|
3985
|
-
defaultExpiryDays?: number | undefined;
|
|
3986
|
-
maxExpiryDays?: number | undefined;
|
|
3987
|
-
laterHours?: number | undefined;
|
|
3988
|
-
notifyAgent?: boolean | undefined;
|
|
3989
4075
|
digest?: {
|
|
3990
4076
|
enabled?: boolean | undefined;
|
|
3991
4077
|
timezone?: string | undefined;
|
|
@@ -3996,6 +4082,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
3996
4082
|
accountId?: string | undefined;
|
|
3997
4083
|
} | undefined;
|
|
3998
4084
|
} | undefined;
|
|
4085
|
+
defaultExpiryDays?: number | undefined;
|
|
4086
|
+
maxExpiryDays?: number | undefined;
|
|
4087
|
+
laterHours?: number | undefined;
|
|
4088
|
+
notifyAgent?: boolean | undefined;
|
|
3999
4089
|
}>>;
|
|
4000
4090
|
/** What happens to runs a restart cuts off (agents/resume). Chat messages
|
|
4001
4091
|
* are resumed in their chat; scheduled jobs never are (the next run
|
|
@@ -4209,6 +4299,19 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
4209
4299
|
timeout?: number | undefined;
|
|
4210
4300
|
interval?: number | undefined;
|
|
4211
4301
|
}>>;
|
|
4302
|
+
/** Peer event feed (#166): follow each healthy peer's /events and merge
|
|
4303
|
+
* its own events into this node's bus. `skipTypes` are left out on the
|
|
4304
|
+
* peer's side; per-step agent activity is too chatty to cross the mesh. */
|
|
4305
|
+
feed: z.ZodDefault<z.ZodObject<{
|
|
4306
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
4307
|
+
skipTypes: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
4308
|
+
}, "strip", z.ZodTypeAny, {
|
|
4309
|
+
enabled: boolean;
|
|
4310
|
+
skipTypes: string[];
|
|
4311
|
+
}, {
|
|
4312
|
+
enabled?: boolean | undefined;
|
|
4313
|
+
skipTypes?: string[] | undefined;
|
|
4314
|
+
}>>;
|
|
4212
4315
|
}, "strip", z.ZodTypeAny, {
|
|
4213
4316
|
enabled: boolean;
|
|
4214
4317
|
peers: {
|
|
@@ -4226,6 +4329,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
4226
4329
|
timeout: number;
|
|
4227
4330
|
interval: number;
|
|
4228
4331
|
};
|
|
4332
|
+
feed: {
|
|
4333
|
+
enabled: boolean;
|
|
4334
|
+
skipTypes: string[];
|
|
4335
|
+
};
|
|
4229
4336
|
}, {
|
|
4230
4337
|
enabled?: boolean | undefined;
|
|
4231
4338
|
peers?: {
|
|
@@ -4243,6 +4350,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
4243
4350
|
timeout?: number | undefined;
|
|
4244
4351
|
interval?: number | undefined;
|
|
4245
4352
|
} | undefined;
|
|
4353
|
+
feed?: {
|
|
4354
|
+
enabled?: boolean | undefined;
|
|
4355
|
+
skipTypes?: string[] | undefined;
|
|
4356
|
+
} | undefined;
|
|
4246
4357
|
}>>;
|
|
4247
4358
|
/** Voices for agents on mesh peers, keyed by remote agent id. The Mac
|
|
4248
4359
|
* speaks for them, so their nodes need no ElevenLabs key. Unset fields
|
|
@@ -5607,6 +5718,14 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
5607
5718
|
intervalMinutes: number;
|
|
5608
5719
|
};
|
|
5609
5720
|
access: "private" | "public";
|
|
5721
|
+
subscriptions: {
|
|
5722
|
+
kinds: string[];
|
|
5723
|
+
delivery: "pull" | "digest" | "wake";
|
|
5724
|
+
maxPerHour: number;
|
|
5725
|
+
match?: string | undefined;
|
|
5726
|
+
agents?: string[] | undefined;
|
|
5727
|
+
nodes?: string[] | undefined;
|
|
5728
|
+
}[];
|
|
5610
5729
|
integrations: {
|
|
5611
5730
|
enabled: boolean;
|
|
5612
5731
|
credentials: {
|
|
@@ -5683,6 +5802,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
5683
5802
|
timeout: number;
|
|
5684
5803
|
interval: number;
|
|
5685
5804
|
};
|
|
5805
|
+
feed: {
|
|
5806
|
+
enabled: boolean;
|
|
5807
|
+
skipTypes: string[];
|
|
5808
|
+
};
|
|
5686
5809
|
};
|
|
5687
5810
|
voice: {
|
|
5688
5811
|
provider: "system" | "elevenlabs";
|
|
@@ -5932,10 +6055,6 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
5932
6055
|
} | undefined;
|
|
5933
6056
|
};
|
|
5934
6057
|
approvals: {
|
|
5935
|
-
defaultExpiryDays: number;
|
|
5936
|
-
maxExpiryDays: number;
|
|
5937
|
-
laterHours: number;
|
|
5938
|
-
notifyAgent: boolean;
|
|
5939
6058
|
digest: {
|
|
5940
6059
|
enabled: boolean;
|
|
5941
6060
|
time: string;
|
|
@@ -5946,6 +6065,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
5946
6065
|
accountId?: string | undefined;
|
|
5947
6066
|
} | undefined;
|
|
5948
6067
|
};
|
|
6068
|
+
defaultExpiryDays: number;
|
|
6069
|
+
maxExpiryDays: number;
|
|
6070
|
+
laterHours: number;
|
|
6071
|
+
notifyAgent: boolean;
|
|
5949
6072
|
};
|
|
5950
6073
|
reminders: {
|
|
5951
6074
|
enabled: boolean;
|
|
@@ -6247,6 +6370,14 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6247
6370
|
} | undefined;
|
|
6248
6371
|
access?: "private" | "public" | undefined;
|
|
6249
6372
|
admin?: boolean | undefined;
|
|
6373
|
+
subscriptions?: {
|
|
6374
|
+
kinds: string[];
|
|
6375
|
+
match?: string | undefined;
|
|
6376
|
+
agents?: string[] | undefined;
|
|
6377
|
+
nodes?: string[] | undefined;
|
|
6378
|
+
delivery?: "pull" | "digest" | "wake" | undefined;
|
|
6379
|
+
maxPerHour?: number | undefined;
|
|
6380
|
+
}[] | undefined;
|
|
6250
6381
|
integrations?: {
|
|
6251
6382
|
label: string;
|
|
6252
6383
|
kind: string;
|
|
@@ -6307,6 +6438,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6307
6438
|
timeout?: number | undefined;
|
|
6308
6439
|
interval?: number | undefined;
|
|
6309
6440
|
} | undefined;
|
|
6441
|
+
feed?: {
|
|
6442
|
+
enabled?: boolean | undefined;
|
|
6443
|
+
skipTypes?: string[] | undefined;
|
|
6444
|
+
} | undefined;
|
|
6310
6445
|
} | undefined;
|
|
6311
6446
|
voice?: {
|
|
6312
6447
|
system?: string | Record<string, string> | undefined;
|
|
@@ -6550,10 +6685,6 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6550
6685
|
} | undefined;
|
|
6551
6686
|
} | undefined;
|
|
6552
6687
|
approvals?: {
|
|
6553
|
-
defaultExpiryDays?: number | undefined;
|
|
6554
|
-
maxExpiryDays?: number | undefined;
|
|
6555
|
-
laterHours?: number | undefined;
|
|
6556
|
-
notifyAgent?: boolean | undefined;
|
|
6557
6688
|
digest?: {
|
|
6558
6689
|
enabled?: boolean | undefined;
|
|
6559
6690
|
timezone?: string | undefined;
|
|
@@ -6564,6 +6695,10 @@ declare const daemonConfigSchema: z.ZodObject<{
|
|
|
6564
6695
|
accountId?: string | undefined;
|
|
6565
6696
|
} | undefined;
|
|
6566
6697
|
} | undefined;
|
|
6698
|
+
defaultExpiryDays?: number | undefined;
|
|
6699
|
+
maxExpiryDays?: number | undefined;
|
|
6700
|
+
laterHours?: number | undefined;
|
|
6701
|
+
notifyAgent?: boolean | undefined;
|
|
6567
6702
|
} | undefined;
|
|
6568
6703
|
reminders?: {
|
|
6569
6704
|
enabled?: boolean | undefined;
|
|
@@ -6994,6 +7129,9 @@ declare class A2AMesh {
|
|
|
6994
7129
|
senderAgentId?: string;
|
|
6995
7130
|
freshSession?: boolean;
|
|
6996
7131
|
context?: Record<string, unknown>;
|
|
7132
|
+
/** Aborts the peer call; the peer's /task treats it as a disconnect
|
|
7133
|
+
* and interrupts the run. */
|
|
7134
|
+
signal?: AbortSignal;
|
|
6997
7135
|
}): AsyncGenerator<{
|
|
6998
7136
|
event: string;
|
|
6999
7137
|
data: any;
|
|
@@ -7233,6 +7371,10 @@ declare class TypedEventBus {
|
|
|
7233
7371
|
private envelopeListeners;
|
|
7234
7372
|
private ring;
|
|
7235
7373
|
private node;
|
|
7374
|
+
/** Envelopes taken in from mesh peers, keyed `${node}:${id}`, so the
|
|
7375
|
+
* live stream and a catch-up read never deliver one event twice. Map
|
|
7376
|
+
* insertion order makes the oldest key the first to drop. */
|
|
7377
|
+
private seen;
|
|
7236
7378
|
constructor();
|
|
7237
7379
|
/** Set the publishing node name and ring size (daemon boot / reload). */
|
|
7238
7380
|
configure(opts: {
|
|
@@ -7244,6 +7386,19 @@ declare class TypedEventBus {
|
|
|
7244
7386
|
emit<E extends EventName>(event: E, payload: AgentXEvents[E]): boolean;
|
|
7245
7387
|
/** The single publish API. Returns the envelope as delivered. */
|
|
7246
7388
|
publish(input: PublishInput): EventEnvelope;
|
|
7389
|
+
/** Name this bus publishes under. An envelope whose `node` differs came
|
|
7390
|
+
* from a mesh peer (see ingest). */
|
|
7391
|
+
get nodeName(): string;
|
|
7392
|
+
/** True for envelopes this node published itself. */
|
|
7393
|
+
isLocal(e: EventEnvelope): boolean;
|
|
7394
|
+
/** Take in an envelope published on a mesh peer. It keeps its id, node
|
|
7395
|
+
* and root, lands in the ring and reaches `subscribe` listeners, but
|
|
7396
|
+
* never the typed `on` listeners: the peer records its own traces.
|
|
7397
|
+
* Returns false for an event already taken in, or one that claims to
|
|
7398
|
+
* come from this node (an echo). */
|
|
7399
|
+
ingest(input: EventEnvelope): boolean;
|
|
7400
|
+
/** Whether an event id is still in this node's ring buffer. */
|
|
7401
|
+
hasRecent(id: string): boolean;
|
|
7247
7402
|
/** Receive every envelope. Returns an unsubscribe function. */
|
|
7248
7403
|
subscribe(fn: EnvelopeListener): () => void;
|
|
7249
7404
|
recent(q?: RecentQuery): EventEnvelope[];
|
|
@@ -7363,6 +7518,7 @@ declare class AgentXDaemon {
|
|
|
7363
7518
|
private hooks;
|
|
7364
7519
|
private landscape;
|
|
7365
7520
|
private heartbeat;
|
|
7521
|
+
private stopEventWaker?;
|
|
7366
7522
|
private business?;
|
|
7367
7523
|
private httpServer?;
|
|
7368
7524
|
private attachSweep?;
|
|
@@ -7405,6 +7561,8 @@ declare class AgentXDaemon {
|
|
|
7405
7561
|
* dashboard) filter by kind / workflow / actor. Created eagerly so
|
|
7406
7562
|
* early boot events don't fall through. */
|
|
7407
7563
|
readonly events: EventBus;
|
|
7564
|
+
/** Follows each healthy peer's event feed into the local bus (#166). */
|
|
7565
|
+
private peerFeed?;
|
|
7408
7566
|
private log;
|
|
7409
7567
|
private sseClients;
|
|
7410
7568
|
private configPath?;
|
|
@@ -9790,6 +9948,13 @@ declare class AgentRegistry {
|
|
|
9790
9948
|
* on WorkflowDispatcher. */
|
|
9791
9949
|
private workflowAutoRunner?;
|
|
9792
9950
|
private messageQueue;
|
|
9951
|
+
/**
|
|
9952
|
+
* Voice chats a waiting question has claimed between its wait ending and
|
|
9953
|
+
* the chat being marked running (the rate limiter awaits in between).
|
|
9954
|
+
* Without the claim, two questions waiting on one chat could both see it
|
|
9955
|
+
* free and run at once.
|
|
9956
|
+
*/
|
|
9957
|
+
private voiceClaims;
|
|
9793
9958
|
/** Intent Knowledge Graph classifier. Null when graph.enabled=false. */
|
|
9794
9959
|
private classifier?;
|
|
9795
9960
|
private graphStore?;
|
|
@@ -10011,6 +10176,9 @@ declare class AgentRegistry {
|
|
|
10011
10176
|
channel: string;
|
|
10012
10177
|
chatId: string;
|
|
10013
10178
|
} | null;
|
|
10179
|
+
/** Stop every in-flight run of `agentId` in one chat. Used when a streaming
|
|
10180
|
+
* caller disconnects (the phone app's Stop). Returns how many it aborted. */
|
|
10181
|
+
cancelChatTasks(agentId: string, channel: string, chatId: string, reason?: string): number;
|
|
10014
10182
|
/**
|
|
10015
10183
|
* Queue a follow-up correction/update for an in-flight task. The message
|
|
10016
10184
|
* lands in the per-session MessageQueue and is dispatched after the
|
|
@@ -10076,9 +10244,7 @@ declare class AgentRegistry {
|
|
|
10076
10244
|
byAgent: Record<string, {
|
|
10077
10245
|
tasks: number;
|
|
10078
10246
|
input: number;
|
|
10079
|
-
output: number;
|
|
10080
|
-
* the requested agent before returning "Unknown agent". Duck-typed so
|
|
10081
|
-
* we don't create a circular import with src/a2a/mesh.ts. */
|
|
10247
|
+
output: number;
|
|
10082
10248
|
cacheRead: number;
|
|
10083
10249
|
cacheCreate: number;
|
|
10084
10250
|
total: number;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as L}from"./chunk-Y57CULGE.js";import{a as St,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt,la as bt,ma as Tt,na as Mt}from"./chunk-
|
|
1
|
+
import{a as L}from"./chunk-Y57CULGE.js";import{a as St,b as kt,c as vt,d as xt,e as $t,f as Ct,g as Pt,la as bt,ma as Tt,na as Mt}from"./chunk-K4RDE6YU.js";import"./chunk-UIVHSYCN.js";import"./chunk-723K4SAW.js";import"./chunk-S7CVSKOX.js";import"./chunk-LQRBGQIR.js";import"./chunk-ZVP6GB4G.js";import"./chunk-SA23V7WX.js";import"./chunk-W4YMMWJL.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import"./chunk-2D3RYIDU.js";import"./chunk-L53FTKEP.js";import{S as yt,l as lt,m as ct,n as dt,o as mt,p as pt}from"./chunk-EJ5ISSWW.js";import"./chunk-CELYD5QW.js";import"./chunk-WP6KLXTP.js";import"./chunk-N6EWZGIX.js";import"./chunk-DP7RTNDM.js";import{s as ut}from"./chunk-O3XG2NVR.js";import"./chunk-EZN2YXRY.js";import{A as D,B as z,C as V,a as ye,b as we,c as Se,d as Ae,e as Ie,f as Oe,g as Ne,h as He,i as je,j as Ue,k as _e,l as I,m as q,n as Be,o as qe,p as Ye,q as O,r as ze,s as Ve,t as Xe,u as x,v as Y,w as Qe,x as Ze,y as et,z as wt}from"./chunk-6AK6WKE5.js";import{a as B,b as M,c as F}from"./chunk-SFQUP3BP.js";import"./chunk-J3SOEFRE.js";import"./chunk-SIU6STB2.js";import"./chunk-X5C5W3E4.js";import"./chunk-76Z4VHDX.js";import"./chunk-W4YR2RO2.js";import"./chunk-AFRHKA7B.js";import"./chunk-4HEVSWO3.js";import"./chunk-DWADWDMU.js";import"./chunk-NO2HOK4B.js";import"./chunk-QD6IICK7.js";import"./chunk-VWTBHLMX.js";import"./chunk-LKJSPO3S.js";import{a as gt,b as ft,e as ht}from"./chunk-C3VRBEJ7.js";import"./chunk-PNWNVOEZ.js";import"./chunk-64P4QHSZ.js";import"./chunk-GSOL2LW6.js";import"./chunk-TFVUOC2C.js";import"./chunk-2GIDVZ4H.js";import{j as it,k as rt,l as at}from"./chunk-M4AG2YNX.js";import"./chunk-72SZI2UW.js";import"./chunk-FCPTN6NF.js";import"./chunk-FX3D7YON.js";import"./chunk-QOYAX2FT.js";import{a as ke,b as ve,c as xe,d as $e,e as Ce,f as Pe,g as be,h as Te,i as Me,j as Re,l as Ee,m as Ge,o as T,p as W}from"./chunk-SZJMS7K4.js";import{a as m,b as G}from"./chunk-7I7IEX4S.js";import{a as Fe,b as Le,c as A,d as De}from"./chunk-VDMYBPYB.js";import{a as Ke,b as Je,e as We}from"./chunk-DSYKYZMT.js";import{l as tt,n as st,o as ot,q as nt}from"./chunk-U4H35SJS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";W();G();import{execa as Rt}from"execa";import{existsSync as se,promises as X}from"fs";import S from"path";import ie from"node-fetch";async function Et(o,e){let t=o.split("/");if(t.length<2)throw new Error(`Invalid skill package ID: ${o}. Expected format: owner/repo`);let s=t[0],i=t[1],n=t[2];try{let a=n?`${s}/${i}/${n}`:`${s}/${i}`;await Rt("npx",["-y","skills","add",a],{cwd:e,stdio:"pipe"}),m.success(`Installed skill package: ${o}`);let r=S.resolve(e,".skills",`${s}_${i}`);if(se(r))return await ne(r,o);let d=S.resolve(e,".skills");return se(d)?await ne(d,o):[]}catch{return m.info(`Fetching skills directly from GitHub: ${s}/${i}`),await Gt(s,i,n,e)}}async function Gt(o,e,t,s){let i=[];try{let n=`https://api.github.com/repos/${o}/${e}/git/trees/main?recursive=1`,a=await ie(n);if(!a.ok)throw new Error(`GitHub API error: ${a.status}`);let d=(await a.json()).tree.filter(p=>p.type==="blob"&&p.path.endsWith("SKILL.md"));if(t){let p=d.find(f=>f.path.includes(`/${t}/`)||f.path===`${t}/SKILL.md`);if(p){let f=await oe(o,e,p.path,s);f&&i.push(f)}}else for(let p of d){let f=await oe(o,e,p.path,s);f&&i.push(f)}}catch(n){m.error(`Failed to fetch skills from GitHub: ${n.message}`)}return i}async function oe(o,e,t,s){try{let i=`https://raw.githubusercontent.com/${o}/${e}/main/${t}`,n=await ie(i);if(!n.ok)return null;let a=await n.text(),r=A(a);if(r){r.source="remote",r.packageId=`${o}/${e}`;let d=S.dirname(t),p=S.resolve(s,".skills",`${o}_${e}`,d);await X.mkdir(p,{recursive:!0}),await X.writeFile(S.resolve(p,"SKILL.md"),a),r.path=S.resolve(p,"SKILL.md")}return r}catch{return null}}async function ne(o,e){let t=[],{default:s}=await import("fast-glob"),i=await s.glob("**/SKILL.md",{cwd:o,deep:5});for(let n of i)try{let a=S.resolve(o,n),r=await X.readFile(a,"utf8"),d=A(r);d&&(d.source="remote",d.path=a,d.packageId=e,t.push(d))}catch{}return t}async function At(o,e,t,s,i){let n=["---",`name: ${o}`,`description: ${e}`];if(s?.length){n.push("tags:");for(let a of s)n.push(` - ${a}`)}if(i?.length){n.push("globs:");for(let a of i)n.push(` - ${a}`)}return n.push("---"),`${n.join(`
|
|
2
2
|
`)}
|
|
3
3
|
|
|
4
4
|
${t}`}async function It(o){let{loadLocalSkills:e}=await import("./loader-EVHZ2R73.js");return e(o)}async function Ot(o,e,t,s,i){let a=[{role:"system",content:`You are a skill author for the Agent Skills ecosystem (skills.sh).
|