agentix-cli 0.147.0 → 0.149.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/dist/{App-AW4OROPH.js → App-2O2UUZGG.js} +2 -2
  2. package/dist/{ChatApp-USXQHII3.js → ChatApp-YU4NF63L.js} +2 -2
  3. package/dist/{absorb-eval-WZCC5VPS.js → absorb-eval-WHWOJYDX.js} +2 -2
  4. package/dist/{agent-TJ2K7FZG.js → agent-NLCR6VBE.js} +2 -2
  5. package/dist/{board-dashboard-JY4YQ5TM.js → board-dashboard-VPDXHHWC.js} +5 -5
  6. package/dist/{board-dashboard-JY4YQ5TM.js.map → board-dashboard-VPDXHHWC.js.map} +1 -1
  7. package/dist/{chunk-PUW4C6YO.js → chunk-2MW32M2D.js} +2 -2
  8. package/dist/{chunk-JLEVL66V.js → chunk-3HVRWULP.js} +2 -2
  9. package/dist/{chunk-7ICJCJ43.js → chunk-5IHUZVPU.js} +2 -2
  10. package/dist/{chunk-GJMYG53S.js → chunk-5QXRPYOY.js} +2 -2
  11. package/dist/{chunk-EG7Y2XLK.js → chunk-6QFDFYI7.js} +2 -2
  12. package/dist/{chunk-7HCSLOTP.js → chunk-6TJNWUMA.js} +3 -3
  13. package/dist/{chunk-P6PFTNN4.js → chunk-6YNRLI6I.js} +2 -2
  14. package/dist/chunk-A76PNG4E.js +4 -0
  15. package/dist/chunk-A76PNG4E.js.map +1 -0
  16. package/dist/{chunk-4F5XUF6T.js → chunk-AONY6U45.js} +2 -2
  17. package/dist/{chunk-7T6SMNVY.js → chunk-ATCIRFH6.js} +2 -2
  18. package/dist/{chunk-KW6SHOAN.js → chunk-BZ6Y264Z.js} +2 -2
  19. package/dist/{chunk-UVF3K5YS.js → chunk-DWOERPBG.js} +2 -2
  20. package/dist/{chunk-E7YHXMJG.js → chunk-E7LPZAXP.js} +2 -2
  21. package/dist/{chunk-Q2QU32JP.js → chunk-EIY2HRAS.js} +2 -2
  22. package/dist/{chunk-EKAUOUN2.js → chunk-GMMRBTLQ.js} +2 -2
  23. package/dist/{chunk-QXPX2NGL.js → chunk-GRI5HOPC.js} +2 -2
  24. package/dist/{chunk-P5BFFU4Y.js → chunk-IGA3T3ZT.js} +2 -2
  25. package/dist/{chunk-MMBFAVBR.js → chunk-JOHDOEZ4.js} +2 -2
  26. package/dist/chunk-MNG2AMKZ.js +3 -0
  27. package/dist/chunk-MNG2AMKZ.js.map +1 -0
  28. package/dist/{chunk-MXDTLR45.js → chunk-NMYC5RW7.js} +2 -2
  29. package/dist/{chunk-YE2X3AFU.js → chunk-NW4N67TU.js} +2 -2
  30. package/dist/{chunk-5TGY4RIQ.js → chunk-OWMKQ4HZ.js} +2 -2
  31. package/dist/{chunk-HAEI2LNC.js → chunk-P34VSROA.js} +2 -2
  32. package/dist/{chunk-6UP5VD3H.js → chunk-PXKIPU27.js} +3 -3
  33. package/dist/chunk-PXKIPU27.js.map +1 -0
  34. package/dist/{chunk-JCFVH3NC.js → chunk-QZ6VBDMX.js} +40 -40
  35. package/dist/chunk-QZ6VBDMX.js.map +1 -0
  36. package/dist/{chunk-GTOQWMRY.js → chunk-S22IBRY6.js} +2 -2
  37. package/dist/{chunk-GLLHUHX2.js → chunk-UZWF7PFH.js} +2 -2
  38. package/dist/chunk-WGPMUWX7.js +35 -0
  39. package/dist/chunk-WGPMUWX7.js.map +1 -0
  40. package/dist/chunk-X7UQY7CH.js +5 -0
  41. package/dist/chunk-X7UQY7CH.js.map +1 -0
  42. package/dist/{chunk-ZZNAR6R2.js → chunk-XNS5OQ3U.js} +212 -212
  43. package/dist/chunk-XNS5OQ3U.js.map +1 -0
  44. package/dist/{chunk-7W3TLSZQ.js → chunk-Z7GEW2SR.js} +5 -5
  45. package/dist/cli.js +1 -1
  46. package/dist/{client-GLBNS45C.js → client-A2N6ETK2.js} +2 -2
  47. package/dist/{config-VRDFC7LW.js → config-2QM2WTI2.js} +2 -2
  48. package/dist/{config-mutate-HU3KKYCD.js → config-mutate-UJS4F7BT.js} +2 -2
  49. package/dist/config-mutator-VWR3SMD3.js +2 -0
  50. package/dist/{contributions-JXPYCLVB.js → contributions-43FWZOGF.js} +2 -2
  51. package/dist/{doctor-5Y7QSXNQ.js → doctor-IN6MWP6I.js} +2 -2
  52. package/dist/{follow-up-tool-53AYA2UQ.js → follow-up-tool-VB7K6HCL.js} +2 -2
  53. package/dist/{grants-O7SJ2J4B.js → grants-2S33F2LV.js} +2 -2
  54. package/dist/{hub-YCOUZFNU.js → hub-JNNNUAZM.js} +2 -2
  55. package/dist/index.d.ts +44 -0
  56. package/dist/index.js +1 -1
  57. package/dist/index.js.map +1 -1
  58. package/dist/note-tool-EZWSB3J3.js +2 -0
  59. package/dist/note-tool-EZWSB3J3.js.map +1 -0
  60. package/dist/{program-CIJEGFYG.js → program-OTENO5DS.js} +174 -174
  61. package/dist/program-OTENO5DS.js.map +1 -0
  62. package/dist/{promote-THTEHZHU.js → promote-VFYVWVTL.js} +2 -2
  63. package/dist/{query-N7JBDLR7.js → query-RB2MU2HV.js} +2 -2
  64. package/dist/{query-settings-BJTVDDCH.js → query-settings-5B54WHCS.js} +2 -2
  65. package/dist/{registry-LJ66OZYJ.js → registry-6OX7U6FV.js} +2 -2
  66. package/dist/{request-planner-PCELXLK7.js → request-planner-TUHVEYSF.js} +2 -2
  67. package/dist/{review-candidates-EMJUROJH.js → review-candidates-FDYTGG2N.js} +2 -2
  68. package/dist/{routing-D2KNBEMG.js → routing-U35SFPEI.js} +2 -2
  69. package/dist/schedule-tool-EPQKUYJX.js +2 -0
  70. package/dist/{scheduler-73UEBYV4.js → scheduler-H2QHWNQ2.js} +2 -2
  71. package/dist/{seat-UFAMWG7M.js → seat-EB3KJMIE.js} +2 -2
  72. package/dist/{select-EPWELLAV.js → select-IU4IOVSO.js} +2 -2
  73. package/dist/{set-enabled-LS65QZQS.js → set-enabled-64BSJ7LR.js} +2 -2
  74. package/dist/{tool-7LKYIA6D.js → tool-B23ACEHV.js} +2 -2
  75. package/dist/{tool-4S3YKLCN.js → tool-W3CIQZJ7.js} +2 -2
  76. package/dist/{wiki-LHT6X2JF.js → wiki-4KMRUD5C.js} +2 -2
  77. package/dist/wiki-enrich-N4GLW2JX.js +2 -0
  78. package/package.json +1 -1
  79. package/dist/chunk-6UP5VD3H.js.map +0 -1
  80. package/dist/chunk-JCFVH3NC.js.map +0 -1
  81. package/dist/chunk-TJZGAKIB.js +0 -4
  82. package/dist/chunk-TJZGAKIB.js.map +0 -1
  83. package/dist/chunk-VY7TBMJU.js +0 -3
  84. package/dist/chunk-VY7TBMJU.js.map +0 -1
  85. package/dist/chunk-Z3AI4KXT.js +0 -18
  86. package/dist/chunk-Z3AI4KXT.js.map +0 -1
  87. package/dist/chunk-ZZNAR6R2.js.map +0 -1
  88. package/dist/config-mutator-JCAIGP6W.js +0 -2
  89. package/dist/program-CIJEGFYG.js.map +0 -1
  90. package/dist/schedule-tool-55MOWHKD.js +0 -2
  91. package/dist/wiki-enrich-CBBS3AC7.js +0 -2
  92. /package/dist/{App-AW4OROPH.js.map → App-2O2UUZGG.js.map} +0 -0
  93. /package/dist/{ChatApp-USXQHII3.js.map → ChatApp-YU4NF63L.js.map} +0 -0
  94. /package/dist/{absorb-eval-WZCC5VPS.js.map → absorb-eval-WHWOJYDX.js.map} +0 -0
  95. /package/dist/{agent-TJ2K7FZG.js.map → agent-NLCR6VBE.js.map} +0 -0
  96. /package/dist/{chunk-PUW4C6YO.js.map → chunk-2MW32M2D.js.map} +0 -0
  97. /package/dist/{chunk-JLEVL66V.js.map → chunk-3HVRWULP.js.map} +0 -0
  98. /package/dist/{chunk-7ICJCJ43.js.map → chunk-5IHUZVPU.js.map} +0 -0
  99. /package/dist/{chunk-GJMYG53S.js.map → chunk-5QXRPYOY.js.map} +0 -0
  100. /package/dist/{chunk-EG7Y2XLK.js.map → chunk-6QFDFYI7.js.map} +0 -0
  101. /package/dist/{chunk-7HCSLOTP.js.map → chunk-6TJNWUMA.js.map} +0 -0
  102. /package/dist/{chunk-P6PFTNN4.js.map → chunk-6YNRLI6I.js.map} +0 -0
  103. /package/dist/{chunk-4F5XUF6T.js.map → chunk-AONY6U45.js.map} +0 -0
  104. /package/dist/{chunk-7T6SMNVY.js.map → chunk-ATCIRFH6.js.map} +0 -0
  105. /package/dist/{chunk-KW6SHOAN.js.map → chunk-BZ6Y264Z.js.map} +0 -0
  106. /package/dist/{chunk-UVF3K5YS.js.map → chunk-DWOERPBG.js.map} +0 -0
  107. /package/dist/{chunk-E7YHXMJG.js.map → chunk-E7LPZAXP.js.map} +0 -0
  108. /package/dist/{chunk-Q2QU32JP.js.map → chunk-EIY2HRAS.js.map} +0 -0
  109. /package/dist/{chunk-EKAUOUN2.js.map → chunk-GMMRBTLQ.js.map} +0 -0
  110. /package/dist/{chunk-QXPX2NGL.js.map → chunk-GRI5HOPC.js.map} +0 -0
  111. /package/dist/{chunk-P5BFFU4Y.js.map → chunk-IGA3T3ZT.js.map} +0 -0
  112. /package/dist/{chunk-MMBFAVBR.js.map → chunk-JOHDOEZ4.js.map} +0 -0
  113. /package/dist/{chunk-MXDTLR45.js.map → chunk-NMYC5RW7.js.map} +0 -0
  114. /package/dist/{chunk-YE2X3AFU.js.map → chunk-NW4N67TU.js.map} +0 -0
  115. /package/dist/{chunk-5TGY4RIQ.js.map → chunk-OWMKQ4HZ.js.map} +0 -0
  116. /package/dist/{chunk-HAEI2LNC.js.map → chunk-P34VSROA.js.map} +0 -0
  117. /package/dist/{chunk-GTOQWMRY.js.map → chunk-S22IBRY6.js.map} +0 -0
  118. /package/dist/{chunk-GLLHUHX2.js.map → chunk-UZWF7PFH.js.map} +0 -0
  119. /package/dist/{chunk-7W3TLSZQ.js.map → chunk-Z7GEW2SR.js.map} +0 -0
  120. /package/dist/{client-GLBNS45C.js.map → client-A2N6ETK2.js.map} +0 -0
  121. /package/dist/{config-VRDFC7LW.js.map → config-2QM2WTI2.js.map} +0 -0
  122. /package/dist/{config-mutate-HU3KKYCD.js.map → config-mutate-UJS4F7BT.js.map} +0 -0
  123. /package/dist/{config-mutator-JCAIGP6W.js.map → config-mutator-VWR3SMD3.js.map} +0 -0
  124. /package/dist/{contributions-JXPYCLVB.js.map → contributions-43FWZOGF.js.map} +0 -0
  125. /package/dist/{doctor-5Y7QSXNQ.js.map → doctor-IN6MWP6I.js.map} +0 -0
  126. /package/dist/{follow-up-tool-53AYA2UQ.js.map → follow-up-tool-VB7K6HCL.js.map} +0 -0
  127. /package/dist/{grants-O7SJ2J4B.js.map → grants-2S33F2LV.js.map} +0 -0
  128. /package/dist/{hub-YCOUZFNU.js.map → hub-JNNNUAZM.js.map} +0 -0
  129. /package/dist/{promote-THTEHZHU.js.map → promote-VFYVWVTL.js.map} +0 -0
  130. /package/dist/{query-N7JBDLR7.js.map → query-RB2MU2HV.js.map} +0 -0
  131. /package/dist/{query-settings-BJTVDDCH.js.map → query-settings-5B54WHCS.js.map} +0 -0
  132. /package/dist/{registry-LJ66OZYJ.js.map → registry-6OX7U6FV.js.map} +0 -0
  133. /package/dist/{request-planner-PCELXLK7.js.map → request-planner-TUHVEYSF.js.map} +0 -0
  134. /package/dist/{review-candidates-EMJUROJH.js.map → review-candidates-FDYTGG2N.js.map} +0 -0
  135. /package/dist/{routing-D2KNBEMG.js.map → routing-U35SFPEI.js.map} +0 -0
  136. /package/dist/{schedule-tool-55MOWHKD.js.map → schedule-tool-EPQKUYJX.js.map} +0 -0
  137. /package/dist/{scheduler-73UEBYV4.js.map → scheduler-H2QHWNQ2.js.map} +0 -0
  138. /package/dist/{seat-UFAMWG7M.js.map → seat-EB3KJMIE.js.map} +0 -0
  139. /package/dist/{select-EPWELLAV.js.map → select-IU4IOVSO.js.map} +0 -0
  140. /package/dist/{set-enabled-LS65QZQS.js.map → set-enabled-64BSJ7LR.js.map} +0 -0
  141. /package/dist/{tool-7LKYIA6D.js.map → tool-B23ACEHV.js.map} +0 -0
  142. /package/dist/{tool-4S3YKLCN.js.map → tool-W3CIQZJ7.js.map} +0 -0
  143. /package/dist/{wiki-LHT6X2JF.js.map → wiki-4KMRUD5C.js.map} +0 -0
  144. /package/dist/{wiki-enrich-CBBS3AC7.js.map → wiki-enrich-N4GLW2JX.js.map} +0 -0
@@ -1,8 +1,8 @@
1
- import{a as Ae}from"./chunk-GTJIKXDB.js";import{E as tn,H as nn,p as Kt}from"./chunk-Z3AI4KXT.js";import{a as w}from"./chunk-7LN4VKDU.js";import{e as Yt,g as Zt,i as Qt,j as $e,l as B,m as j,o as en}from"./chunk-TJZGAKIB.js";import{t as Xt,u as Gt}from"./chunk-P5BFFU4Y.js";import{d as Ht,e as zt}from"./chunk-AQASR6KR.js";import{b as Jt}from"./chunk-YMX3QCV7.js";import{a as Vt,b as Bt,d as qt}from"./chunk-VY7TBMJU.js";import{a as Nt,c as Ot}from"./chunk-KP7KDLZ2.js";import{g as Mt,h as jt,i as Ft,k as Wt,l as Ut}from"./chunk-GJMYG53S.js";import{X as Lt,Z as te,_ as xe,aa as ve,b as Se}from"./chunk-KW6SHOAN.js";import{q as Pt}from"./chunk-P6PFTNN4.js";import{a as Ct,b as Dt}from"./chunk-E7YHXMJG.js";import{Ca as ke,Ka as It,La as Et,Q as $t,R as At,S as _t,T as Rt,Ua as Tt,n as ee,o as xt,p as vt,q as ei}from"./chunk-6UP5VD3H.js";import{a as be,h as ti}from"./chunk-BRK6M6LA.js";import{f as we,n as ni}from"./chunk-UIBUZ2N3.js";import{existsSync as ri,readdirSync as ii,readFileSync as si,statSync as oi}from"fs";import{resolve as ai}from"path";function rn(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let a of e){let o=s.get(a.workflowId);o?o.push(a):s.set(a.workflowId,[a])}return t.map(a=>{let o=s.get(a.id)??[],l=o.filter(g=>n-g.at<=r),c=o.filter(g=>n-g.at>r&&n-g.at<=r*2),u=l.filter(g=>g.status==="failed").length,d=o.filter(g=>g.status==="paused").length,p=o.length?Math.max(...o.map(g=>g.at)):null,f=o.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:a.id,name:a.name||a.id,state:f,lastRunAt:p,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((a,o)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[a.state]-l[o.state]||(o.lastRunAt??0)-(a.lastRunAt??0)})}var ne=new Map;function Fa(t,e=1e3){if(!ri(t))return[];let n=ii(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let a=ai(t,s);return{path:a,mtime:oi(a).mtimeMs}}).sort((s,a)=>a.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of ne.keys())i.has(s)||ne.delete(s);let r=[];for(let{path:s,mtime:a}of n){let o=ne.get(s);if(o&&o.mtime===a){o.summary&&r.push(o.summary);continue}let l=li(s,a);ne.set(s,{mtime:a,summary:l}),l&&r.push(l)}return r}function li(t,e){try{let n=si(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 a=n.length-1;a>=0;a--){let o=JSON.parse(n[a]),l=o.status??o.run?.status;if(l){s=l;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var ci={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},ui=(t,e,n)=>{try{return Pt(t,e,n)}catch{return null}},sn=864e5;function Ba(t){let e=t.now??Date.now(),n={...ci,...t.thresholds},i=t.nextFire??ui,r=[];for(let o of t.crons){let l=t.cronRuns.get(o.id)??[],c=o.timezone||"UTC",u=l.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=l[0],p={id:`cron:${o.id}`,source:"cron",kind:"schedule",name:A(o.id,k.text),trigger:{schedule:A(o.schedule,k.text),timezone:c},agent:o.agent||null,enabled:o.enabled,state:o.enabled?"enabled":"disabled",nextRunAt:o.enabled?_e(o.nextRun)??_e(i(o.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:hi(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:on(u),sampledRuns:l.length,flags:[],attention:null};p.flags=an(p,u,o.schedule,c,null,e,n,i),r.push(ln(p))}let s=new Map(rn(t.workflows.map(o=>({id:o.id,name:o.title})),t.workflowRuns,e).map(o=>[o.id,o])),a=new Map;for(let o of t.workflowRuns){let l=a.get(o.workflowId);l?l.push(o):a.set(o.workflowId,[o])}for(let o of t.workflows){let l=o.nodes.find(I=>I.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=o.state||"active",d=u==="active",p=(a.get(o.id)??[]).slice().sort((I,ye)=>ye.at-I.at),f=p.map(I=>({at:I.at,status:fi(I.status)})),g=f[0],h=l.type==="trigger.cron",y=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",M={id:`workflow:${o.id}`,source:"workflow",kind:h?"schedule":"event",name:A(o.title||o.id,k.text),trigger:h?{schedule:A(y,k.text),timezone:C}:{event:A(typeof c.event=="string"?c.event:"",k.text),filters:mi(c.filter,o)},agent:gi(o),enabled:d,state:u,nextRunAt:h&&d&&y?_e(i(y,new Date(e),C)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let I=f.find(ye=>ye.status==="success");return I?new Date(I.at).toISOString():null})(),consecutiveFailures:on(f),sampledRuns:p.length,flags:[],attention:null},Q=Date.parse(o.updated||o.created||"");M.flags=h?an(M,f,y,C,Number.isFinite(Q)?Q:null,e,n,i):di(M,s.get(o.id)?.state==="dormant",Number.isFinite(Q)?Q:null,e,n),r.push(ln(M))}return r.sort(pi).slice(0,k.routines)}function on(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 an(t,e,n,i,r,s,a,o){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let p=un(c,r,s,a);return p&&l.push(p),l}if(t.consecutiveFailures>=a.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let p=0;p<a.missedFires&&(d=o(n,u,i),!!d);p++)u=d;return d&&s>d.getTime()+a.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${a.missedFires} scheduled fires missed`}),l}function di(t,e,n,i,r){let s=[],a=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let o=un(a,n,i,r);return o&&s.push(o),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),a===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 un(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*sn?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/sn)} days`:"Disabled and never ran"}}function ln(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 cn={critical:0,warning:1,info:2};function pi(t,e){let n=t.attention?cn[t.attention]:3,i=e.attention?cn[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function fi(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 gi(t){if(t.ownerAgent)return A(t.ownerAgent,k.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?A(String(e.config.agentId),k.text):null}function mi(t,e){let n=[],i=e?.project;if(i&&n.push(A(`project=${i}`,k.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,s]of Object.entries(t)){let a=Array.isArray(s)?s.map(String):s==null?[]:[String(s)];a.length&&n.push(A(`${r}=${a.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function _e(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function A(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function hi(t,e){return t===void 0?void 0:A(t,e)}import{mkdirSync as yi,readFileSync as bi,renameSync as wi,writeFileSync as ki}from"fs";import{resolve as Si}from"path";function dn(t){return Si($e(t),"_state.json")}function x(t){try{let e=JSON.parse(bi(dn(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 q(t,e){yi($e(t),{recursive:!0});let n=dn(t),i=`${n}.${process.pid}.tmp`;ki(i,JSON.stringify(e,null,2)+`
3
- `),wi(i,n)}function pn(t,e,n,i=Date.now()){let r=x(t),s={};for(let[a,o]of Object.entries(r.snoozed))Date.parse(o)>i&&(s[a]=o);s[e]=n.toISOString(),q(t,{...r,snoozed:s})}function Ga(t,e){q(t,{...x(t),lastDigest:e})}function Re(t,e,n,i=Date.now()){let r=x(t),s=new Set(n),a={};for(let[l,c]of Object.entries(r.popped??{}))s.has(l)&&(a[l]=c);a[e]=new Date(i).toISOString();let o=(r.wanted??[]).filter(l=>l!==e&&s.has(l));q(t,{...r,popped:a,wanted:o})}function fn(t,e){let n=x(t);q(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function Ka(t,e=Date.now()){q(t,{...x(t),popped:{},passAt:new Date(e).toISOString()})}import{existsSync as H,readdirSync as Mi,readFileSync as ji}from"fs";import{resolve as _}from"path";import{randomBytes as hn}from"crypto";import{existsSync as vi,mkdirSync as $i,readdirSync as Ai,readFileSync as _i,renameSync as yn,unlinkSync as Ri,writeFileSync as Ii}from"fs";import{resolve as bn}from"path";function gn(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var xi=t=>t.trim().split(`
4
- `).pop()?.slice(0,300)||"no output";async function mn(t,e,n,i=Ae){let r=await i(t.bin,[...gn(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${xi(r.stderr||r.stdout)}`}}async function Za(t,e,n,i,r=Ae){return(await r(t.bin,[...gn(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var Ei=2e3,Ti=t=>mn(t.wacli,t.to,t.text);function Ie(t){return bn(t,".agentx","whatsapp-triage","drafts")}var Ci=t=>/^[a-z0-9-]{8,64}$/.test(t),re=(t,e)=>bn(Ie(t),`${e}.json`);function wn(t,e){$i(Ie(t),{recursive:!0});let n=re(t,e.id),i=`${n}.${process.pid}.tmp`;Ii(i,JSON.stringify(e,null,2)+`
5
- `,{mode:384}),yn(i,n)}function il(t,e,n=Date.now()){let i=e.text.trim().slice(0,Ei);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${hn(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return wn(t,r),r}function ie(t,e){if(!Ci(e))return null;try{return JSON.parse(_i(re(t,e),"utf-8"))}catch{return null}}function kn(t,e){let n=Ie(t);return vi(n)?Ai(n).filter(i=>i.endsWith(".json")).map(i=>ie(t,i.slice(0,-5))).filter(i=>!!i&&(!e||i.status===e)).sort((i,r)=>i.created_at.localeCompare(r.created_at)):[]}async function Sn(t,e,n,i={}){let r=ie(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let s=`${re(t,e)}.${process.pid}.${hn(3).toString("hex")}.claim`;try{yn(re(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let a={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")a.status="rejected";else{let o=await(i.send??Ti)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));o.ok?a.status="sent":(a.status="failed",a.error=o.error)}wn(t,a);try{Ri(s)}catch{}return a.status==="failed"?{ok:!1,error:a.error??"send failed"}:{ok:!0,draft:a}}ni();Rt();Rt();var al=["done","skipped"],Di=1e3;function Pi(t){t.exec(`
1
+ import{a as Ae}from"./chunk-GTJIKXDB.js";import{E as nn,H as rn,p as Jt}from"./chunk-WGPMUWX7.js";import{a as w}from"./chunk-7LN4VKDU.js";import{e as Zt,g as Qt,i as en,j as $e,l as B,m as j,o as tn}from"./chunk-A76PNG4E.js";import{t as Gt,u as Kt}from"./chunk-IGA3T3ZT.js";import{d as zt,e as Xt}from"./chunk-AQASR6KR.js";import{b as Yt}from"./chunk-YMX3QCV7.js";import{a as Ut,b as Bt,d as qt,e as Ht}from"./chunk-MNG2AMKZ.js";import{g as Mt,h as jt,i as Ft,k as Wt,l as Vt}from"./chunk-5QXRPYOY.js";import{a as Lt,c as Ot}from"./chunk-KP7KDLZ2.js";import{X as Nt,Z as te,_ as xe,aa as ve,b as Se}from"./chunk-BZ6Y264Z.js";import{q as Pt}from"./chunk-6YNRLI6I.js";import{a as Ct,b as Dt}from"./chunk-E7LPZAXP.js";import{Ca as ke,Ka as It,La as Et,Q as $t,R as At,S as _t,T as Rt,Ua as Tt,n as ee,o as xt,p as vt,q as ti}from"./chunk-PXKIPU27.js";import{a as be,h as ni}from"./chunk-BRK6M6LA.js";import{f as we,n as ri}from"./chunk-UIBUZ2N3.js";import{existsSync as ii,readdirSync as si,readFileSync as oi,statSync as ai}from"fs";import{resolve as li}from"path";function sn(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let a of e){let o=s.get(a.workflowId);o?o.push(a):s.set(a.workflowId,[a])}return t.map(a=>{let o=s.get(a.id)??[],l=o.filter(g=>n-g.at<=r),c=o.filter(g=>n-g.at>r&&n-g.at<=r*2),u=l.filter(g=>g.status==="failed").length,d=o.filter(g=>g.status==="paused").length,p=o.length?Math.max(...o.map(g=>g.at)):null,f=o.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:a.id,name:a.name||a.id,state:f,lastRunAt:p,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((a,o)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[a.state]-l[o.state]||(o.lastRunAt??0)-(a.lastRunAt??0)})}var ne=new Map;function Fa(t,e=1e3){if(!ii(t))return[];let n=si(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let a=li(t,s);return{path:a,mtime:ai(a).mtimeMs}}).sort((s,a)=>a.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of ne.keys())i.has(s)||ne.delete(s);let r=[];for(let{path:s,mtime:a}of n){let o=ne.get(s);if(o&&o.mtime===a){o.summary&&r.push(o.summary);continue}let l=ci(s,a);ne.set(s,{mtime:a,summary:l}),l&&r.push(l)}return r}function ci(t,e){try{let n=oi(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 a=n.length-1;a>=0;a--){let o=JSON.parse(n[a]),l=o.status??o.run?.status;if(l){s=l;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var ui={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},di=(t,e,n)=>{try{return Pt(t,e,n)}catch{return null}},on=864e5;function Ba(t){let e=t.now??Date.now(),n={...ui,...t.thresholds},i=t.nextFire??di,r=[];for(let o of t.crons){let l=t.cronRuns.get(o.id)??[],c=o.timezone||"UTC",u=l.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=l[0],p={id:`cron:${o.id}`,source:"cron",kind:"schedule",name:A(o.id,k.text),trigger:{schedule:A(o.schedule,k.text),timezone:c},agent:o.agent||null,enabled:o.enabled,state:o.enabled?"enabled":"disabled",nextRunAt:o.enabled?_e(o.nextRun)??_e(i(o.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:yi(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:an(u),sampledRuns:l.length,flags:[],attention:null};p.flags=ln(p,u,o.schedule,c,null,e,n,i),r.push(cn(p))}let s=new Map(sn(t.workflows.map(o=>({id:o.id,name:o.title})),t.workflowRuns,e).map(o=>[o.id,o])),a=new Map;for(let o of t.workflowRuns){let l=a.get(o.workflowId);l?l.push(o):a.set(o.workflowId,[o])}for(let o of t.workflows){let l=o.nodes.find(I=>I.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=o.state||"active",d=u==="active",p=(a.get(o.id)??[]).slice().sort((I,ye)=>ye.at-I.at),f=p.map(I=>({at:I.at,status:gi(I.status)})),g=f[0],h=l.type==="trigger.cron",y=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",M={id:`workflow:${o.id}`,source:"workflow",kind:h?"schedule":"event",name:A(o.title||o.id,k.text),trigger:h?{schedule:A(y,k.text),timezone:C}:{event:A(typeof c.event=="string"?c.event:"",k.text),filters:hi(c.filter,o)},agent:mi(o),enabled:d,state:u,nextRunAt:h&&d&&y?_e(i(y,new Date(e),C)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let I=f.find(ye=>ye.status==="success");return I?new Date(I.at).toISOString():null})(),consecutiveFailures:an(f),sampledRuns:p.length,flags:[],attention:null},Q=Date.parse(o.updated||o.created||"");M.flags=h?ln(M,f,y,C,Number.isFinite(Q)?Q:null,e,n,i):pi(M,s.get(o.id)?.state==="dormant",Number.isFinite(Q)?Q:null,e,n),r.push(cn(M))}return r.sort(fi).slice(0,k.routines)}function an(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 ln(t,e,n,i,r,s,a,o){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let p=dn(c,r,s,a);return p&&l.push(p),l}if(t.consecutiveFailures>=a.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let p=0;p<a.missedFires&&(d=o(n,u,i),!!d);p++)u=d;return d&&s>d.getTime()+a.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${a.missedFires} scheduled fires missed`}),l}function pi(t,e,n,i,r){let s=[],a=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let o=dn(a,n,i,r);return o&&s.push(o),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),a===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 dn(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*on?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/on)} days`:"Disabled and never ran"}}function cn(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 un={critical:0,warning:1,info:2};function fi(t,e){let n=t.attention?un[t.attention]:3,i=e.attention?un[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function gi(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 mi(t){if(t.ownerAgent)return A(t.ownerAgent,k.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?A(String(e.config.agentId),k.text):null}function hi(t,e){let n=[],i=e?.project;if(i&&n.push(A(`project=${i}`,k.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,s]of Object.entries(t)){let a=Array.isArray(s)?s.map(String):s==null?[]:[String(s)];a.length&&n.push(A(`${r}=${a.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function _e(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function A(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function yi(t,e){return t===void 0?void 0:A(t,e)}import{mkdirSync as bi,readFileSync as wi,renameSync as ki,writeFileSync as Si}from"fs";import{resolve as xi}from"path";function pn(t){return xi($e(t),"_state.json")}function x(t){try{let e=JSON.parse(wi(pn(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 q(t,e){bi($e(t),{recursive:!0});let n=pn(t),i=`${n}.${process.pid}.tmp`;Si(i,JSON.stringify(e,null,2)+`
3
+ `),ki(i,n)}function fn(t,e,n,i=Date.now()){let r=x(t),s={};for(let[a,o]of Object.entries(r.snoozed))Date.parse(o)>i&&(s[a]=o);s[e]=n.toISOString(),q(t,{...r,snoozed:s})}function Ga(t,e){q(t,{...x(t),lastDigest:e})}function Re(t,e,n,i=Date.now()){let r=x(t),s=new Set(n),a={};for(let[l,c]of Object.entries(r.popped??{}))s.has(l)&&(a[l]=c);a[e]=new Date(i).toISOString();let o=(r.wanted??[]).filter(l=>l!==e&&s.has(l));q(t,{...r,popped:a,wanted:o})}function gn(t,e){let n=x(t);q(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function Ka(t,e=Date.now()){q(t,{...x(t),popped:{},passAt:new Date(e).toISOString()})}import{existsSync as H,readdirSync as ji,readFileSync as Fi}from"fs";import{resolve as _}from"path";import{randomBytes as yn}from"crypto";import{existsSync as $i,mkdirSync as Ai,readdirSync as _i,readFileSync as Ri,renameSync as bn,unlinkSync as Ii,writeFileSync as Ei}from"fs";import{resolve as wn}from"path";function mn(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var vi=t=>t.trim().split(`
4
+ `).pop()?.slice(0,300)||"no output";async function hn(t,e,n,i=Ae){let r=await i(t.bin,[...mn(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${vi(r.stderr||r.stdout)}`}}async function Za(t,e,n,i,r=Ae){return(await r(t.bin,[...mn(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var Ti=2e3,Ci=t=>hn(t.wacli,t.to,t.text);function Ie(t){return wn(t,".agentx","whatsapp-triage","drafts")}var Di=t=>/^[a-z0-9-]{8,64}$/.test(t),re=(t,e)=>wn(Ie(t),`${e}.json`);function kn(t,e){Ai(Ie(t),{recursive:!0});let n=re(t,e.id),i=`${n}.${process.pid}.tmp`;Ei(i,JSON.stringify(e,null,2)+`
5
+ `,{mode:384}),bn(i,n)}function il(t,e,n=Date.now()){let i=e.text.trim().slice(0,Ti);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${yn(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return kn(t,r),r}function ie(t,e){if(!Di(e))return null;try{return JSON.parse(Ri(re(t,e),"utf-8"))}catch{return null}}function Sn(t,e){let n=Ie(t);return $i(n)?_i(n).filter(i=>i.endsWith(".json")).map(i=>ie(t,i.slice(0,-5))).filter(i=>!!i&&(!e||i.status===e)).sort((i,r)=>i.created_at.localeCompare(r.created_at)):[]}async function xn(t,e,n,i={}){let r=ie(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let s=`${re(t,e)}.${process.pid}.${yn(3).toString("hex")}.claim`;try{bn(re(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let a={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")a.status="rejected";else{let o=await(i.send??Ci)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));o.ok?a.status="sent":(a.status="failed",a.error=o.error)}kn(t,a);try{Ii(s)}catch{}return a.status==="failed"?{ok:!1,error:a.error??"send failed"}:{ok:!0,draft:a}}ri();Rt();Rt();var al=["done","skipped"],Pi=1e3;function Ni(t){t.exec(`
6
6
  CREATE TABLE IF NOT EXISTS request_plans (
7
7
  request_id TEXT PRIMARY KEY,
8
8
  created_by TEXT NOT NULL,
@@ -50,9 +50,9 @@ import{a as Ae}from"./chunk-GTJIKXDB.js";import{E as tn,H as nn,p as Kt}from"./c
50
50
  FOREIGN KEY (request_id) REFERENCES request_plans(request_id) ON DELETE CASCADE
51
51
  );
52
52
  CREATE INDEX IF NOT EXISTS idx_request_plan_events ON request_plan_events(request_id, at);
53
- `)}function vn(t){return!!t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'request_plans'").get()}function Ee(t){return{requestId:t.request_id,createdBy:t.created_by,createdAt:t.created_at,state:t.state,finishedAt:t.finished_at??null,notifiedAt:t.notified_at??null}}function xn(t){return{requestId:t.request_id,idx:t.idx,name:t.name,kind:t.kind,agentId:t.agent_id,doneWhen:t.done_when,state:t.state,needsApproval:!!t.needs_approval,approval:t.approval,cardId:t.card_id??null,message:t.message??null,toChannel:t.to_channel??null,toChat:t.to_chat??null,toAccount:t.to_account??null,checkUrl:t.check_url??null,checkContains:t.check_contains??null,stallMinutes:t.stall_minutes??null,evidence:t.evidence??null,note:t.note??null,dispatchedAt:t.dispatched_at??null,updatedAt:t.updated_at,nudges:t.nudges,lastNudgeAt:t.last_nudge_at??null,notifiedAt:t.notified_at??null}}var Li={state:"state",approval:"approval",cardId:"card_id",message:"message",evidence:"evidence",note:"note",dispatchedAt:"dispatched_at",updatedAt:"updated_at",nudges:"nudges",lastNudgeAt:"last_nudge_at",notifiedAt:"notified_at"},se=class{constructor(e){this.db=e;Pi(e)}create(e,n,i,r){let s=this.db.prepare("INSERT INTO request_plans (request_id, created_by, created_at, state) VALUES (?, ?, ?, 'active')"),a=this.db.prepare(`INSERT INTO request_plan_steps (request_id, idx, name, kind, agent_id, done_when, state, needs_approval, message,
53
+ `)}function $n(t){return!!t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'request_plans'").get()}function Ee(t){return{requestId:t.request_id,createdBy:t.created_by,createdAt:t.created_at,state:t.state,finishedAt:t.finished_at??null,notifiedAt:t.notified_at??null}}function vn(t){return{requestId:t.request_id,idx:t.idx,name:t.name,kind:t.kind,agentId:t.agent_id,doneWhen:t.done_when,state:t.state,needsApproval:!!t.needs_approval,approval:t.approval,cardId:t.card_id??null,message:t.message??null,toChannel:t.to_channel??null,toChat:t.to_chat??null,toAccount:t.to_account??null,checkUrl:t.check_url??null,checkContains:t.check_contains??null,stallMinutes:t.stall_minutes??null,evidence:t.evidence??null,note:t.note??null,dispatchedAt:t.dispatched_at??null,updatedAt:t.updated_at,nudges:t.nudges,lastNudgeAt:t.last_nudge_at??null,notifiedAt:t.notified_at??null}}var Li={state:"state",approval:"approval",cardId:"card_id",message:"message",evidence:"evidence",note:"note",dispatchedAt:"dispatched_at",updatedAt:"updated_at",nudges:"nudges",lastNudgeAt:"last_nudge_at",notifiedAt:"notified_at"},se=class{constructor(e){this.db=e;Ni(e)}create(e,n,i,r){let s=this.db.prepare("INSERT INTO request_plans (request_id, created_by, created_at, state) VALUES (?, ?, ?, 'active')"),a=this.db.prepare(`INSERT INTO request_plan_steps (request_id, idx, name, kind, agent_id, done_when, state, needs_approval, message,
54
54
  to_channel, to_chat, to_account, check_url, check_contains, stall_minutes, dispatched_at, updated_at)
55
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);this.db.transaction(()=>{s.run(e,n,r),i.forEach((o,l)=>{let c=l===0,u=c&&o.agentId===n&&o.kind!=="message";a.run(e,l+1,o.name,o.kind,o.agentId,o.doneWhen,c?"active":"pending",o.needsApproval?1:0,o.message??null,o.toChannel??null,o.toChat??null,o.toAccount??null,o.checkUrl??null,o.checkContains??null,o.stallMinutes??null,u?r:null,r)}),this.event(e,null,"created",`${i.length} steps, written by ${n}`,r)})()}get(e){let n=this.db.prepare("SELECT * FROM request_plans WHERE request_id = ?").get(e);return n?Ee(n):null}steps(e){return this.db.prepare("SELECT * FROM request_plan_steps WHERE request_id = ? ORDER BY idx").all(e).map(xn)}step(e,n){let i=this.db.prepare("SELECT * FROM request_plan_steps WHERE request_id = ? AND idx = ?").get(e,n);return i?xn(i):null}listActive(){return this.db.prepare("SELECT * FROM request_plans WHERE state = 'active' ORDER BY created_at, rowid").all().map(Ee)}updateStep(e,n,i){let r=[],s=[];for(let[a,o]of Object.entries(i)){let l=Li[a];!l||o===void 0||(r.push(`${l} = ?`),s.push(typeof o=="boolean"?o?1:0:o))}r.length&&this.db.prepare(`UPDATE request_plan_steps SET ${r.join(", ")} WHERE request_id = ? AND idx = ?`).run(...s,e,n)}finish(e,n,i){return this.db.prepare("UPDATE request_plans SET state = ?, finished_at = ? WHERE request_id = ? AND state = 'active'").run(n,i,e).changes>0}markNotified(e,n){this.db.prepare("UPDATE request_plans SET notified_at = ? WHERE request_id = ?").run(n,e)}awaitingSummary(){return this.db.prepare("SELECT * FROM request_plans WHERE state = 'done' AND notified_at IS NULL ORDER BY finished_at").all().map(Ee)}event(e,n,i,r,s){this.db.prepare("INSERT INTO request_plan_events (request_id, step, at, kind, detail) VALUES (?, ?, ?, ?, ?)").run(e,n,s,i,r.replace(/\s+/g," ").trim().slice(0,Di))}events(e,n=200){return this.db.prepare("SELECT request_id, step, at, kind, detail FROM request_plan_events WHERE request_id = ? ORDER BY at, rowid LIMIT ?").all(e,n).map(i=>({requestId:i.request_id,step:i.step??null,at:i.at,kind:i.kind,detail:i.detail}))}},ll=$t;import{existsSync as Ni,readFileSync as Oi}from"fs";Tt();ti();function $n(t){let e=Ct(t),n={};if(Ni(e))try{n=It(JSON.parse(Oi(e,"utf-8")))}catch{n={}}let i=ke.safeParse(n?.requests);return i.success?i.data:ke.parse(void 0)}async function gl(t,e={}){let n=(t.channels??[]).filter(i=>!be.has(i.toLowerCase().split("@")[0]));return n.length?{success:!1,error:`unknown channel ${n.map(i=>`"${i}"`).join(", ")}: use ${[...be].join(", ")}`}:Dt(i=>{let r=i.requests??={};for(let s of["enabled","channels","from","staleAfterHours","retentionDays"])t[s]!==void 0&&(r[s]=t[s]);if(t.plans){let s=r.plans??={};for(let a of["enabled","stallMinutes","maxNudges","approveKinds","disabledAgents","requireForWork","requireOverMinutes"])t.plans[a]!==void 0&&(s[a]=t.plans[a])}if(t.checkers){let s=r.checkers??={};for(let a of["enabled","checkEveryMinutes"])t.checkers[a]!==void 0&&(s[a]=t.checkers[a])}},{configPath:e.configPath,reload:e.reload})}var Rn=["card","schedule","memory","wiki","whatsapp","request"],Fi=280;function L(t,e=Fi){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Te(t){if(t.configPath)return _(t.configPath);let e=[_(t.root,"agentx.json"),_(t.root,".agentx","config.json")];return e.find(n=>H(n))??e[0]}function Ce(t){return t.wikiDir?_(t.wikiDir):_(t.root,".agentx","wiki")}function Wi(t){return j(t.root,"pending").map(Ui)}function Ui(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,...t.node?{node:t.node}:{},created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.draft?{draft:t.draft}:{},...t.context||t.draft?{detail:L([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function Vi(t){let e=Te(t);if(!H(e))return[];let n;try{n=JSON.parse(ji(e,"utf-8"))}catch{return[]}let i=new Date(t.now??Date.now()),r=[];for(let[s,a]of Object.entries(n?.crons??{})){let o=a?.approval;if(!o||o.action!=="create"&&o.action!=="delete")continue;let l=a.timezone||"UTC",c=a.schedule?Mt(a.schedule):"",u=a.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${a.schedule})`:"no schedule",d=String(a.prompt??a.command??""),p=o.action==="create";r.push({key:`schedule:${s}`,kind:"schedule",title:p?`New schedule "${s}" for ${a.agent??"an agent"}`:`Delete schedule "${s}"`,ask:p?`Let ${a.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(o.requestedBy??"unknown"),created_at:String(o.requestedAt??""),detail:L(`${d}${p&&a.schedule?` \xB7 first run ${Ft(jt(a.schedule,l,i),l)}`:""}`),more:"agentx schedule list"})}return r}function In(t){let e=_(t,".agentx","memory");return H(e)?Mi(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function Bi(t){let e=In(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:L(s.content),more:`agentx memory facts held --agent ${r}`});return i}function qi(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 Hi(t){return zt(Ce(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(`${qi(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function zi(t){return kn(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 z(t){if(t.requests)return t.requests;if(_(t.root)!==process.cwd()||!H(_(t.root,".agentx","db.sqlite")))return null;let e=we({quiet:!0});if(!e)return null;let n=An.get(e);return!n&&!At(e)?null:(n||An.set(e,n=new _t(e)),n)}var An=new WeakMap;function El(t){if(t.plans)return t.plans;if(t.requests||_(t.root)!==process.cwd()||!H(_(t.root,".agentx","db.sqlite")))return null;let e=we({quiet:!0});if(!e||!vn(e))return null;let n=_n.get(e);return n||_n.set(e,n=new se(e)),n}var _n=new WeakMap;function Xi(t){let e=z(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 En={card:Wi,schedule:Vi,memory:Bi,wiki:Hi,whatsapp:zi,request:Xi};function Gi(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 Tl(t,e={}){let n=t.now??Date.now(),{snoozed:i}=x(t.root),r=[],s=[],a=0;for(let o of e.kinds??Rn){let l;try{l=En[o](t)}catch(c){s.push({kind:o,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=i[c.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){a++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(Gi),{items:r,snoozed:a,errors:s}}function Ki(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),i=t.slice(e+1);return!Rn.includes(n)||!i?null:{kind:n,ref:i}}function Ji(t,e,n){switch(e){case"card":return B(t.root,n)?.status==="pending";case"wiki":return Ht(Ce(t),n)?.status==="pending";case"whatsapp":return ie(t.root,n)?.status==="pending";default:return En[e](t).some(i=>i.key===`${e}:${n}`)}}async function Tn(t,e,n,i={}){let r=Ki(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:s,ref:a}=r,o=t.now??Date.now(),l=i.by??"operator";if(n==="later"){if(!Ji(t,s,a))return{ok:!1,error:`nothing waiting for "${e}"`};let u=i.laterHours&&i.laterHours>0?i.laterHours:24,d=new Date(o+u*36e5);return pn(t.root,e,d,o),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(s){case"card":{let u=en(t.root,a,c?"yes":"no",{by:l,note:i.note,now:o,choice:i.choice,text:i.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(c?Wt:Ut)(a,{configPath:Te(t),reload:t.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=a.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=a.slice(0,u),p=a.slice(u+1);if(!In(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,c?"approved":"rejected",l),{ok:!0,message:`${e} ${c?"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=Ce(t),d=c?Xt(u,a,{by:l,force:i.force,now:o}):Gt(u,a,{by:l,reason:i.note,now:o});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await Sn(t.root,a,c?"yes":"no",{by:l,now:o,send:t.sendWhatsApp});return u.ok?{ok:!0,message:c?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}case"request":{let u=z(t),d=u?.get(a);return!u||!d||d.state!=="needs_attention"?{ok:!1,error:`nothing waiting for "${e}"`}:c?$n(Te(t)).enabled?(u.requestPickup(a,o),{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(a,"dropped",i.note?.trim()||`dropped by ${l}`,o),{ok:!0,message:`${e}: dropped`})}}}var Cn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Dl(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/requests"||t.startsWith("/requests/")||t==="/watchers"||t.startsWith("/watchers/")||t==="/follow-up"||t.startsWith("/follow-up/")||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/")||t==="/wiki/agents"||t==="/wiki/entries"||t==="/wiki/articles"||t==="/wiki/article"||t==="/wiki/notes"||t==="/api/wiki/curate"||t==="/api/wiki/curate/restore"||t==="/api/signals/stopped"||t.startsWith("/api/signals/stopped/")||t==="/api/review-gate/reviews"}function Pl(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)||/^\/workflow-runs\/[^/]+\/cancel$/.test(t)||t==="/api/signals/stop"||t==="/api/signals/resume"||t==="/api/signals/drop"||t==="/api/review-gate/replay"}function Ll(t){return Cn.has(t)}function Nl(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(Cn.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 Ol(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 Ml(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 oe(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function Yi(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function Zi(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Fl(t,e=Zi()){let n=oe(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=Yi(n),s=[oe(t.host),oe(t["x-forwarded-host"])].filter(Boolean).map(a=>a.toLowerCase());return r&&s.includes(r)?"same-origin":"foreign"}let i=oe(t["sec-fetch-site"]).toLowerCase();return i==="cross-site"||i==="same-site"?"foreign":"none"}function Wl(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as nr,mkdirSync as Rs,readFileSync as Is,renameSync as Es,writeFileSync as Ts}from"fs";import{homedir as Cs}from"os";import{dirname as Ds,join as Ps}from"path";import{execFile as cs,execFileSync as us}from"child_process";import{execFileSync as Qi}from"child_process";import{existsSync as Pn,mkdirSync as es,readdirSync as ts,readFileSync as Ln,renameSync as ns,writeFileSync as rs}from"fs";import{homedir as Nn}from"os";import{join as Pe}from"path";var v="siri:",On="com.apple.ttsbundle.gryphon-neural_",Mn=t=>!!t&&t.startsWith(On),is=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],ss=()=>{try{return Qi("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},De;function Le(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&De!==void 0)return De;let{platform:n=process.platform,exists:i=Pn,prefDomain:r=ss}=t,s=n==="darwin"&&is.every(a=>i(a))&&r();return e||(De=s),s}var jn=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Fn={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"},Ne=t=>Fn[t.toLowerCase()]??null;function ae(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 os=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function as(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(os)){let a=`${i}-${r}`,o=`${On}${s}_${a}_premium`;e.has(o)||e.set(o,{id:o,name:s[0].toUpperCase()+s.slice(1),locale:a,quality:"premium",gender:Fn[s]??null,siri:!0})}return[...e.values()]}function le(t=jn,e={}){if(!Le(e))return[];let n=[];for(let i of t){let r;try{r=ts(i)}catch{continue}for(let s of r)try{n.push(Ln(Pe(i,s,"Info.plist"),"latin1"))}catch{}}return as(n)}var Dn=`#!/bin/sh
55
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);this.db.transaction(()=>{s.run(e,n,r),i.forEach((o,l)=>{let c=l===0,u=c&&o.agentId===n&&o.kind!=="message";a.run(e,l+1,o.name,o.kind,o.agentId,o.doneWhen,c?"active":"pending",o.needsApproval?1:0,o.message??null,o.toChannel??null,o.toChat??null,o.toAccount??null,o.checkUrl??null,o.checkContains??null,o.stallMinutes??null,u?r:null,r)}),this.event(e,null,"created",`${i.length} steps, written by ${n}`,r)})()}get(e){let n=this.db.prepare("SELECT * FROM request_plans WHERE request_id = ?").get(e);return n?Ee(n):null}steps(e){return this.db.prepare("SELECT * FROM request_plan_steps WHERE request_id = ? ORDER BY idx").all(e).map(vn)}step(e,n){let i=this.db.prepare("SELECT * FROM request_plan_steps WHERE request_id = ? AND idx = ?").get(e,n);return i?vn(i):null}listActive(){return this.db.prepare("SELECT * FROM request_plans WHERE state = 'active' ORDER BY created_at, rowid").all().map(Ee)}updateStep(e,n,i){let r=[],s=[];for(let[a,o]of Object.entries(i)){let l=Li[a];!l||o===void 0||(r.push(`${l} = ?`),s.push(typeof o=="boolean"?o?1:0:o))}r.length&&this.db.prepare(`UPDATE request_plan_steps SET ${r.join(", ")} WHERE request_id = ? AND idx = ?`).run(...s,e,n)}finish(e,n,i){return this.db.prepare("UPDATE request_plans SET state = ?, finished_at = ? WHERE request_id = ? AND state = 'active'").run(n,i,e).changes>0}markNotified(e,n){this.db.prepare("UPDATE request_plans SET notified_at = ? WHERE request_id = ?").run(n,e)}awaitingSummary(){return this.db.prepare("SELECT * FROM request_plans WHERE state = 'done' AND notified_at IS NULL ORDER BY finished_at").all().map(Ee)}event(e,n,i,r,s){this.db.prepare("INSERT INTO request_plan_events (request_id, step, at, kind, detail) VALUES (?, ?, ?, ?, ?)").run(e,n,s,i,r.replace(/\s+/g," ").trim().slice(0,Pi))}events(e,n=200){return this.db.prepare("SELECT request_id, step, at, kind, detail FROM request_plan_events WHERE request_id = ? ORDER BY at, rowid LIMIT ?").all(e,n).map(i=>({requestId:i.request_id,step:i.step??null,at:i.at,kind:i.kind,detail:i.detail}))}},ll=$t;import{existsSync as Oi,readFileSync as Mi}from"fs";Tt();ni();function An(t){let e=Ct(t),n={};if(Oi(e))try{n=It(JSON.parse(Mi(e,"utf-8")))}catch{n={}}let i=ke.safeParse(n?.requests);return i.success?i.data:ke.parse(void 0)}async function gl(t,e={}){let n=(t.channels??[]).filter(i=>!be.has(i.toLowerCase().split("@")[0]));return n.length?{success:!1,error:`unknown channel ${n.map(i=>`"${i}"`).join(", ")}: use ${[...be].join(", ")}`}:Dt(i=>{let r=i.requests??={};for(let s of["enabled","channels","from","staleAfterHours","retentionDays"])t[s]!==void 0&&(r[s]=t[s]);if(t.plans){let s=r.plans??={};for(let a of["enabled","stallMinutes","maxNudges","approveKinds","disabledAgents","requireForWork","requireOverMinutes"])t.plans[a]!==void 0&&(s[a]=t.plans[a])}if(t.checkers){let s=r.checkers??={};for(let a of["enabled","checkEveryMinutes"])t.checkers[a]!==void 0&&(s[a]=t.checkers[a])}},{configPath:e.configPath,reload:e.reload})}var In=["card","schedule","memory","wiki","whatsapp","request"],Wi=280;function N(t,e=Wi){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Te(t){if(t.configPath)return _(t.configPath);let e=[_(t.root,"agentx.json"),_(t.root,".agentx","config.json")];return e.find(n=>H(n))??e[0]}function Ce(t){return t.wikiDir?_(t.wikiDir):_(t.root,".agentx","wiki")}function Vi(t){return j(t.root,"pending").map(Ui)}function Ui(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,...t.node?{node:t.node}:{},created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.draft?{draft:t.draft}:{},...t.context||t.draft?{detail:N([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function Bi(t){let e=Te(t);if(!H(e))return[];let n;try{n=JSON.parse(Fi(e,"utf-8"))}catch{return[]}let i=new Date(t.now??Date.now()),r=[];for(let[s,a]of Object.entries(n?.crons??{})){let o=a?.approval;if(!o||o.action!=="create"&&o.action!=="delete")continue;let l=a.timezone||"UTC",c=a.schedule?Mt(a.schedule):"",u=a.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${a.schedule})`:"no schedule",d=String(a.prompt??a.command??""),p=o.action==="create";r.push({key:`schedule:${s}`,kind:"schedule",title:p?`New schedule "${s}" for ${a.agent??"an agent"}`:`Delete schedule "${s}"`,ask:p?`Let ${a.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(o.requestedBy??"unknown"),created_at:String(o.requestedAt??""),detail:N(`${d}${p&&a.schedule?` \xB7 first run ${Ft(jt(a.schedule,l,i),l)}`:""}`),more:"agentx schedule list"})}return r}function En(t){let e=_(t,".agentx","memory");return H(e)?ji(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function qi(t){let e=En(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:N(s.content),more:`agentx memory facts held --agent ${r}`});return i}function Hi(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 zi(t){return Xt(Ce(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:N(`${Hi(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function Xi(t){return Sn(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:N(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}function z(t){if(t.requests)return t.requests;if(_(t.root)!==process.cwd()||!H(_(t.root,".agentx","db.sqlite")))return null;let e=we({quiet:!0});if(!e)return null;let n=_n.get(e);return!n&&!At(e)?null:(n||_n.set(e,n=new _t(e)),n)}var _n=new WeakMap;function El(t){if(t.plans)return t.plans;if(t.requests||_(t.root)!==process.cwd()||!H(_(t.root,".agentx","db.sqlite")))return null;let e=we({quiet:!0});if(!e||!$n(e))return null;let n=Rn.get(e);return n||Rn.set(e,n=new se(e)),n}var Rn=new WeakMap;function Gi(t){let e=z(t);return e?e.listByState("needs_attention").map(n=>({key:`request:${n.id}`,kind:"request",title:`Request not finished: ${N(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:N(`${n.attentionReason??"It needs attention"}. Asked on ${n.channel}: ${n.text}`),more:`agentx requests show ${n.id}`})):[]}var Tn={card:Vi,schedule:Bi,memory:qi,wiki:zi,whatsapp:Xi,request:Gi};function Ki(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 Tl(t,e={}){let n=t.now??Date.now(),{snoozed:i}=x(t.root),r=[],s=[],a=0;for(let o of e.kinds??In){let l;try{l=Tn[o](t)}catch(c){s.push({kind:o,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=i[c.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){a++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(Ki),{items:r,snoozed:a,errors:s}}function Ji(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 Yi(t,e,n){switch(e){case"card":return B(t.root,n)?.status==="pending";case"wiki":return zt(Ce(t),n)?.status==="pending";case"whatsapp":return ie(t.root,n)?.status==="pending";default:return Tn[e](t).some(i=>i.key===`${e}:${n}`)}}async function Cn(t,e,n,i={}){let r=Ji(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:s,ref:a}=r,o=t.now??Date.now(),l=i.by??"operator";if(n==="later"){if(!Yi(t,s,a))return{ok:!1,error:`nothing waiting for "${e}"`};let u=i.laterHours&&i.laterHours>0?i.laterHours:24,d=new Date(o+u*36e5);return fn(t.root,e,d,o),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(s){case"card":{let u=tn(t.root,a,c?"yes":"no",{by:l,note:i.note,now:o,choice:i.choice,text:i.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}${u.card.choice?` (${u.card.choice}${u.card.choice_suggested?", the suggested option":""})`:""}`}:u}case"schedule":{let u=await(c?Wt:Vt)(a,{configPath:Te(t),reload:t.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=a.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=a.slice(0,u),p=a.slice(u+1);if(!En(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,c?"approved":"rejected",l),{ok:!0,message:`${e} ${c?"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=Ce(t),d=c?Gt(u,a,{by:l,force:i.force,now:o}):Kt(u,a,{by:l,reason:i.note,now:o});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await xn(t.root,a,c?"yes":"no",{by:l,now:o,send:t.sendWhatsApp});return u.ok?{ok:!0,message:c?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}case"request":{let u=z(t),d=u?.get(a);return!u||!d||d.state!=="needs_attention"?{ok:!1,error:`nothing waiting for "${e}"`}:c?An(Te(t)).enabled?(u.requestPickup(a,o),{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(a,"dropped",i.note?.trim()||`dropped by ${l}`,o),{ok:!0,message:`${e}: dropped`})}}}var Dn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Dl(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/native/notes"||t==="/requests"||t.startsWith("/requests/")||t==="/watchers"||t.startsWith("/watchers/")||t==="/follow-up"||t.startsWith("/follow-up/")||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/")||t==="/wiki/agents"||t==="/wiki/entries"||t==="/wiki/articles"||t==="/wiki/article"||t==="/wiki/notes"||t==="/api/wiki/curate"||t==="/api/wiki/curate/restore"||t==="/api/signals/stopped"||t.startsWith("/api/signals/stopped/")||t==="/api/review-gate/reviews"}function Pl(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)||/^\/workflow-runs\/[^/]+\/cancel$/.test(t)||t==="/api/signals/stop"||t==="/api/signals/resume"||t==="/api/signals/drop"||t==="/api/review-gate/replay"}function Nl(t){return Dn.has(t)}function Ll(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 Ol(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 Ml(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 oe(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function Zi(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function Qi(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Fl(t,e=Qi()){let n=oe(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=Zi(n),s=[oe(t.host),oe(t["x-forwarded-host"])].filter(Boolean).map(a=>a.toLowerCase());return r&&s.includes(r)?"same-origin":"foreign"}let i=oe(t["sec-fetch-site"]).toLowerCase();return i==="cross-site"||i==="same-site"?"foreign":"none"}function Wl(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as rr,mkdirSync as Is,readFileSync as Es,renameSync as Ts,writeFileSync as Cs}from"fs";import{homedir as Ds}from"os";import{dirname as Ps,join as Ns}from"path";import{execFile as us,execFileSync as ds}from"child_process";import{execFileSync as es}from"child_process";import{existsSync as Nn,mkdirSync as ts,readdirSync as ns,readFileSync as Ln,renameSync as rs,writeFileSync as is}from"fs";import{homedir as On}from"os";import{join as Pe}from"path";var v="siri:",Mn="com.apple.ttsbundle.gryphon-neural_",jn=t=>!!t&&t.startsWith(Mn),ss=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],os=()=>{try{return es("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},De;function Ne(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&De!==void 0)return De;let{platform:n=process.platform,exists:i=Nn,prefDomain:r=os}=t,s=n==="darwin"&&ss.every(a=>i(a))&&r();return e||(De=s),s}var Fn=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Wn={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=>Wn[t.toLowerCase()]??null;function ae(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 as=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function ls(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(as)){let a=`${i}-${r}`,o=`${Mn}${s}_${a}_premium`;e.has(o)||e.set(o,{id:o,name:s[0].toUpperCase()+s.slice(1),locale:a,quality:"premium",gender:Wn[s]??null,siri:!0})}return[...e.values()]}function le(t=Fn,e={}){if(!Ne(e))return[];let n=[];for(let i of t){let r;try{r=ns(i)}catch{continue}for(let s of r)try{n.push(Ln(Pe(i,s,"Info.plist"),"latin1"))}catch{}}return ls(n)}var Pn=`#!/bin/sh
56
56
  # Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
57
57
  # siri-say.sh [voice] < text speak one line. A Siri voice id switches
58
58
  # the OS default for it; any other id is
@@ -64,7 +64,7 @@ D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
64
64
  dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
65
65
  stops="$dir/stop"
66
66
  read_s=\${AGENTX_SAY_READ_S:-5} stale_s=\${AGENTX_SAY_STALE_S:-30} max_s=\${AGENTX_SAY_MAX_S:-300}
67
- assets=\${AGENTX_SIRI_ASSET_DIRS:-"${jn.join(" ")}"}
67
+ assets=\${AGENTX_SIRI_ASSET_DIRS:-"${Fn.join(" ")}"}
68
68
  if [ "$1" = --stop ]; then
69
69
  mkdir -p "$dir" || exit 1
70
70
  # Queued lines see this change and drop. The owner's trap stops say,
@@ -157,31 +157,31 @@ wait "$say_pid"
157
157
  status=$?
158
158
  say_pid=
159
159
  finish $status
160
- `,ls=(t=Nn())=>Pe(t,".agentx","voice","siri-say.sh");function Wn(t=Nn()){let e=ls(t);return Pn(e)&&Ln(e,"utf8")===Dn||(es(Pe(t,".agentx","voice"),{recursive:!0}),rs(`${e}.tmp`,Dn,{mode:493}),ns(`${e}.tmp`,e)),e}var Un=`ObjC.import("AVFoundation")
160
+ `,cs=(t=On())=>Pe(t,".agentx","voice","siri-say.sh");function Vn(t=On()){let e=cs(t);return Nn(e)&&Ln(e,"utf8")===Pn||(ts(Pe(t,".agentx","voice"),{recursive:!0}),is(`${e}.tmp`,Pn,{mode:493}),rs(`${e}.tmp`,e)),e}var Un=`ObjC.import("AVFoundation")
161
161
  const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
162
162
  for (let i = 0; i < vs.count; i++) {
163
163
  const v = vs.objectAtIndex(i)
164
164
  out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
165
165
  }
166
- out.join("\\n")`,ds=new Set(["Fred","Kathy","Ralph","Junior"]),ps={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 Vn(t){let e=[];for(let n of t.split(`
167
- `)){let[i,r,s,a,o]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!ds.has(r)||e.push({id:i,name:r,locale:s,quality:a==="3"?"premium":a==="2"?"enhanced":"standard",gender:o==="1"?"male":o==="2"?"female":ps[r]??null})}return e}var fs=10*60*1e3,Kl=60*1e3,F=null,Oe=!1;function Me(t=Date.now(),e=fs){if(process.platform!=="darwin")return[];if(F)t-F.at>e&&!Oe&&(Oe=!0,cs("osascript",["-l","JavaScript","-e",Un],{timeout:1e4},(n,i)=>{Oe=!1,n||(F={at:Date.now(),voices:[...Vn(String(i)),...le()]})}));else try{F={at:t,voices:[...Vn(us("osascript",["-l","JavaScript","-e",Un],{encoding:"utf8",timeout:1e4})),...le()]}}catch(n){je(`[voice] could not list system voices: ${String(n?.message??n).split(`
166
+ out.join("\\n")`,ps=new Set(["Fred","Kathy","Ralph","Junior"]),fs={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 Bn(t){let e=[];for(let n of t.split(`
167
+ `)){let[i,r,s,a,o]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!ps.has(r)||e.push({id:i,name:r,locale:s,quality:a==="3"?"premium":a==="2"?"enhanced":"standard",gender:o==="1"?"male":o==="2"?"female":fs[r]??null})}return e}var gs=10*60*1e3,Kl=60*1e3,F=null,Oe=!1;function Me(t=Date.now(),e=gs){if(process.platform!=="darwin")return[];if(F)t-F.at>e&&!Oe&&(Oe=!0,us("osascript",["-l","JavaScript","-e",Un],{timeout:1e4},(n,i)=>{Oe=!1,n||(F={at:Date.now(),voices:[...Bn(String(i)),...le()]})}));else try{F={at:t,voices:[...Bn(ds("osascript",["-l","JavaScript","-e",Un],{encoding:"utf8",timeout:1e4})),...le()]}}catch(n){je(`[voice] could not list system voices: ${String(n?.message??n).split(`
168
168
  `)[0]}`),F={at:t,voices:le()}}return F.voices}var je=t=>process.stderr.write(t+`
169
- `),ce=new Set;function Jl(t){je=t}function N(t,e){ce.has(t)||(ce.add(t),je(e))}function Hn(t){for(let e of ce)t(e)&&ce.delete(e)}var zn=()=>{};function Yl(t){zn=t}function Xn(t){try{zn(t)}catch(e){N("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var gs={premium:3,enhanced:2,standard:1},ms=new Set(["Grandma","Grandpa"]);function Bn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!ms.has(t.name)?1:0;return gs[t.quality]*10+e}var W=t=>t.toLowerCase().split(/[-_]/)[0],qn=t=>t.id.startsWith("com.apple.voice.");function Fe(t,e,n,i=new Set){let r=X(t.filter(o=>!o.siri&&W(o.locale)===W(e)),e);if(r.some(qn)&&(r=r.filter(qn)),n==="female"||n==="male"){let o=r.filter(l=>l.gender===n);o.length&&(r=o)}if(!r.length)return null;let s=r.filter(o=>o.quality===r[0].quality),a=new Set([...i].map(o=>o.toLowerCase()));return s.find(o=>!a.has(o.name.toLowerCase()))??s[0]}function X(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=W(e),r=t.filter(s=>W(s.locale)===i);return(r.length?r:t).slice().sort((s,a)=>Bn(a)-Bn(s)||+(a.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(a.name)||s.locale.localeCompare(a.locale))}function G(t,e,n="en"){let i=t.trim();if(!i)return null;let r=e.find(c=>c.id===i);if(r)return r;if(i.toLowerCase().startsWith(v)){let c=i.slice(v.length).trim().toLowerCase(),u=X(e.filter(p=>p.siri&&p.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=G(c,e.filter(p=>W(p.locale)===W(n)),n);return d&&N(`siri:${c}`,`[voice] Siri voice "${c}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(c=>!c.siri);let s=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(i),a=(s?s[1]:i.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),o=X(e.filter(c=>c.name.toLowerCase()===a),n);return(s?o.find(c=>c.quality===s[2].toLowerCase()):void 0)??o[0]??null}function Gn(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(a=>a.toLowerCase())),s="female";for(let a of t){let o=a.gender==="female"||a.gender==="male",l=o?a.gender:s,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(o?e.find(d=>d.gender===l):void 0)??c[0]??e[i.size%e.length];i.set(a.id,u),r.add(u.name.toLowerCase()),o||(s=s==="female"?"male":"female")}return i}xt();var We="system",hs=t=>t.trim().toLowerCase()===We,ys="21m00Tcm4TlvDq8ikWAM";function Ue(t,e,n={},i=Me()){let r=e[t],s=r?.name||t,a=r?.voice,o=Be(e,n,i).get(t)??null,l=Ss(t,a?.system,a?.gender,n,i);return{agentId:t,name:s,provider:a?.provider??n.provider??"system",elevenlabsVoiceId:a?.elevenlabsVoiceId||null,systemVoice:o?.id??null,systemVoiceName:o?de(o):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:a?.gender??null,style:a?.style||null,intro:a?.intro||vs(s,r?.systemPrompt),...a?.rate?{rate:a.rate}:{},...a?.priority?{priority:a.priority}:{}}}var de=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function bs(t,e,n,i){if(!e||!n.length)return null;let r=G(e,n,i);return r||(N(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),Xn(e)),r}function Zn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(v))return{locale:e,gender:Ne(n.slice(v.length).trim())};let i=ae(n);return i?{locale:i.locale,gender:Ne(i.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var Qn=t=>t.toLowerCase().split(/[-_]/)[0],Kn=(t,e)=>typeof t=="string"?t:t?.[Qn(e)];function ue(t,e,n,i){if(e!==void 0)return hs(e)?null:bs(t,e,n,i)??void 0}var Ve=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function ws(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,a=[],o=ue("voice.system",Kn(e.system,r),n,r),l=()=>new Set([...i,...[...s.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=Kn(u.system,r),p=ue(u.id,d,n,r),f=p!==void 0?p:d!==void 0&&n.length?ks(u,d,r,o,n,l()):o!==void 0&&Ve(o,u.gender)?o:void 0;f!==void 0?s.set(u.id,f):a.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of Gn(a,X(n.filter(p=>!p.siri),r),c))s.set(u,d);return s}function ks(t,e,n,i,r,s){for(let o of t.fallbacks??[]){let l=ue(`${t.id}.fallbacks`,o,r,n);if(l!==void 0)return l}if(i!==void 0&&Ve(i,t.gender))return i;let a=Zn(e,n);return Fe(r,a.locale,t.gender??a.gender,s)??void 0}function Ss(t,e,n,i,r){if(typeof e=="string")return{};let s={},a=(o,l,c)=>{if(!(!l||typeof l=="string"))for(let[u,d]of Object.entries(l)){let p=ue(`${o}.${u}`,d,r,u);p===void 0&&r.length&&(p=Fe(r,u,n??Zn(d,u).gender)??void 0),p!==void 0&&c(p)&&(s[Qn(u)]=p)}};return a("voice.system",i.system,o=>Ve(o,n)),a(t,e,()=>!0),s}function nc(t,e){let n=e?ee(e):null;if(!n||!(n in t.systemByLanguage))return t;let i=t.systemByLanguage[n];return{...t,systemVoice:i?.id??null,systemVoiceName:i?de(i):null}}function Be(t,e={},n=Me()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return ws(i,e,n)}function qe(t,e){let n={provider:t.provider,elevenlabs:xs(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 xs(t,e){return t||e||process.env.AGENTX_VOICE_ID||ys}function vs(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,...a]=r.split(/,\s*/),o=a.join(", ");return o&&s.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${o}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var $s=8*60*60*1e3,As=500,Jn=class{constructor(e=$s){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Yn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Yn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>As&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Yn=(t,e)=>`${t}\0${e}`;function er(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 rc(t,e,n,i={}){let r=e[t],s=Ue(t,e,i),a=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:qe(s),persona:a||`You are ${s.name}.`,introLine:er(s,n)}}var _s="[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 ic(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`${_s}
170
- ${er(r,e.voice.introduce===!0&&!!i)}`}var Ls="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",rr=(t=Cs())=>Ps(t,".agentx","voice","health.json");function Ns(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===We)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 G(i,e,n)!==null}function Os(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[a,o]of Object.entries(s??{}))n.push({owner:r,name:o,locale:a,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 Ms(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:a,perLanguage:o}of Os(t)){if(Ns(s,e,a))continue;i??=Be(t.agents,t.voice,e);let l=n.get(s)??{voice:s,agents:[],speaksWith:{}};l.agents.includes(r)||l.agents.push(r);let c=i.get(r);r!=="voice.system"&&!o&&(l.speaksWith[r]=c?de(c):"the OS default voice"),n.set(s,l)}return[...n.values()]}function He(t){let e=ae(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 js(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${He(n.voice)}: ${i}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
169
+ `),ce=new Set;function Jl(t){je=t}function L(t,e){ce.has(t)||(ce.add(t),je(e))}function zn(t){for(let e of ce)t(e)&&ce.delete(e)}var Xn=()=>{};function Yl(t){Xn=t}function Gn(t){try{Xn(t)}catch(e){L("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var ms={premium:3,enhanced:2,standard:1},hs=new Set(["Grandma","Grandpa"]);function qn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!hs.has(t.name)?1:0;return ms[t.quality]*10+e}var W=t=>t.toLowerCase().split(/[-_]/)[0],Hn=t=>t.id.startsWith("com.apple.voice.");function Fe(t,e,n,i=new Set){let r=X(t.filter(o=>!o.siri&&W(o.locale)===W(e)),e);if(r.some(Hn)&&(r=r.filter(Hn)),n==="female"||n==="male"){let o=r.filter(l=>l.gender===n);o.length&&(r=o)}if(!r.length)return null;let s=r.filter(o=>o.quality===r[0].quality),a=new Set([...i].map(o=>o.toLowerCase()));return s.find(o=>!a.has(o.name.toLowerCase()))??s[0]}function X(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=W(e),r=t.filter(s=>W(s.locale)===i);return(r.length?r:t).slice().sort((s,a)=>qn(a)-qn(s)||+(a.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(a.name)||s.locale.localeCompare(a.locale))}function G(t,e,n="en"){let i=t.trim();if(!i)return null;let r=e.find(c=>c.id===i);if(r)return r;if(i.toLowerCase().startsWith(v)){let c=i.slice(v.length).trim().toLowerCase(),u=X(e.filter(p=>p.siri&&p.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=G(c,e.filter(p=>W(p.locale)===W(n)),n);return d&&L(`siri:${c}`,`[voice] Siri voice "${c}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(c=>!c.siri);let s=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(i),a=(s?s[1]:i.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),o=X(e.filter(c=>c.name.toLowerCase()===a),n);return(s?o.find(c=>c.quality===s[2].toLowerCase()):void 0)??o[0]??null}function Kn(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(a=>a.toLowerCase())),s="female";for(let a of t){let o=a.gender==="female"||a.gender==="male",l=o?a.gender:s,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(o?e.find(d=>d.gender===l):void 0)??c[0]??e[i.size%e.length];i.set(a.id,u),r.add(u.name.toLowerCase()),o||(s=s==="female"?"male":"female")}return i}xt();var We="system",ys=t=>t.trim().toLowerCase()===We,bs="21m00Tcm4TlvDq8ikWAM";function Ve(t,e,n={},i=Me()){let r=e[t],s=r?.name||t,a=r?.voice,o=Be(e,n,i).get(t)??null,l=xs(t,a?.system,a?.gender,n,i);return{agentId:t,name:s,provider:a?.provider??n.provider??"system",elevenlabsVoiceId:a?.elevenlabsVoiceId||null,systemVoice:o?.id??null,systemVoiceName:o?de(o):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:a?.gender??null,style:a?.style||null,intro:a?.intro||$s(s,r?.systemPrompt),...a?.rate?{rate:a.rate}:{},...a?.priority?{priority:a.priority}:{}}}var de=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function ws(t,e,n,i){if(!e||!n.length)return null;let r=G(e,n,i);return r||(L(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),Gn(e)),r}function Qn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(v))return{locale:e,gender:Le(n.slice(v.length).trim())};let i=ae(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 er=t=>t.toLowerCase().split(/[-_]/)[0],Jn=(t,e)=>typeof t=="string"?t:t?.[er(e)];function ue(t,e,n,i){if(e!==void 0)return ys(e)?null:ws(t,e,n,i)??void 0}var Ue=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function ks(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,a=[],o=ue("voice.system",Jn(e.system,r),n,r),l=()=>new Set([...i,...[...s.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=Jn(u.system,r),p=ue(u.id,d,n,r),f=p!==void 0?p:d!==void 0&&n.length?Ss(u,d,r,o,n,l()):o!==void 0&&Ue(o,u.gender)?o:void 0;f!==void 0?s.set(u.id,f):a.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of Kn(a,X(n.filter(p=>!p.siri),r),c))s.set(u,d);return s}function Ss(t,e,n,i,r,s){for(let o of t.fallbacks??[]){let l=ue(`${t.id}.fallbacks`,o,r,n);if(l!==void 0)return l}if(i!==void 0&&Ue(i,t.gender))return i;let a=Qn(e,n);return Fe(r,a.locale,t.gender??a.gender,s)??void 0}function xs(t,e,n,i,r){if(typeof e=="string")return{};let s={},a=(o,l,c)=>{if(!(!l||typeof l=="string"))for(let[u,d]of Object.entries(l)){let p=ue(`${o}.${u}`,d,r,u);p===void 0&&r.length&&(p=Fe(r,u,n??Qn(d,u).gender)??void 0),p!==void 0&&c(p)&&(s[er(u)]=p)}};return a("voice.system",i.system,o=>Ue(o,n)),a(t,e,()=>!0),s}function nc(t,e){let n=e?ee(e):null;if(!n||!(n in t.systemByLanguage))return t;let i=t.systemByLanguage[n];return{...t,systemVoice:i?.id??null,systemVoiceName:i?de(i):null}}function Be(t,e={},n=Me()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return ks(i,e,n)}function qe(t,e){let n={provider:t.provider,elevenlabs:vs(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 vs(t,e){return t||e||process.env.AGENTX_VOICE_ID||bs}function $s(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,...a]=r.split(/,\s*/),o=a.join(", ");return o&&s.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${o}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var As=8*60*60*1e3,_s=500,Yn=class{constructor(e=As){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Zn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Zn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>_s&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Zn=(t,e)=>`${t}\0${e}`;function tr(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 rc(t,e,n,i={}){let r=e[t],s=Ve(t,e,i),a=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:qe(s),persona:a||`You are ${s.name}.`,introLine:tr(s,n)}}var Rs="[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 ic(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`${Rs}
170
+ ${tr(r,e.voice.introduce===!0&&!!i)}`}var Ls="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",ir=(t=Ds())=>Ns(t,".agentx","voice","health.json");function Os(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===We)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 G(i,e,n)!==null}function Ms(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[a,o]of Object.entries(s??{}))n.push({owner:r,name:o,locale:a,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 js(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:a,perLanguage:o}of Ms(t)){if(Os(s,e,a))continue;i??=Be(t.agents,t.voice,e);let l=n.get(s)??{voice:s,agents:[],speaksWith:{}};l.agents.includes(r)||l.agents.push(r);let c=i.get(r);r!=="voice.system"&&!o&&(l.speaksWith[r]=c?de(c):"the OS default voice"),n.set(s,l)}return[...n.values()]}function He(t){let e=ae(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 Fs(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${He(n.voice)}: ${i}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
171
171
  `)}
172
- Reinstall in ${Ls}. Agents switch back on their own once it is installed.`}}function Fs(t=rr()){if(!nr(t))return null;try{let e=JSON.parse(Is(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function Ws(t,e){Rs(Ds(t),{recursive:!0}),Ts(`${t}.tmp`,JSON.stringify(e,null,2)+`
173
- `),Es(`${t}.tmp`,t)}var tr=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??rr(),s=new Map((Fs(r)?.missing??[]).map(d=>[d.voice,d])),a=Ms(e,n),o=a.map(d=>({...d,since:s.get(d.voice)?.since??i.toISOString(),...s.get(d.voice)?.notifiedAt?{notifiedAt:s.get(d.voice).notifiedAt}:{}})),l=[...s.keys()].filter(d=>!a.some(p=>p.voice===d));for(let d of l)this.deps.log(`[voice] ${He(d)} is installed again; its agents speak with it again`);l.length&&Hn(d=>l.some(p=>d===p||d.endsWith(`:${p}`)));let c=o.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:p}=js(c);try{await this.deps.notify(d,p);for(let f of c)f.notifiedAt=i.toISOString();this.deps.log(`[voice] told the owner: ${c.map(f=>He(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=o.length>0;let u={checkedAt:i.toISOString(),missing:o};return(!nr(r)||JSON.stringify(o)!==JSON.stringify([...s.values()]))&&Ws(r,u),u}finally{this.running=!1}}};import{readFileSync as Xe,writeFileSync as cr,existsSync as Ge,readdirSync as Ks,statSync as Js}from"fs";import{resolve as Ke,join as Ys}from"path";import{existsSync as ir,mkdirSync as Us,readFileSync as Vs,writeFileSync as sr}from"fs";import{dirname as Bs,resolve as or}from"path";import{z as m}from"zod";var qs=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),Hs=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:qs.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),zs=m.object({version:m.literal(1),items:m.array(Hs).default([])}),pe=class{constructor(e){this.path=e}jsonPath(){return or(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return or(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return ir(this.jsonPath())}load(){let e=this.jsonPath();if(!ir(e))return{version:1,items:[]};let n=Vs(e,"utf-8");try{return zs.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();Us(Bs(n),{recursive:!0}),sr(n,JSON.stringify(e,null,2)+`
174
- `),sr(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(a=>a.id)),r=new Date().toISOString(),s=[];for(let a of e){if(i.has(a.id))continue;let o={...a,labels:a.labels??[],status:a.status??"todo",createdAt:a.createdAt??r,updatedAt:r};n.items.push(o),s.push(o),i.add(o.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(a=>a.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,a]of r)if(i[s].length){n.push(`## ${a}`,"");for(let o of i[s]){let l=s==="done"?"x":" ",c=o.assignee?`@${o.assignee} `:"",u=o.estimatedSeconds?` [time: ${Math.round(o.estimatedSeconds/60)}m]`:"",d=o.source?` (${o.source.type}: ${o.source.project}#${o.source.iid})`:"";n.push(`- [${l}] ${c}${o.title}${u}${d}`),o.source?.url&&n.push(` - <${o.source.url}>`),o.labels.length&&n.push(` - labels: ${o.labels.join(", ")}`),o.milestone&&n.push(` - milestone: ${o.milestone}`),o.blocker&&n.push(` - BLOCKED: ${o.blocker}`)}n.push("")}return n.join(`
175
- `)}};function hc(t){return`${t.type}:${t.project}:${t.iid}`}function ar(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let a=r.find(o=>o.agentId===s);a?.gitlabUsernames?.length?i.push(a.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let a=r.find(o=>o.agentId===s);a?.githubUsernames?.length?i.push(a.githubUsernames[0]):i.push(s)}}return i}async function ze(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?Xs(t.source,e,n,i):t.source.type==="github"?Gs(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function Xs(t,e,n,i){let r=n.channels.gitlab,s=r?.token,a=r?.host||(t.host?`https://${t.host}`:void 0);if(!s||!a)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let o=[],l=async(f,g={})=>fetch(`${a}/api/v4${f}`,{...g,headers:{"PRIVATE-TOKEN":s,"Content-Type":"application/json",...g.headers||{}}}),c=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async g=>{try{let h=await fetch(`${a}/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 l(`/projects/${c}/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 l(`/projects/${c}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(p)});if(o.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let g=await f.text().catch(()=>"");return{ok:!1,attempts:o,error:`PUT issue ${f.status}: ${g.slice(0,200)}`,url:t.url}}}catch(f){return o.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:o,error:f.message,url:t.url}}if(e.note)try{let f=await l(`/projects/${c}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){o.push({kind:"POST note",ok:!1,error:f.message})}return{ok:o.every(f=>f.ok),attempts:o,url:t.url}}async function Gs(t,e,n,i){let s=n.channels.github?.token;if(!s)return{ok:!1,error:"github token not configured",attempts:[]};let a=[],o=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||{}}}),l=t.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let p=await o(`/repos/${l}/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&&(c=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 o(`/repos/${l}/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),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let p=await o(`/repos/${l}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(a.push({kind:"PATCH issue",ok:p.ok,status:p.status}),!p.ok){let f=await p.text().catch(()=>"");return{ok:!1,attempts:a,error:`PATCH issue ${p.status}: ${f.slice(0,200)}`,url:t.url}}}catch(p){return a.push({kind:"PATCH issue",ok:!1,error:p.message}),{ok:!1,attempts:a,error:p.message,url:t.url}}if(e.note)try{let p=await o(`/repos/${l}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST comment",ok:p.ok,status:p.status})}catch(p){a.push({kind:"POST comment",ok:!1,error:p.message})}return{ok:a.every(p=>p.ok),attempts:a,url:t.url}}var Je=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,fe=/@([a-z0-9_-]+)/i,lr=/\[time:\s*([0-9hm\s]+)\]/i;function Zs(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 Ye=class{constructor(e,n,i=()=>{}){this.path=e;this.daemon=n;this.log=i;this.store=new pe(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Ke(process.cwd(),this.path);return Ge(e)?Xe(e,"utf-8").split(`
176
- `):[]}writeMd(e){let n=Ke(process.cwd(),this.path);cr(n,e.join(`
177
- `))}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(Je);if(!s||s[2].toLowerCase()==="x")continue;let o=s[3],l=o.match(fe);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=o.match(lr),u=o.replace(fe,"").replace(lr,"").trim();i.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?Zs(c[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=ar([r.assignee||e],r.source,this.daemon);ze(r,{assigneeUsernames:s,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(a=>this.log(`[backlog-sync] claim failed for ${n}: ${a?.message??a}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let o={};n.status==="done"?o.status="done":n.status==="blocked"?(o.status="blocked",o.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(o.status="doing"),n.timeSeconds&&(o.estimatedSeconds=n.timeSeconds);let l=this.store.update(e,o);if(l.source&&this.daemon){let c={};n.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):n.status==="blocked"&&(c.addLabels=["Blocked"]),n.note&&(c.note=n.note),Object.keys(c).length&&ze(l,c,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(Je))throw new Error(`backlog line ${i} not a checkbox`);if(n.status==="done"){r[i]=s.replace(/- \[ \]/,"- [x]");let o=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(i+1,0,o)}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"}}},Ze=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(Ge(e))for(let i of Ks(e)){let r=Ys(e,i);Js(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Ke(process.cwd(),this.root),n);let i=[];for(let r of n){let s=Xe(r,"utf-8").split(`
172
+ Reinstall in ${Ls}. Agents switch back on their own once it is installed.`}}function Ws(t=ir()){if(!rr(t))return null;try{let e=JSON.parse(Es(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function Vs(t,e){Is(Ps(t),{recursive:!0}),Cs(`${t}.tmp`,JSON.stringify(e,null,2)+`
173
+ `),Ts(`${t}.tmp`,t)}var nr=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??ir(),s=new Map((Ws(r)?.missing??[]).map(d=>[d.voice,d])),a=js(e,n),o=a.map(d=>({...d,since:s.get(d.voice)?.since??i.toISOString(),...s.get(d.voice)?.notifiedAt?{notifiedAt:s.get(d.voice).notifiedAt}:{}})),l=[...s.keys()].filter(d=>!a.some(p=>p.voice===d));for(let d of l)this.deps.log(`[voice] ${He(d)} is installed again; its agents speak with it again`);l.length&&zn(d=>l.some(p=>d===p||d.endsWith(`:${p}`)));let c=o.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:p}=Fs(c);try{await this.deps.notify(d,p);for(let f of c)f.notifiedAt=i.toISOString();this.deps.log(`[voice] told the owner: ${c.map(f=>He(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=o.length>0;let u={checkedAt:i.toISOString(),missing:o};return(!rr(r)||JSON.stringify(o)!==JSON.stringify([...s.values()]))&&Vs(r,u),u}finally{this.running=!1}}};import{readFileSync as Xe,writeFileSync as ur,existsSync as Ge,readdirSync as Js,statSync as Ys}from"fs";import{resolve as Ke,join as Zs}from"path";import{existsSync as sr,mkdirSync as Us,readFileSync as Bs,writeFileSync as or}from"fs";import{dirname as qs,resolve as ar}from"path";import{z as m}from"zod";var Hs=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),zs=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:Hs.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),Xs=m.object({version:m.literal(1),items:m.array(zs).default([])}),pe=class{constructor(e){this.path=e}jsonPath(){return ar(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return ar(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return sr(this.jsonPath())}load(){let e=this.jsonPath();if(!sr(e))return{version:1,items:[]};let n=Bs(e,"utf-8");try{return Xs.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();Us(qs(n),{recursive:!0}),or(n,JSON.stringify(e,null,2)+`
174
+ `),or(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(a=>a.id)),r=new Date().toISOString(),s=[];for(let a of e){if(i.has(a.id))continue;let o={...a,labels:a.labels??[],status:a.status??"todo",createdAt:a.createdAt??r,updatedAt:r};n.items.push(o),s.push(o),i.add(o.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(a=>a.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,a]of r)if(i[s].length){n.push(`## ${a}`,"");for(let o of i[s]){let l=s==="done"?"x":" ",c=o.assignee?`@${o.assignee} `:"",u=o.estimatedSeconds?` [time: ${Math.round(o.estimatedSeconds/60)}m]`:"",d=o.source?` (${o.source.type}: ${o.source.project}#${o.source.iid})`:"";n.push(`- [${l}] ${c}${o.title}${u}${d}`),o.source?.url&&n.push(` - <${o.source.url}>`),o.labels.length&&n.push(` - labels: ${o.labels.join(", ")}`),o.milestone&&n.push(` - milestone: ${o.milestone}`),o.blocker&&n.push(` - BLOCKED: ${o.blocker}`)}n.push("")}return n.join(`
175
+ `)}};function hc(t){return`${t.type}:${t.project}:${t.iid}`}function lr(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let a=r.find(o=>o.agentId===s);a?.gitlabUsernames?.length?i.push(a.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let a=r.find(o=>o.agentId===s);a?.githubUsernames?.length?i.push(a.githubUsernames[0]):i.push(s)}}return i}async function ze(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?Gs(t.source,e,n,i):t.source.type==="github"?Ks(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function Gs(t,e,n,i){let r=n.channels.gitlab,s=r?.token,a=r?.host||(t.host?`https://${t.host}`:void 0);if(!s||!a)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let o=[],l=async(f,g={})=>fetch(`${a}/api/v4${f}`,{...g,headers:{"PRIVATE-TOKEN":s,"Content-Type":"application/json",...g.headers||{}}}),c=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async g=>{try{let h=await fetch(`${a}/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 l(`/projects/${c}/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 l(`/projects/${c}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(p)});if(o.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let g=await f.text().catch(()=>"");return{ok:!1,attempts:o,error:`PUT issue ${f.status}: ${g.slice(0,200)}`,url:t.url}}}catch(f){return o.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:o,error:f.message,url:t.url}}if(e.note)try{let f=await l(`/projects/${c}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){o.push({kind:"POST note",ok:!1,error:f.message})}return{ok:o.every(f=>f.ok),attempts:o,url:t.url}}async function Ks(t,e,n,i){let s=n.channels.github?.token;if(!s)return{ok:!1,error:"github token not configured",attempts:[]};let a=[],o=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||{}}}),l=t.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let p=await o(`/repos/${l}/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&&(c=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 o(`/repos/${l}/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),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let p=await o(`/repos/${l}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(a.push({kind:"PATCH issue",ok:p.ok,status:p.status}),!p.ok){let f=await p.text().catch(()=>"");return{ok:!1,attempts:a,error:`PATCH issue ${p.status}: ${f.slice(0,200)}`,url:t.url}}}catch(p){return a.push({kind:"PATCH issue",ok:!1,error:p.message}),{ok:!1,attempts:a,error:p.message,url:t.url}}if(e.note)try{let p=await o(`/repos/${l}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST comment",ok:p.ok,status:p.status})}catch(p){a.push({kind:"POST comment",ok:!1,error:p.message})}return{ok:a.every(p=>p.ok),attempts:a,url:t.url}}var Je=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,fe=/@([a-z0-9_-]+)/i,cr=/\[time:\s*([0-9hm\s]+)\]/i;function Qs(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 Ye=class{constructor(e,n,i=()=>{}){this.path=e;this.daemon=n;this.log=i;this.store=new pe(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Ke(process.cwd(),this.path);return Ge(e)?Xe(e,"utf-8").split(`
176
+ `):[]}writeMd(e){let n=Ke(process.cwd(),this.path);ur(n,e.join(`
177
+ `))}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(Je);if(!s||s[2].toLowerCase()==="x")continue;let o=s[3],l=o.match(fe);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=o.match(cr),u=o.replace(fe,"").replace(cr,"").trim();i.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?Qs(c[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=lr([r.assignee||e],r.source,this.daemon);ze(r,{assigneeUsernames:s,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(a=>this.log(`[backlog-sync] claim failed for ${n}: ${a?.message??a}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let o={};n.status==="done"?o.status="done":n.status==="blocked"?(o.status="blocked",o.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(o.status="doing"),n.timeSeconds&&(o.estimatedSeconds=n.timeSeconds);let l=this.store.update(e,o);if(l.source&&this.daemon){let c={};n.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):n.status==="blocked"&&(c.addLabels=["Blocked"]),n.note&&(c.note=n.note),Object.keys(c).length&&ze(l,c,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(Je))throw new Error(`backlog line ${i} not a checkbox`);if(n.status==="done"){r[i]=s.replace(/- \[ \]/,"- [x]");let o=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(i+1,0,o)}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"}}},Ze=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(Ge(e))for(let i of Js(e)){let r=Zs(e,i);Ys(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Ke(process.cwd(),this.root),n);let i=[];for(let r of n){let s=Xe(r,"utf-8").split(`
178
178
  `);for(let a=0;a<s.length;a++){let o=s[a].match(Je);if(!o||o[2].toLowerCase()==="x")continue;let l=o[3].match(fe);!l||l[1].toLowerCase()!==e.toLowerCase()||i.push({id:`wiki:${r}:${a}`,title:o[3].replace(fe,"").trim(),assignee:l[1],priority:a})}}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(!Ge(s))return;let a=Xe(s,"utf-8").split(`
179
- `);n.status==="done"&&a[r]&&(a[r]=a[r].replace(/- \[ \]/,"- [x]"),cr(s,a.join(`
180
- `)))}},Qe=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(c=>({name:c.name,color:c.color,text_color:c.text_color})),r=s.map(c=>c.name)):r=e.labels);let o=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=o[0]?.username;return{id:`gitlab:${i}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:o,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 a of r)try{let o=`assignee_username=${encodeURIComponent(s)}&state=opened&scope=all&per_page=20`,l=a==="__ALL__"?`/issues?${o}`:`/projects/${encodeURIComponent(a)}/issues?${o}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,a);d.assignee=e,i.push(d)}}catch(o){this.log(`[business] GitLab listOpen failed for ${s} on ${a}: ${o.message}`)}return i}async claim(e,n){let{project:i,iid:r,type:s}=this.parseId(n),a=`/projects/${encodeURIComponent(i)}/${s==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(a,{method:"PUT"})}catch(o){this.log(`[business] claim label update failed: ${o.message}`)}}async report(e,n){let{project:i,iid:r,type:s}=this.parseId(e),a=s==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let o=Math.max(1,Math.round(n.timeSeconds/60)),l=o>=60?`${Math.floor(o/60)}h${o%60?` ${o%60}m`:""}`:`${o}m`;try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(o){this.log(`[business] done label update failed: ${o.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(o){this.log(`[business] blocked label update failed: ${o.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(o){this.log(`[business] report note failed: ${o.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 a=this.projects.length?this.projects:["__ALL__"],o=[];for(let c of a)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let p of d)o.push(this.mapIssue(p,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=o;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,n){let{project:i,iid:r,type:s}=this.parseId(e),a=s==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(i)}/${a}/${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(a=>a.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 a;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")a=0;else try{let c=await this.api(`/projects/${encodeURIComponent(i)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(a=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${c.message}`)}let o={};n.title!==void 0&&(o.title=n.title),n.description!==void 0&&(o.description=n.description),n.labels!==void 0&&(o.labels=n.labels.join(",")),n.addLabels?.length&&(o.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(o.remove_labels=n.removeLabels.join(",")),s!==void 0&&(o.assignee_ids=s),a!==void 0&&(o.milestone_id=a);let l=await this.api(`/projects/${encodeURIComponent(i)}/issues/${r}`,{method:"PUT",body:JSON.stringify(o)});return this.mapIssue(l,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 c=>{try{let u=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${c}: ${u.message}`),null}}))).filter(c=>typeof c=="number"));let s;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(s=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let a={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};i?.length&&(a.assignee_ids=i),s!==void 0&&(a.milestone_id=s);let o=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(a)});return this.mapIssue(o,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:a}=this.parseId(e),o=a==="issue"?"issues":"merge_requests",l=new URLSearchParams;n.length&&l.set("add_labels",n.join(",")),i.length&&l.set("remove_labels",i.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${o}/${s}?${l.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 vc(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new Ye(i.path,e,n);case"wiki":return new Ze(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 o of r.agentMappings)o.gitlabUsernames.length&&(s[o.agentId]=o.gitlabUsernames);let a=i.projects.length?i.projects:r.routes.map(o=>o.project);return new Qe(r.host,r.token,a,s,n)}}}var et="unmapped";function tt(t,e=[]){if(!t)return et;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 Qs(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,tt(s.id,n)));let r=(s,a=new Set)=>{if(e.has(s))return e.get(s);if(a.has(s))return;a.add(s);let o=i[s]?.reportsTo;if(!o)return;let l=r(o,a);return l&&e.set(s,l),l};for(let s of Object.keys(i))r(s);return e}function eo(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 Ac(t,e){let n=eo(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return tt(t.project,e.projects);if(t.agentId){let i=Qs(e).get(t.agentId);if(i)return i}return et}function _c(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[i,r,...s]=n,a=s.join(":"),o={agentId:e||i,channel:r};return r==="gitlab"||r==="github"?o.project=a.split(":")[0]:r==="cron"||r==="api"||(o.chatId=a.split("@")[0]),o}var to=t=>t===et?"internal":"client";function no(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??to(t),respondWithinMinutes:ro(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Rc(t){let e=new Set;for(let n of t.projects??[])e.add(tt(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=>no(n,t))}function ro(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 io=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,so=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function ur(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(so)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=oo(i);if(!r)return{cleanText:t};let s=n.index??0,a=n[1]??"";return{cleanText:(t.slice(0,s)+a+t.slice(s+n[0].length)).trim(),ui:r}}function Ec(t){if(!t||!t.includes("agentx:ui"))return t;let e=io.exec(t);return e?t.slice(0,e.index).trimEnd():t}function oo(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 a of e.buttons)!a||typeof a.label!="string"||(typeof a.url=="string"&&/^https?:\/\//i.test(a.url)?i.push({label:a.label,url:a.url}):typeof a.reply=="string"&&a.reply.trim()?r.push({label:a.label,reply:a.reply.trim()}):a.action!=null&&s.push(a.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 Cc(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 ao=5*6e4;function D(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var dr=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(D)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${D(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 a=this.pendingKey(e,n),o=this.pending.get(a);if(o&&o.length){let l=Date.now(),c=o.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(a),c.length&&this.log(`flushed ${c.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
179
+ `);n.status==="done"&&a[r]&&(a[r]=a[r].replace(/- \[ \]/,"- [x]"),ur(s,a.join(`
180
+ `)))}},Qe=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(c=>({name:c.name,color:c.color,text_color:c.text_color})),r=s.map(c=>c.name)):r=e.labels);let o=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=o[0]?.username;return{id:`gitlab:${i}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:o,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 a of r)try{let o=`assignee_username=${encodeURIComponent(s)}&state=opened&scope=all&per_page=20`,l=a==="__ALL__"?`/issues?${o}`:`/projects/${encodeURIComponent(a)}/issues?${o}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,a);d.assignee=e,i.push(d)}}catch(o){this.log(`[business] GitLab listOpen failed for ${s} on ${a}: ${o.message}`)}return i}async claim(e,n){let{project:i,iid:r,type:s}=this.parseId(n),a=`/projects/${encodeURIComponent(i)}/${s==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(a,{method:"PUT"})}catch(o){this.log(`[business] claim label update failed: ${o.message}`)}}async report(e,n){let{project:i,iid:r,type:s}=this.parseId(e),a=s==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let o=Math.max(1,Math.round(n.timeSeconds/60)),l=o>=60?`${Math.floor(o/60)}h${o%60?` ${o%60}m`:""}`:`${o}m`;try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(o){this.log(`[business] done label update failed: ${o.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(o){this.log(`[business] blocked label update failed: ${o.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(i)}/${a}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(o){this.log(`[business] report note failed: ${o.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 a=this.projects.length?this.projects:["__ALL__"],o=[];for(let c of a)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let p of d)o.push(this.mapIssue(p,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=o;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,n){let{project:i,iid:r,type:s}=this.parseId(e),a=s==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(i)}/${a}/${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(a=>a.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 a;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")a=0;else try{let c=await this.api(`/projects/${encodeURIComponent(i)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(a=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${c.message}`)}let o={};n.title!==void 0&&(o.title=n.title),n.description!==void 0&&(o.description=n.description),n.labels!==void 0&&(o.labels=n.labels.join(",")),n.addLabels?.length&&(o.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(o.remove_labels=n.removeLabels.join(",")),s!==void 0&&(o.assignee_ids=s),a!==void 0&&(o.milestone_id=a);let l=await this.api(`/projects/${encodeURIComponent(i)}/issues/${r}`,{method:"PUT",body:JSON.stringify(o)});return this.mapIssue(l,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 c=>{try{let u=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${c}: ${u.message}`),null}}))).filter(c=>typeof c=="number"));let s;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(s=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let a={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};i?.length&&(a.assignee_ids=i),s!==void 0&&(a.milestone_id=s);let o=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(a)});return this.mapIssue(o,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:a}=this.parseId(e),o=a==="issue"?"issues":"merge_requests",l=new URLSearchParams;n.length&&l.set("add_labels",n.join(",")),i.length&&l.set("remove_labels",i.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${o}/${s}?${l.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 vc(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new Ye(i.path,e,n);case"wiki":return new Ze(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 o of r.agentMappings)o.gitlabUsernames.length&&(s[o.agentId]=o.gitlabUsernames);let a=i.projects.length?i.projects:r.routes.map(o=>o.project);return new Qe(r.host,r.token,a,s,n)}}}var et="unmapped";function tt(t,e=[]){if(!t)return et;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 eo(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,tt(s.id,n)));let r=(s,a=new Set)=>{if(e.has(s))return e.get(s);if(a.has(s))return;a.add(s);let o=i[s]?.reportsTo;if(!o)return;let l=r(o,a);return l&&e.set(s,l),l};for(let s of Object.keys(i))r(s);return e}function to(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 Ac(t,e){let n=to(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return tt(t.project,e.projects);if(t.agentId){let i=eo(e).get(t.agentId);if(i)return i}return et}function _c(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[i,r,...s]=n,a=s.join(":"),o={agentId:e||i,channel:r};return r==="gitlab"||r==="github"?o.project=a.split(":")[0]:r==="cron"||r==="api"||(o.chatId=a.split("@")[0]),o}var no=t=>t===et?"internal":"client";function ro(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??no(t),respondWithinMinutes:io(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Rc(t){let e=new Set;for(let n of t.projects??[])e.add(tt(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=>ro(n,t))}function io(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 so=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,oo=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function dr(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(oo)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=ao(i);if(!r)return{cleanText:t};let s=n.index??0,a=n[1]??"";return{cleanText:(t.slice(0,s)+a+t.slice(s+n[0].length)).trim(),ui:r}}function Ec(t){if(!t||!t.includes("agentx:ui"))return t;let e=so.exec(t);return e?t.slice(0,e.index).trimEnd():t}function ao(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 a of e.buttons)!a||typeof a.label!="string"||(typeof a.url=="string"&&/^https?:\/\//i.test(a.url)?i.push({label:a.label,url:a.url}):typeof a.reply=="string"&&a.reply.trim()?r.push({label:a.label,reply:a.reply.trim()}):a.action!=null&&s.push(a.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 Cc(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 lo=5*6e4;function D(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var pr=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(D)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${D(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 a=this.pendingKey(e,n),o=this.pending.get(a);if(o&&o.length){let l=Date.now(),c=o.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(a),c.length&&this.log(`flushed ${c.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
181
181
  data: ${JSON.stringify(n)}
182
182
 
183
- `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=D(e.to);if(n===D(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&&D(i.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(D(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+ao),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=D(e.to);for(let r of this.subs)r.callId===e.callId&&D(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{mkdirSync as lo,readFileSync as pr,renameSync as co,rmSync as uo,writeFileSync as po}from"fs";import{homedir as fo}from"os";import{dirname as go,join as mo}from"path";var fr=mo(fo(),".agentx","call.json");function ho(t=fr,e=Date.now()){try{let n=JSON.parse(pr(t,"utf-8"));if(n?.active===!0&&!(n.until&&Date.parse(n.until)<=e))return{active:!0,mode:"call",reason:`in a call${n.reason?`: ${n.reason}`:""}`}}catch{}return{active:!1,mode:null,reason:"not in a call"}}function gr(t=Nt,e=ho){let n=t();return n.active?n:e()}function Mc(t,e,n=fr,i=Date.now()){let r=null;try{r=JSON.parse(pr(n,"utf-8"))}catch{}if(r&&r.source&&r.source!=="daemon")return;if(!t){r&&uo(n,{force:!0});return}lo(go(n),{recursive:!0});let s=`${n}.${process.pid}.tmp`;po(s,JSON.stringify({active:!0,source:"daemon",reason:t,until:new Date(i+e).toISOString()})+`
184
- `),co(s,n)}var yo={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},mr=class{constructor(e=yo,n=Date.now){this.opts=e;this.now=n}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let n=this.now(),i=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return i>n?Math.ceil((i-n)/1e3):0}fail(e){let n=this.clients.get(e);n||this.clients.set(e,n={failures:[],lockedUntil:0}),this.bump(n,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,n){let i=this.now();e.failures=e.failures.filter(r=>i-r<this.opts.windowMs),e.failures.push(i),e.failures.length>=n&&(e.lockedUntil=i+this.opts.lockoutMs)}},bo="That code didn't work. Check it, or run agentx app pair for a new one.",wo=400;async function Wc(t,e){let n=Date.now(),i=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",s=e.limiter.retryAfter(r);if(s>0)return i(`[app] pair-code refused from ${r}: locked out for ${s}s more`),{status:429,body:{error:"too many attempts",retryAfter:s},retryAfter:s};let a=null;try{a=(await Jt(t,1024)).code}catch{}let o=e.codes.redeem(a),l=o?e.verify(o.token):null;return await ko(n,e.minMs??wo),!o||!l?(e.limiter.fail(r),i(`[app] pair-code failed from ${r}`),{status:401,body:{error:bo}}):(e.limiter.succeed(r),i(`[app] pair-code paired ${o.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:o.token})}async function ko(t,e){let n=t+e-Date.now();n>0&&await new Promise(i=>setTimeout(i,n))}import{execFile as jo}from"child_process";import{mkdtempSync as Co,rmSync as Do,writeFileSync as Po}from"fs";import{tmpdir as Lo}from"os";import{join as kr}from"path";import{randomBytes as So}from"crypto";var E={top:8,side:32,bottom:60},nt={height:56,keep:52},hr=`
183
+ `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=D(e.to);if(n===D(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&&D(i.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(D(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+lo),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=D(e.to);for(let r of this.subs)r.callId===e.callId&&D(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{mkdirSync as co,readFileSync as fr,renameSync as uo,rmSync as po,writeFileSync as fo}from"fs";import{homedir as go}from"os";import{dirname as mo,join as ho}from"path";var gr=ho(go(),".agentx","call.json");function yo(t=gr,e=Date.now()){try{let n=JSON.parse(fr(t,"utf-8"));if(n?.active===!0&&!(n.until&&Date.parse(n.until)<=e))return{active:!0,mode:"call",reason:`in a call${n.reason?`: ${n.reason}`:""}`}}catch{}return{active:!1,mode:null,reason:"not in a call"}}function mr(t=Lt,e=yo){let n=t();return n.active?n:e()}function Mc(t,e,n=gr,i=Date.now()){let r=null;try{r=JSON.parse(fr(n,"utf-8"))}catch{}if(r&&r.source&&r.source!=="daemon")return;if(!t){r&&po(n,{force:!0});return}co(mo(n),{recursive:!0});let s=`${n}.${process.pid}.tmp`;fo(s,JSON.stringify({active:!0,source:"daemon",reason:t,until:new Date(i+e).toISOString()})+`
184
+ `),uo(s,n)}var bo={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},hr=class{constructor(e=bo,n=Date.now){this.opts=e;this.now=n}clients=new Map;all={failures:[],lockedUntil:0};retryAfter(e){let n=this.now(),i=Math.max(this.all.lockedUntil,this.clients.get(e)?.lockedUntil??0);return i>n?Math.ceil((i-n)/1e3):0}fail(e){let n=this.clients.get(e);n||this.clients.set(e,n={failures:[],lockedUntil:0}),this.bump(n,this.opts.perClient),this.bump(this.all,this.opts.global)}succeed(e){this.clients.delete(e)}bump(e,n){let i=this.now();e.failures=e.failures.filter(r=>i-r<this.opts.windowMs),e.failures.push(i),e.failures.length>=n&&(e.lockedUntil=i+this.opts.lockoutMs)}},wo="That code didn't work. Check it, or run agentx app pair for a new one.",ko=400;async function Wc(t,e){let n=Date.now(),i=e.log??(c=>console.log(c)),r=t.socket.remoteAddress||"unknown",s=e.limiter.retryAfter(r);if(s>0)return i(`[app] pair-code refused from ${r}: locked out for ${s}s more`),{status:429,body:{error:"too many attempts",retryAfter:s},retryAfter:s};let a=null;try{a=(await Yt(t,1024)).code}catch{}let o=e.codes.redeem(a),l=o?e.verify(o.token):null;return await So(n,e.minMs??ko),!o||!l?(e.limiter.fail(r),i(`[app] pair-code failed from ${r}`),{status:401,body:{error:wo}}):(e.limiter.succeed(r),i(`[app] pair-code paired ${o.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:o.token})}async function So(t,e){let n=t+e-Date.now();n>0&&await new Promise(i=>setTimeout(i,n))}import{execFile as jo}from"child_process";import{mkdtempSync as Co,rmSync as Do,writeFileSync as Po}from"fs";import{tmpdir as No}from"os";import{join as Sr}from"path";import{randomBytes as xo}from"crypto";var E={top:8,side:32,bottom:60},nt={height:56,keep:52},yr=`
185
185
  :root {
186
186
  --ac-paper: #fafaf9; --ac-soft: #f4f4f2; --ac-edge: #e9e9e6;
187
187
  --ac-text: #0b1413; --ac-muted: #4a5856; --ac-subtle: #7c8987;
@@ -310,14 +310,14 @@ button.primary:hover:not(:disabled) { transform: translateY(-1px); background: v
310
310
  button.primary:disabled { opacity: .55; cursor: not-allowed; }
311
311
  kbd { font: 11px var(--ac-mono); color: var(--ac-subtle); }
312
312
  button.primary kbd { color: inherit; opacity: .7; }
313
- `;var yr=t=>t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),br=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()?yr(n):br(n)}`}function vo(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[br(n)],yr(n)].join(" ")}function $o(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 Ao(t){let e=(t.recommend??"").trim(),n=e.toLowerCase(),i=t.choices??[],r=-1;if(i.forEach((a,o)=>{!n.startsWith(a.toLowerCase())||!/^\s*($|[:,.;–—-](\s|$))/.test(e.slice(a.length))||(r<0||a.length>i[r].length)&&(r=o)}),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 _o(t){return t.origin?.kind==="request"?"Hand it back":t.draft?"Send":t.choices?.length?"Choose":"Yes"}var rt=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>`,Ro=rt('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),Io=rt('<path d="m6 15 6-6 6 6"/>'),Eo=rt('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function wr(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=So(12).toString("base64"),s=t.choices??[],a=t.origin?.kind==="reminder",o=t.origin?.kind==="request",l=Ao(t),c=s.map((p,f)=>`<button class="opt" role="radio" aria-checked="false" data-i="${f}"><span class="n">${f+1}</span><span class="t">${w(p)}</span>${f===l.index?'<i class="dot"></i>':""}</button>`).join(""),u=t.recommend?`<span class="rec"><i class="dot"></i>${w(i)} recommends</span>`:"",d={choices:s,draft:t.draft??"",placeholder:Bt,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:l.index};return`<!doctype html>
313
+ `;var br=t=>t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),wr=t=>`${t.getDate()} ${t.toLocaleDateString("en-US",{month:"short"})}`;function vo(t,e){let n=new Date(t);return Number.isNaN(n.getTime())?"":`since ${n.toDateString()===new Date(e).toDateString()?br(n):wr(n)}`}function $o(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[wr(n)],br(n)].join(" ")}function Ao(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){return t.origin?.kind==="request"?"Hand it back":t.draft?"Send":t.choices?.length?"Choose":"Yes"}var rt=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>`,Ro=rt('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),Io=rt('<path d="m6 15 6-6 6 6"/>'),Eo=rt('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function kr(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=xo(12).toString("base64"),s=t.choices??[],a=t.origin?.kind==="reminder",o=t.origin?.kind==="request",l=Ht(t),c=s.map((p,f)=>`<button class="opt" role="radio" aria-checked="false" data-i="${f}"><span class="n">${f+1}</span><span class="t">${w(p)}</span>${f===l.index?'<i class="dot"></i>':""}</button>`).join(""),u=t.recommend?`<span class="rec"><i class="dot"></i>${w(i)} recommends</span>`:"",d={choices:s,draft:t.draft??"",placeholder:Bt,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:l.index};return`<!doctype html>
314
314
  <html lang="en"><head><meta charset="utf-8">
315
315
  <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${r}'">
316
316
  <title>AgentX</title>
317
- <style>${hr}</style></head>
317
+ <style>${yr}</style></head>
318
318
  <body><div class="wrap"><main class="card${e.still?" still":""}">
319
- <div class="head" title="Drag to move"><span class="avatar">${w($o(i))}</span>
320
- <div class="who"><b>${w(i)}</b><span>${w(xo(t.created_at,n))}</span></div>
319
+ <div class="head" title="Drag to move"><span class="avatar">${w(Ao(i))}</span>
320
+ <div class="who"><b>${w(i)}</b><span>${w(vo(t.created_at,n))}</span></div>
321
321
  <span class="kind${a?"":" decision"}">${a?"Reminder":o?"Request":"Decision"}</span>
322
322
  <button class="fold" id="fold" title="Shrink" aria-label="Shrink the card" aria-expanded="true">${Io}</button></div>
323
323
  <div class="body"><h1 dir="auto">${w(t.title)}</h1>
@@ -328,7 +328,7 @@ ${c?`<div class="options" role="radiogroup">${c}</div>`:""}
328
328
  ${l.why?`<p class="why" dir="auto">${w(l.why)}</p>`:""}
329
329
  ${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>
330
330
  <textarea id="text" dir="auto" rows="2" spellcheck="true"></textarea>`:""}
331
- <div class="notes"><div>${Ro}<span>${o?"It stays in Open requests on the Approvals page until you close it.":`If you don't answer by ${w(vo(t.expires,n))}: ${w(t.if_silent)}.`}</span></div>
331
+ <div class="notes"><div>${Ro}<span>${o?"It stays in Open requests on the Approvals page until you close it.":`If you don't answer by ${w($o(t.expires,n))}: ${w(t.if_silent)}.`}</span></div>
332
332
  <div>${Eo}<span>Nothing goes out until you click.</span></div></div>
333
333
  </div><div class="foot"><button class="btn later" id="later">Not now<kbd>esc</kbd></button>
334
334
  <button class="btn" id="no">${o?"Drop":"No"}</button>
@@ -425,7 +425,7 @@ ${t.draft?`<div class="label-row" id="msg"><span class="label">Message</span><sp
425
425
  });
426
426
  } catch (e) {}
427
427
  })();
428
- `;var No=440,Oo=`
428
+ `;var Lo=440,Oo=`
429
429
  ObjC.import("Cocoa"); ObjC.import("WebKit")
430
430
  function run(argv) {
431
431
  var path = argv[0], side = ${E.side}, gripTop = ${E.top}, gripEnd = ${E.top+nt.height}, keep = ${nt.keep}, w = Number(argv[1]) + 2 * side, h = 420, secs = Number(argv[2]), capture = argv[3] || ""
@@ -501,20 +501,20 @@ function run(argv) {
501
501
  function gone(why) { return JSON.stringify({ action: "dismiss", why: why }) }
502
502
  function quoted(s) { return "'" + String(s).replace(/'/g, "'\\\\''") + "'" }
503
503
  `;function Mo(t,e){let n=t.trim().split(`
504
- `).pop()??"",i;try{i=JSON.parse(n)}catch{return{action:"dismiss"}}if(i?.action==="no")return{action:"no"};if(i?.action==="dismiss"&&xr.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 a;return e.draft&&(a=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
505
- `).trim():"",!a||a.length>Vt.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...a?{text:a}:{}}}async function Sr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=Co(kr(Lo(),"agentx-card-"));try{let s=kr(r,"card.html");Po(s,wr(t,{...e,still:!!e.capture}),{mode:384});let a=["-l","JavaScript","-e",Oo,s,String(No),String(i),...e.capture?[e.capture]:[]],o=await n("/usr/bin/osascript",a,(i+10)*1e3);return o.ok?Mo(o.stdout,t):null}finally{Do(r,{recursive:!0,force:!0})}}var xr=["not now","timed out","closed"],Fo=(t,e,n)=>new Promise(i=>{try{jo(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),vr=160,it=15e3;function $r(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>vr?e.slice(0,vr):e}async function Wo(t,e,n,i,r){let s=e.sound==="chime"?i?"":"Glass":e.sound,a=s?Kt(s):null;if(a&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),a],it),!!e.speak)if(r){let o;await Promise.race([r($r(t)),new Promise(l=>{o=setTimeout(l,it)})]),clearTimeout(o)}else{let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",$r(t)],it)}}function Rr(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function Uo(t,e,n){return Rr(["on run argv","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 Ar(t,e,n,i,r){return Rr(["on run argv","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(`
506
- `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function _r(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
504
+ `).pop()??"",i;try{i=JSON.parse(n)}catch{return{action:"dismiss"}}if(i?.action==="no")return{action:"no"};if(i?.action==="dismiss"&&vr.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 a;return e.draft&&(a=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
505
+ `).trim():"",!a||a.length>Ut.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...a?{text:a}:{}}}async function xr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=Co(Sr(No(),"agentx-card-"));try{let s=Sr(r,"card.html");Po(s,kr(t,{...e,still:!!e.capture}),{mode:384});let a=["-l","JavaScript","-e",Oo,s,String(Lo),String(i),...e.capture?[e.capture]:[]],o=await n("/usr/bin/osascript",a,(i+10)*1e3);return o.ok?Mo(o.stdout,t):null}finally{Do(r,{recursive:!0,force:!0})}}var vr=["not now","timed out","closed"],Fo=(t,e,n)=>new Promise(i=>{try{jo(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),$r=160,it=15e3;function Ar(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>$r?e.slice(0,$r):e}async function Wo(t,e,n,i,r){let s=e.sound==="chime"?i?"":"Glass":e.sound,a=s?Jt(s):null;if(a&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),a],it),!!e.speak)if(r){let o;await Promise.race([r(Ar(t)),new Promise(l=>{o=setTimeout(l,it)})]),clearTimeout(o)}else{let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",Ar(t)],it)}}function Ir(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function Vo(t,e,n){return Ir(["on run argv","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 _r(t,e,n,i,r){return Ir(["on run argv","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(`
506
+ `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function Rr(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
507
507
  `);return n<0?{button:e,text:""}:{button:e.slice(0,n),text:e.slice(n+1)}}function st(t){return[t.ask,t.recommend?`Recommended: ${t.recommend}`:"",`From ${t.raised_by}`].filter(Boolean).join(`
508
508
 
509
- `)}async function Ir(t,e,n={}){let i=n.run??Fo,r=(e.style??"card")==="card",s=Wo(t,e,i,r,n.speak).catch(()=>{});if(r){let a=await Sr(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(a)return a}return await s,Vo(t,e,i)}async function Vo(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=(i+5)*1e3,s=`${t.raised_by}: ${t.title}`,a;if(t.choices?.length){let c=await n("/usr/bin/osascript",Uo(s,st(t),t.choices),r);if(a=c.stdout.replace(/\n$/,""),!c.ok||!t.choices.includes(a))return{action:"dismiss"};if(!t.draft)return{action:"yes",choice:a}}if(t.draft){let c=a?`${a}
509
+ `)}async function Er(t,e,n={}){let i=n.run??Fo,r=(e.style??"card")==="card",s=Wo(t,e,i,r,n.speak).catch(()=>{});if(r){let a=await xr(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(a)return a}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}`,a;if(t.choices?.length){let c=await n("/usr/bin/osascript",Vo(s,st(t),t.choices),r);if(a=c.stdout.replace(/\n$/,""),!c.ok||!t.choices.includes(a))return{action:"dismiss"};if(!t.draft)return{action:"yes",choice:a}}if(t.draft){let c=a?`${a}
510
510
 
511
511
  Message (edit it if you like):`:`${st(t)}
512
512
 
513
- Message (edit it if you like):`,d=await n("/usr/bin/osascript",Ar(s,c,a?["Cancel","Send"]:["Not now","No","Send"],i,qt(t.draft,a)),r),p=d.ok?_r(d.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...a?{choice:a}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let o=await n("/usr/bin/osascript",Ar(s,st(t),["Not now","No","Yes"],i),r),l=o.ok?_r(o.stdout):null;return l?.button==="Yes"?{action:"yes"}:l?.button==="No"?{action:"no"}:{action:"dismiss"}}var lt=24*36e5,ot=!1,Bo=10*6e4,Er=-1/0;function Tr(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=x(t.root),a=r?Date.parse(r):NaN,o=j(t.root,"pending").filter(c=>Date.parse(c.expires)>e),l=o.find(c=>s.includes(`card:${c.id}`));if(l)return l;for(let c of o){let u=`card:${c.id}`;if(n[u]||nn(t.root,c.id,e))continue;let d=i[u];if(d&&Date.parse(d)>e)continue;let p=Date.parse(c.created_at);if(!(e-p>lt&&!(p<=a)))return c}return null}function at(t){try{return z(t)?.listByState("needs_attention")??[]}catch{return[]}}function qo(t){let e=t.now??Date.now(),{popped:n={},snoozed:i}=x(t.root);return at(t).find(r=>{let s=`request:${r.id}`,a=i[s];return!n[s]&&!(a&&Date.parse(a)>e)&&e-r.updatedAt<=lt})??null}function Ho(t,e){return{id:t.id,title:tn(t.text,Qt.title),context:t.attentionReason??"It is not finished and nothing is retrying it.",ask:`Hand it back to ${t.agentId}, or drop it?`,say:"A request you made is not finished.",recommend:"",if_silent:"keep",expires:new Date(e+lt).toISOString(),raised_by:t.agentId,created_at:new Date(t.createdAt).toISOString(),status:"pending",origin:{kind:"request",id:t.id}}}async function hu(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(ot)return"busy";let r=Tr(e)?null:qo(e),s=r?Ho(r,e.now??Date.now()):Tr(e);if(!s)return"none";let a=(t.focus??gr)();if(a.active)return"held";let o=`${r?"request":"card"}:${s.id}`,l=(x(e.root).wanted??[]).includes(o)?null:Yt(s);if(l){let c=[...j(e.root,"pending").map(u=>`card:${u.id}`),...at(e).map(u=>`request:${u.id}`)];return Re(e.root,o,c,e.now),i(`[approvals] popup: ${o} not shown, back to ${s.raised_by}: ${l}`),t.returnToAuthor?.(s,Zt(s,l)),"returned"}ot=!0;try{let c=[...j(e.root,"pending").map(y=>`card:${y.id}`),...at(e).map(y=>`request:${y.id}`)];Re(e.root,o,c,e.now),i(`[approvals] popup: showing ${o} from ${s.raised_by}`);let u=e.now??Date.now(),d=!!r&&u-Er<Bo;r&&n.speak&&(Er=u);let p=t.agentName?.(s.raised_by)??(s.node?`${s.raised_by} on ${s.node}`:void 0),f=await(t.show??Ir)(s,d?{...n,speak:!1}:n,{from:p,speak:t.speak});if(f.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${f.why??"no answer"} (${Ot(a)} when shown)`),"shown";if(!(r?z(e)?.get(r.id)?.state==="needs_attention":B(e.root,s.id)?.status==="pending"))return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let h=await Tn(e,o,f.action,{by:"operator (popup)",...f.action==="yes"?{choice:f.choice,text:f.text}:{}});return i(h.ok?`[approvals] popup: ${h.message}`:`[approvals] popup: ${o} not recorded: ${h.error}`),"shown"}catch(c){return i(`[approvals] popup failed for ${o}: ${c?.message??c}`),"shown"}finally{ot=!1}}function yu(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}`}:(fn(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 zo,fstatSync as Xo,openSync as Go,realpathSync as Cr}from"fs";import{isAbsolute as Ko,resolve as Dr,sep as Pr}from"path";var vu="/app-files",Jo=/^[A-Za-z0-9_.:-]{1,64}$/;function Yo(t,e,n=process.cwd()){if(!e||e.length>te.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 ${ve}/ first`};if(!xe(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=Cr(Dr(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=Cr(Ko(e)?e:Dr(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+Pr))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${ve}/ first`};let s=xe(r);return s?{ok:!0,path:r,...s}:{ok:!1,status:415,error:"this type of file is not served"}}function Zo(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 Qo(t,e,n){return{"Content-Type":t,"Content-Disposition":Zo(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 ea(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 $u(t,e,n,i){let r=(C,M)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(M))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let s=n.searchParams.get("agent")||"",a=n.searchParams.get("file")||"";if(!Jo.test(s))return r(400,{error:"bad agent id"});let o=i.workspaceOf(s);if(!o)return r(404,{error:`no agent "${s}" on this computer`});let l=Yo(o,a,i.cwd);if(!l.ok)return i.log?.(`[app-files] refused ${JSON.stringify(a.slice(0,200))} from ${s}: ${l.error}`),r(l.status,{error:l.error});let c;try{c=Go(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=Xo(c);if(!C.isFile())return K(c),r(404,{error:"not a file"});u=C.size}catch{return K(c),r(404,{error:"file not found"})}if(u>te.bytes)return K(c),r(413,{error:`the file is larger than ${te.bytes/1024/1024} MB`});let d=l.path.split(Pr).pop()||"file",p=Qo(l.mime,d,l.kind),f=ea(t.headers.range,u);if(f==="unsatisfiable"){K(c),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(c),e.end();return}let y=zo("",{fd:c,start:g,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as J}from"child_process";import{readFileSync as ta,writeFileSync as na}from"fs";import{tmpdir as ra}from"os";import{join as ia}from"path";xt();var Lr=t=>t&&t!==1?Math.round(175*t):null,ge=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function sa(){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=ta(t,"utf8").trim();if(e)return e}catch{}return null}function Pu(t=sa()){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",...ge(n.voice.rate)?{voice_settings:{speed:ge(n.voice.rate)}}:{}}),signal:i});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let s=ia(ra(),`agentx-say-${process.pid}-${++e}.mp3`);return na(s,Buffer.from(await r.arrayBuffer())),s}catch(r){if(i.aborted||!n.voice.fallback)throw r;return N(`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 Nr(t,e){let n=t.languages&&ee(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var oa=(t,e="")=>{let n=Nr(t,e),i=Lr(t.rate);return[...n&&!Mn(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function aa(t,e,n){if(!n)return["say",oa(t,e)];let i=Nr(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function Lu(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Nu(t=ct()){if(t)try{J("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Ou(t=ct()){if(t)try{J("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function ct(t={},e){if(!Le(t))return null;try{return Wn(e)}catch(n){return N("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
514
- `)[0]}); Siri voices will not switch`),null}}var Mu=(t,e)=>{if(!t){let[n,i]=aa(e.voice,e.text,ct()),r=Lr(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,a=J(n,i,{stdio:["pipe","ignore","ignore"],env:s});return a.stdin?.on("error",()=>{}),a.stdin?.end(e.text),a}return process.platform==="darwin"?J("afplay",[t],{stdio:"ignore"}):J("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Or}from"child_process";import{accessSync as la,constants as ca,readFileSync as Mr}from"fs";import{homedir as ua}from"os";import{basename as U,delimiter as jr,dirname as da,extname as pa,join as ut}from"path";var P={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Fr(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:pt()}:null}var pt=()=>`The recording is longer than ${P.ms/6e4} minutes.`,fa={"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 Wr(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return fa[e]??null}function Ur(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 ft(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 dt(t,e,n=process.env.PATH??""){let i=ua(),r=[ut(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(jr).filter(Boolean)];for(let s of[e,...r.map(a=>ut(a,t))])if(s)try{return la(s,ca.X_OK),s}catch{}return null}function Bu(t){return{key:t,mlx:dt("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:dt("whisper",process.env.AGENTX_WHISPER),ffmpeg:ga()}}var ga=()=>dt("ffmpeg",process.env.AGENTX_FFMPEG);async function Vr(t,e){return e?ma(t,e):null}async function ma(t,e){let n=String(P.ms/1e3+5);try{let r=[...(await ha(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 Br(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}),U(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 a=await s.json();if(typeof a.text!="string")throw new Error("ElevenLabs returned no text");return a.text.trim()}async function qr(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"],a={...process.env,PATH:`${da(i)}${jr}${process.env.PATH??""}`};await ya(e,s,12e4,a);try{return Mr(ut(r,U(n,pa(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function ha(t,e,n){return new Promise((i,r)=>{let s=Or(t,e,{stdio:["ignore","ignore","pipe"]}),a="",o=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${U(t)} took too long`))},n);s.stderr.on("data",l=>{a=(a+l).slice(-8192)}),s.on("error",l=>{clearTimeout(o),r(l)}),s.on("exit",l=>{clearTimeout(o),l===0?i(a):r(new Error(`${U(t)} exited ${l}`))})})}function ya(t,e,n,i=process.env){return new Promise((r,s)=>{let a=Or(t,e,{stdio:["ignore","pipe","pipe"],env:i}),o="",l="",c=setTimeout(()=>{a.kill("SIGKILL"),s(new Error(`${U(t)} took longer than ${n/1e3}s`))},n);a.stdout.on("data",u=>{o.length<4096&&(o+=u)}),a.stderr.on("data",u=>{l.length<4096&&(l+=u)}),a.on("error",u=>{clearTimeout(c),s(u)}),a.on("exit",u=>{clearTimeout(c),u===0?r(o):s(new Error(`${U(t)} exited ${u}: ${l.trim().split(`
515
- `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as ba,rm as wa,writeFile as ka}from"fs/promises";import{tmpdir as Sa}from"os";import{join as Hr}from"path";ei();var xa=64*1024,va=2,gt=0;function ed(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function td(t,e,n,i){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?$a(t,e,i):Ra(t,e,i)}async function $a(t,e,n){let i=String(t.headers["content-type"]||""),r=Wr(i);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=Fr(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),b(e,s.status,{error:s.error});let a=await zr(t,P.bytes);if(!a)return b(e,413,{error:Ta()});if(!a.length)return b(e,400,{error:"The recording is empty."});if(gt>=va)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let o=n.stt(),l=n.host(),c=Ur(o,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",p=c.length?"":" "+ft(o,l);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(!c.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:ft(o,l),setup:!1});gt++;let u;try{let d=await ba(Hr(Sa(),"agentx-phone-voice-"));try{u=await Aa(d,`speech.${r}`,a,i,l,c,n)}finally{await wa(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{gt--}b(e,u[0],u[1])}async function Aa(t,e,n,i,r,s,a){let o=Hr(t,e);if(await ka(o,n,{mode:384}),r.ffmpeg){let c=await(a.measure??Vr)(o,r.ffmpeg);if(c==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(c*1e3>P.ms+2e3)return[413,{error:pt()}]}let l=[];for(let c of s)try{let u=await _a(c,o,i,r,t,a);return a.log(`[voice] phone recording transcribed with ${c} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:c}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:c}]}catch(u){let d=String(u?.message??u).split(`
516
- `)[0].slice(0,200);l.push(`${c}: ${d}`),a.log(`[voice] phone transcription with ${c} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:l.join("; ")}]}function _a(t,e,n,i,r,s){let a=s.engines?.[t];if(a)return a(e,n,i,r);if(t==="elevenlabs")return Br(e,n,i.key);let o=t==="mlx-whisper"?i.mlx:i.whisper;return qr(t,o,e,i.ffmpeg,r)}async function Ra(t,e,n){let i=await zr(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:"",a=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!s)return b(e,400,{error:"agent is required"});let o=Ia(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!o)return b(e,422,{error:"Nothing in this answer can be said aloud."});let l=n.pronounce?n.pronounce(o):o,c=n.voiceOf(s,a);if(!c)return b(e,404,{error:`Unknown agent: ${s}`});let u=(p,f=200)=>b(e,f,{fallback:"browser",reason:p,text:l});if(c.provider!=="elevenlabs")return u("This agent speaks with a system voice, which only plays on the computer.");let d=n.elevenLabsKey();if(!d)return u("No ElevenLabs key is set on this computer.");try{let p=await(n.synth??Ea)(d,c,l);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":p.length,"Cache-Control":"no-store","X-Spoken-Chars":String(l.length)}),e.end(p)}catch(p){return n.log(`[voice] phone answer synthesis failed: ${String(p?.message??p).split(`
517
- `)[0].slice(0,160)}`),u("ElevenLabs could not speak this answer.",502)}}function Ia(t,e){let n=ur(Lt(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return vt(n,e)}async function Ea(t,e,n){let i=ge(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 Ta=()=>`The recording is larger than ${P.bytes/1024/1024} MB, more than ${P.ms/6e4} minutes of speech.`;function nd(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?qe(Ue(t,r,n.voice)):null}function zr(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",a=>{if(!(s>e)){if(s+=a.length,s>e){r.length=0,n(null);return}r.push(a)}}),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 bt,writeFileSync as wt,mkdirSync as me,readdirSync as yt,rmSync as Ca,statSync as R}from"fs";import{resolve as Xr,relative as Da,dirname as kt,join as O,extname as Y,basename as St}from"path";var S=200*1024,Gr=new Set([".md",".markdown",".txt"]),V=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"]),Pa=6,La=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function T(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Xr(t);if($(n)||me(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let i=Xr(n,e);if(Da(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Kr(t){let e=Y(t).toLowerCase();if(!Gr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function mt(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function od(t){let e=T(t,"."),n=[],i=new Set,r=[];try{r=yt(e)}catch{}for(let o of La){let l=O(e,o);if($(l)&&R(l).isFile()){let c=R(l).size,u=c>0&&c<S?ht(l):"";n.push({path:o,title:mt(u,o),size:c,exists:!0}),i.add(o)}else n.push({path:o,title:o,size:0,exists:!1}),i.add(o)}for(let o of r){if(i.has(o))continue;let l=O(e,o);try{let c=R(l);if(!c.isFile()||!Gr.has(Y(o).toLowerCase()))continue;let u=c.size>0&&c.size<S?ht(l):"";n.push({path:o,title:mt(u,o),size:c.size,exists:!0})}catch{}}let s=[],a=O(e,".claude","skills");if($(a))try{for(let o of yt(a)){let l=O(a,o),c;try{c=R(l)}catch{continue}if(!c.isDirectory())continue;let u=O(l,"SKILL.md");if(!$(u))continue;let d=R(u),p=d.size<S?ht(u):"";s.push({slug:o,title:mt(p,o),size:d.size,path:`.claude/skills/${o}/SKILL.md`})}}catch{}return s.sort((o,l)=>o.slug.localeCompare(l.slug)),{identity:n,skills:s,workspace:e}}function ht(t){try{return bt(t,"utf-8")}catch{return""}}function ad(t,e){let n=T(t,e);if(Kr(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:bt(n,"utf-8")}}function ld(t,e,n){let i=T(t,e);Kr(i);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return me(kt(i),{recursive:!0}),wt(i,r),{path:e,bytes:r.length}}function cd(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=T(t,i);if($(r))throw new Error(`Skill "${e}" already exists.`);me(kt(r),{recursive:!0});let s=n.content?.trim()?n.content:Na(e,n.title);return wt(r,s),{slug:e,path:i}}function ud(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=T(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 Ca(n,{recursive:!0,force:!0}),{slug:e}}function dd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=T(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=[];return r(n,"",0,i),i.sort((s,a)=>s.kind!==a.kind?s.kind==="dir"?-1:1:s.path.localeCompare(a.path)),i;function r(s,a,o,l){if(o>Pa)return;let c=[];try{c=yt(s)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=O(s,u),p=a?`${a}/${u}`:u,f;try{f=R(d)}catch{continue}if(f.isDirectory())l.push({path:`${p}/`,kind:"dir",size:0,editable:!1}),r(d,p,o+1,l);else if(f.isFile()){let g=Y(u).toLowerCase(),h=V.has(g)||V.has(u.toLowerCase());l.push({path:p,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function pd(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=T(t,`.claude/skills/${e}/${n}`);if(!$(i)||!R(i).isFile())throw new Error(`File not found: ${n}`);let r=Y(i).toLowerCase(),s=St(i).toLowerCase();if(!V.has(r)&&!V.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:bt(i,"utf-8")}}function fd(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=T(t,`.claude/skills/${e}/${n}`),s=Y(r).toLowerCase(),a=St(r).toLowerCase();if(!V.has(s)&&!V.has(a))throw new Error(`File type not editable: ${n}`);let o=Buffer.from(i,"utf-8");if(o.length>S)throw new Error(`File too large (${o.length} > ${S} bytes).`);return me(kt(r),{recursive:!0}),wt(r,o),{path:n,bytes:o.length}}function gd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=T(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=r=>$(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 Na(t,e){return`# ${e?.trim()||t}
513
+ Message (edit it if you like):`,d=await n("/usr/bin/osascript",_r(s,c,a?["Cancel","Send"]:["Not now","No","Send"],i,qt(t.draft,a)),r),p=d.ok?Rr(d.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...a?{choice:a}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let o=await n("/usr/bin/osascript",_r(s,st(t),["Not now","No","Yes"],i),r),l=o.ok?Rr(o.stdout):null;return l?.button==="Yes"?{action:"yes"}:l?.button==="No"?{action:"no"}:{action:"dismiss"}}var lt=24*36e5,ot=!1,Bo=10*6e4,Tr=-1/0;function Cr(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=x(t.root),a=r?Date.parse(r):NaN,o=j(t.root,"pending").filter(c=>Date.parse(c.expires)>e),l=o.find(c=>s.includes(`card:${c.id}`));if(l)return l;for(let c of o){let u=`card:${c.id}`;if(n[u]||rn(t.root,c.id,e))continue;let d=i[u];if(d&&Date.parse(d)>e)continue;let p=Date.parse(c.created_at);if(!(e-p>lt&&!(p<=a)))return c}return null}function at(t){try{return z(t)?.listByState("needs_attention")??[]}catch{return[]}}function qo(t){let e=t.now??Date.now(),{popped:n={},snoozed:i}=x(t.root);return at(t).find(r=>{let s=`request:${r.id}`,a=i[s];return!n[s]&&!(a&&Date.parse(a)>e)&&e-r.updatedAt<=lt})??null}function Ho(t,e){return{id:t.id,title:nn(t.text,en.title),context:t.attentionReason??"It is not finished and nothing is retrying it.",ask:`Hand it back to ${t.agentId}, or drop it?`,say:"A request you made is not finished.",recommend:"",if_silent:"keep",expires:new Date(e+lt).toISOString(),raised_by:t.agentId,created_at:new Date(t.createdAt).toISOString(),status:"pending",origin:{kind:"request",id:t.id}}}async function hu(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(ot)return"busy";let r=Cr(e)?null:qo(e),s=r?Ho(r,e.now??Date.now()):Cr(e);if(!s)return"none";let a=(t.focus??mr)();if(a.active)return"held";let o=`${r?"request":"card"}:${s.id}`,l=(x(e.root).wanted??[]).includes(o)?null:Zt(s);if(l){let c=[...j(e.root,"pending").map(u=>`card:${u.id}`),...at(e).map(u=>`request:${u.id}`)];return Re(e.root,o,c,e.now),i(`[approvals] popup: ${o} not shown, back to ${s.raised_by}: ${l}`),t.returnToAuthor?.(s,Qt(s,l)),"returned"}ot=!0;try{let c=[...j(e.root,"pending").map(y=>`card:${y.id}`),...at(e).map(y=>`request:${y.id}`)];Re(e.root,o,c,e.now),i(`[approvals] popup: showing ${o} from ${s.raised_by}`);let u=e.now??Date.now(),d=!!r&&u-Tr<Bo;r&&n.speak&&(Tr=u);let p=t.agentName?.(s.raised_by)??(s.node?`${s.raised_by} on ${s.node}`:void 0),f=await(t.show??Er)(s,d?{...n,speak:!1}:n,{from:p,speak:t.speak});if(f.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${f.why??"no answer"} (${Ot(a)} when shown)`),"shown";if(!(r?z(e)?.get(r.id)?.state==="needs_attention":B(e.root,s.id)?.status==="pending"))return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let h=await Cn(e,o,f.action,{by:"operator (popup)",...f.action==="yes"?{choice:f.choice,text:f.text}:{}});return i(h.ok?`[approvals] popup: ${h.message}`:`[approvals] popup: ${o} not recorded: ${h.error}`),"shown"}catch(c){return i(`[approvals] popup failed for ${o}: ${c?.message??c}`),"shown"}finally{ot=!1}}function yu(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}`}:(gn(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 zo,fstatSync as Xo,openSync as Go,realpathSync as Dr}from"fs";import{isAbsolute as Ko,resolve as Pr,sep as Nr}from"path";var vu="/app-files",Jo=/^[A-Za-z0-9_.:-]{1,64}$/;function Yo(t,e,n=process.cwd()){if(!e||e.length>te.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 ${ve}/ first`};if(!xe(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=Dr(Pr(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=Dr(Ko(e)?e:Pr(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+Nr))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${ve}/ first`};let s=xe(r);return s?{ok:!0,path:r,...s}:{ok:!1,status:415,error:"this type of file is not served"}}function Zo(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 Qo(t,e,n){return{"Content-Type":t,"Content-Disposition":Zo(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 ea(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 $u(t,e,n,i){let r=(C,M)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(M))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let s=n.searchParams.get("agent")||"",a=n.searchParams.get("file")||"";if(!Jo.test(s))return r(400,{error:"bad agent id"});let o=i.workspaceOf(s);if(!o)return r(404,{error:`no agent "${s}" on this computer`});let l=Yo(o,a,i.cwd);if(!l.ok)return i.log?.(`[app-files] refused ${JSON.stringify(a.slice(0,200))} from ${s}: ${l.error}`),r(l.status,{error:l.error});let c;try{c=Go(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=Xo(c);if(!C.isFile())return K(c),r(404,{error:"not a file"});u=C.size}catch{return K(c),r(404,{error:"file not found"})}if(u>te.bytes)return K(c),r(413,{error:`the file is larger than ${te.bytes/1024/1024} MB`});let d=l.path.split(Nr).pop()||"file",p=Qo(l.mime,d,l.kind),f=ea(t.headers.range,u);if(f==="unsatisfiable"){K(c),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(c),e.end();return}let y=zo("",{fd:c,start:g,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as J}from"child_process";import{readFileSync as ta,writeFileSync as na}from"fs";import{tmpdir as ra}from"os";import{join as ia}from"path";xt();var Lr=t=>t&&t!==1?Math.round(175*t):null,ge=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function sa(){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=ta(t,"utf8").trim();if(e)return e}catch{}return null}function Pu(t=sa()){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",...ge(n.voice.rate)?{voice_settings:{speed:ge(n.voice.rate)}}:{}}),signal:i});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let s=ia(ra(),`agentx-say-${process.pid}-${++e}.mp3`);return na(s,Buffer.from(await r.arrayBuffer())),s}catch(r){if(i.aborted||!n.voice.fallback)throw r;return L(`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 Or(t,e){let n=t.languages&&ee(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var oa=(t,e="")=>{let n=Or(t,e),i=Lr(t.rate);return[...n&&!jn(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function aa(t,e,n){if(!n)return["say",oa(t,e)];let i=Or(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function Nu(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Lu(t=ct()){if(t)try{J("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Ou(t=ct()){if(t)try{J("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function ct(t={},e){if(!Ne(t))return null;try{return Vn(e)}catch(n){return L("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
514
+ `)[0]}); Siri voices will not switch`),null}}var Mu=(t,e)=>{if(!t){let[n,i]=aa(e.voice,e.text,ct()),r=Lr(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,a=J(n,i,{stdio:["pipe","ignore","ignore"],env:s});return a.stdin?.on("error",()=>{}),a.stdin?.end(e.text),a}return process.platform==="darwin"?J("afplay",[t],{stdio:"ignore"}):J("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Mr}from"child_process";import{accessSync as la,constants as ca,readFileSync as jr}from"fs";import{homedir as ua}from"os";import{basename as V,delimiter as Fr,dirname as da,extname as pa,join as ut}from"path";var P={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Wr(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:pt()}:null}var pt=()=>`The recording is longer than ${P.ms/6e4} minutes.`,fa={"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 Vr(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return fa[e]??null}function Ur(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 ft(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 dt(t,e,n=process.env.PATH??""){let i=ua(),r=[ut(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Fr).filter(Boolean)];for(let s of[e,...r.map(a=>ut(a,t))])if(s)try{return la(s,ca.X_OK),s}catch{}return null}function Bu(t){return{key:t,mlx:dt("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:dt("whisper",process.env.AGENTX_WHISPER),ffmpeg:ga()}}var ga=()=>dt("ffmpeg",process.env.AGENTX_FFMPEG);async function Br(t,e){return e?ma(t,e):null}async function ma(t,e){let n=String(P.ms/1e3+5);try{let r=[...(await ha(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 qr(t,e,n,i){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([jr(t)],{type:e}),V(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 a=await s.json();if(typeof a.text!="string")throw new Error("ElevenLabs returned no text");return a.text.trim()}async function Hr(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"],a={...process.env,PATH:`${da(i)}${Fr}${process.env.PATH??""}`};await ya(e,s,12e4,a);try{return jr(ut(r,V(n,pa(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function ha(t,e,n){return new Promise((i,r)=>{let s=Mr(t,e,{stdio:["ignore","ignore","pipe"]}),a="",o=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${V(t)} took too long`))},n);s.stderr.on("data",l=>{a=(a+l).slice(-8192)}),s.on("error",l=>{clearTimeout(o),r(l)}),s.on("exit",l=>{clearTimeout(o),l===0?i(a):r(new Error(`${V(t)} exited ${l}`))})})}function ya(t,e,n,i=process.env){return new Promise((r,s)=>{let a=Mr(t,e,{stdio:["ignore","pipe","pipe"],env:i}),o="",l="",c=setTimeout(()=>{a.kill("SIGKILL"),s(new Error(`${V(t)} took longer than ${n/1e3}s`))},n);a.stdout.on("data",u=>{o.length<4096&&(o+=u)}),a.stderr.on("data",u=>{l.length<4096&&(l+=u)}),a.on("error",u=>{clearTimeout(c),s(u)}),a.on("exit",u=>{clearTimeout(c),u===0?r(o):s(new Error(`${V(t)} exited ${u}: ${l.trim().split(`
515
+ `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as ba,rm as wa,writeFile as ka}from"fs/promises";import{tmpdir as Sa}from"os";import{join as zr}from"path";ti();var xa=64*1024,va=2,gt=0;function ed(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function td(t,e,n,i){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?$a(t,e,i):Ra(t,e,i)}async function $a(t,e,n){let i=String(t.headers["content-type"]||""),r=Vr(i);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=Wr(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),b(e,s.status,{error:s.error});let a=await Xr(t,P.bytes);if(!a)return b(e,413,{error:Ta()});if(!a.length)return b(e,400,{error:"The recording is empty."});if(gt>=va)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let o=n.stt(),l=n.host(),c=Ur(o,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",p=c.length?"":" "+ft(o,l);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(!c.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:ft(o,l),setup:!1});gt++;let u;try{let d=await ba(zr(Sa(),"agentx-phone-voice-"));try{u=await Aa(d,`speech.${r}`,a,i,l,c,n)}finally{await wa(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{gt--}b(e,u[0],u[1])}async function Aa(t,e,n,i,r,s,a){let o=zr(t,e);if(await ka(o,n,{mode:384}),r.ffmpeg){let c=await(a.measure??Br)(o,r.ffmpeg);if(c==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(c*1e3>P.ms+2e3)return[413,{error:pt()}]}let l=[];for(let c of s)try{let u=await _a(c,o,i,r,t,a);return a.log(`[voice] phone recording transcribed with ${c} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:c}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:c}]}catch(u){let d=String(u?.message??u).split(`
516
+ `)[0].slice(0,200);l.push(`${c}: ${d}`),a.log(`[voice] phone transcription with ${c} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:l.join("; ")}]}function _a(t,e,n,i,r,s){let a=s.engines?.[t];if(a)return a(e,n,i,r);if(t==="elevenlabs")return qr(e,n,i.key);let o=t==="mlx-whisper"?i.mlx:i.whisper;return Hr(t,o,e,i.ffmpeg,r)}async function Ra(t,e,n){let i=await Xr(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:"",a=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!s)return b(e,400,{error:"agent is required"});let o=Ia(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!o)return b(e,422,{error:"Nothing in this answer can be said aloud."});let l=n.pronounce?n.pronounce(o):o,c=n.voiceOf(s,a);if(!c)return b(e,404,{error:`Unknown agent: ${s}`});let u=(p,f=200)=>b(e,f,{fallback:"browser",reason:p,text:l});if(c.provider!=="elevenlabs")return u("This agent speaks with a system voice, which only plays on the computer.");let d=n.elevenLabsKey();if(!d)return u("No ElevenLabs key is set on this computer.");try{let p=await(n.synth??Ea)(d,c,l);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":p.length,"Cache-Control":"no-store","X-Spoken-Chars":String(l.length)}),e.end(p)}catch(p){return n.log(`[voice] phone answer synthesis failed: ${String(p?.message??p).split(`
517
+ `)[0].slice(0,160)}`),u("ElevenLabs could not speak this answer.",502)}}function Ia(t,e){let n=dr(Nt(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return vt(n,e)}async function Ea(t,e,n){let i=ge(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 Ta=()=>`The recording is larger than ${P.bytes/1024/1024} MB, more than ${P.ms/6e4} minutes of speech.`;function nd(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?qe(Ve(t,r,n.voice)):null}function Xr(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",a=>{if(!(s>e)){if(s+=a.length,s>e){r.length=0,n(null);return}r.push(a)}}),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 bt,writeFileSync as wt,mkdirSync as me,readdirSync as yt,rmSync as Ca,statSync as R}from"fs";import{resolve as Gr,relative as Da,dirname as kt,join as O,extname as Y,basename as St}from"path";var S=200*1024,Kr=new Set([".md",".markdown",".txt"]),U=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"]),Pa=6,Na=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function T(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Gr(t);if($(n)||me(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let i=Gr(n,e);if(Da(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Jr(t){let e=Y(t).toLowerCase();if(!Kr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function mt(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function od(t){let e=T(t,"."),n=[],i=new Set,r=[];try{r=yt(e)}catch{}for(let o of Na){let l=O(e,o);if($(l)&&R(l).isFile()){let c=R(l).size,u=c>0&&c<S?ht(l):"";n.push({path:o,title:mt(u,o),size:c,exists:!0}),i.add(o)}else n.push({path:o,title:o,size:0,exists:!1}),i.add(o)}for(let o of r){if(i.has(o))continue;let l=O(e,o);try{let c=R(l);if(!c.isFile()||!Kr.has(Y(o).toLowerCase()))continue;let u=c.size>0&&c.size<S?ht(l):"";n.push({path:o,title:mt(u,o),size:c.size,exists:!0})}catch{}}let s=[],a=O(e,".claude","skills");if($(a))try{for(let o of yt(a)){let l=O(a,o),c;try{c=R(l)}catch{continue}if(!c.isDirectory())continue;let u=O(l,"SKILL.md");if(!$(u))continue;let d=R(u),p=d.size<S?ht(u):"";s.push({slug:o,title:mt(p,o),size:d.size,path:`.claude/skills/${o}/SKILL.md`})}}catch{}return s.sort((o,l)=>o.slug.localeCompare(l.slug)),{identity:n,skills:s,workspace:e}}function ht(t){try{return bt(t,"utf-8")}catch{return""}}function ad(t,e){let n=T(t,e);if(Jr(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:bt(n,"utf-8")}}function ld(t,e,n){let i=T(t,e);Jr(i);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return me(kt(i),{recursive:!0}),wt(i,r),{path:e,bytes:r.length}}function cd(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=T(t,i);if($(r))throw new Error(`Skill "${e}" already exists.`);me(kt(r),{recursive:!0});let s=n.content?.trim()?n.content:La(e,n.title);return wt(r,s),{slug:e,path:i}}function ud(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=T(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 Ca(n,{recursive:!0,force:!0}),{slug:e}}function dd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=T(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=[];return r(n,"",0,i),i.sort((s,a)=>s.kind!==a.kind?s.kind==="dir"?-1:1:s.path.localeCompare(a.path)),i;function r(s,a,o,l){if(o>Pa)return;let c=[];try{c=yt(s)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=O(s,u),p=a?`${a}/${u}`:u,f;try{f=R(d)}catch{continue}if(f.isDirectory())l.push({path:`${p}/`,kind:"dir",size:0,editable:!1}),r(d,p,o+1,l);else if(f.isFile()){let g=Y(u).toLowerCase(),h=U.has(g)||U.has(u.toLowerCase());l.push({path:p,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function pd(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=T(t,`.claude/skills/${e}/${n}`);if(!$(i)||!R(i).isFile())throw new Error(`File not found: ${n}`);let r=Y(i).toLowerCase(),s=St(i).toLowerCase();if(!U.has(r)&&!U.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:bt(i,"utf-8")}}function fd(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=T(t,`.claude/skills/${e}/${n}`),s=Y(r).toLowerCase(),a=St(r).toLowerCase();if(!U.has(s)&&!U.has(a))throw new Error(`File type not editable: ${n}`);let o=Buffer.from(i,"utf-8");if(o.length>S)throw new Error(`File too large (${o.length} > ${S} bytes).`);return me(kt(r),{recursive:!0}),wt(r,o),{path:n,bytes:o.length}}function gd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=T(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=r=>$(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 La(t,e){return`# ${e?.trim()||t}
518
518
 
519
519
  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.
520
520
 
@@ -529,5 +529,5 @@ Document the arguments, commands, or files the skill expects. Example:
529
529
  # Example invocation
530
530
  claude-code ${St(t)} --arg value
531
531
  \`\`\`
532
- `}Tt();var Jr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Yr(t){return{...Jr,...t??{},regions:{...t?.regions??{}},buffer:{...Jr.buffer,...t?.buffer??{}}}}function yd(t){try{return Yr(Et(t).screen)}catch{return Yr(void 0)}}var Oa=/^[a-z][\w-]*$/,Zr=["window","screen","menubar","notifications"];function Z(t,e,n,i){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${i}`);return r}var he=(t,e)=>Z(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 bd(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=he(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=he(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=he(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Z(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Z(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,a]of Object.entries(e.regions)){if(!Oa.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);a===null?delete r[s]:r[s]=Qr(a)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,s={...n.buffer??{}};"enabled"in r&&(s.enabled=!!r.enabled),"seconds"in r&&(s.seconds=Z(r.seconds,"buffer.seconds",a=>a>0&&a<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Z(r.fps,"buffer.fps",a=>a>0&&a<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=he(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&&!Zr.includes(i)&&!n.regions?.[i])try{Qr(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Zr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{rn as a,Fa as b,tt as c,Qs as d,eo as e,Ac as f,_c as g,Rc as h,ur as i,Ec as j,Cc as k,D as l,dr as m,k as n,Ba as o,gr as p,Mc as q,Za as r,Ti as s,il as t,Sn as u,x as v,Ga as w,Ka as x,al as y,se as z,ll as A,$n as B,gl as C,z as D,El as E,Tl as F,Tn as G,mr as H,Wc as I,Ir as J,hu as K,yu as L,vu as M,Qo as N,$u as O,Dl as P,Pl as Q,Ll as R,Nl as S,Ol as T,Ml as U,Fl as V,Wl as W,Kl as X,Me as Y,Jl as Z,Yl as _,X as $,G as aa,sa as ba,Pu as ca,Lu as da,Nu as ea,Ou as fa,ct as ga,Mu as ha,We as ia,Ue as ja,de as ka,ws as la,Ss as ma,nc as na,Be as oa,qe as pa,xs as qa,vs as ra,Jn as sa,er as ta,rc as ua,_s as va,ic as wa,Ls as xa,Ms as ya,He as za,Fs as Aa,tr as Ba,P as Ca,Fr as Da,Wr as Ea,Ur as Fa,Bu as Ga,ga as Ha,Br as Ia,qr as Ja,ed as Ka,td as La,Ta as Ma,nd as Na,zr as Oa,pe as Pa,hc as Qa,ar as Ra,ze as Sa,Qe as Ta,vc as Ua,od as Va,ad as Wa,ld as Xa,cd as Ya,ud as Za,dd as _a,pd as $a,fd as ab,gd as bb,Jr as cb,Yr as db,yd as eb,Zr as fb,bd as gb};
533
- //# sourceMappingURL=chunk-JCFVH3NC.js.map
532
+ `}Tt();var Yr={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{...Yr,...t??{},regions:{...t?.regions??{}},buffer:{...Yr.buffer,...t?.buffer??{}}}}function yd(t){try{return Zr(Et(t).screen)}catch{return Zr(void 0)}}var Oa=/^[a-z][\w-]*$/,Qr=["window","screen","menubar","notifications"];function Z(t,e,n,i){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${i}`);return r}var he=(t,e)=>Z(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function ei(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 bd(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=he(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=he(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=he(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Z(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Z(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,a]of Object.entries(e.regions)){if(!Oa.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);a===null?delete r[s]:r[s]=ei(a)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,s={...n.buffer??{}};"enabled"in r&&(s.enabled=!!r.enabled),"seconds"in r&&(s.seconds=Z(r.seconds,"buffer.seconds",a=>a>0&&a<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Z(r.fps,"buffer.fps",a=>a>0&&a<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=he(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&&!Qr.includes(i)&&!n.regions?.[i])try{ei(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Qr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{sn as a,Fa as b,tt as c,eo as d,to as e,Ac as f,_c as g,Rc as h,dr as i,Ec as j,Cc as k,D as l,pr as m,k as n,Ba as o,mr as p,Mc as q,Za as r,Ci as s,il as t,xn as u,x as v,Ga as w,Ka as x,al as y,se as z,ll as A,An as B,gl as C,z as D,El as E,Tl as F,Cn as G,hr as H,Wc as I,Er as J,hu as K,yu as L,vu as M,Qo as N,$u as O,Dl as P,Pl as Q,Nl as R,Ll as S,Ol as T,Ml as U,Fl as V,Wl as W,Kl as X,Me as Y,Jl as Z,Yl as _,X as $,G as aa,sa as ba,Pu as ca,Nu as da,Lu as ea,Ou as fa,ct as ga,Mu as ha,We as ia,Ve as ja,de as ka,ks as la,xs as ma,nc as na,Be as oa,qe as pa,vs as qa,$s as ra,Yn as sa,tr as ta,rc as ua,Rs as va,ic as wa,Ls as xa,js as ya,He as za,Ws as Aa,nr as Ba,P as Ca,Wr as Da,Vr as Ea,Ur as Fa,Bu as Ga,ga as Ha,qr as Ia,Hr as Ja,ed as Ka,td as La,Ta as Ma,nd as Na,Xr as Oa,pe as Pa,hc as Qa,lr as Ra,ze as Sa,Qe as Ta,vc as Ua,od as Va,ad as Wa,ld as Xa,cd as Ya,ud as Za,dd as _a,pd as $a,fd as ab,gd as bb,Yr as cb,Zr as db,yd as eb,Qr as fb,bd as gb};
533
+ //# sourceMappingURL=chunk-QZ6VBDMX.js.map