agentix-cli 0.146.0 → 0.148.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 (146) hide show
  1. package/dist/{App-EU2AJWW5.js → App-2O2UUZGG.js} +2 -2
  2. package/dist/{ChatApp-ORR3U3AN.js → ChatApp-YU4NF63L.js} +2 -2
  3. package/dist/{absorb-eval-3VGPDRWS.js → absorb-eval-WHWOJYDX.js} +2 -2
  4. package/dist/{agent-NVJNOK5L.js → agent-NLCR6VBE.js} +2 -2
  5. package/dist/{board-dashboard-JV2JNRWD.js → board-dashboard-KXSZIMWV.js} +216 -216
  6. package/dist/board-dashboard-KXSZIMWV.js.map +1 -0
  7. package/dist/{chunk-UFX6INNI.js → chunk-2MW32M2D.js} +2 -2
  8. package/dist/{chunk-5YAUENDI.js → chunk-3HVRWULP.js} +2 -2
  9. package/dist/{chunk-7O7VDA3J.js → chunk-5IHUZVPU.js} +2 -2
  10. package/dist/{chunk-USTNT7P7.js → chunk-5QXRPYOY.js} +2 -2
  11. package/dist/{chunk-3BMIZY6X.js → chunk-6QFDFYI7.js} +2 -2
  12. package/dist/{chunk-5TFXFLMN.js → chunk-6TJNWUMA.js} +3 -3
  13. package/dist/{chunk-MOCKFVYE.js → chunk-6YNRLI6I.js} +2 -2
  14. package/dist/{chunk-OEB6RTRA.js → chunk-AONY6U45.js} +2 -2
  15. package/dist/{chunk-WCOT35YG.js → chunk-ATCIRFH6.js} +2 -2
  16. package/dist/{chunk-O7ZJS33Z.js → chunk-BZ6Y264Z.js} +2 -2
  17. package/dist/{chunk-TYONASHA.js → chunk-CHBZHUIF.js} +41 -41
  18. package/dist/chunk-CHBZHUIF.js.map +1 -0
  19. package/dist/{chunk-NBDYBTI6.js → chunk-CJVAIAD7.js} +259 -259
  20. package/dist/chunk-CJVAIAD7.js.map +1 -0
  21. package/dist/{chunk-UVJLIHLL.js → chunk-DWOERPBG.js} +2 -2
  22. package/dist/chunk-E7LPZAXP.js +7 -0
  23. package/dist/chunk-E7LPZAXP.js.map +1 -0
  24. package/dist/{chunk-UTYNYG7M.js → chunk-EIY2HRAS.js} +2 -2
  25. package/dist/{chunk-OT5KLHUT.js → chunk-GMMRBTLQ.js} +2 -2
  26. package/dist/{chunk-GECGRCYC.js → chunk-GRI5HOPC.js} +2 -2
  27. package/dist/{chunk-UYLVSS6I.js → chunk-IGA3T3ZT.js} +2 -2
  28. package/dist/chunk-INT5PIF3.js +533 -0
  29. package/dist/chunk-INT5PIF3.js.map +1 -0
  30. package/dist/{chunk-WBG6NA7R.js → chunk-KP7KDLZ2.js} +2 -2
  31. package/dist/{chunk-QNS3WHGU.js → chunk-NMYC5RW7.js} +2 -2
  32. package/dist/{chunk-DTWBB7B7.js → chunk-NW4N67TU.js} +2 -2
  33. package/dist/chunk-OIMJLAWD.js +7 -0
  34. package/dist/chunk-OIMJLAWD.js.map +1 -0
  35. package/dist/{chunk-TZVJP4H3.js → chunk-OWMKQ4HZ.js} +2 -2
  36. package/dist/chunk-PXKIPU27.js +64 -0
  37. package/dist/chunk-PXKIPU27.js.map +1 -0
  38. package/dist/{chunk-DG2DC43E.js → chunk-PYHR4HXO.js} +2 -2
  39. package/dist/{chunk-SK24JFEK.js → chunk-S22IBRY6.js} +2 -2
  40. package/dist/chunk-S5NGIJDI.js +35 -0
  41. package/dist/chunk-S5NGIJDI.js.map +1 -0
  42. package/dist/chunk-X7UQY7CH.js +5 -0
  43. package/dist/chunk-X7UQY7CH.js.map +1 -0
  44. package/dist/{chunk-SNCRLEH3.js → chunk-Z7GEW2SR.js} +5 -5
  45. package/dist/cli.js +1 -1
  46. package/dist/{client-6KZZKCN2.js → client-A2N6ETK2.js} +2 -2
  47. package/dist/config-2QM2WTI2.js +2 -0
  48. package/dist/{config-mutate-57YT7BNB.js → config-mutate-UJS4F7BT.js} +2 -2
  49. package/dist/config-mutator-VWR3SMD3.js +2 -0
  50. package/dist/{contributions-Y6B6LG7X.js → contributions-43FWZOGF.js} +2 -2
  51. package/dist/doctor-5R6X7JH6.js +2 -0
  52. package/dist/{follow-up-tool-5AMZKVI4.js → follow-up-tool-VB7K6HCL.js} +2 -2
  53. package/dist/{hub-BZF3ZYQ5.js → hub-JNNNUAZM.js} +2 -2
  54. package/dist/index.d.ts +119 -1
  55. package/dist/index.js +1 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/note-tool-EZWSB3J3.js +2 -0
  58. package/dist/note-tool-EZWSB3J3.js.map +1 -0
  59. package/dist/{program-MO7HLAP5.js → program-VS6QDZNX.js} +209 -209
  60. package/dist/program-VS6QDZNX.js.map +1 -0
  61. package/dist/{promote-IJANZNQK.js → promote-VFYVWVTL.js} +2 -2
  62. package/dist/{query-DC74NB3R.js → query-RB2MU2HV.js} +2 -2
  63. package/dist/{query-settings-RXFOATOZ.js → query-settings-5B54WHCS.js} +2 -2
  64. package/dist/{registry-24IXRDWX.js → registry-6OX7U6FV.js} +2 -2
  65. package/dist/{request-planner-33CWWCJU.js → request-planner-TUHVEYSF.js} +2 -2
  66. package/dist/{review-candidates-ENWB6LHD.js → review-candidates-FDYTGG2N.js} +2 -2
  67. package/dist/{routing-AUFJ4MNP.js → routing-U35SFPEI.js} +2 -2
  68. package/dist/schedule-tool-EPQKUYJX.js +2 -0
  69. package/dist/{scheduler-KWSBBZKW.js → scheduler-H2QHWNQ2.js} +2 -2
  70. package/dist/{seat-YGMLJ6KS.js → seat-EB3KJMIE.js} +2 -2
  71. package/dist/{select-JJGBM6ZT.js → select-IU4IOVSO.js} +2 -2
  72. package/dist/{set-enabled-THE7QIGQ.js → set-enabled-64BSJ7LR.js} +2 -2
  73. package/dist/{tool-4ACTSFKC.js → tool-PLM6Z42O.js} +2 -2
  74. package/dist/{tool-6LR6VORJ.js → tool-W3CIQZJ7.js} +2 -2
  75. package/dist/{wiki-YAW7UEOQ.js → wiki-4KMRUD5C.js} +2 -2
  76. package/dist/wiki-enrich-N4GLW2JX.js +2 -0
  77. package/package.json +1 -1
  78. package/dist/board-dashboard-JV2JNRWD.js.map +0 -1
  79. package/dist/chunk-IBK7AG4S.js +0 -62
  80. package/dist/chunk-IBK7AG4S.js.map +0 -1
  81. package/dist/chunk-J723FL3J.js +0 -7
  82. package/dist/chunk-J723FL3J.js.map +0 -1
  83. package/dist/chunk-K3QDK4BX.js +0 -5
  84. package/dist/chunk-K3QDK4BX.js.map +0 -1
  85. package/dist/chunk-MO7DH5L6.js +0 -535
  86. package/dist/chunk-MO7DH5L6.js.map +0 -1
  87. package/dist/chunk-NBDYBTI6.js.map +0 -1
  88. package/dist/chunk-S2GAEH2F.js +0 -13
  89. package/dist/chunk-S2GAEH2F.js.map +0 -1
  90. package/dist/chunk-TYONASHA.js.map +0 -1
  91. package/dist/config-W6JNVPBY.js +0 -2
  92. package/dist/config-mutator-6NWQPE7K.js +0 -2
  93. package/dist/doctor-ZP4KADAD.js +0 -2
  94. package/dist/program-MO7HLAP5.js.map +0 -1
  95. package/dist/schedule-tool-NAMOBMZE.js +0 -2
  96. package/dist/wiki-enrich-6ANFA2VB.js +0 -2
  97. /package/dist/{App-EU2AJWW5.js.map → App-2O2UUZGG.js.map} +0 -0
  98. /package/dist/{ChatApp-ORR3U3AN.js.map → ChatApp-YU4NF63L.js.map} +0 -0
  99. /package/dist/{absorb-eval-3VGPDRWS.js.map → absorb-eval-WHWOJYDX.js.map} +0 -0
  100. /package/dist/{agent-NVJNOK5L.js.map → agent-NLCR6VBE.js.map} +0 -0
  101. /package/dist/{chunk-UFX6INNI.js.map → chunk-2MW32M2D.js.map} +0 -0
  102. /package/dist/{chunk-5YAUENDI.js.map → chunk-3HVRWULP.js.map} +0 -0
  103. /package/dist/{chunk-7O7VDA3J.js.map → chunk-5IHUZVPU.js.map} +0 -0
  104. /package/dist/{chunk-USTNT7P7.js.map → chunk-5QXRPYOY.js.map} +0 -0
  105. /package/dist/{chunk-3BMIZY6X.js.map → chunk-6QFDFYI7.js.map} +0 -0
  106. /package/dist/{chunk-5TFXFLMN.js.map → chunk-6TJNWUMA.js.map} +0 -0
  107. /package/dist/{chunk-MOCKFVYE.js.map → chunk-6YNRLI6I.js.map} +0 -0
  108. /package/dist/{chunk-OEB6RTRA.js.map → chunk-AONY6U45.js.map} +0 -0
  109. /package/dist/{chunk-WCOT35YG.js.map → chunk-ATCIRFH6.js.map} +0 -0
  110. /package/dist/{chunk-O7ZJS33Z.js.map → chunk-BZ6Y264Z.js.map} +0 -0
  111. /package/dist/{chunk-UVJLIHLL.js.map → chunk-DWOERPBG.js.map} +0 -0
  112. /package/dist/{chunk-UTYNYG7M.js.map → chunk-EIY2HRAS.js.map} +0 -0
  113. /package/dist/{chunk-OT5KLHUT.js.map → chunk-GMMRBTLQ.js.map} +0 -0
  114. /package/dist/{chunk-GECGRCYC.js.map → chunk-GRI5HOPC.js.map} +0 -0
  115. /package/dist/{chunk-UYLVSS6I.js.map → chunk-IGA3T3ZT.js.map} +0 -0
  116. /package/dist/{chunk-WBG6NA7R.js.map → chunk-KP7KDLZ2.js.map} +0 -0
  117. /package/dist/{chunk-QNS3WHGU.js.map → chunk-NMYC5RW7.js.map} +0 -0
  118. /package/dist/{chunk-DTWBB7B7.js.map → chunk-NW4N67TU.js.map} +0 -0
  119. /package/dist/{chunk-TZVJP4H3.js.map → chunk-OWMKQ4HZ.js.map} +0 -0
  120. /package/dist/{chunk-DG2DC43E.js.map → chunk-PYHR4HXO.js.map} +0 -0
  121. /package/dist/{chunk-SK24JFEK.js.map → chunk-S22IBRY6.js.map} +0 -0
  122. /package/dist/{chunk-SNCRLEH3.js.map → chunk-Z7GEW2SR.js.map} +0 -0
  123. /package/dist/{client-6KZZKCN2.js.map → client-A2N6ETK2.js.map} +0 -0
  124. /package/dist/{config-W6JNVPBY.js.map → config-2QM2WTI2.js.map} +0 -0
  125. /package/dist/{config-mutate-57YT7BNB.js.map → config-mutate-UJS4F7BT.js.map} +0 -0
  126. /package/dist/{config-mutator-6NWQPE7K.js.map → config-mutator-VWR3SMD3.js.map} +0 -0
  127. /package/dist/{contributions-Y6B6LG7X.js.map → contributions-43FWZOGF.js.map} +0 -0
  128. /package/dist/{doctor-ZP4KADAD.js.map → doctor-5R6X7JH6.js.map} +0 -0
  129. /package/dist/{follow-up-tool-5AMZKVI4.js.map → follow-up-tool-VB7K6HCL.js.map} +0 -0
  130. /package/dist/{hub-BZF3ZYQ5.js.map → hub-JNNNUAZM.js.map} +0 -0
  131. /package/dist/{promote-IJANZNQK.js.map → promote-VFYVWVTL.js.map} +0 -0
  132. /package/dist/{query-DC74NB3R.js.map → query-RB2MU2HV.js.map} +0 -0
  133. /package/dist/{query-settings-RXFOATOZ.js.map → query-settings-5B54WHCS.js.map} +0 -0
  134. /package/dist/{registry-24IXRDWX.js.map → registry-6OX7U6FV.js.map} +0 -0
  135. /package/dist/{request-planner-33CWWCJU.js.map → request-planner-TUHVEYSF.js.map} +0 -0
  136. /package/dist/{review-candidates-ENWB6LHD.js.map → review-candidates-FDYTGG2N.js.map} +0 -0
  137. /package/dist/{routing-AUFJ4MNP.js.map → routing-U35SFPEI.js.map} +0 -0
  138. /package/dist/{schedule-tool-NAMOBMZE.js.map → schedule-tool-EPQKUYJX.js.map} +0 -0
  139. /package/dist/{scheduler-KWSBBZKW.js.map → scheduler-H2QHWNQ2.js.map} +0 -0
  140. /package/dist/{seat-YGMLJ6KS.js.map → seat-EB3KJMIE.js.map} +0 -0
  141. /package/dist/{select-JJGBM6ZT.js.map → select-IU4IOVSO.js.map} +0 -0
  142. /package/dist/{set-enabled-THE7QIGQ.js.map → set-enabled-64BSJ7LR.js.map} +0 -0
  143. /package/dist/{tool-4ACTSFKC.js.map → tool-PLM6Z42O.js.map} +0 -0
  144. /package/dist/{tool-6LR6VORJ.js.map → tool-W3CIQZJ7.js.map} +0 -0
  145. /package/dist/{wiki-YAW7UEOQ.js.map → wiki-4KMRUD5C.js.map} +0 -0
  146. /package/dist/{wiki-enrich-6ANFA2VB.js.map → wiki-enrich-N4GLW2JX.js.map} +0 -0
@@ -0,0 +1,533 @@
1
+ import{a as Ae}from"./chunk-GTJIKXDB.js";import{E as tn,H as nn,p as Kt}from"./chunk-S5NGIJDI.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-IGA3T3ZT.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{g as Mt,h as jt,i as Ft,k as Wt,l as Ut}from"./chunk-5QXRPYOY.js";import{a as Nt,c as Ot}from"./chunk-KP7KDLZ2.js";import{X as Lt,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 ei}from"./chunk-PXKIPU27.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(`
6
+ CREATE TABLE IF NOT EXISTS request_plans (
7
+ request_id TEXT PRIMARY KEY,
8
+ created_by TEXT NOT NULL,
9
+ created_at INTEGER NOT NULL,
10
+ state TEXT NOT NULL,
11
+ finished_at INTEGER,
12
+ notified_at INTEGER,
13
+ FOREIGN KEY (request_id) REFERENCES requests(id) ON DELETE CASCADE
14
+ );
15
+ CREATE INDEX IF NOT EXISTS idx_request_plans_state ON request_plans(state);
16
+ CREATE TABLE IF NOT EXISTS request_plan_steps (
17
+ request_id TEXT NOT NULL,
18
+ idx INTEGER NOT NULL,
19
+ name TEXT NOT NULL,
20
+ kind TEXT NOT NULL,
21
+ agent_id TEXT NOT NULL,
22
+ done_when TEXT NOT NULL,
23
+ state TEXT NOT NULL,
24
+ needs_approval INTEGER NOT NULL DEFAULT 0,
25
+ approval TEXT NOT NULL DEFAULT 'none',
26
+ card_id TEXT,
27
+ message TEXT,
28
+ to_channel TEXT,
29
+ to_chat TEXT,
30
+ to_account TEXT,
31
+ check_url TEXT,
32
+ check_contains TEXT,
33
+ stall_minutes REAL,
34
+ evidence TEXT,
35
+ note TEXT,
36
+ dispatched_at INTEGER,
37
+ updated_at INTEGER NOT NULL,
38
+ nudges INTEGER NOT NULL DEFAULT 0,
39
+ last_nudge_at INTEGER,
40
+ notified_at INTEGER,
41
+ PRIMARY KEY (request_id, idx),
42
+ FOREIGN KEY (request_id) REFERENCES request_plans(request_id) ON DELETE CASCADE
43
+ );
44
+ CREATE TABLE IF NOT EXISTS request_plan_events (
45
+ request_id TEXT NOT NULL,
46
+ step INTEGER,
47
+ at INTEGER NOT NULL,
48
+ kind TEXT NOT NULL,
49
+ detail TEXT NOT NULL,
50
+ FOREIGN KEY (request_id) REFERENCES request_plans(request_id) ON DELETE CASCADE
51
+ );
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,
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==="/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 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
56
+ # Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
57
+ # siri-say.sh [voice] < text speak one line. A Siri voice id switches
58
+ # the OS default for it; any other id is
59
+ # passed to say -v.
60
+ # siri-say.sh --stop silence the line speaking, drop the queue.
61
+ # siri-say.sh --restore put back a voice a killed line left switched.
62
+ # AGENTX_SAY_RATE=<words a minute> sets the speed; unset, say's own.
63
+ D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
64
+ dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
65
+ stops="$dir/stop"
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(" ")}"}
68
+ if [ "$1" = --stop ]; then
69
+ mkdir -p "$dir" || exit 1
70
+ # Queued lines see this change and drop. The owner's trap stops say,
71
+ # restores the voice, and frees the lock.
72
+ echo "$$ $(date +%s)" > "$stops"
73
+ owner=$(cat "$lock/pid" 2>/dev/null)
74
+ [ -n "$owner" ] && kill "$owner" 2>/dev/null
75
+ exit 0
76
+ fi
77
+ mode=speak
78
+ [ "$1" = --restore ] && { mode=restore; set --; }
79
+ case "$1" in com.apple.ttsbundle.gryphon-neural_*) siri=$1 voice= ;; *) siri= voice=$1 ;; esac
80
+ rate=\${AGENTX_SAY_RATE:-}
81
+ case "$rate" in *[!0-9]*) rate= ;; esac
82
+ case "$siri" in *[!A-Za-z0-9._-]*) echo "bad voice id" >&2; exit 2;; esac
83
+ # Not macOS, or no pref tools: speak as is and never touch a pref.
84
+ if [ "$(uname)" != Darwin ] || ! command -v defaults >/dev/null || ! command -v plutil >/dev/null; then
85
+ [ "$mode" = restore ] && exit 0
86
+ if [ -n "$voice" ]; then exec say \${rate:+-r "$rate"} -v "$voice"; else exec say \${rate:+-r "$rate"}; fi
87
+ fi
88
+ mkdir -p "$dir" || exit 1
89
+ mine=$(cat "$stops" 2>/dev/null)
90
+ stopped() { [ "$(cat "$stops" 2>/dev/null)" != "$mine" ]; }
91
+ txt=$(mktemp "\${TMPDIR:-/tmp}/agentx-say.XXXXXX") || exit 1
92
+ say_pid= dog=
93
+ restore() {
94
+ [ -f "$saved" ] || return 0
95
+ if [ -s "$saved" ]; then defaults write $D $K "$(cat "$saved")"; else defaults delete $D $K 2>/dev/null; fi
96
+ rm -f "$saved"
97
+ }
98
+ finish() {
99
+ [ -n "$say_pid" ] && kill "$say_pid" 2>/dev/null
100
+ [ -n "$dog" ] && { pkill -P "$dog" 2>/dev/null; kill "$dog" 2>/dev/null; }
101
+ restore; rm -rf "$lock"; rm -f "$txt"; exit "$1"
102
+ }
103
+ drop() { rm -f "$txt"; exit 75; }
104
+ # A Siri voice whose asset macOS purged: switching to it makes the OS
105
+ # speak a fallback of its own (Eloquence Flo), so leave the pref alone.
106
+ if [ -n "$siri" ]; then
107
+ s=\${siri#com.apple.ttsbundle.gryphon-neural_} ; name=\${s%%_*} ; s=\${s#*_} ; loc=$(printf %s "\${s%%_*}" | tr - _)
108
+ found=
109
+ for a in $assets; do
110
+ grep -aqs "com.apple.siri.tts.voice.$loc.$name.neural.premium" "$a"/*/Info.plist && { found=1; break; }
111
+ done
112
+ [ -z "$found" ] && { echo "Siri voice $siri is not installed; speaking with the OS default" >&2; siri=; }
113
+ fi
114
+ # The whole text first, before the lock: a writer that never closes stdin
115
+ # must not hold up every other speaker.
116
+ [ "$mode" = restore ] && exec 0</dev/null
117
+ exec 3<&0 0</dev/null
118
+ cat <&3 > "$txt" & cat_pid=$!
119
+ exec 3<&-
120
+ n=0
121
+ while kill -0 "$cat_pid" 2>/dev/null; do
122
+ if [ $n -ge $((read_s * 10)) ]; then
123
+ kill "$cat_pid" 2>/dev/null; echo "stdin never closed; nothing said" >&2; rm -f "$txt"; exit 3
124
+ fi
125
+ sleep 0.1; n=$((n + 1))
126
+ done
127
+ # One speaker at a time. A lock whose owner died is taken over. A line
128
+ # that waits past stale_s, or that a stop overtook, is dropped unsaid.
129
+ n=0
130
+ while ! mkdir "$lock" 2>/dev/null; do
131
+ stopped && drop
132
+ if [ $n -ge $((stale_s * 10)) ]; then echo "waited \${stale_s}s for the speaker; dropped" >&2; drop; fi
133
+ owner=$(cat "$lock/pid" 2>/dev/null)
134
+ if [ -n "$owner" ] && ! kill -0 "$owner" 2>/dev/null; then rm -rf "$lock"
135
+ elif [ -z "$owner" ] && [ -n "$(find "$lock" -maxdepth 0 -mmin +1 2>/dev/null)" ]; then rm -rf "$lock"
136
+ else sleep 0.1; n=$((n + 1)); fi
137
+ done
138
+ echo $$ > "$lock/pid"
139
+ trap 'finish 143' TERM INT HUP
140
+ stopped && finish 75
141
+ [ "$mode" = restore ] && finish 0
142
+ restore
143
+ if [ -n "$siri" ]; then
144
+ lang=$(defaults read -g AppleLanguages 2>/dev/null | sed -n '2s/^[^A-Za-z]*\\([A-Za-z]*\\).*/\\1/p')
145
+ defaults export $D - 2>/dev/null | plutil -extract $K xml1 -o "$saved.tmp" - 2>/dev/null || : > "$saved.tmp"
146
+ mv "$saved.tmp" "$saved"
147
+ defaults write $D $K -array "\${lang:-en}" "{ _type = \\"Speech.VoiceSelection\\"; _version = 0; voiceId = \\"$siri\\"; }"
148
+ fi
149
+ # A watchdog: no line runs past its length's worth of speech (a hung say
150
+ # held the lock for minutes), capped at max_s.
151
+ limit=$((5 + $(wc -w < "$txt") * 6 / 10))
152
+ [ $limit -gt $max_s ] && limit=$max_s
153
+ if [ -n "$voice" ]; then say \${rate:+-r "$rate"} -v "$voice" -f "$txt" & else say \${rate:+-r "$rate"} -f "$txt" & fi
154
+ say_pid=$!
155
+ ( sleep "$limit"; echo "say ran past \${limit}s; stopped" >&2; kill "$say_pid" 2>/dev/null ) & dog=$!
156
+ wait "$say_pid"
157
+ status=$?
158
+ say_pid=
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")
161
+ const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
162
+ for (let i = 0; i < vs.count; i++) {
163
+ const v = vs.objectAtIndex(i)
164
+ out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
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(`
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(`
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(`
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
181
+ data: ${JSON.stringify(n)}
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=`
185
+ :root {
186
+ --ac-paper: #fafaf9; --ac-soft: #f4f4f2; --ac-edge: #e9e9e6;
187
+ --ac-text: #0b1413; --ac-muted: #4a5856; --ac-subtle: #7c8987;
188
+ --ac-primary: #1e3a8a; --ac-primary-deep: #172554;
189
+ --ac-blue: #1e3a8a; --ac-blue-2: #1d4ed8;
190
+ --ac-accent: #14b8a6; --ac-accent-deep: #0f766e;
191
+ --ac-rim: rgba(11,20,19,.10);
192
+ --ac-shadow: 0 0 0 .5px rgba(11,20,19,.05), 0 24px 48px -16px rgba(11,20,19,.30), 0 2px 6px rgba(11,20,19,.06);
193
+ --ac-lift: 0 12px 40px rgba(30,58,138,.20), 0 2px 6px rgba(11,20,19,.06);
194
+ --ac-font: "Geist", -apple-system, BlinkMacSystemFont, "Noto Sans Arabic", system-ui, sans-serif;
195
+ --ac-mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
196
+ color-scheme: light;
197
+ }
198
+ [data-theme="dark"] {
199
+ --ac-paper: #111c1b; --ac-soft: #172322; --ac-edge: #263433;
200
+ --ac-text: #e8eeed; --ac-muted: #a7b3b1; --ac-subtle: #83918f;
201
+ --ac-primary: #2563eb; --ac-primary-deep: #1d4ed8;
202
+ --ac-blue: #93c5fd; --ac-blue-2: #60a5fa;
203
+ --ac-accent-deep: #5eead4;
204
+ --ac-rim: rgba(255,255,255,.09);
205
+ --ac-shadow: 0 0 0 .5px rgba(0,0,0,.6), 0 28px 56px -16px rgba(0,0,0,.65), 0 2px 8px rgba(0,0,0,.3);
206
+ color-scheme: dark;
207
+ }
208
+ * { box-sizing: border-box; }
209
+ html, body { margin: 0; background: transparent; }
210
+ body {
211
+ font: 13.5px/1.5 var(--ac-font); color: var(--ac-text); font-feature-settings: "ss01", "cv11";
212
+ -webkit-font-smoothing: antialiased; -webkit-user-select: none; user-select: none; cursor: default;
213
+ }
214
+ .wrap { padding: ${E.top}px ${E.side}px ${E.bottom}px; }
215
+ .card {
216
+ background: var(--ac-paper); border: 1px solid var(--ac-rim); border-radius: 18px;
217
+ box-shadow: var(--ac-shadow); overflow: hidden; animation: ac-in .26s cubic-bezier(.65,0,.35,1);
218
+ position: relative; display: flex; flex-direction: column; max-height: calc(100vh - ${E.top+E.bottom}px);
219
+ }
220
+ .card::before {
221
+ content: ""; position: absolute; top: 6px; left: 50%; width: 32px; height: 4px; margin-left: -16px;
222
+ border-radius: 2px; background: var(--ac-edge);
223
+ }
224
+ @keyframes ac-in { from { transform: translateY(14px); opacity: 0; } }
225
+ .card.still { animation: none; }
226
+ @media (prefers-reduced-motion: reduce) { .card { animation: none; } }
227
+ .head { flex: none; display: flex; align-items: center; gap: 10px; padding: 18px 20px 0; cursor: grab; }
228
+ .body { padding: 14px 20px 16px; min-height: 0; overflow-y: auto; }
229
+ .fold {
230
+ flex: none; width: 24px; height: 24px; display: grid; place-items: center; padding: 0; border-radius: 6px;
231
+ border: 1px solid var(--ac-edge); background: var(--ac-soft); color: var(--ac-subtle); cursor: pointer;
232
+ }
233
+ .fold:hover { color: var(--ac-text); border-color: var(--ac-subtle); }
234
+ .folded .fold svg { transform: rotate(180deg); }
235
+ .folded .body > :not(h1), .folded .foot { display: none; }
236
+ .avatar {
237
+ flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center;
238
+ font-size: 14px; font-weight: 600; color: #fff;
239
+ background: linear-gradient(135deg, var(--ac-blue-2), var(--ac-accent));
240
+ }
241
+ .who { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
242
+ .who b { font-size: 13.5px; font-weight: 560; letter-spacing: -.008em; line-height: 1.25; }
243
+ .who span { font-size: 12px; line-height: 1.3; color: var(--ac-subtle); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
244
+ .label, .kind, .edited { font-family: var(--ac-mono); font-size: 10.5px; letter-spacing: .06em; text-transform: uppercase; }
245
+ .kind {
246
+ padding: 3px 8px; border-radius: 999px; white-space: nowrap;
247
+ color: var(--ac-muted); background: var(--ac-soft); border: 1px solid var(--ac-edge);
248
+ }
249
+ .kind.decision {
250
+ color: var(--ac-blue); background: color-mix(in oklab, var(--ac-blue-2) 10%, var(--ac-paper));
251
+ border-color: color-mix(in oklab, var(--ac-blue-2) 22%, var(--ac-edge));
252
+ }
253
+ h1 { margin: 0; font-size: 18.5px; line-height: 1.3; font-weight: 540; letter-spacing: -.018em; text-wrap: balance; }
254
+ h1:dir(rtl) { letter-spacing: 0; }
255
+ .context { margin: 6px 0 0; color: var(--ac-muted); white-space: pre-wrap; unicode-bidi: plaintext; text-wrap: pretty; }
256
+ .ask { margin: 10px 0 0; font-weight: 500; unicode-bidi: plaintext; }
257
+ .label-row { margin-top: 16px; display: flex; align-items: center; gap: 8px; min-height: 18px; }
258
+ .label { color: var(--ac-subtle); margin-inline-end: auto; }
259
+ .dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--ac-accent); }
260
+ .rec { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ac-subtle); }
261
+ .why { margin: 8px 0 0; font-size: 12px; line-height: 1.4; color: var(--ac-subtle); unicode-bidi: plaintext; }
262
+ .options { margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px; }
263
+ .opt {
264
+ display: inline-flex; align-items: center; gap: 8px; padding: 5px 12px 5px 5px; padding-inline: 5px 12px;
265
+ border-radius: 999px; border: 1px solid var(--ac-edge); background: var(--ac-paper); color: var(--ac-text);
266
+ font: inherit; font-size: 13px; line-height: 1.35; text-align: start; cursor: pointer;
267
+ transition: background .15s ease, border-color .15s ease, transform .15s ease;
268
+ }
269
+ .opt:hover { transform: translateY(-1px); }
270
+ .opt .n {
271
+ flex: none; width: 20px; height: 20px; display: grid; place-items: center; border-radius: 6px;
272
+ border: 1px solid var(--ac-edge); border-bottom-width: 2px; background: var(--ac-soft); color: var(--ac-subtle);
273
+ font-family: var(--ac-mono); font-size: 10.5px;
274
+ }
275
+ .opt .t { unicode-bidi: plaintext; }
276
+ .opt[aria-checked="true"] { background: var(--ac-primary); border-color: var(--ac-primary); color: #fff; }
277
+ .opt[aria-checked="true"] .n { background: rgba(255,255,255,.16); border-color: rgba(255,255,255,.28); color: #fff; }
278
+ .opt[aria-checked="true"] .dot { background: #5eead4; }
279
+ .edited { display: none; align-items: center; gap: 5px; color: var(--ac-accent-deep); }
280
+ .edited .dot { width: 5px; height: 5px; }
281
+ .reset { display: none; border: 0; background: none; padding: 0; font: inherit; font-size: 12px; color: var(--ac-muted); cursor: pointer; }
282
+ .reset:hover { color: var(--ac-text); }
283
+ .touched .edited { display: inline-flex; }
284
+ .touched .reset { display: inline; }
285
+ textarea {
286
+ margin-top: 6px; display: block; width: 100%; min-height: 60px; max-height: 240px; resize: none; overflow-y: auto;
287
+ padding: 10px 12px; border: 1px solid var(--ac-edge); border-radius: 10px; background: var(--ac-soft);
288
+ color: var(--ac-text); font: inherit; line-height: 1.45; outline: none; unicode-bidi: plaintext;
289
+ -webkit-user-select: text; user-select: text; cursor: text; transition: border-color .15s ease, box-shadow .15s ease;
290
+ }
291
+ textarea::placeholder { color: var(--ac-subtle); }
292
+ textarea:focus {
293
+ border-color: var(--ac-accent); background: var(--ac-paper);
294
+ box-shadow: 0 0 0 4px color-mix(in oklab, var(--ac-accent) 18%, transparent);
295
+ }
296
+ .notes { margin-top: 14px; display: flex; flex-direction: column; gap: 5px; font-size: 12px; line-height: 1.4; color: var(--ac-subtle); }
297
+ .notes div { display: flex; gap: 7px; align-items: flex-start; }
298
+ .notes svg { flex: none; margin-top: 1.5px; }
299
+ .foot { flex: none; display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--ac-edge); background: var(--ac-soft); }
300
+ .foot .later { margin-inline-end: auto; }
301
+ button.btn {
302
+ display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; border-radius: 999px;
303
+ font: inherit; font-weight: 500; letter-spacing: -.005em; white-space: nowrap; cursor: pointer;
304
+ background: transparent; color: var(--ac-text); border: 1px solid var(--ac-edge);
305
+ transition: transform .15s ease, background .15s ease, box-shadow .15s ease, border-color .15s ease;
306
+ }
307
+ button.btn:hover { background: var(--ac-soft); border-color: var(--ac-subtle); }
308
+ button.primary, button.primary:hover { background: var(--ac-primary); border-color: transparent; color: #fff; }
309
+ button.primary:hover:not(:disabled) { transform: translateY(-1px); background: var(--ac-primary-deep); box-shadow: var(--ac-lift); }
310
+ button.primary:disabled { opacity: .55; cursor: not-allowed; }
311
+ kbd { font: 11px var(--ac-mono); color: var(--ac-subtle); }
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>
314
+ <html lang="en"><head><meta charset="utf-8">
315
+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${r}'">
316
+ <title>AgentX</title>
317
+ <style>${hr}</style></head>
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>
321
+ <span class="kind${a?"":" decision"}">${a?"Reminder":o?"Request":"Decision"}</span>
322
+ <button class="fold" id="fold" title="Shrink" aria-label="Shrink the card" aria-expanded="true">${Io}</button></div>
323
+ <div class="body"><h1 dir="auto">${w(t.title)}</h1>
324
+ ${t.context?`<p class="context" dir="auto">${w(t.context)}</p>`:""}
325
+ <p class="ask" dir="auto">${w(t.ask)}</p>
326
+ ${c||u?`<div class="label-row">${c?'<span class="label">Pick one</span>':""}${u}</div>`:""}
327
+ ${c?`<div class="options" role="radiogroup">${c}</div>`:""}
328
+ ${l.why?`<p class="why" dir="auto">${w(l.why)}</p>`:""}
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
+ <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>
332
+ <div>${Eo}<span>Nothing goes out until you click.</span></div></div>
333
+ </div><div class="foot"><button class="btn later" id="later">Not now<kbd>esc</kbd></button>
334
+ <button class="btn" id="no">${o?"Drop":"No"}</button>
335
+ <button class="btn primary" id="yes">${_o(t)}<kbd>\u2318\u21A9</kbd></button></div>
336
+ </main></div>
337
+ <script type="application/json" id="data">${JSON.stringify(d).replace(/</g,"\\u003c")}</script>
338
+ <script nonce="${r}">${To}</script>
339
+ </body></html>`}var To=`
340
+ (function () {
341
+ var d = JSON.parse(document.getElementById("data").textContent);
342
+ var root = document.documentElement;
343
+ var dark = d.theme === "dark" || (d.theme === "system" && matchMedia("(prefers-color-scheme: dark)").matches);
344
+ if (dark) root.setAttribute("data-theme", "dark");
345
+ var opts = [].slice.call(document.querySelectorAll(".opt"));
346
+ var box = document.getElementById("text");
347
+ var msg = document.getElementById("msg");
348
+ var yes = document.getElementById("yes");
349
+ var card = document.querySelector(".card");
350
+ var body = document.querySelector(".body");
351
+ var fold = document.getElementById("fold");
352
+ var pick = -1, touched = false, done = false;
353
+
354
+ function fill(i) { return d.draft.split(d.placeholder).join(i >= 0 ? d.choices[i] : "").trim(); }
355
+ function send(a) { if (done) return; done = true; window.agentxAnswer = JSON.stringify(a); document.title = "agentx:answer"; }
356
+ // What the card needs, not what it has: in a window too short for it, its middle scrolls.
357
+ function fit() {
358
+ // The title carries the answer signal once sent: a late resize must not write over it.
359
+ if (done) return;
360
+ var wrap = document.querySelector(".wrap"), head = document.querySelector(".head"), foot = document.querySelector(".foot");
361
+ document.title = "agentx:size:" + Math.ceil(wrap.offsetHeight - card.clientHeight + head.offsetHeight + body.scrollHeight + foot.offsetHeight);
362
+ }
363
+ function mark() { touched = box.value.trim() !== fill(pick); msg.classList.toggle("touched", touched); }
364
+ function update() {
365
+ opts.forEach(function (o, i) { o.setAttribute("aria-checked", String(i === pick)); });
366
+ yes.disabled = (d.choices.length > 0 && pick < 0) || (box && !box.value.trim());
367
+ }
368
+ function grow() { if (!box) return; box.style.height = "auto"; box.style.height = box.scrollHeight + 4 + "px"; }
369
+ // quiet: the pick made on open. The box is not focused, so the number keys still pick.
370
+ function choose(i, quiet) {
371
+ // An edited message keeps the edits, with the old pick swapped for the new one.
372
+ if (box && touched && pick >= 0) box.value = box.value.split(d.choices[pick]).join(d.choices[i]);
373
+ else if (box) box.value = fill(i);
374
+ pick = i;
375
+ if (box) { grow(); mark(); }
376
+ update();
377
+ if (box && !quiet) box.focus();
378
+ }
379
+ opts.forEach(function (o, i) { o.addEventListener("click", function () { choose(i); }); });
380
+ if (box) {
381
+ box.value = d.choices.length ? "" : fill(-1);
382
+ box.placeholder = d.choices.length ? "Pick an option above" : "";
383
+ grow();
384
+ box.addEventListener("input", function () { grow(); mark(); update(); });
385
+ document.getElementById("reset").addEventListener("click", function () { box.value = fill(pick); grow(); mark(); update(); box.focus(); });
386
+ }
387
+ yes.addEventListener("click", function () {
388
+ if (yes.disabled) return;
389
+ var a = { action: "yes" };
390
+ if (pick >= 0) a.choice = d.choices[pick];
391
+ if (box) a.text = box.value.trim();
392
+ send(a);
393
+ });
394
+ document.getElementById("no").addEventListener("click", function () { send({ action: "no" }); });
395
+ document.getElementById("later").addEventListener("click", function () { send({ action: "dismiss", why: "not now" }); });
396
+ fold.addEventListener("click", function () {
397
+ var shrunk = card.classList.toggle("folded");
398
+ fold.setAttribute("aria-expanded", String(!shrunk));
399
+ fold.title = shrunk ? "Show all" : "Shrink";
400
+ fit();
401
+ });
402
+ document.addEventListener("keydown", function (e) {
403
+ if (e.key === "Escape") return send({ action: "dismiss", why: "not now" });
404
+ // A shrunk card hides its buttons: no answer by key while they can't be seen.
405
+ if (card.classList.contains("folded")) return;
406
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); return yes.click(); }
407
+ // preventDefault: choose() focuses the box, and the digit must not be typed into it.
408
+ if (document.activeElement !== box && /^[1-9]$/.test(e.key) && opts[+e.key - 1]) { e.preventDefault(); choose(+e.key - 1); }
409
+ });
410
+ if (d.pick >= 0) choose(d.pick, true); else update();
411
+ requestAnimationFrame(fit);
412
+ if (box) new ResizeObserver(fit).observe(box);
413
+
414
+ if (d.chime) try {
415
+ var ac = new AudioContext(), t = ac.currentTime + 0.05;
416
+ [[783.99, 0], [1046.5, 0.14]].forEach(function (n) {
417
+ [1, 2].forEach(function (h) {
418
+ var o = ac.createOscillator(), g = ac.createGain();
419
+ o.type = "sine"; o.frequency.value = n[0] * h;
420
+ g.gain.setValueAtTime(0, t + n[1]);
421
+ g.gain.linearRampToValueAtTime(d.volume * (h === 1 ? 0.5 : 0.12), t + n[1] + 0.012);
422
+ g.gain.exponentialRampToValueAtTime(0.0001, t + n[1] + 1.4);
423
+ o.connect(g).connect(ac.destination); o.start(t + n[1]); o.stop(t + n[1] + 1.5);
424
+ });
425
+ });
426
+ } catch (e) {}
427
+ })();
428
+ `;var No=440,Oo=`
429
+ ObjC.import("Cocoa"); ObjC.import("WebKit")
430
+ function run(argv) {
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] || ""
432
+ var app = $.NSApplication.sharedApplication
433
+ app.setActivationPolicy($.NSApplicationActivationPolicyAccessory)
434
+ ObjC.registerSubclass({ name: "AgentXCardView", superclass: "WKWebView", methods: {
435
+ "acceptsFirstMouse:": { types: ["bool", ["id"]], implementation: function () { return true } },
436
+ } })
437
+ var vis = $.NSScreen.mainScreen.visibleFrame
438
+ var top = vis.origin.y + vis.size.height - 4, right = vis.origin.x + vis.size.width - 14 + side
439
+ var mask = $.NSWindowStyleMaskTitled | $.NSWindowStyleMaskClosable | $.NSWindowStyleMaskFullSizeContentView | $.NSWindowStyleMaskNonactivatingPanel
440
+ var win = $.NSPanel.alloc.initWithContentRectStyleMaskBackingDefer($.NSMakeRect(right - w, top - h, w, h), mask, $.NSBackingStoreBuffered, false)
441
+ win.titlebarAppearsTransparent = true
442
+ win.titleVisibility = $.NSWindowTitleHidden
443
+ win.movableByWindowBackground = true
444
+ win.level = $.NSFloatingWindowLevel
445
+ win.releasedWhenClosed = false
446
+ win.hidesOnDeactivate = false
447
+ win.collectionBehavior = $.NSWindowCollectionBehaviorCanJoinAllSpaces
448
+ win.opaque = false
449
+ win.backgroundColor = $.NSColor.clearColor
450
+ win.hasShadow = false
451
+ ;[$.NSWindowCloseButton, $.NSWindowMiniaturizeButton, $.NSWindowZoomButton].forEach(function (b) { win.standardWindowButton(b).hidden = true })
452
+ var cfg = $.WKWebViewConfiguration.alloc.init
453
+ cfg.mediaTypesRequiringUserActionForPlayback = 0
454
+ var web = $.AgentXCardView.alloc.initWithFrameConfiguration($.NSMakeRect(0, 0, w, h), cfg)
455
+ web.autoresizingMask = $.NSViewWidthSizable | $.NSViewHeightSizable
456
+ web.setValueForKey(false, "drawsBackground")
457
+ win.contentView = web
458
+ var url = $.NSURL.fileURLWithPath(path)
459
+ web.loadFileURLAllowingReadAccessToURL(url, url.URLByDeletingLastPathComponent)
460
+ // No focus taken (#394): shown over the app in use, which keeps the keyboard.
461
+ // A click on the card still lands (acceptsFirstMouse); a click in its text
462
+ // box makes the panel key without bringing anything else forward.
463
+ win.orderFrontRegardless
464
+ var end = Date.now() + secs * 1000, sized = 0, shot = false, seen = "", asked = false, answer = null
465
+ // Every kind of event, as a number. JXA hands the AppKit constant for it over as text, and a
466
+ // loop asking with that gets no event at all: no click, no drag, no key.
467
+ var anyEvent = Number.MAX_SAFE_INTEGER
468
+ while (Date.now() < end) {
469
+ var ev = app.nextEventMatchingMaskUntilDateInModeDequeue(anyEvent, $.NSDate.dateWithTimeIntervalSinceNow(0.05), $.NSDefaultRunLoopMode, true)
470
+ if (ev && !ev.isNil()) {
471
+ if (onGrip(ev)) win.performWindowDragWithEvent(ev); else app.sendEvent(ev)
472
+ }
473
+ if (answer !== null) { win.close; return answer }
474
+ if (!win.isVisible) return gone("closed")
475
+ var t = web.title.js || ""
476
+ if (t === "agentx:answer" && !asked) {
477
+ asked = true
478
+ web.evaluateJavaScriptCompletionHandler("window.agentxAnswer", function (r) { answer = String(ObjC.unwrap(r) || "") })
479
+ }
480
+ if (t !== seen && t.indexOf("agentx:size:") === 0) {
481
+ seen = t
482
+ var want = Math.min(Number(t.slice(12)), vis.size.height - 8)
483
+ var f = win.frame
484
+ if (want > 80) { win.setFrameDisplayAnimate($.NSMakeRect(f.origin.x, f.origin.y + f.size.height - want, w, want), true, true); sized = Date.now() }
485
+ }
486
+ if (capture && !shot && sized && Date.now() - sized > 900) {
487
+ shot = true
488
+ var sa = Application.currentApplication(); sa.includeStandardAdditions = true
489
+ sa.doShellScript("/usr/sbin/screencapture -x -o -l " + win.windowNumber + " " + quoted(capture))
490
+ end = Math.min(end, Date.now() + 300)
491
+ }
492
+ }
493
+ win.close
494
+ return gone("timed out")
495
+ function onGrip(ev) {
496
+ if (ev.type != $.NSEventTypeLeftMouseDown || ev.windowNumber != win.windowNumber) return false
497
+ var p = ev.locationInWindow, down = win.frame.size.height - p.y
498
+ return down >= gripTop && down <= gripEnd && p.x >= side && p.x <= w - side - keep
499
+ }
500
+ }
501
+ function gone(why) { return JSON.stringify({ action: "dismiss", why: why }) }
502
+ function quoted(s) { return "'" + String(s).replace(/'/g, "'\\\\''") + "'" }
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(`
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
+
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}
510
+
511
+ Message (edit it if you like):`:`${st(t)}
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}
518
+
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
+
521
+ ## When to use
522
+ - Trigger condition 1
523
+ - Trigger condition 2
524
+
525
+ ## How to use
526
+ Document the arguments, commands, or files the skill expects. Example:
527
+
528
+ \`\`\`bash
529
+ # Example invocation
530
+ claude-code ${St(t)} --arg value
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-INT5PIF3.js.map