agentix-cli 0.84.0 → 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{board-dashboard-R5NMATZ3.js → board-dashboard-IDV5SYLW.js} +2 -2
- package/dist/{chunk-ZL7RKS6H.js → chunk-AR7CGFAT.js} +2 -2
- package/dist/{chunk-WDASUG6A.js → chunk-QFF6ARGN.js} +2 -2
- package/dist/{chunk-WDASUG6A.js.map → chunk-QFF6ARGN.js.map} +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{program-G7R64P7A.js → program-VSIDVWPL.js} +192 -175
- package/dist/program-VSIDVWPL.js.map +1 -0
- package/package.json +1 -1
- package/dist/program-G7R64P7A.js.map +0 -1
- /package/dist/{board-dashboard-R5NMATZ3.js.map → board-dashboard-IDV5SYLW.js.map} +0 -0
- /package/dist/{chunk-ZL7RKS6H.js.map → chunk-AR7CGFAT.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as A,b as Fn,c as Un,d as Wn,e as Gn,f as ke,g as Xn,h as Kn,i as Jn,m as Vn,n as Yn,o as Qn,t as Zn,u as er,v as ar,w as nr,x as rr}from"./chunk-
|
|
1
|
+
import{a as A,b as Fn,c as Un,d as Wn,e as Gn,f as ke,g as Xn,h as Kn,i as Jn,m as Vn,n as Yn,o as Qn,t as Zn,u as er,v as ar,w as nr,x as rr}from"./chunk-QFF6ARGN.js";import{a as tr}from"./chunk-BYD5B3P3.js";import{a as qn}from"./chunk-CPXZWVKN.js";import{a as xt,b as z,c as Dn,d as L,i as Pe,j as vt,k as re,l as X,m as bt,n as Hn,o as Bn,p as zn}from"./chunk-O5U5NVLR.js";import{a as Nn}from"./chunk-2NYP4OQU.js";import{a as ce,b as On}from"./chunk-JWDJMFU6.js";import{A as ct,D as vn,E as bn,Ea as In,F as yn,Ga as Re,La as Mn,M as q,N as wn,Na as $e,O as kn,Oa as ut,Pa as mt,Qa as ft,Ra as ht,Sa as Ln,Ta as Rn,Ua as $n,Va as gt,Xa as Pn,_a as jn,a as sn,c as ot,d as Jt,e as ln,i as st,l as Fe,n as cn,sa as Sn,ua as Tn,va as An,w as Yt,wa as Cn,x as hn,y as Qt,z as lt}from"./chunk-H4EGM4L7.js";import"./chunk-GTJIKXDB.js";import{g as rn,h as on}from"./chunk-WABEHPU5.js";import{a as O,b as _n,c as En}from"./chunk-CL53UVOF.js";import{p as dn,t as pn}from"./chunk-S2GAEH2F.js";import"./chunk-4GNAOJ7P.js";import"./chunk-2AXFYDWF.js";import"./chunk-AQASR6KR.js";import{b as G,c as we,d as un,e as Vt}from"./chunk-ACFQBLPX.js";import{g as it}from"./chunk-LQE73AZR.js";import{b as mn,c as fn}from"./chunk-2D3RYIDU.js";import{m as gn,n as dt,o as pt,q as xn}from"./chunk-XIYWXCNU.js";import{a as Qa,f as Za,g as Xt,h as Kt,l as en,m as tn,n as an,u as at,v as nt,w as rt,x as le,y as nn}from"./chunk-ZVUEJXCY.js";import"./chunk-GLQLCBJS.js";import"./chunk-DP7RTNDM.js";import"./chunk-Y4CYQV7G.js";import"./chunk-SHEUCITK.js";import"./chunk-5DUPIMOI.js";import"./chunk-SZDACK6O.js";import"./chunk-AFRHKA7B.js";import"./chunk-6NE2GLO6.js";import"./chunk-ZJJJM7AR.js";import"./chunk-Y3C37PF5.js";import"./chunk-3D3B4NQ7.js";import"./chunk-KA2UIZXG.js";import"./chunk-GQ76J72O.js";import"./chunk-ILEC3IAV.js";import"./chunk-GV7S5BAX.js";import"./chunk-GSX4NK2N.js";import"./chunk-QD6IICK7.js";import"./chunk-CECHWYJ2.js";import{g as Ya}from"./chunk-3VP3UWNT.js";import"./chunk-WPNRDEHW.js";import"./chunk-2GIDVZ4H.js";import"./chunk-DA2NTRUR.js";import"./chunk-72SZI2UW.js";import"./chunk-FX3D7YON.js";import"./chunk-FCPTN6NF.js";import"./chunk-QOYAX2FT.js";import"./chunk-5MUJZODV.js";import"./chunk-7I7IEX4S.js";import{F as Va,I as zi,a as Ga,aa as W,b as Xa,c as Ni,da as tt,q as et,r as Di,s as Wt,t as Gt,w as Bi}from"./chunk-QA4RTSKI.js";import{a as ye,i as Ja}from"./chunk-PN6XHTG5.js";import{b as Ka,h as Hi}from"./chunk-BRK6M6LA.js";import"./chunk-2QNT5JDS.js";import"./chunk-RGDKHYY2.js";import"./chunk-QIJLFPWE.js";function Zt(t,e,a=Date.now()){let n=Math.max(0,a-(t.updatedAt||a)),r=t.clientId?e[t.clientId]:void 0;if(!r)return{score:n/864e5,ageMs:n,rising:!1,overdue:!1};let o=n/(r*6e4);return{score:1e3+o,ageMs:n,rising:!0,overdue:o>=1}}function or(t,e,a=Date.now()){return t.map((n,r)=>({i:r,s:Zt(n,e,a).score})).sort((n,r)=>r.s-n.s||n.i-r.i).map(n=>n.i)}var oe={refresh:'<path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/>',clock:'<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',alert:'<path d="M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/><path d="M12 9v4"/><path d="M12 17h.01"/>',gavel:'<path d="M12 3 6 9"/><path d="m9 6 6 6"/><path d="M15 9 9 15"/><path d="m12 12 6 6"/><path d="M4 21h10"/>',loop:'<path d="M17 2l4 4-4 4"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><path d="M7 22l-4-4 4-4"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/>',broom:'<path d="M3 21h18"/><path d="M12 3v9"/><path d="m7 12 5-3 5 3-1.5 6h-7Z"/>',server:'<rect x="2" y="3" width="20" height="7" rx="2"/><rect x="2" y="14" width="20" height="7" rx="2"/><path d="M6 6.5h.01"/><path d="M6 17.5h.01"/>',inbox:'<path d="M21 12h-6l-2 3h-2l-2-3H3"/><path d="M5 5h14l2 7v5a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Z"/>',cross:'<circle cx="12" cy="12" r="9"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/>',file:'<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7Z"/><path d="M14 2v5h5"/>',search:'<circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/>',chev:'<path d="m6 9 6 6 6-6"/>',chevr:'<path d="m9 6 6 6-6 6"/>',ext:'<path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/>',pulse:'<path d="M3 12h4l3-8 4 16 3-8h4"/>',plug:'<path d="M9 2v6"/><path d="M15 2v6"/><path d="M6 8h12v3a6 6 0 0 1-12 0Z"/><path d="M12 17v5"/>',check:'<path d="M20 6 9 17l-5-5"/>',route:'<circle cx="6" cy="19" r="3"/><circle cx="18" cy="5" r="3"/><path d="M9 19h6a4 4 0 0 0 0-8H9a4 4 0 0 1 0-8h6"/>',branch:'<circle cx="6" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><circle cx="18" cy="8" r="3"/><path d="M18 11v1a3 3 0 0 1-3 3H9"/><path d="M6 9v6"/>',send:'<path d="M22 2 11 13"/><path d="M22 2l-7 20-4-9-9-4Z"/>',msg:'<path d="M21 11.5a8.4 8.4 0 0 1-12.9 7.5L3 21l2-5.1A8.4 8.4 0 1 1 21 11.5Z"/>',code:'<path d="m9 18-6-6 6-6"/><path d="m15 6 6 6-6 6"/>',hash:'<path d="M4 9h16"/><path d="M4 15h16"/><path d="M10 3 8 21"/><path d="M16 3l-2 18"/>',x:'<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',trace:'<path d="M4 4v16h16"/><path d="m7 15 4-4 3 3 5-6"/>'},_e=(t,e=14)=>'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="'+e+'" height="'+e+'" aria-hidden="true">'+t+"</svg>",yt=(t,e,a,n="")=>'<div class="ax-sec-label"><h3>'+_e(t,13)+e+(a?'<span class="ax-sec-label__n" id="'+a+'"></span>':"")+"</h3>"+n+"</div>";function sr(t={}){return L({title:"AgentX \xB7 Monitor",activeTab:"monitor",subtitle:"Monitor",peers:t.peers,body:`<div class="bf">
|
|
2
2
|
|
|
3
3
|
<div class="bf-head">
|
|
4
4
|
<div>
|
|
@@ -18937,4 +18937,4 @@ data: ${h.replace(/\n/g," ")}
|
|
|
18937
18937
|
`)}catch{}}};s.stdout?.on("data",l),s.stderr?.on("data",l);let c=setInterval(()=>{try{e.write(`: hb
|
|
18938
18938
|
|
|
18939
18939
|
`)}catch{}},15e3),p=()=>{clearInterval(c);try{s.kill()}catch{}try{e.end()}catch{}};t.on("close",p),s.on("exit",p),s.on("error",p)}async function Ai(t,e,a,n){let r=a.url+n,o=(t.method||"GET").toUpperCase(),i=o!=="GET"&&o!=="HEAD"?await new Promise((u,f)=>{let h=[];t.on("data",k=>h.push(k)),t.on("end",()=>u(Buffer.concat(h))),t.on("error",f)}):void 0,l={},c=t.headers["content-type"];c&&(l["Content-Type"]=Array.isArray(c)?c[0]:c);let p=t.headers["x-requested-with"];p&&(l["X-Requested-With"]=Array.isArray(p)?p[0]:p),a.token&&(l.Authorization=`Bearer ${a.token}`),l["X-Agentx-Peer"]="primary";try{let u=await fetch(r,{method:o,headers:l,body:i&&i.length>0?i:void 0}),f=Buffer.from(await u.arrayBuffer());e.writeHead(u.status,{"Content-Type":u.headers.get("content-type")||"application/json","Cache-Control":"no-store"}),e.end(f)}catch(u){y(e,502,{error:`proxy to peer failed: ${u?.message||u}`,target:r})}}function Ze(t,e){let a=t.replace(/\/+$/,""),n=(e.dashboard?.daemons||[]).find(r=>r.url.replace(/\/+$/,"")===a);return n?{url:$i(n),token:n.dashboardToken||n.token}:null}export{Qu as applyAttachSessions,Wu as fetchDaemonAgents,Hu as handleBoardRequest,Tb as resetLiveCaches,be as resolveNodeTargets,Sb as startBoardDashboard,Yu as withLastGood};
|
|
18940
|
-
//# sourceMappingURL=board-dashboard-
|
|
18940
|
+
//# sourceMappingURL=board-dashboard-IDV5SYLW.js.map
|
|
@@ -512,7 +512,7 @@ ${l}`)}let S={agentId:o,message:v,context:{channel:y,sender:f?"opencode":"openai
|
|
|
512
512
|
|
|
513
513
|
`)}}function ou(r){r.writeHead(200,{"Content-Type":"text/event-stream; charset=utf-8","Cache-Control":"no-cache",Connection:"keep-alive","X-Accel-Buffering":"no"})}function au(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}]})}
|
|
514
514
|
|
|
515
|
-
`)}function cu(r,e,t,n,s,i){let o=i?.usage?.inputTokens??0,a=i?.usage?.outputTokens??Math.ceil(s.length/4);ti(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 ti(r,e,t){r.writeHead(e,{"Content-Type":"application/json"}),r.end(JSON.stringify(t))}var Nt=class{module;minLevel;constructor(e,t="info"){this.module=e,this.minLevel=t}child(e){return new Nt(`${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(Nt.levelOrder[e]<Nt.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)}},Dt=Nt;Xe(Dt,"levelOrder",{debug:0,info:1,warn:2,error:3});var Bn={version:"0.
|
|
515
|
+
`)}function cu(r,e,t,n,s,i){let o=i?.usage?.inputTokens??0,a=i?.usage?.outputTokens??Math.ceil(s.length/4);ti(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 ti(r,e,t){r.writeHead(e,{"Content-Type":"application/json"}),r.end(JSON.stringify(t))}var Nt=class{module;minLevel;constructor(e,t="info"){this.module=e,this.minLevel=t}child(e){return new Nt(`${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(Nt.levelOrder[e]<Nt.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)}},Dt=Nt;Xe(Dt,"levelOrder",{debug:0,info:1,warn:2,error:3});var Bn={version:"0.85.0",commit:"c518003",startedAt:new Date(Date.now()-process.uptime()*1e3).toISOString()};import{randomUUID as rw}from"crypto";var Wn=class{constructor(e=new va){this.core=e}count=0;subscribe(e,t){this.count++;let n=this.core.subscribe((i,o)=>{if(!o||!iw.includes(o.kind))return;let a={...o,rootId:i.rootId,node:i.node};aw(e,a)&&t(a)}),s=!0;return()=>{s&&(s=!1,this.count--,n())}}publish(e){let t={id:typeof e.id=="string"?e.id:rw(),at:typeof e.at=="string"?e.at:new Date().toISOString(),...e},{type:n,summary:s,ref:i,agentId:o}=ow(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}},iw=["run","task","signal","mesh","channel","status"];function ow(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 aw(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 du(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 qn,timingSafeEqual as uu}from"crypto";var Vn=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[v,S]of Object.entries(e.headers))(v.startsWith("x-hubspot")||v.startsWith("x-hub")||v.startsWith("x-github")||v.startsWith("x-gitlab")||v.startsWith("stripe")||v.startsWith("sentry")||v.startsWith("x-vercel")||v.startsWith("x-odoo")||v.startsWith("x-webhook")||v==="user-agent"||v==="content-type"||v==="host"||v==="x-forwarded-host"||v==="x-forwarded-proto"||v==="x-forwarded-for")&&(b[v]=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 h=this.extractEventType(l,c,e.headers),m=this.webhookEntries.find(b=>b.enabled&&b.agentId===i&&b.source===l),f=h&&m?.triggers?.[h]||m?.defaultWorkflow||null;if(await this.fireHookSafe(l,h,i,c),f&&this.workflowDispatcher)try{let b=await this.workflowDispatcher.dispatchWorkflow({workflowId:f,entityRef:{kind:"webhook",id:`${l}:${i}:${h??"\u2014"}:${Date.now()}`},event:{kind:"webhook",source:l,eventType:h,payload:c},trigger:{source:l}});this.log(`Webhook [${l}/${h??"\u2014"}] -> workflow=${f} (claimed=${b.claimed})`),this.sendJson(t,202,{ok:!0,agent:i,source:l,eventType:h,workflow:f,claimed:b.claimed});return}catch(b){this.log(`Workflow dispatch failed [${l}/${h}/${f}]: ${b.message}`)}let y=this.webhookEntries.find(b=>b.enabled&&b.node&&b.agentId===i&&b.source===l);if(y?.node&&this.mesh){this.sendJson(t,202,{ok:!0,agent:i,source:l,node:y.node,status:"accepted"}),this.mesh.sendTask(y.node,u,i,{context:{channel:`webhook:${l}`,sender:`webhook:${l}`}}).then(b=>this.log(`Mesh-forwarded webhook [${l}] -> ${y.node}/${i}: ${b?.slice(0,100)||"ok"}`),b=>this.log(`Mesh forward failed [${l}] -> ${y.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(`
|
|
516
516
|
`)[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(`
|
|
517
517
|
`)[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??"?",h=l.changeFlag??l.changeSource??"";s.push(` - ${d} (object ${u}${h?`, ${h}`:""})`)}}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(`
|
|
518
518
|
`)}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="+qn("sha256",a).update(t).digest("hex");return lt(u,d)}if(n==="gitlab"){let d=c("x-gitlab-token");return d?lt(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 h=qn("sha256",a).update(`${u.t}.${t}`).digest("hex");return lt(h,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 h=parseInt(u,10);if(!Number.isFinite(h))return"malformed X-HubSpot-Request-Timestamp";let m=Date.now()-h;if(m>5*6e4)return`HubSpot webhook is ${Math.floor(m/1e3)}s old (>5min replay window)`;let f="POST",y=i||e["x-original-uri"]||e["x-forwarded-path"]||"",b=e["x-forwarded-host"],v=e.host,S=e["x-forwarded-proto"]||"https",T=new Set;b&&y&&T.add(`${S}://${b}${y}`),v&&y&&T.add(`https://${v}${y}`),v&&y&&T.add(`http://${v}${y}`),y&&T.add(y),T.add("");for(let A of T){let D=qn("sha256",a).update(`${f}${A}${t}${u}`).digest("base64");if(d.length===D.length&&uu(Buffer.from(d),Buffer.from(D)))return null}return`signature mismatch (tried ${T.size} URI variants)`}if(n==="odoo"){let d=c("x-odoo-signature");if(d){let h=qn("sha256",a).update(t).digest("hex"),m=d.startsWith("sha256=")?d.slice(7):d;return lt(h,m)}let u=c("x-odoo-webhook-token")??c("x-webhook-secret");return u?lt(a,u):"missing X-Odoo-Signature or X-Odoo-Webhook-Token"}let l=c("x-webhook-secret");return l?lt(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 lt(r,e){if(r.length!==e.length)return"signature mismatch";let t=Buffer.from(r),n=Buffer.from(e);return uu(t,n)?null:"signature mismatch"}qm();Um();function cw(r){return{insertTaskHistory:r.prepare(`
|
|
@@ -1136,4 +1136,4 @@ data: ${JSON.stringify(W)}
|
|
|
1136
1136
|
`)}catch{}},O=setInterval(()=>{try{t.write(`: ping
|
|
1137
1137
|
|
|
1138
1138
|
`)}catch{}},15e3);O.unref?.();let j=new AbortController;t.on("close",()=>{t.writableEnded||j.abort()});try{for await(let N of this.mesh.sendTaskStream(g.peer,g.message,g.agent,{context:g.context,signal:j.signal,vouchOwner:k}))x(N.event,N.data)}catch(N){x("error",{error:N?.message??String(N)})}finally{clearInterval(O);try{t.end()}catch{}}break}let M=g.context,P=typeof g.senderAgentId=="string"?g.senderAgentId:void 0;if(fm(g,!0)==="callback"){let x=this.delegationGate(e,g,{callee:g.agent,peer:g.peer,message:g.message,calleeContext:M});if(!("track"in x)){let O=Ls(x);this.json(t,O.status,O.body);break}}if(g.async===!0){let x=M?.channel,O=M?.chatId;if(!x||!O){this.json(t,400,{error:"async requires context.channel and context.chatId \u2014 there is no route back otherwise"});return}let j=`mesh-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;this.json(t,202,{accepted:!0,taskId:j,deliverTo:`${x}:${O}`,note:"result will be delivered to the originating chat when the peer finishes"});let N=g.peer,W=g.agent,z=this.mesh;(async()=>{let B=Date.now(),H;try{H=await z.sendTask(N,g.message,W,{vouchOwner:k,context:M,senderAgentId:P}),this.log(`[mesh/task async ${j}] ${N}/${W??"default"} finished in ${Date.now()-B}ms`)}catch(X){H=`Delegation to ${N}/${W??"default"} failed: ${X?.message??X}`,this.log(`[mesh/task async ${j}] failed: ${X?.message??X}`)}try{await this.router.sendOutbound({channel:x,chatId:O,text:H,agentId:M?.agentId??P,accountId:M?.accountId})}catch(X){this.log(`[mesh/task async ${j}] delivery failed: ${X?.message??X}`)}})();break}let C=await this.mesh.sendTask(g.peer,g.message,g.agent,{context:M,senderAgentId:P,vouchOwner:k});this.json(t,200,{response:C});break}case"POST /webrtc/signal/out":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await U(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let w=await this.webrtc.handleOutgoing(p);this.json(t,w.ok?200:400,w);break}case"POST /webrtc/signal":{if(!this.webrtc){this.json(t,404,{error:"WebRTC signaling not enabled"});return}let p=await U(e);if(!p.kind||!p.callId||!p.from||!p.to){this.json(t,400,{error:"Missing: kind, callId, from, to"});return}let w=this.webrtc.handleIncoming(p);this.json(t,w.ok?200:400,w);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 g=await U(e),p=g.callId,w=g.target,k=g.agentId||this.config.channels.webrtc?.bot.defaultAgentId;if(!p||!w||!k){this.json(t,400,{error:"Missing: callId, target, agentId (or defaultAgentId in config)"});return}let I=await this.botManager.invite({callId:p,target:w,agentId:k});this.json(t,I.ok?200:500,I);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 g=this.config.channels.webrtc;if(!g?.enabled){this.json(t,404,{error:"WebRTC signaling not enabled"});return}this.json(t,200,{localName:this.config.node.name,iceServers:[...g.stunServers.map(p=>({urls:p})),...g.turnServers],peers:this.mesh?.directory().map(p=>({name:p.peer,healthy:p.healthy}))||[],camera:g.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(g=>{let p=this.config.agents[g.id]||{},w=typeof p.description=="string"&&p.description.trim()||$0(p.systemPrompt)||`Agent "${g.name}" (${g.tier})`,k=Array.isArray(p.mentions)?p.mentions.slice(0,4):[];return{id:g.id,name:g.name,description:w,tags:[g.tier,...k],color:re(g.id,p).color}}),channels:this.router.getChannelNames(),defaultInputModes:["text"],defaultOutputModes:["text"]});break;case"GET /wiki/agents":{let g=this.registry.getWikiHub();this.json(t,200,{nodeId:this.config.node.id,agents:g.summary()});break}case"GET /wiki/entries":{let g=this.registry.getWikiHub(),p=n.searchParams.get("agent")||void 0,w=n.searchParams.get("after")||void 0,k=p?g.getAgentEntries(p):g.getSharedStore().listEntries({after:w});this.json(t,200,{nodeId:this.config.node.id,count:k.length,entries:k.map(I=>({id:I.id,date:I.date,agentId:I.agentId,source:I.source,sourceContext:I.sourceContext,content:I.content}))});break}case"GET /wiki/articles":{let g=this.registry.getWikiHub(),p=n.searchParams.get("agent");if(!p){this.json(t,400,{error:"?agent= required"});break}let k=g.getAgentWiki(p).rebuildIndex();this.json(t,200,{nodeId:this.config.node.id,agentId:p,articles:k.articles});break}case"GET /wiki/article":{let g=this.registry.getWikiHub(),p=n.searchParams.get("agent"),w=n.searchParams.get("path");if(!p||!w){this.json(t,400,{error:"?agent= and ?path= required"});break}let I=g.getAgentWiki(p).readArticle(w);if(!I){this.json(t,404,{error:"Article not found"});break}this.json(t,200,{nodeId:this.config.node.id,agentId:p,path:I.path,title:I.meta.title,tags:I.meta.tags,owner:I.meta.owner,created:I.meta.created,lastUpdated:I.meta.lastUpdated,sources:I.meta.sources,content:I.content});break}case"GET /graph/schema":{let g=this.registry.getGraphStore();if(!g){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,schema:g.loadSchema()});break}case"GET /graph/nodes":{let g=this.registry.getGraphStore();if(!g){this.json(t,404,{error:"graph disabled on this node"});break}this.json(t,200,{nodeId:this.config.node.id,...g.loadNodes()});break}case"GET /graph/classifications":{let g=this.registry.getGraphStore();if(!g){this.json(t,404,{error:"graph disabled on this node"});break}let p=n.searchParams.get("status")||"approved",w=Math.max(1,Math.min(1e3,parseInt(n.searchParams.get("limit")||"200",10)||200)),k=g.listByStatus(p,w);this.json(t,200,{nodeId:this.config.node.id,status:p,count:k.length,classifications:k});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 /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 /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/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 U(e);await lu(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=ig(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=Du();if(e==="json")return this.registry.getTodayUsage();let t=Ou(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||!kt(n)))try{let s=se(n,".claude","skills");Nm(s,{recursive:!0});let i=se(s,ug);if(!kt(i))Ao(i,Ci(e)),this.log(` memory-skill: installed remember.md \u2192 ${t.id}`);else{let o=gg(Yt(i,"utf-8"),e);o&&(Ao(i,o),this.log(` memory-skill: updated remember.md \u2192 ${t.id}`))}this.agentMemory.syncToWorkspace(t.id,n)}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||!kt(n))continue;let s=lg(aa(t),this.config.requests.enabled?cg():null);try{switch(dg(n,s)){case"installed":this.log(` mcp: installed ${Object.keys(s).length} server(s) \u2192 ${e}`);break;case"updated":this.log(` mcp: updated .mcp.json (${Object.keys(s).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(s).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(i){this.log(` mcp: ${e} install failed \u2014 ${i?.message??i}`)}}}workspaceFor(e){for(let t of this.registry.list())if(t.id===e)return t.workspace;return null}handleMemoryApi(e,t,n,s){return Uh(e,t,n,s,{mem:this.agentMemory,workspaceFor:i=>this.workspaceFor(i),runningTaskOwner:i=>this.registry.runningTaskOwner(i)})}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 ee(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 h=typeof n?.fromPeer=="string"?n.fromPeer:"unknown";this.log(`[workflows/mesh] received trigger from "${h}" source="${s.trigger.source}" chat="${s.trigger.chat??"*"}"`);let m=await this.workflowDispatcher.dispatch({trigger:s.trigger,entityRef:o,event:i,fromRemote:{peer:h}});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(h=>h.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 relayPush(e,t){let n=e.toLowerCase(),s=this.mesh?.directory().find(a=>a.peer.toLowerCase()===n);if(!s)throw new Error(`push: channels.push.relayTo "${e}" is not a mesh peer of this node`);let i=await fetch(`${s.peerUrl}/channel/send`,{method:"POST",headers:{"Content-Type":"application/json",...this.mesh.authHeaders(s.peer)},body:JSON.stringify(t),signal:AbortSignal.timeout(15e3)});if(!i.ok)throw new Error(`push: ${s.peer} /channel/send -> ${i.status} ${(await i.text().catch(()=>"")).slice(0,200)}`);return(await i.json().catch(()=>({}))).messageId??void 0}async handleChannelSend(e,t){let n;try{n=await ee(e)}catch(c){this.json(t,400,{error:"invalid JSON body",message:c.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}try{let c=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},{recordInSession:!1});this.json(t,200,{ok:!0,messageId:c??null})}catch(c){this.log(`[mesh] /channel/send "${s}" failed: ${c.message}`),this.json(t,500,{error:c.message})}}async handleChannelChats(e,t,n={}){let s=new Set,i=[],o=[],a=(l,d)=>{let u=0;for(let h of l)!h.id||s.has(h.id)||(s.add(h.id),i.push({...h,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 h=await u.json();Array.isArray(h.chats)&&a(h.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 ee(e)}catch{s={}}try{let i=await rg({get:o=>this.workflowStore.get(o),dispatchWorkflow:o=>this.workflowDispatcher.dispatchWorkflow(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})}}},Ro=Eo;Xe(Ro,"MESH_PROTECTED_PATHS",new Set(["/task","/ask","/mesh/task","/mesh/inbox/send","/workflow/event","/workflow/transition","/channel/send","/webrtc/signal","/gitlab/react","/gitlab/send-note","/gitlab/log-time","/channel/edit-comment","/github/send-comment"]));function $0(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 ee(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 T0(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 U(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)})}Fm();function QD(r){typeof r=="string"&&(Qt.error(r),process.exit(1)),r instanceof Error&&(Qt.error(r.message),process.exit(1)),Qt.error("Something went wrong. Please try again."),process.exit(1)}export{j0 as a,Pr as b,Ge as c,Rt as d,Pt as e,qe as f,Rn as g,x$ as h,$u as i,ww as j,bw as k,Eu as l,Ce as m,dt as n,Mu as o,ut as p,vx as q,Sx as r,Ii as s,sR as t,rR as u,iR as v,Kh as w,rk as x,dR as y,uR as z,ds as A,Ft as B,Rg as C,nv as D,CE as E,ps as F,re as G,ys as H,Hv as I,Sp as J,Bv as K,xp as L,ks as M,qt as N,$s as O,xs as P,_p as Q,so as R,$e as S,we as T,Gp as U,Hp as V,Bp as W,Wp as X,qs as Y,Am as Z,$o as _,Em as $,u0 as aa,HM as ba,Ro as ca,QD as da};
|
|
1139
|
-
//# sourceMappingURL=chunk-
|
|
1139
|
+
//# sourceMappingURL=chunk-AR7CGFAT.js.map
|
|
@@ -740,5 +740,5 @@ tr:hover td { background: var(--bg-hover); }
|
|
|
740
740
|
WHERE person = ? AND (channel IS NULL OR channel != 'a2a')
|
|
741
741
|
ORDER BY started_at DESC LIMIT ?`).all(t,Math.max(1,Math.min(n,500))).map(r=>({taskId:r.task_id,agentId:r.agent_id,channel:r.channel,chatId:r.chat_id,status:r.status,startedAt:r.started_at,messagePreview:r.message_preview}))}function nn(e,t){return e.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'requests'").get()?e.prepare("PRAGMA table_info(requests)").all().some(o=>o.name==="person")?e.prepare(`SELECT id, state, channel, agent_id, text, created_at FROM requests
|
|
742
742
|
WHERE person = ? AND state IN (${L.map(()=>"?").join(",")})
|
|
743
|
-
ORDER BY created_at`).all(t,...L).map(o=>({id:o.id,state:o.state,channel:o.channel,agentId:o.agent_id,text:o.text,createdAt:o.created_at})):[]:[]}Te();var V="member:",it=90,st="members",dt="tailscale-user-login",lt=400,ct=60*60*1e3;function pt(e){let t=e.scopes.find(n=>n.startsWith(V));return t?t.slice(V.length):null}function we(e,t){if(!e)return null;let n=t.verify(e),a=n?pt(n):null;return n&&a?{rec:n,personId:a}:null}function ln(e,t){let n=e.people().find(l=>l.id===t);if(!n)return{ok:!1,error:`No person "${t}". Add them first: agentx people add ${t} --name "\u2026"`};let{token:a,record:r}=e.tokens.create({name:`${n.name} (machine not paired yet)`,scopes:[`${V}${n.id}`],expiresInDays:it}),{code:o,expiresAt:s}=e.codes.create({token:a,tokenId:r.id,name:n.id});return e.members.log({person:n.id,device:r.id,event:"invited"}),{ok:!0,code:o,expiresAt:s,tokenId:r.id,person:n}}var gt="The private network says someone else is connecting from this machine. Ask the owner for a new code.",mt="Too many machines are waiting for the owner's answer. Try again later.",$e=(e,t)=>{let n=e.headers[t];return(Array.isArray(n)?n[0]:n||"").trim()};function Ae(e){let t=e.socket?.remoteAddress||"";return t==="127.0.0.1"||t==="::1"||t==="::ffff:127.0.0.1"}function ut(e){if(!Ae(e))return null;let t=$e(e,dt).toLowerCase();return t?t.slice(0,80):null}function ft(e){let t=e.socket?.remoteAddress||"unknown";if(!Ae(e))return t;let n=$e(e,"x-forwarded-for").split(",")
|
|
744
|
-
//# sourceMappingURL=chunk-
|
|
743
|
+
ORDER BY created_at`).all(t,...L).map(o=>({id:o.id,state:o.state,channel:o.channel,agentId:o.agent_id,text:o.text,createdAt:o.created_at})):[]:[]}Te();var V="member:",it=90,st="members",dt="tailscale-user-login",lt=400,ct=60*60*1e3;function pt(e){let t=e.scopes.find(n=>n.startsWith(V));return t?t.slice(V.length):null}function we(e,t){if(!e)return null;let n=t.verify(e),a=n?pt(n):null;return n&&a?{rec:n,personId:a}:null}function ln(e,t){let n=e.people().find(l=>l.id===t);if(!n)return{ok:!1,error:`No person "${t}". Add them first: agentx people add ${t} --name "\u2026"`};let{token:a,record:r}=e.tokens.create({name:`${n.name} (machine not paired yet)`,scopes:[`${V}${n.id}`],expiresInDays:it}),{code:o,expiresAt:s}=e.codes.create({token:a,tokenId:r.id,name:n.id});return e.members.log({person:n.id,device:r.id,event:"invited"}),{ok:!0,code:o,expiresAt:s,tokenId:r.id,person:n}}var gt="The private network says someone else is connecting from this machine. Ask the owner for a new code.",mt="Too many machines are waiting for the owner's answer. Try again later.",$e=(e,t)=>{let n=e.headers[t];return(Array.isArray(n)?n[0]:n||"").trim()};function Ae(e){let t=e.socket?.remoteAddress||"";return t==="127.0.0.1"||t==="::1"||t==="::ffff:127.0.0.1"}function ut(e){if(!Ae(e))return null;let t=$e(e,dt).toLowerCase();return t?t.slice(0,80):null}function ft(e){let t=e.socket?.remoteAddress||"unknown";if(!Ae(e))return t;let n=$e(e,"x-forwarded-for").split(",").pop().trim();return/^[0-9a-fA-F:.]{2,45}$/.test(n)?n:t}function ht(e){return typeof e=="string"?e.replace(/[^\p{L}\p{N} ._'()-]/gu," ").replace(/\s+/g," ").trim().slice(0,60):""}function vt(e){return e.identities.map(Q).filter(t=>!!t&&t.channel==="tailscale").map(t=>t.value)}async function cn(e,t){let n=Date.now(),a=t.now??Date.now,r=t.log??(m=>console.log(m)),o=ft(e),s=t.limiter.retryAfter(o);if(s>0)return r(`[member] pair-code refused from ${o}: locked out for ${s}s more`),{status:429,body:{error:"too many attempts",retryAfter:s},retryAfter:s};let l=null,i="";try{let m=await oe(e,2048);l=m.code,i=ht(m.machine)}catch{}let p=t.codes.redeem(l),g=p?we(p.token,t.tokens):null;if(await xt(n,t.minMs??lt),!p||!g)return t.limiter.fail(o),r(`[member] pair-code failed from ${o}`),{status:401,body:{error:j}};t.limiter.succeed(o);let{rec:f,personId:d}=g,h=t.people().find(m=>m.id===d);if(!h)return t.tokens.revoke(f.id),t.members.log({person:d,device:f.id,event:"refused",address:o,detail:"person no longer listed"}),r(`[member] pair-code for ${d} refused from ${o}: person no longer listed`),{status:403,body:{error:j}};let u=ut(e),A=vt(h);if(A.length&&(!u||!A.includes(u)))return t.tokens.revoke(f.id),t.members.log({person:d,device:f.id,event:"refused",address:o,detail:`network login ${u??"missing"}; expected ${A.join(" or ")}`}),r(`[member] ${d}: pairing from ${o} refused: the network says "${u??"nobody"}", expected ${A.join(" or ")}`),{status:403,body:{error:gt}};let x=i||"Unnamed machine",y=h.name.slice(0,40),v=re(t.root,{title:`New machine for ${y}`,ask:`From ${o}, ${u?`network login ${u}`:"no network login reported"}. Machine name, as typed there: "${x}". Let it see ${y}'s own work?`,recommend:`Yes if ${y} told you they just paired this machine. No if you did not expect it.`,if_silent:"discard",raised_by:st},{now:a()});return v.ok?(t.members.add({tokenId:f.id,personId:d,name:x,state:"pending",cardId:v.card.id,address:o,...u?{network:u}:{},createdAt:new Date(a()).toISOString()}),t.members.log({person:d,device:f.id,event:"paired",address:o,detail:x}),r(`[member] ${d} paired "${x}" from ${o}; waiting for the owner (card ${v.card.id})`),{status:200,body:{person:d,name:x,state:"pending"},token:p.token}):(t.tokens.revoke(f.id),t.members.log({person:d,device:f.id,event:"refused",address:o,detail:v.error}),r(`[member] ${d}: pairing from ${o} refused: ${v.error}`),{status:503,body:{error:mt}})}var H="this machine is not paired",bt="waiting for the owner to approve this machine";function pn(e,t,n){let a=t.now??Date.now,r=t.log??(g=>console.log(g)),o=we(e,t.tokens);if(!o)return{ok:!1,status:401,error:H};let{rec:s,personId:l}=o,i=t.members.byToken(s.id);if(!i||i.state==="removed"||i.personId!==l)return{ok:!1,status:401,error:H};if(t.people&&!t.people().some(g=>g.id===l))return Se(t,s.id,"person no longer listed"),r(`[member] ${l}: "${i.name}" ended: person no longer listed`),{ok:!1,status:401,error:H};if(i.state==="pending"){let g=i.cardId?ae(t.root,i.cardId):null,f=g?g.status==="decided"?g.verdict:g.status==="expired"?"no":null:null;if(f==="yes")i=t.members.update(s.id,{state:"active",approvedAt:new Date(a()).toISOString()})??i,t.members.log({person:l,device:s.id,event:"approved",detail:g?.decided_by}),r(`[member] ${l}: "${i.name}" approved`);else if(f==="no"){let d=g?.status==="expired"?"the owner did not answer in time":"the owner said no";return t.tokens.revoke(s.id),t.members.update(s.id,{state:"removed",removedAt:new Date(a()).toISOString(),removedReason:d}),t.members.log({person:l,device:s.id,event:"refused",detail:d}),r(`[member] ${l}: "${i.name}" refused: ${d}`),{ok:!1,status:401,error:H}}else return{ok:!1,status:403,error:bt,waiting:!0}}let p=i.lastSeenAt?Date.parse(i.lastSeenAt):0;return n&&(a()-p>=ct||i.lastAddress!==n)&&(i=t.members.update(s.id,{lastSeenAt:new Date(a()).toISOString(),lastAddress:n})??i,t.members.log({person:l,device:s.id,event:"signed-in",address:n})),{ok:!0,device:i,personId:l,rec:s}}function Se(e,t,n="removed by the owner"){let a=e.members.byToken(t);if(!a)return null;e.tokens.revoke(t);let r=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}),r}function gn(e,t){return e.members.devices(t).filter(n=>n.state!=="removed").map(n=>Se(e,n.tokenId,"person removed by the owner")).filter(n=>!!n)}async function xt(e,t){let n=e+t-Date.now();n>0&&await new Promise(a=>setTimeout(a,n))}var Ie=["gitlab","github"];function yt(e,t,n){let a=String(t||"").trim().toLowerCase();if(!Ie.includes(a))throw new Error(`Request status works on ${Ie.join(" and ")}, not on "${t}".`);e.requestStatus=e.requestStatus&&typeof e.requestStatus=="object"?e.requestStatus:{};let r=Array.isArray(e.requestStatus.channels)?e.requestStatus.channels.map(o=>String(o).toLowerCase()):[];return e.requestStatus.channels=n?[...new Set([...r,a])]:r.filter(o=>o!==a),`request status on ${a} is ${n?"on":"off"}`}function fn(e){return Array.isArray(e?.requestStatus?.channels)?e.requestStatus.channels.map(t=>String(t).toLowerCase()):[]}function hn(e){let{summary:t}=W(n=>yt(n,e?.channel,!!e?.enabled));return{summary:t}}var kt="https://ntfy.sh";function bn(e){return{enabled:!!e?.enabled,server:e?.server||kt,topicSet:!!e?.topic,tokenSet:!!e?.token}}function xn(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{W as a,ve as b,Nt as c,Ut as d,Wt as e,Ft as f,qt as g,jt as h,tn as i,nn as j,it as k,ln as l,ft as m,cn as n,pn as o,Se as p,gn as q,Ie as r,yt as s,fn as t,hn as u,bn as v,xn as w,rt as x,Qt as y};
|
|
744
|
+
//# sourceMappingURL=chunk-QFF6ARGN.js.map
|