agentix-cli 0.82.0 → 0.83.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 (150) hide show
  1. package/dist/{App-3AZUZJPW.js → App-KI7DWO6L.js} +2 -2
  2. package/dist/{App-3AZUZJPW.js.map → App-KI7DWO6L.js.map} +1 -1
  3. package/dist/ChatApp-XFJ23EEP.js +7 -0
  4. package/dist/{ChatApp-ACIKF3GC.js.map → ChatApp-XFJ23EEP.js.map} +1 -1
  5. package/dist/{agent-X2UYZ3ZE.js → agent-SWWBRKCE.js} +2 -2
  6. package/dist/{board-dashboard-65HGTFRC.js → board-dashboard-RT3CMQKD.js} +311 -241
  7. package/dist/board-dashboard-RT3CMQKD.js.map +1 -0
  8. package/dist/chunk-2QNT5JDS.js +4 -0
  9. package/dist/chunk-2QNT5JDS.js.map +1 -0
  10. package/dist/{chunk-E63BQ6VJ.js → chunk-3YTFEGKY.js} +2 -2
  11. package/dist/{chunk-C4YY6746.js → chunk-44GK7FM6.js} +2 -2
  12. package/dist/{chunk-ONGL6EKZ.js → chunk-44UYVCS4.js} +2 -2
  13. package/dist/chunk-4L244AW4.js +3 -0
  14. package/dist/chunk-4L244AW4.js.map +1 -0
  15. package/dist/chunk-4LLSTP5G.js +49 -0
  16. package/dist/chunk-4LLSTP5G.js.map +1 -0
  17. package/dist/{chunk-E3SVSIUU.js → chunk-5NTGUHOO.js} +55 -58
  18. package/dist/chunk-5NTGUHOO.js.map +1 -0
  19. package/dist/{chunk-5LD6TA4A.js → chunk-5TUEA72F.js} +2 -2
  20. package/dist/{chunk-LQLMNBJS.js → chunk-64DPYFWO.js} +2 -2
  21. package/dist/{chunk-BM6ZLX6F.js → chunk-6ZQ6XUM5.js} +2 -2
  22. package/dist/chunk-ACFQBLPX.js +3 -0
  23. package/dist/chunk-ACFQBLPX.js.map +1 -0
  24. package/dist/{chunk-6G72CCT2.js → chunk-AJ44V2QR.js} +23 -17
  25. package/dist/chunk-AJ44V2QR.js.map +1 -0
  26. package/dist/chunk-AM47KSTK.js +5 -0
  27. package/dist/{chunk-FSHQMXM3.js.map → chunk-AM47KSTK.js.map} +1 -1
  28. package/dist/{chunk-6PTO6DWW.js → chunk-AXMFBUCJ.js} +2 -2
  29. package/dist/{chunk-UCKKAWLZ.js → chunk-BRK6M6LA.js} +2 -2
  30. package/dist/chunk-BRK6M6LA.js.map +1 -0
  31. package/dist/{chunk-AW3YGAVS.js → chunk-JLLIBTN4.js} +212 -212
  32. package/dist/chunk-JLLIBTN4.js.map +1 -0
  33. package/dist/{chunk-PLTX6YGD.js → chunk-JODZ6DEJ.js} +2 -2
  34. package/dist/{chunk-CG3FSQ23.js → chunk-KKMDRBMJ.js} +2 -2
  35. package/dist/chunk-LIH7ZBYR.js +744 -0
  36. package/dist/chunk-LIH7ZBYR.js.map +1 -0
  37. package/dist/chunk-LQE73AZR.js +3 -0
  38. package/dist/chunk-LQE73AZR.js.map +1 -0
  39. package/dist/{chunk-KUUIIZEH.js → chunk-NUUEMTTV.js} +77 -77
  40. package/dist/chunk-NUUEMTTV.js.map +1 -0
  41. package/dist/{chunk-X7STXQOX.js → chunk-OENLCMTT.js} +2 -2
  42. package/dist/{chunk-CT36XINH.js → chunk-P44IU454.js} +2 -2
  43. package/dist/{chunk-WIGJ5BVG.js → chunk-PGIQW2AR.js} +2 -2
  44. package/dist/chunk-PPUN7YHA.js +5 -0
  45. package/dist/chunk-PPUN7YHA.js.map +1 -0
  46. package/dist/{chunk-ISRGFMQC.js → chunk-S5XLAIGY.js} +2 -2
  47. package/dist/{chunk-ZUCJK5PL.js → chunk-V3OZCYJX.js} +2 -2
  48. package/dist/chunk-VZLIBDLH.js +3 -0
  49. package/dist/chunk-VZLIBDLH.js.map +1 -0
  50. package/dist/chunk-XIYWXCNU.js +4 -0
  51. package/dist/chunk-XIYWXCNU.js.map +1 -0
  52. package/dist/cli.js +1 -1
  53. package/dist/client-LTHXQRE3.js +2 -0
  54. package/dist/config-IJ3QQTHJ.js +2 -0
  55. package/dist/config-mutator-AQIB7KSP.js +2 -0
  56. package/dist/doctor-KL3CY5YU.js +2 -0
  57. package/dist/{facts-5T5GRUTG.js → facts-ROUMKS7I.js} +2 -2
  58. package/dist/grants-N7XC7NLS.js +2 -0
  59. package/dist/hosts-NFNCYKGY.js +2 -0
  60. package/dist/index.d.ts +54 -6
  61. package/dist/index.js +1 -1
  62. package/dist/index.js.map +1 -1
  63. package/dist/pair-codes-EYGELBPD.js +2 -0
  64. package/dist/{program-R646G4NP.js → program-SZQY46QR.js} +201 -190
  65. package/dist/program-SZQY46QR.js.map +1 -0
  66. package/dist/promote-GPKUSAHD.js +2 -0
  67. package/dist/query-JS5N27BF.js +2 -0
  68. package/dist/registry-GH2GQ6H6.js +2 -0
  69. package/dist/request-planner-Y2KC43OY.js +2 -0
  70. package/dist/{request-planner-L2S4KMMU.js.map → request-planner-Y2KC43OY.js.map} +1 -1
  71. package/dist/review-candidates-4PJN3ZSM.js +4 -0
  72. package/dist/{review-candidates-R23QNJ2Q.js.map → review-candidates-4PJN3ZSM.js.map} +1 -1
  73. package/dist/routing-WI4IFJ4P.js +2 -0
  74. package/dist/schedule-tool-RJPS6ENN.js +2 -0
  75. package/dist/scheduler-WKAS5TGA.js +2 -0
  76. package/dist/scheduler-WKAS5TGA.js.map +1 -0
  77. package/dist/seat-VACK7BIT.js +2 -0
  78. package/dist/seat-VACK7BIT.js.map +1 -0
  79. package/dist/select-D2OSTDZF.js +2 -0
  80. package/dist/{select-KCCT7OJZ.js.map → select-D2OSTDZF.js.map} +1 -1
  81. package/dist/set-enabled-QKF7NREN.js +2 -0
  82. package/dist/{set-enabled-FEUPS2WI.js.map → set-enabled-QKF7NREN.js.map} +1 -1
  83. package/dist/store-7W2AP5H4.js +2 -0
  84. package/dist/store-7W2AP5H4.js.map +1 -0
  85. package/dist/token-store-YBSU2DTV.js +2 -0
  86. package/dist/token-store-YBSU2DTV.js.map +1 -0
  87. package/dist/{tool-WGPZW3SR.js → tool-NPLCT7MV.js} +2 -2
  88. package/dist/{tool-WGPZW3SR.js.map → tool-NPLCT7MV.js.map} +1 -1
  89. package/dist/{tool-YOXUNCTU.js → tool-TLU7DQBO.js} +2 -2
  90. package/dist/{tool-YOXUNCTU.js.map → tool-TLU7DQBO.js.map} +1 -1
  91. package/dist/wiki-UF6GARQR.js +2 -0
  92. package/dist/wiki-UF6GARQR.js.map +1 -0
  93. package/package.json +1 -1
  94. package/dist/ChatApp-ACIKF3GC.js +0 -7
  95. package/dist/board-dashboard-65HGTFRC.js.map +0 -1
  96. package/dist/chunk-6G72CCT2.js.map +0 -1
  97. package/dist/chunk-AW3YGAVS.js.map +0 -1
  98. package/dist/chunk-E3SVSIUU.js.map +0 -1
  99. package/dist/chunk-FSHQMXM3.js +0 -5
  100. package/dist/chunk-KUUIIZEH.js.map +0 -1
  101. package/dist/chunk-UCKKAWLZ.js.map +0 -1
  102. package/dist/chunk-VQN36LEB.js +0 -51
  103. package/dist/chunk-VQN36LEB.js.map +0 -1
  104. package/dist/chunk-XMDA4JYK.js +0 -748
  105. package/dist/chunk-XMDA4JYK.js.map +0 -1
  106. package/dist/client-QE4D43K3.js +0 -2
  107. package/dist/config-ME774GIO.js +0 -2
  108. package/dist/config-mutator-2AUDHSVD.js +0 -2
  109. package/dist/doctor-GS2ZHLWU.js +0 -2
  110. package/dist/program-R646G4NP.js.map +0 -1
  111. package/dist/promote-ZJCGGVRD.js +0 -2
  112. package/dist/query-UMGPOBEJ.js +0 -2
  113. package/dist/registry-WD5B2DQQ.js +0 -2
  114. package/dist/request-planner-L2S4KMMU.js +0 -2
  115. package/dist/review-candidates-R23QNJ2Q.js +0 -4
  116. package/dist/routing-PUQUADQ6.js +0 -2
  117. package/dist/schedule-tool-3DAJU764.js +0 -2
  118. package/dist/scheduler-JTPIGC5K.js +0 -2
  119. package/dist/seat-O5IC5M5D.js +0 -2
  120. package/dist/select-KCCT7OJZ.js +0 -2
  121. package/dist/set-enabled-FEUPS2WI.js +0 -2
  122. package/dist/wiki-QSBAE5ZK.js +0 -2
  123. /package/dist/{agent-X2UYZ3ZE.js.map → agent-SWWBRKCE.js.map} +0 -0
  124. /package/dist/{chunk-E63BQ6VJ.js.map → chunk-3YTFEGKY.js.map} +0 -0
  125. /package/dist/{chunk-C4YY6746.js.map → chunk-44GK7FM6.js.map} +0 -0
  126. /package/dist/{chunk-ONGL6EKZ.js.map → chunk-44UYVCS4.js.map} +0 -0
  127. /package/dist/{chunk-5LD6TA4A.js.map → chunk-5TUEA72F.js.map} +0 -0
  128. /package/dist/{chunk-LQLMNBJS.js.map → chunk-64DPYFWO.js.map} +0 -0
  129. /package/dist/{chunk-BM6ZLX6F.js.map → chunk-6ZQ6XUM5.js.map} +0 -0
  130. /package/dist/{chunk-6PTO6DWW.js.map → chunk-AXMFBUCJ.js.map} +0 -0
  131. /package/dist/{chunk-PLTX6YGD.js.map → chunk-JODZ6DEJ.js.map} +0 -0
  132. /package/dist/{chunk-CG3FSQ23.js.map → chunk-KKMDRBMJ.js.map} +0 -0
  133. /package/dist/{chunk-X7STXQOX.js.map → chunk-OENLCMTT.js.map} +0 -0
  134. /package/dist/{chunk-CT36XINH.js.map → chunk-P44IU454.js.map} +0 -0
  135. /package/dist/{chunk-WIGJ5BVG.js.map → chunk-PGIQW2AR.js.map} +0 -0
  136. /package/dist/{chunk-ISRGFMQC.js.map → chunk-S5XLAIGY.js.map} +0 -0
  137. /package/dist/{chunk-ZUCJK5PL.js.map → chunk-V3OZCYJX.js.map} +0 -0
  138. /package/dist/{client-QE4D43K3.js.map → client-LTHXQRE3.js.map} +0 -0
  139. /package/dist/{config-ME774GIO.js.map → config-IJ3QQTHJ.js.map} +0 -0
  140. /package/dist/{config-mutator-2AUDHSVD.js.map → config-mutator-AQIB7KSP.js.map} +0 -0
  141. /package/dist/{doctor-GS2ZHLWU.js.map → doctor-KL3CY5YU.js.map} +0 -0
  142. /package/dist/{facts-5T5GRUTG.js.map → facts-ROUMKS7I.js.map} +0 -0
  143. /package/dist/{promote-ZJCGGVRD.js.map → grants-N7XC7NLS.js.map} +0 -0
  144. /package/dist/{query-UMGPOBEJ.js.map → hosts-NFNCYKGY.js.map} +0 -0
  145. /package/dist/{registry-WD5B2DQQ.js.map → pair-codes-EYGELBPD.js.map} +0 -0
  146. /package/dist/{routing-PUQUADQ6.js.map → promote-GPKUSAHD.js.map} +0 -0
  147. /package/dist/{schedule-tool-3DAJU764.js.map → query-JS5N27BF.js.map} +0 -0
  148. /package/dist/{scheduler-JTPIGC5K.js.map → registry-GH2GQ6H6.js.map} +0 -0
  149. /package/dist/{seat-O5IC5M5D.js.map → routing-WI4IFJ4P.js.map} +0 -0
  150. /package/dist/{wiki-QSBAE5ZK.js.map → schedule-tool-RJPS6ENN.js.map} +0 -0
@@ -1,11 +1,8 @@
1
- import{a as Ie}from"./chunk-GTJIKXDB.js";import{q as Kt}from"./chunk-S2GAEH2F.js";import{a as k}from"./chunk-CL53UVOF.js";import{t as Ht,u as qt}from"./chunk-E63BQ6VJ.js";import{d as Bt,e as zt}from"./chunk-AQASR6KR.js";import{b as Se,u as Ct,w as ne,x as ve,z as $e}from"./chunk-6G72CCT2.js";import{a as Mt,b as jt,c as Vt,d as Wt,e as Ft,f as Ut}from"./chunk-Y4CYQV7G.js";import{a as Dt,b as Et}from"./chunk-SHEUCITK.js";import{g as Tt,h as Pt,i as Lt,k as Ot,l as Nt}from"./chunk-WIGJ5BVG.js";import{q as _t}from"./chunk-CG3FSQ23.js";import{a as At,b as Rt}from"./chunk-FSHQMXM3.js";import{A as St,B as Jr,W as xe,aa as vt,ba as $t,ea as It,r as te,s as bt,t as wt,u as Kr,z as xt}from"./chunk-VQN36LEB.js";import{a as ke,h as Gr}from"./chunk-UCKKAWLZ.js";import{a as kt,i as Xr}from"./chunk-PN6XHTG5.js";import{existsSync as Yr,readdirSync as Zr,readFileSync as Qr,statSync as ei}from"fs";import{resolve as ti}from"path";function Gt(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)??[],c=a.filter(g=>n-g.at<=r),l=a.filter(g=>n-g.at>r&&n-g.at<=r*2),u=c.filter(g=>g.status==="failed").length,d=a.filter(g=>g.status==="paused").length,p=a.length?Math.max(...a.map(g=>g.at)):null,f=a.length?l.length>0&&c.length===0?"dormant":c.length>0&&u*2>=c.length?"failing":c.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:p,recent:c.length,prior:l.length,failed:u,paused:d}}).sort((o,a)=>{let c={dormant:0,failing:1,active:2,quiet:3,never:4};return c[o.state]-c[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var re=new Map;function ja(t,e=1e3){if(!Yr(t))return[];let n=Zr(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=ti(t,s);return{path:o,mtime:ei(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 c=ni(s,o);re.set(s,{mtime:o,summary:c}),c&&r.push(c)}return r}function ni(t,e){try{let n=Qr(t,"utf-8").split(`
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]),c=a.status??a.run?.status;if(c){s=c;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var ri={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},x={routines:200,summary:160,filters:6,filterValue:60,text:120},ii=(t,e,n)=>{try{return _t(t,e,n)}catch{return null}},Xt=864e5;function Ua(t){let e=t.now??Date.now(),n={...ri,...t.thresholds},i=t.nextFire??ii,r=[];for(let a of t.crons){let c=t.cronRuns.get(a.id)??[],l=a.timezone||"UTC",u=c.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=c[0],p={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:I(a.id,x.text),trigger:{schedule:I(a.schedule,x.text),timezone:l},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?Ae(a.nextRun)??Ae(i(a.schedule,new Date(e),l)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:ui(d.status==="success"?void 0:d.errorSummary,x.summary)}:null,lastSuccessAt:c.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:Jt(u),sampledRuns:c.length,flags:[],attention:null};p.flags=Yt(p,u,a.schedule,l,null,e,n,i),r.push(Zt(p))}let s=new Map(Gt(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 c=o.get(a.workflowId);c?c.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let c=a.nodes.find(_=>_.type.startsWith("trigger."));if(!c||c.type!=="trigger.cron"&&c.type!=="trigger.hook")continue;let l=c.config??{},u=a.state||"active",d=u==="active",p=(o.get(a.id)??[]).slice().sort((_,we)=>we.at-_.at),f=p.map(_=>({at:_.at,status:ai(_.status)})),g=f[0],h=c.type==="trigger.cron",y=typeof l.spec=="string"?l.spec:"",T=typeof l.timezone=="string"?l.timezone:"UTC",F={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:I(a.title||a.id,x.text),trigger:h?{schedule:I(y,x.text),timezone:T}:{event:I(typeof l.event=="string"?l.event:"",x.text),filters:li(l.filter,a)},agent:ci(a),enabled:d,state:u,nextRunAt:h&&d&&y?Ae(i(y,new Date(e),T)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let _=f.find(we=>we.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:Jt(f),sampledRuns:p.length,flags:[],attention:null},ee=Date.parse(a.updated||a.created||"");F.flags=h?Yt(F,f,y,T,Number.isFinite(ee)?ee:null,e,n,i):si(F,s.get(a.id)?.state==="dormant",Number.isFinite(ee)?ee:null,e,n),r.push(Zt(F))}return r.sort(oi).slice(0,x.routines)}function Jt(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 Yt(t,e,n,i,r,s,o,a){let c=[],l=e.length?e[0].at:null;if(!t.enabled){let p=en(l,r,s,o);return p&&c.push(p),c}if(t.consecutiveFailures>=o.failStreak&&c.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),l===null)return c.push({reason:"never-ran",detail:"No persisted attempt"}),c;let u=new Date(l),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&&c.push({reason:"overdue",detail:`No attempt since ${new Date(l).toISOString()}; ${o.missedFires} scheduled fires missed`}),c}function si(t,e,n,i,r){let s=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=en(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 en(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*Xt?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/Xt)} days`:"Disabled and never ran"}}function Zt(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 Qt={critical:0,warning:1,info:2};function oi(t,e){let n=t.attention?Qt[t.attention]:3,i=e.attention?Qt[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function ai(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 ci(t){if(t.ownerAgent)return I(t.ownerAgent,x.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?I(String(e.config.agentId),x.text):null}function li(t,e){let n=[],i=e?.project;if(i&&n.push(I(`project=${i}`,x.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(I(`${r}=${o.join(",")}`,x.filterValue))}return n.slice(0,x.filters)}function Ae(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function I(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function ui(t,e){return t===void 0?void 0:I(t,e)}import{createHash as di,randomBytes as tn}from"crypto";import{existsSync as pi,mkdirSync as fi,readFileSync as gi,writeFileSync as mi}from"fs";import{resolve as hi,dirname as yi}from"path";var Re="agx_live_",bi=".agentx/tokens.json",nn=class{file;constructor(e=process.cwd(),n=bi){this.file=hi(e,n)}load(){if(!pi(this.file))return[];try{return JSON.parse(gi(this.file,"utf-8"))}catch{return[]}}save(e){fi(yi(this.file),{recursive:!0}),mi(this.file,JSON.stringify(e,null,2)+`
3
- `,"utf-8")}create(e){if(!e.name?.trim())throw new Error("Token name is required.");if(!Array.isArray(e.scopes)||e.scopes.length===0)throw new Error("At least one scope is required.");for(let o of e.scopes)if(!wi(o))throw new Error(`Invalid scope: ${o}`);let n=tn(32).toString("hex"),i=Re+n,r={id:"tok_"+tn(4).toString("hex"),name:e.name.trim(),prefix:Re+n.slice(0,4),hash:rn(i),scopes:[...e.scopes],createdAt:new Date().toISOString(),expiresAt:e.expiresInDays?new Date(Date.now()+e.expiresInDays*86400*1e3).toISOString():void 0},s=this.load();return s.push(r),this.save(s),{token:i,record:r}}list(){return this.load()}revoke(e){let n=this.load(),i=n.find(r=>r.id===e);return i?(i.revokedAt=new Date().toISOString(),this.save(n),i):null}isActive(e){let n=this.load().find(i=>i.id===e);return!!n&&!n.revokedAt&&!(n.expiresAt&&Date.parse(n.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(Re))return null;let n=rn(e),i=this.load(),r=i.find(a=>a.hash===n);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let s=Date.now(),o=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(s-o>6e4){r.lastUsedAt=new Date(s).toISOString();try{this.save(i)}catch{}}return r}};function Ka(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function wi(t){return t==="dashboard:read"||t==="dashboard:write"||t==="agent:*"||/^agent:[a-z0-9][a-z0-9_-]*$/.test(t)||t==="mesh:peer"||t==="app"||/^member:[a-z0-9][a-z0-9_-]{0,39}$/.test(t)}function rn(t){return"sha256:"+di("sha256").update(t).digest("hex")}function Ga(t){let e=t.headers.authorization,n=Array.isArray(e)?e[0]:e;if(n&&n.toLowerCase().startsWith("bearer "))return n.slice(7).trim();if(t.url)try{let r=new URL(t.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}import{existsSync as ae,readdirSync as Gi,readFileSync as Xi}from"fs";import{resolve as O}from"path";import{randomBytes as an}from"crypto";import{existsSync as xi,mkdirSync as Si,readdirSync as vi,readFileSync as $i,renameSync as cn,unlinkSync as Ii,writeFileSync as Ai}from"fs";import{resolve as ln}from"path";function sn(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var ki=t=>t.trim().split(`
4
- `).pop()?.slice(0,300)||"no output";async function on(t,e,n,i=Ie){let r=await i(t.bin,[...sn(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${ki(r.stderr||r.stdout)}`}}async function Ya(t,e,n,i,r=Ie){return(await r(t.bin,[...sn(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var Ri=2e3,_i=t=>on(t.wacli,t.to,t.text);function _e(t){return ln(t,".agentx","whatsapp-triage","drafts")}var Ci=t=>/^[a-z0-9-]{8,64}$/.test(t),ie=(t,e)=>ln(_e(t),`${e}.json`);function un(t,e){Si(_e(t),{recursive:!0});let n=ie(t,e.id),i=`${n}.${process.pid}.tmp`;Ai(i,JSON.stringify(e,null,2)+`
5
- `,{mode:384}),cn(i,n)}function rc(t,e,n=Date.now()){let i=e.text.trim().slice(0,Ri);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${an(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return un(t,r),r}function se(t,e){if(!Ci(e))return null;try{return JSON.parse($i(ie(t,e),"utf-8"))}catch{return null}}function dn(t,e){let n=_e(t);return xi(n)?vi(n).filter(i=>i.endsWith(".json")).map(i=>se(t,i.slice(0,-5))).filter(i=>!!i&&(!e||i.status===e)).sort((i,r)=>i.created_at.localeCompare(r.created_at)):[]}async function pn(t,e,n,i={}){let r=se(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let s=`${ie(t,e)}.${process.pid}.${an(3).toString("hex")}.claim`;try{cn(ie(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(i.send??_i)(r).catch(c=>({ok:!1,error:String(c?.message??c)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}un(t,o);try{Ii(s)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{existsSync as Di,mkdirSync as Ei,readdirSync as Ti,readFileSync as Pi,renameSync as Li,writeFileSync as Oi}from"fs";import{resolve as mn}from"path";function fn(t,e){let n=t.list?` in the "${t.list}" list`:"",i=[`This card came from the operator's reminder "${t.title}"${n} (id ${t.id}).`];return i.push(e?`Do what the operator chose, then tick the reminder off: remindctl complete ${t.id}`:"Leave the reminder open; it will come back at a later check-in."),i}var gn=["discard","keep","pause","approve"],A={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Ni={defaultExpiryDays:3,maxExpiryDays:30};function U(t){return mn(t,".agentx","approvals")}var Mi=/^[a-z0-9][a-z0-9-]{0,80}$/;function hn(t){return Mi.test(t)}function yn(t,e){if(!hn(e))throw new Error(`invalid card id: ${e}`);return mn(U(t),`${e}.json`)}function ji(t,e){let n=new Date(t).toISOString().slice(0,10),i=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${n}-${i||"card"}-${Math.random().toString(36).slice(2,6)}`}function oe(t,e){Ei(U(t),{recursive:!0});let n=yn(t,e.id),i=`${n}.${process.pid}.tmp`;Oi(i,JSON.stringify(e,null,2)+`
6
- `),Li(i,n)}function P(t,e){if(!hn(e))return null;try{return JSON.parse(Pi(yn(t,e),"utf-8"))}catch{return null}}function L(t,e){let n=U(t);if(!Di(n))return[];let i=[];for(let r of Ti(n).filter(s=>s.endsWith(".json")&&!s.startsWith("_")).sort()){let s=P(t,r.slice(0,-5));s&&(!e||s.status===e)&&i.push(s)}return i}function w(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function Vi(t,e,n){let i=e+n.maxExpiryDays*864e5,r,s=w(t);if(!s)r=e+n.defaultExpiryDays*864e5;else{let o=/^(\d+)\s*([hd])$/i.exec(s);if(o)r=e+Number(o[1])*(o[2].toLowerCase()==="d"?864e5:36e5);else if(r=Date.parse(s),Number.isNaN(r))return{ok:!1,error:`expires must be an ISO date or time, or like "12h" / "3d" (got "${s}")`}}return r<=e?{ok:!1,error:"expires must be in the future"}:{ok:!0,at:new Date(Math.min(r,i)).toISOString()}}function Wi(t,e={}){let n=e.now??Date.now(),i=e.settings??Ni,r=w(t.title),s=w(t.ask),o=w(t.recommend),a=w(t.raised_by);if(!r)return{ok:!1,error:"title is required"};if(!s)return{ok:!1,error:"ask is required: the yes/no question"};if(!o)return{ok:!1,error:"recommend is required: your advice and why, in one line"};if(!a)return{ok:!1,error:"raised_by is required: the agent id"};if(r.length>A.title)return{ok:!1,error:`title is longer than ${A.title} characters`};if(s.length>A.ask)return{ok:!1,error:`ask is longer than ${A.ask} characters`};if(o.length>A.recommend)return{ok:!1,error:`recommend is longer than ${A.recommend} characters`};let c=w(t.if_silent).toLowerCase();if(!gn.includes(c))return{ok:!1,error:`if_silent must be one of ${gn.join(", ")}`};let l=Vi(t.expires,n,i);if(!l.ok)return l;let u=w(t.source);if(u.length>A.source)return{ok:!1,error:`source is longer than ${A.source} characters`};if(u&&/^[a-z][a-z0-9+.-]*:/i.test(u)&&!/^https?:\/\//i.test(u))return{ok:!1,error:"source must be an http(s) link or a plain reference"};let d=Vt(t);if(!d.ok)return d;let p,f=t.reply;return f&&typeof f=="object"&&w(f.channel)&&w(f.chatId)&&(p={channel:w(f.channel),chatId:w(f.chatId),...w(f.accountId)?{accountId:w(f.accountId)}:{}}),{ok:!0,card:{id:ji(n,r),title:r,ask:s,recommend:o,if_silent:c,expires:l.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...p?{reply:p}:{},...d.value,...e.origin?{origin:e.origin}:{},status:"pending"}}}function uc(t,e,n={}){let i=Wi(e,n);if(!i.ok)return i;let r=L(t,"pending").filter(s=>s.raised_by===i.card.raised_by).length;return r>=A.pendingPerAgent?{ok:!1,error:`${i.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(oe(t,i.card),i)}function bn(t,e,n,i={}){let r=P(t,e);if(!r)return{ok:!1,error:`no card "${e}"`};if(r.status!=="pending")return{ok:!1,error:`card "${e}" is already ${r.status}`};let s=Ft(r,n,i);if(!s.ok)return s;let o=w(i.note).slice(0,A.note),a={...r,status:"decided",verdict:n,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString(),...o?{note:o}:{},...s.choice?{choice:s.choice}:{},...s.text?{text:s.text}:{}};return oe(t,a),{ok:!0,card:a}}function dc(t,e=Date.now()){let n=[];for(let i of L(t,"pending")){if(Date.parse(i.expires)>e)continue;let r={...i,status:"expired",outcome:i.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};oe(t,r),n.push(r)}return n}function pc(t){return L(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function fc(t,e,n=Date.now()){let i=P(t,e);!i||i.agent_notified_at||oe(t,{...i,agent_notified_at:new Date(n).toISOString()})}function gc(t){let e=t.status==="decided"?t.verdict==="yes"?"The operator said YES.":"The operator said NO.":`Nobody answered before it expired, so the default applied: ${t.outcome??t.if_silent}.`,n=[`[Approval result] Your decision card "${t.title}" (${t.id}) is closed.`,`Question: ${t.ask}`,e];return t.status==="decided"&&t.verdict==="yes"&&n.push(...Ut(t)),t.note&&n.push(`Operator note: ${t.note}`),t.source&&n.push(`Source: ${t.source}`),t.origin&&n.push(...fn(t.origin,t.status==="decided"&&t.verdict==="yes")),t.reply&&n.push(`You raised it from ${t.reply.channel} chat ${t.reply.chatId}; reply there if the requester should know.`),n.push("Act on this result now. Do not raise the same card again."),n.join(`
7
- `)}import{mkdirSync as Fi,readFileSync as Ui,renameSync as Bi,writeFileSync as zi}from"fs";import{resolve as Hi}from"path";function wn(t){return Hi(U(t),"_state.json")}function C(t){try{let e=JSON.parse(Ui(wn(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 K(t,e){Fi(U(t),{recursive:!0});let n=wn(t),i=`${n}.${process.pid}.tmp`;zi(i,JSON.stringify(e,null,2)+`
8
- `),Bi(i,n)}function kn(t,e,n,i=Date.now()){let r=C(t),s={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>i&&(s[o]=a);s[e]=n.toISOString(),K(t,{...r,snoozed:s})}function wc(t,e){K(t,{...C(t),lastDigest:e})}function xn(t,e,n,i=Date.now()){let r=C(t),s=new Set(n),o={};for(let[c,l]of Object.entries(r.popped??{}))s.has(c)&&(o[c]=l);o[e]=new Date(i).toISOString();let a=(r.wanted??[]).filter(c=>c!==e&&s.has(c));K(t,{...r,popped:o,wanted:a})}function Sn(t,e){let n=C(t);K(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function kc(t,e=Date.now()){K(t,{...C(t),popped:{},passAt:new Date(e).toISOString()})}Xr();Jr();import{existsSync as qi,readFileSync as Ki}from"fs";It();Gr();function vn(t){let e=At(t),n={};if(qi(e))try{n=vt(JSON.parse(Ki(e,"utf-8")))}catch{n={}}let i=xe.safeParse(n?.requests);return i.success?i.data:xe.parse(void 0)}async function Ac(t,e={}){let n=(t.channels??[]).filter(i=>!ke.has(i.toLowerCase().split("@")[0]));return n.length?{success:!1,error:`unknown channel ${n.map(i=>`"${i}"`).join(", ")}: use ${[...ke].join(", ")}`}:Rt(i=>{let r=i.requests??={};for(let s of["enabled","channels","from","staleAfterHours","retentionDays"])t[s]!==void 0&&(r[s]=t[s])},{configPath:e.configPath,reload:e.reload})}var In=["card","schedule","memory","wiki","whatsapp","request"],Ji=280;function j(t,e=Ji){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Ce(t){if(t.configPath)return O(t.configPath);let e=[O(t.root,"agentx.json"),O(t.root,".agentx","config.json")];return e.find(n=>ae(n))??e[0]}function De(t){return t.wikiDir?O(t.wikiDir):O(t.root,".agentx","wiki")}function Yi(t){return L(t.root,"pending").map(Zi)}function Zi(t){return{key:`card:${t.id}`,kind:"card",title:t.title,ask:t.ask,yes:`tell ${t.raised_by} yes`,no:`tell ${t.raised_by} no`,recommend:t.recommend,if_silent:t.if_silent,expires:t.expires,...t.source?{source:t.source}:{},raised_by:t.raised_by,created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.context||t.draft?{detail:j([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function Qi(t){let e=Ce(t);if(!ae(e))return[];let n;try{n=JSON.parse(Xi(e,"utf-8"))}catch{return[]}let i=new Date(t.now??Date.now()),r=[];for(let[s,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let c=o.timezone||"UTC",l=o.schedule?Tt(o.schedule):"",u=o.schedule?`${l.charAt(0).toLowerCase()}${l.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),p=a.action==="create";r.push({key:`schedule:${s}`,kind:"schedule",title:p?`New schedule "${s}" for ${o.agent??"an agent"}`:`Delete schedule "${s}"`,ask:p?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${s}" (${u})?`,yes:p?"enable it":"remove it",no:p?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:j(`${d}${p&&o.schedule?` \xB7 first run ${Lt(Pt(o.schedule,c,i),c)}`:""}`),more:"agentx schedule list"})}return r}function An(t){let e=O(t,".agentx","memory");return ae(e)?Gi(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function es(t){let e=An(t.root);if(e.length===0)return[];let n=new Se(t.root),i=[];for(let r of e)for(let s of n.held(r))i.push({key:`memory:${r}/${s.id}`,kind:"memory",title:`Fact ${r} learned from ${s.source.channel}`,ask:`Let ${r} use this fact in its prompts?`,yes:"use it",no:"keep it out for good",raised_by:r,created_at:s.createdAt,detail:j(s.content),more:`agentx memory facts held --agent ${r}`});return i}function ts(t){let e=t.sources.filter(n=>n.failure);return e.length?e.map(n=>`Recurring failure: ${n.agentId}'s ${n.failure.tool} fails with "${n.failure.errorClass}" in ${n.occurrences??1} sessions (${n.failure.runs} runs).`).join(" "):`${t.sources.length} source(s)${t.occurrences>1?`, seen in ${t.occurrences} sessions`:""}.`}function ns(t){return zt(De(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:j(`${ts(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function rs(t){return dn(t.root,"pending").map(e=>({key:`whatsapp:${e.id}`,kind:"whatsapp",title:`WhatsApp reply to ${e.chat_name||e.to}`,ask:`Send this to ${e.chat_name||e.to}? "${e.text}"`,yes:"send it on WhatsApp",no:"drop the draft",raised_by:e.agent,created_at:e.created_at,detail:j(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}function Rn(t){if(t.requests)return t.requests;if(O(t.root)!==process.cwd()||!ae(O(t.root,".agentx","db.sqlite")))return null;let e=kt({quiet:!0});if(!e)return null;let n=$n.get(e);return!n&&!xt(e)?null:(n||$n.set(e,n=new St(e)),n)}var $n=new WeakMap;function is(t){let e=Rn(t);return e?e.listByState("needs_attention").map(n=>({key:`request:${n.id}`,kind:"request",title:`Request not finished: ${j(n.text,80)}`,ask:`Ask ${n.agentId} to pick it up again?`,yes:`hand it back to ${n.agentId}`,no:"drop the request",raised_by:n.agentId,created_at:new Date(n.createdAt).toISOString(),detail:j(`${n.attentionReason??"It needs attention"}. Asked on ${n.channel}: ${n.text}`),more:`agentx requests show ${n.id}`})):[]}var _n={card:Yi,schedule:Qi,memory:es,wiki:ns,whatsapp:rs,request:is};function ss(t,e){let n=t.expires?Date.parse(t.expires):1/0,i=e.expires?Date.parse(e.expires):1/0;return n!==i?n-i:(Date.parse(t.created_at)||0)-(Date.parse(e.created_at)||0)}function Wc(t,e={}){let n=t.now??Date.now(),{snoozed:i}=C(t.root),r=[],s=[],o=0;for(let a of e.kinds??In){let c;try{c=_n[a](t)}catch(l){s.push({kind:a,error:String(l?.message??l).slice(0,200)});continue}for(let l of c){let u=i[l.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}l.snoozed_until=u}r.push(l)}}return r.sort(ss),{items:r,snoozed:o,errors:s}}function os(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),i=t.slice(e+1);return!In.includes(n)||!i?null:{kind:n,ref:i}}function as(t,e,n){switch(e){case"card":return P(t.root,n)?.status==="pending";case"wiki":return Bt(De(t),n)?.status==="pending";case"whatsapp":return se(t.root,n)?.status==="pending";default:return _n[e](t).some(i=>i.key===`${e}:${n}`)}}async function Cn(t,e,n,i={}){let r=os(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:s,ref:o}=r,a=t.now??Date.now(),c=i.by??"operator";if(n==="later"){if(!as(t,s,o))return{ok:!1,error:`nothing waiting for "${e}"`};let u=i.laterHours&&i.laterHours>0?i.laterHours:24,d=new Date(a+u*36e5);return kn(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let l=n==="yes";switch(s){case"card":{let u=bn(t.root,o,l?"yes":"no",{by:c,note:i.note,now:a,choice:i.choice,text:i.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${l?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(l?Ot:Nt)(o,{configPath:Ce(t),reload:t.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=o.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=o.slice(0,u),p=o.slice(u+1);if(!An(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new Se(t.root);return f.held(d).some(g=>g.id===p)?(f.review(d,p,l?"approved":"rejected",c),{ok:!0,message:`${e} ${l?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${p}" isn't waiting for review`}}case"wiki":{let u=De(t),d=l?Ht(u,o,{by:c,force:i.force,now:a}):qt(u,o,{by:c,reason:i.note,now:a});return d.ok?{ok:!0,message:l?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await pn(t.root,o,l?"yes":"no",{by:c,now:a,send:t.sendWhatsApp});return u.ok?{ok:!0,message:l?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}case"request":{let u=Rn(t),d=u?.get(o);return!u||!d||d.state!=="needs_attention"?{ok:!1,error:`nothing waiting for "${e}"`}:l?vn(Ce(t)).enabled?(u.requestPickup(o,a),{ok:!0,message:`${e}: ${d.agentId} will be asked to pick it up again`}):{ok:!1,error:"Requests are off, so nothing would hand it back. Turn them on (agentx requests settings --enabled on), or answer no to drop it."}:(u.close(o,"dropped",i.note?.trim()||`dropped by ${c}`,a),{ok:!0,message:`${e}: dropped`})}}}var Dn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Uc(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/requests"||t.startsWith("/requests/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/a2a/delegations"||t.startsWith("/a2a/delegations/")||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"||t==="/app-files"||t==="/calls"||t.startsWith("/calls/")||t==="/webrtc/camera"||t.startsWith("/webrtc/camera/")}function Bc(t){return t==="/reload"||t==="/api/processes/kill"||t==="/send"||t==="/send/agent"||t==="/send/contact"||t==="/mesh/announce"||t==="/voice/settings"||t==="/voice/preview"||/^\/api\/tasks\/[^/]+\/(cancel|followup)$/.test(t)||/^\/crons\/[^/]+\/enabled$/.test(t)}function zc(t){return Dn.has(t)}function Hc(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(Dn.has(t.remoteAddress))return{allowed:!0,reason:"loopback"};if(t.acceptedTokens.size===0)return{allowed:!0,reason:"no-tokens-configured"};let e=t.authorizationHeader||"",n=e.startsWith("Bearer ")?e.slice(7).trim():"";return n&&t.acceptedTokens.has(n)?{allowed:!0,reason:"token"}:{allowed:!1,reason:"missing-or-invalid-token"}}function qc(t,e=process.env){let n=new Set;e.MESH_TOKEN&&n.add(e.MESH_TOKEN);for(let i of t.mesh?.peers||[])i.token&&n.add(i.token);return n}function Kc(t,e,n=process.env){let i=s=>s.replace(/\/+$/,"");return(e===i(t.daemonUrl)?t.token:t.daemons.find(s=>i(s.url)===e)?.token)||n.MESH_TOKEN||void 0}function ce(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function cs(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function ls(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Xc(t,e=ls()){let n=ce(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=cs(n),s=[ce(t.host),ce(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&s.includes(r)?"same-origin":"foreign"}let i=ce(t["sec-fetch-site"]).toLowerCase();return i==="cross-site"||i==="same-site"?"foreign":"none"}function Jc(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as tr,mkdirSync as js,readFileSync as Vs,renameSync as Ws,writeFileSync as Fs}from"fs";import{homedir as Us}from"os";import{dirname as Bs,join as zs}from"path";import{execFile as ks,execFileSync as xs}from"child_process";import{execFileSync as us}from"child_process";import{existsSync as Tn,mkdirSync as ds,readdirSync as ps,readFileSync as Pn,renameSync as fs,writeFileSync as gs}from"fs";import{homedir as Ln}from"os";import{join as Te}from"path";var v="siri:",On="com.apple.ttsbundle.gryphon-neural_",Nn=t=>!!t&&t.startsWith(On),ms=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],hs=()=>{try{return us("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},Ee;function Pe(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&Ee!==void 0)return Ee;let{platform:n=process.platform,exists:i=Tn,prefDomain:r=hs}=t,s=n==="darwin"&&ms.every(o=>i(o))&&r();return e||(Ee=s),s}var Mn=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],jn={aaron:"male",damon:"male",daniel:"male",pierre:"male",samer:"male",arthur:"male",gordon:"male",martin:"male",nora:"female",simone:"female",marie:"female",soha:"female",martha:"female",catherine:"female",helena:"female",nicky:"female"},Le=t=>jn[t.toLowerCase()]??null;function le(t){let e=/^com\.apple\.ttsbundle\.gryphon-neural_([a-z]+)_([a-z]{2}-[A-Z]{2})_premium$/.exec(t);return e?{name:e[1],locale:e[2]}:null}var ys=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function bs(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(ys)){let o=`${i}-${r}`,a=`${On}${s}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:s[0].toUpperCase()+s.slice(1),locale:o,quality:"premium",gender:jn[s]??null,siri:!0})}return[...e.values()]}function ue(t=Mn,e={}){if(!Pe(e))return[];let n=[];for(let i of t){let r;try{r=ps(i)}catch{continue}for(let s of r)try{n.push(Pn(Te(i,s,"Info.plist"),"latin1"))}catch{}}return bs(n)}var En=`#!/bin/sh
1
+ import{a as Se}from"./chunk-GTJIKXDB.js";import{a as w}from"./chunk-CL53UVOF.js";import{q as Wt}from"./chunk-S2GAEH2F.js";import{t as jt,u as Vt}from"./chunk-3YTFEGKY.js";import{d as Ot,e as Nt}from"./chunk-AQASR6KR.js";import{c as xe,e as B,f as U,h as Ft}from"./chunk-XIYWXCNU.js";import{A as ke,b as be,v as At,x as Q,y as we}from"./chunk-AJ44V2QR.js";import{a as Pt,b as Lt,d as Mt}from"./chunk-Y4CYQV7G.js";import{a as It,b as Rt}from"./chunk-SHEUCITK.js";import{g as _t,h as Ct,i as Dt,k as Et,l as Tt}from"./chunk-PGIQW2AR.js";import{q as $t}from"./chunk-KKMDRBMJ.js";import{a as St,b as vt}from"./chunk-AM47KSTK.js";import{$ as wt,U as ye,aa as kt,da as xt,m as Z,n as gt,o as mt,p as Tr,u as yt,v as bt,w as Mr}from"./chunk-4LLSTP5G.js";import{a as ht,i as Lr}from"./chunk-PN6XHTG5.js";import{a as he,h as Pr}from"./chunk-BRK6M6LA.js";import{existsSync as Or,readdirSync as Nr,readFileSync as jr,statSync as Vr}from"fs";import{resolve as Wr}from"path";function Bt(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)??[],c=a.filter(g=>n-g.at<=r),l=a.filter(g=>n-g.at>r&&n-g.at<=r*2),u=c.filter(g=>g.status==="failed").length,d=a.filter(g=>g.status==="paused").length,p=a.length?Math.max(...a.map(g=>g.at)):null,f=a.length?l.length>0&&c.length===0?"dormant":c.length>0&&u*2>=c.length?"failing":c.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:p,recent:c.length,prior:l.length,failed:u,paused:d}}).sort((o,a)=>{let c={dormant:0,failing:1,active:2,quiet:3,never:4};return c[o.state]-c[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var ee=new Map;function ra(t,e=1e3){if(!Or(t))return[];let n=Nr(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=Wr(t,s);return{path:o,mtime:Vr(o).mtimeMs}}).sort((s,o)=>o.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of ee.keys())i.has(s)||ee.delete(s);let r=[];for(let{path:s,mtime:o}of n){let a=ee.get(s);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let c=Fr(s,o);ee.set(s,{mtime:o,summary:c}),c&&r.push(c)}return r}function Fr(t,e){try{let n=jr(t,"utf-8").split(`
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]),c=a.status??a.run?.status;if(c){s=c;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var Br={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},Ur=(t,e,n)=>{try{return $t(t,e,n)}catch{return null}},Ut=864e5;function aa(t){let e=t.now??Date.now(),n={...Br,...t.thresholds},i=t.nextFire??Ur,r=[];for(let a of t.crons){let c=t.cronRuns.get(a.id)??[],l=a.timezone||"UTC",u=c.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=c[0],p={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,k.text),trigger:{schedule:$(a.schedule,k.text),timezone:l},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?ve(a.nextRun)??ve(i(a.schedule,new Date(e),l)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:Xr(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:c.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:zt(u),sampledRuns:c.length,flags:[],attention:null};p.flags=Ht(p,u,a.schedule,l,null,e,n,i),r.push(qt(p))}let s=new Map(Bt(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 c=o.get(a.workflowId);c?c.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let c=a.nodes.find(I=>I.type.startsWith("trigger."));if(!c||c.type!=="trigger.cron"&&c.type!=="trigger.hook")continue;let l=c.config??{},u=a.state||"active",d=u==="active",p=(o.get(a.id)??[]).slice().sort((I,me)=>me.at-I.at),f=p.map(I=>({at:I.at,status:qr(I.status)})),g=f[0],h=c.type==="trigger.cron",y=typeof l.spec=="string"?l.spec:"",D=typeof l.timezone=="string"?l.timezone:"UTC",N={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,k.text),trigger:h?{schedule:$(y,k.text),timezone:D}:{event:$(typeof l.event=="string"?l.event:"",k.text),filters:Gr(l.filter,a)},agent:Kr(a),enabled:d,state:u,nextRunAt:h&&d&&y?ve(i(y,new Date(e),D)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let I=f.find(me=>me.status==="success");return I?new Date(I.at).toISOString():null})(),consecutiveFailures:zt(f),sampledRuns:p.length,flags:[],attention:null},Y=Date.parse(a.updated||a.created||"");N.flags=h?Ht(N,f,y,D,Number.isFinite(Y)?Y:null,e,n,i):zr(N,s.get(a.id)?.state==="dormant",Number.isFinite(Y)?Y:null,e,n),r.push(qt(N))}return r.sort(Hr).slice(0,k.routines)}function zt(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 Ht(t,e,n,i,r,s,o,a){let c=[],l=e.length?e[0].at:null;if(!t.enabled){let p=Gt(l,r,s,o);return p&&c.push(p),c}if(t.consecutiveFailures>=o.failStreak&&c.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),l===null)return c.push({reason:"never-ran",detail:"No persisted attempt"}),c;let u=new Date(l),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&&c.push({reason:"overdue",detail:`No attempt since ${new Date(l).toISOString()}; ${o.missedFires} scheduled fires missed`}),c}function zr(t,e,n,i,r){let s=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=Gt(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 Gt(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*Ut?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/Ut)} days`:"Disabled and never ran"}}function qt(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 Kt={critical:0,warning:1,info:2};function Hr(t,e){let n=t.attention?Kt[t.attention]:3,i=e.attention?Kt[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function qr(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 Kr(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 Gr(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 ve(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 Xr(t,e){return t===void 0?void 0:$(t,e)}import{existsSync as re,readdirSync as fi,readFileSync as gi}from"fs";import{resolve as E}from"path";import{randomBytes as Yt}from"crypto";import{existsSync as Yr,mkdirSync as Zr,readdirSync as Qr,readFileSync as ei,renameSync as Zt,unlinkSync as ti,writeFileSync as ni}from"fs";import{resolve as Qt}from"path";function Xt(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var Jr=t=>t.trim().split(`
3
+ `).pop()?.slice(0,300)||"no output";async function Jt(t,e,n,i=Se){let r=await i(t.bin,[...Xt(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${Jr(r.stderr||r.stdout)}`}}async function ua(t,e,n,i,r=Se){return(await r(t.bin,[...Xt(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var ri=2e3,ii=t=>Jt(t.wacli,t.to,t.text);function $e(t){return Qt(t,".agentx","whatsapp-triage","drafts")}var si=t=>/^[a-z0-9-]{8,64}$/.test(t),te=(t,e)=>Qt($e(t),`${e}.json`);function en(t,e){Zr($e(t),{recursive:!0});let n=te(t,e.id),i=`${n}.${process.pid}.tmp`;ni(i,JSON.stringify(e,null,2)+`
4
+ `,{mode:384}),Zt(i,n)}function ha(t,e,n=Date.now()){let i=e.text.trim().slice(0,ri);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${Yt(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return en(t,r),r}function ne(t,e){if(!si(e))return null;try{return JSON.parse(ei(te(t,e),"utf-8"))}catch{return null}}function tn(t,e){let n=$e(t);return Yr(n)?Qr(n).filter(i=>i.endsWith(".json")).map(i=>ne(t,i.slice(0,-5))).filter(i=>!!i&&(!e||i.status===e)).sort((i,r)=>i.created_at.localeCompare(r.created_at)):[]}async function nn(t,e,n,i={}){let r=ne(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let s=`${te(t,e)}.${process.pid}.${Yt(3).toString("hex")}.claim`;try{Zt(te(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(i.send??ii)(r).catch(c=>({ok:!1,error:String(c?.message??c)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}en(t,o);try{ti(s)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{mkdirSync as oi,readFileSync as ai,renameSync as ci,writeFileSync as li}from"fs";import{resolve as ui}from"path";function rn(t){return ui(xe(t),"_state.json")}function R(t){try{let e=JSON.parse(ai(rn(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 z(t,e){oi(xe(t),{recursive:!0});let n=rn(t),i=`${n}.${process.pid}.tmp`;li(i,JSON.stringify(e,null,2)+`
5
+ `),ci(i,n)}function sn(t,e,n,i=Date.now()){let r=R(t),s={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>i&&(s[o]=a);s[e]=n.toISOString(),z(t,{...r,snoozed:s})}function xa(t,e){z(t,{...R(t),lastDigest:e})}function on(t,e,n,i=Date.now()){let r=R(t),s=new Set(n),o={};for(let[c,l]of Object.entries(r.popped??{}))s.has(c)&&(o[c]=l);o[e]=new Date(i).toISOString();let a=(r.wanted??[]).filter(c=>c!==e&&s.has(c));z(t,{...r,popped:o,wanted:a})}function an(t,e){let n=R(t);z(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function Sa(t,e=Date.now()){z(t,{...R(t),popped:{},passAt:new Date(e).toISOString()})}Lr();Mr();import{existsSync as di,readFileSync as pi}from"fs";xt();Pr();function cn(t){let e=St(t),n={};if(di(e))try{n=wt(JSON.parse(pi(e,"utf-8")))}catch{n={}}let i=ye.safeParse(n?.requests);return i.success?i.data:ye.parse(void 0)}async function _a(t,e={}){let n=(t.channels??[]).filter(i=>!he.has(i.toLowerCase().split("@")[0]));return n.length?{success:!1,error:`unknown channel ${n.map(i=>`"${i}"`).join(", ")}: use ${[...he].join(", ")}`}:vt(i=>{let r=i.requests??={};for(let s of["enabled","channels","from","staleAfterHours","retentionDays"])t[s]!==void 0&&(r[s]=t[s])},{configPath:e.configPath,reload:e.reload})}var un=["card","schedule","memory","wiki","whatsapp","request"],mi=280;function L(t,e=mi){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Ae(t){if(t.configPath)return E(t.configPath);let e=[E(t.root,"agentx.json"),E(t.root,".agentx","config.json")];return e.find(n=>re(n))??e[0]}function Ie(t){return t.wikiDir?E(t.wikiDir):E(t.root,".agentx","wiki")}function hi(t){return U(t.root,"pending").map(yi)}function yi(t){return{key:`card:${t.id}`,kind:"card",title:t.title,ask:t.ask,yes:`tell ${t.raised_by} yes`,no:`tell ${t.raised_by} no`,recommend:t.recommend,if_silent:t.if_silent,expires:t.expires,...t.source?{source:t.source}:{},raised_by:t.raised_by,created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.context||t.draft?{detail:L([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function bi(t){let e=Ae(t);if(!re(e))return[];let n;try{n=JSON.parse(gi(e,"utf-8"))}catch{return[]}let i=new Date(t.now??Date.now()),r=[];for(let[s,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let c=o.timezone||"UTC",l=o.schedule?_t(o.schedule):"",u=o.schedule?`${l.charAt(0).toLowerCase()}${l.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),p=a.action==="create";r.push({key:`schedule:${s}`,kind:"schedule",title:p?`New schedule "${s}" for ${o.agent??"an agent"}`:`Delete schedule "${s}"`,ask:p?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${s}" (${u})?`,yes:p?"enable it":"remove it",no:p?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:L(`${d}${p&&o.schedule?` \xB7 first run ${Dt(Ct(o.schedule,c,i),c)}`:""}`),more:"agentx schedule list"})}return r}function dn(t){let e=E(t,".agentx","memory");return re(e)?fi(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function wi(t){let e=dn(t.root);if(e.length===0)return[];let n=new be(t.root),i=[];for(let r of e)for(let s of n.held(r))i.push({key:`memory:${r}/${s.id}`,kind:"memory",title:`Fact ${r} learned from ${s.source.channel}`,ask:`Let ${r} use this fact in its prompts?`,yes:"use it",no:"keep it out for good",raised_by:r,created_at:s.createdAt,detail:L(s.content),more:`agentx memory facts held --agent ${r}`});return i}function ki(t){let e=t.sources.filter(n=>n.failure);return e.length?e.map(n=>`Recurring failure: ${n.agentId}'s ${n.failure.tool} fails with "${n.failure.errorClass}" in ${n.occurrences??1} sessions (${n.failure.runs} runs).`).join(" "):`${t.sources.length} source(s)${t.occurrences>1?`, seen in ${t.occurrences} sessions`:""}.`}function xi(t){return Nt(Ie(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:L(`${ki(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function Si(t){return tn(t.root,"pending").map(e=>({key:`whatsapp:${e.id}`,kind:"whatsapp",title:`WhatsApp reply to ${e.chat_name||e.to}`,ask:`Send this to ${e.chat_name||e.to}? "${e.text}"`,yes:"send it on WhatsApp",no:"drop the draft",raised_by:e.agent,created_at:e.created_at,detail:L(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}function pn(t){if(t.requests)return t.requests;if(E(t.root)!==process.cwd()||!re(E(t.root,".agentx","db.sqlite")))return null;let e=ht({quiet:!0});if(!e)return null;let n=ln.get(e);return!n&&!yt(e)?null:(n||ln.set(e,n=new bt(e)),n)}var ln=new WeakMap;function vi(t){let e=pn(t);return e?e.listByState("needs_attention").map(n=>({key:`request:${n.id}`,kind:"request",title:`Request not finished: ${L(n.text,80)}`,ask:`Ask ${n.agentId} to pick it up again?`,yes:`hand it back to ${n.agentId}`,no:"drop the request",raised_by:n.agentId,created_at:new Date(n.createdAt).toISOString(),detail:L(`${n.attentionReason??"It needs attention"}. Asked on ${n.channel}: ${n.text}`),more:`agentx requests show ${n.id}`})):[]}var fn={card:hi,schedule:bi,memory:wi,wiki:xi,whatsapp:Si,request:vi};function $i(t,e){let n=t.expires?Date.parse(t.expires):1/0,i=e.expires?Date.parse(e.expires):1/0;return n!==i?n-i:(Date.parse(t.created_at)||0)-(Date.parse(e.created_at)||0)}function Ba(t,e={}){let n=t.now??Date.now(),{snoozed:i}=R(t.root),r=[],s=[],o=0;for(let a of e.kinds??un){let c;try{c=fn[a](t)}catch(l){s.push({kind:a,error:String(l?.message??l).slice(0,200)});continue}for(let l of c){let u=i[l.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}l.snoozed_until=u}r.push(l)}}return r.sort($i),{items:r,snoozed:o,errors:s}}function Ai(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),i=t.slice(e+1);return!un.includes(n)||!i?null:{kind:n,ref:i}}function Ii(t,e,n){switch(e){case"card":return B(t.root,n)?.status==="pending";case"wiki":return Ot(Ie(t),n)?.status==="pending";case"whatsapp":return ne(t.root,n)?.status==="pending";default:return fn[e](t).some(i=>i.key===`${e}:${n}`)}}async function gn(t,e,n,i={}){let r=Ai(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:s,ref:o}=r,a=t.now??Date.now(),c=i.by??"operator";if(n==="later"){if(!Ii(t,s,o))return{ok:!1,error:`nothing waiting for "${e}"`};let u=i.laterHours&&i.laterHours>0?i.laterHours:24,d=new Date(a+u*36e5);return sn(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let l=n==="yes";switch(s){case"card":{let u=Ft(t.root,o,l?"yes":"no",{by:c,note:i.note,now:a,choice:i.choice,text:i.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${l?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(l?Et:Tt)(o,{configPath:Ae(t),reload:t.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=o.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=o.slice(0,u),p=o.slice(u+1);if(!dn(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new be(t.root);return f.held(d).some(g=>g.id===p)?(f.review(d,p,l?"approved":"rejected",c),{ok:!0,message:`${e} ${l?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${p}" isn't waiting for review`}}case"wiki":{let u=Ie(t),d=l?jt(u,o,{by:c,force:i.force,now:a}):Vt(u,o,{by:c,reason:i.note,now:a});return d.ok?{ok:!0,message:l?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await nn(t.root,o,l?"yes":"no",{by:c,now:a,send:t.sendWhatsApp});return u.ok?{ok:!0,message:l?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}case"request":{let u=pn(t),d=u?.get(o);return!u||!d||d.state!=="needs_attention"?{ok:!1,error:`nothing waiting for "${e}"`}:l?cn(Ae(t)).enabled?(u.requestPickup(o,a),{ok:!0,message:`${e}: ${d.agentId} will be asked to pick it up again`}):{ok:!1,error:"Requests are off, so nothing would hand it back. Turn them on (agentx requests settings --enabled on), or answer no to drop it."}:(u.close(o,"dropped",i.note?.trim()||`dropped by ${c}`,a),{ok:!0,message:`${e}: dropped`})}}}var mn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function za(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/requests"||t.startsWith("/requests/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/a2a/delegations"||t.startsWith("/a2a/delegations/")||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"||t==="/app-files"||t==="/calls"||t.startsWith("/calls/")||t==="/webrtc/camera"||t.startsWith("/webrtc/camera/")||t==="/mesh/guests"||t.startsWith("/mesh/guests/")}function Ha(t){return t==="/reload"||t==="/api/processes/kill"||t==="/send"||t==="/send/agent"||t==="/send/contact"||t==="/mesh/announce"||t==="/voice/settings"||t==="/voice/preview"||/^\/api\/tasks\/[^/]+\/(cancel|followup)$/.test(t)||/^\/mesh\/guests\/[^/]+\/(pause|resume|end|update)$/.test(t)||/^\/crons\/[^/]+\/enabled$/.test(t)}function qa(t){return mn.has(t)}function Ka(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(mn.has(t.remoteAddress))return{allowed:!0,reason:"loopback"};if(t.acceptedTokens.size===0)return{allowed:!0,reason:"no-tokens-configured"};let e=t.authorizationHeader||"",n=e.startsWith("Bearer ")?e.slice(7).trim():"";return n&&t.acceptedTokens.has(n)?{allowed:!0,reason:"token"}:{allowed:!1,reason:"missing-or-invalid-token"}}function Ga(t,e=process.env){let n=new Set;e.MESH_TOKEN&&n.add(e.MESH_TOKEN);for(let i of t.mesh?.peers||[])i.token&&n.add(i.token);return n}function Xa(t,e,n=process.env){let i=s=>s.replace(/\/+$/,"");return(e===i(t.daemonUrl)?t.token:t.daemons.find(s=>i(s.url)===e)?.token)||n.MESH_TOKEN||void 0}function ie(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function Ri(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function _i(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Ya(t,e=_i()){let n=ie(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=Ri(n),s=[ie(t.host),ie(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&s.includes(r)?"same-origin":"foreign"}let i=ie(t["sec-fetch-site"]).toLowerCase();return i==="cross-site"||i==="same-site"?"foreign":"none"}function Za(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as Wn,mkdirSync as rs,readFileSync as is,renameSync as ss,writeFileSync as os}from"fs";import{homedir as as}from"os";import{dirname as cs,join as ls}from"path";import{execFile as Vi,execFileSync as Wi}from"child_process";import{execFileSync as Ci}from"child_process";import{existsSync as yn,mkdirSync as Di,readdirSync as Ei,readFileSync as bn,renameSync as Ti,writeFileSync as Pi}from"fs";import{homedir as wn}from"os";import{join as _e}from"path";var S="siri:",kn="com.apple.ttsbundle.gryphon-neural_",xn=t=>!!t&&t.startsWith(kn),Li=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],Mi=()=>{try{return Ci("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},Re;function Ce(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&Re!==void 0)return Re;let{platform:n=process.platform,exists:i=yn,prefDomain:r=Mi}=t,s=n==="darwin"&&Li.every(o=>i(o))&&r();return e||(Re=s),s}var Sn=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],vn={aaron:"male",damon:"male",daniel:"male",pierre:"male",samer:"male",arthur:"male",gordon:"male",martin:"male",nora:"female",simone:"female",marie:"female",soha:"female",martha:"female",catherine:"female",helena:"female",nicky:"female"},De=t=>vn[t.toLowerCase()]??null;function se(t){let e=/^com\.apple\.ttsbundle\.gryphon-neural_([a-z]+)_([a-z]{2}-[A-Z]{2})_premium$/.exec(t);return e?{name:e[1],locale:e[2]}:null}var Oi=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function Ni(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(Oi)){let o=`${i}-${r}`,a=`${kn}${s}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:s[0].toUpperCase()+s.slice(1),locale:o,quality:"premium",gender:vn[s]??null,siri:!0})}return[...e.values()]}function oe(t=Sn,e={}){if(!Ce(e))return[];let n=[];for(let i of t){let r;try{r=Ei(i)}catch{continue}for(let s of r)try{n.push(bn(_e(i,s,"Info.plist"),"latin1"))}catch{}}return Ni(n)}var hn=`#!/bin/sh
9
6
  # Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
10
7
  # siri-say.sh [voice] < text speak one line. A Siri voice id switches
11
8
  # the OS default for it; any other id is
@@ -17,7 +14,7 @@ D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
17
14
  dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
18
15
  stops="$dir/stop"
19
16
  read_s=\${AGENTX_SAY_READ_S:-5} stale_s=\${AGENTX_SAY_STALE_S:-30} max_s=\${AGENTX_SAY_MAX_S:-300}
20
- assets=\${AGENTX_SIRI_ASSET_DIRS:-"${Mn.join(" ")}"}
17
+ assets=\${AGENTX_SIRI_ASSET_DIRS:-"${Sn.join(" ")}"}
21
18
  if [ "$1" = --stop ]; then
22
19
  mkdir -p "$dir" || exit 1
23
20
  # Queued lines see this change and drop. The owner's trap stops say,
@@ -110,30 +107,30 @@ wait "$say_pid"
110
107
  status=$?
111
108
  say_pid=
112
109
  finish $status
113
- `,ws=(t=Ln())=>Te(t,".agentx","voice","siri-say.sh");function Vn(t=Ln()){let e=ws(t);return Tn(e)&&Pn(e,"utf8")===En||(ds(Te(t,".agentx","voice"),{recursive:!0}),gs(`${e}.tmp`,En,{mode:493}),fs(`${e}.tmp`,e)),e}var Wn=`ObjC.import("AVFoundation")
110
+ `,ji=(t=wn())=>_e(t,".agentx","voice","siri-say.sh");function $n(t=wn()){let e=ji(t);return yn(e)&&bn(e,"utf8")===hn||(Di(_e(t,".agentx","voice"),{recursive:!0}),Pi(`${e}.tmp`,hn,{mode:493}),Ti(`${e}.tmp`,e)),e}var An=`ObjC.import("AVFoundation")
114
111
  const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
115
112
  for (let i = 0; i < vs.count; i++) {
116
113
  const v = vs.objectAtIndex(i)
117
114
  out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
118
115
  }
119
- out.join("\\n")`,Ss=new Set(["Fred","Kathy","Ralph","Junior"]),vs={Flo:"female",Sandy:"female",Shelley:"female",Grandma:"female",Kathy:"female",Eddy:"male",Reed:"male",Rocko:"male",Grandpa:"male",Fred:"male",Ralph:"male",Junior:"male"};function Fn(t){let e=[];for(let n of t.split(`
120
- `)){let[i,r,s,o,a]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!Ss.has(r)||e.push({id:i,name:r,locale:s,quality:o==="3"?"premium":o==="2"?"enhanced":"standard",gender:a==="1"?"male":a==="2"?"female":vs[r]??null})}return e}var $s=10*60*1e3,sl=60*1e3,B=null,Oe=!1;function Ne(t=Date.now(),e=$s){if(process.platform!=="darwin")return[];if(B)t-B.at>e&&!Oe&&(Oe=!0,ks("osascript",["-l","JavaScript","-e",Wn],{timeout:1e4},(n,i)=>{Oe=!1,n||(B={at:Date.now(),voices:[...Fn(String(i)),...ue()]})}));else try{B={at:t,voices:[...Fn(xs("osascript",["-l","JavaScript","-e",Wn],{encoding:"utf8",timeout:1e4})),...ue()]}}catch(n){Me(`[voice] could not list system voices: ${String(n?.message??n).split(`
121
- `)[0]}`),B={at:t,voices:ue()}}return B.voices}var Me=t=>process.stderr.write(t+`
122
- `),de=new Set;function ol(t){Me=t}function V(t,e){de.has(t)||(de.add(t),Me(e))}function zn(t){for(let e of de)t(e)&&de.delete(e)}var Hn=()=>{};function al(t){Hn=t}function qn(t){try{Hn(t)}catch(e){V("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var Is={premium:3,enhanced:2,standard:1},As=new Set(["Grandma","Grandpa"]);function Un(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!As.has(t.name)?1:0;return Is[t.quality]*10+e}var z=t=>t.toLowerCase().split(/[-_]/)[0],Bn=t=>t.id.startsWith("com.apple.voice.");function je(t,e,n,i=new Set){let r=G(t.filter(a=>!a.siri&&z(a.locale)===z(e)),e);if(r.some(Bn)&&(r=r.filter(Bn)),n==="female"||n==="male"){let a=r.filter(c=>c.gender===n);a.length&&(r=a)}if(!r.length)return null;let s=r.filter(a=>a.quality===r[0].quality),o=new Set([...i].map(a=>a.toLowerCase()));return s.find(a=>!o.has(a.name.toLowerCase()))??s[0]}function G(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=z(e),r=t.filter(s=>z(s.locale)===i);return(r.length?r:t).slice().sort((s,o)=>Un(o)-Un(s)||+(o.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(o.name)||s.locale.localeCompare(o.locale))}function X(t,e,n="en"){let i=t.trim();if(!i)return null;let r=e.find(l=>l.id===i);if(r)return r;if(i.toLowerCase().startsWith(v)){let l=i.slice(v.length).trim().toLowerCase(),u=G(e.filter(p=>p.siri&&p.name.toLowerCase()===l),n)[0];if(u||!l)return u??null;let d=X(l,e.filter(p=>z(p.locale)===z(n)),n);return d&&V(`siri:${l}`,`[voice] Siri voice "${l}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(l=>!l.siri);let s=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(i),o=(s?s[1]:i.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=G(e.filter(l=>l.name.toLowerCase()===o),n);return(s?a.find(l=>l.quality===s[2].toLowerCase()):void 0)??a[0]??null}function Kn(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(o=>o.toLowerCase())),s="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",c=a?o.gender:s,l=e.filter(d=>!r.has(d.name.toLowerCase())),u=l.find(d=>d.gender===c)??(a?e.find(d=>d.gender===c):void 0)??l[0]??e[i.size%e.length];i.set(o.id,u),r.add(u.name.toLowerCase()),a||(s=s==="female"?"male":"female")}return i}bt();var Ve="system",Rs=t=>t.trim().toLowerCase()===Ve,_s="21m00Tcm4TlvDq8ikWAM";function We(t,e,n={},i=Ne()){let r=e[t],s=r?.name||t,o=r?.voice,a=Ue(e,n,i).get(t)??null,c=Ts(t,o?.system,o?.gender,n,i);return{agentId:t,name:s,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?fe(a):null,systemByLanguage:c,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Ls(s,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var fe=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function Cs(t,e,n,i){if(!e||!n.length)return null;let r=X(e,n,i);return r||(V(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),qn(e)),r}function Yn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(v))return{locale:e,gender:Le(n.slice(v.length).trim())};let i=le(n);return i?{locale:i.locale,gender:Le(i.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var Zn=t=>t.toLowerCase().split(/[-_]/)[0],Gn=(t,e)=>typeof t=="string"?t:t?.[Zn(e)];function pe(t,e,n,i){if(e!==void 0)return Rs(e)?null:Cs(t,e,n,i)??void 0}var Fe=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Ds(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,o=[],a=pe("voice.system",Gn(e.system,r),n,r),c=()=>new Set([...i,...[...s.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=Gn(u.system,r),p=pe(u.id,d,n,r),f=p!==void 0?p:d!==void 0&&n.length?Es(u,d,r,a,n,c()):a!==void 0&&Fe(a,u.gender)?a:void 0;f!==void 0?s.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let l=c();for(let[u,d]of Kn(o,G(n.filter(p=>!p.siri),r),l))s.set(u,d);return s}function Es(t,e,n,i,r,s){for(let a of t.fallbacks??[]){let c=pe(`${t.id}.fallbacks`,a,r,n);if(c!==void 0)return c}if(i!==void 0&&Fe(i,t.gender))return i;let o=Yn(e,n);return je(r,o.locale,t.gender??o.gender,s)??void 0}function Ts(t,e,n,i,r){if(typeof e=="string")return{};let s={},o=(a,c,l)=>{if(!(!c||typeof c=="string"))for(let[u,d]of Object.entries(c)){let p=pe(`${a}.${u}`,d,r,u);p===void 0&&r.length&&(p=je(r,u,n??Yn(d,u).gender)??void 0),p!==void 0&&l(p)&&(s[Zn(u)]=p)}};return o("voice.system",i.system,a=>Fe(a,n)),o(t,e,()=>!0),s}function pl(t,e){let n=e?te(e):null;if(!n||!(n in t.systemByLanguage))return t;let i=t.systemByLanguage[n];return{...t,systemVoice:i?.id??null,systemVoiceName:i?fe(i):null}}function Ue(t,e={},n=Ne()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return Ds(i,e,n)}function Be(t,e){let n={provider:t.provider,elevenlabs:Ps(e,t.elevenlabsVoiceId),system:t.systemVoice,fallback:t.fallback},i=Object.entries(t.systemByLanguage??{});return i.length&&(n.languages=Object.fromEntries(i.map(([r,s])=>[r,s?.id??null]))),t.rate&&t.rate!==1&&(n.rate=t.rate),t.priority&&t.priority!=="normal"&&(n.priority=t.priority),n}function Ps(t,e){return t||e||process.env.AGENTX_VOICE_ID||_s}function Ls(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",i=/^You are (.+?)\.?$/i.exec(n.trim());if(!i)return`Hello, this is ${t}.`;let r=i[1].replace(/\s*\([^)]*\)/g,"").trim(),[s,...o]=r.split(/,\s*/),a=o.join(", ");return a&&s.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${a}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var Os=8*60*60*1e3,Ns=500,Xn=class{constructor(e=Os){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Jn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Jn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>Ns&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Jn=(t,e)=>`${t}\0${e}`;function Qn(t,e){let n=t.style?` Your speaking manner: ${t.style}.`:"";return e?`[VOICE INTRO] This is your first spoken exchange with this person in a while. Open with one short sentence introducing yourself in your own manner, along the lines of "${t.intro}", then answer.${n}`:"[VOICE CASUAL] You have already introduced yourself in this voice conversation. Do not introduce yourself or greet again; talk casually, like a colleague in the same office."+n}function fl(t,e,n,i={}){let r=e[t],s=We(t,e,i),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:Be(s),persona:o||`You are ${s.name}.`,introLine:Qn(s,n)}}var Ms="[VOICE MODE] This question arrived by voice and your reply will be spoken aloud by a TTS engine. Answer in two or three short sentences. Plain language, no markdown, no code blocks, no bullet points, no URLs. Speak conversationally.";function gl(t){let e=t;if(e?.channel!=="voice"||!e.voice||typeof e.voice!="object")return;let n=s=>typeof s=="string"?s.replace(/\s+/g," ").slice(0,200):"",i=n(e.voice.intro),r={agentId:"",name:"",provider:"system",elevenlabsVoiceId:null,systemVoice:null,systemVoiceName:null,systemByLanguage:{},fallback:!0,gender:null,style:n(e.voice.style)||null,intro:i||"Hello."};return`${Ms}
123
- ${Qn(r,e.voice.introduce===!0&&!!i)}`}var Hs="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",nr=(t=Us())=>zs(t,".agentx","voice","health.json");function qs(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===Ve)return!0;if(i.toLowerCase().startsWith(v)){let r=i.slice(v.length).trim().toLowerCase();return e.some(s=>s.siri&&s.name.toLowerCase()===r)}return X(i,e,n)!==null}function Ks(t){let e=t.voice?.locale??"en",n=[],i=(r,s)=>{if(typeof s=="string")n.push({owner:r,name:s,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(s??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};i("voice.system",t.voice?.system);for(let[r,s]of Object.entries(t.agents))(s.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||i(r,s.voice?.system);return n}function Gs(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:o,perLanguage:a}of Ks(t)){if(qs(s,e,o))continue;i??=Ue(t.agents,t.voice,e);let c=n.get(s)??{voice:s,agents:[],speaksWith:{}};c.agents.includes(r)||c.agents.push(r);let l=i.get(r);r!=="voice.system"&&!a&&(c.speaksWith[r]=l?fe(l):"the OS default voice"),n.set(s,c)}return[...n.values()]}function ze(t){let e=le(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(v)){let n=t.slice(v.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function Xs(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${ze(n.voice)}: ${i}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
116
+ out.join("\\n")`,Fi=new Set(["Fred","Kathy","Ralph","Junior"]),Bi={Flo:"female",Sandy:"female",Shelley:"female",Grandma:"female",Kathy:"female",Eddy:"male",Reed:"male",Rocko:"male",Grandpa:"male",Fred:"male",Ralph:"male",Junior:"male"};function In(t){let e=[];for(let n of t.split(`
117
+ `)){let[i,r,s,o,a]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!Fi.has(r)||e.push({id:i,name:r,locale:s,quality:o==="3"?"premium":o==="2"?"enhanced":"standard",gender:a==="1"?"male":a==="2"?"female":Bi[r]??null})}return e}var Ui=10*60*1e3,ac=60*1e3,j=null,Ee=!1;function Te(t=Date.now(),e=Ui){if(process.platform!=="darwin")return[];if(j)t-j.at>e&&!Ee&&(Ee=!0,Vi("osascript",["-l","JavaScript","-e",An],{timeout:1e4},(n,i)=>{Ee=!1,n||(j={at:Date.now(),voices:[...In(String(i)),...oe()]})}));else try{j={at:t,voices:[...In(Wi("osascript",["-l","JavaScript","-e",An],{encoding:"utf8",timeout:1e4})),...oe()]}}catch(n){Pe(`[voice] could not list system voices: ${String(n?.message??n).split(`
118
+ `)[0]}`),j={at:t,voices:oe()}}return j.voices}var Pe=t=>process.stderr.write(t+`
119
+ `),ae=new Set;function cc(t){Pe=t}function M(t,e){ae.has(t)||(ae.add(t),Pe(e))}function Cn(t){for(let e of ae)t(e)&&ae.delete(e)}var Dn=()=>{};function lc(t){Dn=t}function En(t){try{Dn(t)}catch(e){M("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var zi={premium:3,enhanced:2,standard:1},Hi=new Set(["Grandma","Grandpa"]);function Rn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!Hi.has(t.name)?1:0;return zi[t.quality]*10+e}var V=t=>t.toLowerCase().split(/[-_]/)[0],_n=t=>t.id.startsWith("com.apple.voice.");function Le(t,e,n,i=new Set){let r=H(t.filter(a=>!a.siri&&V(a.locale)===V(e)),e);if(r.some(_n)&&(r=r.filter(_n)),n==="female"||n==="male"){let a=r.filter(c=>c.gender===n);a.length&&(r=a)}if(!r.length)return null;let s=r.filter(a=>a.quality===r[0].quality),o=new Set([...i].map(a=>a.toLowerCase()));return s.find(a=>!o.has(a.name.toLowerCase()))??s[0]}function H(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=V(e),r=t.filter(s=>V(s.locale)===i);return(r.length?r:t).slice().sort((s,o)=>Rn(o)-Rn(s)||+(o.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(o.name)||s.locale.localeCompare(o.locale))}function q(t,e,n="en"){let i=t.trim();if(!i)return null;let r=e.find(l=>l.id===i);if(r)return r;if(i.toLowerCase().startsWith(S)){let l=i.slice(S.length).trim().toLowerCase(),u=H(e.filter(p=>p.siri&&p.name.toLowerCase()===l),n)[0];if(u||!l)return u??null;let d=q(l,e.filter(p=>V(p.locale)===V(n)),n);return d&&M(`siri:${l}`,`[voice] Siri voice "${l}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(l=>!l.siri);let s=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(i),o=(s?s[1]:i.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=H(e.filter(l=>l.name.toLowerCase()===o),n);return(s?a.find(l=>l.quality===s[2].toLowerCase()):void 0)??a[0]??null}function Tn(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(o=>o.toLowerCase())),s="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",c=a?o.gender:s,l=e.filter(d=>!r.has(d.name.toLowerCase())),u=l.find(d=>d.gender===c)??(a?e.find(d=>d.gender===c):void 0)??l[0]??e[i.size%e.length];i.set(o.id,u),r.add(u.name.toLowerCase()),a||(s=s==="female"?"male":"female")}return i}gt();var Me="system",qi=t=>t.trim().toLowerCase()===Me,Ki="21m00Tcm4TlvDq8ikWAM";function Oe(t,e,n={},i=Te()){let r=e[t],s=r?.name||t,o=r?.voice,a=je(e,n,i).get(t)??null,c=Yi(t,o?.system,o?.gender,n,i);return{agentId:t,name:s,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?le(a):null,systemByLanguage:c,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Qi(s,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var le=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function Gi(t,e,n,i){if(!e||!n.length)return null;let r=q(e,n,i);return r||(M(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),En(e)),r}function On(t,e){let n=t.trim();if(n.toLowerCase().startsWith(S))return{locale:e,gender:De(n.slice(S.length).trim())};let i=se(n);return i?{locale:i.locale,gender:De(i.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var Nn=t=>t.toLowerCase().split(/[-_]/)[0],Pn=(t,e)=>typeof t=="string"?t:t?.[Nn(e)];function ce(t,e,n,i){if(e!==void 0)return qi(e)?null:Gi(t,e,n,i)??void 0}var Ne=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Xi(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,o=[],a=ce("voice.system",Pn(e.system,r),n,r),c=()=>new Set([...i,...[...s.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=Pn(u.system,r),p=ce(u.id,d,n,r),f=p!==void 0?p:d!==void 0&&n.length?Ji(u,d,r,a,n,c()):a!==void 0&&Ne(a,u.gender)?a:void 0;f!==void 0?s.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let l=c();for(let[u,d]of Tn(o,H(n.filter(p=>!p.siri),r),l))s.set(u,d);return s}function Ji(t,e,n,i,r,s){for(let a of t.fallbacks??[]){let c=ce(`${t.id}.fallbacks`,a,r,n);if(c!==void 0)return c}if(i!==void 0&&Ne(i,t.gender))return i;let o=On(e,n);return Le(r,o.locale,t.gender??o.gender,s)??void 0}function Yi(t,e,n,i,r){if(typeof e=="string")return{};let s={},o=(a,c,l)=>{if(!(!c||typeof c=="string"))for(let[u,d]of Object.entries(c)){let p=ce(`${a}.${u}`,d,r,u);p===void 0&&r.length&&(p=Le(r,u,n??On(d,u).gender)??void 0),p!==void 0&&l(p)&&(s[Nn(u)]=p)}};return o("voice.system",i.system,a=>Ne(a,n)),o(t,e,()=>!0),s}function gc(t,e){let n=e?Z(e):null;if(!n||!(n in t.systemByLanguage))return t;let i=t.systemByLanguage[n];return{...t,systemVoice:i?.id??null,systemVoiceName:i?le(i):null}}function je(t,e={},n=Te()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return Xi(i,e,n)}function Ve(t,e){let n={provider:t.provider,elevenlabs:Zi(e,t.elevenlabsVoiceId),system:t.systemVoice,fallback:t.fallback},i=Object.entries(t.systemByLanguage??{});return i.length&&(n.languages=Object.fromEntries(i.map(([r,s])=>[r,s?.id??null]))),t.rate&&t.rate!==1&&(n.rate=t.rate),t.priority&&t.priority!=="normal"&&(n.priority=t.priority),n}function Zi(t,e){return t||e||process.env.AGENTX_VOICE_ID||Ki}function Qi(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",i=/^You are (.+?)\.?$/i.exec(n.trim());if(!i)return`Hello, this is ${t}.`;let r=i[1].replace(/\s*\([^)]*\)/g,"").trim(),[s,...o]=r.split(/,\s*/),a=o.join(", ");return a&&s.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${a}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var es=8*60*60*1e3,ts=500,Ln=class{constructor(e=es){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Mn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Mn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>ts&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Mn=(t,e)=>`${t}\0${e}`;function jn(t,e){let n=t.style?` Your speaking manner: ${t.style}.`:"";return e?`[VOICE INTRO] This is your first spoken exchange with this person in a while. Open with one short sentence introducing yourself in your own manner, along the lines of "${t.intro}", then answer.${n}`:"[VOICE CASUAL] You have already introduced yourself in this voice conversation. Do not introduce yourself or greet again; talk casually, like a colleague in the same office."+n}function mc(t,e,n,i={}){let r=e[t],s=Oe(t,e,i),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:Ve(s),persona:o||`You are ${s.name}.`,introLine:jn(s,n)}}var ns="[VOICE MODE] This question arrived by voice and your reply will be spoken aloud by a TTS engine. Answer in two or three short sentences. Plain language, no markdown, no code blocks, no bullet points, no URLs. Speak conversationally.";function hc(t){let e=t;if(e?.channel!=="voice"||!e.voice||typeof e.voice!="object")return;let n=s=>typeof s=="string"?s.replace(/\s+/g," ").slice(0,200):"",i=n(e.voice.intro),r={agentId:"",name:"",provider:"system",elevenlabsVoiceId:null,systemVoice:null,systemVoiceName:null,systemByLanguage:{},fallback:!0,gender:null,style:n(e.voice.style)||null,intro:i||"Hello."};return`${ns}
120
+ ${jn(r,e.voice.introduce===!0&&!!i)}`}var us="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",Fn=(t=as())=>ls(t,".agentx","voice","health.json");function ds(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===Me)return!0;if(i.toLowerCase().startsWith(S)){let r=i.slice(S.length).trim().toLowerCase();return e.some(s=>s.siri&&s.name.toLowerCase()===r)}return q(i,e,n)!==null}function ps(t){let e=t.voice?.locale??"en",n=[],i=(r,s)=>{if(typeof s=="string")n.push({owner:r,name:s,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(s??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};i("voice.system",t.voice?.system);for(let[r,s]of Object.entries(t.agents))(s.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||i(r,s.voice?.system);return n}function fs(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:o,perLanguage:a}of ps(t)){if(ds(s,e,o))continue;i??=je(t.agents,t.voice,e);let c=n.get(s)??{voice:s,agents:[],speaksWith:{}};c.agents.includes(r)||c.agents.push(r);let l=i.get(r);r!=="voice.system"&&!a&&(c.speaksWith[r]=l?le(l):"the OS default voice"),n.set(s,c)}return[...n.values()]}function We(t){let e=se(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(S)){let n=t.slice(S.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function gs(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${We(n.voice)}: ${i}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
124
121
  `)}
125
- Reinstall in ${Hs}. Agents switch back on their own once it is installed.`}}function Js(t=nr()){if(!tr(t))return null;try{let e=JSON.parse(Vs(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function Ys(t,e){js(Bs(t),{recursive:!0}),Fs(`${t}.tmp`,JSON.stringify(e,null,2)+`
126
- `),Ws(`${t}.tmp`,t)}var er=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,i=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??nr(),s=new Map((Js(r)?.missing??[]).map(d=>[d.voice,d])),o=Gs(e,n),a=o.map(d=>({...d,since:s.get(d.voice)?.since??i.toISOString(),...s.get(d.voice)?.notifiedAt?{notifiedAt:s.get(d.voice).notifiedAt}:{}})),c=[...s.keys()].filter(d=>!o.some(p=>p.voice===d));for(let d of c)this.deps.log(`[voice] ${ze(d)} is installed again; its agents speak with it again`);c.length&&zn(d=>c.some(p=>d===p||d.endsWith(`:${p}`)));let l=a.filter(d=>!d.notifiedAt);if(l.length){let{title:d,message:p}=Xs(l);try{await this.deps.notify(d,p);for(let f of l)f.notifiedAt=i.toISOString();this.deps.log(`[voice] told the owner: ${l.map(f=>ze(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=a.length>0;let u={checkedAt:i.toISOString(),missing:a};return(!tr(r)||JSON.stringify(a)!==JSON.stringify([...s.values()]))&&Ys(r,u),u}finally{this.running=!1}}};import{readFileSync as qe,writeFileSync as cr,existsSync as Ke,readdirSync as oo,statSync as ao}from"fs";import{resolve as Ge,join as co}from"path";import{existsSync as rr,mkdirSync as Zs,readFileSync as Qs,writeFileSync as ir}from"fs";import{dirname as eo,resolve as sr}from"path";import{z as m}from"zod";var to=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),no=m.object({id:m.string(),title:m.string(),description:m.string().optional(),assignee:m.string().optional(),labels:m.array(m.string()).default([]),milestone:m.string().optional(),status:m.enum(["todo","doing","blocked","done"]).default("todo"),priority:m.number().int().optional(),estimatedSeconds:m.number().int().optional(),source:to.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),ro=m.object({version:m.literal(1),items:m.array(no).default([])}),ge=class{constructor(e){this.path=e}jsonPath(){return sr(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return sr(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return rr(this.jsonPath())}load(){let e=this.jsonPath();if(!rr(e))return{version:1,items:[]};let n=Qs(e,"utf-8");try{return ro.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();Zs(eo(n),{recursive:!0}),ir(n,JSON.stringify(e,null,2)+`
127
- `),ir(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(s=>s.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let i=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??i,updatedAt:i};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),i=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),s=[];for(let o of e){if(i.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),s.push(a),i.add(a.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let s={...i.items[r],...n,id:i.items[r].id,createdAt:i.items[r].createdAt,updatedAt:new Date().toISOString()};return i.items[r]=s,this.save(i),s}remove(e){let n=this.load(),i=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===i?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],i={doing:[],blocked:[],todo:[],done:[]};for(let s of e.items)i[s.status].push(s);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[s,o]of r)if(i[s].length){n.push(`## ${o}`,"");for(let a of i[s]){let c=s==="done"?"x":" ",l=a.assignee?`@${a.assignee} `:"",u=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",d=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${c}] ${l}${a.title}${u}${d}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
128
- `)}};function Al(t){return`${t.type}:${t.project}:${t.iid}`}function or(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.gitlabUsernames?.length?i.push(o.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.githubUsernames?.length?i.push(o.githubUsernames[0]):i.push(s)}}return i}async function He(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?io(t.source,e,n,i):t.source.type==="github"?so(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function io(t,e,n,i){let r=n.channels.gitlab,s=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!s||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],c=async(f,g={})=>fetch(`${o}/api/v4${f}`,{...g,headers:{"PRIVATE-TOKEN":s,"Content-Type":"application/json",...g.headers||{}}}),l=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async g=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(g)}`,{headers:{"PRIVATE-TOKEN":s}});if(!h.ok)return null;let y=await h.json();return Array.isArray(y)&&y[0]?.id?y[0].id:null}catch{return null}}))).filter(g=>typeof g=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await c(`/projects/${l}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let g=await f.json();Array.isArray(g)&&g[0]?.id&&(d=g[0].id)}}catch(f){i(`[backlog-sync] milestone lookup failed: ${f.message}`)}let p={};if(e.title!==void 0&&(p.title=e.title),e.description!==void 0&&(p.description=e.description),e.labels!==void 0&&(p.labels=e.labels.join(",")),e.addLabels?.length&&(p.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(p.remove_labels=e.removeLabels.join(",")),u!==void 0&&(p.assignee_ids=u),d!==void 0&&(p.milestone_id=d),e.state&&(p.state_event=e.state==="closed"?"close":"reopen"),Object.keys(p).length)try{let f=await c(`/projects/${l}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(p)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let g=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${g.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await c(`/projects/${l}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function so(t,e,n,i){let s=n.channels.github?.token;if(!s)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(p,f={})=>fetch(`https://api.github.com${p}`,{...f,headers:{Authorization:`Bearer ${s}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),c=t.project,l;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")l=null;else try{let p=await a(`/repos/${c}/milestones?state=all&per_page=100`);if(p.ok){let f=await p.json(),g=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;g?.number&&(l=g.number)}}catch(p){i(`[backlog-sync] github milestone lookup failed: ${p.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let p=await a(`/repos/${c}/issues/${t.iid}`);if(p.ok){let f=await p.json(),g=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...g,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(p){i(`[backlog-sync] github label fetch failed: ${p.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),l!==void 0&&(d.milestone=l),e.state&&(d.state=e.state),Object.keys(d).length)try{let p=await a(`/repos/${c}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:p.ok,status:p.status}),!p.ok){let f=await p.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${p.status}: ${f.slice(0,200)}`,url:t.url}}}catch(p){return o.push({kind:"PATCH issue",ok:!1,error:p.message}),{ok:!1,attempts:o,error:p.message,url:t.url}}if(e.note)try{let p=await a(`/repos/${c}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:p.ok,status:p.status})}catch(p){o.push({kind:"POST comment",ok:!1,error:p.message})}return{ok:o.every(p=>p.ok),attempts:o,url:t.url}}var Xe=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,me=/@([a-z0-9_-]+)/i,ar=/\[time:\s*([0-9hm\s]+)\]/i;function lo(t){let e=t.match(/(\d+)\s*h/i),n=t.match(/(\d+)\s*m/i);return(e?parseInt(e[1],10)*3600:0)+(n?parseInt(n[1],10)*60:0)}var Je=class{constructor(e,n,i=()=>{}){this.path=e;this.daemon=n;this.log=i;this.store=new ge(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Ge(process.cwd(),this.path);return Ke(e)?qe(e,"utf-8").split(`
129
- `):[]}writeMd(e){let n=Ge(process.cwd(),this.path);cr(n,e.join(`
130
- `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(s=>s.status!=="done"&&(!s.assignee||s.assignee.toLowerCase()===e.toLowerCase())).map(s=>this.toWorkItem(s));let n=this.readMd(),i=[];for(let r=0;r<n.length;r++){let s=n[r].match(Xe);if(!s||s[2].toLowerCase()==="x")continue;let a=s[3],c=a.match(me);if(c&&c[1].toLowerCase()!==e.toLowerCase())continue;let l=a.match(ar),u=a.replace(me,"").replace(ar,"").trim();i.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:c?c[1]:void 0,estimatedSeconds:l?lo(l[1]):void 0,priority:r})}return i}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let i=this.store.findById(n);if(!i)return;let r=this.store.update(n,{assignee:i.assignee||e,status:"doing"});if(r.source&&this.daemon){let s=or([r.assignee||e],r.source,this.daemon);He(r,{assigneeUsernames:s,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(o=>this.log(`[backlog-sync] claim failed for ${n}: ${o?.message??o}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let a={};n.status==="done"?a.status="done":n.status==="blocked"?(a.status="blocked",a.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(a.status="doing"),n.timeSeconds&&(a.estimatedSeconds=n.timeSeconds);let c=this.store.update(e,a);if(c.source&&this.daemon){let l={};n.status==="done"?(l.addLabels=["Done"],l.removeLabels=["Doing"]):n.status==="blocked"&&(l.addLabels=["Blocked"]),n.note&&(l.note=n.note),Object.keys(l).length&&He(c,l,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let i=parseInt(e.slice(8),10),r=this.readMd(),s=r[i];if(!s)throw new Error(`backlog line ${i} missing`);if(!s.match(Xe))throw new Error(`backlog line ${i} not a checkbox`);if(n.status==="done"){r[i]=s.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(i+1,0,a)}else n.status==="blocked"?r.splice(i+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(i+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},Ye=class{constructor(e,n){this.root=e;this.glob=n}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,n){if(Ke(e))for(let i of oo(e)){let r=co(e,i);ao(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Ge(process.cwd(),this.root),n);let i=[];for(let r of n){let s=qe(r,"utf-8").split(`
131
- `);for(let o=0;o<s.length;o++){let a=s[o].match(Xe);if(!a||a[2].toLowerCase()==="x")continue;let c=a[3].match(me);!c||c[1].toLowerCase()!==e.toLowerCase()||i.push({id:`wiki:${r}:${o}`,title:a[3].replace(me,"").trim(),assignee:c[1],priority:o})}}return i}async claim(){}async report(e,n){let i=e.split(":"),r=parseInt(i[i.length-1],10),s=i.slice(1,-1).join(":");if(!Ke(s))return;let o=qe(s,"utf-8").split(`
132
- `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),cr(s,o.join(`
133
- `)))}},Ze=class{constructor(e,n,i,r,s){this.host=e;this.token=n;this.projects=i;this.agentUsernames=r;this.log=s}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,i]of Object.entries(this.agentUsernames))if(i.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let i=e.references?.full?.split("#")[0]||n,r=[],s;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(s=e.labels.map(l=>({name:l.name,color:l.color,text_color:l.text_color})),r=s.map(l=>l.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(l=>({username:l.username,name:l.name,avatarUrl:l.avatar_url})),c=a[0]?.username;return{id:`gitlab:${i}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:c?this.usernameToAgent(c)||c:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:s,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let i=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!i.ok)throw new Error(`GitLab ${i.status}: ${await i.text().catch(()=>"")}`);return i.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let i=[],r=this.projects.length?this.projects:["__ALL__"];for(let s of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(s)}&state=opened&scope=all&per_page=20`,c=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,l=await this.api(c);for(let u of l){let d=this.mapIssue(u,o);d.assignee=e,i.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${s} on ${o}: ${a.message}`)}return i}async claim(e,n){let{project:i,iid:r,type:s}=this.parseId(n),o=`/projects/${encodeURIComponent(i)}/${s==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(a){this.log(`[business] claim label update failed: ${a.message}`)}}async report(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),c=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(c)}`,{method:"POST"})}catch(l){this.log(`[business] add_spent_time failed: ${l.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(a){this.log(`[business] done label update failed: ${a.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(a){this.log(`[business] blocked label update failed: ${a.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(a){this.log(`[business] report note failed: ${a.message}`)}}async listAll(e={}){let n=e.sinceDays??30,i=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,s=e.state??"opened";r.set("state",s),r.set("updated_after",i),r.set("scope","all"),r.set("per_page","100"),r.set("with_labels_details","true"),r.set("order_by","updated_at"),r.set("sort","desc"),e.labels?.length&&r.set("labels",e.labels.join(",")),e.milestone&&r.set("milestone",e.milestone),e.search&&r.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],a=[];for(let l of o)try{let u=l==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(l)}/issues?${r.toString()}`,d=await this.api(u);for(let p of d)a.push(this.mapIssue(p,l))}catch(u){this.log(`[business] GitLab listAll failed on ${l}: ${u.message}`)}let c=a;if(e.notLabels?.length){let l=new Set(e.notLabels);c=c.filter(u=>!(u.labels||[]).some(d=>l.has(d)))}if(e.withoutScopedPrefix){let l=e.withoutScopedPrefix+"::";c=c.filter(u=>!(u.labels||[]).some(d=>d.startsWith(l)))}return c}async setState(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:i}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${i}?with_labels_details=true`);return{...this.mapIssue(r,n),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(o=>o.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,n){let{project:i,iid:r}=this.parseId(e),s;n.assigneeUsernames&&(s=(await Promise.all(n.assigneeUsernames.map(async u=>{try{let d=await this.api(`/users?username=${encodeURIComponent(u)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch{return null}}))).filter(u=>typeof u=="number"));let o;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")o=0;else try{let l=await this.api(`/projects/${encodeURIComponent(i)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(o=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${l.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),s!==void 0&&(a.assignee_ids=s),o!==void 0&&(a.milestone_id=o);let c=await this.api(`/projects/${encodeURIComponent(i)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(c,i)}async listMembers(){let e=new Map;for(let n of this.projects)try{let i=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of i)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(i){this.log(`[board] listMembers failed for ${n}: ${i.message}`)}return[...e.values()].sort((n,i)=>n.username.localeCompare(i.username))}async listMilestones(){let e=new Map;for(let i of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(i)}/milestones?per_page=100`);for(let s of r)s.title&&!e.has(s.title)&&e.set(s.title,{id:s.id,title:s.title,state:s.state,dueDate:s.due_date})}catch(r){this.log(`[board] listMilestones failed for ${i}: ${r.message}`)}let n=[...e.values()];return n.sort((i,r)=>i.state!==r.state?i.state==="active"?-1:1:i.title.localeCompare(r.title)),n}async create(e){let n=e.projectHint||this.projects[0];if(!n)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let i,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(i=(await Promise.all(r.map(async l=>{try{let u=await this.api(`/users?username=${encodeURIComponent(l)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${l}: ${u.message}`),null}}))).filter(l=>typeof l=="number"));let s;if(e.milestoneTitle)try{let c=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(s=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${c.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};i?.length&&(o.assignee_ids=i),s!==void 0&&(o.milestone_id=s);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,i){await this.transitionMany(e,n?[n]:[],i?[i]:[])}async transitionMany(e,n,i){let{project:r,iid:s,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",c=new URLSearchParams;n.length&&c.set("add_labels",n.join(",")),i.length&&c.set("remove_labels",i.join(",")),c.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${s}?${c.toString()}`,{method:"PUT"})}parseId(e){let i=e.replace(/^gitlab:/,"").split(":"),r=i.pop(),s=i.pop()==="mr"?"mr":"issue";return{project:i.join(":"),type:s,iid:r}}};function Pl(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new Je(i.path,e,n);case"wiki":return new Ye(i.path,i.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let s={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(s[a.agentId]=a.gitlabUsernames);let o=i.projects.length?i.projects:r.routes.map(a=>a.project);return new Ze(r.host,r.token,o,s,n)}}}var Qe="unmapped";function et(t,e=[]){if(!t)return Qe;let n=e.find(r=>r.id===t);if(n?.client)return n.client;let i=t.indexOf("/");return i>0?t.slice(0,i):t}function uo(t){let e=new Map,n=t.projects??[],i=t.orgChart??{};for(let s of n)s.pm&&(e.has(s.pm)||e.set(s.pm,et(s.id,n)));let r=(s,o=new Set)=>{if(e.has(s))return e.get(s);if(o.has(s))return;o.add(s);let a=i[s]?.reportsTo;if(!a)return;let c=r(a,o);return c&&e.set(s,c),c};for(let s of Object.keys(i))r(s);return e}function po(t,e,n=[]){if(!n.length)return;let i=n.filter(r=>!r.channel||r.channel===t);return i.find(r=>r.chatId&&e.chatId&&r.chatId===e.chatId)??i.find(r=>r.username&&e.username&&r.username===e.username)??i.find(r=>r.senderId&&e.senderId&&r.senderId===e.senderId)??i.find(r=>r.channel&&!r.chatId&&!r.username&&!r.senderId)}function Ol(t,e){let n=po(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return et(t.project,e.projects);if(t.agentId){let i=uo(e).get(t.agentId);if(i)return i}return Qe}function Nl(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[i,r,...s]=n,o=s.join(":"),a={agentId:e||i,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var fo=t=>t===Qe?"internal":"client";function go(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??fo(t),respondWithinMinutes:mo(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Ml(t){let e=new Set;for(let n of t.projects??[])e.add(et(n.id,t.projects));for(let n of t.contactMap??[])e.add(n.client);for(let n of Object.keys(t.clients??{}))e.add(n);return[...e].sort().map(n=>go(n,t))}function mo(t){let e=/^(\d+)\s*([mhd])$/.exec(String(t??"").trim());if(!e)return;let n=Number(e[1]);return e[2]==="m"?n:e[2]==="h"?n*60:n*1440}var ho=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,yo=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function lr(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(yo)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=bo(i);if(!r)return{cleanText:t};let s=n.index??0,o=n[1]??"";return{cleanText:(t.slice(0,s)+o+t.slice(s+n[0].length)).trim(),ui:r}}function Vl(t){if(!t||!t.includes("agentx:ui"))return t;let e=ho.exec(t);return e?t.slice(0,e.index).trimEnd():t}function bo(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n={};if(Array.isArray(e.buttons)){let i=[],r=[],s=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?i.push({label:o.label,url:o.url}):typeof o.reply=="string"&&o.reply.trim()?r.push({label:o.label,reply:o.reply.trim()}):o.action!=null&&s.push(o.label));i.length&&(n.buttons=i),r.length&&(n.replies=r),s.length&&(n.skippedActions=s)}if(e.poll&&typeof e.poll=="object"){let i=e.poll.question,r=e.poll.options;typeof i=="string"&&i.trim()&&Array.isArray(r)&&r.filter(s=>typeof s=="string").length>=2&&(n.poll={question:i,options:r.filter(s=>typeof s=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:i,url:r,caption:s}=e.media;["image","document","audio","video"].includes(i)&&typeof r=="string"&&r&&(n.media={type:i,url:r,...typeof s=="string"?{caption:s}:{}})}if(Array.isArray(e.quickReplies)){let i=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());i.length&&(n.quickReplies=i)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function Fl(t,e){let n=`${e}/call?to=${encodeURIComponent(t.from)}&callId=${encodeURIComponent(t.callId)}`;return t.reason==="camera"?`\u{1F4F7} ${t.from} is sharing a phone camera \u2014 tap to watch: ${n}&watch=1`:`\u{1F4DE} ${t.from} is calling \u2014 tap to join: ${n}`}var wo=5*6e4;function N(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var ur=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],i=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(N)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${N(n)}`}cleanupExpired(){let e=Date.now();for(let[n,i]of this.pending){let r=i.filter(s=>s.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==i.length&&this.pending.set(n,r)}for(let[n,i]of this.recentRings)i<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,i){return this.addSubscriber(e,n,{kind:"sse",res:i})}subscribeInternal(e,n,i){return this.addSubscriber(e,n,{kind:"callback",deliver:i})}addSubscriber(e,n,i){let r={callId:e,recipient:n,sink:i};this.subs.add(r);let s=i.kind==="sse"?"sse":"internal";this.log(`subscribe[${s}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let c=Date.now(),l=a.filter(u=>u.expiresAt>c);for(let{signal:u}of l)this.deliverTo(r,u);this.pending.delete(o),l.length&&this.log(`flushed ${l.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${s}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
122
+ Reinstall in ${us}. Agents switch back on their own once it is installed.`}}function ms(t=Fn()){if(!Wn(t))return null;try{let e=JSON.parse(is(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function hs(t,e){rs(cs(t),{recursive:!0}),os(`${t}.tmp`,JSON.stringify(e,null,2)+`
123
+ `),ss(`${t}.tmp`,t)}var Vn=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,i=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??Fn(),s=new Map((ms(r)?.missing??[]).map(d=>[d.voice,d])),o=fs(e,n),a=o.map(d=>({...d,since:s.get(d.voice)?.since??i.toISOString(),...s.get(d.voice)?.notifiedAt?{notifiedAt:s.get(d.voice).notifiedAt}:{}})),c=[...s.keys()].filter(d=>!o.some(p=>p.voice===d));for(let d of c)this.deps.log(`[voice] ${We(d)} is installed again; its agents speak with it again`);c.length&&Cn(d=>c.some(p=>d===p||d.endsWith(`:${p}`)));let l=a.filter(d=>!d.notifiedAt);if(l.length){let{title:d,message:p}=gs(l);try{await this.deps.notify(d,p);for(let f of l)f.notifiedAt=i.toISOString();this.deps.log(`[voice] told the owner: ${l.map(f=>We(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=a.length>0;let u={checkedAt:i.toISOString(),missing:a};return(!Wn(r)||JSON.stringify(a)!==JSON.stringify([...s.values()]))&&hs(r,u),u}finally{this.running=!1}}};import{readFileSync as Be,writeFileSync as Kn,existsSync as Ue,readdirSync as As,statSync as Is}from"fs";import{resolve as ze,join as Rs}from"path";import{existsSync as Bn,mkdirSync as ys,readFileSync as bs,writeFileSync as Un}from"fs";import{dirname as ws,resolve as zn}from"path";import{z as m}from"zod";var ks=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),xs=m.object({id:m.string(),title:m.string(),description:m.string().optional(),assignee:m.string().optional(),labels:m.array(m.string()).default([]),milestone:m.string().optional(),status:m.enum(["todo","doing","blocked","done"]).default("todo"),priority:m.number().int().optional(),estimatedSeconds:m.number().int().optional(),source:ks.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),Ss=m.object({version:m.literal(1),items:m.array(xs).default([])}),ue=class{constructor(e){this.path=e}jsonPath(){return zn(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return zn(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return Bn(this.jsonPath())}load(){let e=this.jsonPath();if(!Bn(e))return{version:1,items:[]};let n=bs(e,"utf-8");try{return Ss.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();ys(ws(n),{recursive:!0}),Un(n,JSON.stringify(e,null,2)+`
124
+ `),Un(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(s=>s.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let i=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??i,updatedAt:i};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),i=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),s=[];for(let o of e){if(i.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),s.push(a),i.add(a.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let s={...i.items[r],...n,id:i.items[r].id,createdAt:i.items[r].createdAt,updatedAt:new Date().toISOString()};return i.items[r]=s,this.save(i),s}remove(e){let n=this.load(),i=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===i?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],i={doing:[],blocked:[],todo:[],done:[]};for(let s of e.items)i[s.status].push(s);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[s,o]of r)if(i[s].length){n.push(`## ${o}`,"");for(let a of i[s]){let c=s==="done"?"x":" ",l=a.assignee?`@${a.assignee} `:"",u=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",d=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${c}] ${l}${a.title}${u}${d}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
125
+ `)}};function _c(t){return`${t.type}:${t.project}:${t.iid}`}function Hn(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.gitlabUsernames?.length?i.push(o.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.githubUsernames?.length?i.push(o.githubUsernames[0]):i.push(s)}}return i}async function Fe(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?vs(t.source,e,n,i):t.source.type==="github"?$s(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function vs(t,e,n,i){let r=n.channels.gitlab,s=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!s||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],c=async(f,g={})=>fetch(`${o}/api/v4${f}`,{...g,headers:{"PRIVATE-TOKEN":s,"Content-Type":"application/json",...g.headers||{}}}),l=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async g=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(g)}`,{headers:{"PRIVATE-TOKEN":s}});if(!h.ok)return null;let y=await h.json();return Array.isArray(y)&&y[0]?.id?y[0].id:null}catch{return null}}))).filter(g=>typeof g=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await c(`/projects/${l}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let g=await f.json();Array.isArray(g)&&g[0]?.id&&(d=g[0].id)}}catch(f){i(`[backlog-sync] milestone lookup failed: ${f.message}`)}let p={};if(e.title!==void 0&&(p.title=e.title),e.description!==void 0&&(p.description=e.description),e.labels!==void 0&&(p.labels=e.labels.join(",")),e.addLabels?.length&&(p.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(p.remove_labels=e.removeLabels.join(",")),u!==void 0&&(p.assignee_ids=u),d!==void 0&&(p.milestone_id=d),e.state&&(p.state_event=e.state==="closed"?"close":"reopen"),Object.keys(p).length)try{let f=await c(`/projects/${l}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(p)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let g=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${g.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await c(`/projects/${l}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function $s(t,e,n,i){let s=n.channels.github?.token;if(!s)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(p,f={})=>fetch(`https://api.github.com${p}`,{...f,headers:{Authorization:`Bearer ${s}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),c=t.project,l;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")l=null;else try{let p=await a(`/repos/${c}/milestones?state=all&per_page=100`);if(p.ok){let f=await p.json(),g=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;g?.number&&(l=g.number)}}catch(p){i(`[backlog-sync] github milestone lookup failed: ${p.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let p=await a(`/repos/${c}/issues/${t.iid}`);if(p.ok){let f=await p.json(),g=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...g,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(p){i(`[backlog-sync] github label fetch failed: ${p.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),l!==void 0&&(d.milestone=l),e.state&&(d.state=e.state),Object.keys(d).length)try{let p=await a(`/repos/${c}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:p.ok,status:p.status}),!p.ok){let f=await p.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${p.status}: ${f.slice(0,200)}`,url:t.url}}}catch(p){return o.push({kind:"PATCH issue",ok:!1,error:p.message}),{ok:!1,attempts:o,error:p.message,url:t.url}}if(e.note)try{let p=await a(`/repos/${c}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:p.ok,status:p.status})}catch(p){o.push({kind:"POST comment",ok:!1,error:p.message})}return{ok:o.every(p=>p.ok),attempts:o,url:t.url}}var He=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,de=/@([a-z0-9_-]+)/i,qn=/\[time:\s*([0-9hm\s]+)\]/i;function _s(t){let e=t.match(/(\d+)\s*h/i),n=t.match(/(\d+)\s*m/i);return(e?parseInt(e[1],10)*3600:0)+(n?parseInt(n[1],10)*60:0)}var qe=class{constructor(e,n,i=()=>{}){this.path=e;this.daemon=n;this.log=i;this.store=new ue(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=ze(process.cwd(),this.path);return Ue(e)?Be(e,"utf-8").split(`
126
+ `):[]}writeMd(e){let n=ze(process.cwd(),this.path);Kn(n,e.join(`
127
+ `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(s=>s.status!=="done"&&(!s.assignee||s.assignee.toLowerCase()===e.toLowerCase())).map(s=>this.toWorkItem(s));let n=this.readMd(),i=[];for(let r=0;r<n.length;r++){let s=n[r].match(He);if(!s||s[2].toLowerCase()==="x")continue;let a=s[3],c=a.match(de);if(c&&c[1].toLowerCase()!==e.toLowerCase())continue;let l=a.match(qn),u=a.replace(de,"").replace(qn,"").trim();i.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:c?c[1]:void 0,estimatedSeconds:l?_s(l[1]):void 0,priority:r})}return i}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let i=this.store.findById(n);if(!i)return;let r=this.store.update(n,{assignee:i.assignee||e,status:"doing"});if(r.source&&this.daemon){let s=Hn([r.assignee||e],r.source,this.daemon);Fe(r,{assigneeUsernames:s,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(o=>this.log(`[backlog-sync] claim failed for ${n}: ${o?.message??o}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let a={};n.status==="done"?a.status="done":n.status==="blocked"?(a.status="blocked",a.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(a.status="doing"),n.timeSeconds&&(a.estimatedSeconds=n.timeSeconds);let c=this.store.update(e,a);if(c.source&&this.daemon){let l={};n.status==="done"?(l.addLabels=["Done"],l.removeLabels=["Doing"]):n.status==="blocked"&&(l.addLabels=["Blocked"]),n.note&&(l.note=n.note),Object.keys(l).length&&Fe(c,l,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let i=parseInt(e.slice(8),10),r=this.readMd(),s=r[i];if(!s)throw new Error(`backlog line ${i} missing`);if(!s.match(He))throw new Error(`backlog line ${i} not a checkbox`);if(n.status==="done"){r[i]=s.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(i+1,0,a)}else n.status==="blocked"?r.splice(i+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(i+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},Ke=class{constructor(e,n){this.root=e;this.glob=n}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,n){if(Ue(e))for(let i of As(e)){let r=Rs(e,i);Is(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(ze(process.cwd(),this.root),n);let i=[];for(let r of n){let s=Be(r,"utf-8").split(`
128
+ `);for(let o=0;o<s.length;o++){let a=s[o].match(He);if(!a||a[2].toLowerCase()==="x")continue;let c=a[3].match(de);!c||c[1].toLowerCase()!==e.toLowerCase()||i.push({id:`wiki:${r}:${o}`,title:a[3].replace(de,"").trim(),assignee:c[1],priority:o})}}return i}async claim(){}async report(e,n){let i=e.split(":"),r=parseInt(i[i.length-1],10),s=i.slice(1,-1).join(":");if(!Ue(s))return;let o=Be(s,"utf-8").split(`
129
+ `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),Kn(s,o.join(`
130
+ `)))}},Ge=class{constructor(e,n,i,r,s){this.host=e;this.token=n;this.projects=i;this.agentUsernames=r;this.log=s}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,i]of Object.entries(this.agentUsernames))if(i.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let i=e.references?.full?.split("#")[0]||n,r=[],s;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(s=e.labels.map(l=>({name:l.name,color:l.color,text_color:l.text_color})),r=s.map(l=>l.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(l=>({username:l.username,name:l.name,avatarUrl:l.avatar_url})),c=a[0]?.username;return{id:`gitlab:${i}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:c?this.usernameToAgent(c)||c:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:s,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let i=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!i.ok)throw new Error(`GitLab ${i.status}: ${await i.text().catch(()=>"")}`);return i.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let i=[],r=this.projects.length?this.projects:["__ALL__"];for(let s of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(s)}&state=opened&scope=all&per_page=20`,c=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,l=await this.api(c);for(let u of l){let d=this.mapIssue(u,o);d.assignee=e,i.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${s} on ${o}: ${a.message}`)}return i}async claim(e,n){let{project:i,iid:r,type:s}=this.parseId(n),o=`/projects/${encodeURIComponent(i)}/${s==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(a){this.log(`[business] claim label update failed: ${a.message}`)}}async report(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),c=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(c)}`,{method:"POST"})}catch(l){this.log(`[business] add_spent_time failed: ${l.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(a){this.log(`[business] done label update failed: ${a.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(a){this.log(`[business] blocked label update failed: ${a.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(a){this.log(`[business] report note failed: ${a.message}`)}}async listAll(e={}){let n=e.sinceDays??30,i=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,s=e.state??"opened";r.set("state",s),r.set("updated_after",i),r.set("scope","all"),r.set("per_page","100"),r.set("with_labels_details","true"),r.set("order_by","updated_at"),r.set("sort","desc"),e.labels?.length&&r.set("labels",e.labels.join(",")),e.milestone&&r.set("milestone",e.milestone),e.search&&r.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],a=[];for(let l of o)try{let u=l==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(l)}/issues?${r.toString()}`,d=await this.api(u);for(let p of d)a.push(this.mapIssue(p,l))}catch(u){this.log(`[business] GitLab listAll failed on ${l}: ${u.message}`)}let c=a;if(e.notLabels?.length){let l=new Set(e.notLabels);c=c.filter(u=>!(u.labels||[]).some(d=>l.has(d)))}if(e.withoutScopedPrefix){let l=e.withoutScopedPrefix+"::";c=c.filter(u=>!(u.labels||[]).some(d=>d.startsWith(l)))}return c}async setState(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:i}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${i}?with_labels_details=true`);return{...this.mapIssue(r,n),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(o=>o.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,n){let{project:i,iid:r}=this.parseId(e),s;n.assigneeUsernames&&(s=(await Promise.all(n.assigneeUsernames.map(async u=>{try{let d=await this.api(`/users?username=${encodeURIComponent(u)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch{return null}}))).filter(u=>typeof u=="number"));let o;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")o=0;else try{let l=await this.api(`/projects/${encodeURIComponent(i)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(o=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${l.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),s!==void 0&&(a.assignee_ids=s),o!==void 0&&(a.milestone_id=o);let c=await this.api(`/projects/${encodeURIComponent(i)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(c,i)}async listMembers(){let e=new Map;for(let n of this.projects)try{let i=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of i)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(i){this.log(`[board] listMembers failed for ${n}: ${i.message}`)}return[...e.values()].sort((n,i)=>n.username.localeCompare(i.username))}async listMilestones(){let e=new Map;for(let i of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(i)}/milestones?per_page=100`);for(let s of r)s.title&&!e.has(s.title)&&e.set(s.title,{id:s.id,title:s.title,state:s.state,dueDate:s.due_date})}catch(r){this.log(`[board] listMilestones failed for ${i}: ${r.message}`)}let n=[...e.values()];return n.sort((i,r)=>i.state!==r.state?i.state==="active"?-1:1:i.title.localeCompare(r.title)),n}async create(e){let n=e.projectHint||this.projects[0];if(!n)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let i,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(i=(await Promise.all(r.map(async l=>{try{let u=await this.api(`/users?username=${encodeURIComponent(l)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${l}: ${u.message}`),null}}))).filter(l=>typeof l=="number"));let s;if(e.milestoneTitle)try{let c=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(s=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${c.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};i?.length&&(o.assignee_ids=i),s!==void 0&&(o.milestone_id=s);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,i){await this.transitionMany(e,n?[n]:[],i?[i]:[])}async transitionMany(e,n,i){let{project:r,iid:s,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",c=new URLSearchParams;n.length&&c.set("add_labels",n.join(",")),i.length&&c.set("remove_labels",i.join(",")),c.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${s}?${c.toString()}`,{method:"PUT"})}parseId(e){let i=e.replace(/^gitlab:/,"").split(":"),r=i.pop(),s=i.pop()==="mr"?"mr":"issue";return{project:i.join(":"),type:s,iid:r}}};function Mc(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new qe(i.path,e,n);case"wiki":return new Ke(i.path,i.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let s={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(s[a.agentId]=a.gitlabUsernames);let o=i.projects.length?i.projects:r.routes.map(a=>a.project);return new Ge(r.host,r.token,o,s,n)}}}var Xe="unmapped";function Je(t,e=[]){if(!t)return Xe;let n=e.find(r=>r.id===t);if(n?.client)return n.client;let i=t.indexOf("/");return i>0?t.slice(0,i):t}function Cs(t){let e=new Map,n=t.projects??[],i=t.orgChart??{};for(let s of n)s.pm&&(e.has(s.pm)||e.set(s.pm,Je(s.id,n)));let r=(s,o=new Set)=>{if(e.has(s))return e.get(s);if(o.has(s))return;o.add(s);let a=i[s]?.reportsTo;if(!a)return;let c=r(a,o);return c&&e.set(s,c),c};for(let s of Object.keys(i))r(s);return e}function Ds(t,e,n=[]){if(!n.length)return;let i=n.filter(r=>!r.channel||r.channel===t);return i.find(r=>r.chatId&&e.chatId&&r.chatId===e.chatId)??i.find(r=>r.username&&e.username&&r.username===e.username)??i.find(r=>r.senderId&&e.senderId&&r.senderId===e.senderId)??i.find(r=>r.channel&&!r.chatId&&!r.username&&!r.senderId)}function Nc(t,e){let n=Ds(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return Je(t.project,e.projects);if(t.agentId){let i=Cs(e).get(t.agentId);if(i)return i}return Xe}function jc(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[i,r,...s]=n,o=s.join(":"),a={agentId:e||i,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var Es=t=>t===Xe?"internal":"client";function Ts(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??Es(t),respondWithinMinutes:Ps(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Vc(t){let e=new Set;for(let n of t.projects??[])e.add(Je(n.id,t.projects));for(let n of t.contactMap??[])e.add(n.client);for(let n of Object.keys(t.clients??{}))e.add(n);return[...e].sort().map(n=>Ts(n,t))}function Ps(t){let e=/^(\d+)\s*([mhd])$/.exec(String(t??"").trim());if(!e)return;let n=Number(e[1]);return e[2]==="m"?n:e[2]==="h"?n*60:n*1440}var Ls=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Ms=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function Gn(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(Ms)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=Os(i);if(!r)return{cleanText:t};let s=n.index??0,o=n[1]??"";return{cleanText:(t.slice(0,s)+o+t.slice(s+n[0].length)).trim(),ui:r}}function Fc(t){if(!t||!t.includes("agentx:ui"))return t;let e=Ls.exec(t);return e?t.slice(0,e.index).trimEnd():t}function Os(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n={};if(Array.isArray(e.buttons)){let i=[],r=[],s=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?i.push({label:o.label,url:o.url}):typeof o.reply=="string"&&o.reply.trim()?r.push({label:o.label,reply:o.reply.trim()}):o.action!=null&&s.push(o.label));i.length&&(n.buttons=i),r.length&&(n.replies=r),s.length&&(n.skippedActions=s)}if(e.poll&&typeof e.poll=="object"){let i=e.poll.question,r=e.poll.options;typeof i=="string"&&i.trim()&&Array.isArray(r)&&r.filter(s=>typeof s=="string").length>=2&&(n.poll={question:i,options:r.filter(s=>typeof s=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:i,url:r,caption:s}=e.media;["image","document","audio","video"].includes(i)&&typeof r=="string"&&r&&(n.media={type:i,url:r,...typeof s=="string"?{caption:s}:{}})}if(Array.isArray(e.quickReplies)){let i=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());i.length&&(n.quickReplies=i)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function Uc(t,e){let n=`${e}/call?to=${encodeURIComponent(t.from)}&callId=${encodeURIComponent(t.callId)}`;return t.reason==="camera"?`\u{1F4F7} ${t.from} is sharing a phone camera \u2014 tap to watch: ${n}&watch=1`:`\u{1F4DE} ${t.from} is calling \u2014 tap to join: ${n}`}var Ns=5*6e4;function T(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var Xn=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],i=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(T)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${T(n)}`}cleanupExpired(){let e=Date.now();for(let[n,i]of this.pending){let r=i.filter(s=>s.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==i.length&&this.pending.set(n,r)}for(let[n,i]of this.recentRings)i<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,i){return this.addSubscriber(e,n,{kind:"sse",res:i})}subscribeInternal(e,n,i){return this.addSubscriber(e,n,{kind:"callback",deliver:i})}addSubscriber(e,n,i){let r={callId:e,recipient:n,sink:i};this.subs.add(r);let s=i.kind==="sse"?"sse":"internal";this.log(`subscribe[${s}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let c=Date.now(),l=a.filter(u=>u.expiresAt>c);for(let{signal:u}of l)this.deliverTo(r,u);this.pending.delete(o),l.length&&this.log(`flushed ${l.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${s}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
134
131
  data: ${JSON.stringify(n)}
135
132
 
136
- `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=N(e.to);if(n===N(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let i of this.subs)if(i.callId===e&&N(i.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(N(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let i=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>i)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,i+wo),this.ringHandler)try{this.ringHandler(e)}catch(s){this.log(`ringHandler threw: ${s.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let i=this.pendingKey(e.callId,e.to),r=this.pending.get(i)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(i,r),this.log(`buffered ${e.kind} for call=${e.callId} to=${e.to} (no subscriber yet, ${r.length} pending)`)}return{ok:!0}}fanOut(e){let n=0,i=N(e.to);for(let r of this.subs)r.callId===e.callId&&N(r.recipient)===i&&(this.deliverTo(r,e)?n++:this.subs.delete(r));return n}get subscriberCount(){return this.subs.size}shutdown(){this.cleanupTimer&&clearInterval(this.cleanupTimer);for(let e of this.subs)if(e.sink.kind==="sse")try{e.sink.res.end()}catch{}this.subs.clear(),this.pending.clear()}};import{execFile as Mo}from"child_process";import{mkdtempSync as Do,rmSync as Eo,writeFileSync as To}from"fs";import{tmpdir as Po}from"os";import{join as mr}from"path";import{randomBytes as ko}from"crypto";var D={top:8,side:32,bottom:60},tt={height:56,keep:52},dr=`
133
+ `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=T(e.to);if(n===T(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let i of this.subs)if(i.callId===e&&T(i.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(T(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let i=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>i)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,i+Ns),this.ringHandler)try{this.ringHandler(e)}catch(s){this.log(`ringHandler threw: ${s.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let i=this.pendingKey(e.callId,e.to),r=this.pending.get(i)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(i,r),this.log(`buffered ${e.kind} for call=${e.callId} to=${e.to} (no subscriber yet, ${r.length} pending)`)}return{ok:!0}}fanOut(e){let n=0,i=T(e.to);for(let r of this.subs)r.callId===e.callId&&T(r.recipient)===i&&(this.deliverTo(r,e)?n++:this.subs.delete(r));return n}get subscriberCount(){return this.subs.size}shutdown(){this.cleanupTimer&&clearInterval(this.cleanupTimer);for(let e of this.subs)if(e.sink.kind==="sse")try{e.sink.res.end()}catch{}this.subs.clear(),this.pending.clear()}};import{execFile as to}from"child_process";import{mkdtempSync as Gs,rmSync as Xs,writeFileSync as Js}from"fs";import{tmpdir as Ys}from"os";import{join as er}from"path";import{randomBytes as js}from"crypto";var _={top:8,side:32,bottom:60},Ye={height:56,keep:52},Jn=`
137
134
  :root {
138
135
  --ac-paper: #fafaf9; --ac-soft: #f4f4f2; --ac-edge: #e9e9e6;
139
136
  --ac-text: #0b1413; --ac-muted: #4a5856; --ac-subtle: #7c8987;
@@ -163,11 +160,11 @@ body {
163
160
  font: 13.5px/1.5 var(--ac-font); color: var(--ac-text); font-feature-settings: "ss01", "cv11";
164
161
  -webkit-font-smoothing: antialiased; -webkit-user-select: none; user-select: none; cursor: default;
165
162
  }
166
- .wrap { padding: ${D.top}px ${D.side}px ${D.bottom}px; }
163
+ .wrap { padding: ${_.top}px ${_.side}px ${_.bottom}px; }
167
164
  .card {
168
165
  background: var(--ac-paper); border: 1px solid var(--ac-rim); border-radius: 18px;
169
166
  box-shadow: var(--ac-shadow); overflow: hidden; animation: ac-in .26s cubic-bezier(.65,0,.35,1);
170
- position: relative; display: flex; flex-direction: column; max-height: calc(100vh - ${D.top+D.bottom}px);
167
+ position: relative; display: flex; flex-direction: column; max-height: calc(100vh - ${_.top+_.bottom}px);
171
168
  }
172
169
  .card::before {
173
170
  content: ""; position: absolute; top: 6px; left: 50%; width: 32px; height: 4px; margin-left: -16px;
@@ -262,33 +259,33 @@ button.primary:hover:not(:disabled) { transform: translateY(-1px); background: v
262
259
  button.primary:disabled { opacity: .55; cursor: not-allowed; }
263
260
  kbd { font: 11px var(--ac-mono); color: var(--ac-subtle); }
264
261
  button.primary kbd { color: inherit; opacity: .7; }
265
- `;var pr=t=>t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),fr=t=>`${t.getDate()} ${t.toLocaleDateString("en-US",{month:"short"})}`;function xo(t,e){let n=new Date(t);return Number.isNaN(n.getTime())?"":`since ${n.toDateString()===new Date(e).toDateString()?pr(n):fr(n)}`}function So(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[fr(n)],pr(n)].join(" ")}function vo(t){let e=t.trim().split(/[\s_-]+/).filter(Boolean);return(e.length>1?e[0][0]+e[1][0]:t.trim().slice(0,1)).toUpperCase()}function $o(t){let e=(t.recommend??"").trim(),n=e.toLowerCase(),i=t.choices??[],r=-1;if(i.forEach((o,a)=>{!n.startsWith(o.toLowerCase())||!/^\s*($|[:,.;–—-](\s|$))/.test(e.slice(o.length))||(r<0||o.length>i[r].length)&&(r=a)}),r<0)return{index:r,why:e};let s=e.slice(i[r].length).replace(/^[\s:,.;–—-]+/,"");return{index:r,why:s.slice(0,1).toUpperCase()+s.slice(1)}}function Io(t){return t.draft?"Send":t.choices?.length?"Choose":"Yes"}var nt=t=>`<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${t}</svg>`,Ao=nt('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),Ro=nt('<path d="m6 15 6-6 6 6"/>'),_o=nt('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function gr(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=ko(12).toString("base64"),s=t.choices??[],o=t.origin?.kind==="reminder",a=$o(t),c=s.map((d,p)=>`<button class="opt" role="radio" aria-checked="false" data-i="${p}"><span class="n">${p+1}</span><span class="t">${k(d)}</span>${p===a.index?'<i class="dot"></i>':""}</button>`).join(""),l=t.recommend?`<span class="rec"><i class="dot"></i>${k(i)} recommends</span>`:"",u={choices:s,draft:t.draft??"",placeholder:jt,chime:e.sound==="chime",volume:Math.min(1,Math.max(0,e.volume??.4)),theme:e.theme??"system",pick:e.pick&&e.pick<=s.length?e.pick-1:a.index};return`<!doctype html>
262
+ `;var Yn=t=>t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),Zn=t=>`${t.getDate()} ${t.toLocaleDateString("en-US",{month:"short"})}`;function Vs(t,e){let n=new Date(t);return Number.isNaN(n.getTime())?"":`since ${n.toDateString()===new Date(e).toDateString()?Yn(n):Zn(n)}`}function Ws(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[Zn(n)],Yn(n)].join(" ")}function Fs(t){let e=t.trim().split(/[\s_-]+/).filter(Boolean);return(e.length>1?e[0][0]+e[1][0]:t.trim().slice(0,1)).toUpperCase()}function Bs(t){let e=(t.recommend??"").trim(),n=e.toLowerCase(),i=t.choices??[],r=-1;if(i.forEach((o,a)=>{!n.startsWith(o.toLowerCase())||!/^\s*($|[:,.;–—-](\s|$))/.test(e.slice(o.length))||(r<0||o.length>i[r].length)&&(r=a)}),r<0)return{index:r,why:e};let s=e.slice(i[r].length).replace(/^[\s:,.;–—-]+/,"");return{index:r,why:s.slice(0,1).toUpperCase()+s.slice(1)}}function Us(t){return t.draft?"Send":t.choices?.length?"Choose":"Yes"}var Ze=t=>`<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${t}</svg>`,zs=Ze('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),Hs=Ze('<path d="m6 15 6-6 6 6"/>'),qs=Ze('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function Qn(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=js(12).toString("base64"),s=t.choices??[],o=t.origin?.kind==="reminder",a=Bs(t),c=s.map((d,p)=>`<button class="opt" role="radio" aria-checked="false" data-i="${p}"><span class="n">${p+1}</span><span class="t">${w(d)}</span>${p===a.index?'<i class="dot"></i>':""}</button>`).join(""),l=t.recommend?`<span class="rec"><i class="dot"></i>${w(i)} recommends</span>`:"",u={choices:s,draft:t.draft??"",placeholder:Lt,chime:e.sound==="chime",volume:Math.min(1,Math.max(0,e.volume??.4)),theme:e.theme??"system",pick:e.pick&&e.pick<=s.length?e.pick-1:a.index};return`<!doctype html>
266
263
  <html lang="en"><head><meta charset="utf-8">
267
264
  <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${r}'">
268
265
  <title>AgentX</title>
269
- <style>${dr}</style></head>
266
+ <style>${Jn}</style></head>
270
267
  <body><div class="wrap"><main class="card${e.still?" still":""}">
271
- <div class="head" title="Drag to move"><span class="avatar">${k(vo(i))}</span>
272
- <div class="who"><b>${k(i)}</b><span>${k(xo(t.created_at,n))}</span></div>
268
+ <div class="head" title="Drag to move"><span class="avatar">${w(Fs(i))}</span>
269
+ <div class="who"><b>${w(i)}</b><span>${w(Vs(t.created_at,n))}</span></div>
273
270
  <span class="kind${o?"":" decision"}">${o?"Reminder":"Decision"}</span>
274
- <button class="fold" id="fold" title="Shrink" aria-label="Shrink the card" aria-expanded="true">${Ro}</button></div>
275
- <div class="body"><h1 dir="auto">${k(t.title)}</h1>
276
- ${t.context?`<p class="context" dir="auto">${k(t.context)}</p>`:""}
277
- <p class="ask" dir="auto">${k(t.ask)}</p>
271
+ <button class="fold" id="fold" title="Shrink" aria-label="Shrink the card" aria-expanded="true">${Hs}</button></div>
272
+ <div class="body"><h1 dir="auto">${w(t.title)}</h1>
273
+ ${t.context?`<p class="context" dir="auto">${w(t.context)}</p>`:""}
274
+ <p class="ask" dir="auto">${w(t.ask)}</p>
278
275
  ${c||l?`<div class="label-row">${c?'<span class="label">Pick one</span>':""}${l}</div>`:""}
279
276
  ${c?`<div class="options" role="radiogroup">${c}</div>`:""}
280
- ${a.why?`<p class="why" dir="auto">${k(a.why)}</p>`:""}
277
+ ${a.why?`<p class="why" dir="auto">${w(a.why)}</p>`:""}
281
278
  ${t.draft?`<div class="label-row" id="msg"><span class="label">Message</span><span class="edited"><i class="dot"></i>Edited</span><button class="reset" id="reset">Reset</button></div>
282
279
  <textarea id="text" dir="auto" rows="2" spellcheck="true"></textarea>`:""}
283
- <div class="notes"><div>${Ao}<span>If you don't answer by ${k(So(t.expires,n))}: ${k(t.if_silent)}.</span></div>
284
- <div>${_o}<span>Nothing goes out until you click.</span></div></div>
280
+ <div class="notes"><div>${zs}<span>If you don't answer by ${w(Ws(t.expires,n))}: ${w(t.if_silent)}.</span></div>
281
+ <div>${qs}<span>Nothing goes out until you click.</span></div></div>
285
282
  </div><div class="foot"><button class="btn later" id="later">Not now<kbd>esc</kbd></button>
286
283
  <button class="btn" id="no">No</button>
287
- <button class="btn primary" id="yes">${Io(t)}<kbd>\u2318\u21A9</kbd></button></div>
284
+ <button class="btn primary" id="yes">${Us(t)}<kbd>\u2318\u21A9</kbd></button></div>
288
285
  </main></div>
289
286
  <script type="application/json" id="data">${JSON.stringify(u).replace(/</g,"\\u003c")}</script>
290
- <script nonce="${r}">${Co}</script>
291
- </body></html>`}var Co=`
287
+ <script nonce="${r}">${Ks}</script>
288
+ </body></html>`}var Ks=`
292
289
  (function () {
293
290
  var d = JSON.parse(document.getElementById("data").textContent);
294
291
  var root = document.documentElement;
@@ -377,10 +374,10 @@ ${t.draft?`<div class="label-row" id="msg"><span class="label">Message</span><sp
377
374
  });
378
375
  } catch (e) {}
379
376
  })();
380
- `;var Lo=440,Oo=`
377
+ `;var Zs=440,Qs=`
381
378
  ObjC.import("Cocoa"); ObjC.import("WebKit")
382
379
  function run(argv) {
383
- var path = argv[0], side = ${D.side}, gripTop = ${D.top}, gripEnd = ${D.top+tt.height}, keep = ${tt.keep}, w = Number(argv[1]) + 2 * side, h = 420, secs = Number(argv[2]), capture = argv[3] || ""
380
+ var path = argv[0], side = ${_.side}, gripTop = ${_.top}, gripEnd = ${_.top+Ye.height}, keep = ${Ye.keep}, w = Number(argv[1]) + 2 * side, h = 420, secs = Number(argv[2]), capture = argv[3] || ""
384
381
  var app = $.NSApplication.sharedApplication
385
382
  app.setActivationPolicy($.NSApplicationActivationPolicyAccessory)
386
383
  ObjC.registerSubclass({ name: "AgentXCardView", superclass: "WKWebView", methods: {
@@ -450,21 +447,21 @@ function run(argv) {
450
447
  }
451
448
  function gone(why) { return JSON.stringify({ action: "dismiss", why: why }) }
452
449
  function quoted(s) { return "'" + String(s).replace(/'/g, "'\\\\''") + "'" }
453
- `;function No(t,e){let n=t.trim().split(`
454
- `).pop()??"",i;try{i=JSON.parse(n)}catch{return{action:"dismiss"}}if(i?.action==="no")return{action:"no"};if(i?.action==="dismiss"&&yr.includes(i.why))return{action:"dismiss",why:i.why};if(i?.action!=="yes")return{action:"dismiss"};let r=e.choices??[],s;if(r.length){if(typeof i.choice!="string"||!r.includes(i.choice))return{action:"dismiss"};s=i.choice}let o;return e.draft&&(o=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
455
- `).trim():"",!o||o.length>Mt.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...o?{text:o}:{}}}async function hr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=Do(mr(Po(),"agentx-card-"));try{let s=mr(r,"card.html");To(s,gr(t,{...e,still:!!e.capture}),{mode:384});let o=["-l","JavaScript","-e",Oo,s,String(Lo),String(i),...e.capture?[e.capture]:[]],a=await n("/usr/bin/osascript",o,(i+10)*1e3);return a.ok?No(a.stdout,t):null}finally{Eo(r,{recursive:!0,force:!0})}}var yr=["not now","timed out","closed"],jo=(t,e,n)=>new Promise(i=>{try{Mo(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),br=160,wr=15e3;function Vo(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>br?e.slice(0,br):e}async function Wo(t,e,n,i){let r=e.sound==="chime"?i?"":"Glass":e.sound,s=r?Kt(r):null;if(s&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),s],wr),e.speak){let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",Vo(t)],wr)}}function Sr(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function Fo(t,e,n){return Sr(["on run argv","activate","set opts to items 3 thru -1 of argv",'set pick to choose from list opts with title (item 1 of argv) with prompt (item 2 of argv) OK button name "Next" cancel button name "Not now"','if pick is false then return ""',"return item 1 of pick","end run"],[t,e,...n])}function kr(t,e,n,i,r){return Sr(["on run argv","activate","set AppleScript's text item delimiters to linefeed","set btns to text items of (item 3 of argv)","set secs to (item 5 of argv) as integer","if (count of argv) > 5 then","set r to display dialog (item 2 of argv) with title (item 1 of argv) default answer (item 6 of argv) buttons btns default button (item 4 of argv) giving up after secs","else","set r to display dialog (item 2 of argv) with title (item 1 of argv) buttons btns default button (item 4 of argv) giving up after secs","end if",'if gave up of r then return ""',"if (count of argv) > 5 then return (button returned of r) & linefeed & (text returned of r)","return button returned of r","end run"],[t,e,n.join(`
456
- `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function xr(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
457
- `);return n<0?{button:e,text:""}:{button:e.slice(0,n),text:e.slice(n+1)}}function rt(t){return[t.ask,t.recommend?`Recommended: ${t.recommend}`:"",`From ${t.raised_by}`].filter(Boolean).join(`
450
+ `;function eo(t,e){let n=t.trim().split(`
451
+ `).pop()??"",i;try{i=JSON.parse(n)}catch{return{action:"dismiss"}}if(i?.action==="no")return{action:"no"};if(i?.action==="dismiss"&&nr.includes(i.why))return{action:"dismiss",why:i.why};if(i?.action!=="yes")return{action:"dismiss"};let r=e.choices??[],s;if(r.length){if(typeof i.choice!="string"||!r.includes(i.choice))return{action:"dismiss"};s=i.choice}let o;return e.draft&&(o=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
452
+ `).trim():"",!o||o.length>Pt.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...o?{text:o}:{}}}async function tr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=Gs(er(Ys(),"agentx-card-"));try{let s=er(r,"card.html");Js(s,Qn(t,{...e,still:!!e.capture}),{mode:384});let o=["-l","JavaScript","-e",Qs,s,String(Zs),String(i),...e.capture?[e.capture]:[]],a=await n("/usr/bin/osascript",o,(i+10)*1e3);return a.ok?eo(a.stdout,t):null}finally{Xs(r,{recursive:!0,force:!0})}}var nr=["not now","timed out","closed"],no=(t,e,n)=>new Promise(i=>{try{to(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),rr=160,ir=15e3;function ro(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>rr?e.slice(0,rr):e}async function io(t,e,n,i){let r=e.sound==="chime"?i?"":"Glass":e.sound,s=r?Wt(r):null;if(s&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),s],ir),e.speak){let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",ro(t)],ir)}}function ar(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function so(t,e,n){return ar(["on run argv","activate","set opts to items 3 thru -1 of argv",'set pick to choose from list opts with title (item 1 of argv) with prompt (item 2 of argv) OK button name "Next" cancel button name "Not now"','if pick is false then return ""',"return item 1 of pick","end run"],[t,e,...n])}function sr(t,e,n,i,r){return ar(["on run argv","activate","set AppleScript's text item delimiters to linefeed","set btns to text items of (item 3 of argv)","set secs to (item 5 of argv) as integer","if (count of argv) > 5 then","set r to display dialog (item 2 of argv) with title (item 1 of argv) default answer (item 6 of argv) buttons btns default button (item 4 of argv) giving up after secs","else","set r to display dialog (item 2 of argv) with title (item 1 of argv) buttons btns default button (item 4 of argv) giving up after secs","end if",'if gave up of r then return ""',"if (count of argv) > 5 then return (button returned of r) & linefeed & (text returned of r)","return button returned of r","end run"],[t,e,n.join(`
453
+ `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function or(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
454
+ `);return n<0?{button:e,text:""}:{button:e.slice(0,n),text:e.slice(n+1)}}function Qe(t){return[t.ask,t.recommend?`Recommended: ${t.recommend}`:"",`From ${t.raised_by}`].filter(Boolean).join(`
458
455
 
459
- `)}async function vr(t,e,n={}){let i=n.run??jo,r=(e.style??"card")==="card",s=Wo(t,e,i,r).catch(()=>{});if(r){let o=await hr(t,{timeoutSeconds:e.timeoutSeconds,sound:e.sound,volume:e.volume,theme:e.theme,from:n.from,capture:n.capture,pick:n.pick},i).catch(()=>null);if(o)return o}return await s,Uo(t,e,i)}async function Uo(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=(i+5)*1e3,s=`${t.raised_by}: ${t.title}`,o;if(t.choices?.length){let l=await n("/usr/bin/osascript",Fo(s,rt(t),t.choices),r);if(o=l.stdout.replace(/\n$/,""),!l.ok||!t.choices.includes(o))return{action:"dismiss"};if(!t.draft)return{action:"yes",choice:o}}if(t.draft){let l=o?`${o}
456
+ `)}async function cr(t,e,n={}){let i=n.run??no,r=(e.style??"card")==="card",s=io(t,e,i,r).catch(()=>{});if(r){let o=await tr(t,{timeoutSeconds:e.timeoutSeconds,sound:e.sound,volume:e.volume,theme:e.theme,from:n.from,capture:n.capture,pick:n.pick},i).catch(()=>null);if(o)return o}return await s,oo(t,e,i)}async function oo(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=(i+5)*1e3,s=`${t.raised_by}: ${t.title}`,o;if(t.choices?.length){let l=await n("/usr/bin/osascript",so(s,Qe(t),t.choices),r);if(o=l.stdout.replace(/\n$/,""),!l.ok||!t.choices.includes(o))return{action:"dismiss"};if(!t.draft)return{action:"yes",choice:o}}if(t.draft){let l=o?`${o}
460
457
 
461
- Message (edit it if you like):`:`${rt(t)}
458
+ Message (edit it if you like):`:`${Qe(t)}
462
459
 
463
- Message (edit it if you like):`,d=await n("/usr/bin/osascript",kr(s,l,o?["Cancel","Send"]:["Not now","No","Send"],i,Wt(t.draft,o)),r),p=d.ok?xr(d.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...o?{choice:o}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let a=await n("/usr/bin/osascript",kr(s,rt(t),["Not now","No","Yes"],i),r),c=a.ok?xr(a.stdout):null;return c?.button==="Yes"?{action:"yes"}:c?.button==="No"?{action:"no"}:{action:"dismiss"}}var Bo=24*36e5,it=!1;function zo(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=C(t.root),o=r?Date.parse(r):NaN,a=L(t.root,"pending").filter(l=>Date.parse(l.expires)>e),c=a.find(l=>s.includes(`card:${l.id}`));if(c)return c;for(let l of a){let u=`card:${l.id}`;if(n[u])continue;let d=i[u];if(d&&Date.parse(d)>e)continue;let p=Date.parse(l.created_at);if(!(e-p>Bo&&!(p<=o)))return l}return null}async function fu(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(it)return"busy";let r=zo(e);if(!r)return"none";let s=(t.focus??Dt)();if(s.active)return"held";it=!0;let o=`card:${r.id}`;try{let a=L(e.root,"pending").map(u=>`card:${u.id}`);xn(e.root,o,a,e.now),i(`[approvals] popup: showing ${o} from ${r.raised_by}`);let c=await(t.show??vr)(r,n,{from:t.agentName?.(r.raised_by)});if(c.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${c.why??"no answer"} (${Et(s)} when shown)`),"shown";if(P(e.root,r.id)?.status!=="pending")return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let l=await Cn(e,o,c.action,{by:"operator (popup)",...c.action==="yes"?{choice:c.choice,text:c.text}:{}});return i(l.ok?`[approvals] popup: ${l.message}`:`[approvals] popup: ${o} not recorded: ${l.error}`),"shown"}catch(a){return i(`[approvals] popup failed for ${o}: ${a?.message??a}`),"shown"}finally{it=!1}}function gu(t,e,n){if(!n)return{ok:!1,error:"the Mac popup is off; turn it on with `agentx approvals settings --popup on`"};let i=e.startsWith("card:")?P(t.root,e.slice(5)):null;return i?i.status!=="pending"?{ok:!1,error:`${e} is already ${i.status}`}:(Sn(t.root,e),{ok:!0,message:`${e} will show on the Mac within a minute`}):{ok:!1,error:`no card "${e}"; the popup shows decision cards only`}}import{closeSync as J,createReadStream as Ho,fstatSync as qo,openSync as Ko,realpathSync as $r}from"fs";import{isAbsolute as Go,resolve as Ir,sep as Ar}from"path";var ku="/app-files",Xo=/^[A-Za-z0-9_.:-]{1,64}$/;function Jo(t,e,n=process.cwd()){if(!e||e.length>ne.pathChars||e.includes("\0"))return{ok:!1,status:400,error:"bad file path"};if(e.split(/[\\/]/).includes(".."))return{ok:!1,status:403,error:`the path leaves the workspace: copy the file into ${$e}/ first`};if(!ve(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=$r(Ir(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=$r(Go(e)?e:Ir(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+Ar))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${$e}/ first`};let s=ve(r);return s?{ok:!0,path:r,...s}:{ok:!1,status:415,error:"this type of file is not served"}}function Yo(t,e){let n=t.replace(/[^\x20-\x7e]/g,"_").replace(/["\\;]/g,"_").slice(0,120)||"file";return`${e==="file"?"attachment":"inline"}; filename="${n}"; filename*=UTF-8''${encodeURIComponent(t.slice(0,120))}`}function Zo(t,e,n){return{"Content-Type":t,"Content-Disposition":Yo(e,n),"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; img-src 'self'; media-src 'self'; sandbox","Cache-Control":"private, max-age=3600","Accept-Ranges":"bytes"}}function Qo(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let i,r;return n[1]?(i=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(i=Math.max(0,e-Number(n[2])),r=e-1),i>r||i>=e?"unsatisfiable":{start:i,end:r}}function xu(t,e,n,i){let r=(T,F)=>{e.writeHead(T,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(F))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let s=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!Xo.test(s))return r(400,{error:"bad agent id"});let a=i.workspaceOf(s);if(!a)return r(404,{error:`no agent "${s}" on this computer`});let c=Jo(a,o,i.cwd);if(!c.ok)return i.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${s}: ${c.error}`),r(c.status,{error:c.error});let l;try{l=Ko(c.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let T=qo(l);if(!T.isFile())return J(l),r(404,{error:"not a file"});u=T.size}catch{return J(l),r(404,{error:"file not found"})}if(u>ne.bytes)return J(l),r(413,{error:`the file is larger than ${ne.bytes/1024/1024} MB`});let d=c.path.split(Ar).pop()||"file",p=Zo(c.mime,d,c.kind),f=Qo(t.headers.range,u);if(f==="unsatisfiable"){J(l),e.writeHead(416,{...p,"Content-Range":`bytes */${u}`}),e.end();return}let{start:g,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...p,"Content-Length":String(u?h-g+1:0),...f?{"Content-Range":`bytes ${g}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){J(l),e.end();return}let y=Ho("",{fd:l,start:g,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as Y}from"child_process";import{readFileSync as ea,writeFileSync as ta}from"fs";import{tmpdir as na}from"os";import{join as ra}from"path";bt();var Rr=t=>t&&t!==1?Math.round(175*t):null,he=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function ia(){if(process.env.ELEVENLABS_API_KEY)return process.env.ELEVENLABS_API_KEY;for(let t of[`${process.env.HOME}/.elevenlabs/key`,`${process.env.HOME}/.agentx/elevenlabs-key.txt`])try{let e=ea(t,"utf8").trim();if(e)return e}catch{}return null}function Du(t=ia()){let e=0;return async(n,i)=>{if(n.voice.provider==="system")return null;if(!t){if(n.voice.fallback)return null;throw new Error("ElevenLabs is the voice provider but no key is set")}try{let r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${n.voice.elevenlabs}/stream?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n.text,model_id:"eleven_flash_v2_5",...he(n.voice.rate)?{voice_settings:{speed:he(n.voice.rate)}}:{}}),signal:i});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let s=ra(na(),`agentx-say-${process.pid}-${++e}.mp3`);return ta(s,Buffer.from(await r.arrayBuffer())),s}catch(r){if(i.aborted||!n.voice.fallback)throw r;return V(`elevenlabs:${String(r?.message??r).slice(0,40)}`,`[voice] ElevenLabs failed (${String(r?.message??r).slice(0,160)}); speaking with the system voice`),null}}}function _r(t,e){let n=t.languages&&te(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var sa=(t,e="")=>{let n=_r(t,e),i=Rr(t.rate);return[...n&&!Nn(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function oa(t,e,n){if(!n)return["say",sa(t,e)];let i=_r(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function Eu(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Tu(t=st()){if(t)try{Y("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Pu(t=st()){if(t)try{Y("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function st(t={},e){if(!Pe(t))return null;try{return Vn(e)}catch(n){return V("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
464
- `)[0]}); Siri voices will not switch`),null}}var Lu=(t,e)=>{if(!t){let[n,i]=oa(e.voice,e.text,st()),r=Rr(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=Y(n,i,{stdio:["pipe","ignore","ignore"],env:s});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?Y("afplay",[t],{stdio:"ignore"}):Y("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Cr}from"child_process";import{accessSync as aa,constants as ca,readFileSync as Dr}from"fs";import{homedir as la}from"os";import{basename as H,delimiter as Er,dirname as ua,extname as da,join as ot}from"path";var M={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Tr(t){let e=Array.isArray(t)?t[0]:t;return!e||!/^\d{1,9}$/.test(e.trim())?{status:400,error:"Say how long the recording is (X-Audio-Duration-Ms)."}:Number(e)>M.ms+2e3?{status:413,error:ct()}:null}var ct=()=>`The recording is longer than ${M.ms/6e4} minutes.`,pa={"audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/mp4":"m4a","video/mp4":"m4a","audio/x-m4a":"m4a","audio/aac":"aac","audio/mpeg":"mp3","audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav"};function Pr(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return pa[e]??null}function Lr(t,e){let n=[];return t!=="local"&&e.key&&n.push("elevenlabs"),e.ffmpeg&&(e.mlx?n.push("mlx-whisper"):e.whisper&&n.push("whisper")),n}function lt(t,e){return t==="local"&&e.key&&!e.ffmpeg?"Speech to text is set to local, and this computer has no ffmpeg.":(e.mlx||e.whisper)&&!e.ffmpeg?"This computer has Whisper but no ffmpeg to read the recording.":"Add an ElevenLabs key on this computer, or install mlx-whisper and ffmpeg."}function at(t,e,n=process.env.PATH??""){let i=la(),r=[ot(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Er).filter(Boolean)];for(let s of[e,...r.map(o=>ot(o,t))])if(s)try{return aa(s,ca.X_OK),s}catch{}return null}function Wu(t){return{key:t,mlx:at("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:at("whisper",process.env.AGENTX_WHISPER),ffmpeg:fa()}}var fa=()=>at("ffmpeg",process.env.AGENTX_FFMPEG);async function Or(t,e){return e?ga(t,e):null}async function ga(t,e){let n=String(M.ms/1e3+5);try{let r=[...(await ma(e,["-nostdin","-hide_banner","-t",n,"-i",t,"-f","null","-"],3e4)).matchAll(/time=(\d+):(\d+):(\d+(?:\.\d+)?)/g)],s=r[r.length-1];return s?Number(s[1])*3600+Number(s[2])*60+Number(s[3]):null}catch{return null}}async function Nr(t,e,n,i){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Dr(t)],{type:e}),H(t));let s=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:i??AbortSignal.timeout(6e4)});if(!s.ok)throw new Error(`ElevenLabs ${s.status}: ${(await s.text().catch(()=>"")).slice(0,160)}`);let o=await s.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Mr(t,e,n,i,r){let s=t==="mlx-whisper"?["--model",process.env.AGENTX_MLX_MODEL||"mlx-community/whisper-large-v3-turbo","--output-format","txt","--output-dir",r,n]:[n,"--model",process.env.AGENTX_WHISPER_MODEL||"base","--output_format","txt","--output_dir",r,"--fp16","False"],o={...process.env,PATH:`${ua(i)}${Er}${process.env.PATH??""}`};await ha(e,s,12e4,o);try{return Dr(ot(r,H(n,da(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function ma(t,e,n){return new Promise((i,r)=>{let s=Cr(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${H(t)} took too long`))},n);s.stderr.on("data",c=>{o=(o+c).slice(-8192)}),s.on("error",c=>{clearTimeout(a),r(c)}),s.on("exit",c=>{clearTimeout(a),c===0?i(o):r(new Error(`${H(t)} exited ${c}`))})})}function ha(t,e,n,i=process.env){return new Promise((r,s)=>{let o=Cr(t,e,{stdio:["ignore","pipe","pipe"],env:i}),a="",c="",l=setTimeout(()=>{o.kill("SIGKILL"),s(new Error(`${H(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{c.length<4096&&(c+=u)}),o.on("error",u=>{clearTimeout(l),s(u)}),o.on("exit",u=>{clearTimeout(l),u===0?r(a):s(new Error(`${H(t)} exited ${u}: ${c.trim().split(`
465
- `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as ya,rm as ba,writeFile as wa}from"fs/promises";import{tmpdir as ka}from"os";import{join as jr}from"path";Kr();var xa=64*1024,Sa=2,ut=0;function Yu(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function Zu(t,e,n,i){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?va(t,e,i):Aa(t,e,i)}async function va(t,e,n){let i=String(t.headers["content-type"]||""),r=Pr(i);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=Tr(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),b(e,s.status,{error:s.error});let o=await Vr(t,M.bytes);if(!o)return b(e,413,{error:Ca()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(ut>=Sa)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),c=n.host(),l=Lr(a,c);if(!c.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",p=l.length?"":" "+lt(a,c);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${p}`,setup:!1})}if(!l.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:lt(a,c),setup:!1});ut++;let u;try{let d=await ya(jr(ka(),"agentx-phone-voice-"));try{u=await $a(d,`speech.${r}`,o,i,c,l,n)}finally{await ba(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{ut--}b(e,u[0],u[1])}async function $a(t,e,n,i,r,s,o){let a=jr(t,e);if(await wa(a,n,{mode:384}),r.ffmpeg){let l=await(o.measure??Or)(a,r.ffmpeg);if(l==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(l*1e3>M.ms+2e3)return[413,{error:ct()}]}let c=[];for(let l of s)try{let u=await Ia(l,a,i,r,t,o);return o.log(`[voice] phone recording transcribed with ${l} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:l}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:l}]}catch(u){let d=String(u?.message??u).split(`
466
- `)[0].slice(0,200);c.push(`${l}: ${d}`),o.log(`[voice] phone transcription with ${l} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:c.join("; ")}]}function Ia(t,e,n,i,r,s){let o=s.engines?.[t];if(o)return o(e,n,i,r);if(t==="elevenlabs")return Nr(e,n,i.key);let a=t==="mlx-whisper"?i.mlx:i.whisper;return Mr(t,a,e,i.ffmpeg,r)}async function Aa(t,e,n){let i=await Vr(t,xa);if(!i)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(i.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let s=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!s)return b(e,400,{error:"agent is required"});let a=Ra(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let c=n.voiceOf(s,o);if(!c)return b(e,404,{error:`Unknown agent: ${s}`});let l=(d,p=200)=>b(e,p,{fallback:"browser",reason:d,text:a});if(c.provider!=="elevenlabs")return l("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return l("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??_a)(u,c,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(d)}catch(d){return n.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
467
- `)[0].slice(0,160)}`),l("ElevenLabs could not speak this answer.",502)}}function Ra(t,e){let n=lr(Ct(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return wt(n,e)}async function _a(t,e,n){let i=he(e.rate),r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(e.elevenlabs)}?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n,model_id:"eleven_flash_v2_5",...i?{voice_settings:{speed:i}}:{}}),signal:AbortSignal.timeout(6e4)});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text().catch(()=>"")).slice(0,160)}`);return Buffer.from(await r.arrayBuffer())}var Ca=()=>`The recording is larger than ${M.bytes/1024/1024} MB, more than ${M.ms/6e4} minutes of speech.`;function Qu(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Be(We(t,r,n.voice)):null}function Vr(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,i)=>{let r=[],s=0;t.on("data",o=>{if(!(s>e)){if(s+=o.length,s>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{s<=e&&n(Buffer.concat(r))}),t.on("error",i)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as $,readFileSync as gt,writeFileSync as mt,mkdirSync as ye,readdirSync as ft,rmSync as Da,statSync as R}from"fs";import{resolve as Wr,relative as Ea,dirname as ht,join as W,extname as Z,basename as yt}from"path";var S=200*1024,Fr=new Set([".md",".markdown",".txt"]),q=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),Ta=6,Pa=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function E(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Wr(t);if($(n)||ye(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let i=Wr(n,e);if(Ea(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Ur(t){let e=Z(t).toLowerCase();if(!Fr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function dt(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function rd(t){let e=E(t,"."),n=[],i=new Set,r=[];try{r=ft(e)}catch{}for(let a of Pa){let c=W(e,a);if($(c)&&R(c).isFile()){let l=R(c).size,u=l>0&&l<S?pt(c):"";n.push({path:a,title:dt(u,a),size:l,exists:!0}),i.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),i.add(a)}for(let a of r){if(i.has(a))continue;let c=W(e,a);try{let l=R(c);if(!l.isFile()||!Fr.has(Z(a).toLowerCase()))continue;let u=l.size>0&&l.size<S?pt(c):"";n.push({path:a,title:dt(u,a),size:l.size,exists:!0})}catch{}}let s=[],o=W(e,".claude","skills");if($(o))try{for(let a of ft(o)){let c=W(o,a),l;try{l=R(c)}catch{continue}if(!l.isDirectory())continue;let u=W(c,"SKILL.md");if(!$(u))continue;let d=R(u),p=d.size<S?pt(u):"";s.push({slug:a,title:dt(p,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return s.sort((a,c)=>a.slug.localeCompare(c.slug)),{identity:n,skills:s,workspace:e}}function pt(t){try{return gt(t,"utf-8")}catch{return""}}function id(t,e){let n=E(t,e);if(Ur(n),!$(n))return{path:e,content:""};if(R(n).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:gt(n,"utf-8")}}function sd(t,e,n){let i=E(t,e);Ur(i);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return ye(ht(i),{recursive:!0}),mt(i,r),{path:e,bytes:r.length}}function od(t,e,n={}){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Skill slug must be lowercase (letters, digits, -, _) and start with a letter or digit.");let i=`.claude/skills/${e}/SKILL.md`,r=E(t,i);if($(r))throw new Error(`Skill "${e}" already exists.`);ye(ht(r),{recursive:!0});let s=n.content?.trim()?n.content:La(e,n.title);return mt(r,s),{slug:e,path:i}}function ad(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);if(!R(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return Da(n,{recursive:!0,force:!0}),{slug:e}}function cd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=[];return r(n,"",0,i),i.sort((s,o)=>s.kind!==o.kind?s.kind==="dir"?-1:1:s.path.localeCompare(o.path)),i;function r(s,o,a,c){if(a>Ta)return;let l=[];try{l=ft(s)}catch{return}for(let u of l){if(u==="node_modules"||u===".git")continue;let d=W(s,u),p=o?`${o}/${u}`:u,f;try{f=R(d)}catch{continue}if(f.isDirectory())c.push({path:`${p}/`,kind:"dir",size:0,editable:!1}),r(d,p,a+1,c);else if(f.isFile()){let g=Z(u).toLowerCase(),h=q.has(g)||q.has(u.toLowerCase());c.push({path:p,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function ld(t,e,n){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let i=E(t,`.claude/skills/${e}/${n}`);if(!$(i)||!R(i).isFile())throw new Error(`File not found: ${n}`);let r=Z(i).toLowerCase(),s=yt(i).toLowerCase();if(!q.has(r)&&!q.has(s))throw new Error(`File type not editable: ${n}`);if(R(i).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:gt(i,"utf-8")}}function ud(t,e,n,i){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let r=E(t,`.claude/skills/${e}/${n}`),s=Z(r).toLowerCase(),o=yt(r).toLowerCase();if(!q.has(s)&&!q.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(i,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return ye(ht(r),{recursive:!0}),mt(r,a),{path:n,bytes:a.length}}function dd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=r=>$(W(n,r));return i("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:i("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:i("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:i("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:i("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function La(t,e){return`# ${e?.trim()||t}
460
+ Message (edit it if you like):`,d=await n("/usr/bin/osascript",sr(s,l,o?["Cancel","Send"]:["Not now","No","Send"],i,Mt(t.draft,o)),r),p=d.ok?or(d.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...o?{choice:o}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let a=await n("/usr/bin/osascript",sr(s,Qe(t),["Not now","No","Yes"],i),r),c=a.ok?or(a.stdout):null;return c?.button==="Yes"?{action:"yes"}:c?.button==="No"?{action:"no"}:{action:"dismiss"}}var ao=24*36e5,et=!1;function co(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=R(t.root),o=r?Date.parse(r):NaN,a=U(t.root,"pending").filter(l=>Date.parse(l.expires)>e),c=a.find(l=>s.includes(`card:${l.id}`));if(c)return c;for(let l of a){let u=`card:${l.id}`;if(n[u])continue;let d=i[u];if(d&&Date.parse(d)>e)continue;let p=Date.parse(l.created_at);if(!(e-p>ao&&!(p<=o)))return l}return null}async function ml(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(et)return"busy";let r=co(e);if(!r)return"none";let s=(t.focus??It)();if(s.active)return"held";et=!0;let o=`card:${r.id}`;try{let a=U(e.root,"pending").map(u=>`card:${u.id}`);on(e.root,o,a,e.now),i(`[approvals] popup: showing ${o} from ${r.raised_by}`);let c=await(t.show??cr)(r,n,{from:t.agentName?.(r.raised_by)});if(c.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${c.why??"no answer"} (${Rt(s)} when shown)`),"shown";if(B(e.root,r.id)?.status!=="pending")return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let l=await gn(e,o,c.action,{by:"operator (popup)",...c.action==="yes"?{choice:c.choice,text:c.text}:{}});return i(l.ok?`[approvals] popup: ${l.message}`:`[approvals] popup: ${o} not recorded: ${l.error}`),"shown"}catch(a){return i(`[approvals] popup failed for ${o}: ${a?.message??a}`),"shown"}finally{et=!1}}function hl(t,e,n){if(!n)return{ok:!1,error:"the Mac popup is off; turn it on with `agentx approvals settings --popup on`"};let i=e.startsWith("card:")?B(t.root,e.slice(5)):null;return i?i.status!=="pending"?{ok:!1,error:`${e} is already ${i.status}`}:(an(t.root,e),{ok:!0,message:`${e} will show on the Mac within a minute`}):{ok:!1,error:`no card "${e}"; the popup shows decision cards only`}}import{closeSync as K,createReadStream as lo,fstatSync as uo,openSync as po,realpathSync as lr}from"fs";import{isAbsolute as fo,resolve as ur,sep as dr}from"path";var Sl="/app-files",go=/^[A-Za-z0-9_.:-]{1,64}$/;function mo(t,e,n=process.cwd()){if(!e||e.length>Q.pathChars||e.includes("\0"))return{ok:!1,status:400,error:"bad file path"};if(e.split(/[\\/]/).includes(".."))return{ok:!1,status:403,error:`the path leaves the workspace: copy the file into ${ke}/ first`};if(!we(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=lr(ur(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=lr(fo(e)?e:ur(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+dr))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${ke}/ first`};let s=we(r);return s?{ok:!0,path:r,...s}:{ok:!1,status:415,error:"this type of file is not served"}}function ho(t,e){let n=t.replace(/[^\x20-\x7e]/g,"_").replace(/["\\;]/g,"_").slice(0,120)||"file";return`${e==="file"?"attachment":"inline"}; filename="${n}"; filename*=UTF-8''${encodeURIComponent(t.slice(0,120))}`}function yo(t,e,n){return{"Content-Type":t,"Content-Disposition":ho(e,n),"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; img-src 'self'; media-src 'self'; sandbox","Cache-Control":"private, max-age=3600","Accept-Ranges":"bytes"}}function bo(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let i,r;return n[1]?(i=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(i=Math.max(0,e-Number(n[2])),r=e-1),i>r||i>=e?"unsatisfiable":{start:i,end:r}}function vl(t,e,n,i){let r=(D,N)=>{e.writeHead(D,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(N))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let s=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!go.test(s))return r(400,{error:"bad agent id"});let a=i.workspaceOf(s);if(!a)return r(404,{error:`no agent "${s}" on this computer`});let c=mo(a,o,i.cwd);if(!c.ok)return i.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${s}: ${c.error}`),r(c.status,{error:c.error});let l;try{l=po(c.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let D=uo(l);if(!D.isFile())return K(l),r(404,{error:"not a file"});u=D.size}catch{return K(l),r(404,{error:"file not found"})}if(u>Q.bytes)return K(l),r(413,{error:`the file is larger than ${Q.bytes/1024/1024} MB`});let d=c.path.split(dr).pop()||"file",p=yo(c.mime,d,c.kind),f=bo(t.headers.range,u);if(f==="unsatisfiable"){K(l),e.writeHead(416,{...p,"Content-Range":`bytes */${u}`}),e.end();return}let{start:g,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...p,"Content-Length":String(u?h-g+1:0),...f?{"Content-Range":`bytes ${g}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){K(l),e.end();return}let y=lo("",{fd:l,start:g,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as G}from"child_process";import{readFileSync as wo,writeFileSync as ko}from"fs";import{tmpdir as xo}from"os";import{join as So}from"path";gt();var pr=t=>t&&t!==1?Math.round(175*t):null,pe=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function vo(){if(process.env.ELEVENLABS_API_KEY)return process.env.ELEVENLABS_API_KEY;for(let t of[`${process.env.HOME}/.elevenlabs/key`,`${process.env.HOME}/.agentx/elevenlabs-key.txt`])try{let e=wo(t,"utf8").trim();if(e)return e}catch{}return null}function Tl(t=vo()){let e=0;return async(n,i)=>{if(n.voice.provider==="system")return null;if(!t){if(n.voice.fallback)return null;throw new Error("ElevenLabs is the voice provider but no key is set")}try{let r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${n.voice.elevenlabs}/stream?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n.text,model_id:"eleven_flash_v2_5",...pe(n.voice.rate)?{voice_settings:{speed:pe(n.voice.rate)}}:{}}),signal:i});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let s=So(xo(),`agentx-say-${process.pid}-${++e}.mp3`);return ko(s,Buffer.from(await r.arrayBuffer())),s}catch(r){if(i.aborted||!n.voice.fallback)throw r;return M(`elevenlabs:${String(r?.message??r).slice(0,40)}`,`[voice] ElevenLabs failed (${String(r?.message??r).slice(0,160)}); speaking with the system voice`),null}}}function fr(t,e){let n=t.languages&&Z(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var $o=(t,e="")=>{let n=fr(t,e),i=pr(t.rate);return[...n&&!xn(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function Ao(t,e,n){if(!n)return["say",$o(t,e)];let i=fr(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function Pl(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Ll(t=tt()){if(t)try{G("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Ml(t=tt()){if(t)try{G("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function tt(t={},e){if(!Ce(t))return null;try{return $n(e)}catch(n){return M("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
461
+ `)[0]}); Siri voices will not switch`),null}}var Ol=(t,e)=>{if(!t){let[n,i]=Ao(e.voice,e.text,tt()),r=pr(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=G(n,i,{stdio:["pipe","ignore","ignore"],env:s});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?G("afplay",[t],{stdio:"ignore"}):G("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as gr}from"child_process";import{accessSync as Io,constants as Ro,readFileSync as mr}from"fs";import{homedir as _o}from"os";import{basename as W,delimiter as hr,dirname as Co,extname as Do,join as nt}from"path";var P={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function yr(t){let e=Array.isArray(t)?t[0]:t;return!e||!/^\d{1,9}$/.test(e.trim())?{status:400,error:"Say how long the recording is (X-Audio-Duration-Ms)."}:Number(e)>P.ms+2e3?{status:413,error:it()}:null}var it=()=>`The recording is longer than ${P.ms/6e4} minutes.`,Eo={"audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/mp4":"m4a","video/mp4":"m4a","audio/x-m4a":"m4a","audio/aac":"aac","audio/mpeg":"mp3","audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav"};function br(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return Eo[e]??null}function wr(t,e){let n=[];return t!=="local"&&e.key&&n.push("elevenlabs"),e.ffmpeg&&(e.mlx?n.push("mlx-whisper"):e.whisper&&n.push("whisper")),n}function st(t,e){return t==="local"&&e.key&&!e.ffmpeg?"Speech to text is set to local, and this computer has no ffmpeg.":(e.mlx||e.whisper)&&!e.ffmpeg?"This computer has Whisper but no ffmpeg to read the recording.":"Add an ElevenLabs key on this computer, or install mlx-whisper and ffmpeg."}function rt(t,e,n=process.env.PATH??""){let i=_o(),r=[nt(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(hr).filter(Boolean)];for(let s of[e,...r.map(o=>nt(o,t))])if(s)try{return Io(s,Ro.X_OK),s}catch{}return null}function Bl(t){return{key:t,mlx:rt("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:rt("whisper",process.env.AGENTX_WHISPER),ffmpeg:To()}}var To=()=>rt("ffmpeg",process.env.AGENTX_FFMPEG);async function kr(t,e){return e?Po(t,e):null}async function Po(t,e){let n=String(P.ms/1e3+5);try{let r=[...(await Lo(e,["-nostdin","-hide_banner","-t",n,"-i",t,"-f","null","-"],3e4)).matchAll(/time=(\d+):(\d+):(\d+(?:\.\d+)?)/g)],s=r[r.length-1];return s?Number(s[1])*3600+Number(s[2])*60+Number(s[3]):null}catch{return null}}async function xr(t,e,n,i){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([mr(t)],{type:e}),W(t));let s=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:i??AbortSignal.timeout(6e4)});if(!s.ok)throw new Error(`ElevenLabs ${s.status}: ${(await s.text().catch(()=>"")).slice(0,160)}`);let o=await s.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Sr(t,e,n,i,r){let s=t==="mlx-whisper"?["--model",process.env.AGENTX_MLX_MODEL||"mlx-community/whisper-large-v3-turbo","--output-format","txt","--output-dir",r,n]:[n,"--model",process.env.AGENTX_WHISPER_MODEL||"base","--output_format","txt","--output_dir",r,"--fp16","False"],o={...process.env,PATH:`${Co(i)}${hr}${process.env.PATH??""}`};await Mo(e,s,12e4,o);try{return mr(nt(r,W(n,Do(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function Lo(t,e,n){return new Promise((i,r)=>{let s=gr(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${W(t)} took too long`))},n);s.stderr.on("data",c=>{o=(o+c).slice(-8192)}),s.on("error",c=>{clearTimeout(a),r(c)}),s.on("exit",c=>{clearTimeout(a),c===0?i(o):r(new Error(`${W(t)} exited ${c}`))})})}function Mo(t,e,n,i=process.env){return new Promise((r,s)=>{let o=gr(t,e,{stdio:["ignore","pipe","pipe"],env:i}),a="",c="",l=setTimeout(()=>{o.kill("SIGKILL"),s(new Error(`${W(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{c.length<4096&&(c+=u)}),o.on("error",u=>{clearTimeout(l),s(u)}),o.on("exit",u=>{clearTimeout(l),u===0?r(a):s(new Error(`${W(t)} exited ${u}: ${c.trim().split(`
462
+ `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as Oo,rm as No,writeFile as jo}from"fs/promises";import{tmpdir as Vo}from"os";import{join as vr}from"path";Tr();var Wo=64*1024,Fo=2,ot=0;function Ql(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function eu(t,e,n,i){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?Bo(t,e,i):Ho(t,e,i)}async function Bo(t,e,n){let i=String(t.headers["content-type"]||""),r=br(i);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=yr(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),b(e,s.status,{error:s.error});let o=await $r(t,P.bytes);if(!o)return b(e,413,{error:Go()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(ot>=Fo)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),c=n.host(),l=wr(a,c);if(!c.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",p=l.length?"":" "+st(a,c);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${p}`,setup:!1})}if(!l.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:st(a,c),setup:!1});ot++;let u;try{let d=await Oo(vr(Vo(),"agentx-phone-voice-"));try{u=await Uo(d,`speech.${r}`,o,i,c,l,n)}finally{await No(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{ot--}b(e,u[0],u[1])}async function Uo(t,e,n,i,r,s,o){let a=vr(t,e);if(await jo(a,n,{mode:384}),r.ffmpeg){let l=await(o.measure??kr)(a,r.ffmpeg);if(l==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(l*1e3>P.ms+2e3)return[413,{error:it()}]}let c=[];for(let l of s)try{let u=await zo(l,a,i,r,t,o);return o.log(`[voice] phone recording transcribed with ${l} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:l}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:l}]}catch(u){let d=String(u?.message??u).split(`
463
+ `)[0].slice(0,200);c.push(`${l}: ${d}`),o.log(`[voice] phone transcription with ${l} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:c.join("; ")}]}function zo(t,e,n,i,r,s){let o=s.engines?.[t];if(o)return o(e,n,i,r);if(t==="elevenlabs")return xr(e,n,i.key);let a=t==="mlx-whisper"?i.mlx:i.whisper;return Sr(t,a,e,i.ffmpeg,r)}async function Ho(t,e,n){let i=await $r(t,Wo);if(!i)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(i.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let s=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!s)return b(e,400,{error:"agent is required"});let a=qo(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let c=n.voiceOf(s,o);if(!c)return b(e,404,{error:`Unknown agent: ${s}`});let l=(d,p=200)=>b(e,p,{fallback:"browser",reason:d,text:a});if(c.provider!=="elevenlabs")return l("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return l("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??Ko)(u,c,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(d)}catch(d){return n.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
464
+ `)[0].slice(0,160)}`),l("ElevenLabs could not speak this answer.",502)}}function qo(t,e){let n=Gn(At(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return mt(n,e)}async function Ko(t,e,n){let i=pe(e.rate),r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(e.elevenlabs)}?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n,model_id:"eleven_flash_v2_5",...i?{voice_settings:{speed:i}}:{}}),signal:AbortSignal.timeout(6e4)});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text().catch(()=>"")).slice(0,160)}`);return Buffer.from(await r.arrayBuffer())}var Go=()=>`The recording is larger than ${P.bytes/1024/1024} MB, more than ${P.ms/6e4} minutes of speech.`;function tu(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Ve(Oe(t,r,n.voice)):null}function $r(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,i)=>{let r=[],s=0;t.on("data",o=>{if(!(s>e)){if(s+=o.length,s>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{s<=e&&n(Buffer.concat(r))}),t.on("error",i)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as v,readFileSync as ut,writeFileSync as dt,mkdirSync as fe,readdirSync as lt,rmSync as Xo,statSync as A}from"fs";import{resolve as Ar,relative as Jo,dirname as pt,join as O,extname as X,basename as ft}from"path";var x=200*1024,Ir=new Set([".md",".markdown",".txt"]),F=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),Yo=6,Zo=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function C(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Ar(t);if(v(n)||fe(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let i=Ar(n,e);if(Jo(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Rr(t){let e=X(t).toLowerCase();if(!Ir.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function at(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function su(t){let e=C(t,"."),n=[],i=new Set,r=[];try{r=lt(e)}catch{}for(let a of Zo){let c=O(e,a);if(v(c)&&A(c).isFile()){let l=A(c).size,u=l>0&&l<x?ct(c):"";n.push({path:a,title:at(u,a),size:l,exists:!0}),i.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),i.add(a)}for(let a of r){if(i.has(a))continue;let c=O(e,a);try{let l=A(c);if(!l.isFile()||!Ir.has(X(a).toLowerCase()))continue;let u=l.size>0&&l.size<x?ct(c):"";n.push({path:a,title:at(u,a),size:l.size,exists:!0})}catch{}}let s=[],o=O(e,".claude","skills");if(v(o))try{for(let a of lt(o)){let c=O(o,a),l;try{l=A(c)}catch{continue}if(!l.isDirectory())continue;let u=O(c,"SKILL.md");if(!v(u))continue;let d=A(u),p=d.size<x?ct(u):"";s.push({slug:a,title:at(p,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return s.sort((a,c)=>a.slug.localeCompare(c.slug)),{identity:n,skills:s,workspace:e}}function ct(t){try{return ut(t,"utf-8")}catch{return""}}function ou(t,e){let n=C(t,e);if(Rr(n),!v(n))return{path:e,content:""};if(A(n).size>x)throw new Error(`File is too large to edit in the admin panel (> ${x/1024} KB).`);return{path:e,content:ut(n,"utf-8")}}function au(t,e,n){let i=C(t,e);Rr(i);let r=Buffer.from(n,"utf-8");if(r.length>x)throw new Error(`File too large (${r.length} > ${x} bytes).`);return fe(pt(i),{recursive:!0}),dt(i,r),{path:e,bytes:r.length}}function cu(t,e,n={}){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Skill slug must be lowercase (letters, digits, -, _) and start with a letter or digit.");let i=`.claude/skills/${e}/SKILL.md`,r=C(t,i);if(v(r))throw new Error(`Skill "${e}" already exists.`);fe(pt(r),{recursive:!0});let s=n.content?.trim()?n.content:Qo(e,n.title);return dt(r,s),{slug:e,path:i}}function lu(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=C(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);if(!A(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return Xo(n,{recursive:!0,force:!0}),{slug:e}}function uu(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=C(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let i=[];return r(n,"",0,i),i.sort((s,o)=>s.kind!==o.kind?s.kind==="dir"?-1:1:s.path.localeCompare(o.path)),i;function r(s,o,a,c){if(a>Yo)return;let l=[];try{l=lt(s)}catch{return}for(let u of l){if(u==="node_modules"||u===".git")continue;let d=O(s,u),p=o?`${o}/${u}`:u,f;try{f=A(d)}catch{continue}if(f.isDirectory())c.push({path:`${p}/`,kind:"dir",size:0,editable:!1}),r(d,p,a+1,c);else if(f.isFile()){let g=X(u).toLowerCase(),h=F.has(g)||F.has(u.toLowerCase());c.push({path:p,kind:"file",size:f.size,editable:h&&f.size<x})}}}}function du(t,e,n){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let i=C(t,`.claude/skills/${e}/${n}`);if(!v(i)||!A(i).isFile())throw new Error(`File not found: ${n}`);let r=X(i).toLowerCase(),s=ft(i).toLowerCase();if(!F.has(r)&&!F.has(s))throw new Error(`File type not editable: ${n}`);if(A(i).size>x)throw new Error(`File too large to edit (> ${x/1024} KB): ${n}`);return{path:n,content:ut(i,"utf-8")}}function pu(t,e,n,i){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let r=C(t,`.claude/skills/${e}/${n}`),s=X(r).toLowerCase(),o=ft(r).toLowerCase();if(!F.has(s)&&!F.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(i,"utf-8");if(a.length>x)throw new Error(`File too large (${a.length} > ${x} bytes).`);return fe(pt(r),{recursive:!0}),dt(r,a),{path:n,bytes:a.length}}function fu(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=C(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let i=r=>v(O(n,r));return i("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:i("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:i("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:i("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:i("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function Qo(t,e){return`# ${e?.trim()||t}
468
465
 
469
466
  Describe what this skill does and when the agent should use it. Keep it under ~5 lines \u2014 the agent reads this to decide whether to invoke the skill.
470
467
 
@@ -477,7 +474,7 @@ Document the arguments, commands, or files the skill expects. Example:
477
474
 
478
475
  \`\`\`bash
479
476
  # Example invocation
480
- claude-code ${yt(t)} --arg value
477
+ claude-code ${ft(t)} --arg value
481
478
  \`\`\`
482
- `}It();var Br={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function zr(t){return{...Br,...t??{},regions:{...t?.regions??{}},buffer:{...Br.buffer,...t?.buffer??{}}}}function gd(t){try{return zr($t(t).screen)}catch{return zr(void 0)}}var Oa=/^[a-z][\w-]*$/,Hr=["window","screen","menubar","notifications"];function Q(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)=>Q(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function qr(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 md(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=Q(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Q(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(!Oa.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);o===null?delete r[s]:r[s]=qr(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=Q(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Q(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&&!Hr.includes(i)&&!n.regions?.[i])try{qr(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Hr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{Gt as a,ja as b,et as c,uo as d,po as e,Ol as f,Nl as g,Ml as h,lr as i,Vl as j,Fl as k,N as l,ur as m,x as n,Ua as o,nn as p,Ka as q,rn as r,Ga as s,gn as t,A as u,U as v,hn as w,P as x,uc as y,dc as z,pc as A,fc as B,gc as C,Ya as D,_i as E,rc as F,pn as G,C as H,wc as I,kc as J,vn as K,Ac as L,Rn as M,Wc as N,Cn as O,vr as P,fu as Q,gu as R,ku as S,Zo as T,xu as U,Uc as V,Bc as W,zc as X,Hc as Y,qc as Z,Kc as _,Xc as $,Jc as aa,sl as ba,Ne as ca,ol as da,al as ea,G as fa,X as ga,ia as ha,Du as ia,Eu as ja,Tu as ka,Pu as la,st as ma,Lu as na,Ve as oa,We as pa,fe as qa,Ds as ra,Ts as sa,pl as ta,Ue as ua,Be as va,Ps as wa,Ls as xa,Xn as ya,Qn as za,fl as Aa,Ms as Ba,gl as Ca,Hs as Da,Gs as Ea,ze as Fa,Js as Ga,er as Ha,M as Ia,Tr as Ja,Pr as Ka,Lr as La,Wu as Ma,fa as Na,Nr as Oa,Mr as Pa,Yu as Qa,Zu as Ra,Ca as Sa,Qu as Ta,Vr as Ua,ge as Va,Al as Wa,or as Xa,He as Ya,Ze as Za,Pl as _a,rd as $a,id as ab,sd as bb,od as cb,ad as db,cd as eb,ld as fb,ud as gb,dd as hb,Br as ib,zr as jb,gd as kb,Hr as lb,md as mb};
483
- //# sourceMappingURL=chunk-E3SVSIUU.js.map
479
+ `}xt();var _r={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Cr(t){return{..._r,...t??{},regions:{...t?.regions??{}},buffer:{..._r.buffer,...t?.buffer??{}}}}function hu(t){try{return Cr(kt(t).screen)}catch{return Cr(void 0)}}var ea=/^[a-z][\w-]*$/,Dr=["window","screen","menubar","notifications"];function J(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 ge=(t,e)=>J(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function Er(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 yu(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=ge(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=ge(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=ge(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=J(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=J(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(!ea.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);o===null?delete r[s]:r[s]=Er(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=J(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=J(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=ge(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&&!Dr.includes(i)&&!n.regions?.[i])try{Er(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Dr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{Bt as a,ra as b,Je as c,Cs as d,Ds as e,Nc as f,jc as g,Vc as h,Gn as i,Fc as j,Uc as k,T as l,Xn as m,k as n,aa as o,ua as p,ii as q,ha as r,nn as s,R as t,xa as u,Sa as v,cn as w,_a as x,pn as y,Ba as z,gn as A,cr as B,ml as C,hl as D,Sl as E,yo as F,vl as G,za as H,Ha as I,qa as J,Ka as K,Ga as L,Xa as M,Ya as N,Za as O,ac as P,Te as Q,cc as R,lc as S,H as T,q as U,vo as V,Tl as W,Pl as X,Ll as Y,Ml as Z,tt as _,Ol as $,Me as aa,Oe as ba,le as ca,Xi as da,Yi as ea,gc as fa,je as ga,Ve as ha,Zi as ia,Qi as ja,Ln as ka,jn as la,mc as ma,ns as na,hc as oa,us as pa,fs as qa,We as ra,ms as sa,Vn as ta,P as ua,yr as va,br as wa,wr as xa,Bl as ya,To as za,xr as Aa,Sr as Ba,Ql as Ca,eu as Da,Go as Ea,tu as Fa,$r as Ga,ue as Ha,_c as Ia,Hn as Ja,Fe as Ka,Ge as La,Mc as Ma,su as Na,ou as Oa,au as Pa,cu as Qa,lu as Ra,uu as Sa,du as Ta,pu as Ua,fu as Va,_r as Wa,Cr as Xa,hu as Ya,Dr as Za,yu as _a};
480
+ //# sourceMappingURL=chunk-5NTGUHOO.js.map