agentix-cli 0.138.0 → 0.138.1

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.
Files changed (31) hide show
  1. package/dist/{agent-L5CJF3GH.js → agent-BLRZVUG4.js} +2 -2
  2. package/dist/{board-dashboard-33NGOGWC.js → board-dashboard-42C7GGD7.js} +119 -119
  3. package/dist/board-dashboard-42C7GGD7.js.map +1 -0
  4. package/dist/{chunk-4HHHVWDB.js → chunk-6XMISPQD.js} +16 -16
  5. package/dist/chunk-6XMISPQD.js.map +1 -0
  6. package/dist/{chunk-TVW5ZKJY.js → chunk-ADYTED3R.js} +2 -2
  7. package/dist/{chunk-GAIXI26T.js → chunk-AOV5RMFH.js} +2 -2
  8. package/dist/{chunk-7YZL5MUL.js → chunk-BKSWOMAM.js} +2 -2
  9. package/dist/{chunk-UPNKRCFX.js → chunk-J5FNCTG2.js} +5 -5
  10. package/dist/{chunk-CZZJEFUM.js → chunk-JAML6222.js} +2 -2
  11. package/dist/{chunk-7DYVNET6.js → chunk-YMX3QCV7.js} +1 -1
  12. package/dist/chunk-YMX3QCV7.js.map +1 -0
  13. package/dist/cli.js +1 -1
  14. package/dist/index.d.ts +4 -0
  15. package/dist/index.js +1 -1
  16. package/dist/{program-KMUCHLDU.js → program-5RLTC6CR.js} +4 -4
  17. package/dist/{push-bridge-276ZLSUT.js → push-bridge-P7HH25VN.js} +2 -2
  18. package/dist/{registry-IUNSHCOL.js → registry-RH5NFDL7.js} +2 -2
  19. package/package.json +1 -1
  20. package/dist/board-dashboard-33NGOGWC.js.map +0 -1
  21. package/dist/chunk-4HHHVWDB.js.map +0 -1
  22. package/dist/chunk-7DYVNET6.js.map +0 -1
  23. /package/dist/{agent-L5CJF3GH.js.map → agent-BLRZVUG4.js.map} +0 -0
  24. /package/dist/{chunk-TVW5ZKJY.js.map → chunk-ADYTED3R.js.map} +0 -0
  25. /package/dist/{chunk-GAIXI26T.js.map → chunk-AOV5RMFH.js.map} +0 -0
  26. /package/dist/{chunk-7YZL5MUL.js.map → chunk-BKSWOMAM.js.map} +0 -0
  27. /package/dist/{chunk-UPNKRCFX.js.map → chunk-J5FNCTG2.js.map} +0 -0
  28. /package/dist/{chunk-CZZJEFUM.js.map → chunk-JAML6222.js.map} +0 -0
  29. /package/dist/{program-KMUCHLDU.js.map → program-5RLTC6CR.js.map} +0 -0
  30. /package/dist/{push-bridge-276ZLSUT.js.map → push-bridge-P7HH25VN.js.map} +0 -0
  31. /package/dist/{registry-IUNSHCOL.js.map → registry-RH5NFDL7.js.map} +0 -0
@@ -1,4 +1,4 @@
1
- import{a as Re,b as w,c as z,d as Pe,e as ie,f as se,g as M,h as le,i as N,j as O,n as De,o as ze,p as _e,q as We}from"./chunk-H4NSB54D.js";import{b as oe}from"./chunk-MTX4UPNB.js";import{e as Ee,i as Te}from"./chunk-QAWKN2N4.js";import{c as Ie,d as ae,e as T,f as re,g as B}from"./chunk-B2QYMUTD.js";import{a as G,b as Ce}from"./chunk-AGQYUOZY.js";import{a as Se}from"./chunk-7LN4VKDU.js";import{a as Ae}from"./chunk-IMLAPB7G.js";import{i as ne,k as ke}from"./chunk-AKWBDCMU.js";import{b as xe}from"./chunk-7DYVNET6.js";import{c as ye,e as we}from"./chunk-LQE73AZR.js";import{b as $e}from"./chunk-MRIVENBY.js";import{G as K}from"./chunk-7V73QTQ7.js";import{a as L,b as F}from"./chunk-JIJDBCV7.js";import{a as ve}from"./chunk-TFH6S7IT.js";import{a as be}from"./chunk-ROLSSYXE.js";import{A as me,Aa as te,E as dt,V as fe,aa as ct,pa as ee,ra as H,sa as he,z as Z}from"./chunk-HJCFLGVT.js";import{existsSync as j,readFileSync as Oe,writeFileSync as Ue,appendFileSync as ut,mkdirSync as mt}from"fs";import{dirname as ft,resolve as _}from"path";import{fileURLToPath as ht}from"url";import{hostname as bt}from"os";import{spawn as vt}from"child_process";function Me(e,t){let n=e.configExists?e.agentCount===0?"Add your first agent":"Add another agent":"Set up your team",a=`<header class="ax-topbar">
1
+ import{a as Re,b as w,c as z,d as Pe,e as ie,f as se,g as M,h as le,i as N,j as O,n as De,o as ze,p as _e,q as We}from"./chunk-H4NSB54D.js";import{b as oe}from"./chunk-MTX4UPNB.js";import{e as Ee,i as Te}from"./chunk-QAWKN2N4.js";import{c as Ie,d as ae,e as T,f as re,g as B}from"./chunk-B2QYMUTD.js";import{a as G,b as Ce}from"./chunk-AGQYUOZY.js";import{a as Se}from"./chunk-7LN4VKDU.js";import{a as Ae}from"./chunk-IMLAPB7G.js";import{i as ne,k as ke}from"./chunk-AKWBDCMU.js";import{b as xe}from"./chunk-YMX3QCV7.js";import{c as ye,e as we}from"./chunk-LQE73AZR.js";import{b as $e}from"./chunk-MRIVENBY.js";import{G as K}from"./chunk-7V73QTQ7.js";import{a as L,b as F}from"./chunk-JIJDBCV7.js";import{a as ve}from"./chunk-TFH6S7IT.js";import{a as be}from"./chunk-ROLSSYXE.js";import{A as me,Aa as te,E as dt,V as fe,aa as ct,pa as ee,ra as H,sa as he,z as Z}from"./chunk-HJCFLGVT.js";import{existsSync as j,readFileSync as Oe,writeFileSync as Ue,appendFileSync as ut,mkdirSync as mt}from"fs";import{dirname as ft,resolve as _}from"path";import{fileURLToPath as ht}from"url";import{hostname as bt}from"os";import{spawn as vt}from"child_process";function Me(e,t){let n=e.configExists?e.agentCount===0?"Add your first agent":"Add another agent":"Set up your team",a=`<header class="ax-topbar">
2
2
  <div class="ax-topbar__left">
3
3
  <div class="ax-brand">
4
4
  <span class="ax-brand__mark">AX</span>
@@ -858,4 +858,4 @@ tr:hover td { background: var(--bg-hover); }
858
858
  WHERE person = ? AND state IN (${n.map(()=>"?").join(",")})
859
859
  ${a}`).all(t,...n,...o).map(i=>({id:i.id,state:i.state,channel:i.channel,agentId:i.agent_id,text:i.text,createdAt:i.created_at})):[]}function ga(e,t){return et(e,t,Z,"ORDER BY created_at")}function ua(e,t,n=50){return et(e,t,[...Z,...me],"ORDER BY created_at DESC, rowid DESC LIMIT ?",Math.max(1,Math.min(n,500)))}ct();var ue="member:",Yt=90,Vt="members",Xt="tailscale-user-login",Qt=400,Zt=60*60*1e3;function en(e){let t=e.scopes.find(n=>n.startsWith(ue));return t?t.slice(ue.length):null}function nt(e,t){if(!e)return null;let n=t.verify(e),a=n?en(n):null;return n&&a?{rec:n,personId:a}:null}function ya(e,t){let n=e.people().find(s=>s.id===t);if(!n)return{ok:!1,error:`No person "${t}". Add them first: agentx people add ${t} --name "\u2026"`};let{token:a,record:o}=e.tokens.create({name:`${n.name} (machine not paired yet)`,scopes:[`${ue}${n.id}`],expiresInDays:Yt}),{code:r,expiresAt:i}=e.codes.create({token:a,tokenId:o.id,name:n.id});return e.members.log({person:n.id,device:o.id,event:"invited"}),{ok:!0,code:r,expiresAt:i,tokenId:o.id,person:n}}var tn=Math.round(ye/6e4);function nn(e){return e==="client"?"Your project":"My work"}function wa(e){let t=nn(e.person.role),n=e.person.role==="client"?`I use AgentX to keep track of the work I do for you. It has a page for you, "${t}": what you asked us for, and where each request stands.`:`I use AgentX to give our AI agents their jobs. It has a page for you, "${t}": what you asked the agents for, and where each request stands.`;return[`Hi ${e.person.name},`,"",n,"","To open it:","1. Accept the Tailscale share I sent you. Tailscale is a small program that connects your computer to mine, privately.",`2. Open ${e.origin.replace(/\/+$/,"")}/member in Edge or Chrome, give your computer a name and type this code: ${we(e.code)}`,` The code works once, for ${tn} minutes. If it has stopped working, tell me and I will send you a new one.`,"","I then approve your machine, and the page opens by itself."].join(`
860
860
  `)}var an="The private network says someone else is connecting from this machine. Ask the person who invited you for a new code.",rn="Too many machines are waiting for the owner's answer. Try again later.",tt="That code didn't work. Check it, or ask the person who invited you for a new one.",at=(e,t)=>{let n=e.headers[t];return(Array.isArray(n)?n[0]:n||"").trim()};function rt(e){let t=e.socket?.remoteAddress||"";return t==="127.0.0.1"||t==="::1"||t==="::ffff:127.0.0.1"}function on(e){if(!rt(e))return null;let t=at(e,Xt).toLowerCase();return t?t.slice(0,80):null}function sn(e){let t=e.socket?.remoteAddress||"unknown";if(!rt(e))return t;let n=at(e,"x-forwarded-for").split(",").pop().trim();return/^[0-9a-fA-F:.]{2,45}$/.test(n)?n:t}function ln(e){return typeof e=="string"?e.replace(/[^\p{L}\p{N} ._'()-]/gu," ").replace(/\s+/g," ").trim().slice(0,60):""}function dn(e){return e.identities.map(fe).filter(t=>!!t&&t.channel==="tailscale").map(t=>t.value)}async function ka(e,t){let n=Date.now(),a=t.now??Date.now,o=t.log??(b=>console.log(b)),r=sn(e),i=t.limiter.retryAfter(r);if(i>0)return o(`[member] pair-code refused from ${r}: locked out for ${i}s more`),{status:429,body:{error:"too many attempts",retryAfter:i},retryAfter:i};let s=null,l="";try{let b=await xe(e,2048);s=b.code,l=ln(b.machine)}catch{}let c=t.codes.redeem(s),d=c?nt(c.token,t.tokens):null;if(await pn(n,t.minMs??Qt),!c||!d)return t.limiter.fail(r),o(`[member] pair-code failed from ${r}`),{status:401,body:{error:tt}};t.limiter.succeed(r);let{rec:m,personId:p}=d,k=t.people().find(b=>b.id===p);if(!k)return t.tokens.revoke(m.id),t.members.log({person:p,device:m.id,event:"refused",address:r,detail:"person no longer listed"}),o(`[member] pair-code for ${p} refused from ${r}: person no longer listed`),{status:403,body:{error:tt}};let u=on(e),f=dn(k);if(f.length&&(!u||!f.includes(u)))return t.tokens.revoke(m.id),t.members.log({person:p,device:m.id,event:"refused",address:r,detail:`network login ${u??"missing"}; expected ${f.join(" or ")}`}),o(`[member] ${p}: pairing from ${r} refused: the network says "${u??"nobody"}", expected ${f.join(" or ")}`),{status:403,body:{error:an}};let I=l||"Unnamed machine",x=k.name.slice(0,40),v=ke(t.root,{title:`New machine for ${x}`,ask:`From ${r}, ${u?`network login ${u}`:"no network login reported"}. Machine name, as typed there: "${I}". Let it see ${x}'s own work?`,recommend:`Yes if ${x} told you they just paired this machine. No if you did not expect it.`,if_silent:"discard",raised_by:Vt},{now:a()});return v.ok?(t.members.add({tokenId:m.id,personId:p,name:I,state:"pending",cardId:v.card.id,address:r,...u?{network:u}:{},createdAt:new Date(a()).toISOString()}),t.members.log({person:p,device:m.id,event:"paired",address:r,detail:I}),o(`[member] ${p} paired "${I}" from ${r}; waiting for the owner (card ${v.card.id})`),{status:200,body:{person:p,name:I,state:"pending"},token:c.token}):(t.tokens.revoke(m.id),t.members.log({person:p,device:m.id,event:"refused",address:r,detail:v.error}),o(`[member] ${p}: pairing from ${r} refused: ${v.error}`),{status:503,body:{error:rn}})}var Q="this machine is not paired",cn="waiting for the owner to approve this machine";function ot(e){return e?e.status==="decided"?e.verdict??null:e.status==="expired"?"no":null:null}function $a(e,t){return t.state==="pending"&&t.cardId?ot(ne(e,t.cardId)):null}function Aa(e,t,n){let a=t.now??Date.now,o=t.log??(d=>console.log(d)),r=nt(e,t.tokens);if(!r)return{ok:!1,status:401,error:Q};let{rec:i,personId:s}=r,l=t.members.byToken(i.id);if(!l||l.state==="removed"||l.personId!==s)return{ok:!1,status:401,error:Q};if(t.people&&!t.people().some(d=>d.id===s))return it(t,i.id,"person no longer listed"),o(`[member] ${s}: "${l.name}" ended: person no longer listed`),{ok:!1,status:401,error:Q};if(l.state==="pending"){let d=l.cardId?ne(t.root,l.cardId):null,m=ot(d);if(m==="yes")l=t.members.update(i.id,{state:"active",approvedAt:new Date(a()).toISOString()})??l,t.members.log({person:s,device:i.id,event:"approved",detail:d?.decided_by}),o(`[member] ${s}: "${l.name}" approved`);else if(m==="no"){let p=d?.status==="expired"?"the owner did not answer in time":"the owner said no";return t.tokens.revoke(i.id),t.members.update(i.id,{state:"removed",removedAt:new Date(a()).toISOString(),removedReason:p}),t.members.log({person:s,device:i.id,event:"refused",detail:p}),o(`[member] ${s}: "${l.name}" refused: ${p}`),{ok:!1,status:401,error:Q}}else return{ok:!1,status:403,error:cn,waiting:!0}}let c=l.lastSeenAt?Date.parse(l.lastSeenAt):0;return n&&(a()-c>=Zt||l.lastAddress!==n)&&(l=t.members.update(i.id,{lastSeenAt:new Date(a()).toISOString(),lastAddress:n})??l,t.members.log({person:s,device:i.id,event:"signed-in",address:n})),{ok:!0,device:l,personId:s,rec:i}}function it(e,t,n="removed by the owner"){let a=e.members.byToken(t);if(!a)return null;e.tokens.revoke(t);let o=e.members.update(t,{state:"removed",removedAt:new Date((e.now??Date.now)()).toISOString(),removedReason:n});return e.members.log({person:a.personId,device:t,event:"removed",detail:n}),o}function Sa(e,t){return e.members.devices(t).filter(n=>n.state!=="removed").map(n=>it(e,n.tokenId,"person removed by the owner")).filter(n=>!!n)}async function pn(e,t){let n=e+t-Date.now();n>0&&await new Promise(a=>setTimeout(a,n))}var st=["gitlab","github"];function gn(e,t,n){let a=String(t||"").trim().toLowerCase();if(!st.includes(a))throw new Error(`Request status works on ${st.join(" and ")}, not on "${t}".`);e.requestStatus=e.requestStatus&&typeof e.requestStatus=="object"?e.requestStatus:{};let o=Array.isArray(e.requestStatus.channels)?e.requestStatus.channels.map(r=>String(r).toLowerCase()):[];return e.requestStatus.channels=n?[...new Set([...o,a])]:o.filter(r=>r!==a),`request status on ${a} is ${n?"on":"off"}`}function Ea(e){return Array.isArray(e?.requestStatus?.channels)?e.requestStatus.channels.map(t=>String(t).toLowerCase()):[]}function Ta(e){let{summary:t}=G(n=>gn(n,e?.channel,!!e?.enabled));return{summary:t}}function Pa(e){return new Set(Object.entries(e).filter(([,t])=>t?.wiki?.absorb?.enabled===!1).map(([t])=>t))}function Da(e,t){return t.only?{agents:[t.only],skipped:[]}:{agents:e.filter(n=>!t.off.has(n)),skipped:e.filter(n=>t.off.has(n))}}function za(e,t){return`absorb is off for this agent (agents.${e}.wiki.absorb.enabled); skipped.${e===t?" It reads the wiki notes inbox, so the inbox was not read.":""} Use --agent ${e} to run it anyway.`}function _a(e,t){if(t){if(!e.wiki?.absorb)return;delete e.wiki.absorb.enabled,Object.keys(e.wiki.absorb).length===0&&delete e.wiki.absorb,Object.keys(e.wiki).length===0&&delete e.wiki;return}e.wiki??={},e.wiki.absorb??={},e.wiki.absorb.enabled=!1}var un="https://ntfy.sh";function Ma(e){return{enabled:!!e?.enabled,server:e?.server||un,topicSet:!!e?.topic,tokenSet:!!e?.token}}function Na(e,t){let n={...e??{}};if("enabled"in t&&(n.enabled=!!t.enabled),"server"in t){let a=String(t.server).trim().replace(/\/+$/,"");if(!/^https?:\/\/\S+$/.test(a))throw new Error("ntfy server must be an http(s) URL");n.server=a}if("topic"in t){let a=String(t.topic).trim();if(!a)throw new Error("ntfy topic cannot be empty");n.topic=a}if("token"in t){let a=String(t.token??"").trim();a?n.token=a:delete n.token}if(n.enabled&&!n.topic)throw new Error("set a topic before enabling ntfy");return n}export{Be as a,An as b,Sn as c,In as d,Pn as e,Dn as f,zn as g,pa as h,ga as i,ua as j,Yt as k,ya as l,tn as m,nn as n,wa as o,sn as p,ka as q,$a as r,Aa as s,it as t,Sa as u,st as v,gn as w,Ea as x,Ta as y,Pa as z,Da as A,za as B,_a as C,Ma as D,Na as E,Ht as F,ta as G,sa as H,la as I};
861
- //# sourceMappingURL=chunk-TVW5ZKJY.js.map
861
+ //# sourceMappingURL=chunk-ADYTED3R.js.map
@@ -48,7 +48,7 @@ The "modified" field is optional and can contain updated values to pass forward.
48
48
  ... (output truncated)`:i;return s.exitCode!==0?{tool_use_id:e.id,content:`Command exited with code ${s.exitCode}:
49
49
  ${c}`,is_error:!0}:{tool_use_id:e.id,content:c||"(no output)"}}async editFile(e){let t=String(e.input.path||""),o=e.input.edits,n=ge.resolve(this.cwd,t);if(!o||o.length===0)return{tool_use_id:e.id,content:"No edits provided.",is_error:!0};let s=await W.checkFileWrite(t);if(s==="deny")return{tool_use_id:e.id,content:`File write blocked by permissions: ${t}`,is_error:!0};if(s==="skip")return{tool_use_id:e.id,content:`File write skipped (plan mode): ${t}`};if(f.has("pre:file-write")){let a=await f.execute("pre:file-write",{event:"pre:file-write",file:n,cwd:this.cwd});if(a.blocked)return{tool_use_id:e.id,content:a.message||`File edit blocked by pre:file-write hook: ${t}`,is_error:!0}}let i=await re.readFile(n,"utf8"),c=[];for(let a of o)i.includes(a.old_text)?(i=i.replace(a.old_text,a.new_text),c.push(`Replaced: "${a.old_text.slice(0,40)}..."`)):c.push(`Not found: "${a.old_text.slice(0,40)}..."`);return this.options.dryRun||await re.writeFile(n,i,"utf8"),f.has("post:file-write")&&await f.execute("post:file-write",{event:"post:file-write",file:n,fileContent:i,cwd:this.cwd}),{tool_use_id:e.id,content:`Edited ${t}:
50
50
  ${c.join(`
51
- `)}`}}async createFiles(e){let t=e.input,o=t.files||[];return{tool_use_id:e.id,content:t.summary||`Queued ${o.length} file(s) for creation.`,files:o}}async spawnAgent(e){let t=String(e.input.agent_id||""),o=String(e.input.prompt||""),n=Number(e.input.timeout_seconds)||300;if(!t||!o)return{tool_use_id:e.id,content:"agent_id and prompt are required.",is_error:!0};try{let{SubAgentManager:s}=await import("./subagent-XY5N7TUU.js"),{getGlobalRegistry:i}=await import("./registry-IUNSHCOL.js"),c=i();if(!c)return{tool_use_id:e.id,content:"Sub-agent spawning requires the daemon to be running.",is_error:!0};let p=await new s(c).spawn({targetAgentId:t,prompt:o,parentAgentId:"orchestrator",timeout:n*1e3});return p.success?{tool_use_id:e.id,content:`Sub-agent "${t}" completed (${Math.round(p.duration/1e3)}s):
51
+ `)}`}}async createFiles(e){let t=e.input,o=t.files||[];return{tool_use_id:e.id,content:t.summary||`Queued ${o.length} file(s) for creation.`,files:o}}async spawnAgent(e){let t=String(e.input.agent_id||""),o=String(e.input.prompt||""),n=Number(e.input.timeout_seconds)||300;if(!t||!o)return{tool_use_id:e.id,content:"agent_id and prompt are required.",is_error:!0};try{let{SubAgentManager:s}=await import("./subagent-XY5N7TUU.js"),{getGlobalRegistry:i}=await import("./registry-RH5NFDL7.js"),c=i();if(!c)return{tool_use_id:e.id,content:"Sub-agent spawning requires the daemon to be running.",is_error:!0};let p=await new s(c).spawn({targetAgentId:t,prompt:o,parentAgentId:"orchestrator",timeout:n*1e3});return p.success?{tool_use_id:e.id,content:`Sub-agent "${t}" completed (${Math.round(p.duration/1e3)}s):
52
52
 
53
53
  ${p.content}`}:{tool_use_id:e.id,content:`Sub-agent "${t}" failed: ${p.error}`,is_error:!0}}catch(s){return{tool_use_id:e.id,content:`Failed to spawn sub-agent: ${s.message}`,is_error:!0}}}async askUser(e){let t=String(e.input.question||""),o=e.input.options,n=t;return o?.length&&(n+=`
54
54
  Options: ${o.join(", ")}`),{tool_use_id:e.id,content:"Question sent to user.",followUp:n}}};async function Ae(r){let{provider:e,systemPrompt:t,messages:o,providerOptions:n,cwd:s,maxIterations:i=20,enabledTools:c,interactive:a=!0,overwrite:p=!1,dryRun:l=!1,onProgress:d,abortSignal:u}=r,m=u?{...n,abortSignal:u}:n;if(!e.generateRaw)return dt(r);let I=new se(s,{interactive:a,overwrite:p,dryRun:l,acmeContext:r.acmeContext,abortSignal:u}),D=be(c);if(r.acmeContext)for(let g of at)D.push({name:g.name,description:g.description,input_schema:g.input_schema});let E=new Set;if(r.mcpTools?.length)for(let g of r.mcpTools)D.push({name:g.name,description:g.description,input_schema:g.input_schema}),E.add(g.name);let C=o.filter(g=>g.role!=="system").map(g=>({role:g.role,content:g.content})),B=[],G=0,F=0,A=0,O="",j,_=0;for(;_<i;){if(_++,u?.aborted)throw new Error("cancelled");d?.({type:"iteration_start",iteration:_}),b.step(_,`Agentic loop iteration (${D.length} tools available)`);let g,M=!!e.generateRawStream&&!!d;try{if(M){let T=null,U=null,v="";for await(let x of e.generateRawStream(C,t,D,m))x.type==="text_delta"?(v+=x.text,d?.({type:"text_delta",text:x.text})):x.type==="thinking_delta"?d?.({type:"thinking_delta",text:x.text}):x.type==="raw_result"?T=x.result:x.type==="error"&&(U=x.error);if(U&&!T)throw new Error(U);if(!T)throw new Error("generateRawStream returned no raw_result event");g=T,g._streamedText=v}else g=await e.generateRaw(C,t,D,m)}catch(T){if(T.message?.includes("not available"))return dt(r);throw T}G+=g.usage.input_tokens+g.usage.output_tokens,F+=g.usage.input_tokens,A+=g.usage.output_tokens;let P=g._streamedText;for(let T of g.content)T.type==="text"&&(O+=T.text,P===void 0&&d?.({type:"text_delta",text:T.text}));if(P!==void 0&&delete g._streamedText,g.stop_reason==="end_turn"||g.stop_reason==="max_tokens")break;if(g.stop_reason==="tool_use"){let T=g.content.filter(v=>v.type==="tool_use");if(T.length===0)break;C.push({role:"assistant",content:g.content});let U=[];for(let v of T){d?.({type:"tool_call",name:v.name,id:v.id,input:v.input}),b.step(_,`Tool call: ${v.name}`);let x;if(E.has(v.name)&&r.mcpDispatch){let h=await r.mcpDispatch(v.name,v.input);x={tool_use_id:v.id,content:h.content,is_error:h.isError}}else x=await I.execute({name:v.name,id:v.id,input:v.input});d?.({type:"tool_result",name:v.name,id:v.id,content:x.content.slice(0,200),is_error:x.is_error}),x.files?.length&&(B.push(...x.files),d?.({type:"files_created",files:x.files})),x.followUp&&(j=x.followUp),U.push({type:"tool_result",tool_use_id:x.tool_use_id,content:x.content,is_error:x.is_error})}if(C.push({role:"user",content:U}),j)break;continue}break}return d?.({type:"complete",iterations:_,totalTokens:G}),{files:B,content:O,followUp:j,tokensUsed:G,inputTokens:F||void 0,outputTokens:A||void 0,iterations:_}}async function dt(r){let{provider:e,systemPrompt:t,messages:o,providerOptions:n,maxIterations:s=5}=r,c=[{role:"system",content:t+`
@@ -123,4 +123,4 @@ ${r.projectInstructions}`),r.memoryContext&&o.push(r.memoryContext),o.push(`# Ou
123
123
  Generate output appropriate for: ${e}. Use the \`create_files\` tool to output all files.`),o.join(`
124
124
 
125
125
  `)}export{qe as a,Vt as b,Yt as c,We as d,ze as e,Ve as f,Ye as g,Pe as h,ee as i,Re as j,le as k,te as l,Tt as m,oe as n,Mt as o,f as p,et as q,tt as r,Me as s,de as t,W as u,ne as v,it as w,Ee as x,$e as y,se as z,mt as A,Zn as B,er as C};
126
- //# sourceMappingURL=chunk-GAIXI26T.js.map
126
+ //# sourceMappingURL=chunk-AOV5RMFH.js.map
@@ -1,4 +1,4 @@
1
- import{a as Re}from"./chunk-GTJIKXDB.js";import{a as w}from"./chunk-7LN4VKDU.js";import{a as ne}from"./chunk-IMLAPB7G.js";import{q as Kt}from"./chunk-S2GAEH2F.js";import{f as Yt,g as Ae,i as V,j as q,l as Zt}from"./chunk-AKWBDCMU.js";import{b as Jt}from"./chunk-7DYVNET6.js";import{t as Xt,u as Gt}from"./chunk-6VP2KMUM.js";import{d as Ht,e as zt}from"./chunk-AQASR6KR.js";import{X as Nt,Z as te,_ as ve,aa as $e,b as Se}from"./chunk-7V73QTQ7.js";import{a as Vt,b as qt,d as Bt}from"./chunk-Y4CYQV7G.js";import{a as Lt,b as Ot}from"./chunk-SHEUCITK.js";import{g as Mt,h as jt,i as Wt,k as Ft,l as Ut}from"./chunk-6AUWEL6V.js";import{q as Pt}from"./chunk-DBJUGKX2.js";import{a as Ct,b as Dt}from"./chunk-JIJDBCV7.js";import{Aa as Tt,B as $t,C as At,D as Rt,E as _t,ka as xe,n as ee,o as St,p as vt,q as Jr,ra as It,sa as Et}from"./chunk-HJCFLGVT.js";import{a as we,h as Yr}from"./chunk-BRK6M6LA.js";import{f as ke,n as Zr}from"./chunk-UIBUZ2N3.js";import{existsSync as Qr,readdirSync as ei,readFileSync as ti,statSync as ni}from"fs";import{resolve as ri}from"path";function Qt(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let o of e){let a=s.get(o.workflowId);a?a.push(o):s.set(o.workflowId,[o])}return t.map(o=>{let a=s.get(o.id)??[],l=a.filter(f=>n-f.at<=r),c=a.filter(f=>n-f.at>r&&n-f.at<=r*2),u=l.filter(f=>f.status==="failed").length,d=a.filter(f=>f.status==="paused").length,p=a.length?Math.max(...a.map(f=>f.at)):null,g=a.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:g,lastRunAt:p,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((o,a)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[o.state]-l[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var re=new Map;function Ea(t,e=1e3){if(!Qr(t))return[];let n=ei(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=ri(t,s);return{path:o,mtime:ni(o).mtimeMs}}).sort((s,o)=>o.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of re.keys())i.has(s)||re.delete(s);let r=[];for(let{path:s,mtime:o}of n){let a=re.get(s);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=ii(s,o);re.set(s,{mtime:o,summary:l}),l&&r.push(l)}return r}function ii(t,e){try{let n=ti(t,"utf-8").split(`
1
+ import{a as Re}from"./chunk-GTJIKXDB.js";import{a as w}from"./chunk-7LN4VKDU.js";import{a as ne}from"./chunk-IMLAPB7G.js";import{q as Kt}from"./chunk-S2GAEH2F.js";import{f as Yt,g as Ae,i as V,j as q,l as Zt}from"./chunk-AKWBDCMU.js";import{b as Jt}from"./chunk-YMX3QCV7.js";import{t as Xt,u as Gt}from"./chunk-6VP2KMUM.js";import{d as Ht,e as zt}from"./chunk-AQASR6KR.js";import{X as Nt,Z as te,_ as ve,aa as $e,b as Se}from"./chunk-7V73QTQ7.js";import{a as Vt,b as qt,d as Bt}from"./chunk-Y4CYQV7G.js";import{a as Lt,b as Ot}from"./chunk-SHEUCITK.js";import{g as Mt,h as jt,i as Wt,k as Ft,l as Ut}from"./chunk-6AUWEL6V.js";import{q as Pt}from"./chunk-DBJUGKX2.js";import{a as Ct,b as Dt}from"./chunk-JIJDBCV7.js";import{Aa as Tt,B as $t,C as At,D as Rt,E as _t,ka as xe,n as ee,o as St,p as vt,q as Jr,ra as It,sa as Et}from"./chunk-HJCFLGVT.js";import{a as we,h as Yr}from"./chunk-BRK6M6LA.js";import{f as ke,n as Zr}from"./chunk-UIBUZ2N3.js";import{existsSync as Qr,readdirSync as ei,readFileSync as ti,statSync as ni}from"fs";import{resolve as ri}from"path";function Qt(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let o of e){let a=s.get(o.workflowId);a?a.push(o):s.set(o.workflowId,[o])}return t.map(o=>{let a=s.get(o.id)??[],l=a.filter(f=>n-f.at<=r),c=a.filter(f=>n-f.at>r&&n-f.at<=r*2),u=l.filter(f=>f.status==="failed").length,d=a.filter(f=>f.status==="paused").length,p=a.length?Math.max(...a.map(f=>f.at)):null,g=a.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:g,lastRunAt:p,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((o,a)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[o.state]-l[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var re=new Map;function Ea(t,e=1e3){if(!Qr(t))return[];let n=ei(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=ri(t,s);return{path:o,mtime:ni(o).mtimeMs}}).sort((s,o)=>o.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of re.keys())i.has(s)||re.delete(s);let r=[];for(let{path:s,mtime:o}of n){let a=re.get(s);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=ii(s,o);re.set(s,{mtime:o,summary:l}),l&&r.push(l)}return r}function ii(t,e){try{let n=ti(t,"utf-8").split(`
2
2
  `).filter(Boolean);if(!n.length)return null;let i=JSON.parse(n[0]),r=i.run?.workflowId;if(!r)return null;let s=i.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),l=a.status??a.run?.status;if(l){s=l;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var si={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},oi=(t,e,n)=>{try{return Pt(t,e,n)}catch{return null}},en=864e5;function Pa(t){let e=t.now??Date.now(),n={...si,...t.thresholds},i=t.nextFire??oi,r=[];for(let a of t.crons){let l=t.cronRuns.get(a.id)??[],c=a.timezone||"UTC",u=l.map(g=>({at:Date.parse(g.startedAt),status:g.status})),d=l[0],p={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,k.text),trigger:{schedule:$(a.schedule,k.text),timezone:c},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?_e(a.nextRun)??_e(i(a.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:pi(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(g=>g.status==="success")?.startedAt??null,consecutiveFailures:tn(u),sampledRuns:l.length,flags:[],attention:null};p.flags=nn(p,u,a.schedule,c,null,e,n,i),r.push(rn(p))}let s=new Map(Qt(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let l=o.get(a.workflowId);l?l.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let l=a.nodes.find(I=>I.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=a.state||"active",d=u==="active",p=(o.get(a.id)??[]).slice().sort((I,ye)=>ye.at-I.at),g=p.map(I=>({at:I.at,status:ci(I.status)})),f=g[0],h=l.type==="trigger.cron",b=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",M={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,k.text),trigger:h?{schedule:$(b,k.text),timezone:C}:{event:$(typeof c.event=="string"?c.event:"",k.text),filters:di(c.filter,a)},agent:ui(a),enabled:d,state:u,nextRunAt:h&&d&&b?_e(i(b,new Date(e),C)):null,lastRun:f?{at:new Date(f.at).toISOString(),status:f.status}:null,lastSuccessAt:(()=>{let I=g.find(ye=>ye.status==="success");return I?new Date(I.at).toISOString():null})(),consecutiveFailures:tn(g),sampledRuns:p.length,flags:[],attention:null},Q=Date.parse(a.updated||a.created||"");M.flags=h?nn(M,g,b,C,Number.isFinite(Q)?Q:null,e,n,i):ai(M,s.get(a.id)?.state==="dormant",Number.isFinite(Q)?Q:null,e,n),r.push(rn(M))}return r.sort(li).slice(0,k.routines)}function tn(t){let e=0;for(let n of t)if(!(n.status==="running"||n.status==="paused"||n.status==="unknown"))if(n.status==="failed"||n.status==="timeout")e++;else break;return e}function nn(t,e,n,i,r,s,o,a){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let p=on(c,r,s,o);return p&&l.push(p),l}if(t.consecutiveFailures>=o.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let p=0;p<o.missedFires&&(d=a(n,u,i),!!d);p++)u=d;return d&&s>d.getTime()+o.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${o.missedFires} scheduled fires missed`}),l}function ai(t,e,n,i,r){let s=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=on(o,n,i,r);return a&&s.push(a),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),o===null?s.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&s.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),s}function on(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*en?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/en)} days`:"Disabled and never ran"}}function rn(t){let e=new Set(t.flags.map(n=>n.reason));return t.attention=e.has("failing")?"critical":e.has("overdue")||e.has("dormant")||e.has("never-ran")?"warning":e.has("disabled-long")?"info":null,t}var sn={critical:0,warning:1,info:2};function li(t,e){let n=t.attention?sn[t.attention]:3,i=e.attention?sn[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function ci(t){switch(t){case"completed":case"ok":return"success";case"failed":return"failed";case"timeout":return"timeout";case"canceled":return"canceled";case"running":return"running";case"paused":return"paused";default:return"unknown"}}function ui(t){if(t.ownerAgent)return $(t.ownerAgent,k.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?$(String(e.config.agentId),k.text):null}function di(t,e){let n=[],i=e?.project;if(i&&n.push($(`project=${i}`,k.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,s]of Object.entries(t)){let o=Array.isArray(s)?s.map(String):s==null?[]:[String(s)];o.length&&n.push($(`${r}=${o.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function _e(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function $(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function pi(t,e){return t===void 0?void 0:$(t,e)}import{mkdirSync as gi,readFileSync as fi,renameSync as mi,writeFileSync as hi}from"fs";import{resolve as bi}from"path";function an(t){return bi(Ae(t),"_state.json")}function A(t){try{let e=JSON.parse(fi(an(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{},...e?.popped&&typeof e.popped=="object"?{popped:e.popped}:{},...typeof e?.passAt=="string"?{passAt:e.passAt}:{},...Array.isArray(e?.wanted)?{wanted:e.wanted.filter(n=>typeof n=="string")}:{}}}catch{return{snoozed:{}}}}function B(t,e){gi(Ae(t),{recursive:!0});let n=an(t),i=`${n}.${process.pid}.tmp`;hi(i,JSON.stringify(e,null,2)+`
3
3
  `),mi(i,n)}function ln(t,e,n,i=Date.now()){let r=A(t),s={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>i&&(s[o]=a);s[e]=n.toISOString(),B(t,{...r,snoozed:s})}function ja(t,e){B(t,{...A(t),lastDigest:e})}function cn(t,e,n,i=Date.now()){let r=A(t),s=new Set(n),o={};for(let[l,c]of Object.entries(r.popped??{}))s.has(l)&&(o[l]=c);o[e]=new Date(i).toISOString();let a=(r.wanted??[]).filter(l=>l!==e&&s.has(l));B(t,{...r,popped:o,wanted:a})}function un(t,e){let n=A(t);B(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function Wa(t,e=Date.now()){B(t,{...A(t),popped:{},passAt:new Date(e).toISOString()})}import{existsSync as H,readdirSync as Pi,readFileSync as Ni}from"fs";import{resolve as R}from"path";import{randomBytes as gn}from"crypto";import{existsSync as wi,mkdirSync as ki,readdirSync as xi,readFileSync as Si,renameSync as fn,unlinkSync as vi,writeFileSync as $i}from"fs";import{resolve as mn}from"path";function dn(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var yi=t=>t.trim().split(`
4
4
  `).pop()?.slice(0,300)||"no output";async function pn(t,e,n,i=Re){let r=await i(t.bin,[...dn(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${yi(r.stderr||r.stdout)}`}}async function Va(t,e,n,i,r=Re){return(await r(t.bin,[...dn(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var Ai=2e3,Ri=t=>pn(t.wacli,t.to,t.text);function Ie(t){return mn(t,".agentx","whatsapp-triage","drafts")}var _i=t=>/^[a-z0-9-]{8,64}$/.test(t),ie=(t,e)=>mn(Ie(t),`${e}.json`);function hn(t,e){ki(Ie(t),{recursive:!0});let n=ie(t,e.id),i=`${n}.${process.pid}.tmp`;$i(i,JSON.stringify(e,null,2)+`
@@ -529,4 +529,4 @@ Document the arguments, commands, or files the skill expects. Example:
529
529
  claude-code ${xt(t)} --arg value
530
530
  \`\`\`
531
531
  `}Tt();var zr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Xr(t){return{...zr,...t??{},regions:{...t?.regions??{}},buffer:{...zr.buffer,...t?.buffer??{}}}}function td(t){try{return Xr(Et(t).screen)}catch{return Xr(void 0)}}var Ra=/^[a-z][\w-]*$/,Gr=["window","screen","menubar","notifications"];function Z(t,e,n,i){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${i}`);return r}var be=(t,e)=>Z(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function Kr(t){let e=typeof t=="string"?t.split(",").map(Number):[t?.x,t?.y,t?.width,t?.height].map(Number);if(e.length!==4||!e.every(Number.isFinite)||e[2]<=0||e[3]<=0)throw new Error("a region is x,y,width,height in screen points, with width and height above 0");return{x:e[0],y:e[1],width:e[2],height:e[3]}}function nd(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=be(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=be(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=be(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Z(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Z(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,o]of Object.entries(e.regions)){if(!Ra.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);o===null?delete r[s]:r[s]=Kr(o)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,s={...n.buffer??{}};"enabled"in r&&(s.enabled=!!r.enabled),"seconds"in r&&(s.seconds=Z(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Z(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=be(r.maxPixels,"buffer.maxPixels")),"region"in r&&(s.region=String(r.region).trim()),n.buffer=s}let i=n.buffer?.region;if(i!==void 0&&!Gr.includes(i)&&!n.regions?.[i])try{Kr(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Gr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{Qt as a,Ea as b,tt as c,Ks as d,Js as e,mc as f,hc as g,bc as h,ar as i,wc as j,xc as k,D as l,lr as m,k as n,Pa as o,Va as p,Ri as q,Ga as r,yn as s,A as t,ja as u,Wa as v,Ya as w,oe as x,Za as y,xn as z,il as A,z as B,wl as C,kl as D,_n as E,cr as F,$c as G,nt as H,_c as I,vr as J,eu as K,tu as L,au as M,qo as N,lu as O,Sl as P,vl as Q,$l as R,Al as S,Rl as T,_l as U,El as V,Tl as W,Wl as X,Me as Y,Fl as Z,Ul as _,X as $,G as aa,Ko as ba,bu as ca,yu as da,wu as ea,ku as fa,ct as ga,xu as ha,Fe as ia,Ue as ja,pe as ka,ms as la,bs as ma,zl as na,qe as oa,Be as pa,ys as qa,ws as ra,Xn as sa,Yn as ta,Xl as ua,Ss as va,Gl as wa,Ts as xa,Ps as ya,He as za,Ls as Aa,Zn as Ba,P as Ca,Lr as Da,Or as Ea,Mr as Fa,_u as Ga,ia as Ha,Wr as Ia,Fr as Ja,ju as Ka,Wu as La,ka as Ma,Fu as Na,Vr as Oa,ge as Pa,oc as Qa,ir as Ra,ze as Sa,Qe as Ta,gc as Ua,Bu as Va,Hu as Wa,zu as Xa,Xu as Ya,Gu as Za,Ku as _a,Ju as $a,Yu as ab,Zu as bb,zr as cb,Xr as db,td as eb,Gr as fb,nd as gb};
532
- //# sourceMappingURL=chunk-7YZL5MUL.js.map
532
+ //# sourceMappingURL=chunk-BKSWOMAM.js.map
@@ -1,4 +1,4 @@
1
- import{Ba as Vu,D as Kn,F as mu,Fa as Ju,Ga as es,Ha as ji,Ia as Xu,Ja as Ku,K as yu,Ka as zu,La as Yu,M as wu,Na as Qu,O as ku,P as _i,Q as bu,R as He,S as vu,T as zn,Ua as Zu,V as Mi,Va as eh,W as Su,X as Di,Y as tt,Z as Pu,_ as _u,a as Rd,b as Ii,ba as nt,ca as Mu,cb as Li,da as Ou,db as Fi,ea as Du,f as Ti,fa as Nu,fb as th,g as Ed,ga as ju,h as Cd,ha as Lu,i as Ge,j as Pd,ja as be,k as _d,ka as Yn,la as Ni,m as Md,ma as Fu,na as Kt,o as Od,oa as Uu,p as Kd,pa as Pe,q as zd,qa as Gu,r as Yd,ra as Wu,s as Qd,sa as Hu,t as Zd,ta as Qn,u as eu,ua as Zn,v as tu,va as Bu,w as nu,wa as qu,x as su,y as Ci}from"./chunk-7YZL5MUL.js";import{d as Td,g as xd,h as Ad}from"./chunk-LA6P3TUK.js";import{b as Cu}from"./chunk-7LN4VKDU.js";import{a as Dd}from"./chunk-ZVP6GB4G.js";import{m as Ld,n as Fd,o as Ai,p as Ce,r as Ud,s as ke}from"./chunk-S2GAEH2F.js";import{i as iu,m as Pi,n as ou,p as au,q as cu,r as lu,s as du,t as uu,u as hu}from"./chunk-UNIXYV3U.js";import{f as Ri,g as qd,h as Jn,i as vt,k as We,m as Vd,n as Jd,o as Xd,p as Ei,q as Xn}from"./chunk-AKWBDCMU.js";import{a as gu}from"./chunk-PPUN7YHA.js";import{a as pu,b as fu}from"./chunk-VZLIBDLH.js";import{b as $u,c as Iu,d as Oi,e as Tu,f as xu,g as Au,h as Ru,i as Eu}from"./chunk-EKJG63EJ.js";import{b as Vn}from"./chunk-EMGB23H5.js";import{d as Gd}from"./chunk-CZZJEFUM.js";import{g as Wd}from"./chunk-LQE73AZR.js";import{b as Hd,c as Bd}from"./chunk-2D3RYIDU.js";import{b as ru}from"./chunk-MRIVENBY.js";import{a as Nd,b as jd}from"./chunk-A5GYG56I.js";import{o as xi}from"./chunk-6VP2KMUM.js";import{A as ml,B as yl,C as wl,D as de,E as bl,F as vl,G as Sl,H as $l,I as Il,J as Tl,K as xl,L as dd,M as ud,N as hd,O as gd,P as pd,Q as fd,U as wd,a as Hc,b as gi,c as qc,ca as kd,d as Zc,e as el,f as Vt,h as fi,i as mi,j as yi,k as wi,l as tl,s as nl,t as il,u as Ze,v as ol,w as ll,x as J,z as fl}from"./chunk-4HHHVWDB.js";import{A as Zl,B as ed,C as td,D as nd,E as sd,F as rd,H as id,K as od,P as ad,Q as cd,T as ld,X as md,a as sl,ba as yd,c as al,d as cl,e as et,f as Ne,l as Al,n as Rl,p as Wl,q as Hl,r as Jl,s as Xl,t as Kl,u as zl,w as $i,x as Bn,y as Yl,z as Ql}from"./chunk-7V73QTQ7.js";import{b as Nl,c as jl,d as vi,f as Wn,g as Ll,h as Fl,i as Ul,j as Jt,k as Hn,l as Gl}from"./chunk-QSKG754X.js";import{a as ki,b as rl}from"./chunk-MEFPXHQJ.js";import{A as bd,B as qn,C as vd,h as ic,n as oc,o as Zr}from"./chunk-GAIXI26T.js";import{b as nc}from"./chunk-SFQUP3BP.js";import{a as Ue}from"./chunk-Y4CYQV7G.js";import{a as Sd,b as Xt,c as $d,d as Id}from"./chunk-LLNPKE7H.js";import{a as kt,b as bt}from"./chunk-SHEUCITK.js";import{a as El,b as bi,c as Cl,d as Pl,e as _l,i as Ml,j as Ol}from"./chunk-HF5EF335.js";import{b as kl}from"./chunk-W4YR2RO2.js";import{b as le,d as wt,f as je,g as Un,i as ue,j as Dl,k as Le,l as Fe,m as Vl,s as Si}from"./chunk-DBJUGKX2.js";import{a as Bl,b as ql}from"./chunk-JIJDBCV7.js";import{d as dl,e as ul,f as hl,g as gl,h as pl,j as Gn}from"./chunk-X5C5W3E4.js";import{c as Fn}from"./chunk-OWNQ2FD4.js";import{d as cc,e as gk,m as Fc,n as $k,q as Uc,v as Gc,y as yt,z as jn}from"./chunk-MTDVAO5C.js";import{a as Qe,b as qt,f as hi}from"./chunk-72SZI2UW.js";import{a as Ht,b as ac}from"./chunk-FCPTN6NF.js";import{c as Wc}from"./chunk-MYVHVJWZ.js";import{e as Bc}from"./chunk-6TURWSMN.js";import{d as Vc,e as Jc,f as pi,g as Ln,h as Xc,i as Kc,j as zc,k as Yc,q as Qc}from"./chunk-AV7T3SYT.js";import{a as _n,b as hk}from"./chunk-7I7IEX4S.js";import{b as sc,e as rc}from"./chunk-JHCI6XCJ.js";import{e as Ke}from"./chunk-DSYKYZMT.js";import{A as Ac,Aa as Sk,D as Rc,E as ai,F as ci,H as li,J as Ec,K as Cc,M as Bt,N as Pc,O as _c,P as Mc,Q as Oc,R as kk,U as Dc,X as Nc,Y as jc,aa as bk,ca as di,d as mt,e as dc,ea as vk,f as ti,g as pk,h as Mn,i as ni,j as On,l as ze,m as si,n as uc,o as fk,p as Dn,q as mk,r as Nn,s as hc,sa as ui,t as yk,ta as Lc,u as gc,v as pc,w as fc,z as xc}from"./chunk-HJCFLGVT.js";import{e as Ye,f as mc,g as yc,h as ri}from"./chunk-BRK6M6LA.js";import{a as wc,b as kc,c as bc,e as vc,f as ii,g as Sc,h as $c,i as oi,j as Ic,k as Tc,n as wk}from"./chunk-UIBUZ2N3.js";import{b as ei,e as lc}from"./chunk-2QNT5JDS.js";import{d as ft}from"./chunk-QIJLFPWE.js";import{existsSync as Bi,readFileSync as qi}from"fs";fc();var nh=["answer","narration","line"],sh=5e3;function rh(r){return r==="/voice/queue"||r.startsWith("/voice/queue/")}async function ih(r,e,t,n,s,i){if(n==="/voice/queue"){if(t==="GET")return{status:200,body:{...r.view(),...i?{floor:i.view()}:{}}};if(t!=="POST")return{status:405,body:{error:"GET or POST"}};let l=String(s.text??"").trim(),d=String(s.agentId??s.agent??""),u=String(s.kind??"line");if(!l||!d||!nh.includes(u))return{status:400,body:{error:`Required: text and agentId; kind is ${nh.join(" | ")}`}};if(l.length>sh)return{status:413,body:{error:`text is over ${sh} characters`}};let g=e(d);if(!g)return{status:404,body:{error:`Unknown agent: ${d}`}};let{item:m,done:f}=r.enqueue({voice:g,text:l,agentId:d,kind:u,...typeof s.floor=="string"?{floor:s.floor}:{}});return s.wait!==!0?{status:202,body:{item:m}}:{status:200,body:{item:m,played:await f}}}if(t==="POST"&&n==="/voice/queue/pause")return r.pause(),{status:200,body:r.view()};if(t==="POST"&&n==="/voice/queue/resume")return r.resume(),{status:200,body:r.view()};let[,,,o,a,c]=n.split("/");if(t!=="POST"||!o||c!==void 0)return{status:404,body:{error:"Not found"}};switch(a){case"skip":return r.skip(o)?{status:200,body:r.view()}:Ui(o);case"front":return r.front(o)?{status:200,body:r.view()}:Ui(o);case"replay":{let l=r.replay(o);return l?{status:202,body:{item:l}}:Ui(o)}default:return{status:404,body:{error:"Not found"}}}}function oh(r){let e=n=>`${n.agentId??"someone"} (${n.kind}): "${n.text.length>80?`${n.text.slice(0,79)}\u2026`:n.text}" [${n.id}]`,t=r.playing?`Speaking: ${e(r.playing)}`:r.paused?"Paused: the listener is speaking; the queue plays on after.":"Nothing is speaking.";return[...r.floor?.held?[pc(r.floor)]:[],t,...r.waiting.map((n,s)=>`${s+1}. waiting: ${e(n)}`)].join(`
1
+ import{Ba as Vu,D as Kn,F as mu,Fa as Ju,Ga as es,Ha as ji,Ia as Xu,Ja as Ku,K as yu,Ka as zu,La as Yu,M as wu,Na as Qu,O as ku,P as _i,Q as bu,R as He,S as vu,T as zn,Ua as Zu,V as Mi,Va as eh,W as Su,X as Di,Y as tt,Z as Pu,_ as _u,a as Rd,b as Ii,ba as nt,ca as Mu,cb as Li,da as Ou,db as Fi,ea as Du,f as Ti,fa as Nu,fb as th,g as Ed,ga as ju,h as Cd,ha as Lu,i as Ge,j as Pd,ja as be,k as _d,ka as Yn,la as Ni,m as Md,ma as Fu,na as Kt,o as Od,oa as Uu,p as Kd,pa as Pe,q as zd,qa as Gu,r as Yd,ra as Wu,s as Qd,sa as Hu,t as Zd,ta as Qn,u as eu,ua as Zn,v as tu,va as Bu,w as nu,wa as qu,x as su,y as Ci}from"./chunk-BKSWOMAM.js";import{d as Td,g as xd,h as Ad}from"./chunk-LA6P3TUK.js";import{b as Cu}from"./chunk-7LN4VKDU.js";import{a as Dd}from"./chunk-ZVP6GB4G.js";import{m as Ld,n as Fd,o as Ai,p as Ce,r as Ud,s as ke}from"./chunk-S2GAEH2F.js";import{i as iu,m as Pi,n as ou,p as au,q as cu,r as lu,s as du,t as uu,u as hu}from"./chunk-UNIXYV3U.js";import{f as Ri,g as qd,h as Jn,i as vt,k as We,m as Vd,n as Jd,o as Xd,p as Ei,q as Xn}from"./chunk-AKWBDCMU.js";import{a as gu}from"./chunk-PPUN7YHA.js";import{a as pu,b as fu}from"./chunk-VZLIBDLH.js";import{b as $u,c as Iu,d as Oi,e as Tu,f as xu,g as Au,h as Ru,i as Eu}from"./chunk-EKJG63EJ.js";import{b as Vn}from"./chunk-EMGB23H5.js";import{d as Gd}from"./chunk-JAML6222.js";import{g as Wd}from"./chunk-LQE73AZR.js";import{b as Hd,c as Bd}from"./chunk-2D3RYIDU.js";import{b as ru}from"./chunk-MRIVENBY.js";import{a as Nd,b as jd}from"./chunk-A5GYG56I.js";import{o as xi}from"./chunk-6VP2KMUM.js";import{A as ml,B as yl,C as wl,D as de,E as bl,F as vl,G as Sl,H as $l,I as Il,J as Tl,K as xl,L as dd,M as ud,N as hd,O as gd,P as pd,Q as fd,U as wd,a as Hc,b as gi,c as qc,ca as kd,d as Zc,e as el,f as Vt,h as fi,i as mi,j as yi,k as wi,l as tl,s as nl,t as il,u as Ze,v as ol,w as ll,x as J,z as fl}from"./chunk-6XMISPQD.js";import{A as Zl,B as ed,C as td,D as nd,E as sd,F as rd,H as id,K as od,P as ad,Q as cd,T as ld,X as md,a as sl,ba as yd,c as al,d as cl,e as et,f as Ne,l as Al,n as Rl,p as Wl,q as Hl,r as Jl,s as Xl,t as Kl,u as zl,w as $i,x as Bn,y as Yl,z as Ql}from"./chunk-7V73QTQ7.js";import{b as Nl,c as jl,d as vi,f as Wn,g as Ll,h as Fl,i as Ul,j as Jt,k as Hn,l as Gl}from"./chunk-QSKG754X.js";import{a as ki,b as rl}from"./chunk-MEFPXHQJ.js";import{A as bd,B as qn,C as vd,h as ic,n as oc,o as Zr}from"./chunk-AOV5RMFH.js";import{b as nc}from"./chunk-SFQUP3BP.js";import{a as Ue}from"./chunk-Y4CYQV7G.js";import{a as Sd,b as Xt,c as $d,d as Id}from"./chunk-LLNPKE7H.js";import{a as kt,b as bt}from"./chunk-SHEUCITK.js";import{a as El,b as bi,c as Cl,d as Pl,e as _l,i as Ml,j as Ol}from"./chunk-HF5EF335.js";import{b as kl}from"./chunk-W4YR2RO2.js";import{b as le,d as wt,f as je,g as Un,i as ue,j as Dl,k as Le,l as Fe,m as Vl,s as Si}from"./chunk-DBJUGKX2.js";import{a as Bl,b as ql}from"./chunk-JIJDBCV7.js";import{d as dl,e as ul,f as hl,g as gl,h as pl,j as Gn}from"./chunk-X5C5W3E4.js";import{c as Fn}from"./chunk-OWNQ2FD4.js";import{d as cc,e as gk,m as Fc,n as $k,q as Uc,v as Gc,y as yt,z as jn}from"./chunk-MTDVAO5C.js";import{a as Qe,b as qt,f as hi}from"./chunk-72SZI2UW.js";import{a as Ht,b as ac}from"./chunk-FCPTN6NF.js";import{c as Wc}from"./chunk-MYVHVJWZ.js";import{e as Bc}from"./chunk-6TURWSMN.js";import{d as Vc,e as Jc,f as pi,g as Ln,h as Xc,i as Kc,j as zc,k as Yc,q as Qc}from"./chunk-AV7T3SYT.js";import{a as _n,b as hk}from"./chunk-7I7IEX4S.js";import{b as sc,e as rc}from"./chunk-JHCI6XCJ.js";import{e as Ke}from"./chunk-DSYKYZMT.js";import{A as Ac,Aa as Sk,D as Rc,E as ai,F as ci,H as li,J as Ec,K as Cc,M as Bt,N as Pc,O as _c,P as Mc,Q as Oc,R as kk,U as Dc,X as Nc,Y as jc,aa as bk,ca as di,d as mt,e as dc,ea as vk,f as ti,g as pk,h as Mn,i as ni,j as On,l as ze,m as si,n as uc,o as fk,p as Dn,q as mk,r as Nn,s as hc,sa as ui,t as yk,ta as Lc,u as gc,v as pc,w as fc,z as xc}from"./chunk-HJCFLGVT.js";import{e as Ye,f as mc,g as yc,h as ri}from"./chunk-BRK6M6LA.js";import{a as wc,b as kc,c as bc,e as vc,f as ii,g as Sc,h as $c,i as oi,j as Ic,k as Tc,n as wk}from"./chunk-UIBUZ2N3.js";import{b as ei,e as lc}from"./chunk-2QNT5JDS.js";import{d as ft}from"./chunk-QIJLFPWE.js";import{existsSync as Bi,readFileSync as qi}from"fs";fc();var nh=["answer","narration","line"],sh=5e3;function rh(r){return r==="/voice/queue"||r.startsWith("/voice/queue/")}async function ih(r,e,t,n,s,i){if(n==="/voice/queue"){if(t==="GET")return{status:200,body:{...r.view(),...i?{floor:i.view()}:{}}};if(t!=="POST")return{status:405,body:{error:"GET or POST"}};let l=String(s.text??"").trim(),d=String(s.agentId??s.agent??""),u=String(s.kind??"line");if(!l||!d||!nh.includes(u))return{status:400,body:{error:`Required: text and agentId; kind is ${nh.join(" | ")}`}};if(l.length>sh)return{status:413,body:{error:`text is over ${sh} characters`}};let g=e(d);if(!g)return{status:404,body:{error:`Unknown agent: ${d}`}};let{item:m,done:f}=r.enqueue({voice:g,text:l,agentId:d,kind:u,...typeof s.floor=="string"?{floor:s.floor}:{}});return s.wait!==!0?{status:202,body:{item:m}}:{status:200,body:{item:m,played:await f}}}if(t==="POST"&&n==="/voice/queue/pause")return r.pause(),{status:200,body:r.view()};if(t==="POST"&&n==="/voice/queue/resume")return r.resume(),{status:200,body:r.view()};let[,,,o,a,c]=n.split("/");if(t!=="POST"||!o||c!==void 0)return{status:404,body:{error:"Not found"}};switch(a){case"skip":return r.skip(o)?{status:200,body:r.view()}:Ui(o);case"front":return r.front(o)?{status:200,body:r.view()}:Ui(o);case"replay":{let l=r.replay(o);return l?{status:202,body:{item:l}}:Ui(o)}default:return{status:404,body:{error:"Not found"}}}}function oh(r){let e=n=>`${n.agentId??"someone"} (${n.kind}): "${n.text.length>80?`${n.text.slice(0,79)}\u2026`:n.text}" [${n.id}]`,t=r.playing?`Speaking: ${e(r.playing)}`:r.paused?"Paused: the listener is speaking; the queue plays on after.":"Nothing is speaking.";return[...r.floor?.held?[pc(r.floor)]:[],t,...r.waiting.map((n,s)=>`${s+1}. waiting: ${e(n)}`)].join(`
2
2
  `)}var Ui=r=>({status:404,body:{error:`No such line in the queue: ${r}`}});import{resolve as Vi}from"path";vk();var Ik={name:"agentx",version:"0.1.0"},Tk=["2024-11-05","2025-03-26","2025-06-18","2025-11-25"],xk="2024-11-05";function Ak(r){return typeof r=="string"&&Tk.includes(r)?r:xk}var Rk={tools:{},elicitation:{form:{}}},Ek=0;async function ah(r,e){let t=++Ek;return st({jsonrpc:"2.0",id:`elicit-${t}`,method:"elicitation/create",params:{mode:"form",message:r,requestedSchema:e}}),new Promise(n=>{zt.set(`elicit-${t}`,s=>{s?.action==="accept"&&s.content?n(s.content):n(null)}),setTimeout(()=>{zt.has(`elicit-${t}`)&&(zt.delete(`elicit-${t}`),n(null))},6e4)})}var zt=new Map,Ck="http://localhost:18800",Gi;function Pk(){if(process.env.AGENTX_DAEMON_URL)return process.env.AGENTX_DAEMON_URL;for(let r of["agentx.json",".agentx/config.json"])try{let e=Vi(process.cwd(),r);if(!Bi(e))continue;let t=JSON.parse(qi(e,"utf-8"))?.node?.bind;if(typeof t!="string"||!t.includes(":"))continue;{let n=t.lastIndexOf(":"),s=t.slice(0,n),i=t.slice(n+1),o=!s||s==="0.0.0.0"||s==="::"||s==="*"?"127.0.0.1":s;if(i)return`http://${o}:${i}`}}catch{}return Ck}function X(){return Gi===void 0&&(Gi=Pk()),Gi}var Wi;function _k(r){try{let e=Vi(process.cwd(),".env");if(!Bi(e))return"";for(let t of qi(e,"utf-8").split(`
3
3
  `)){let n=t.trim().replace(/^export\s+/,"");if(!n.startsWith(`${r}=`))continue;let s=n.slice(r.length+1).trim();return/^(["']).*\1$/.test(s)?s.slice(1,-1):s}}catch{}return""}function Mk(r=process.env){if(r.AGENTX_TOKEN)return r.AGENTX_TOKEN;if(r.MESH_TOKEN)return r.MESH_TOKEN;let e=_k("MESH_TOKEN");if(e)return e;for(let t of["agentx.json",".agentx/config.json"])try{let n=Vi(process.cwd(),t);if(!Bi(n))continue;let s=JSON.parse(qi(n,"utf-8"))?.dashboard?.token;if(typeof s=="string"&&s)return s}catch{}return""}function Ok(){return Wi===void 0&&(Wi=Mk()),Wi}var K=(r,e)=>{let t=Ok();if(!t)return fetch(r,e);let n=new Headers(e?.headers);return n.has("Authorization")||n.set("Authorization",`Bearer ${t}`),fetch(r,{...e,headers:n})};function Hi(r=process.env){let e={};return r.AGENTX_TASK_ID&&(e.callerTaskId=r.AGENTX_TASK_ID),r.AGENTX_CHANNEL&&(e.callerChannel=r.AGENTX_CHANNEL),r.AGENTX_CHAT_ID&&(e.callerChatId=r.AGENTX_CHAT_ID),e}async function Dk(){let r=process.env.AGENTX_AGENT_ID,e=Hi();if(!(!r||!e.callerChannel||!e.callerChatId))try{let t=new URLSearchParams({channel:e.callerChannel,chatId:e.callerChatId}),n=await K(`${X()}/agents/${encodeURIComponent(r)}/intent-path?${t}`,{signal:AbortSignal.timeout(2e3)});if(!n.ok)return;let s=await n.json();return{...Array.isArray(s.path)&&s.path.length?{path:s.path}:{},...typeof s.graphWeight=="number"?{graphWeight:s.graphWeight}:{}}}catch{return}}var Nk=1e4,jk=new Set(["ECONNREFUSED","ENOTFOUND","EAI_AGAIN","EHOSTUNREACH","ENETUNREACH"]);function Lk(r,e){let t=e,n=t?.cause?.code??t?.code;if(n&&jk.has(n))return`Error: the AgentX daemon could not be reached (${n}); the message to ${r} was not sent.`;let s=t?.name==="TimeoutError"||t?.name==="AbortError"?"no answer in time":t?.message||String(e);return`Probably delivered to ${r}: the daemon did not confirm (${s}), but the request was sent and is most likely queued. Do not treat this as a failure. If unsure, send the same message again: within 10 minutes a repeat returns the existing task id instead of a second task, and delivers it if the first never arrived. A busy ${r} shows no trace until its turn starts; later, \`agentx trace list --agent ${r} --since 1h\` or the daemon log ("[send/agent]") shows it.`}var Fk=/\x1B\[[0-9;]*[A-Za-z]/g;function St(r){return r.replace(Fk,"")}async function Uk(r,e,t){let n=await K(`${X()}/recall`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent:r,channel:e,limit:Math.min(Math.max(t??30,1),100)})}),s=await n.json().catch(()=>({}));if(!n.ok)return{content:[{type:"text",text:`Error: ${s.error||n.statusText}`}]};let i=s.turns||[],o=e?`on ${e}`:"on any channel";return i.length===0?{content:[{type:"text",text:`No other messages ${o} today for ${r}.`}]}:{content:[{type:"text",text:Gk(i,!!s.hasMore)}]}}function Gk(r,e){let t=new Map;for(let s of r){let i=`${s.channel}/${s.chatId}`;t.has(i)||t.set(i,[]),t.get(i).push(s)}let n=[];for(let[s,i]of t){let o=[...i].sort((a,c)=>a.ts.localeCompare(c.ts)).map(a=>{let c=a.role==="agent"?"you":a.senderName||"user";return` [${a.ts.slice(11,16)}] ${c}: ${a.content.slice(0,300)}`});n.push(`From ${s}:
4
4
  ${o.join(`
@@ -530,7 +530,7 @@ ${l}`)}let S={agentId:o,message:k,context:{channel:w,sender:f?"opencode":"openai
530
530
 
531
531
  `)}}function $g(r){r.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"})}function Ig(r,e,t,n,s,i){r.write(`data: ${JSON.stringify({id:e,object:"chat.completion.chunk",created:t,model:n,choices:[{index:0,delta:s,finish_reason:i}]})}
532
532
 
533
- `)}function Tg(r,e,t,n,s,i){let o=i?.usage?.inputTokens??0,a=i?.usage?.outputTokens??Math.ceil(s.length/4);wo(r,200,{id:e,object:"chat.completion",created:t,model:n,choices:[{index:0,message:{role:"assistant",content:s},finish_reason:"stop"}],usage:{prompt_tokens:o,completion_tokens:a,total_tokens:o+a}})}function wo(r,e,t){r.writeHead(e,{"Content-Type":"application/json"}),r.end(JSON.stringify(t))}var an=class{module;minLevel;constructor(e,t="info"){this.module=e,this.minLevel=t}child(e){return new an(`${this.module}:${e}`,this.minLevel)}debug(e,t){this.emit("debug",e,t)}info(e,t){this.emit("info",e,t)}warn(e,t){this.emit("warn",e,t)}error(e,t){this.emit("error",e,t)}asConsoleLog(){return(...e)=>{let n=e.map(s=>typeof s=="string"?s:JSON.stringify(s)).join(" ").replace(/^\[agentx\]\s*/,"");n&&this.info(n)}}emit(e,t,n){if(an.levelOrder[e]<an.levelOrder[this.minLevel])return;let s={time:new Date().toISOString(),level:e,module:this.module,msg:t,...n},i=e==="error"?"ERROR":e==="warn"?"WARN":"",o=`[${this.module}]`,a=i?`${o} ${i}: ${t}`:`${o} ${t}`;console.error(a)}},on=an;ft(on,"levelOrder",{debug:0,info:1,warn:2,error:3});import{realpathSync as Vv,statSync as Jv}from"fs";var Et={version:"0.138.0",commit:"85bd8f9",startedAt:new Date(Date.now()-process.uptime()*1e3).toISOString()};function Xv(r,e){let t=e.mtimeMs!==null&&e.mtimeMs>Date.parse(r.startedAt),n=!!e.version&&!!r.version&&e.version!==r.version;return{newer:t||n,changedAt:e.mtimeMs===null?null:new Date(e.mtimeMs).toISOString(),version:e.version}}function Ag(){let r=null;try{r=Jv(Vv(process.argv[1])).mtimeMs}catch{}let e=Xh().version;return Xv(Et,{mtimeMs:r,version:e&&e!=="0.0.0"?e:null})}import{randomUUID as Kv}from"crypto";var Rs=class{constructor(e=new ll){this.core=e}count=0;subscribe(e,t){this.count++;let n=this.core.subscribe((i,o)=>{if(!o||!zv.includes(o.kind))return;let a={...o,rootId:i.rootId,node:i.node};Qv(e,a)&&t(a)}),s=!0;return()=>{s&&(s=!1,this.count--,n())}}publish(e){let t={id:typeof e.id=="string"?e.id:Kv(),at:typeof e.at=="string"?e.at:new Date().toISOString(),...e},{type:n,summary:s,ref:i,agentId:o}=Yv(t);this.core.publish({id:t.id,at:t.at,kind:t.kind,type:n,summary:s,ref:i,agentId:o,rootId:typeof e.rootId=="string"?e.rootId:void 0,data:t})}get size(){return this.count}},zv=["run","task","signal","mesh","channel","status"];function Yv(r){switch(r.kind){case"run":return{type:r.phase,ref:r.runId,summary:[r.workflowId,r.nodeId,r.phase,r.note].filter(Boolean).join(" ")};case"task":return{type:r.phase,ref:r.taskId,summary:`${r.title??r.taskId} ${r.phase}`};case"signal":return{type:"emitted",summary:`signal ${r.name} (${r.scope})`};case"mesh":return{type:r.delta,summary:`peer ${r.peer} ${r.delta}`};case"channel":return{type:r.direction,ref:r.messageId,agentId:r.agentId,summary:`${r.channel} ${r.direction==="in"?"inbound":"outbound"}`};case"status":return{type:"status",summary:r.message}}}function Qv(r,e){return!(r.kinds&&r.kinds.length>0&&!r.kinds.includes(e.kind)||r.workflowId&&(e.kind==="run"&&e.workflowId!==r.workflowId||e.kind==="task"&&e.workflowId!==r.workflowId||e.kind==="signal"&&e.workflowId&&e.workflowId!==r.workflowId)||r.runId&&(e.kind==="run"&&e.runId!==r.runId||e.kind==="task"&&e.runId!==r.runId)||r.actor&&(e.kind!=="task"||!(e.assignedTo?.includes(r.actor)||e.submittedBy===r.actor))||r.channel&&(e.kind!=="channel"||e.channel!==r.channel))}function Rg(r){if(!r)return;let e=["run","task","signal","mesh","channel","status"],n=r.split(",").map(s=>s.trim()).filter(Boolean).filter(s=>e.includes(s));return n.length?n:void 0}import{createHmac as Es,timingSafeEqual as Eg}from"crypto";var Cs=class{registry;config;mesh;webhookEntries;log;workflowDispatcher;hooks;constructor(e,t={},n=console.error.bind(console,"[webhook]"),s,i=[],o){this.registry=e,this.config=t,this.log=n,this.mesh=s,this.webhookEntries=i,this.hooks=o}hookEventFor(e,t){if(e==="stripe")return"on:stripe-event";if(e==="sentry")return"on:sentry-issue";if(e==="vercel")return"on:vercel-deployment";if(e==="hubspot")return"on:hubspot-event";if(e==="odoo")return"on:odoo-event";if(e==="github"){let n=(t??"").split(".")[0];return n==="issues"||n==="issue_comment"?"on:github-issue":n==="pull_request"||n==="pull_request_review"?"on:github-pr":n==="push"?"on:github-push":null}return null}async fireHookSafe(e,t,n,s){let i=this.hookEventFor(e,t);if(!i||!this.hooks||!this.hooks.has(i))return;let o={};if(e==="github"){let a=s;typeof a.sender?.login=="string"&&(o.author=a.sender.login),typeof a.repository?.full_name=="string"&&(o.repo=a.repository.full_name);let c=a.issue?.number??a.pull_request?.number;typeof c=="number"&&(o.number=c)}try{await this.hooks.execute(i,{event:i,source:e,eventType:t,agentId:n,payload:s,...o})}catch(a){this.log(`${i} hook error (non-fatal): ${a?.message??a}`)}}setWorkflowDispatcher(e){this.workflowDispatcher=e}setWebhookEntries(e){this.webhookEntries=e}async handle(e,t,n){let s=n.replace(/^\/webhook\/?/,"").split("/").filter(Boolean),i=s[0],o=s[1];if(!i){this.sendJson(t,400,{error:"Missing agent ID. Use /webhook/:agentId"});return}let{raw:a,parsed:c}=await this.readBody(e),l=o||this.detectSource(e.headers);if(process.env.AGENTX_WEBHOOK_DEBUG_HEADERS==="1"){let b={};for(let[k,S]of Object.entries(e.headers))(k.startsWith("x-hubspot")||k.startsWith("x-hub")||k.startsWith("x-github")||k.startsWith("x-gitlab")||k.startsWith("stripe")||k.startsWith("sentry")||k.startsWith("x-vercel")||k.startsWith("x-odoo")||k.startsWith("x-webhook")||k==="user-agent"||k==="content-type"||k==="host"||k==="x-forwarded-host"||k==="x-forwarded-proto"||k==="x-forwarded-for")&&(b[k]=S);this.log(`Webhook [${l}] reqUrl=${e.url} headers: ${JSON.stringify(b)}`)}let d=this.validateSignature(e.headers,a,l,i,e.url);if(d){this.log(`Webhook [${l}] -> ${i}: REJECTED (${d})`),this.sendJson(t,401,{error:d});return}let u=this.buildSummary(l,c,e.headers);this.log(`Webhook [${l}] -> ${i}: ${u.slice(0,100)}`);let g=this.extractEventType(l,c,e.headers),m=this.webhookEntries.find(b=>b.enabled&&b.agentId===i&&b.source===l),f=g&&m?.triggers?.[g]||m?.defaultWorkflow||null;if(await this.fireHookSafe(l,g,i,c),f&&this.workflowDispatcher)try{let b=await this.workflowDispatcher.dispatchWorkflow({workflowId:f,entityRef:{kind:"webhook",id:`${l}:${i}:${g??"\u2014"}:${Date.now()}`},event:{kind:"webhook",source:l,eventType:g,payload:c},trigger:{source:l}});this.log(`Webhook [${l}/${g??"\u2014"}] -> workflow=${f} (claimed=${b.claimed})`),this.sendJson(t,202,{ok:!0,agent:i,source:l,eventType:g,workflow:f,claimed:b.claimed});return}catch(b){this.log(`Workflow dispatch failed [${l}/${g}/${f}]: ${b.message}`)}let w=this.webhookEntries.find(b=>b.enabled&&b.node&&b.agentId===i&&b.source===l);if(w?.node&&this.mesh){this.sendJson(t,202,{ok:!0,agent:i,source:l,node:w.node,status:"accepted"}),this.mesh.sendTask(w.node,u,i,{context:{channel:`webhook:${l}`,sender:`webhook:${l}`}}).then(b=>this.log(`Mesh-forwarded webhook [${l}] -> ${w.node}/${i}: ${b?.slice(0,100)||"ok"}`),b=>this.log(`Mesh forward failed [${l}] -> ${w.node}/${i}: ${b.message}`));return}try{let b=await this.registry.execute({message:u,agentId:i,context:{channel:`webhook:${l}`,sender:`webhook:${l}`}});this.sendJson(t,b.error?500:200,{ok:!b.error,agent:i,source:l,response:b.content?.slice(0,500),error:b.error,duration:b.duration})}catch(b){this.sendJson(t,500,{error:b.message})}}extractEventType(e,t,n){let s=i=>{let o=n[i.toLowerCase()];return Array.isArray(o)?o[0]:o};if(e==="github"){let i=s("x-github-event");if(!i)return;let o=typeof t.action=="string"?t.action:void 0;return o?`${i}.${o}`:i}if(e==="gitlab")return s("x-gitlab-event")||(typeof t.object_kind=="string"?t.object_kind:void 0);if(e==="stripe")return typeof t.type=="string"?t.type:void 0;if(e==="sentry")return s("sentry-hook-resource");if(e==="hubspot"){if(Array.isArray(t)&&t.length>0){let i=t[0];if(i&&typeof i.subscriptionType=="string")return i.subscriptionType}return typeof t.subscriptionType=="string"?t.subscriptionType:void 0}if(e==="odoo")return typeof t.event=="string"?t.event:typeof t.subscriptionType=="string"?t.subscriptionType:typeof t.model=="string"?typeof t.action=="string"?`${t.model}.${t.action}`:t.model:void 0}detectSource(e){return e["x-gitlab-event"]||e["x-gitlab-token"]?"gitlab":e["x-github-event"]?"github":e["stripe-signature"]?"stripe":e["sentry-hook-resource"]?"sentry":e["x-vercel-signature"]?"vercel":e["x-hubspot-signature-v3"]||e["x-hubspot-signature-version"]?"hubspot":e["x-odoo-database"]||e["x-odoo-signature"]?"odoo":e["x-hub-signature-256"]?"github":"unknown"}buildSummary(e,t,n){let s=[`[Webhook from ${e}]`];switch(e){case"gitlab":{let o=n["x-gitlab-event"]||t.object_kind||"event",a=t.project?.path_with_namespace||"",c=t.user?.name||t.user_username||"";if(s.push(`Event: ${o}`),a&&s.push(`Project: ${a}`),c&&s.push(`User: ${c}`),t.ref&&s.push(`Ref: ${t.ref}`),t.commits&&Array.isArray(t.commits)){s.push(`Commits: ${t.commits.length}`);for(let d of t.commits.slice(0,3))s.push(` - ${d.message?.split(`
533
+ `)}function Tg(r,e,t,n,s,i){let o=i?.usage?.inputTokens??0,a=i?.usage?.outputTokens??Math.ceil(s.length/4);wo(r,200,{id:e,object:"chat.completion",created:t,model:n,choices:[{index:0,message:{role:"assistant",content:s},finish_reason:"stop"}],usage:{prompt_tokens:o,completion_tokens:a,total_tokens:o+a}})}function wo(r,e,t){r.writeHead(e,{"Content-Type":"application/json"}),r.end(JSON.stringify(t))}var an=class{module;minLevel;constructor(e,t="info"){this.module=e,this.minLevel=t}child(e){return new an(`${this.module}:${e}`,this.minLevel)}debug(e,t){this.emit("debug",e,t)}info(e,t){this.emit("info",e,t)}warn(e,t){this.emit("warn",e,t)}error(e,t){this.emit("error",e,t)}asConsoleLog(){return(...e)=>{let n=e.map(s=>typeof s=="string"?s:JSON.stringify(s)).join(" ").replace(/^\[agentx\]\s*/,"");n&&this.info(n)}}emit(e,t,n){if(an.levelOrder[e]<an.levelOrder[this.minLevel])return;let s={time:new Date().toISOString(),level:e,module:this.module,msg:t,...n},i=e==="error"?"ERROR":e==="warn"?"WARN":"",o=`[${this.module}]`,a=i?`${o} ${i}: ${t}`:`${o} ${t}`;console.error(a)}},on=an;ft(on,"levelOrder",{debug:0,info:1,warn:2,error:3});import{realpathSync as Vv,statSync as Jv}from"fs";var Et={version:"0.138.1",commit:"81dc59c",startedAt:new Date(Date.now()-process.uptime()*1e3).toISOString()};function Xv(r,e){let t=e.mtimeMs!==null&&e.mtimeMs>Date.parse(r.startedAt),n=!!e.version&&!!r.version&&e.version!==r.version;return{newer:t||n,changedAt:e.mtimeMs===null?null:new Date(e.mtimeMs).toISOString(),version:e.version}}function Ag(){let r=null;try{r=Jv(Vv(process.argv[1])).mtimeMs}catch{}let e=Xh().version;return Xv(Et,{mtimeMs:r,version:e&&e!=="0.0.0"?e:null})}import{randomUUID as Kv}from"crypto";var Rs=class{constructor(e=new ll){this.core=e}count=0;subscribe(e,t){this.count++;let n=this.core.subscribe((i,o)=>{if(!o||!zv.includes(o.kind))return;let a={...o,rootId:i.rootId,node:i.node};Qv(e,a)&&t(a)}),s=!0;return()=>{s&&(s=!1,this.count--,n())}}publish(e){let t={id:typeof e.id=="string"?e.id:Kv(),at:typeof e.at=="string"?e.at:new Date().toISOString(),...e},{type:n,summary:s,ref:i,agentId:o}=Yv(t);this.core.publish({id:t.id,at:t.at,kind:t.kind,type:n,summary:s,ref:i,agentId:o,rootId:typeof e.rootId=="string"?e.rootId:void 0,data:t})}get size(){return this.count}},zv=["run","task","signal","mesh","channel","status"];function Yv(r){switch(r.kind){case"run":return{type:r.phase,ref:r.runId,summary:[r.workflowId,r.nodeId,r.phase,r.note].filter(Boolean).join(" ")};case"task":return{type:r.phase,ref:r.taskId,summary:`${r.title??r.taskId} ${r.phase}`};case"signal":return{type:"emitted",summary:`signal ${r.name} (${r.scope})`};case"mesh":return{type:r.delta,summary:`peer ${r.peer} ${r.delta}`};case"channel":return{type:r.direction,ref:r.messageId,agentId:r.agentId,summary:`${r.channel} ${r.direction==="in"?"inbound":"outbound"}`};case"status":return{type:"status",summary:r.message}}}function Qv(r,e){return!(r.kinds&&r.kinds.length>0&&!r.kinds.includes(e.kind)||r.workflowId&&(e.kind==="run"&&e.workflowId!==r.workflowId||e.kind==="task"&&e.workflowId!==r.workflowId||e.kind==="signal"&&e.workflowId&&e.workflowId!==r.workflowId)||r.runId&&(e.kind==="run"&&e.runId!==r.runId||e.kind==="task"&&e.runId!==r.runId)||r.actor&&(e.kind!=="task"||!(e.assignedTo?.includes(r.actor)||e.submittedBy===r.actor))||r.channel&&(e.kind!=="channel"||e.channel!==r.channel))}function Rg(r){if(!r)return;let e=["run","task","signal","mesh","channel","status"],n=r.split(",").map(s=>s.trim()).filter(Boolean).filter(s=>e.includes(s));return n.length?n:void 0}import{createHmac as Es,timingSafeEqual as Eg}from"crypto";var Cs=class{registry;config;mesh;webhookEntries;log;workflowDispatcher;hooks;constructor(e,t={},n=console.error.bind(console,"[webhook]"),s,i=[],o){this.registry=e,this.config=t,this.log=n,this.mesh=s,this.webhookEntries=i,this.hooks=o}hookEventFor(e,t){if(e==="stripe")return"on:stripe-event";if(e==="sentry")return"on:sentry-issue";if(e==="vercel")return"on:vercel-deployment";if(e==="hubspot")return"on:hubspot-event";if(e==="odoo")return"on:odoo-event";if(e==="github"){let n=(t??"").split(".")[0];return n==="issues"||n==="issue_comment"?"on:github-issue":n==="pull_request"||n==="pull_request_review"?"on:github-pr":n==="push"?"on:github-push":null}return null}async fireHookSafe(e,t,n,s){let i=this.hookEventFor(e,t);if(!i||!this.hooks||!this.hooks.has(i))return;let o={};if(e==="github"){let a=s;typeof a.sender?.login=="string"&&(o.author=a.sender.login),typeof a.repository?.full_name=="string"&&(o.repo=a.repository.full_name);let c=a.issue?.number??a.pull_request?.number;typeof c=="number"&&(o.number=c)}try{await this.hooks.execute(i,{event:i,source:e,eventType:t,agentId:n,payload:s,...o})}catch(a){this.log(`${i} hook error (non-fatal): ${a?.message??a}`)}}setWorkflowDispatcher(e){this.workflowDispatcher=e}setWebhookEntries(e){this.webhookEntries=e}async handle(e,t,n){let s=n.replace(/^\/webhook\/?/,"").split("/").filter(Boolean),i=s[0],o=s[1];if(!i){this.sendJson(t,400,{error:"Missing agent ID. Use /webhook/:agentId"});return}let{raw:a,parsed:c}=await this.readBody(e),l=o||this.detectSource(e.headers);if(process.env.AGENTX_WEBHOOK_DEBUG_HEADERS==="1"){let b={};for(let[k,S]of Object.entries(e.headers))(k.startsWith("x-hubspot")||k.startsWith("x-hub")||k.startsWith("x-github")||k.startsWith("x-gitlab")||k.startsWith("stripe")||k.startsWith("sentry")||k.startsWith("x-vercel")||k.startsWith("x-odoo")||k.startsWith("x-webhook")||k==="user-agent"||k==="content-type"||k==="host"||k==="x-forwarded-host"||k==="x-forwarded-proto"||k==="x-forwarded-for")&&(b[k]=S);this.log(`Webhook [${l}] reqUrl=${e.url} headers: ${JSON.stringify(b)}`)}let d=this.validateSignature(e.headers,a,l,i,e.url);if(d){this.log(`Webhook [${l}] -> ${i}: REJECTED (${d})`),this.sendJson(t,401,{error:d});return}let u=this.buildSummary(l,c,e.headers);this.log(`Webhook [${l}] -> ${i}: ${u.slice(0,100)}`);let g=this.extractEventType(l,c,e.headers),m=this.webhookEntries.find(b=>b.enabled&&b.agentId===i&&b.source===l),f=g&&m?.triggers?.[g]||m?.defaultWorkflow||null;if(await this.fireHookSafe(l,g,i,c),f&&this.workflowDispatcher)try{let b=await this.workflowDispatcher.dispatchWorkflow({workflowId:f,entityRef:{kind:"webhook",id:`${l}:${i}:${g??"\u2014"}:${Date.now()}`},event:{kind:"webhook",source:l,eventType:g,payload:c},trigger:{source:l}});this.log(`Webhook [${l}/${g??"\u2014"}] -> workflow=${f} (claimed=${b.claimed})`),this.sendJson(t,202,{ok:!0,agent:i,source:l,eventType:g,workflow:f,claimed:b.claimed});return}catch(b){this.log(`Workflow dispatch failed [${l}/${g}/${f}]: ${b.message}`)}let w=this.webhookEntries.find(b=>b.enabled&&b.node&&b.agentId===i&&b.source===l);if(w?.node&&this.mesh){this.sendJson(t,202,{ok:!0,agent:i,source:l,node:w.node,status:"accepted"}),this.mesh.sendTask(w.node,u,i,{context:{channel:`webhook:${l}`,sender:`webhook:${l}`}}).then(b=>this.log(`Mesh-forwarded webhook [${l}] -> ${w.node}/${i}: ${b?.slice(0,100)||"ok"}`),b=>this.log(`Mesh forward failed [${l}] -> ${w.node}/${i}: ${b.message}`));return}try{let b=await this.registry.execute({message:u,agentId:i,context:{channel:`webhook:${l}`,sender:`webhook:${l}`}});this.sendJson(t,b.error?500:200,{ok:!b.error,agent:i,source:l,response:b.content?.slice(0,500),error:b.error,duration:b.duration})}catch(b){this.sendJson(t,500,{error:b.message})}}extractEventType(e,t,n){let s=i=>{let o=n[i.toLowerCase()];return Array.isArray(o)?o[0]:o};if(e==="github"){let i=s("x-github-event");if(!i)return;let o=typeof t.action=="string"?t.action:void 0;return o?`${i}.${o}`:i}if(e==="gitlab")return s("x-gitlab-event")||(typeof t.object_kind=="string"?t.object_kind:void 0);if(e==="stripe")return typeof t.type=="string"?t.type:void 0;if(e==="sentry")return s("sentry-hook-resource");if(e==="hubspot"){if(Array.isArray(t)&&t.length>0){let i=t[0];if(i&&typeof i.subscriptionType=="string")return i.subscriptionType}return typeof t.subscriptionType=="string"?t.subscriptionType:void 0}if(e==="odoo")return typeof t.event=="string"?t.event:typeof t.subscriptionType=="string"?t.subscriptionType:typeof t.model=="string"?typeof t.action=="string"?`${t.model}.${t.action}`:t.model:void 0}detectSource(e){return e["x-gitlab-event"]||e["x-gitlab-token"]?"gitlab":e["x-github-event"]?"github":e["stripe-signature"]?"stripe":e["sentry-hook-resource"]?"sentry":e["x-vercel-signature"]?"vercel":e["x-hubspot-signature-v3"]||e["x-hubspot-signature-version"]?"hubspot":e["x-odoo-database"]||e["x-odoo-signature"]?"odoo":e["x-hub-signature-256"]?"github":"unknown"}buildSummary(e,t,n){let s=[`[Webhook from ${e}]`];switch(e){case"gitlab":{let o=n["x-gitlab-event"]||t.object_kind||"event",a=t.project?.path_with_namespace||"",c=t.user?.name||t.user_username||"";if(s.push(`Event: ${o}`),a&&s.push(`Project: ${a}`),c&&s.push(`User: ${c}`),t.ref&&s.push(`Ref: ${t.ref}`),t.commits&&Array.isArray(t.commits)){s.push(`Commits: ${t.commits.length}`);for(let d of t.commits.slice(0,3))s.push(` - ${d.message?.split(`
534
534
  `)[0]||"no message"} (${d.author?.name||""})`)}let l=t.object_attributes;if(l?.title&&(s.push(`Title: ${l.title}`),s.push(`State: ${l.state||""}`),s.push(`Action: ${l.action||""}`),l.source_branch&&s.push(`Branch: ${l.source_branch} -> ${l.target_branch}`),l.url&&s.push(`URL: ${l.url}`)),l?.iid&&!l?.source_branch&&(s.push(`Issue #${l.iid}: ${l.title||""}`),l.description&&s.push(`Description: ${l.description.slice(0,200)}`)),t.object_kind==="pipeline"){let d=t.object_attributes;s.push(`Pipeline: ${d?.status||""} (${d?.ref||""})`),s.push(`Duration: ${d?.duration||0}s`)}break}case"github":{let o=n["x-github-event"]||"event",a=t.repository?.full_name||"",c=t.sender?.login||"";if(s.push(`Event: ${o}`),a&&s.push(`Repository: ${a}`),c&&s.push(`Sender: ${c}`),t.ref&&s.push(`Ref: ${t.ref}`),t.commits&&Array.isArray(t.commits))for(let u of t.commits.slice(0,3))s.push(` - ${u.message?.split(`
535
535
  `)[0]||""} (${u.author?.name||""})`);let l=t.pull_request;l&&(s.push(`PR #${l.number}: ${l.title}`),s.push(`Action: ${t.action}`),s.push(`Branch: ${l.head?.ref} -> ${l.base?.ref}`));let d=t.issue;d&&(s.push(`Issue #${d.number}: ${d.title}`),s.push(`Action: ${t.action}`));break}case"stripe":{let o=t.type||"event",a=t.data?.object||{};s.push(`Event: ${o}`),a.amount&&s.push(`Amount: ${(a.amount/100).toFixed(2)} ${a.currency?.toUpperCase()||""}`),a.customer_email&&s.push(`Customer: ${a.customer_email}`),a.description&&s.push(`Description: ${a.description}`),a.status&&s.push(`Status: ${a.status}`);break}case"sentry":{let o=n["sentry-hook-resource"]||"event";s.push(`Resource: ${o}`);let a=t.data||t;a.error?.title&&s.push(`Error: ${a.error.title}`),a.error?.culprit&&s.push(`Culprit: ${a.error.culprit}`),a.error?.metadata?.value&&s.push(`Message: ${a.error.metadata.value}`),t.url&&s.push(`URL: ${t.url}`);break}case"hubspot":{let o=Array.isArray(t)?t:null,a=o||null;if(a&&a.length){s.push(`Events: ${a.length}`);for(let l of a.slice(0,3)){let d=l.subscriptionType??"?",u=l.objectId??"?",g=l.changeFlag??l.changeSource??"";s.push(` - ${d} (object ${u}${g?`, ${g}`:""})`)}}else{let l=t.subscriptionType??"event",d=t.objectId??"?";s.push(`Event: ${l} (object ${d})`)}let c=a?.[0]?.portalId??t.portalId;c!=null&&s.push(`Portal: ${c}`);break}case"odoo":{let o=typeof t.event=="string"&&t.event||typeof t.subscriptionType=="string"&&t.subscriptionType||typeof t.model=="string"&&(typeof t.action=="string"?`${t.model}.${t.action}`:t.model)||"event";s.push(`Event: ${o}`);let a=n["x-odoo-database"]||(typeof t.database=="string"?t.database:"");a&&s.push(`Database: ${a}`);let c=t.record||t;c?.id&&s.push(`Record id: ${c.id}`),c?.name&&s.push(`Name: ${String(c.name).slice(0,200)}`),c?.partner_id?.[1]&&s.push(`Partner: ${c.partner_id[1]}`),c?.email&&s.push(`Email: ${c.email}`),c?.amount_total!=null&&s.push(`Amount: ${c.amount_total}`),c?.state&&s.push(`State: ${c.state}`);break}default:s.push(`Headers: ${JSON.stringify(Object.keys(n).filter(o=>o.startsWith("x-")).slice(0,5))}`),s.push(`Payload keys: ${Object.keys(t).slice(0,10).join(", ")}`);let i=JSON.stringify(t).slice(0,500);s.push(`Body: ${i}`)}return s.join(`
536
536
  `)}async readBody(e){return new Promise(t=>{let n="";e.on("data",s=>n+=s.toString()),e.on("end",()=>{let s;try{s=n?JSON.parse(n):{}}catch{s={raw:n}}t({raw:n,parsed:s})}),e.on("error",()=>t({raw:"",parsed:{}}))})}validateSignature(e,t,n,s,i){let o=this.webhookEntries.find(d=>d.enabled&&d.agentId===s&&d.source===n);if(!o?.secretEnv)return null;let a=process.env[o.secretEnv];if(!a)return`webhook entry "${o.id}" expects env ${o.secretEnv} but it is unset`;let c=d=>{let u=e[d.toLowerCase()];return Array.isArray(u)?u[0]:u};if(n==="github"){let d=c("x-hub-signature-256");if(!d)return"missing X-Hub-Signature-256";let u="sha256="+Es("sha256",a).update(t).digest("hex");return Ct(u,d)}if(n==="gitlab"){let d=c("x-gitlab-token");return d?Ct(a,d):"missing X-Gitlab-Token"}if(n==="stripe"){let d=c("stripe-signature");if(!d)return"missing Stripe-Signature";let u=Object.fromEntries(d.split(",").map(m=>m.split("=")));if(!u.t||!u.v1)return"malformed Stripe-Signature";let g=Es("sha256",a).update(`${u.t}.${t}`).digest("hex");return Ct(g,u.v1)}if(n==="hubspot"){let d=c("x-hubspot-signature-v3"),u=c("x-hubspot-request-timestamp");if(!d)return"missing X-HubSpot-Signature-v3";if(!u)return"missing X-HubSpot-Request-Timestamp";let g=parseInt(u,10);if(!Number.isFinite(g))return"malformed X-HubSpot-Request-Timestamp";let m=Date.now()-g;if(m>5*6e4)return`HubSpot webhook is ${Math.floor(m/1e3)}s old (>5min replay window)`;let f="POST",w=i||e["x-original-uri"]||e["x-forwarded-path"]||"",b=e["x-forwarded-host"],k=e.host,S=e["x-forwarded-proto"]||"https",I=new Set;b&&w&&I.add(`${S}://${b}${w}`),k&&w&&I.add(`https://${k}${w}`),k&&w&&I.add(`http://${k}${w}`),w&&I.add(w),I.add("");for(let C of I){let N=Es("sha256",a).update(`${f}${C}${t}${u}`).digest("base64");if(d.length===N.length&&Eg(Buffer.from(d),Buffer.from(N)))return null}return`signature mismatch (tried ${I.size} URI variants)`}if(n==="odoo"){let d=c("x-odoo-signature");if(d){let g=Es("sha256",a).update(t).digest("hex"),m=d.startsWith("sha256=")?d.slice(7):d;return Ct(g,m)}let u=c("x-odoo-webhook-token")??c("x-webhook-secret");return u?Ct(a,u):"missing X-Odoo-Signature or X-Odoo-Webhook-Token"}let l=c("x-webhook-secret");return l?Ct(a,l):"missing X-Webhook-Secret"}sendJson(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n,null,2))}};function Ct(r,e){if(r.length!==e.length)return"signature mismatch";let t=Buffer.from(r),n=Buffer.from(e);return Eg(t,n)?null:"signature mismatch"}wk();ac();vc();function Zv(r){return{insertTaskHistory:r.prepare(`
@@ -1108,7 +1108,7 @@ Error: ${o.slice(0,300)}`),this.broadcastSSE("cron-failure",JSON.stringify({jobI
1108
1108
  ${o.slice(0,300)}`,record:!0,taskId:`cron-fail:${s.replace(/\//g,":")}:${Date.now()}`,outcome:"error",summary:`Cron "${s}" failed (${a}x)`})}catch(l){this.log(`[CRON ALERT] notify send failed: ${l.message}`)}}),e.setDeliverCallback(async(s,i,o,a)=>{let c=t.crons[s]?.notify;c&&await Ur(n,{channel:c.channel,chatId:c.chatId,accountId:c.accountId,agentId:i,text:o,record:!0,taskId:`cron:${a.replace(/\//g,":")}`,idempotencyKey:a,outcome:"done",summary:`Cron "${s}" result`})})}async reload(){let e;try{e=ui(this.configPath)}catch(k){return this.log(`[reload] config invalid, keeping previous: ${k.message}`),{applied:[],restartRequired:[],error:k.message}}let t=[],n=[];if(["maxClaudeCodeDispatchesPerHour","maxClaudeCodeDispatchesPer5h"].some(k=>this.config.session[k]!==e.session[k])&&(bl({maxPerHour:e.session.maxClaudeCodeDispatchesPerHour,maxPer5h:e.session.maxClaudeCodeDispatchesPer5h}),t.push("dispatch-budget")),JSON.stringify(this.config.crons)!==JSON.stringify(e.crons))try{await this.cron.stop(),this.cron=new Si(e,this.registry,this.hooks,this.log),this.wireCronCallbacks(this.cron,e),await this.cron.start(),t.push("crons")}catch(k){this.log(`[reload] cron reload failed: ${k.message}`)}let i=this.config.channels?.telegram,o=e.channels?.telegram,a=JSON.stringify(i)!==JSON.stringify(o),c=!1;if(a&&o?.enabled){let k=this.router.getChannel("telegram");if(k)try{let S=await k.reloadAccounts(o.accounts,o.policy);this.router.updateConfig(e);let I=[];S.added.length&&I.push(`+${S.added.join(",")}`),S.removed.length&&I.push(`-${S.removed.join(",")}`),S.tokenChanged.length&&I.push(`~${S.tokenChanged.join(",")}`),t.push(I.length?`telegram(${I.join(" ")})`:"telegram"),c=!0}catch(S){this.log(`[reload] telegram hot-reload failed: ${S.message}`)}}else a&&!o?.enabled&&i?.enabled||a&&o?.enabled&&!i?.enabled?c=!1:a||(c=!0);if(JSON.stringify(this.config.providers)!==JSON.stringify(e.providers))try{this.registry.setProviders(e.providers),t.push("providers")}catch(k){this.log(`[reload] providers hot-reload failed: ${k.message}`)}let l=this.config.mesh,d=e.mesh,u=JSON.stringify(l)!==JSON.stringify(d),g=!u;if(u&&d.enabled&&l.enabled&&this.mesh&&!(JSON.stringify(l.healthCheck)!==JSON.stringify(d.healthCheck)))try{let S=await this.mesh.reloadPeers(e),I=[];S.added.length&&I.push(`+${S.added.join(",")}`),S.removed.length&&I.push(`-${S.removed.join(",")}`),S.updated.length&&I.push(`~${S.updated.join(",")}`),t.push(I.length?`mesh(${I.join(" ")})`:"mesh"),g=!0}catch(S){this.log(`[reload] mesh hot-reload failed: ${S.message}`)}if(JSON.stringify(this.config.services)!==JSON.stringify(e.services))try{let k=this.router.getServiceMatcher();if(k){let{count:S}=k.reload(e.services);t.push(`services(${S})`)}else if(Object.keys(e.services).length>0){let S=new En(e.services,this.log);this.router.setServiceMatcher(S),t.push(`services(${Object.keys(e.services).length})`)}}catch(k){this.log(`[reload] services hot-reload failed: ${k.message}`)}try{let k=this.hooks.size?.()??0;this.hooks.clear(),Zr(process.cwd(),this.hooks);let S=this.hooks.size?.()??0;k!==S&&t.push(`hooks(${S})`)}catch(k){this.log(`[reload] hooks reload failed: ${k.message}`)}if(JSON.stringify(this.config.business)!==JSON.stringify(e.business)||JSON.stringify(this.config.agents)!==JSON.stringify(e.agents)){try{this.landscape=new fn(e),this.registry.setLandscape(this.landscape),t.push("landscape")}catch(k){this.log(`[reload] landscape rebuild failed: ${k.message}`)}if(this.mesh&&this.mesh.peerCount()>0)try{let k=await this.mesh.refreshAll(),S=k.filter(I=>I.healthy).length;t.push(`mesh.refresh(${S}/${k.length})`)}catch(k){this.log(`[reload] mesh refresh failed: ${k.message}`)}}if(JSON.stringify(this.config.agents)!==JSON.stringify(e.agents)){let k=Object.keys(this.config.agents).sort().join(","),S=Object.keys(e.agents).sort().join(",");k===S&&(this.registry.setConfig(e),t.push("agents.meta"));let I=fA(this.config.agents,e.agents);I.length>0&&n.push(`agents(${I.join(",")})`)}JSON.stringify(this.config.people)!==JSON.stringify(e.people)&&(this.registry.setPeople(e.people),t.push(`people(${e.people.length})`)),g||n.push("mesh"),JSON.stringify(this.config.node)!==JSON.stringify(e.node)&&n.push("node");let m={...this.config.channels,telegram:void 0},f={...e.channels,telegram:void 0};JSON.stringify(m)!==JSON.stringify(f)?n.push("channels"):a&&!c&&n.push("channels.telegram");{let k=this.contacts.size(),S=this.contacts.reload();S.error?this.log(`[reload] contacts.json invalid: ${S.error}`):S.count!==k&&t.push(`contacts(${S.count})`)}if(JSON.stringify(this.config.webhooks)!==JSON.stringify(e.webhooks))try{this.webhooks.setWebhookEntries(e.webhooks),t.push(`webhooks(${e.webhooks.length})`)}catch(k){this.log(`[reload] webhooks hot-reload failed: ${k.message}`)}JSON.stringify(this.config.workflows)!==JSON.stringify(e.workflows)&&(this.registry.setWorkflows(e.workflows),t.push("workflows"),this.config.workflows.enabled!==e.workflows.enabled&&n.push("workflows.enabled")),JSON.stringify(this.config.whatsappTriage)!==JSON.stringify(e.whatsappTriage)&&t.push(`whatsappTriage(${e.whatsappTriage.rules.length} rule(s))`);let w=JSON.stringify(this.config.screen)!==JSON.stringify(e.screen),b=JSON.stringify(this.config.reminders)!==JSON.stringify(e.reminders);return this.config=e,J().configure({node:e.node.name||e.node.id,ringSize:e.events.ringSize}),this.router.updateConfig(e),w&&(this.screenBuffer?.configure(Fi(e.screen)),t.push("screen")),b&&(this.stopReminders?.(),this.startReminders(),t.push("reminders")),t.length&&this.log(`[reload] applied: ${t.join(", ")}`),n.length?(this.log(`[reload] restart required to apply changes in: ${n.join(", ")}`),this.broadcastSSE("reload-partial",JSON.stringify({applied:t,restartRequired:n}))):t.length&&this.broadcastSSE("reload-complete",JSON.stringify({applied:t})),this.workflowPolls?.sync(),{applied:t,restartRequired:n}}requests=null;guestStore=new gu(process.cwd());guestJoinLimiter=new mu;operatorKey=null;requestsSweeping=!1;status=null;forwardCommentEdit(e){return async(t,n,s,i,o)=>{let a=this.mesh?.directory().find(d=>d.peer===t&&d.healthy);if(!a)return this.log(`[${e}] edit-comment forward: peer "${t}" not found or unhealthy`),!1;let c=await fetch(`${a.peerUrl}/channel/edit-comment`,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(a.peer)},body:JSON.stringify({channel:e,chatId:n,commentId:s,agentId:i,text:o})}),l=await c.json().catch(()=>({}));return c.ok&&l.ok===!0}}approvalsTimer;pushRosterTimer;pushHost;approvalsSweeping=!1;startApprovalsSweep(){let e=async()=>{if(!(this.approvalsSweeping||this.shuttingDown)){this.approvalsSweeping=!0;try{let t=this.config.notifications?.destination;if(await vp({ctx:{root:process.cwd()},settings:this.config.approvals,fallbackDestination:t?{channel:t.channel,chatId:t.chatId,accountId:t.accountId}:void 0,hasAgent:n=>!!this.registry.getAgent(n),onCardResult:n=>{this.requests?.tracker.cardResolved(n),this.status?.board.cardResolved(n),this.workflowCardResult(n)},tellAgent:async(n,s,i)=>this.tellAgentCardResult(i,s),tellPeer:async(n,s)=>{let i=this.approvalsPeer(n);if(!i)throw new Error(`no mesh peer named "${n}"`);await Ap(s,{self:this.config.node.name,peer:i})},sendDigest:async(n,s)=>{await this.router.sendOutbound({channel:n.channel,chatId:n.chatId,accountId:n.accountId,text:s})},log:this.log}),this.requests&&!this.requestsSweeping){this.requestsSweeping=!0;let n=new Promise((s,i)=>{setTimeout(()=>i(new Error("timed out after 5 min")),3e5).unref?.()});Promise.race([this.sweepRequests(this.requests),n]).catch(s=>this.log(`[requests] sweep failed: ${s?.message??s}`)).finally(()=>{this.requestsSweeping=!1})}this.status?.board.sweep(),this.voiceTalk.floor.view().held||yu({ctx:{root:process.cwd()},settings:this.config.approvals.popup,log:this.log,agentName:n=>this.registry.getAgent(n)?.name,speak:n=>this.voiceTalk.speech.say({voice:{provider:"system",elevenlabs:"",system:this.config.approvals.popup.voice??null,fallback:!1},text:n,kind:"line"})}).catch(n=>this.log(`[approvals] popup failed: ${n?.message??n}`)),this.runCheckin().catch(n=>this.log(`[checkin] failed: ${n?.message??n}`))}catch(t){this.log(`[approvals] sweep failed: ${t?.message??t}`)}finally{this.approvalsSweeping=!1}}};this.approvalsTimer=setInterval(()=>{e()},6e4),this.approvalsTimer.unref?.()}tellAgentCardResult(e,t=Xn(e)){this.registry.execute({agentId:e.raised_by,message:t,context:{channel:"approvals",chatId:e.id,sender:"operator"}}).catch(n=>this.log(`[approvals] ${e.id}: turn on ${e.raised_by} failed: ${n?.message??n}`))}approvalsPeer(e){return Ep(e,this.config.mesh.peers,this.mesh?.directory()??[])}forwardToWarned;approvalsForward(){let e=this.config.approvals.forwardTo;if(!e)return;let t=this.approvalsPeer(e);if(!t){this.forwardToWarned!==e&&(this.forwardToWarned=e,this.log(`[approvals] approvals.forwardTo names "${e}", which is not in mesh.peers; cards stay on this node`));return}return{self:this.config.node.name,peer:t}}carriesMeshToken(e){let t=String(e.headers.authorization||""),n=t.startsWith("Bearer ")?t.slice(7).trim():"";return!!n&&zn(this.config).has(n)}async notifyRequestOwner(e,t,n){await dt({title:e,message:t,from:n.agentId,priority:4},async s=>{try{await this.router.sendOutbound({channel:s.channel??ut(this.config),chatId:s.chatId??"default",text:`${s.title}
1109
1109
  ${s.message}`,priority:s.priority,agentId:n.agentId})}catch(i){if(this.log(`[requests] push for ${n.id} failed: ${i?.message??i}`),process.platform!=="darwin")throw i}},{alert:ke(Ce(this.config.notifications.local))})}plansSweeping=!1;plansKick;kickPlans(){this.plansKick||!this.requests||(this.plansKick=setTimeout(()=>{this.plansKick=void 0,this.requests&&!this.shuttingDown&&this.sweepPlans(this.requests).catch(e=>this.log(`[plans] check failed: ${e?.message??e}`))},1e3),this.plansKick.unref?.())}async sweepPlans(e){if(!(this.plansSweeping||!this.config.requests.enabled)){this.plansSweeping=!0;try{await Xp({requests:e.store,plans:e.plans,settings:this.config.requests.plans??Hs,tellAgent:async(t,n,s,i)=>{let o=a=>{let c=e.plans.step(i.requestId,i.idx);c?.state==="active"&&Oe(e.store,e.plans,c,`could not hand it to ${t}: ${a}`,Date.now()),this.log(`[plans] ${s.id} step ${i.idx}: turn on ${t} failed: ${a}`)};this.registry.execute({agentId:t,message:n,context:ci(s.id)}).then(a=>{a?.error&&!Ne(a.error)&&o(a.error)}).catch(a=>o(a?.message??String(a)))},send:async(t,n)=>{await this.router.sendOutbound({channel:t.toChannel,chatId:t.toChat,text:n,agentId:t.agentId,...t.toAccount?{accountId:t.toAccount}:{}},{idempotencyKey:`plan:${t.requestId}:${t.idx}`,dedupeWindowMs:24*36e5})},notify:(t,n,s)=>this.notifyRequestOwner(t,n,s),raiseCard:(t,n,s)=>{let i=We(process.cwd(),{...s,if_silent:"discard",raised_by:n.agentId},{settings:this.config.approvals,origin:{kind:"plan-step",requestId:t.id,step:n.idx}});if(!i.ok)throw new Error(i.error);return i.card.id},readCard:t=>vt(process.cwd(),t),hasAgent:t=>!!this.registry.getAgent(t),log:this.log})}finally{this.plansSweeping=!1}}}async sweepRequests(e){await this.sweepPlans(e).catch(t=>this.log(`[plans] check failed: ${t?.message??t}`)),await _p({store:e.store,settings:this.config.requests,notify:(t,n,s)=>this.notifyRequestOwner(t,n,s),hasAgent:t=>!!this.registry.getAgent(t),tellAgent:async(t,n,s)=>{this.registry.execute({agentId:t,message:n,context:ci(s.id)}).then(i=>{Oo(e.store,s,i,Date.now())&&this.log(`[requests] ${s.id}: could not hand it back to ${t}: ${i.error}`)}).catch(i=>{Oo(e.store,s,{error:i?.message??String(i)},Date.now()),this.log(`[requests] ${s.id}: turn on ${t} failed: ${i?.message??i}`)})},log:this.log})}async notifyOwner(e,t,n,s=4){await dt({title:e,message:t,from:n,priority:s},async i=>{try{await this.router.sendOutbound({channel:i.channel??ut(this.config),chatId:i.chatId??"default",text:`${i.title}
1110
1110
  ${i.message}`,priority:i.priority,agentId:n})}catch(o){if(this.log(`[workflows] push "${e}" failed: ${o?.message??o}`),process.platform!=="darwin")throw o}},{alert:ke(Ce(this.config.notifications.local))})}workflowCardResult(e){if(e.origin?.kind==="workflow"){this.workflowDispatcher?.resumeFromCard(e).catch(n=>this.log(`[workflows] card ${e.id}: resume failed: ${n?.message??n}`));return}if(e.origin?.kind!=="workflow-proposal"||!this.workflowStore)return;let t=this.workflowStore.get(e.origin.workflowId);t&&(e.status==="decided"&&e.verdict==="yes"?(this.workflowStore.save({...t,status:"active",state:"active"}),this.log(`[workflows] ${t.id} kept as a reusable workflow (card ${e.id})`)):this.log(`[workflows] ${t.id} not kept (card ${e.id} ${e.status==="decided"?"no":"expired"}); it stays switched off`))}workflowRequestEnded(e){let t=e.meta?.requestId,n=this.requests?.store;if(!t||!n)return;let s=Date.now();try{e.status==="completed"?n.close(t,"done",nd(e),s):n.needsAttention(t,`Workflow run ${e.id} ${e.status==="canceled"?"was stopped":"did not finish"}: ${e.history.at(-1)?.note??e.status}`,s)&&n.markNotified(t,s)}catch(i){this.log(`[workflows] request ${t} after run ${e.id}: ${i?.message??i}`)}}runCheckin(e){if(process.platform!=="darwin")return Promise.resolve(null);let t={root:process.cwd(),settings:this.config.approvals.checkin,cardSettings:this.config.approvals,source:Zs(this.config.reminders.command),...this.config.reminders.enabled?{claimsPath:Xs(process.cwd())}:{},hasAgent:n=>!!this.registry.getAgent(n),ask:async(n,s,i)=>{let o=await this.registry.execute({agentId:n,message:s,timeoutMinutes:this.config.approvals.checkin.composeTimeoutSeconds/60,context:{channel:"reminder",chatId:`checkin:${i.id}`,sender:"approvals"}});if(o.error)throw new Error(o.error);return o.content??""},notify:async(n,s)=>{let i=this.config.approvals.checkin.agent;await dt({title:n,message:s,from:i,priority:4},async o=>{try{await this.router.sendOutbound({channel:o.channel??ut(this.config),chatId:o.chatId??"default",text:`${o.title}
1111
- ${o.message}`,priority:o.priority,agentId:i})}catch(a){this.log(`[checkin] push for "${o.title}" failed: ${a?.message??a}`)}},{alert:ke(Ce(this.config.notifications.local))})},log:this.log};return kf(t,e)}stopReminders;startReminders(){let e=this.config.notifications?.destination;this.stopReminders=Sf({settings:this.config.reminders,root:process.cwd(),execute:(t,n,s,i)=>this.registry.execute(t,n,s,i),hasAgent:t=>!!this.registry.getAgent(t),send:t=>this.router.sendOutbound(t),fallbackDestination:e?{channel:e.channel,chatId:e.chatId,accountId:e.accountId}:void 0,isStopping:()=>this.shuttingDown,log:this.log})}scheduleMidnightHook(){let e=()=>{let t=new Date,n=new Date(t);n.setDate(n.getDate()+1),n.setHours(0,0,5,0);let s=n.getTime()-t.getTime();this.log(` Cost tracking: next run in ${Math.round(s/6e4)}min`),this.midnightTimer=setTimeout(async()=>{await this.runDailyCostReport(),e()},Math.max(s,6e4))};e()}async runDailyCostReport(){let e=new Date(Date.now()-864e5).toISOString().slice(0,10),t=this.registry.getTokenTracker();if(t.hasTokenCostsEntry(e)){this.log(` Cost tracking: ${e} already logged, skipping`);return}let n=t.generateDailyReport(e);if(!n||n.totalTasks===0){this.log(` Cost tracking: no usage for ${e}, skipping`);return}t.appendToTokenCosts(n),this.log(` Cost tracking: ${e} \u2014 ${n.totalTasks} tasks, $${n.totalCost.toFixed(4)} (top: ${n.topAgent} $${n.topCost.toFixed(4)})`)}async startChannels(){if(this.config.channels.telegram.enabled){let e=this.config.channels.telegram.accounts;if(Object.keys(e).length>0){let t=this.config.channels.telegram.policy,n=new ct(e,{policy:{allowFrom:t?.allowFrom}},this.log);this.router.addChannel(n);let s=t?.allowFrom?.length??0,i=Object.entries(e).filter(([,a])=>!a.allowFrom&&s===0).length;i>0?this.log(` Telegram: enabled \u2014 WARNING: ${i} account(s) have no allowFrom (global or per-account). All incoming messages will be DROPPED.`):this.log(` Telegram: enabled \u2014 global allowFrom entries: ${s}`);let o=Object.entries(e).filter(([,a])=>(a.allowFrom??t?.allowFrom??[]).includes(cs)).map(([a])=>a);o.length>0&&this.log(` Telegram: public \u2014 anyone can message ${o.join(", ")} (allowFrom contains "${cs}")`)}}if(this.config.channels.whatsapp.enabled){let{setWhatsAppQR:e,setWhatsAppStatus:t}=await import("./whatsapp-state-LB3R32BK.js"),n=new us({sessionDir:this.config.channels.whatsapp.sessionDir,defaultAgent:this.config.channels.whatsapp.defaultAgent,allowFrom:this.config.channels.whatsapp.allowFrom,routes:this.config.channels.whatsapp.routes,throttle:{minMsBetweenCalls:this.config.channels.whatsapp.ingest?.throttle?.minMsBetweenCalls,maxCallsPerMinute:this.config.channels.whatsapp.ingest?.throttle?.maxCallsPerMinute},onQR:e,onStatus:t},this.log);this.router.addChannel(n);let s=this.config.channels.whatsapp.allowFrom??[];s.length===0?this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes) \u2014 WARNING: no allowFrom. All incoming messages will be DROPPED.`):s.some(i=>i.trim()==="*")?this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes) \u2014 WARNING: allowFrom contains "*". Every chat on the paired account is answered.`):this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes) \u2014 allowFrom entries: ${s.length}`)}if(this.config.channels.gitlab?.enabled&&this.config.channels.gitlab.token){let e=new ps({webhookPort:this.config.channels.gitlab.webhookPort,webhookSecret:this.config.channels.gitlab.webhookSecret,host:this.config.channels.gitlab.host,token:this.config.channels.gitlab.token,routes:this.config.channels.gitlab.routes,agentMappings:this.config.channels.gitlab.agentMappings,knownAgentIds:Object.keys(this.config.agents),agentUsernamePrefixes:this.config.channels.gitlab.agentUsernamePrefixes},this.log,this.hooks);e.setStatusComments(()=>this.config.requestStatus.channels.some(t=>t.toLowerCase()==="gitlab")),this.mesh&&(e.setMesh(this.mesh),e.setEditCommentForwarder(this.forwardCommentEdit("gitlab")),e.setReactForwarder(async(t,n,s,i,o,a,c)=>{let l=this.mesh.directory().find(u=>u.peer===t&&u.healthy);if(!l){this.log(`[gitlab] react forward: peer "${t}" not found or unhealthy`);return}let d=`${l.peerUrl}/gitlab/react`;try{let u=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(l.peer)},body:JSON.stringify({project:n,noteableType:s,noteableIid:i,noteId:o,agentId:a,name:c})}),g=await u.text().catch(()=>"");this.log(`[gitlab] react forward -> ${d} : ${u.status} ${g.slice(0,200)}`)}catch(u){this.log(`[gitlab] react forward FAILED -> ${d} : ${u.message}`)}}),e.setSendNoteForwarder(async(t,n,s,i,o,a)=>{let c=this.mesh.directory().find(d=>d.peer===t&&d.healthy);if(!c)return this.log(`[gitlab] send-note forward: peer "${t}" not found or unhealthy`),"";let l=`${c.peerUrl}/gitlab/send-note`;try{let d=await fetch(l,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(c.peer)},body:JSON.stringify({project:n,noteableType:s,noteableIid:i,agentId:o,text:a})}),u=await d.json().catch(()=>({}));return this.log(`[gitlab] send-note forward -> ${l} : ${d.status} noteId=${u.noteId||"?"}`),u.noteId||""}catch(d){return this.log(`[gitlab] send-note forward FAILED -> ${l} : ${d.message}`),""}}),e.setLogTimeForwarder(async(t,n,s,i,o,a)=>{let c=this.mesh.directory().find(d=>d.peer===t&&d.healthy);if(!c){this.log(`[gitlab] log-time forward: peer "${t}" not found or unhealthy`);return}let l=`${c.peerUrl}/gitlab/log-time`;try{let d=await fetch(l,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(c.peer)},body:JSON.stringify({project:n,noteableType:s,noteableIid:i,agentId:o,durationMs:a})}),u=await d.text().catch(()=>"");this.log(`[gitlab] log-time forward -> ${l} : ${d.status} ${u.slice(0,160)}`)}catch(d){this.log(`[gitlab] log-time forward FAILED -> ${l} : ${d.message}`)}})),e.setProjectRules(this.projectRules),this.router.addChannel(e),this.log(` GitLab: enabled (${this.config.channels.gitlab.routes.length} project routes, webhook :${this.config.channels.gitlab.webhookPort})`)}if(this.config.channels.github?.enabled){let e=this.config.channels.github;this.github=new ys({token:e.token,tokenFile:e.tokenFile,appId:e.appId,clientId:e.clientId,privateKeyFile:e.privateKeyFile,webhookSecret:e.webhookSecret,routes:e.routes,agentMappings:e.agentMappings,issueActions:e.issueActions,pullRequestActions:e.pullRequestActions,ignoreOwnChanges:e.ignoreOwnChanges,debounceSeconds:e.debounceSeconds},this.log),this.mesh&&(this.github.setEditCommentForwarder(this.forwardCommentEdit("github")),this.github.setSendCommentForwarder(async(t,n,s,i,o)=>{let a=this.mesh.directory().find(l=>l.peer===t&&l.healthy);if(!a)return this.log(`[github] send-comment forward: peer "${t}" not found or unhealthy`),"";let c=`${a.peerUrl}/github/send-comment`;try{let l=await fetch(c,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(a.peer)},body:JSON.stringify({repo:n,issueNumber:s,agentId:i,text:o})}),d=await l.json().catch(()=>({}));return this.log(`[github] send-comment forward -> ${c} : ${l.status} commentId=${d.commentId||"?"}`),d.commentId||""}catch(l){return this.log(`[github] send-comment forward FAILED -> ${c} : ${l.message}`),""}})),this.mesh&&this.github.setPeerPostingLogins(()=>this.mesh.directory().flatMap(t=>t.githubLogins)),this.github.setProjectRules(this.projectRules),this.router.addChannel(this.github),this.log(` GitHub: enabled (${e.routes.length} repo routes)`)}if(this.config.channels.ntfy?.enabled){let e=this.config.channels.ntfy;if(!e.topic)this.log(" ntfy: enabled but channels.ntfy.topic is unset \u2014 skipping");else{let{NtfyAdapter:t}=await import("./ntfy-Q4YHFKWW.js"),n=new t({server:e.server,topic:e.topic,token:e.token,defaultPriority:e.defaultPriority,defaultTitle:e.defaultTitle},this.log);this.router.addChannel(n),await n.start(),this.log(` ntfy: enabled (${e.server})`)}}if(this.config.channels.push?.enabled){let e=this.config.channels.push;if(e.relayTo){let{PushRelayAdapter:t}=await import("./push-PRFZMCIK.js"),{pushOrigin:n,PushRosterSync:s,ROSTER_CHECK_MS:i,relayTokenProblem:o}=await import("./push-bridge-276ZLSUT.js"),a=e.relayTo,c=n(this.config.node.name),l=o(a,this.config.mesh.peers,process.env.MESH_TOKEN);l&&this.log(` push: ${l}`);let d=new t(a,(m,f)=>this.postToPushHost(m,"/channel/send",f),this.log,c);this.router.addChannel(d),await d.start();let u=new Vn,g=new s({active:()=>u.activePhoneIds(),send:m=>this.postToPushHost(a,"/push/app",{op:"roster",origin:c,active:m}),log:this.log});this.pushRosterTimer=setInterval(()=>{g.tick()},i),this.pushRosterTimer.unref?.()}else if(!e.subject)this.log(" push: enabled but channels.push.subject is unset \u2014 skipping");else{let t=ii();if(!t)this.log(" push: enabled but the SQLite database is unavailable \u2014 skipping");else{let{PushAdapter:n,isRemoteDevice:s}=await import("./push-PRFZMCIK.js"),{peerOrigins:i}=await import("./push-bridge-276ZLSUT.js"),{PushStore:o}=await import("./push-store-L5QHMSST.js"),{pushKeysPath:a,readPushKeys:c}=await import("./push-keys-2DTD7YNQ.js"),{default:l}=await import("web-push"),d=new Vn,u=a(e.keysFile),g=new n({store:new o(t),keys:()=>c(u),subject:e.subject,ttlSeconds:e.ttlSeconds,keepRecent:e.keepRecent,deviceActive:b=>s(b)?i(this.config.mesh.peers).has(b.slice(0,b.indexOf(":"))):d.isActive(b),sender:(b,k,S)=>l.sendNotification(b,k,S),log:this.log});this.router.addChannel(g),await g.start();let m=new o(t);this.pushHost={store:()=>m,publicKey:()=>c(u)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts};let{attachAnnouncePush:f}=await import("./push-announce-PM5FZJRW.js"),{PushPrefs:w}=await import("./push-prefs-YOJNTOJF.js");f({bus:J(),store:new o(t),prefs:new w(t),send:b=>g.send(b),log:this.log})}}}if(this.config.channels.webrtc?.enabled){let e=this.config.channels.webrtc;if(this.webrtc=new Md(this.config.node.name,e.allowedCallers,this.log),this.mesh&&this.webrtc.setForwarder(async(t,n)=>{try{return await this.mesh.sendSignal(t,n)}catch(s){return this.log(`[webrtc] forward to "${t}" failed: ${s.message}`),!1}}),e.ringNotify.length>0){let t=e.callUrlBase||`http://${this.config.node.bind}`;this.webrtc.setRingHandler(async n=>{let s=_d(n,t);for(let i of e.ringNotify)try{await this.router.sendOutbound({channel:i.channel,chatId:i.chatId,text:s,parseMode:"plain",...i.accountId?{accountId:i.accountId}:{}})}catch(o){this.log(`[webrtc] ring notify via ${i.channel}:${i.chatId} failed: ${o.message}`)}})}if(e.bot.enabled){let t=e.bot,n=[...e.stunServers.map(s=>({urls:s})),...e.turnServers];this.botManager=new Ts({broker:this.webrtc,iceServers:n,whisperBackend:t.whisperBackend,whisperModel:t.whisperModel,whisperLanguage:t.whisperLanguage,mlxBinary:t.mlxBinary,maxCallMinutes:t.maxCallMinutes,log:this.log,onTranscript:async({invite:s,text:i,durationMs:o})=>{let a=t.transcriptChannel;if(!a)return;let c=`[${new Date().toLocaleTimeString()} \u2022 ${(o/1e3).toFixed(1)}s \u2022 ${s.target}]`;try{await this.router.sendOutbound({channel:a.channel,chatId:a.chatId,text:`${c}
1111
+ ${o.message}`,priority:o.priority,agentId:i})}catch(a){this.log(`[checkin] push for "${o.title}" failed: ${a?.message??a}`)}},{alert:ke(Ce(this.config.notifications.local))})},log:this.log};return kf(t,e)}stopReminders;startReminders(){let e=this.config.notifications?.destination;this.stopReminders=Sf({settings:this.config.reminders,root:process.cwd(),execute:(t,n,s,i)=>this.registry.execute(t,n,s,i),hasAgent:t=>!!this.registry.getAgent(t),send:t=>this.router.sendOutbound(t),fallbackDestination:e?{channel:e.channel,chatId:e.chatId,accountId:e.accountId}:void 0,isStopping:()=>this.shuttingDown,log:this.log})}scheduleMidnightHook(){let e=()=>{let t=new Date,n=new Date(t);n.setDate(n.getDate()+1),n.setHours(0,0,5,0);let s=n.getTime()-t.getTime();this.log(` Cost tracking: next run in ${Math.round(s/6e4)}min`),this.midnightTimer=setTimeout(async()=>{await this.runDailyCostReport(),e()},Math.max(s,6e4))};e()}async runDailyCostReport(){let e=new Date(Date.now()-864e5).toISOString().slice(0,10),t=this.registry.getTokenTracker();if(t.hasTokenCostsEntry(e)){this.log(` Cost tracking: ${e} already logged, skipping`);return}let n=t.generateDailyReport(e);if(!n||n.totalTasks===0){this.log(` Cost tracking: no usage for ${e}, skipping`);return}t.appendToTokenCosts(n),this.log(` Cost tracking: ${e} \u2014 ${n.totalTasks} tasks, $${n.totalCost.toFixed(4)} (top: ${n.topAgent} $${n.topCost.toFixed(4)})`)}async startChannels(){if(this.config.channels.telegram.enabled){let e=this.config.channels.telegram.accounts;if(Object.keys(e).length>0){let t=this.config.channels.telegram.policy,n=new ct(e,{policy:{allowFrom:t?.allowFrom}},this.log);this.router.addChannel(n);let s=t?.allowFrom?.length??0,i=Object.entries(e).filter(([,a])=>!a.allowFrom&&s===0).length;i>0?this.log(` Telegram: enabled \u2014 WARNING: ${i} account(s) have no allowFrom (global or per-account). All incoming messages will be DROPPED.`):this.log(` Telegram: enabled \u2014 global allowFrom entries: ${s}`);let o=Object.entries(e).filter(([,a])=>(a.allowFrom??t?.allowFrom??[]).includes(cs)).map(([a])=>a);o.length>0&&this.log(` Telegram: public \u2014 anyone can message ${o.join(", ")} (allowFrom contains "${cs}")`)}}if(this.config.channels.whatsapp.enabled){let{setWhatsAppQR:e,setWhatsAppStatus:t}=await import("./whatsapp-state-LB3R32BK.js"),n=new us({sessionDir:this.config.channels.whatsapp.sessionDir,defaultAgent:this.config.channels.whatsapp.defaultAgent,allowFrom:this.config.channels.whatsapp.allowFrom,routes:this.config.channels.whatsapp.routes,throttle:{minMsBetweenCalls:this.config.channels.whatsapp.ingest?.throttle?.minMsBetweenCalls,maxCallsPerMinute:this.config.channels.whatsapp.ingest?.throttle?.maxCallsPerMinute},onQR:e,onStatus:t},this.log);this.router.addChannel(n);let s=this.config.channels.whatsapp.allowFrom??[];s.length===0?this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes) \u2014 WARNING: no allowFrom. All incoming messages will be DROPPED.`):s.some(i=>i.trim()==="*")?this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes) \u2014 WARNING: allowFrom contains "*". Every chat on the paired account is answered.`):this.log(` WhatsApp: enabled (${this.config.channels.whatsapp.routes.length} routes) \u2014 allowFrom entries: ${s.length}`)}if(this.config.channels.gitlab?.enabled&&this.config.channels.gitlab.token){let e=new ps({webhookPort:this.config.channels.gitlab.webhookPort,webhookSecret:this.config.channels.gitlab.webhookSecret,host:this.config.channels.gitlab.host,token:this.config.channels.gitlab.token,routes:this.config.channels.gitlab.routes,agentMappings:this.config.channels.gitlab.agentMappings,knownAgentIds:Object.keys(this.config.agents),agentUsernamePrefixes:this.config.channels.gitlab.agentUsernamePrefixes},this.log,this.hooks);e.setStatusComments(()=>this.config.requestStatus.channels.some(t=>t.toLowerCase()==="gitlab")),this.mesh&&(e.setMesh(this.mesh),e.setEditCommentForwarder(this.forwardCommentEdit("gitlab")),e.setReactForwarder(async(t,n,s,i,o,a,c)=>{let l=this.mesh.directory().find(u=>u.peer===t&&u.healthy);if(!l){this.log(`[gitlab] react forward: peer "${t}" not found or unhealthy`);return}let d=`${l.peerUrl}/gitlab/react`;try{let u=await fetch(d,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(l.peer)},body:JSON.stringify({project:n,noteableType:s,noteableIid:i,noteId:o,agentId:a,name:c})}),g=await u.text().catch(()=>"");this.log(`[gitlab] react forward -> ${d} : ${u.status} ${g.slice(0,200)}`)}catch(u){this.log(`[gitlab] react forward FAILED -> ${d} : ${u.message}`)}}),e.setSendNoteForwarder(async(t,n,s,i,o,a)=>{let c=this.mesh.directory().find(d=>d.peer===t&&d.healthy);if(!c)return this.log(`[gitlab] send-note forward: peer "${t}" not found or unhealthy`),"";let l=`${c.peerUrl}/gitlab/send-note`;try{let d=await fetch(l,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(c.peer)},body:JSON.stringify({project:n,noteableType:s,noteableIid:i,agentId:o,text:a})}),u=await d.json().catch(()=>({}));return this.log(`[gitlab] send-note forward -> ${l} : ${d.status} noteId=${u.noteId||"?"}`),u.noteId||""}catch(d){return this.log(`[gitlab] send-note forward FAILED -> ${l} : ${d.message}`),""}}),e.setLogTimeForwarder(async(t,n,s,i,o,a)=>{let c=this.mesh.directory().find(d=>d.peer===t&&d.healthy);if(!c){this.log(`[gitlab] log-time forward: peer "${t}" not found or unhealthy`);return}let l=`${c.peerUrl}/gitlab/log-time`;try{let d=await fetch(l,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(c.peer)},body:JSON.stringify({project:n,noteableType:s,noteableIid:i,agentId:o,durationMs:a})}),u=await d.text().catch(()=>"");this.log(`[gitlab] log-time forward -> ${l} : ${d.status} ${u.slice(0,160)}`)}catch(d){this.log(`[gitlab] log-time forward FAILED -> ${l} : ${d.message}`)}})),e.setProjectRules(this.projectRules),this.router.addChannel(e),this.log(` GitLab: enabled (${this.config.channels.gitlab.routes.length} project routes, webhook :${this.config.channels.gitlab.webhookPort})`)}if(this.config.channels.github?.enabled){let e=this.config.channels.github;this.github=new ys({token:e.token,tokenFile:e.tokenFile,appId:e.appId,clientId:e.clientId,privateKeyFile:e.privateKeyFile,webhookSecret:e.webhookSecret,routes:e.routes,agentMappings:e.agentMappings,issueActions:e.issueActions,pullRequestActions:e.pullRequestActions,ignoreOwnChanges:e.ignoreOwnChanges,debounceSeconds:e.debounceSeconds},this.log),this.mesh&&(this.github.setEditCommentForwarder(this.forwardCommentEdit("github")),this.github.setSendCommentForwarder(async(t,n,s,i,o)=>{let a=this.mesh.directory().find(l=>l.peer===t&&l.healthy);if(!a)return this.log(`[github] send-comment forward: peer "${t}" not found or unhealthy`),"";let c=`${a.peerUrl}/github/send-comment`;try{let l=await fetch(c,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(a.peer)},body:JSON.stringify({repo:n,issueNumber:s,agentId:i,text:o})}),d=await l.json().catch(()=>({}));return this.log(`[github] send-comment forward -> ${c} : ${l.status} commentId=${d.commentId||"?"}`),d.commentId||""}catch(l){return this.log(`[github] send-comment forward FAILED -> ${c} : ${l.message}`),""}})),this.mesh&&this.github.setPeerPostingLogins(()=>this.mesh.directory().flatMap(t=>t.githubLogins)),this.github.setProjectRules(this.projectRules),this.router.addChannel(this.github),this.log(` GitHub: enabled (${e.routes.length} repo routes)`)}if(this.config.channels.ntfy?.enabled){let e=this.config.channels.ntfy;if(!e.topic)this.log(" ntfy: enabled but channels.ntfy.topic is unset \u2014 skipping");else{let{NtfyAdapter:t}=await import("./ntfy-Q4YHFKWW.js"),n=new t({server:e.server,topic:e.topic,token:e.token,defaultPriority:e.defaultPriority,defaultTitle:e.defaultTitle},this.log);this.router.addChannel(n),await n.start(),this.log(` ntfy: enabled (${e.server})`)}}if(this.config.channels.push?.enabled){let e=this.config.channels.push;if(e.relayTo){let{PushRelayAdapter:t}=await import("./push-PRFZMCIK.js"),{pushOrigin:n,PushRosterSync:s,ROSTER_CHECK_MS:i,relayTokenProblem:o}=await import("./push-bridge-P7HH25VN.js"),a=e.relayTo,c=n(this.config.node.name),l=o(a,this.config.mesh.peers,process.env.MESH_TOKEN);l&&this.log(` push: ${l}`);let d=new t(a,(m,f)=>this.postToPushHost(m,"/channel/send",f),this.log,c);this.router.addChannel(d),await d.start();let u=new Vn,g=new s({active:()=>u.activePhoneIds(),send:m=>this.postToPushHost(a,"/push/app",{op:"roster",origin:c,active:m}),log:this.log});this.pushRosterTimer=setInterval(()=>{g.tick()},i),this.pushRosterTimer.unref?.()}else if(!e.subject)this.log(" push: enabled but channels.push.subject is unset \u2014 skipping");else{let t=ii();if(!t)this.log(" push: enabled but the SQLite database is unavailable \u2014 skipping");else{let{PushAdapter:n,isRemoteDevice:s}=await import("./push-PRFZMCIK.js"),{peerOrigins:i}=await import("./push-bridge-P7HH25VN.js"),{PushStore:o}=await import("./push-store-L5QHMSST.js"),{pushKeysPath:a,readPushKeys:c}=await import("./push-keys-2DTD7YNQ.js"),{default:l}=await import("web-push"),d=new Vn,u=a(e.keysFile),g=new n({store:new o(t),keys:()=>c(u),subject:e.subject,ttlSeconds:e.ttlSeconds,keepRecent:e.keepRecent,deviceActive:b=>s(b)?i(this.config.mesh.peers).has(b.slice(0,b.indexOf(":"))):d.isActive(b),sender:(b,k,S)=>l.sendNotification(b,k,S),log:this.log});this.router.addChannel(g),await g.start();let m=new o(t);this.pushHost={store:()=>m,publicKey:()=>c(u)?.publicKey??null,keepRecent:e.keepRecent,allowedHosts:e.allowedHosts};let{attachAnnouncePush:f}=await import("./push-announce-PM5FZJRW.js"),{PushPrefs:w}=await import("./push-prefs-YOJNTOJF.js");f({bus:J(),store:new o(t),prefs:new w(t),send:b=>g.send(b),log:this.log})}}}if(this.config.channels.webrtc?.enabled){let e=this.config.channels.webrtc;if(this.webrtc=new Md(this.config.node.name,e.allowedCallers,this.log),this.mesh&&this.webrtc.setForwarder(async(t,n)=>{try{return await this.mesh.sendSignal(t,n)}catch(s){return this.log(`[webrtc] forward to "${t}" failed: ${s.message}`),!1}}),e.ringNotify.length>0){let t=e.callUrlBase||`http://${this.config.node.bind}`;this.webrtc.setRingHandler(async n=>{let s=_d(n,t);for(let i of e.ringNotify)try{await this.router.sendOutbound({channel:i.channel,chatId:i.chatId,text:s,parseMode:"plain",...i.accountId?{accountId:i.accountId}:{}})}catch(o){this.log(`[webrtc] ring notify via ${i.channel}:${i.chatId} failed: ${o.message}`)}})}if(e.bot.enabled){let t=e.bot,n=[...e.stunServers.map(s=>({urls:s})),...e.turnServers];this.botManager=new Ts({broker:this.webrtc,iceServers:n,whisperBackend:t.whisperBackend,whisperModel:t.whisperModel,whisperLanguage:t.whisperLanguage,mlxBinary:t.mlxBinary,maxCallMinutes:t.maxCallMinutes,log:this.log,onTranscript:async({invite:s,text:i,durationMs:o})=>{let a=t.transcriptChannel;if(!a)return;let c=`[${new Date().toLocaleTimeString()} \u2022 ${(o/1e3).toFixed(1)}s \u2022 ${s.target}]`;try{await this.router.sendOutbound({channel:a.channel,chatId:a.chatId,text:`${c}
1112
1112
  ${i}`,parseMode:"plain",...a.accountId?{accountId:a.accountId}:{}})}catch(l){this.log(`[bot-manager] transcript send via ${a.channel}:${a.chatId} failed: ${l.message}`)}}}),this.log(` WebRTC bot: enabled (whisper=${t.whisperBackend}, default-agent=${t.defaultAgentId||"(none)"}, transcript=${t.transcriptChannel?`${t.transcriptChannel.channel}:${t.transcriptChannel.chatId}`:"(none)"})`)}this.cameraWatch=this.createCameraWatch(),this.log(` WebRTC signaling: enabled (stun=${e.stunServers.length}, turn=${e.turnServers.length}, allowedCallers=${e.allowedCallers.length||"all"}, ringNotify=${e.ringNotify.length}, bot=${e.bot.enabled?"on":"off"}, camera-bot frames=${e.camera.bot.frameIntervalSeconds?`every ${e.camera.bot.frameIntervalSeconds}s`:"on demand"})`)}await this.bootWorkflowEngine(),this.registry.getSessionStore().setAdapterResolver(e=>this.router.getChannel(e)),await this.router.startAll(),this.delegations.recover().then(e=>{e&&this.log(`[delegation] ${e} delegation(s) lost in the restart were reported to their callers`)}).catch(e=>this.log(`[delegation] recovery failed: ${e?.message??e}`))}async bootWorkflowEngine(){let e=this.config.workflows;if(!e?.enabled){this.log(" Workflows: disabled (set workflows.enabled to turn the engine on)");return}let t=new Al({baseDir:ne(process.cwd(),e.dir)}),n=new Rl({baseDir:ne(process.cwd(),e.dir),nodeId:this.config.node.id}),s={};for(let k of this.router.getChannelNames()){let S=this.router.getChannel(k);S&&(s[k]=S)}let i={execute:async k=>{let S=Date.now();try{let I=k.workflowRunId?`workflow:${k.workflowRunId}`:"workflow:adhoc",C,N=await this.registry.execute({agentId:k.agentId,message:k.message,workflowRunId:k.workflowRunId,timeoutMinutes:k.timeoutMinutes,autonomy:k.autonomy,context:{channel:"workflow",chatId:I,sender:"workflow"},onStart:R=>{C=R}});return{content:N.content??"",error:N.error,errorKind:N.errorKind,autonomyBlocks:N.autonomyBlocks,taskId:`wf-${k.workflowRunId??"na"}-${S.toString(36)}`,...C?{runTaskId:C}:{},durationMs:Date.now()-S}}catch(I){return{content:"",error:I.message}}}},o=this.mesh?{forwardTransition:async(k,S)=>{let I=this.mesh.directory().find(N=>N.peer===k&&N.healthy);if(!I){this.log(`[workflows] forward to "${k}" skipped \u2014 peer not found or unhealthy`);return}let C=`${I.peerUrl}/workflow/event`;try{let N=await fetch(C,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(I.peer)},body:JSON.stringify({payload:S})});N.ok||this.log(`[workflows] forward ${C} -> ${N.status}`)}catch(N){this.log(`[workflows] forward ${C} failed: ${N.message}`)}},broadcastTrigger:async k=>{let S=this.mesh.directory().filter(C=>C.healthy);if(S.length===0)return;let I=this.config.node.id;this.log(`[workflows/mesh] broadcasting trigger source="${k.trigger.source}" chat="${k.trigger.chat??"*"}" -> ${S.length} peer(s): ${S.map(C=>C.peer).join(", ")}`),await Promise.allSettled(S.map(async C=>{let N=`${C.peerUrl}/workflow/event`;try{let R=await fetch(N,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(C.peer)},body:JSON.stringify({kind:"trigger",fromPeer:I,payload:k}),signal:AbortSignal.timeout(5e3)});R.ok||this.log(`[workflows/mesh] broadcastTrigger ${C.peer} -> ${R.status}`)}catch(R){this.log(`[workflows/mesh] broadcastTrigger ${C.peer} failed: ${R.message}`)}}))},forwardChannelSend:async k=>{let S=this.mesh.directory().filter(A=>A.healthy&&A.channels?.includes(k.channel));if(S.length===0)throw new Error(`no healthy mesh peer hosts channel "${k.channel}"`);let I=S[0],C=`${I.peerUrl}/channel/send`,N=await fetch(C,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(I.peer)},body:JSON.stringify(k),signal:AbortSignal.timeout(15e3)});if(!N.ok){let A=await N.text().catch(()=>"");throw new Error(`peer ${I.peer} /channel/send -> ${N.status} ${A.slice(0,200)}`)}return{messageId:(await N.json().catch(()=>({}))).messageId??null}}}:void 0,{TimerService:a}=await import("./timers-KK7GF77Y.js"),c=new a({baseDir:e.dir?ne(process.cwd(),e.dir):void 0,log:k=>this.log(k)}),l={notify:(k,S)=>this.notifyOwner(S.meta?.title?`Workflow: ${S.meta.title}`.slice(0,120):"Workflow",k,S.meta?.startedBy??"workflow",3),ask:async(k,S,I)=>{let C=We(process.cwd(),{...k,if_silent:"discard",raised_by:S.meta?.startedBy??t.get(S.workflowId)?.ownerAgent??"workflow"},{settings:this.config.approvals,origin:{kind:"workflow",runId:S.id,nodeId:I}});if(!C.ok)throw new Error(C.error);return this.log(`[workflows] run ${S.id}: card ${C.card.id} for step "${I}"`),{cardId:C.card.id}}},d=new Wl({store:t,runs:n,nodeId:this.config.node.id,channels:s,agents:i,forwarder:o,timers:c,events:this.events,log:k=>this.log(k),owner:l,followUp:()=>this.config.workflows.followUp,onRunEnded:async(k,S)=>{let{title:I,message:C}=td(k,S);await this.notifyOwner(I,C,k.meta?.startedBy??"workflow",k.status==="completed"?3:4),this.workflowRequestEnded(k)},onBlocked:async(k,S,I,C)=>{let{title:N,message:R}=sd(k,S,I,C);await this.notifyOwner(N,R,k.meta?.startedBy??"workflow",4);let A=k.meta?.requestId;A&&this.requests?.store.needsAttention(A,`Workflow step "${I}" is blocked: ${C}`,Date.now())&&this.requests.store.markNotified(A,Date.now())}});c.start();let u=Hl(d);for(let[k,S]of Object.entries(u))S&&this.hooks.registerHandler(k,`workflows:${k}`,S,50);this.workflowDispatcher=d,this.workflowStore=t,this.workflowRuns=n,this.registry.setWorkflowRunStore(n);try{let k=n.moveTaskRuns();k&&this.log(` Workflows: moved ${k} task run(s) to their own folder`)}catch(k){this.log(` Workflows: moving task runs failed (non-fatal): ${k?.message||k}`)}try{let k=ld(n);k&&this.log(` Workflows: closed ${k} task run(s) cut off by the last stop`)}catch(k){this.log(` Workflows: closing cut-off task runs failed (non-fatal): ${k?.message||k}`)}let g=()=>{try{let k=n.pruneTaskRuns(this.config.workflows.required?.retentionDays??30);k&&this.log(` Workflows: removed ${k} task run(s) past workflows.required.retentionDays`)}catch(k){this.log(` Workflows: pruning task runs failed (non-fatal): ${k?.message||k}`)}};g(),this.taskRunPrune&&clearInterval(this.taskRunPrune),this.taskRunPrune=setInterval(g,6*60*60*1e3),this.taskRunPrune.unref?.(),this.webhooks.setWorkflowDispatcher(d),this.registry.setWorkflowAutoRunner(async({workflowId:k,agentId:S,channel:I,chatId:C,message:N,payload:R,follow:A})=>{let M=t.get(k);if(!M)throw new Error(`auto-run target workflow not found: ${k}`);let j=zl(M,{chatId:C,channel:I,message:typeof R.message=="string"?R.message:void 0,agentId:typeof R.agentId=="string"?R.agentId:void 0,senderId:typeof R.senderId=="string"?R.senderId:void 0,senderUsername:typeof R.senderUsername=="string"?R.senderUsername:void 0});if(j.missing.length>0)throw new Error(`inputSchema requires ${j.missing.join(", ")} \u2014 chatId+defaults filled [chatId: ${j.filledFrom.chatId.join(",")||"\u2014"} | defaults: ${j.filledFrom.defaults.join(",")||"\u2014"}]; auto-run skipped (operator can fill manually or extend the inputSchema).`);if(this.log(`[workflows] auto-run input resolution for ${k}: passthrough=[${j.filledFrom.passthrough.join(",")}] chatId=[${j.filledFrom.chatId.join(",")}] defaults=[${j.filledFrom.defaults.join(",")}]`),A){let y=await d.startRun({workflowId:k,inputs:{...j.inputs,requestedBy:S,channel:I,chatId:C},meta:{title:N.replace(/\s+/g," ").trim().slice(0,80)||M.title,tags:[`agent:${S}`],startedBy:S}});if(!y.run)throw new Error(y.error??`could not start ${k}`);return{runId:y.run.id,title:M.title}}let E={backend:"manual",id:C||`auto-${Date.now().toString(36)}`},h=`auto:${k}:${C}:${Date.now()}`;return{runId:(await d.dispatchWorkflow({workflowId:k,entityRef:E,event:{id:h,payload:j.inputs},trigger:{source:"manual"}})).run?.id}});let{cronTimers:m,hookSubscribers:f}=Jl({store:t,dispatcher:d,hooks:this.hooks,log:k=>this.log(k),forgeUsernames:k=>[...ot(this.config.channels.gitlab?.agentMappings,"gitlabUsernames",k),...ot(this.config.channels.github?.agentMappings,"githubUsernames",k)]});this.workflowPolls=new Xl({store:t,dispatcher:d,log:k=>this.log(k)});let w=this.workflowPolls.start(),b=t.list().length;this.log(` Workflows: enabled (${b} definition${b===1?"":"s"} loaded from ${e.dir}, editor=${e.editor}, cron=${m}, hook=${f}, poll=${w})`);try{let{detectConflicts:k}=await import("./conflict-detector-KS7OSS45.js"),S=k(t.list(),this.config);if(S.length>0){this.log(` Workflows: ${S.length} dispatch conflict(s) detected`);for(let I of S)this.log(` [${I.severity}] ${I.workflowId}: ${I.summary}`),this.log(` \u2192 ${I.suggestion}`)}}catch(k){this.log(` Workflows: conflict-detector failed: ${k.message}`)}}async startHttpApi(){let[e,t]=this.config.node.bind.split(":"),n=parseInt(t||"18800",10);this.httpServer=cA(async(s,i)=>{if(Mi(s.headers)==="foreign"&&Su(s.method)){this.log(`[auth] \u2717 refused ${s.method} ${(s.url||"").split("?")[0]} from a page on another origin (${s.headers.origin||s.headers["sec-fetch-site"]})`),this.json(i,403,{error:"Forbidden: request from a page on another origin"});return}if(this.shuttingDown&&Eu(s.method,(s.url||"/").split("?")[0])){i.setHeader("Retry-After","30"),this.json(i,503,{error:"daemon is restarting; retry shortly"});return}if(s.method==="OPTIONS"){i.writeHead(204),i.end();return}await this.handleHttp(s,i)}),this.httpServer.on("error",s=>{s.code==="EADDRINUSE"?(this.log(` ERROR: Port ${n} is already in use. Retrying in 5s...`),setTimeout(()=>{this.httpServer?.close(),this.httpServer?.listen(n,e||"0.0.0.0")},5e3)):this.log(` HTTP error: ${s.message}`)}),this.httpServer.listen(n,e||"0.0.0.0",()=>{this.log(` HTTP API: http://${e||"0.0.0.0"}:${n}`);let s=Of(this.config,i=>!!this.registry.getAgent(i));for(let i of s)this.log(` [mesh-relay] \u26A0 inbox "${i.name}" names agent "${i.agent}", which is not on this node \u2014 it will refuse messages`)}),this.attachSweep=setInterval(()=>{try{let s=de();s.sweep(),s.prune()}catch{}},1e3),this.attachSweep.unref?.()}delegationGate(e,t,n,s={}){let i=ja(e,t),o=La(i,this.registry),a=Ua(n.callee,o,this.registry,this.syncWaits);if(a)return{refused:a};if(!n.peer&&this.registry.getAgent(n.callee)){let d=Uw(n.callee,i,o,this.registry,this.syncWaits);if(d)return{refused:d}}let c=s.callback===!1?null:this.startCallback(t,o,n);if(c)return{accepted:c};let l;return{track:{...o?{root:Ye(o.context,o.agentId)}:{},onStart:d=>{l=d,o?.taskId&&this.syncWaits.begin(o.taskId,d,Fa(o,this.syncWaits))},end:()=>{l&&this.syncWaits.end(l)}}}}startCallback(e,t,n){let s=e.async===!0?!0:e.async===!1?!1:void 0;if(!t||!this.delegations.shouldCallback(t,s))return null;let i=n.peer;if(!i&&!this.registry.getAgent(n.callee)){let c=this.mesh?.findAgentPeer(n.callee);if(!c?.healthy)return null;i=c.peer}let o={};if(!i){let c=this.recordInboundDispatch(n.callee,{channel:"a2a",sender:`agent:${t.agentId}`,chatId:`a2a:${t.agentId}:${n.callee}`,initiator:Ye(t.context,t.agentId)},n.message,t.agentId);c&&(o.intentRef=c)}let{taskId:a}=this.delegations.start({caller:t,callee:n.callee,peer:i,message:n.message,calleeContext:n.calleeContext,extras:o});return Ww(a,n.callee,i)}recordInboundDispatch(e,t,n,s,i=jc(this.config.people,t)?.id??null){if(ue("mesh")!=="off")try{let o=Jf(le(),{agentId:e,senderAgentId:s,context:t},Vf(e,s,t,n,i),{agentId:e,outcome:"dispatched",reason:s?`from ${s}`:null});return o.outcome==="dispatched"?{eventId:o.eventId,decidedBy:o.decidedBy}:void 0}catch(o){this.log(`[ledger] ${t?.channel??"mesh"} agent="${e}" record failed: ${o?.message??o}`);return}}broadcastSSE(e,t){if(this.sseClients.size===0)return;let n=`event: ${e}
1113
1113
  data: ${JSON.stringify({time:new Date().toISOString(),message:t})}
1114
1114
 
@@ -1175,5 +1175,5 @@ data: ${JSON.stringify(G)}
1175
1175
 
1176
1176
  `)}catch{}},D=setInterval(()=>{try{t.write(`: ping
1177
1177
 
1178
- `)}catch{}},15e3);D.unref?.();let L=new AbortController;t.on("close",()=>{t.writableEnded||L.abort()});try{for await(let F of this.mesh.sendTaskStream(h.peer,h.message,h.agent,{context:h.context,signal:L.signal,vouchOwner:v}))x(F.event,F.data)}catch(F){x("error",{error:F?.message??String(F)})}finally{clearInterval(D);try{t.end()}catch{}}break}let _=h.context,P=typeof h.senderAgentId=="string"?h.senderAgentId:void 0;if(Gw(h,!0)==="callback"){let x=this.delegationGate(e,h,{callee:h.agent,peer:h.peer,message:h.message,calleeContext:_});if(!("track"in x)){let D=Fr(x);this.json(t,D.status,D.body);break}}if(h.async===!0){let x=_?.channel,D=_?.chatId;if(!x||!D){this.json(t,400,{error:"async requires context.channel and context.chatId \u2014 there is no route back otherwise"});return}let L=`mesh-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;this.json(t,202,{accepted:!0,taskId:L,deliverTo:`${x}:${D}`,note:"result will be delivered to the originating chat when the peer finishes"});let F=h.peer,G=h.agent,Z=this.mesh;(async()=>{let W=Date.now(),V;try{V=await Z.sendTask(F,h.message,G,{vouchOwner:v,context:_,senderAgentId:P}),this.log(`[mesh/task async ${L}] ${F}/${G??"default"} finished in ${Date.now()-W}ms`)}catch(B){V=`Delegation to ${F}/${G??"default"} failed: ${B?.message??B}`,this.log(`[mesh/task async ${L}] failed: ${B?.message??B}`)}try{await this.router.sendOutbound({channel:x,chatId:D,text:V,agentId:_?.agentId??P,accountId:_?.accountId})}catch(B){this.log(`[mesh/task async ${L}] delivery failed: ${B?.message??B}`)}})();break}let O=await this.mesh.sendTask(h.peer,h.message,h.agent,{context:_,senderAgentId:P,vouchOwner:v});this.json(t,200,{response:O});break}case"POST /webrtc/signal/out":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await H(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let y=await this.webrtc.handleOutgoing(p);this.json(t,y.ok?200:400,y);break}case"POST /webrtc/signal":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await H(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let y=this.webrtc.handleIncoming(p);this.json(t,y.ok?200:400,y);break}case"POST /webrtc/bot/invite":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled (channels.webrtc.bot.enabled=false)"});return}let h=await H(e),p=h.callId,y=h.target,v=h.agentId||this.config.channels.webrtc?.bot.defaultAgentId;if(!p||!y||!v){this.json(t,400,{error:"Missing: callId, target, agentId (or defaultAgentId in config)"});return}let $=await this.botManager.invite({callId:p,target:y,agentId:v});this.json(t,$.ok?200:500,$);break}case"GET /webrtc/bots":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active()});break}case"GET /webrtc/history":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active(),history:this.botManager.history()});break}case"GET /webrtc/config":{let h=this.config.channels.webrtc;if(!h?.enabled){this.json(t,404,{error:"WebRTC signaling not enabled"});return}this.json(t,200,{localName:this.config.node.name,iceServers:[...h.stunServers.map(p=>({urls:p})),...h.turnServers],peers:this.mesh?.directory().map(p=>({name:p.peer,healthy:p.healthy}))||[],camera:h.camera,agents:this.registry.list().map(p=>({id:p.id,name:p.name}))});break}case"GET /.well-known/agent-card.json":this.json(t,200,{name:this.config.node.name,description:`AgentX daemon node "${this.config.node.name}"`,url:`http://${this.config.node.bind}`,version:"1.0.0",capabilities:{streaming:!1,pushNotifications:!1,stateTransitionHistory:!1},skills:this.registry.list().map(h=>{let p=this.config.agents[h.id]||{},y=typeof p.description=="string"&&p.description.trim()||pA(p.systemPrompt)||`Agent "${h.name}" (${h.tier})`,v=Array.isArray(p.mentions)?p.mentions.slice(0,4):[];return{id:h.id,name:h.name,description:y,tags:[h.tier,...v],color:fe(h.id,p).color}}),channels:this.router.getChannelNames(),githubLogins:this.github?.postingAccounts()??[],defaultInputModes:["text"],defaultOutputModes:["text"]});break;case"GET /wiki/agents":{let h=this.registry.getWikiHub();this.json(t,200,{nodeId:this.config.node.id,agents:h.summary()});break}case"GET /wiki/entries":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent")||void 0,y=n.searchParams.get("after")||void 0,v=p?h.getAgentEntries(p):h.getSharedStore().listEntries({after:y});this.json(t,200,{nodeId:this.config.node.id,count:v.length,entries:v.map($=>({id:$.id,date:$.date,agentId:$.agentId,source:$.source,sourceContext:$.sourceContext,content:$.content}))});break}case"GET /wiki/articles":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent");if(!p){this.json(t,400,{error:"?agent= required"});break}let v=h.getAgentWiki(p).rebuildIndex();this.json(t,200,{nodeId:this.config.node.id,agentId:p,articles:v.articles});break}case"GET /wiki/article":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent"),y=n.searchParams.get("path");if(!p||!y){this.json(t,400,{error:"?agent= and ?path= required"});break}let $=h.getAgentWiki(p).readArticle(y);if(!$){this.json(t,404,{error:"Article not found"});break}this.json(t,200,{nodeId:this.config.node.id,agentId:p,path:$.path,title:$.meta.title,tags:$.meta.tags,owner:$.meta.owner,created:$.meta.created,lastUpdated:$.meta.lastUpdated,sources:$.meta.sources,content:$.content});break}case"GET /wiki/notes":{let{NoteStore:h}=await import("./notes-WJJEJ4CJ.js"),p=n.searchParams.get("status")||"waiting";if(!["waiting","open","patched","rejected","deferred","expired","all"].includes(p)){this.json(t,400,{error:"status must be waiting, open, patched, rejected, deferred, expired or all"});break}let y=Math.max(1,Math.min(200,parseInt(n.searchParams.get("limit")||"50",10)||50)),$=new h(this.registry.getWikiHub().getBaseDir()).list(p==="all"?void 0:p);this.json(t,200,{nodeId:this.config.node.id,enabled:this.config.wikiNotes.enabled,inbox:this.config.wikiNotes.inbox??null,crons:this.config.wikiNotes.crons,absorbAgent:this.config.wikiNotes.absorbAgent??null,total:$.length,notes:$.slice(-y).reverse()});break}case"POST /wiki/notes":{let{NoteStore:h,validateNote:p}=await import("./notes-WJJEJ4CJ.js"),y=this.config.wikiNotes;if(!y.enabled||!y.inbox){this.json(t,409,{error:"wiki notes are off on this node: set wikiNotes.enabled and wikiNotes.inbox"});break}let v=await H(e),$=p({...v,to:y.inbox});if("error"in $){this.json(t,400,{error:$.error});break}let T=$.note;if(this.registry.getAgent(y.inbox)){try{let{note:O,added:x}=new h(this.registry.getWikiHub().getBaseDir()).add(T);this.json(t,x?201:200,{ok:!0,added:x,note:O,node:this.config.node.id})}catch(O){this.json(t,507,{error:O?.message??String(O)})}break}if(v.forwarded===!0){this.json(t,404,{error:`inbox agent "${y.inbox}" is not on this node`});break}let _=this.mesh?.findAgentPeer(y.inbox);if(!_){this.json(t,404,{error:`inbox agent "${y.inbox}" is not on this node or any known peer`});break}let P=this.mesh.directory().find(O=>O.peer===_.peer)?.peerUrl;if(!_.healthy||!P){this.json(t,503,{error:`the node hosting "${y.inbox}" (${_.peer}) is unreachable; try again later`});break}try{let O=await fetch(`${P.replace(/\/$/,"")}/wiki/notes`,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(_.peer)},body:JSON.stringify({...T,fromNode:T.fromNode||this.config.node.id,forwarded:!0}),signal:AbortSignal.timeout(1e4)}),x=await O.json().catch(()=>({}));this.json(t,O.status,{...x,peer:_.peer})}catch(O){this.json(t,502,{error:`forward to ${_.peer} failed: ${O?.message??O}`,peer:_.peer})}break}case"GET /graph/schema":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,schema:h.loadSchema()});break}case"GET /graph/nodes":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,...h.loadNodes()});break}case"GET /graph/classifications":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}let p=n.searchParams.get("status")||"approved",y=Math.max(1,Math.min(1e3,parseInt(n.searchParams.get("limit")||"200",10)||200)),v=h.listByStatus(p,y);this.json(t,200,{nodeId:this.config.node.id,status:p,count:v.length,classifications:v});break}default:this.json(t,404,{error:"Not found",endpoints:["GET /health","GET /agents","GET /crons","GET /routines \u2014 schedules + cron/hook workflows with staleness flags","GET /mesh","GET /wiki/agents","GET /wiki/entries[?agent=X&after=YYYY-MM-DD]","GET /wiki/articles?agent=X","GET /wiki/notes[?status=waiting|open|patched|rejected|deferred|expired|all&limit=N]","POST /wiki/notes { from, change, source, date? } \u2014 a note for the wiki observe/sweep run","GET /graph/schema","GET /graph/nodes","GET /graph/classifications[?status=approved|pending|rejected&limit=N]","POST /task { agent, message, context?, freshSession?: bool }","GET /agents/:id \u2014 resolved agent config (permission, tier, model, persistentProcess, toolUseRequired)","POST /agents/:id/selftest { message? } \u2014 canary probe; runs a fresh-session task and reports {ok, durationMs, tokens, billedModel}","GET /traces[?agentId=&channel=&chatId=&workflowRunId=&status=&since=&until=&limit=]","GET /traces/:taskId \u2014 full per-task execution trace (steps + tokens)","GET /voice/history[?agent=&limit=&before=] \u2014 past voice exchanges, bounded summaries","GET /voice/history/:id \u2014 one voice exchange in full; POST /voice/history/:id/replay","GET /api/processes \u2014 live persistent claude processes (JSON)","POST /api/processes/kill { agentId, channel, chatId, reason? }","GET /api/actions/builtin \u2014 list shipped built-in typed actions","POST /api/actions/builtin/:name \u2014 run a built-in with JSON body input","POST /mesh/task { peer, message }","POST /webhook/:agentId[/:source] \u2014 webhook callback","POST /reload \u2014 re-read agentx.json (hot-swaps crons)","GET /usage/plan \u2014 Claude plan windows, cold-dispatch counters, active holds","POST /usage/plan/lift \u2014 drop the active Claude plan holds","GET /daemon/restart \u2014 in-flight count, service manager, pending restart","POST /daemon/restart \u2014 restart when idle { timeoutMinutes?, onTimeout? }","POST /daemon/restart/cancel","GET /.well-known/agent-card.json","GET /call \u2014 browser UI for P2P A/V calls (requires channels.webrtc.enabled)","GET /webrtc/config \u2014 ICE servers + peer directory for the call page","GET /webrtc/events?callId=&as= \u2014 SSE stream of signaling events","POST /webrtc/signal/out \u2014 browser-originated signal, forwarded to remote peer","POST /webrtc/signal \u2014 remote-peer-originated signal, fanned out to local browser","POST /webrtc/bot/invite { callId, target, agentId } \u2014 spawn a transcribing bot peer for a call","GET /webrtc/bots \u2014 active bot sessions","POST /webrtc/camera/watch { callId, agentId } \u2014 an agent watches the phone camera share","GET /webrtc/camera/watch \u2014 agents watching a camera now","POST /webrtc/camera/watch/:id/look { note? } \u2014 ask the watching agent what it sees","POST /webrtc/camera/watch/:id/stream { seconds, note? } \u2014 the agent keeps watching for a while (0 stops)","POST /webrtc/camera/look { agentId } \u2014 from an agent's run: the newest frame as a PNG path"]})}}catch(i){this.json(t,500,{error:i.message})}}async handleOpenAICompat(e,t,n){let s=await H(e);await xg(e,t,n,s,{execute:(i,o,a,c)=>this.registry.execute(i,o,a,c),agentIds:Object.keys(this.config.agents),cancel:(i,o,a,c)=>{let l=this.registry.list().find(d=>d.id===i)?.runningTasks.filter(d=>d.channel===o&&d.chatId===a)||[];for(let d of l)this.registry.cancelRunningTask(d.id,c)},log:i=>this.log(i)})}json(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n,null,2))}resolveGitlabTokenForAgent(e){if(!e)return{token:this.config.channels.gitlab?.token,source:"global"};let t=(this.config.channels.gitlab?.agentMappings||[]).find(s=>s.agentId===e);if(t?.token)return{token:t.token,source:"agentMappings"};let n=bm(this.config,e,"gitlab-user","tokenEnv");return n.status==="ok"&&n.value?{token:n.value,source:`integrations(${n.envVar})`}:this.config.channels.gitlab?.token?{token:this.config.channels.gitlab.token,source:"global"}:{token:void 0,source:n.status}}resolveTodayUsage(){let e=Zg();if(e==="json")return this.registry.getTodayUsage();let t=Qg(this.db);return e==="sqlite"||Object.keys(t.agents).length>0?t:this.registry.getTodayUsage()}installAgentMemorySurface(){let e=parseInt(this.config.node.bind.split(":")[1]||"18800",10);for(let t of this.registry.list()){let n=t.workspace;if(!(!n||!Wt(n)))try{let s=ne(n,".claude","skills");dk(s,{recursive:!0});let i=ne(s,vm);if(!Wt(i))Qa(i,Zo(e)),this.log(` memory-skill: installed remember.md \u2192 ${t.id}`);else{let o=$m(Cn(i,"utf-8"),e);o&&(Qa(i,o),this.log(` memory-skill: updated remember.md \u2192 ${t.id}`))}this.agentMemory.syncToWorkspace(t.id,n,this.config.session.memoryIndexMaxChars)}catch(s){this.log(` memory-skill: ${t.id} install failed \u2014 ${s?.message??s}`)}}}installAgentMcpConfig(){for(let[e,t]of Object.entries(this.config.agents)){let n=t.workspace;if(!n||!Wt(n))continue;let s=this.config.workflows.enabled&&(this.config.workflows.followUp.enabled&&(this.config.workflows.followUp.agents[e]??!0)||id(this.config.workflows,e)),i=Tl(Vc(t),this.config.requests.enabled||s?Il():null);try{switch(xl(n,i)){case"installed":this.log(` mcp: installed ${Object.keys(i).length} server(s) \u2192 ${e}`);break;case"updated":this.log(` mcp: updated .mcp.json (${Object.keys(i).length} server(s)) \u2192 ${e}`);break;case"removed":this.log(` mcp: removed managed .mcp.json (config now empty) \u2192 ${e}`);break;case"skipped-operator-owned":Object.keys(i).length>0&&this.log(` mcp: ${e} has operator-owned .mcp.json \u2014 skipping (delete file or marker to let agentx manage)`);break;case"noop":break}}catch(o){this.log(` mcp: ${e} install failed \u2014 ${o?.message??o}`)}}}workspaceFor(e){for(let t of this.registry.list())if(t.id===e)return t.workspace;return null}handleMemoryApi(e,t,n,s){return Zf(e,t,n,s,{mem:this.agentMemory,workspaceFor:i=>this.workspaceFor(i),runningTaskOwner:i=>this.registry.runningTaskOwner(i),indexMaxChars:()=>this.config.session.memoryIndexMaxChars})}async handleWorkflowEvent(e,t){if(!this.workflowDispatcher){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let n;try{n=await se(e)}catch(c){this.json(t,400,{error:"invalid JSON body",message:c.message});return}let s=n?.payload??n,i=s?.event,o=s?.entityRef;if(!i?.id||!o?.backend||!o?.id){this.json(t,400,{error:"missing event or entityRef"});return}let a=n?.kind;try{if(a==="trigger"&&s.trigger){let g=typeof n?.fromPeer=="string"?n.fromPeer:"unknown";this.log(`[workflows/mesh] received trigger from "${g}" source="${s.trigger.source}" chat="${s.trigger.chat??"*"}"`);let m=await this.workflowDispatcher.dispatch({trigger:s.trigger,entityRef:o,event:i,fromRemote:{peer:g}});this.log(`[workflows/mesh] dispatched broadcast: matched=${m.claimed.length} ${m.claimed.length?`(${m.claimed.map(f=>f.id).join(", ")})`:"[none \u2014 no workflow with mesh.allowRemote matched]"}`),this.json(t,202,{ok:!0,mode:"trigger-broadcast",matched:m.claimed.map(f=>f.id)});return}let d=(s.workflowId?this.workflowStore?.get(s.workflowId):null)?.nodes.find(g=>g.type.startsWith("trigger."))?.config??{},u={source:String(d.source??"hook"),project:d.filter?.project,repo:d.filter?.repo,chat:d.filter?.chat,labels:d.filter?.labels};await this.workflowDispatcher.dispatch({trigger:u,entityRef:o,event:i}),this.json(t,202,{ok:!0})}catch(c){this.log(`[workflows] /workflow/event failed: ${c.message}`),this.json(t,500,{error:c.message})}}async postToPushHost(e,t,n){let s=e.toLowerCase(),i=this.mesh?.directory().find(c=>c.peer.toLowerCase()===s);if(!i)throw new Error(`push: channels.push.relayTo "${e}" is not a mesh peer of this node`);let o=await fetch(`${i.peerUrl}${t}`,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(i.peer)},body:JSON.stringify(n),signal:AbortSignal.timeout(15e3)});if(!o.ok)throw new Error(`push: ${i.peer} ${t} -> ${o.status} ${(await o.text().catch(()=>"")).slice(0,200)}`);let a=await o.json().catch(()=>({}));if(t==="/channel/send")return a.messageId??void 0;if(typeof a.status!="number")throw new Error(`push: ${i.peer} ${t} gave no answer`);return{status:a.status,body:a.body??{}}}async handlePushApp(e,t){let n;try{n=await se(e)}catch(c){this.json(t,400,{error:"invalid JSON body",message:c.message});return}let{handlePushBridge:s,pushOrigin:i}=await import("./push-bridge-276ZLSUT.js"),o=this.config.channels.push;if(!o?.enabled){this.json(t,200,{status:503,body:{error:`Notifications are off on ${this.config.node.name}.`}});return}if(o.relayTo){if(n?.origin!==void 0){this.json(t,200,{status:409,body:{error:`${this.config.node.name} relays its notifications too (channels.push.relayTo = ${o.relayTo})`}});return}if(n?.op!=="app"){this.json(t,400,{error:"op must be app"});return}try{this.json(t,200,await this.postToPushHost(o.relayTo,"/push/app",{op:"app",origin:i(this.config.node.name),call:n.call}))}catch(c){this.log(`[push] /push/app to ${o.relayTo} failed: ${c.message}`),this.json(t,502,{error:c.message})}return}let a=this.pushBridgeCaller(e);"error"in a&&n?.op!=="roster"&&this.log(`[push] /push/app from ${e.socket?.remoteAddress||"?"} refused: ${a.error}`),this.json(t,200,s(n,a,this.pushHost??null,this.pushHost?void 0:`Notifications are not running on ${this.config.node.name}. Check channels.push.subject and the database there.`))}pushBridgeCaller(e){return Gd(String(e.headers.authorization||""),this.config.mesh.peers,process.env.MESH_TOKEN)}async handleChannelSend(e,t){let n;try{n=await se(e)}catch(l){this.json(t,400,{error:"invalid JSON body",message:l.message});return}let s=String(n?.channel??""),i=String(n?.chatId??""),o=String(n?.text??"");if(!s||!i||!o){this.json(t,400,{error:"channel, chatId, and text are required"});return}if(!this.router.getChannel(s)){this.json(t,404,{error:`channel "${s}" not hosted on this node`});return}let c;if(n.relayed===!0&&n.origin!==void 0){let l=this.pushBridgeCaller(e);if("origin"in l)c=l.origin;else if(i!=="default"){this.json(t,403,{error:l.error});return}}if(s==="push"&&i.includes(":")){let{scopedPushTarget:l}=await import("./push-bridge-276ZLSUT.js"),d=l(i,this.pushBridgeCaller(e));if("error"in d){this.json(t,403,{error:d.error});return}}try{let l=await this.router.sendOutbound({channel:s,chatId:i,text:o,accountId:typeof n.accountId=="string"?n.accountId:void 0,parseMode:typeof n.parseMode=="string"?n.parseMode:void 0,replyTo:typeof n.replyTo=="string"?n.replyTo:void 0,buttons:Array.isArray(n.buttons)?n.buttons:void 0,agentId:typeof n.agentId=="string"?n.agentId:void 0,relayed:n.relayed===!0?!0:void 0,origin:c},{recordInSession:!1});this.json(t,200,{ok:!0,messageId:l??null})}catch(l){this.log(`[mesh] /channel/send "${s}" failed: ${l.message}`),this.json(t,500,{error:l.message})}}async handleChannelChats(e,t,n={}){let s=new Set,i=[],o=[],a=(l,d)=>{let u=0;for(let g of l)!g.id||s.has(g.id)||(s.add(g.id),i.push({...g,source:d}),u++);u>0&&o.push(`${d}:${u}`)},c=this.router.getChannel(t);if(c?.listKnownChats)try{a(c.listKnownChats(),"local")}catch{}else if(c?.listChats)try{a(c.listChats().map(l=>({id:l.jid,name:l.name,kind:l.isGroup?"group":"dm"})),"local")}catch{}if(!n.localOnly&&this.mesh){let l=this.mesh.directory().filter(d=>d.healthy&&d.channels?.includes(t));await Promise.allSettled(l.map(async d=>{try{let u=await fetch(`${d.peerUrl}/channels/${encodeURIComponent(t)}/chats?local=1`,{headers:this.mesh.authHeaders(d.peer),signal:AbortSignal.timeout(5e3)});if(!u.ok)return;let g=await u.json();Array.isArray(g.chats)&&a(g.chats.map(m=>({id:m.id,name:m.name,kind:m.kind??"dm",accountId:m.accountId})),`mesh:${d.peer}`)}catch{}}))}this.json(e,200,{channel:t,source:o.join(", ")||"none",chats:i})}async handleWorkflowManualRun(e,t,n){if(!this.workflowDispatcher||!this.workflowStore){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let s;try{s=await se(e)}catch{s={}}try{let i=await km({get:o=>this.workflowStore.get(o),dispatchWorkflow:o=>this.workflowDispatcher.dispatchWorkflow(o),startRun:o=>this.workflowDispatcher.startRun(o)},n,s);this.json(t,i.status,i.body)}catch(i){this.log(`[workflows] manual run "${n}" failed: ${i.message}`),this.json(t,500,{error:i.message})}}},Za=ec;ft(Za,"MESH_PROTECTED_PATHS",new Set(["/task","/ask","/mesh/task","/mesh/inbox/send","/workflow/event","/workflow/transition","/channel/send","/push/app","/webrtc/signal","/gitlab/react","/gitlab/send-note","/gitlab/log-time","/channel/edit-comment","/github/send-comment"]));function pA(r){if(typeof r!="string")return"";let e=r.trim();if(!e)return"";let t=e.match(/^[^.!?\n]+[.!?]?/),n=(t?t[0]:e).trim();return n.length>140?n.slice(0,137)+"\u2026":n}function se(r){return new Promise((e,t)=>{let n="";r.setEncoding("utf8"),r.on("data",s=>{n+=s}),r.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(s){t(s)}}),r.on("error",t)})}function fA(r,e){let t=["model","workspace","tier","permissionMode","mcpServers"],n=new Set,s=new Set([...Object.keys(r),...Object.keys(e)]);for(let i of s){let o=r[i],a=e[i];if(!o||!a){n.add("add/remove");continue}for(let c of t)JSON.stringify(o[c])!==JSON.stringify(a[c])&&n.add(`${i}.${c}`)}return Array.from(n).slice(0,6)}async function H(r){return new Promise((e,t)=>{let n="";r.on("data",s=>n+=s.toString()),r.on("end",()=>{try{e(n?JSON.parse(n):{})}catch{e({})}}),r.on("error",t)})}hk();function SU(r){typeof r=="string"&&(_n.error(r),process.exit(1)),r instanceof Error&&(_n.error(r.message),process.exit(1)),_n.error("Something went wrong. Please try again."),process.exit(1)}export{CA as a,Ji as b,rt as c,Qt as d,tn as e,ct as f,us as g,Xh as h,Wg as i,lS as j,dS as k,Jg as l,Be as m,dt as n,zg as o,ut as p,yP as q,wP as r,Hs as s,y_ as t,o$ as u,Vo as v,FM as w,UM as x,GM as y,cm as z,L$ as A,VM as B,JM as C,fn as D,Dt as E,mn as F,kO as G,Um as H,EI as I,uD as J,ur as K,ha as L,ga as M,mr as N,fe as O,Py as P,kr as Q,xT as R,By as S,RT as T,Xy as U,Sr as V,In as W,xr as X,Rr as Y,ew as Z,Ra as _,Je as $,Re as aa,cw as ba,lw as ca,dw as da,uw as ea,Xr as fa,tk as ga,Ka as ha,sk as ia,nA as ja,OL as ka,Za as la,SU as ma};
1179
- //# sourceMappingURL=chunk-UPNKRCFX.js.map
1178
+ `)}catch{}},15e3);D.unref?.();let L=new AbortController;t.on("close",()=>{t.writableEnded||L.abort()});try{for await(let F of this.mesh.sendTaskStream(h.peer,h.message,h.agent,{context:h.context,signal:L.signal,vouchOwner:v}))x(F.event,F.data)}catch(F){x("error",{error:F?.message??String(F)})}finally{clearInterval(D);try{t.end()}catch{}}break}let _=h.context,P=typeof h.senderAgentId=="string"?h.senderAgentId:void 0;if(Gw(h,!0)==="callback"){let x=this.delegationGate(e,h,{callee:h.agent,peer:h.peer,message:h.message,calleeContext:_});if(!("track"in x)){let D=Fr(x);this.json(t,D.status,D.body);break}}if(h.async===!0){let x=_?.channel,D=_?.chatId;if(!x||!D){this.json(t,400,{error:"async requires context.channel and context.chatId \u2014 there is no route back otherwise"});return}let L=`mesh-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;this.json(t,202,{accepted:!0,taskId:L,deliverTo:`${x}:${D}`,note:"result will be delivered to the originating chat when the peer finishes"});let F=h.peer,G=h.agent,Z=this.mesh;(async()=>{let W=Date.now(),V;try{V=await Z.sendTask(F,h.message,G,{vouchOwner:v,context:_,senderAgentId:P}),this.log(`[mesh/task async ${L}] ${F}/${G??"default"} finished in ${Date.now()-W}ms`)}catch(B){V=`Delegation to ${F}/${G??"default"} failed: ${B?.message??B}`,this.log(`[mesh/task async ${L}] failed: ${B?.message??B}`)}try{await this.router.sendOutbound({channel:x,chatId:D,text:V,agentId:_?.agentId??P,accountId:_?.accountId})}catch(B){this.log(`[mesh/task async ${L}] delivery failed: ${B?.message??B}`)}})();break}let O=await this.mesh.sendTask(h.peer,h.message,h.agent,{context:_,senderAgentId:P,vouchOwner:v});this.json(t,200,{response:O});break}case"POST /webrtc/signal/out":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await H(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let y=await this.webrtc.handleOutgoing(p);this.json(t,y.ok?200:400,y);break}case"POST /webrtc/signal":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await H(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let y=this.webrtc.handleIncoming(p);this.json(t,y.ok?200:400,y);break}case"POST /webrtc/bot/invite":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled (channels.webrtc.bot.enabled=false)"});return}let h=await H(e),p=h.callId,y=h.target,v=h.agentId||this.config.channels.webrtc?.bot.defaultAgentId;if(!p||!y||!v){this.json(t,400,{error:"Missing: callId, target, agentId (or defaultAgentId in config)"});return}let $=await this.botManager.invite({callId:p,target:y,agentId:v});this.json(t,$.ok?200:500,$);break}case"GET /webrtc/bots":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active()});break}case"GET /webrtc/history":{if(!this.botManager){this.json(t,404,{error:"WebRTC bot not enabled"});return}this.json(t,200,{active:this.botManager.active(),history:this.botManager.history()});break}case"GET /webrtc/config":{let h=this.config.channels.webrtc;if(!h?.enabled){this.json(t,404,{error:"WebRTC signaling not enabled"});return}this.json(t,200,{localName:this.config.node.name,iceServers:[...h.stunServers.map(p=>({urls:p})),...h.turnServers],peers:this.mesh?.directory().map(p=>({name:p.peer,healthy:p.healthy}))||[],camera:h.camera,agents:this.registry.list().map(p=>({id:p.id,name:p.name}))});break}case"GET /.well-known/agent-card.json":this.json(t,200,{name:this.config.node.name,description:`AgentX daemon node "${this.config.node.name}"`,url:`http://${this.config.node.bind}`,version:"1.0.0",capabilities:{streaming:!1,pushNotifications:!1,stateTransitionHistory:!1},skills:this.registry.list().map(h=>{let p=this.config.agents[h.id]||{},y=typeof p.description=="string"&&p.description.trim()||pA(p.systemPrompt)||`Agent "${h.name}" (${h.tier})`,v=Array.isArray(p.mentions)?p.mentions.slice(0,4):[];return{id:h.id,name:h.name,description:y,tags:[h.tier,...v],color:fe(h.id,p).color}}),channels:this.router.getChannelNames(),githubLogins:this.github?.postingAccounts()??[],defaultInputModes:["text"],defaultOutputModes:["text"]});break;case"GET /wiki/agents":{let h=this.registry.getWikiHub();this.json(t,200,{nodeId:this.config.node.id,agents:h.summary()});break}case"GET /wiki/entries":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent")||void 0,y=n.searchParams.get("after")||void 0,v=p?h.getAgentEntries(p):h.getSharedStore().listEntries({after:y});this.json(t,200,{nodeId:this.config.node.id,count:v.length,entries:v.map($=>({id:$.id,date:$.date,agentId:$.agentId,source:$.source,sourceContext:$.sourceContext,content:$.content}))});break}case"GET /wiki/articles":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent");if(!p){this.json(t,400,{error:"?agent= required"});break}let v=h.getAgentWiki(p).rebuildIndex();this.json(t,200,{nodeId:this.config.node.id,agentId:p,articles:v.articles});break}case"GET /wiki/article":{let h=this.registry.getWikiHub(),p=n.searchParams.get("agent"),y=n.searchParams.get("path");if(!p||!y){this.json(t,400,{error:"?agent= and ?path= required"});break}let $=h.getAgentWiki(p).readArticle(y);if(!$){this.json(t,404,{error:"Article not found"});break}this.json(t,200,{nodeId:this.config.node.id,agentId:p,path:$.path,title:$.meta.title,tags:$.meta.tags,owner:$.meta.owner,created:$.meta.created,lastUpdated:$.meta.lastUpdated,sources:$.meta.sources,content:$.content});break}case"GET /wiki/notes":{let{NoteStore:h}=await import("./notes-WJJEJ4CJ.js"),p=n.searchParams.get("status")||"waiting";if(!["waiting","open","patched","rejected","deferred","expired","all"].includes(p)){this.json(t,400,{error:"status must be waiting, open, patched, rejected, deferred, expired or all"});break}let y=Math.max(1,Math.min(200,parseInt(n.searchParams.get("limit")||"50",10)||50)),$=new h(this.registry.getWikiHub().getBaseDir()).list(p==="all"?void 0:p);this.json(t,200,{nodeId:this.config.node.id,enabled:this.config.wikiNotes.enabled,inbox:this.config.wikiNotes.inbox??null,crons:this.config.wikiNotes.crons,absorbAgent:this.config.wikiNotes.absorbAgent??null,total:$.length,notes:$.slice(-y).reverse()});break}case"POST /wiki/notes":{let{NoteStore:h,validateNote:p}=await import("./notes-WJJEJ4CJ.js"),y=this.config.wikiNotes;if(!y.enabled||!y.inbox){this.json(t,409,{error:"wiki notes are off on this node: set wikiNotes.enabled and wikiNotes.inbox"});break}let v=await H(e),$=p({...v,to:y.inbox});if("error"in $){this.json(t,400,{error:$.error});break}let T=$.note;if(this.registry.getAgent(y.inbox)){try{let{note:O,added:x}=new h(this.registry.getWikiHub().getBaseDir()).add(T);this.json(t,x?201:200,{ok:!0,added:x,note:O,node:this.config.node.id})}catch(O){this.json(t,507,{error:O?.message??String(O)})}break}if(v.forwarded===!0){this.json(t,404,{error:`inbox agent "${y.inbox}" is not on this node`});break}let _=this.mesh?.findAgentPeer(y.inbox);if(!_){this.json(t,404,{error:`inbox agent "${y.inbox}" is not on this node or any known peer`});break}let P=this.mesh.directory().find(O=>O.peer===_.peer)?.peerUrl;if(!_.healthy||!P){this.json(t,503,{error:`the node hosting "${y.inbox}" (${_.peer}) is unreachable; try again later`});break}try{let O=await fetch(`${P.replace(/\/$/,"")}/wiki/notes`,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(_.peer)},body:JSON.stringify({...T,fromNode:T.fromNode||this.config.node.id,forwarded:!0}),signal:AbortSignal.timeout(1e4)}),x=await O.json().catch(()=>({}));this.json(t,O.status,{...x,peer:_.peer})}catch(O){this.json(t,502,{error:`forward to ${_.peer} failed: ${O?.message??O}`,peer:_.peer})}break}case"GET /graph/schema":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,schema:h.loadSchema()});break}case"GET /graph/nodes":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,...h.loadNodes()});break}case"GET /graph/classifications":{let h=this.registry.getGraphStore();if(!h){this.json(t,404,{error:"graph disabled on this node"});break}let p=n.searchParams.get("status")||"approved",y=Math.max(1,Math.min(1e3,parseInt(n.searchParams.get("limit")||"200",10)||200)),v=h.listByStatus(p,y);this.json(t,200,{nodeId:this.config.node.id,status:p,count:v.length,classifications:v});break}default:this.json(t,404,{error:"Not found",endpoints:["GET /health","GET /agents","GET /crons","GET /routines \u2014 schedules + cron/hook workflows with staleness flags","GET /mesh","GET /wiki/agents","GET /wiki/entries[?agent=X&after=YYYY-MM-DD]","GET /wiki/articles?agent=X","GET /wiki/notes[?status=waiting|open|patched|rejected|deferred|expired|all&limit=N]","POST /wiki/notes { from, change, source, date? } \u2014 a note for the wiki observe/sweep run","GET /graph/schema","GET /graph/nodes","GET /graph/classifications[?status=approved|pending|rejected&limit=N]","POST /task { agent, message, context?, freshSession?: bool }","GET /agents/:id \u2014 resolved agent config (permission, tier, model, persistentProcess, toolUseRequired)","POST /agents/:id/selftest { message? } \u2014 canary probe; runs a fresh-session task and reports {ok, durationMs, tokens, billedModel}","GET /traces[?agentId=&channel=&chatId=&workflowRunId=&status=&since=&until=&limit=]","GET /traces/:taskId \u2014 full per-task execution trace (steps + tokens)","GET /voice/history[?agent=&limit=&before=] \u2014 past voice exchanges, bounded summaries","GET /voice/history/:id \u2014 one voice exchange in full; POST /voice/history/:id/replay","GET /api/processes \u2014 live persistent claude processes (JSON)","POST /api/processes/kill { agentId, channel, chatId, reason? }","GET /api/actions/builtin \u2014 list shipped built-in typed actions","POST /api/actions/builtin/:name \u2014 run a built-in with JSON body input","POST /mesh/task { peer, message }","POST /webhook/:agentId[/:source] \u2014 webhook callback","POST /reload \u2014 re-read agentx.json (hot-swaps crons)","GET /usage/plan \u2014 Claude plan windows, cold-dispatch counters, active holds","POST /usage/plan/lift \u2014 drop the active Claude plan holds","GET /daemon/restart \u2014 in-flight count, service manager, pending restart","POST /daemon/restart \u2014 restart when idle { timeoutMinutes?, onTimeout? }","POST /daemon/restart/cancel","GET /.well-known/agent-card.json","GET /call \u2014 browser UI for P2P A/V calls (requires channels.webrtc.enabled)","GET /webrtc/config \u2014 ICE servers + peer directory for the call page","GET /webrtc/events?callId=&as= \u2014 SSE stream of signaling events","POST /webrtc/signal/out \u2014 browser-originated signal, forwarded to remote peer","POST /webrtc/signal \u2014 remote-peer-originated signal, fanned out to local browser","POST /webrtc/bot/invite { callId, target, agentId } \u2014 spawn a transcribing bot peer for a call","GET /webrtc/bots \u2014 active bot sessions","POST /webrtc/camera/watch { callId, agentId } \u2014 an agent watches the phone camera share","GET /webrtc/camera/watch \u2014 agents watching a camera now","POST /webrtc/camera/watch/:id/look { note? } \u2014 ask the watching agent what it sees","POST /webrtc/camera/watch/:id/stream { seconds, note? } \u2014 the agent keeps watching for a while (0 stops)","POST /webrtc/camera/look { agentId } \u2014 from an agent's run: the newest frame as a PNG path"]})}}catch(i){this.json(t,500,{error:i.message})}}async handleOpenAICompat(e,t,n){let s=await H(e);await xg(e,t,n,s,{execute:(i,o,a,c)=>this.registry.execute(i,o,a,c),agentIds:Object.keys(this.config.agents),cancel:(i,o,a,c)=>{let l=this.registry.list().find(d=>d.id===i)?.runningTasks.filter(d=>d.channel===o&&d.chatId===a)||[];for(let d of l)this.registry.cancelRunningTask(d.id,c)},log:i=>this.log(i)})}json(e,t,n){e.writeHead(t,{"Content-Type":"application/json"}),e.end(JSON.stringify(n,null,2))}resolveGitlabTokenForAgent(e){if(!e)return{token:this.config.channels.gitlab?.token,source:"global"};let t=(this.config.channels.gitlab?.agentMappings||[]).find(s=>s.agentId===e);if(t?.token)return{token:t.token,source:"agentMappings"};let n=bm(this.config,e,"gitlab-user","tokenEnv");return n.status==="ok"&&n.value?{token:n.value,source:`integrations(${n.envVar})`}:this.config.channels.gitlab?.token?{token:this.config.channels.gitlab.token,source:"global"}:{token:void 0,source:n.status}}resolveTodayUsage(){let e=Zg();if(e==="json")return this.registry.getTodayUsage();let t=Qg(this.db);return e==="sqlite"||Object.keys(t.agents).length>0?t:this.registry.getTodayUsage()}installAgentMemorySurface(){let e=parseInt(this.config.node.bind.split(":")[1]||"18800",10);for(let t of this.registry.list()){let n=t.workspace;if(!(!n||!Wt(n)))try{let s=ne(n,".claude","skills");dk(s,{recursive:!0});let i=ne(s,vm);if(!Wt(i))Qa(i,Zo(e)),this.log(` memory-skill: installed remember.md \u2192 ${t.id}`);else{let o=$m(Cn(i,"utf-8"),e);o&&(Qa(i,o),this.log(` memory-skill: updated remember.md \u2192 ${t.id}`))}this.agentMemory.syncToWorkspace(t.id,n,this.config.session.memoryIndexMaxChars)}catch(s){this.log(` memory-skill: ${t.id} install failed \u2014 ${s?.message??s}`)}}}installAgentMcpConfig(){for(let[e,t]of Object.entries(this.config.agents)){let n=t.workspace;if(!n||!Wt(n))continue;let s=this.config.workflows.enabled&&(this.config.workflows.followUp.enabled&&(this.config.workflows.followUp.agents[e]??!0)||id(this.config.workflows,e)),i=Tl(Vc(t),this.config.requests.enabled||s?Il():null);try{switch(xl(n,i)){case"installed":this.log(` mcp: installed ${Object.keys(i).length} server(s) \u2192 ${e}`);break;case"updated":this.log(` mcp: updated .mcp.json (${Object.keys(i).length} server(s)) \u2192 ${e}`);break;case"removed":this.log(` mcp: removed managed .mcp.json (config now empty) \u2192 ${e}`);break;case"skipped-operator-owned":Object.keys(i).length>0&&this.log(` mcp: ${e} has operator-owned .mcp.json \u2014 skipping (delete file or marker to let agentx manage)`);break;case"noop":break}}catch(o){this.log(` mcp: ${e} install failed \u2014 ${o?.message??o}`)}}}workspaceFor(e){for(let t of this.registry.list())if(t.id===e)return t.workspace;return null}handleMemoryApi(e,t,n,s){return Zf(e,t,n,s,{mem:this.agentMemory,workspaceFor:i=>this.workspaceFor(i),runningTaskOwner:i=>this.registry.runningTaskOwner(i),indexMaxChars:()=>this.config.session.memoryIndexMaxChars})}async handleWorkflowEvent(e,t){if(!this.workflowDispatcher){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let n;try{n=await se(e)}catch(c){this.json(t,400,{error:"invalid JSON body",message:c.message});return}let s=n?.payload??n,i=s?.event,o=s?.entityRef;if(!i?.id||!o?.backend||!o?.id){this.json(t,400,{error:"missing event or entityRef"});return}let a=n?.kind;try{if(a==="trigger"&&s.trigger){let g=typeof n?.fromPeer=="string"?n.fromPeer:"unknown";this.log(`[workflows/mesh] received trigger from "${g}" source="${s.trigger.source}" chat="${s.trigger.chat??"*"}"`);let m=await this.workflowDispatcher.dispatch({trigger:s.trigger,entityRef:o,event:i,fromRemote:{peer:g}});this.log(`[workflows/mesh] dispatched broadcast: matched=${m.claimed.length} ${m.claimed.length?`(${m.claimed.map(f=>f.id).join(", ")})`:"[none \u2014 no workflow with mesh.allowRemote matched]"}`),this.json(t,202,{ok:!0,mode:"trigger-broadcast",matched:m.claimed.map(f=>f.id)});return}let d=(s.workflowId?this.workflowStore?.get(s.workflowId):null)?.nodes.find(g=>g.type.startsWith("trigger."))?.config??{},u={source:String(d.source??"hook"),project:d.filter?.project,repo:d.filter?.repo,chat:d.filter?.chat,labels:d.filter?.labels};await this.workflowDispatcher.dispatch({trigger:u,entityRef:o,event:i}),this.json(t,202,{ok:!0})}catch(c){this.log(`[workflows] /workflow/event failed: ${c.message}`),this.json(t,500,{error:c.message})}}async postToPushHost(e,t,n){let s=e.toLowerCase(),i=this.mesh?.directory().find(c=>c.peer.toLowerCase()===s);if(!i)throw new Error(`push: channels.push.relayTo "${e}" is not a mesh peer of this node`);let o=await fetch(`${i.peerUrl}${t}`,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(i.peer)},body:JSON.stringify(n),signal:AbortSignal.timeout(15e3)});if(!o.ok)throw new Error(`push: ${i.peer} ${t} -> ${o.status} ${(await o.text().catch(()=>"")).slice(0,200)}`);let a=await o.json().catch(()=>({}));if(t==="/channel/send")return a.messageId??void 0;if(typeof a.status!="number")throw new Error(`push: ${i.peer} ${t} gave no answer`);return{status:a.status,body:a.body??{}}}async handlePushApp(e,t){let n;try{n=await se(e)}catch(c){this.json(t,400,{error:"invalid JSON body",message:c.message});return}let{handlePushBridge:s,pushOrigin:i}=await import("./push-bridge-P7HH25VN.js"),o=this.config.channels.push;if(!o?.enabled){this.json(t,200,{status:503,body:{error:`Notifications are off on ${this.config.node.name}.`}});return}if(o.relayTo){if(n?.origin!==void 0){this.json(t,200,{status:409,body:{error:`${this.config.node.name} relays its notifications too (channels.push.relayTo = ${o.relayTo})`}});return}if(n?.op!=="app"){this.json(t,400,{error:"op must be app"});return}try{this.json(t,200,await this.postToPushHost(o.relayTo,"/push/app",{op:"app",origin:i(this.config.node.name),call:n.call}))}catch(c){this.log(`[push] /push/app to ${o.relayTo} failed: ${c.message}`),this.json(t,502,{error:c.message})}return}let a=this.pushBridgeCaller(e);"error"in a&&n?.op!=="roster"&&this.log(`[push] /push/app from ${e.socket?.remoteAddress||"?"} refused: ${a.error}`),this.json(t,200,s(n,a,this.pushHost??null,this.pushHost?void 0:`Notifications are not running on ${this.config.node.name}. Check channels.push.subject and the database there.`))}pushBridgeCaller(e){return Gd(String(e.headers.authorization||""),this.config.mesh.peers,process.env.MESH_TOKEN)}async handleChannelSend(e,t){let n;try{n=await se(e)}catch(l){this.json(t,400,{error:"invalid JSON body",message:l.message});return}let s=String(n?.channel??""),i=String(n?.chatId??""),o=String(n?.text??"");if(!s||!i||!o){this.json(t,400,{error:"channel, chatId, and text are required"});return}if(!this.router.getChannel(s)){this.json(t,404,{error:`channel "${s}" not hosted on this node`});return}let c;if(n.relayed===!0&&n.origin!==void 0){let l=this.pushBridgeCaller(e);if("origin"in l)c=l.origin;else if(i!=="default"){this.json(t,403,{error:l.error});return}}if(s==="push"&&i.includes(":")){let{scopedPushTarget:l}=await import("./push-bridge-P7HH25VN.js"),d=l(i,this.pushBridgeCaller(e));if("error"in d){this.json(t,403,{error:d.error});return}}try{let l=await this.router.sendOutbound({channel:s,chatId:i,text:o,accountId:typeof n.accountId=="string"?n.accountId:void 0,parseMode:typeof n.parseMode=="string"?n.parseMode:void 0,replyTo:typeof n.replyTo=="string"?n.replyTo:void 0,buttons:Array.isArray(n.buttons)?n.buttons:void 0,agentId:typeof n.agentId=="string"?n.agentId:void 0,relayed:n.relayed===!0?!0:void 0,origin:c},{recordInSession:!1});this.json(t,200,{ok:!0,messageId:l??null})}catch(l){this.log(`[mesh] /channel/send "${s}" failed: ${l.message}`),this.json(t,500,{error:l.message})}}async handleChannelChats(e,t,n={}){let s=new Set,i=[],o=[],a=(l,d)=>{let u=0;for(let g of l)!g.id||s.has(g.id)||(s.add(g.id),i.push({...g,source:d}),u++);u>0&&o.push(`${d}:${u}`)},c=this.router.getChannel(t);if(c?.listKnownChats)try{a(c.listKnownChats(),"local")}catch{}else if(c?.listChats)try{a(c.listChats().map(l=>({id:l.jid,name:l.name,kind:l.isGroup?"group":"dm"})),"local")}catch{}if(!n.localOnly&&this.mesh){let l=this.mesh.directory().filter(d=>d.healthy&&d.channels?.includes(t));await Promise.allSettled(l.map(async d=>{try{let u=await fetch(`${d.peerUrl}/channels/${encodeURIComponent(t)}/chats?local=1`,{headers:this.mesh.authHeaders(d.peer),signal:AbortSignal.timeout(5e3)});if(!u.ok)return;let g=await u.json();Array.isArray(g.chats)&&a(g.chats.map(m=>({id:m.id,name:m.name,kind:m.kind??"dm",accountId:m.accountId})),`mesh:${d.peer}`)}catch{}}))}this.json(e,200,{channel:t,source:o.join(", ")||"none",chats:i})}async handleWorkflowManualRun(e,t,n){if(!this.workflowDispatcher||!this.workflowStore){this.json(t,503,{error:"workflow engine not enabled on this node"});return}let s;try{s=await se(e)}catch{s={}}try{let i=await km({get:o=>this.workflowStore.get(o),dispatchWorkflow:o=>this.workflowDispatcher.dispatchWorkflow(o),startRun:o=>this.workflowDispatcher.startRun(o)},n,s);this.json(t,i.status,i.body)}catch(i){this.log(`[workflows] manual run "${n}" failed: ${i.message}`),this.json(t,500,{error:i.message})}}},Za=ec;ft(Za,"MESH_PROTECTED_PATHS",new Set(["/task","/ask","/mesh/task","/mesh/inbox/send","/workflow/event","/workflow/transition","/channel/send","/push/app","/webrtc/signal","/gitlab/react","/gitlab/send-note","/gitlab/log-time","/channel/edit-comment","/github/send-comment"]));function pA(r){if(typeof r!="string")return"";let e=r.trim();if(!e)return"";let t=e.match(/^[^.!?\n]+[.!?]?/),n=(t?t[0]:e).trim();return n.length>140?n.slice(0,137)+"\u2026":n}function se(r){return new Promise((e,t)=>{let n="";r.setEncoding("utf8"),r.on("data",s=>{n+=s}),r.on("end",()=>{try{e(n?JSON.parse(n):{})}catch(s){t(s)}}),r.on("error",t)})}function fA(r,e){let t=["model","workspace","tier","permissionMode","mcpServers"],n=new Set,s=new Set([...Object.keys(r),...Object.keys(e)]);for(let i of s){let o=r[i],a=e[i];if(!o||!a){n.add("add/remove");continue}for(let c of t)JSON.stringify(o[c])!==JSON.stringify(a[c])&&n.add(`${i}.${c}`)}return Array.from(n).slice(0,6)}async function H(r){return new Promise((e,t)=>{let n="";r.on("data",s=>n+=s.toString()),r.on("end",()=>{try{e(n?JSON.parse(n):{})}catch{e({})}}),r.on("error",t)})}hk();function SU(r){typeof r=="string"&&(_n.error(r),process.exit(1)),r instanceof Error&&(_n.error(r.message),process.exit(1)),_n.error("Something went wrong. Please try again."),process.exit(1)}export{CA as a,Ji as b,rt as c,Qt as d,tn as e,ct as f,us as g,Xh as h,Wg as i,lS as j,dS as k,Jg as l,Be as m,dt as n,zg as o,ut as p,yP as q,wP as r,Hs as s,y_ as t,o$ as u,Vo as v,FM as w,UM as x,GM as y,cm as z,L$ as A,VM as B,JM as C,fn as D,Dt as E,mn as F,kO as G,Um as H,EI as I,uD as J,ur as K,ha as L,ga as M,mr as N,fe as O,Py as P,kr as Q,xT as R,By as S,RT as T,Xy as U,Sr as V,In as W,xr as X,Rr as Y,ew as Z,Ra as _,Je as $,Re as aa,cw as ba,lw as ca,dw as da,uw as ea,Xr as fa,tk as ga,Ka as ha,sk as ia,nA as ja,OL as ka,Za as la,SU as ma};
1179
+ //# sourceMappingURL=chunk-J5FNCTG2.js.map
@@ -1,2 +1,2 @@
1
- import{c as d,g}from"./chunk-7DYVNET6.js";import{a as f}from"./chunk-5HLD66CW.js";var k=/^[A-Za-z0-9._-]{1,64}$/,m=/^[A-Za-z0-9_-]{1,64}$/,A=100,w=1e3,E=6e4,P=15*6e4;function p(r){return(r.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"node").slice(0,64)}function _(r,t,n){let i=/^bearer /i.test(r)?r.slice(7).trim():"",e="Phones paired with another computer need that computer's own peer token: give it a token in mesh.peers on both computers.";if(!i||n&&i===n)return{error:e};let a=new Set(t.filter(s=>s.token===i).map(s=>p(s.name)));if(a.size===0)return{error:e};if(a.size>1)return{error:`Several mesh.peers entries share this token (${[...a].join(", ")}). Give each computer its own token.`};let[o]=a,u=t.filter(s=>s.token!==i&&p(s.name)===o).map(s=>s.name);return u.length?{error:`mesh.peers names ${u.map(s=>`"${s}"`).join(", ")} too close to this computer's name: rename one so they differ in letters or digits.`}:{origin:o}}function C(r,t){let n=r.indexOf(":");return n<0?{ok:!0}:"error"in t?{error:t.error}:r.slice(0,n)!==t.origin?{error:`${r} is a phone paired with another computer; only that computer can send to it.`}:{ok:!0}}function x(r,t,n){let i=r.toLowerCase(),e=t.find(a=>a.name.toLowerCase()===i);return e?e.token?n&&e.token===n?`mesh.peers "${e.name}" uses the shared MESH_TOKEN, so phones paired here can't turn notifications on. Give this pair a token of its own on both computers.`:null:`mesh.peers "${e.name}" has no token, so phones paired here can't turn notifications on. Give it a token of its own on both computers.`:null}function O(r){return new Set(r.map(t=>p(t.name)))}function j(r,t,n,i){let e=r&&typeof r=="object"?r:{};if("error"in t)return{status:403,body:{error:t.error}};let a=t.origin;if(!k.test(a))return{status:403,body:{error:"this peer's name can't be used as a notification origin"}};if(!n)return{status:503,body:{error:i??"Notifications are not set up on the computer that sends them."}};if(e.op==="roster"){if(!Array.isArray(e.active)||e.active.length>w||!e.active.every(l=>typeof l=="string"&&m.test(l)))return{status:400,body:{error:"active must be a list of device ids"}};let h=n.store();return h?{status:200,body:{ok:!0,removed:h.pruneOrigin(a,e.active)}}:{status:503,body:{error:n.reason??"the database is unavailable"}}}if(e.op!=="app")return{status:400,body:{error:"op must be app or roster"}};let o=e.call&&typeof e.call=="object"?e.call:{},u=o.device&&typeof o.device=="object"?o.device:{},s=typeof o.path=="string"?o.path:"",c=o.method==="GET"||o.method==="POST"?o.method:"";if(!d(s)||!c)return{status:404,body:{error:"not found"}};if(typeof u.id!="string"||!m.test(u.id))return{status:400,body:{error:"device.id is required"}};let b=typeof u.name=="string"&&u.name.trim()?u.name.trim():u.id,v=o.body&&typeof o.body=="object"&&!Array.isArray(o.body)?o.body:{};return g({path:s,method:c,body:v,device:{id:f(a,u.id),name:S(`${b} (${a})`,A)}},n)}var y=class{constructor(t){this.deps=t}lastKey=null;lastSentAt=0;failing=!1;async tick(){let t=(this.deps.now??Date.now)(),n;try{n=[...new Set(this.deps.active())].sort()}catch(e){return this.deps.log?.(`push: phone list not read, not sent this time: ${e?.message??e}`),!1}let i=n.join(",");if(i===this.lastKey&&t-this.lastSentAt<P)return!1;try{let e=await this.deps.send(n);if(e&&typeof e=="object"&&typeof e.status=="number"&&e.status!==200)throw new Error(`${e.status} ${typeof e.body?.error=="string"?e.body.error:"refused"}`);return this.lastKey=i,this.lastSentAt=t,this.failing&&this.deps.log?.("push: phone list sent to the push host again"),this.failing=!1,!0}catch(e){return this.failing||this.deps.log?.(`push: phone list not sent to the push host, retrying every minute: ${e?.message??e}`),this.failing=!0,!1}}};function S(r,t){let n=[...r];return n.length>t?n.slice(0,t-1).join("")+"\u2026":r}export{E as a,P as b,p as c,_ as d,C as e,x as f,O as g,j as h,y as i};
2
- //# sourceMappingURL=chunk-CZZJEFUM.js.map
1
+ import{c as d,g}from"./chunk-YMX3QCV7.js";import{a as f}from"./chunk-5HLD66CW.js";var k=/^[A-Za-z0-9._-]{1,64}$/,m=/^[A-Za-z0-9_-]{1,64}$/,A=100,w=1e3,E=6e4,P=15*6e4;function p(r){return(r.replace(/[^A-Za-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||"node").slice(0,64)}function _(r,t,n){let i=/^bearer /i.test(r)?r.slice(7).trim():"",e="Phones paired with another computer need that computer's own peer token: give it a token in mesh.peers on both computers.";if(!i||n&&i===n)return{error:e};let a=new Set(t.filter(s=>s.token===i).map(s=>p(s.name)));if(a.size===0)return{error:e};if(a.size>1)return{error:`Several mesh.peers entries share this token (${[...a].join(", ")}). Give each computer its own token.`};let[o]=a,u=t.filter(s=>s.token!==i&&p(s.name)===o).map(s=>s.name);return u.length?{error:`mesh.peers names ${u.map(s=>`"${s}"`).join(", ")} too close to this computer's name: rename one so they differ in letters or digits.`}:{origin:o}}function C(r,t){let n=r.indexOf(":");return n<0?{ok:!0}:"error"in t?{error:t.error}:r.slice(0,n)!==t.origin?{error:`${r} is a phone paired with another computer; only that computer can send to it.`}:{ok:!0}}function x(r,t,n){let i=r.toLowerCase(),e=t.find(a=>a.name.toLowerCase()===i);return e?e.token?n&&e.token===n?`mesh.peers "${e.name}" uses the shared MESH_TOKEN, so phones paired here can't turn notifications on. Give this pair a token of its own on both computers.`:null:`mesh.peers "${e.name}" has no token, so phones paired here can't turn notifications on. Give it a token of its own on both computers.`:null}function O(r){return new Set(r.map(t=>p(t.name)))}function j(r,t,n,i){let e=r&&typeof r=="object"?r:{};if("error"in t)return{status:403,body:{error:t.error}};let a=t.origin;if(!k.test(a))return{status:403,body:{error:"this peer's name can't be used as a notification origin"}};if(!n)return{status:503,body:{error:i??"Notifications are not set up on the computer that sends them."}};if(e.op==="roster"){if(!Array.isArray(e.active)||e.active.length>w||!e.active.every(l=>typeof l=="string"&&m.test(l)))return{status:400,body:{error:"active must be a list of device ids"}};let h=n.store();return h?{status:200,body:{ok:!0,removed:h.pruneOrigin(a,e.active)}}:{status:503,body:{error:n.reason??"the database is unavailable"}}}if(e.op!=="app")return{status:400,body:{error:"op must be app or roster"}};let o=e.call&&typeof e.call=="object"?e.call:{},u=o.device&&typeof o.device=="object"?o.device:{},s=typeof o.path=="string"?o.path:"",c=o.method==="GET"||o.method==="POST"?o.method:"";if(!d(s)||!c)return{status:404,body:{error:"not found"}};if(typeof u.id!="string"||!m.test(u.id))return{status:400,body:{error:"device.id is required"}};let b=typeof u.name=="string"&&u.name.trim()?u.name.trim():u.id,v=o.body&&typeof o.body=="object"&&!Array.isArray(o.body)?o.body:{};return g({path:s,method:c,body:v,device:{id:f(a,u.id),name:S(`${b} (${a})`,A)}},n)}var y=class{constructor(t){this.deps=t}lastKey=null;lastSentAt=0;failing=!1;async tick(){let t=(this.deps.now??Date.now)(),n;try{n=[...new Set(this.deps.active())].sort()}catch(e){return this.deps.log?.(`push: phone list not read, not sent this time: ${e?.message??e}`),!1}let i=n.join(",");if(i===this.lastKey&&t-this.lastSentAt<P)return!1;try{let e=await this.deps.send(n);if(e&&typeof e=="object"&&typeof e.status=="number"&&e.status!==200)throw new Error(`${e.status} ${typeof e.body?.error=="string"?e.body.error:"refused"}`);return this.lastKey=i,this.lastSentAt=t,this.failing&&this.deps.log?.("push: phone list sent to the push host again"),this.failing=!1,!0}catch(e){return this.failing||this.deps.log?.(`push: phone list not sent to the push host, retrying every minute: ${e?.message??e}`),this.failing=!0,!1}}};function S(r,t){let n=[...r];return n.length>t?n.slice(0,t-1).join("")+"\u2026":r}export{E as a,P as b,p as c,_ as d,C as e,x as f,O as g,j as h,y as i};
2
+ //# sourceMappingURL=chunk-JAML6222.js.map
@@ -1,3 +1,3 @@
1
1
  import{a as f}from"./chunk-JWDJMFU6.js";import{mkdirSync as D,readFileSync as F,renameSync as H,writeFileSync as K}from"fs";import{dirname as J,resolve as M}from"path";function k(e,t=160){if(!e)return e;let r=e.replace(/\s+/g," ").trim();return r.length>t?r.slice(0,t-1)+"\u2026":r}function j(e){let t=new Map;for(let n of e.cronRuns??[]){let s=t.get(n.jobId);(!s||s.startedAt<n.startedAt)&&t.set(n.jobId,n)}let r={success:0,failed:0};for(let n of e.cronRuns??[])n.status==="success"?r.success++:r.failed++;return{id:e.id,name:e.name,url:e.url,reachable:e.reachable,error:k(e.error),uptimeSec:e.uptimeSec,inflight:e.inflight,restart:e.restart?.state&&e.restart.state!=="none"?e.restart:void 0,agents:e.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:k(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:r,items:(e.crons??[]).map(n=>{let s=t.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:s?{status:s.status,at:s.startedAt,text:k(s.status==="success"?s.responseSummary:s.errorSummary)}:void 0}})}}}function E(e){let t=[];for(let r of e)for(let n of r.agents)for(let s of n.runningTasks??[])t.push({node:r.url,nodeName:r.name,agentId:n.id,agentName:n.name,taskId:s.id,preview:k(s.messagePreview),channel:s.channel,startedAt:s.startedAt});return t.sort((r,n)=>r.startedAt<n.startedAt?1:-1)}var O=/^\/api\/app\/tasks\/(cancel|followup)$/;async function _(e,t,r,n,s,o){let a=new URL(e.url||r,"http://localhost");if(n==="GET"&&(r==="/api/app/fleet"||r==="/api/app/activity")){let c=$(a.searchParams.get("timezone")),l=await o.snapshot({date:U(c),timezone:c});return r==="/api/app/activity"?b(t,200,{ts:l.ts,tasks:E(l.nodes)}):b(t,200,{ts:l.ts,nodes:l.nodes.map(j)})}if(n==="GET"&&r==="/api/app/approvals")return b(t,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let p=r.match(O);if(!(p||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(r)))return!1;let i;try{i=await P(e)}catch(c){return b(t,400,{error:c.message})}let m=A(i.node);if(!m)return b(t,400,{error:"node is required"});let w=`operator (phone: ${s})`,u;if(p){let c=A(i.taskId);if(!c)return b(t,400,{error:"taskId is required"});let l=`/api/tasks/${encodeURIComponent(c)}/${p[1]}`;if(p[1]==="cancel")u=await o.nodePost(m,l,{reason:`cancelled by ${w}`});else{let y=A(i.message);if(!y)return b(t,400,{error:"message is required"});u=await o.nodePost(m,l,{message:y,sender:w})}}else if(r==="/api/app/nodes/restart")u=await o.nodePost(m,i.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(r==="/api/app/nodes/reload")u=await o.nodePost(m,"/reload",{});else if(r==="/api/app/crons/toggle"){let c=A(i.cronId);if(!c||typeof i.enabled!="boolean")return b(t,400,{error:"cronId and enabled (true or false) are required"});u=await o.nodePost(m,`/crons/${encodeURIComponent(c)}/enabled`,{enabled:i.enabled})}else{let c=A(i.key),l=i.action;if(!c||l!=="yes"&&l!=="no"&&l!=="later")return b(t,400,{error:"key and action (yes, no or later) are required"});let y=typeof i.choice=="number"?i.choice:A(i.choice),d=typeof i.text=="string"&&i.text.trim()?i.text:"",C={...y!==""?{choice:y}:{},...d?{text:d}:{}};u=await o.decide(m,c,l,w,C)}return b(t,u.status,u.body)}function A(e){return typeof e=="string"?e.trim():""}function $(e){if(!e)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:e}),e}catch{return"UTC"}}function U(e,t=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit"}).format(t)}async function P(e,t=16*1024){let r=0,n=[];for await(let a of e){if(r+=a.length,r>t)throw new Error("body too large");n.push(a)}let s=Buffer.concat(n).toString("utf-8").trim();if(!s)return{};let o=JSON.parse(s);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function b(e,t,r){return e.writeHead(t,{"Content-Type":"application/json","Cache-Control":"no-store"}),e.end(JSON.stringify(r)),!0}function I(e){return e==="/api/app/push"||e.startsWith("/api/app/push/")||e==="/api/app/alerts"}var G=2048,N=/^[A-Za-z0-9_-]{8,256}$/;async function Y(e,t,r,n,s,o){if(!I(r))return!1;let a={};if(n==="POST")try{a=await P(e)}catch(i){return R(t,400,{error:i.message})}let p={path:r,method:n,body:a,device:{id:s.id,name:s.name}};if(!o.forward){let i=B(p,o);return R(t,i.status,i.body)}let h;try{h=await o.forward(p),S.note(p,h)}catch(i){h=z(p,`${o.reason??"Can't reach the computer that sends notifications"}: ${i?.message??i}`)}return R(t,h.status,h.body)}var v=class{phones=new Map;file=null;persistTo(t){if(this.file!==t){this.file=t;try{let r=JSON.parse(F(t,"utf-8"));for(let[n,s]of Object.entries(r??{}))s&&typeof s=="object"&&typeof s.subscribed=="boolean"&&this.phones.set(n,{subscribed:s.subscribed,prefs:q(s.prefs)})}catch{}}}note(t,r){if(r.status!==200||!r.body||typeof r.body!="object")return;let n=r.body,s=this.phones.get(t.device.id)??{subscribed:!1,prefs:{}};if(t.method==="GET"&&t.path==="/api/app/push")s.subscribed=n.available===!0&&Number(n.subscriptions)>0,s.prefs=x(n);else if(t.path==="/api/app/push/prefs")s.prefs={...s.prefs,...x(n)};else if(t.path==="/api/app/push/subscribe")s.subscribed=!0;else if(t.path==="/api/app/push/unsubscribe")n.removed&&(s.subscribed=!1);else return;this.phones.set(t.device.id,s),this.save()}save(){if(this.file)try{D(J(this.file),{recursive:!0});let t=`${this.file}.${process.pid}.tmp`;K(t,JSON.stringify(Object.fromEntries(this.phones))+`
2
2
  `,{encoding:"utf-8",mode:384}),H(t,this.file)}catch{}}on(t,r){return this.phones.get(t)?.prefs[f[r].field]??f[r].default}finishOn(t){return!!this.phones.get(t)?.subscribed&&this.on(t,"finish")}},S=new v;function ee(){return S.persistTo(M(process.cwd(),".agentx/push-relayed.json")),S}function x(e){let t={};for(let r of Object.values(f))typeof e[r.field]=="boolean"&&(t[r.field]=e[r.field]);return t}function q(e){return e&&typeof e=="object"&&!Array.isArray(e)?x(e):{}}function z(e,t){return e.method==="GET"&&e.path==="/api/app/push"?{status:200,body:{available:!1,reason:t,publicKey:null,subscriptions:0,...T()}}:e.method==="GET"&&e.path==="/api/app/alerts"?{status:200,body:{items:[],error:t}}:{status:502,body:{error:t}}}function B(e,t){let{path:r,method:n,body:s,device:o}=e;if(!I(r))return{status:404,body:{error:"not found"}};let a=t.store(),p=a?t.publicKey():null,h=a?p?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":t.reason??"Notifications are not set up on this computer.";if(n==="GET"&&r==="/api/app/push")return g(200,{available:!h,reason:h??null,publicKey:p,subscriptions:a&&p?a.list(o.id).filter(u=>u.publicKey===p).length:0,...a?a.prefs.all(o.id):T()});if(n==="GET"&&r==="/api/app/alerts")return g(200,{items:a?a.recent(t.keepRecent,o.id):[]});if(n!=="POST"||r!=="/api/app/push/subscribe"&&r!=="/api/app/push/unsubscribe"&&r!=="/api/app/push/prefs")return g(404,{error:"not found"});if(!a||h)return g(503,{error:h});if(r==="/api/app/push/prefs"){let u=Object.keys(f).filter(d=>s[f[d].field]!==void 0),c=u.map(d=>f[d].field).join(", "),l=Object.values(f).map(d=>d.field).join(" or ");if(u.length===0)return g(400,{error:`send ${l}, true or false`});if(u.some(d=>typeof s[f[d].field]!="boolean"))return g(400,{error:`${c} must be true or false`});let y={};for(let d of u)a.prefs.set(o.id,d,s[f[d].field]),y[f[d].field]=s[f[d].field];return g(200,{ok:!0,...y})}let i=L(s.endpoint,t.allowedHosts);if(!i){let u="";try{u=new URL(String(s.endpoint)).hostname}catch{}return g(400,{error:`not a known push service${u?`: ${u}`:""} (see channels.push.allowedHosts)`})}if(r==="/api/app/push/unsubscribe")return g(200,{ok:!0,removed:a.unsubscribe(i,o.id)});let m=s.keys?.p256dh,w=s.keys?.auth;return typeof m!="string"||!N.test(m)||typeof w!="string"||!N.test(w)?g(400,{error:"keys.p256dh and keys.auth are required"}):s.publicKey!==void 0&&s.publicKey!==p?g(409,{error:"this computer's push keys changed; turn notifications on again"}):(a.subscribe({endpoint:i,p256dh:m,auth:w,deviceId:o.id,deviceName:o.name,publicKey:p}),g(200,{ok:!0}))}function g(e,t){return{status:e,body:t}}function T(){let e={};for(let t of Object.values(f))e[t.field]=t.default;return e}function L(e,t){if(typeof e!="string"||e.length>G)return null;try{let r=new URL(e);if(r.protocol!=="https:"||r.port||r.username||r.password)return null;let n=r.hostname.toLowerCase();return t.some(o=>{let a=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!a&&(n===a||n.endsWith("."+a))})?e:null}catch{return null}}function R(e,t,r){return e.writeHead(t,{"Content-Type":"application/json","Cache-Control":"no-store"}),e.end(JSON.stringify(r)),!0}export{_ as a,P as b,I as c,Y as d,S as e,ee as f,B as g};
3
- //# sourceMappingURL=chunk-7DYVNET6.js.map
3
+ //# sourceMappingURL=chunk-YMX3QCV7.js.map