agentix-cli 0.154.2 → 0.155.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 (138) hide show
  1. package/dist/{App-6T6NVB7O.js → App-P4MLXD46.js} +2 -2
  2. package/dist/{ChatApp-QZBJ4NHC.js → ChatApp-DILDQOJL.js} +2 -2
  3. package/dist/{absorb-eval-EVX7LDXR.js → absorb-eval-DBC7EKU5.js} +2 -2
  4. package/dist/{agent-F2NT6B25.js → agent-OZ3KPI6Y.js} +2 -2
  5. package/dist/{board-dashboard-642BO7GV.js → board-dashboard-MWUCBHDN.js} +239 -233
  6. package/dist/board-dashboard-MWUCBHDN.js.map +1 -0
  7. package/dist/{chunk-KA2NV7H4.js → chunk-3ZAAUY2N.js} +2 -2
  8. package/dist/{chunk-743RAKLP.js → chunk-4RHM4XTI.js} +2 -2
  9. package/dist/{chunk-U4YTTWR6.js → chunk-6CXJAZZD.js} +2 -2
  10. package/dist/{chunk-AKCEMKQM.js → chunk-ACB6GRSP.js} +2 -2
  11. package/dist/{chunk-W2RB5XG7.js → chunk-AHZBWCXI.js} +2 -2
  12. package/dist/chunk-AVAR5KNN.js +36 -0
  13. package/dist/chunk-AVAR5KNN.js.map +1 -0
  14. package/dist/{chunk-E76HREC7.js → chunk-CTXHMJLZ.js} +3 -3
  15. package/dist/{chunk-IA4J3YLB.js → chunk-D65HXPIB.js} +2 -2
  16. package/dist/{chunk-S3EX64LR.js → chunk-EE3ZYIIB.js} +2 -2
  17. package/dist/{chunk-VRF4YW46.js → chunk-FTIJQLBX.js} +2 -2
  18. package/dist/{chunk-YL26FRKJ.js → chunk-GIFUJ3LL.js} +2 -2
  19. package/dist/chunk-H7DLFJBV.js +575 -0
  20. package/dist/chunk-H7DLFJBV.js.map +1 -0
  21. package/dist/{chunk-4CWACHEH.js → chunk-HGF73KFH.js} +2 -2
  22. package/dist/{chunk-JAML6222.js → chunk-HOVJVXEP.js} +2 -2
  23. package/dist/{chunk-GRVTLUQ6.js → chunk-IW4AZVJR.js} +2 -2
  24. package/dist/{chunk-IWWEUXZQ.js → chunk-J3IP3UZX.js} +2 -2
  25. package/dist/{chunk-67DWBJEO.js → chunk-J432IZXG.js} +333 -336
  26. package/dist/chunk-J432IZXG.js.map +1 -0
  27. package/dist/{chunk-37I654UJ.js → chunk-KYRF2FPT.js} +2 -2
  28. package/dist/{chunk-SD3CC4EX.js → chunk-NJEJU5XN.js} +2 -2
  29. package/dist/{chunk-CUAS4ITR.js → chunk-PI6CKUUH.js} +2 -2
  30. package/dist/{chunk-HUN6COOF.js → chunk-Q7LUTCNO.js} +2 -2
  31. package/dist/chunk-QHRQ3PUX.js +3 -0
  32. package/dist/chunk-QHRQ3PUX.js.map +1 -0
  33. package/dist/chunk-SQTL2CLY.js +76 -0
  34. package/dist/chunk-SQTL2CLY.js.map +1 -0
  35. package/dist/{chunk-EGTANAFI.js → chunk-SSFQWEPJ.js} +2 -2
  36. package/dist/{chunk-MLC5INGD.js → chunk-UK6MICKK.js} +5 -5
  37. package/dist/{chunk-MLC5INGD.js.map → chunk-UK6MICKK.js.map} +1 -1
  38. package/dist/{chunk-YJNUVAM4.js → chunk-WHMX2D2Q.js} +2 -2
  39. package/dist/{chunk-ABCQ6QMJ.js → chunk-YDAFHXDE.js} +2 -2
  40. package/dist/{chunk-GFRAHUAQ.js → chunk-YLAJOO5X.js} +2 -2
  41. package/dist/{chunk-B75BLZ2M.js → chunk-YXBQSLFV.js} +2 -2
  42. package/dist/cli.js +1 -1
  43. package/dist/{client-OCLSGJYQ.js → client-7JINGNNU.js} +2 -2
  44. package/dist/{config-FZTWI3VG.js → config-S4ZZHOUZ.js} +2 -2
  45. package/dist/{config-mutate-X5IKMROK.js → config-mutate-U3KKAXVD.js} +2 -2
  46. package/dist/config-mutator-KKRVNVVV.js +2 -0
  47. package/dist/{contributions-KHGGVSR6.js → contributions-6F3MYSRR.js} +2 -2
  48. package/dist/{doctor-KNCRQ3YO.js → doctor-UDZI2OMU.js} +2 -2
  49. package/dist/{follow-up-tool-TGKEPA5C.js → follow-up-tool-MP6FOIQE.js} +2 -2
  50. package/dist/{hub-HQUAH5H6.js → hub-TSUVK7PH.js} +2 -2
  51. package/dist/index.d.ts +362 -61
  52. package/dist/index.js +1 -1
  53. package/dist/{program-CYOAZ43O.js → program-CMWF3BQS.js} +234 -232
  54. package/dist/program-CMWF3BQS.js.map +1 -0
  55. package/dist/{promote-VD4OVQGL.js → promote-YVOYLTXI.js} +2 -2
  56. package/dist/{push-bridge-P7HH25VN.js → push-bridge-CFPGPPO7.js} +2 -2
  57. package/dist/{query-5CPK6G2H.js → query-ZGXXMJ4M.js} +2 -2
  58. package/dist/{query-settings-35GDM3HU.js → query-settings-TNOGVKBX.js} +2 -2
  59. package/dist/{registry-JCHKHCRE.js → registry-R2X4YGUK.js} +2 -2
  60. package/dist/{request-planner-ZIG4YVXC.js → request-planner-QBNGJMF5.js} +2 -2
  61. package/dist/{review-candidates-LPZWOR2K.js → review-candidates-WCDKCFXR.js} +2 -2
  62. package/dist/{routing-BLOYDLU4.js → routing-RRRO2GDA.js} +2 -2
  63. package/dist/schedule-tool-2XZ3I5IL.js +2 -0
  64. package/dist/{scheduler-BEJRDQR3.js → scheduler-7O73TDCG.js} +2 -2
  65. package/dist/{seat-NU3UJC6C.js → seat-CCDGNARC.js} +2 -2
  66. package/dist/{select-IWAFX4XJ.js → select-VPZ4QDHV.js} +2 -2
  67. package/dist/{set-enabled-JF75TSFU.js → set-enabled-VYSPZXPC.js} +2 -2
  68. package/dist/{tool-PQBQJWM5.js → tool-K3PZOFC2.js} +2 -2
  69. package/dist/{tool-WTOOPTGC.js → tool-VPDXU3IZ.js} +2 -2
  70. package/dist/{wiki-DXG655NP.js → wiki-QA7BDTOR.js} +2 -2
  71. package/dist/wiki-enrich-ZIZ5QHQ3.js +2 -0
  72. package/package.json +1 -1
  73. package/dist/board-dashboard-642BO7GV.js.map +0 -1
  74. package/dist/chunk-67DWBJEO.js.map +0 -1
  75. package/dist/chunk-HSCZSNOX.js +0 -533
  76. package/dist/chunk-HSCZSNOX.js.map +0 -1
  77. package/dist/chunk-VKEH4IBA.js +0 -76
  78. package/dist/chunk-VKEH4IBA.js.map +0 -1
  79. package/dist/chunk-XOUK5ZIQ.js +0 -36
  80. package/dist/chunk-XOUK5ZIQ.js.map +0 -1
  81. package/dist/chunk-YMX3QCV7.js +0 -3
  82. package/dist/chunk-YMX3QCV7.js.map +0 -1
  83. package/dist/config-mutator-C5BMIBZO.js +0 -2
  84. package/dist/program-CYOAZ43O.js.map +0 -1
  85. package/dist/schedule-tool-7KFO3NPD.js +0 -2
  86. package/dist/wiki-enrich-5VQCT6BT.js +0 -2
  87. /package/dist/{App-6T6NVB7O.js.map → App-P4MLXD46.js.map} +0 -0
  88. /package/dist/{ChatApp-QZBJ4NHC.js.map → ChatApp-DILDQOJL.js.map} +0 -0
  89. /package/dist/{absorb-eval-EVX7LDXR.js.map → absorb-eval-DBC7EKU5.js.map} +0 -0
  90. /package/dist/{agent-F2NT6B25.js.map → agent-OZ3KPI6Y.js.map} +0 -0
  91. /package/dist/{chunk-KA2NV7H4.js.map → chunk-3ZAAUY2N.js.map} +0 -0
  92. /package/dist/{chunk-743RAKLP.js.map → chunk-4RHM4XTI.js.map} +0 -0
  93. /package/dist/{chunk-U4YTTWR6.js.map → chunk-6CXJAZZD.js.map} +0 -0
  94. /package/dist/{chunk-AKCEMKQM.js.map → chunk-ACB6GRSP.js.map} +0 -0
  95. /package/dist/{chunk-W2RB5XG7.js.map → chunk-AHZBWCXI.js.map} +0 -0
  96. /package/dist/{chunk-E76HREC7.js.map → chunk-CTXHMJLZ.js.map} +0 -0
  97. /package/dist/{chunk-IA4J3YLB.js.map → chunk-D65HXPIB.js.map} +0 -0
  98. /package/dist/{chunk-S3EX64LR.js.map → chunk-EE3ZYIIB.js.map} +0 -0
  99. /package/dist/{chunk-VRF4YW46.js.map → chunk-FTIJQLBX.js.map} +0 -0
  100. /package/dist/{chunk-YL26FRKJ.js.map → chunk-GIFUJ3LL.js.map} +0 -0
  101. /package/dist/{chunk-4CWACHEH.js.map → chunk-HGF73KFH.js.map} +0 -0
  102. /package/dist/{chunk-JAML6222.js.map → chunk-HOVJVXEP.js.map} +0 -0
  103. /package/dist/{chunk-GRVTLUQ6.js.map → chunk-IW4AZVJR.js.map} +0 -0
  104. /package/dist/{chunk-IWWEUXZQ.js.map → chunk-J3IP3UZX.js.map} +0 -0
  105. /package/dist/{chunk-37I654UJ.js.map → chunk-KYRF2FPT.js.map} +0 -0
  106. /package/dist/{chunk-SD3CC4EX.js.map → chunk-NJEJU5XN.js.map} +0 -0
  107. /package/dist/{chunk-CUAS4ITR.js.map → chunk-PI6CKUUH.js.map} +0 -0
  108. /package/dist/{chunk-HUN6COOF.js.map → chunk-Q7LUTCNO.js.map} +0 -0
  109. /package/dist/{chunk-EGTANAFI.js.map → chunk-SSFQWEPJ.js.map} +0 -0
  110. /package/dist/{chunk-YJNUVAM4.js.map → chunk-WHMX2D2Q.js.map} +0 -0
  111. /package/dist/{chunk-ABCQ6QMJ.js.map → chunk-YDAFHXDE.js.map} +0 -0
  112. /package/dist/{chunk-GFRAHUAQ.js.map → chunk-YLAJOO5X.js.map} +0 -0
  113. /package/dist/{chunk-B75BLZ2M.js.map → chunk-YXBQSLFV.js.map} +0 -0
  114. /package/dist/{client-OCLSGJYQ.js.map → client-7JINGNNU.js.map} +0 -0
  115. /package/dist/{config-FZTWI3VG.js.map → config-S4ZZHOUZ.js.map} +0 -0
  116. /package/dist/{config-mutate-X5IKMROK.js.map → config-mutate-U3KKAXVD.js.map} +0 -0
  117. /package/dist/{config-mutator-C5BMIBZO.js.map → config-mutator-KKRVNVVV.js.map} +0 -0
  118. /package/dist/{contributions-KHGGVSR6.js.map → contributions-6F3MYSRR.js.map} +0 -0
  119. /package/dist/{doctor-KNCRQ3YO.js.map → doctor-UDZI2OMU.js.map} +0 -0
  120. /package/dist/{follow-up-tool-TGKEPA5C.js.map → follow-up-tool-MP6FOIQE.js.map} +0 -0
  121. /package/dist/{hub-HQUAH5H6.js.map → hub-TSUVK7PH.js.map} +0 -0
  122. /package/dist/{promote-VD4OVQGL.js.map → promote-YVOYLTXI.js.map} +0 -0
  123. /package/dist/{push-bridge-P7HH25VN.js.map → push-bridge-CFPGPPO7.js.map} +0 -0
  124. /package/dist/{query-5CPK6G2H.js.map → query-ZGXXMJ4M.js.map} +0 -0
  125. /package/dist/{query-settings-35GDM3HU.js.map → query-settings-TNOGVKBX.js.map} +0 -0
  126. /package/dist/{registry-JCHKHCRE.js.map → registry-R2X4YGUK.js.map} +0 -0
  127. /package/dist/{request-planner-ZIG4YVXC.js.map → request-planner-QBNGJMF5.js.map} +0 -0
  128. /package/dist/{review-candidates-LPZWOR2K.js.map → review-candidates-WCDKCFXR.js.map} +0 -0
  129. /package/dist/{routing-BLOYDLU4.js.map → routing-RRRO2GDA.js.map} +0 -0
  130. /package/dist/{schedule-tool-7KFO3NPD.js.map → schedule-tool-2XZ3I5IL.js.map} +0 -0
  131. /package/dist/{scheduler-BEJRDQR3.js.map → scheduler-7O73TDCG.js.map} +0 -0
  132. /package/dist/{seat-NU3UJC6C.js.map → seat-CCDGNARC.js.map} +0 -0
  133. /package/dist/{select-IWAFX4XJ.js.map → select-VPZ4QDHV.js.map} +0 -0
  134. /package/dist/{set-enabled-JF75TSFU.js.map → set-enabled-VYSPZXPC.js.map} +0 -0
  135. /package/dist/{tool-PQBQJWM5.js.map → tool-K3PZOFC2.js.map} +0 -0
  136. /package/dist/{tool-WTOOPTGC.js.map → tool-VPDXU3IZ.js.map} +0 -0
  137. /package/dist/{wiki-DXG655NP.js.map → wiki-QA7BDTOR.js.map} +0 -0
  138. /package/dist/{wiki-enrich-5VQCT6BT.js.map → wiki-enrich-ZIZ5QHQ3.js.map} +0 -0
@@ -1,533 +0,0 @@
1
- import{a as Re}from"./chunk-GTJIKXDB.js";import{A as Zt,H as rn,j as B}from"./chunk-XOUK5ZIQ.js";import{a as w}from"./chunk-7LN4VKDU.js";import{f as en,i as tn,k as Ae,l as _e,n as q,o as M,q as nn}from"./chunk-LQS27HSV.js";import{t as Jt,u as Yt}from"./chunk-S3EX64LR.js";import{d as Gt,e as Kt}from"./chunk-AQASR6KR.js";import{b as Qt}from"./chunk-YMX3QCV7.js";import{a as qt,b as Ht,d as zt,e as Xt}from"./chunk-MNG2AMKZ.js";import{g as Ft,h as Wt,i as Vt,k as Ut,l as Bt}from"./chunk-AKCEMKQM.js";import{a as Mt,c as jt}from"./chunk-KP7KDLZ2.js";import{X as Ot,Z as ne,_ as ve,aa as $e,b as xe}from"./chunk-YL26FRKJ.js";import{q as Lt}from"./chunk-W2RB5XG7.js";import{a as Pt,b as Nt}from"./chunk-GRVTLUQ6.js";import{Ca as Se,Ka as Tt,La as Ct,Q as _t,R as Rt,S as It,T as Et,Ua as Dt,n as te,o as $t,p as At,q as ni}from"./chunk-VKEH4IBA.js";import{a as we,h as ri}from"./chunk-BRK6M6LA.js";import{f as ke,n as ii}from"./chunk-UIBUZ2N3.js";import{existsSync as si,readdirSync as oi,readFileSync as ai,statSync as li}from"fs";import{resolve as ci}from"path";function sn(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let a of e){let o=s.get(a.workflowId);o?o.push(a):s.set(a.workflowId,[a])}return t.map(a=>{let o=s.get(a.id)??[],l=o.filter(g=>n-g.at<=r),c=o.filter(g=>n-g.at>r&&n-g.at<=r*2),u=l.filter(g=>g.status==="failed").length,d=o.filter(g=>g.status==="paused").length,p=o.length?Math.max(...o.map(g=>g.at)):null,f=o.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:a.id,name:a.name||a.id,state:f,lastRunAt:p,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((a,o)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[a.state]-l[o.state]||(o.lastRunAt??0)-(a.lastRunAt??0)})}var re=new Map;function Wa(t,e=1e3){if(!si(t))return[];let n=oi(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let a=ci(t,s);return{path:a,mtime:li(a).mtimeMs}}).sort((s,a)=>a.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of re.keys())i.has(s)||re.delete(s);let r=[];for(let{path:s,mtime:a}of n){let o=re.get(s);if(o&&o.mtime===a){o.summary&&r.push(o.summary);continue}let l=ui(s,a);re.set(s,{mtime:a,summary:l}),l&&r.push(l)}return r}function ui(t,e){try{let n=ai(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 di={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},pi=(t,e,n)=>{try{return Lt(t,e,n)}catch{return null}},on=864e5;function qa(t){let e=t.now??Date.now(),n={...di,...t.thresholds},i=t.nextFire??pi,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?Ie(o.nextRun)??Ie(i(o.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:yi(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:an(u),sampledRuns:l.length,flags:[],attention:null};p.flags=ln(p,u,o.schedule,c,null,e,n,i),r.push(cn(p))}let s=new Map(sn(t.workflows.map(o=>({id:o.id,name:o.title})),t.workflowRuns,e).map(o=>[o.id,o])),a=new Map;for(let o of t.workflowRuns){let l=a.get(o.workflowId);l?l.push(o):a.set(o.workflowId,[o])}for(let o of t.workflows){let l=o.nodes.find(I=>I.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=o.state||"active",d=u==="active",p=(a.get(o.id)??[]).slice().sort((I,ye)=>ye.at-I.at),f=p.map(I=>({at:I.at,status:mi(I.status)})),g=f[0],h=l.type==="trigger.cron",b=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",O={id:`workflow:${o.id}`,source:"workflow",kind:h?"schedule":"event",name:A(o.title||o.id,k.text),trigger:h?{schedule:A(b,k.text),timezone:C}:{event:A(typeof c.event=="string"?c.event:"",k.text),filters:bi(c.filter,o)},agent:hi(o),enabled:d,state:u,nextRunAt:h&&d&&b?Ie(i(b,new Date(e),C)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let I=f.find(ye=>ye.status==="success");return I?new Date(I.at).toISOString():null})(),consecutiveFailures:an(f),sampledRuns:p.length,flags:[],attention:null},ee=Date.parse(o.updated||o.created||"");O.flags=h?ln(O,f,b,C,Number.isFinite(ee)?ee:null,e,n,i):fi(O,s.get(o.id)?.state==="dormant",Number.isFinite(ee)?ee:null,e,n),r.push(cn(O))}return r.sort(gi).slice(0,k.routines)}function an(t){let e=0;for(let n of t)if(!(n.status==="running"||n.status==="paused"||n.status==="unknown"))if(n.status==="failed"||n.status==="timeout")e++;else break;return e}function ln(t,e,n,i,r,s,a,o){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let p=dn(c,r,s,a);return p&&l.push(p),l}if(t.consecutiveFailures>=a.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let p=0;p<a.missedFires&&(d=o(n,u,i),!!d);p++)u=d;return d&&s>d.getTime()+a.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${a.missedFires} scheduled fires missed`}),l}function fi(t,e,n,i,r){let s=[],a=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let o=dn(a,n,i,r);return o&&s.push(o),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),a===null?s.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&s.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),s}function dn(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*on?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/on)} days`:"Disabled and never ran"}}function cn(t){let e=new Set(t.flags.map(n=>n.reason));return t.attention=e.has("failing")?"critical":e.has("overdue")||e.has("dormant")||e.has("never-ran")?"warning":e.has("disabled-long")?"info":null,t}var un={critical:0,warning:1,info:2};function gi(t,e){let n=t.attention?un[t.attention]:3,i=e.attention?un[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function mi(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 hi(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 bi(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 Ie(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function A(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function yi(t,e){return t===void 0?void 0:A(t,e)}import{mkdirSync as wi,readFileSync as ki,renameSync as Si,writeFileSync as xi}from"fs";import{resolve as vi}from"path";function pn(t){return vi(_e(t),"_state.json")}function x(t){try{let e=JSON.parse(ki(pn(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{},...e?.popped&&typeof e.popped=="object"?{popped:e.popped}:{},...typeof e?.passAt=="string"?{passAt:e.passAt}:{},...Array.isArray(e?.wanted)?{wanted:e.wanted.filter(n=>typeof n=="string")}:{}}}catch{return{snoozed:{}}}}function H(t,e){wi(_e(t),{recursive:!0});let n=pn(t),i=`${n}.${process.pid}.tmp`;xi(i,JSON.stringify(e,null,2)+`
3
- `),Si(i,n)}function fn(t,e,n,i=Date.now()){let r=x(t),s={};for(let[a,o]of Object.entries(r.snoozed))Date.parse(o)>i&&(s[a]=o);s[e]=n.toISOString(),H(t,{...r,snoozed:s})}function Ka(t,e){H(t,{...x(t),lastDigest:e})}function Ee(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));H(t,{...r,popped:a,wanted:o})}function gn(t,e){let n=x(t);H(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function Ja(t,e=Date.now()){H(t,{...x(t),popped:{},passAt:new Date(e).toISOString()})}import{existsSync as z,readdirSync as Fi,readFileSync as Wi}from"fs";import{resolve as _}from"path";import{randomBytes as bn}from"crypto";import{existsSync as Ai,mkdirSync as _i,readdirSync as Ri,readFileSync as Ii,renameSync as yn,unlinkSync as Ei,writeFileSync as Ti}from"fs";import{resolve as wn}from"path";function mn(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var $i=t=>t.trim().split(`
4
- `).pop()?.slice(0,300)||"no output";async function hn(t,e,n,i=Re){let r=await i(t.bin,[...mn(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${$i(r.stderr||r.stdout)}`}}async function Qa(t,e,n,i,r=Re){return(await r(t.bin,[...mn(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var Ci=2e3,Di=t=>hn(t.wacli,t.to,t.text);function Te(t){return wn(t,".agentx","whatsapp-triage","drafts")}var Pi=t=>/^[a-z0-9-]{8,64}$/.test(t),ie=(t,e)=>wn(Te(t),`${e}.json`);function kn(t,e){_i(Te(t),{recursive:!0});let n=ie(t,e.id),i=`${n}.${process.pid}.tmp`;Ti(i,JSON.stringify(e,null,2)+`
5
- `,{mode:384}),yn(i,n)}function sl(t,e,n=Date.now()){let i=e.text.trim().slice(0,Ci);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${bn(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return kn(t,r),r}function se(t,e){if(!Pi(e))return null;try{return JSON.parse(Ii(ie(t,e),"utf-8"))}catch{return null}}function Sn(t,e){let n=Te(t);return Ai(n)?Ri(n).filter(i=>i.endsWith(".json")).map(i=>se(t,i.slice(0,-5))).filter(i=>!!i&&(!e||i.status===e)).sort((i,r)=>i.created_at.localeCompare(r.created_at)):[]}async function xn(t,e,n,i={}){let r=se(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let s=`${ie(t,e)}.${process.pid}.${bn(3).toString("hex")}.claim`;try{yn(ie(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??Di)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));o.ok?a.status="sent":(a.status="failed",a.error=o.error)}kn(t,a);try{Ei(s)}catch{}return a.status==="failed"?{ok:!1,error:a.error??"send failed"}:{ok:!0,draft:a}}ii();Et();Et();var ll=["done","skipped"],Ni=1e3;function Li(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 $n(t){return!!t.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'request_plans'").get()}function Ce(t){return{requestId:t.request_id,createdBy:t.created_by,createdAt:t.created_at,state:t.state,finishedAt:t.finished_at??null,notifiedAt:t.notified_at??null}}function vn(t){return{requestId:t.request_id,idx:t.idx,name:t.name,kind:t.kind,agentId:t.agent_id,doneWhen:t.done_when,state:t.state,needsApproval:!!t.needs_approval,approval:t.approval,cardId:t.card_id??null,message:t.message??null,toChannel:t.to_channel??null,toChat:t.to_chat??null,toAccount:t.to_account??null,checkUrl:t.check_url??null,checkContains:t.check_contains??null,stallMinutes:t.stall_minutes??null,evidence:t.evidence??null,note:t.note??null,dispatchedAt:t.dispatched_at??null,updatedAt:t.updated_at,nudges:t.nudges,lastNudgeAt:t.last_nudge_at??null,notifiedAt:t.notified_at??null}}var Oi={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"},oe=class{constructor(e){this.db=e;Li(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?Ce(n):null}steps(e){return this.db.prepare("SELECT * FROM request_plan_steps WHERE request_id = ? ORDER BY idx").all(e).map(vn)}step(e,n){let i=this.db.prepare("SELECT * FROM request_plan_steps WHERE request_id = ? AND idx = ?").get(e,n);return i?vn(i):null}listActive(){return this.db.prepare("SELECT * FROM request_plans WHERE state = 'active' ORDER BY created_at, rowid").all().map(Ce)}updateStep(e,n,i){let r=[],s=[];for(let[a,o]of Object.entries(i)){let l=Oi[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(Ce)}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,Ni))}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}))}},cl=_t;import{existsSync as Mi,readFileSync as ji}from"fs";Dt();ri();function An(t){let e=Pt(t),n={};if(Mi(e))try{n=Tt(JSON.parse(ji(e,"utf-8")))}catch{n={}}let i=Se.safeParse(n?.requests);return i.success?i.data:Se.parse(void 0)}async function ml(t,e={}){let n=(t.channels??[]).filter(i=>!we.has(i.toLowerCase().split("@")[0]));return n.length?{success:!1,error:`unknown channel ${n.map(i=>`"${i}"`).join(", ")}: use ${[...we].join(", ")}`}:Nt(i=>{let r=i.requests??={};for(let s of["enabled","channels","from","staleAfterHours","retentionDays","settleHandedBack"])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.headlines?.enabled!==void 0&&((r.headlines??={}).enabled=t.headlines.enabled),t.checkers){let s=r.checkers??={};for(let a of["enabled","checkEveryMinutes"])t.checkers[a]!==void 0&&(s[a]=t.checkers[a])}},{configPath:e.configPath,reload:e.reload})}var In=["card","schedule","memory","wiki","whatsapp","request"],Vi=280;function j(t,e=Vi){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function De(t){if(t.configPath)return _(t.configPath);let e=[_(t.root,"agentx.json"),_(t.root,".agentx","config.json")];return e.find(n=>z(n))??e[0]}function Pe(t){return t.wikiDir?_(t.wikiDir):_(t.root,".agentx","wiki")}function Ui(t){return M(t.root,"pending").map(Bi)}function Bi(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:j([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function qi(t){let e=De(t);if(!z(e))return[];let n;try{n=JSON.parse(Wi(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?Ft(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:j(`${d}${p&&a.schedule?` \xB7 first run ${Vt(Wt(a.schedule,l,i),l)}`:""}`),more:"agentx schedule list"})}return r}function En(t){let e=_(t,".agentx","memory");return z(e)?Fi(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function Hi(t){let e=En(t.root);if(e.length===0)return[];let n=new xe(t.root),i=[];for(let r of e)for(let s of n.held(r))i.push({key:`memory:${r}/${s.id}`,kind:"memory",title:`Fact ${r} learned from ${s.source.channel}`,ask:`Let ${r} use this fact in its prompts?`,yes:"use it",no:"keep it out for good",raised_by:r,created_at:s.createdAt,detail:j(s.content),more:`agentx memory facts held --agent ${r}`});return i}function zi(t){let e=t.sources.filter(n=>n.failure);return e.length?e.map(n=>`Recurring failure: ${n.agentId}'s ${n.failure.tool} fails with "${n.failure.errorClass}" in ${n.occurrences??1} sessions (${n.failure.runs} runs).`).join(" "):`${t.sources.length} source(s)${t.occurrences>1?`, seen in ${t.occurrences} sessions`:""}.`}function Xi(t){return Kt(Pe(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:j(`${zi(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function Gi(t){return Sn(t.root,"pending").map(e=>({key:`whatsapp:${e.id}`,kind:"whatsapp",title:`WhatsApp reply to ${e.chat_name||e.to}`,ask:`Send this to ${e.chat_name||e.to}? "${e.text}"`,yes:"send it on WhatsApp",no:"drop the draft",raised_by:e.agent,created_at:e.created_at,detail:j(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}function X(t){if(t.requests)return t.requests;if(_(t.root)!==process.cwd()||!z(_(t.root,".agentx","db.sqlite")))return null;let e=ke({quiet:!0});if(!e)return null;let n=_n.get(e);return!n&&!Rt(e)?null:(n||_n.set(e,n=new It(e)),n)}var _n=new WeakMap;function Cl(t){if(t.plans)return t.plans;if(t.requests||_(t.root)!==process.cwd()||!z(_(t.root,".agentx","db.sqlite")))return null;let e=ke({quiet:!0});if(!e||!$n(e))return null;let n=Rn.get(e);return n||Rn.set(e,n=new oe(e)),n}var Rn=new WeakMap;function Ki(t){let e=X(t);return e?e.listByState("needs_attention").map(n=>({key:`request:${n.id}`,kind:"request",title:B(n,120).headline,ask:`Not finished. Ask ${n.agentId} to pick it up again?`,yes:`hand it back to ${n.agentId}`,no:"drop the request",raised_by:n.agentId,created_at:new Date(n.createdAt).toISOString(),detail:j(`${n.attentionReason??"It needs attention"}. You said (${n.channel}): ${n.text}`),more:`agentx requests show ${n.id}`})):[]}var Tn={card:Ui,schedule:qi,memory:Hi,wiki:Xi,whatsapp:Gi,request:Ki};function Ji(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 Dl(t,e={}){let n=t.now??Date.now(),{snoozed:i}=x(t.root),r=[],s=[],a=0;for(let o of e.kinds??In){let l;try{l=Tn[o](t)}catch(c){s.push({kind:o,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=i[c.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){a++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(Ji),{items:r,snoozed:a,errors:s}}function Yi(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),i=t.slice(e+1);return!In.includes(n)||!i?null:{kind:n,ref:i}}function Zi(t,e,n){switch(e){case"card":return q(t.root,n)?.status==="pending";case"wiki":return Gt(Pe(t),n)?.status==="pending";case"whatsapp":return se(t.root,n)?.status==="pending";default:return Tn[e](t).some(i=>i.key===`${e}:${n}`)}}async function Cn(t,e,n,i={}){let r=Yi(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(!Zi(t,s,a))return{ok:!1,error:`nothing waiting for "${e}"`};let u=i.laterHours&&i.laterHours>0?i.laterHours:24,d=new Date(o+u*36e5);return fn(t.root,e,d,o),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(s){case"card":{let u=nn(t.root,a,c?"yes":"no",{by:l,note:i.note,now:o,choice:i.choice,text:i.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}${u.card.choice?` (${u.card.choice}${u.card.choice_suggested?", the suggested option":""})`:""}`}:u}case"schedule":{let u=await(c?Ut:Bt)(a,{configPath:De(t),reload:t.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=a.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=a.slice(0,u),p=a.slice(u+1);if(!En(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new xe(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=Pe(t),d=c?Jt(u,a,{by:l,force:i.force,now:o}):Yt(u,a,{by:l,reason:i.note,now:o});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await xn(t.root,a,c?"yes":"no",{by:l,now:o,send:t.sendWhatsApp});return u.ok?{ok:!0,message:c?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}case"request":{let u=X(t),d=u?.get(a);return!u||!d||d.state!=="needs_attention"?{ok:!1,error:`nothing waiting for "${e}"`}:c?An(De(t)).enabled?(u.requestPickup(a,o),{ok:!0,message:`${e}: ${d.agentId} will be asked to pick it up again`}):{ok:!1,error:"Requests are off, so nothing would hand it back. Turn them on (agentx requests settings --enabled on), or answer no to drop it."}:(u.close(a,"dropped",i.note?.trim()||`dropped by ${l}`,o),{ok:!0,message:`${e}: dropped`})}}}var Dn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Nl(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/screen"||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"||t==="/owner/told"}function Ll(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 Ol(t){return Dn.has(t)}function Ml(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(Dn.has(t.remoteAddress))return{allowed:!0,reason:"loopback"};if(t.acceptedTokens.size===0)return{allowed:!0,reason:"no-tokens-configured"};let e=t.authorizationHeader||"",n=e.startsWith("Bearer ")?e.slice(7).trim():"";return n&&t.acceptedTokens.has(n)?{allowed:!0,reason:"token"}:{allowed:!1,reason:"missing-or-invalid-token"}}function jl(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 Fl(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 ae(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function Qi(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function es(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Vl(t,e=es()){let n=ae(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=Qi(n),s=[ae(t.host),ae(t["x-forwarded-host"])].filter(Boolean).map(a=>a.toLowerCase());return r&&s.includes(r)?"same-origin":"foreign"}let i=ae(t["sec-fetch-site"]).toLowerCase();return i==="cross-site"||i==="same-site"?"foreign":"none"}function Ul(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as rr,mkdirSync as Es,readFileSync as Ts,renameSync as Cs,writeFileSync as Ds}from"fs";import{homedir as Ps}from"os";import{dirname as Ns,join as Ls}from"path";import{execFile as ds,execFileSync as ps}from"child_process";import{execFileSync as ts}from"child_process";import{existsSync as Nn,mkdirSync as ns,readdirSync as rs,readFileSync as Ln,renameSync as is,writeFileSync as ss}from"fs";import{homedir as On}from"os";import{join as Le}from"path";var v="siri:",Mn="com.apple.ttsbundle.gryphon-neural_",jn=t=>!!t&&t.startsWith(Mn),os=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],as=()=>{try{return ts("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},Ne;function Oe(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&Ne!==void 0)return Ne;let{platform:n=process.platform,exists:i=Nn,prefDomain:r=as}=t,s=n==="darwin"&&os.every(a=>i(a))&&r();return e||(Ne=s),s}var Fn=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Wn={aaron:"male",damon:"male",daniel:"male",pierre:"male",samer:"male",arthur:"male",gordon:"male",martin:"male",nora:"female",simone:"female",marie:"female",soha:"female",martha:"female",catherine:"female",helena:"female",nicky:"female"},Me=t=>Wn[t.toLowerCase()]??null;function le(t){let e=/^com\.apple\.ttsbundle\.gryphon-neural_([a-z]+)_([a-z]{2}-[A-Z]{2})_premium$/.exec(t);return e?{name:e[1],locale:e[2]}:null}var ls=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function cs(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(ls)){let a=`${i}-${r}`,o=`${Mn}${s}_${a}_premium`;e.has(o)||e.set(o,{id:o,name:s[0].toUpperCase()+s.slice(1),locale:a,quality:"premium",gender:Wn[s]??null,siri:!0})}return[...e.values()]}function ce(t=Fn,e={}){if(!Oe(e))return[];let n=[];for(let i of t){let r;try{r=rs(i)}catch{continue}for(let s of r)try{n.push(Ln(Le(i,s,"Info.plist"),"latin1"))}catch{}}return cs(n)}var Pn=`#!/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:-"${Fn.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
- `,us=(t=On())=>Le(t,".agentx","voice","siri-say.sh");function Vn(t=On()){let e=us(t);return Nn(e)&&Ln(e,"utf8")===Pn||(ns(Le(t,".agentx","voice"),{recursive:!0}),ss(`${e}.tmp`,Pn,{mode:493}),is(`${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")`,fs=new Set(["Fred","Kathy","Ralph","Junior"]),gs={Flo:"female",Sandy:"female",Shelley:"female",Grandma:"female",Kathy:"female",Eddy:"male",Reed:"male",Rocko:"male",Grandpa:"male",Fred:"male",Ralph:"male",Junior:"male"};function Bn(t){let e=[];for(let n of t.split(`
167
- `)){let[i,r,s,a,o]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!fs.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":gs[r]??null})}return e}var ms=10*60*1e3,Yl=60*1e3,F=null,je=!1;function Fe(t=Date.now(),e=ms){if(process.platform!=="darwin")return[];if(F)t-F.at>e&&!je&&(je=!0,ds("osascript",["-l","JavaScript","-e",Un],{timeout:1e4},(n,i)=>{je=!1,n||(F={at:Date.now(),voices:[...Bn(String(i)),...ce()]})}));else try{F={at:t,voices:[...Bn(ps("osascript",["-l","JavaScript","-e",Un],{encoding:"utf8",timeout:1e4})),...ce()]}}catch(n){We(`[voice] could not list system voices: ${String(n?.message??n).split(`
168
- `)[0]}`),F={at:t,voices:ce()}}return F.voices}var We=t=>process.stderr.write(t+`
169
- `),ue=new Set;function Zl(t){We=t}function N(t,e){ue.has(t)||(ue.add(t),We(e))}function zn(t){for(let e of ue)t(e)&&ue.delete(e)}var Xn=()=>{};function Ql(t){Xn=t}function Gn(t){try{Xn(t)}catch(e){N("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var hs={premium:3,enhanced:2,standard:1},bs=new Set(["Grandma","Grandpa"]);function qn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!bs.has(t.name)?1:0;return hs[t.quality]*10+e}var W=t=>t.toLowerCase().split(/[-_]/)[0],Hn=t=>t.id.startsWith("com.apple.voice.");function Ve(t,e,n,i=new Set){let r=G(t.filter(o=>!o.siri&&W(o.locale)===W(e)),e);if(r.some(Hn)&&(r=r.filter(Hn)),n==="female"||n==="male"){let o=r.filter(l=>l.gender===n);o.length&&(r=o)}if(!r.length)return null;let s=r.filter(o=>o.quality===r[0].quality),a=new Set([...i].map(o=>o.toLowerCase()));return s.find(o=>!a.has(o.name.toLowerCase()))??s[0]}function G(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=W(e),r=t.filter(s=>W(s.locale)===i);return(r.length?r:t).slice().sort((s,a)=>qn(a)-qn(s)||+(a.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(a.name)||s.locale.localeCompare(a.locale))}function K(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=G(e.filter(p=>p.siri&&p.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=K(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=G(e.filter(c=>c.name.toLowerCase()===a),n);return(s?o.find(c=>c.quality===s[2].toLowerCase()):void 0)??o[0]??null}function Kn(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(a=>a.toLowerCase())),s="female";for(let a of t){let o=a.gender==="female"||a.gender==="male",l=o?a.gender:s,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(o?e.find(d=>d.gender===l):void 0)??c[0]??e[i.size%e.length];i.set(a.id,u),r.add(u.name.toLowerCase()),o||(s=s==="female"?"male":"female")}return i}$t();var Ue="system",ys=t=>t.trim().toLowerCase()===Ue,ws="21m00Tcm4TlvDq8ikWAM";function Be(t,e,n={},i=Fe()){let r=e[t],s=r?.name||t,a=r?.voice,o=He(e,n,i).get(t)??null,l=vs(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?pe(o):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:a?.gender??null,style:a?.style||null,intro:a?.intro||As(s,r?.systemPrompt),...a?.rate?{rate:a.rate}:{},...a?.priority?{priority:a.priority}:{}}}var pe=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function ks(t,e,n,i){if(!e||!n.length)return null;let r=K(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.`),Gn(e)),r}function Qn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(v))return{locale:e,gender:Me(n.slice(v.length).trim())};let i=le(n);return i?{locale:i.locale,gender:Me(i.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var er=t=>t.toLowerCase().split(/[-_]/)[0],Jn=(t,e)=>typeof t=="string"?t:t?.[er(e)];function de(t,e,n,i){if(e!==void 0)return ys(e)?null:ks(t,e,n,i)??void 0}var qe=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Ss(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,a=[],o=de("voice.system",Jn(e.system,r),n,r),l=()=>new Set([...i,...[...s.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=Jn(u.system,r),p=de(u.id,d,n,r),f=p!==void 0?p:d!==void 0&&n.length?xs(u,d,r,o,n,l()):o!==void 0&&qe(o,u.gender)?o:void 0;f!==void 0?s.set(u.id,f):a.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of Kn(a,G(n.filter(p=>!p.siri),r),c))s.set(u,d);return s}function xs(t,e,n,i,r,s){for(let o of t.fallbacks??[]){let l=de(`${t.id}.fallbacks`,o,r,n);if(l!==void 0)return l}if(i!==void 0&&qe(i,t.gender))return i;let a=Qn(e,n);return Ve(r,a.locale,t.gender??a.gender,s)??void 0}function vs(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=de(`${o}.${u}`,d,r,u);p===void 0&&r.length&&(p=Ve(r,u,n??Qn(d,u).gender)??void 0),p!==void 0&&c(p)&&(s[er(u)]=p)}};return a("voice.system",i.system,o=>qe(o,n)),a(t,e,()=>!0),s}function ic(t,e){let n=e?te(e):null;if(!n||!(n in t.systemByLanguage))return t;let i=t.systemByLanguage[n];return{...t,systemVoice:i?.id??null,systemVoiceName:i?pe(i):null}}function He(t,e={},n=Fe()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return Ss(i,e,n)}function ze(t,e){let n={provider:t.provider,elevenlabs:$s(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 $s(t,e){return t||e||process.env.AGENTX_VOICE_ID||ws}function As(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,Rs=500,Yn=class{constructor(e=_s){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Zn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Zn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>Rs&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Zn=(t,e)=>`${t}\0${e}`;function tr(t,e){let n=t.style?` Your speaking manner: ${t.style}.`:"";return e?`[VOICE INTRO] This is your first spoken exchange with this person in a while. Open with one short sentence introducing yourself in your own manner, along the lines of "${t.intro}", then answer.${n}`:"[VOICE CASUAL] You have already introduced yourself in this voice conversation. Do not introduce yourself or greet again; talk casually, like a colleague in the same office."+n}function sc(t,e,n,i={}){let r=e[t],s=Be(t,e,i),a=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:ze(s),persona:a||`You are ${s.name}.`,introLine:tr(s,n)}}var Is="[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 oc(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`${Is}
170
- ${tr(r,e.voice.introduce===!0&&!!i)}`}var Os="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",ir=(t=Ps())=>Ls(t,".agentx","voice","health.json");function Ms(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===Ue)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 K(i,e,n)!==null}function js(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 Fs(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:a,perLanguage:o}of js(t)){if(Ms(s,e,a))continue;i??=He(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?pe(c):"the OS default voice"),n.set(s,l)}return[...n.values()]}function Xe(t){let e=le(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(v)){let n=t.slice(v.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function Ws(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${Xe(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 ${Os}. Agents switch back on their own once it is installed.`}}function Vs(t=ir()){if(!rr(t))return null;try{let e=JSON.parse(Ts(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function Us(t,e){Es(Ns(t),{recursive:!0}),Ds(`${t}.tmp`,JSON.stringify(e,null,2)+`
173
- `),Cs(`${t}.tmp`,t)}var nr=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,i=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??ir(),s=new Map((Vs(r)?.missing??[]).map(d=>[d.voice,d])),a=Fs(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] ${Xe(d)} is installed again; its agents speak with it again`);l.length&&zn(d=>l.some(p=>d===p||d.endsWith(`:${p}`)));let c=o.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:p}=Ws(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=>Xe(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=o.length>0;let u={checkedAt:i.toISOString(),missing:o};return(!rr(r)||JSON.stringify(o)!==JSON.stringify([...s.values()]))&&Us(r,u),u}finally{this.running=!1}}};import{readFileSync as Ke,writeFileSync as ur,existsSync as Je,readdirSync as Ys,statSync as Zs}from"fs";import{resolve as Ye,join as Qs}from"path";import{existsSync as sr,mkdirSync as Bs,readFileSync as qs,writeFileSync as or}from"fs";import{dirname as Hs,resolve as ar}from"path";import{z as m}from"zod";var zs=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),Xs=m.object({id:m.string(),title:m.string(),description:m.string().optional(),assignee:m.string().optional(),labels:m.array(m.string()).default([]),milestone:m.string().optional(),status:m.enum(["todo","doing","blocked","done"]).default("todo"),priority:m.number().int().optional(),estimatedSeconds:m.number().int().optional(),source:zs.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),Gs=m.object({version:m.literal(1),items:m.array(Xs).default([])}),fe=class{constructor(e){this.path=e}jsonPath(){return ar(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return ar(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return sr(this.jsonPath())}load(){let e=this.jsonPath();if(!sr(e))return{version:1,items:[]};let n=qs(e,"utf-8");try{return Gs.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();Bs(Hs(n),{recursive:!0}),or(n,JSON.stringify(e,null,2)+`
174
- `),or(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(s=>s.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let i=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??i,updatedAt:i};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),i=new Set(n.items.map(a=>a.id)),r=new Date().toISOString(),s=[];for(let a of e){if(i.has(a.id))continue;let o={...a,labels:a.labels??[],status:a.status??"todo",createdAt:a.createdAt??r,updatedAt:r};n.items.push(o),s.push(o),i.add(o.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(a=>a.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let s={...i.items[r],...n,id:i.items[r].id,createdAt:i.items[r].createdAt,updatedAt:new Date().toISOString()};return i.items[r]=s,this.save(i),s}remove(e){let n=this.load(),i=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===i?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],i={doing:[],blocked:[],todo:[],done:[]};for(let s of e.items)i[s.status].push(s);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[s,a]of r)if(i[s].length){n.push(`## ${a}`,"");for(let o of i[s]){let l=s==="done"?"x":" ",c=o.assignee?`@${o.assignee} `:"",u=o.estimatedSeconds?` [time: ${Math.round(o.estimatedSeconds/60)}m]`:"",d=o.source?` (${o.source.type}: ${o.source.project}#${o.source.iid})`:"";n.push(`- [${l}] ${c}${o.title}${u}${d}`),o.source?.url&&n.push(` - <${o.source.url}>`),o.labels.length&&n.push(` - labels: ${o.labels.join(", ")}`),o.milestone&&n.push(` - milestone: ${o.milestone}`),o.blocker&&n.push(` - BLOCKED: ${o.blocker}`)}n.push("")}return n.join(`
175
- `)}};function yc(t){return`${t.type}:${t.project}:${t.iid}`}function lr(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let a=r.find(o=>o.agentId===s);a?.gitlabUsernames?.length?i.push(a.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let a=r.find(o=>o.agentId===s);a?.githubUsernames?.length?i.push(a.githubUsernames[0]):i.push(s)}}return i}async function Ge(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?Ks(t.source,e,n,i):t.source.type==="github"?Js(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function Ks(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 b=await h.json();return Array.isArray(b)&&b[0]?.id?b[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 Js(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(b=>typeof b=="string"?b:b.name):[],h=new Set([...g,...e.addLabels??[]]);for(let b of e.removeLabels??[])h.delete(b);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 Ze=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,ge=/@([a-z0-9_-]+)/i,cr=/\[time:\s*([0-9hm\s]+)\]/i;function eo(t){let e=t.match(/(\d+)\s*h/i),n=t.match(/(\d+)\s*m/i);return(e?parseInt(e[1],10)*3600:0)+(n?parseInt(n[1],10)*60:0)}var Qe=class{constructor(e,n,i=()=>{}){this.path=e;this.daemon=n;this.log=i;this.store=new fe(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Ye(process.cwd(),this.path);return Je(e)?Ke(e,"utf-8").split(`
176
- `):[]}writeMd(e){let n=Ye(process.cwd(),this.path);ur(n,e.join(`
177
- `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(s=>s.status!=="done"&&(!s.assignee||s.assignee.toLowerCase()===e.toLowerCase())).map(s=>this.toWorkItem(s));let n=this.readMd(),i=[];for(let r=0;r<n.length;r++){let s=n[r].match(Ze);if(!s||s[2].toLowerCase()==="x")continue;let o=s[3],l=o.match(ge);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=o.match(cr),u=o.replace(ge,"").replace(cr,"").trim();i.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?eo(c[1]):void 0,priority:r})}return i}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let i=this.store.findById(n);if(!i)return;let r=this.store.update(n,{assignee:i.assignee||e,status:"doing"});if(r.source&&this.daemon){let s=lr([r.assignee||e],r.source,this.daemon);Ge(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&&Ge(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(Ze))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"}}},et=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(Je(e))for(let i of Ys(e)){let r=Qs(e,i);Zs(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Ye(process.cwd(),this.root),n);let i=[];for(let r of n){let s=Ke(r,"utf-8").split(`
178
- `);for(let a=0;a<s.length;a++){let o=s[a].match(Ze);if(!o||o[2].toLowerCase()==="x")continue;let l=o[3].match(ge);!l||l[1].toLowerCase()!==e.toLowerCase()||i.push({id:`wiki:${r}:${a}`,title:o[3].replace(ge,"").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(!Je(s))return;let a=Ke(s,"utf-8").split(`
179
- `);n.status==="done"&&a[r]&&(a[r]=a[r].replace(/- \[ \]/,"- [x]"),ur(s,a.join(`
180
- `)))}},tt=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 Ac(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new Qe(i.path,e,n);case"wiki":return new et(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 tt(r.host,r.token,a,s,n)}}}var nt="unmapped";function rt(t,e=[]){if(!t)return nt;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 to(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,rt(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 no(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 Rc(t,e){let n=no(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return rt(t.project,e.projects);if(t.agentId){let i=to(e).get(t.agentId);if(i)return i}return nt}function Ic(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 ro=t=>t===nt?"internal":"client";function io(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??ro(t),respondWithinMinutes:so(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Ec(t){let e=new Set;for(let n of t.projects??[])e.add(rt(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=>io(n,t))}function so(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 oo=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,ao=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function dr(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(ao)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=lo(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 Cc(t){if(!t||!t.includes("agentx:ui"))return t;let e=oo.exec(t);return e?t.slice(0,e.index).trimEnd():t}function lo(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 Pc(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 co=5*6e4;function D(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var pr=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],i=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(D)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${D(n)}`}cleanupExpired(){let e=Date.now();for(let[n,i]of this.pending){let r=i.filter(s=>s.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==i.length&&this.pending.set(n,r)}for(let[n,i]of this.recentRings)i<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,i){return this.addSubscriber(e,n,{kind:"sse",res:i})}subscribeInternal(e,n,i){return this.addSubscriber(e,n,{kind:"callback",deliver:i})}addSubscriber(e,n,i){let r={callId:e,recipient:n,sink:i};this.subs.add(r);let s=i.kind==="sse"?"sse":"internal";this.log(`subscribe[${s}] call=${e} as=${n} (${this.subs.size} total)`);let a=this.pendingKey(e,n),o=this.pending.get(a);if(o&&o.length){let l=Date.now(),c=o.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(a),c.length&&this.log(`flushed ${c.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${s}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
181
- 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+co),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 uo,readFileSync as fr,renameSync as po,rmSync as fo,writeFileSync as go}from"fs";import{homedir as mo}from"os";import{dirname as ho,join as bo}from"path";var gr=bo(mo(),".agentx","call.json");function yo(t=gr,e=Date.now()){try{let n=JSON.parse(fr(t,"utf-8"));if(n?.active===!0&&!(n.until&&Date.parse(n.until)<=e))return{active:!0,mode:"call",reason:`in a call${n.reason?`: ${n.reason}`:""}`}}catch{}return{active:!1,mode:null,reason:"not in a call"}}function mr(t=Mt,e=yo){let n=t();return n.active?n:e()}function Fc(t,e,n=gr,i=Date.now()){let r=null;try{r=JSON.parse(fr(n,"utf-8"))}catch{}if(r&&r.source&&r.source!=="daemon")return;if(!t){r&&fo(n,{force:!0});return}uo(ho(n),{recursive:!0});let s=`${n}.${process.pid}.tmp`;go(s,JSON.stringify({active:!0,source:"daemon",reason:t,until:new Date(i+e).toISOString()})+`
184
- `),po(s,n)}var wo={perClient:5,global:10,windowMs:10*60*1e3,lockoutMs:5*60*1e3},hr=class{constructor(e=wo,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)}},ko="That code didn't work. Check it, or run agentx app pair for a new one.",So=400;async function Uc(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 Qt(t,1024)).code}catch{}let o=e.codes.redeem(a),l=o?e.verify(o.token):null;return await xo(n,e.minMs??So),!o||!l?(e.limiter.fail(r),i(`[app] pair-code failed from ${r}`),{status:401,body:{error:ko}}):(e.limiter.succeed(r),i(`[app] pair-code paired ${o.tokenId} (${l}) from ${r}`),{status:200,body:{device:l},token:o.token})}async function xo(t,e){let n=t+e-Date.now();n>0&&await new Promise(i=>setTimeout(i,n))}import{execFile as Fo}from"child_process";import{mkdtempSync as Do,rmSync as Po,writeFileSync as No}from"fs";import{tmpdir as Lo}from"os";import{join as Sr}from"path";import{randomBytes as vo}from"crypto";var E={top:8,side:32,bottom:60},it={height:56,keep:52},br=`
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"}),wr=t=>`${t.getDate()} ${t.toLocaleDateString("en-US",{month:"short"})}`;function $o(t,e){let n=new Date(t);return Number.isNaN(n.getTime())?"":`since ${n.toDateString()===new Date(e).toDateString()?yr(n):wr(n)}`}function Ao(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[wr(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 Ro(t){return t.origin?.kind==="request"?"Hand it back":t.draft?"Send":t.choices?.length?"Choose":"Yes"}var st=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>`,Io=st('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),Eo=st('<path d="m6 15 6-6 6 6"/>'),To=st('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function kr(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=vo(12).toString("base64"),s=t.choices??[],a=t.origin?.kind==="reminder",o=t.origin?.kind==="request",l=Xt(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:Ht,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>${br}</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($o(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">${Eo}</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>${Io}<span>${o?"It stays in Open requests on the Approvals page until you close it.":`If you don't answer by ${w(Ao(t.expires,n))}: ${w(t.if_silent)}.`}</span></div>
332
- <div>${To}<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">${Ro(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}">${Co}</script>
339
- </body></html>`}var Co=`
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 Oo=440,Mo=`
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+it.height}, keep = ${it.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 jo(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"&&vr.includes(i.why))return{action:"dismiss",why:i.why};if(i?.action!=="yes")return{action:"dismiss"};let r=e.choices??[],s;if(r.length){if(typeof i.choice!="string"||!r.includes(i.choice))return{action:"dismiss"};s=i.choice}let a;return e.draft&&(a=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
505
- `).trim():"",!a||a.length>qt.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...a?{text:a}:{}}}async function xr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=Do(Sr(Lo(),"agentx-card-"));try{let s=Sr(r,"card.html");No(s,kr(t,{...e,still:!!e.capture}),{mode:384});let a=["-l","JavaScript","-e",Mo,s,String(Oo),String(i),...e.capture?[e.capture]:[]],o=await n("/usr/bin/osascript",a,(i+10)*1e3);return o.ok?jo(o.stdout,t):null}finally{Po(r,{recursive:!0,force:!0})}}var vr=["not now","timed out","closed"],Wo=(t,e,n)=>new Promise(i=>{try{Fo(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),$r=160,ot=15e3;function Ar(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>$r?e.slice(0,$r):e}async function Vo(t,e,n,i,r){let s=e.sound==="chime"?i?"":"Glass":e.sound,a=s?Zt(s):null;if(a&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),a],ot),!!e.speak)if(r){let o;await Promise.race([r(Ar(t)),new Promise(l=>{o=setTimeout(l,ot)})]),clearTimeout(o)}else{let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",Ar(t)],ot)}}function Ir(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function Uo(t,e,n){return Ir(["on run argv","set opts to items 3 thru -1 of argv",'set pick to choose from list opts with title (item 1 of argv) with prompt (item 2 of argv) OK button name "Next" cancel button name "Not now"','if pick is false then return ""',"return item 1 of pick","end run"],[t,e,...n])}function _r(t,e,n,i,r){return Ir(["on run argv","set AppleScript's text item delimiters to linefeed","set btns to text items of (item 3 of argv)","set secs to (item 5 of argv) as integer","if (count of argv) > 5 then","set r to display dialog (item 2 of argv) with title (item 1 of argv) default answer (item 6 of argv) buttons btns default button (item 4 of argv) giving up after secs","else","set r to display dialog (item 2 of argv) with title (item 1 of argv) buttons btns default button (item 4 of argv) giving up after secs","end if",'if gave up of r then return ""',"if (count of argv) > 5 then return (button returned of r) & linefeed & (text returned of r)","return button returned of r","end run"],[t,e,n.join(`
506
- `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function Rr(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
507
- `);return n<0?{button:e,text:""}:{button:e.slice(0,n),text:e.slice(n+1)}}function at(t){return[t.ask,t.recommend?`Recommended: ${t.recommend}`:"",`From ${t.raised_by}`].filter(Boolean).join(`
508
-
509
- `)}async function Er(t,e,n={}){let i=n.run??Wo,r=(e.style??"card")==="card",s=Vo(t,e,i,r,n.speak).catch(()=>{});if(r){let a=await xr(t,{timeoutSeconds:e.timeoutSeconds,sound:e.sound,volume:e.volume,theme:e.theme,from:n.from,capture:n.capture,pick:n.pick},i).catch(()=>null);if(a)return a}return await s,Bo(t,e,i)}async function Bo(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,at(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):`:`${at(t)}
512
-
513
- Message (edit it if you like):`,d=await n("/usr/bin/osascript",_r(s,c,a?["Cancel","Send"]:["Not now","No","Send"],i,zt(t.draft,a)),r),p=d.ok?Rr(d.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...a?{choice:a}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let o=await n("/usr/bin/osascript",_r(s,at(t),["Not now","No","Yes"],i),r),l=o.ok?Rr(o.stdout):null;return l?.button==="Yes"?{action:"yes"}:l?.button==="No"?{action:"no"}:{action:"dismiss"}}var ut=24*36e5,lt=!1,qo=10*6e4,Tr=-1/0;function Cr(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=x(t.root),a=r?Date.parse(r):NaN,o=M(t.root,"pending").filter(c=>Date.parse(c.expires)>e),l=o.find(c=>s.includes(`card:${c.id}`));if(l)return l;for(let c of o){let u=`card:${c.id}`;if(n[u]||rn(t.root,c.id,e))continue;let d=i[u];if(d&&Date.parse(d)>e)continue;let p=Date.parse(c.created_at);if(!(e-p>ut&&!(p<=a)))return c}return null}function ct(t){try{return X(t)?.listByState("needs_attention")??[]}catch{return[]}}var Dr=new Map;function Ho(t){let e=t.now??Date.now(),{popped:n={},snoozed:i}=x(t.root);return ct(t).find(r=>{let s=`request:${r.id}`,a=i[s];return Dr.get(r.id)===B(r,Ae.title).headline?!1:!n[s]&&!(a&&Date.parse(a)>e)&&e-r.updatedAt<=ut})??null}function zo(t,e){return{id:t.id,title:B(t,Ae.title).headline,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+ut).toISOString(),raised_by:t.agentId,created_at:new Date(t.createdAt).toISOString(),status:"pending",origin:{kind:"request",id:t.id}}}async function yu(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(lt)return"busy";let r=Cr(e)?null:Ho(e),s=r?zo(r,e.now??Date.now()):Cr(e);if(!s)return"none";let a=(t.focus??mr)();if(a.active)return"held";let o=`${r?"request":"card"}:${s.id}`,l=(x(e.root).wanted??[]).includes(o)?null:en(s);if(l){if(r)Dr.set(r.id,s.title);else{let c=[...M(e.root,"pending").map(u=>`card:${u.id}`),...ct(e).map(u=>`request:${u.id}`)];Ee(e.root,o,c,e.now)}return i(`[approvals] popup: ${o} not shown, back to ${s.raised_by}: ${l}`),t.returnToAuthor?.(s,tn(s,l)),"returned"}lt=!0;try{let c=[...M(e.root,"pending").map(b=>`card:${b.id}`),...ct(e).map(b=>`request:${b.id}`)];Ee(e.root,o,c,e.now),i(`[approvals] popup: showing ${o} from ${s.raised_by}`);let u=e.now??Date.now(),d=!!r&&u-Tr<qo;r&&n.speak&&(Tr=u);let p=t.agentName?.(s.raised_by)??(s.node?`${s.raised_by} on ${s.node}`:void 0),f=await(t.show??Er)(s,d?{...n,speak:!1}:n,{from:p,speak:t.speak});if(f.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${f.why??"no answer"} (${jt(a)} when shown)`),"shown";if(!(r?X(e)?.get(r.id)?.state==="needs_attention":q(e.root,s.id)?.status==="pending"))return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let h=await Cn(e,o,f.action,{by:"operator (popup)",...f.action==="yes"?{choice:f.choice,text:f.text}:{}});return i(h.ok?`[approvals] popup: ${h.message}`:`[approvals] popup: ${o} not recorded: ${h.error}`),"shown"}catch(c){return i(`[approvals] popup failed for ${o}: ${c?.message??c}`),"shown"}finally{lt=!1}}function wu(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:")?q(t.root,e.slice(5)):null;return i?i.status!=="pending"?{ok:!1,error:`${e} is already ${i.status}`}:(gn(t.root,e),{ok:!0,message:`${e} will show on the Mac within a minute`}):{ok:!1,error:`no card "${e}"; the popup shows decision cards only`}}import{closeSync as J,createReadStream as Xo,fstatSync as Go,openSync as Ko,realpathSync as Pr}from"fs";import{isAbsolute as Jo,resolve as Nr,sep as Lr}from"path";var Au="/app-files",Yo=/^[A-Za-z0-9_.:-]{1,64}$/;function Zo(t,e,n=process.cwd()){if(!e||e.length>ne.pathChars||e.includes("\0"))return{ok:!1,status:400,error:"bad file path"};if(e.split(/[\\/]/).includes(".."))return{ok:!1,status:403,error:`the path leaves the workspace: copy the file into ${$e}/ first`};if(!ve(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=Pr(Nr(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=Pr(Jo(e)?e:Nr(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+Lr))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${$e}/ first`};let s=ve(r);return s?{ok:!0,path:r,...s}:{ok:!1,status:415,error:"this type of file is not served"}}function Qo(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 ea(t,e,n){return{"Content-Type":t,"Content-Disposition":Qo(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 ta(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,O)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(O))};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(!Yo.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=Zo(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=Ko(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=Go(c);if(!C.isFile())return J(c),r(404,{error:"not a file"});u=C.size}catch{return J(c),r(404,{error:"file not found"})}if(u>ne.bytes)return J(c),r(413,{error:`the file is larger than ${ne.bytes/1024/1024} MB`});let d=l.path.split(Lr).pop()||"file",p=ea(l.mime,d,l.kind),f=ta(t.headers.range,u);if(f==="unsatisfiable"){J(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){J(c),e.end();return}let b=Xo("",{fd:c,start:g,end:h,autoClose:!0});b.on("error",()=>e.destroy()),e.on("close",()=>b.destroy()),b.pipe(e)}import{spawn as Y}from"child_process";import{readFileSync as na,writeFileSync as ra}from"fs";import{tmpdir as ia}from"os";import{join as sa}from"path";$t();var Or=t=>t&&t!==1?Math.round(175*t):null,me=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function oa(){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=na(t,"utf8").trim();if(e)return e}catch{}return null}function Lu(t=oa()){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",...me(n.voice.rate)?{voice_settings:{speed:me(n.voice.rate)}}:{}}),signal:i});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let s=sa(ia(),`agentx-say-${process.pid}-${++e}.mp3`);return ra(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 Mr(t,e){let n=t.languages&&te(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var aa=(t,e="")=>{let n=Mr(t,e),i=Or(t.rate);return[...n&&!jn(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function la(t,e,n){if(!n)return["say",aa(t,e)];let i=Mr(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function Ou(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Mu(t=dt()){if(t)try{Y("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function ju(t=dt()){if(t)try{Y("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function dt(t={},e){if(!Oe(t))return null;try{return Vn(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 Fu=(t,e)=>{if(!t){let[n,i]=la(e.voice,e.text,dt()),r=Or(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,a=Y(n,i,{stdio:["pipe","ignore","ignore"],env:s});return a.stdin?.on("error",()=>{}),a.stdin?.end(e.text),a}return process.platform==="darwin"?Y("afplay",[t],{stdio:"ignore"}):Y("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as jr}from"child_process";import{accessSync as ca,constants as ua,readFileSync as Fr}from"fs";import{homedir as da}from"os";import{basename as V,delimiter as Wr,dirname as pa,extname as fa,join as pt}from"path";var P={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Vr(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:gt()}:null}var gt=()=>`The recording is longer than ${P.ms/6e4} minutes.`,ga={"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 Ur(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return ga[e]??null}function Br(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 mt(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 ft(t,e,n=process.env.PATH??""){let i=da(),r=[pt(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Wr).filter(Boolean)];for(let s of[e,...r.map(a=>pt(a,t))])if(s)try{return ca(s,ua.X_OK),s}catch{}return null}function Hu(t){return{key:t,mlx:ft("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:ft("whisper",process.env.AGENTX_WHISPER),ffmpeg:ma()}}var ma=()=>ft("ffmpeg",process.env.AGENTX_FFMPEG);async function qr(t,e){return e?ha(t,e):null}async function ha(t,e){let n=String(P.ms/1e3+5);try{let r=[...(await ba(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 Hr(t,e,n,i){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Fr(t)],{type:e}),V(t));let s=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:i??AbortSignal.timeout(6e4)});if(!s.ok)throw new Error(`ElevenLabs ${s.status}: ${(await s.text().catch(()=>"")).slice(0,160)}`);let a=await s.json();if(typeof a.text!="string")throw new Error("ElevenLabs returned no text");return a.text.trim()}async function zr(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:`${pa(i)}${Wr}${process.env.PATH??""}`};await ya(e,s,12e4,a);try{return Fr(pt(r,V(n,fa(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function ba(t,e,n){return new Promise((i,r)=>{let s=jr(t,e,{stdio:["ignore","ignore","pipe"]}),a="",o=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${V(t)} took too long`))},n);s.stderr.on("data",l=>{a=(a+l).slice(-8192)}),s.on("error",l=>{clearTimeout(o),r(l)}),s.on("exit",l=>{clearTimeout(o),l===0?i(a):r(new Error(`${V(t)} exited ${l}`))})})}function ya(t,e,n,i=process.env){return new Promise((r,s)=>{let a=jr(t,e,{stdio:["ignore","pipe","pipe"],env:i}),o="",l="",c=setTimeout(()=>{a.kill("SIGKILL"),s(new Error(`${V(t)} took longer than ${n/1e3}s`))},n);a.stdout.on("data",u=>{o.length<4096&&(o+=u)}),a.stderr.on("data",u=>{l.length<4096&&(l+=u)}),a.on("error",u=>{clearTimeout(c),s(u)}),a.on("exit",u=>{clearTimeout(c),u===0?r(o):s(new Error(`${V(t)} exited ${u}: ${l.trim().split(`
515
- `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as wa,rm as ka,writeFile as Sa}from"fs/promises";import{tmpdir as xa}from"os";import{join as Xr}from"path";ni();var va=64*1024,$a=2,ht=0;function nd(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function rd(t,e,n,i){return t.method!=="POST"?y(e,405,{error:"POST"}):n==="/voice/transcribe"?Aa(t,e,i):Ia(t,e,i)}async function Aa(t,e,n){let i=String(t.headers["content-type"]||""),r=Ur(i);if(!r)return y(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=Vr(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),y(e,s.status,{error:s.error});let a=await Gr(t,P.bytes);if(!a)return y(e,413,{error:Ca()});if(!a.length)return y(e,400,{error:"The recording is empty."});if(ht>=$a)return y(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let o=n.stt(),l=n.host(),c=Br(o,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",p=c.length?"":" "+mt(o,l);return y(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 y(e,503,{error:"Voice input isn't set up on this computer.",hint:mt(o,l),setup:!1});ht++;let u;try{let d=await wa(Xr(xa(),"agentx-phone-voice-"));try{u=await _a(d,`speech.${r}`,a,i,l,c,n)}finally{await ka(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{ht--}y(e,u[0],u[1])}async function _a(t,e,n,i,r,s,a){let o=Xr(t,e);if(await Sa(o,n,{mode:384}),r.ffmpeg){let c=await(a.measure??qr)(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:gt()}]}let l=[];for(let c of s)try{let u=await Ra(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 Ra(t,e,n,i,r,s){let a=s.engines?.[t];if(a)return a(e,n,i,r);if(t==="elevenlabs")return Hr(e,n,i.key);let o=t==="mlx-whisper"?i.mlx:i.whisper;return zr(t,o,e,i.ffmpeg,r)}async function Ia(t,e,n){let i=await Gr(t,va);if(!i)return y(e,413,{error:"request too large"});let r;try{r=JSON.parse(i.toString("utf8")||"{}")}catch{return y(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 y(e,400,{error:"agent is required"});let o=Ea(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!o)return y(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 y(e,404,{error:`Unknown agent: ${s}`});let u=(p,f=200)=>y(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??Ta)(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 Ea(t,e){let n=dr(Ot(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return At(n,e)}async function Ta(t,e,n){let i=me(e.rate),r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(e.elevenlabs)}?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n,model_id:"eleven_flash_v2_5",...i?{voice_settings:{speed:i}}:{}}),signal:AbortSignal.timeout(6e4)});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text().catch(()=>"")).slice(0,160)}`);return Buffer.from(await r.arrayBuffer())}var Ca=()=>`The recording is larger than ${P.bytes/1024/1024} MB, more than ${P.ms/6e4} minutes of speech.`;function id(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?ze(Be(t,r,n.voice)):null}function Gr(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 y(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as $,readFileSync as kt,writeFileSync as St,mkdirSync as he,readdirSync as wt,rmSync as Da,statSync as R}from"fs";import{resolve as Kr,relative as Pa,dirname as xt,join as L,extname as Z,basename as vt}from"path";var S=200*1024,Jr=new Set([".md",".markdown",".txt"]),U=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),Na=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=Kr(t);if($(n)||he(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let i=Kr(n,e);if(Pa(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Yr(t){let e=Z(t).toLowerCase();if(!Jr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function bt(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function ld(t){let e=T(t,"."),n=[],i=new Set,r=[];try{r=wt(e)}catch{}for(let o of La){let l=L(e,o);if($(l)&&R(l).isFile()){let c=R(l).size,u=c>0&&c<S?yt(l):"";n.push({path:o,title:bt(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=L(e,o);try{let c=R(l);if(!c.isFile()||!Jr.has(Z(o).toLowerCase()))continue;let u=c.size>0&&c.size<S?yt(l):"";n.push({path:o,title:bt(u,o),size:c.size,exists:!0})}catch{}}let s=[],a=L(e,".claude","skills");if($(a))try{for(let o of wt(a)){let l=L(a,o),c;try{c=R(l)}catch{continue}if(!c.isDirectory())continue;let u=L(l,"SKILL.md");if(!$(u))continue;let d=R(u),p=d.size<S?yt(u):"";s.push({slug:o,title:bt(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 yt(t){try{return kt(t,"utf-8")}catch{return""}}function cd(t,e){let n=T(t,e);if(Yr(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:kt(n,"utf-8")}}function ud(t,e,n){let i=T(t,e);Yr(i);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return he(xt(i),{recursive:!0}),St(i,r),{path:e,bytes:r.length}}function dd(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.`);he(xt(r),{recursive:!0});let s=n.content?.trim()?n.content:Oa(e,n.title);return St(r,s),{slug:e,path:i}}function pd(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 Da(n,{recursive:!0,force:!0}),{slug:e}}function fd(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>Na)return;let c=[];try{c=wt(s)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=L(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=Z(u).toLowerCase(),h=U.has(g)||U.has(u.toLowerCase());l.push({path:p,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function gd(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=Z(i).toLowerCase(),s=vt(i).toLowerCase();if(!U.has(r)&&!U.has(s))throw new Error(`File type not editable: ${n}`);if(R(i).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:kt(i,"utf-8")}}function md(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=Z(r).toLowerCase(),a=vt(r).toLowerCase();if(!U.has(s)&&!U.has(a))throw new Error(`File type not editable: ${n}`);let o=Buffer.from(i,"utf-8");if(o.length>S)throw new Error(`File too large (${o.length} > ${S} bytes).`);return he(xt(r),{recursive:!0}),St(r,o),{path:n,bytes:o.length}}function hd(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=>$(L(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 Oa(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 ${vt(t)} --arg value
531
- \`\`\`
532
- `}Dt();var Zr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Qr(t){return{...Zr,...t??{},regions:{...t?.regions??{}},buffer:{...Zr.buffer,...t?.buffer??{}}}}function wd(t){try{return Qr(Ct(t).screen)}catch{return Qr(void 0)}}var Ma=/^[a-z][\w-]*$/,ei=["window","screen","menubar","notifications"];function Q(t,e,n,i){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${i}`);return r}var be=(t,e)=>Q(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function ti(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 kd(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=be(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=be(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=be(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Q(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Q(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,a]of Object.entries(e.regions)){if(!Ma.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);a===null?delete r[s]:r[s]=ti(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=Q(r.seconds,"buffer.seconds",a=>a>0&&a<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Q(r.fps,"buffer.fps",a=>a>0&&a<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=be(r.maxPixels,"buffer.maxPixels")),"region"in r&&(s.region=String(r.region).trim()),n.buffer=s}let i=n.buffer?.region;if(i!==void 0&&!ei.includes(i)&&!n.regions?.[i])try{ti(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...ei,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{sn as a,Wa as b,rt as c,to as d,no as e,Rc as f,Ic as g,Ec as h,dr as i,Cc as j,Pc as k,D as l,pr as m,k as n,qa as o,mr as p,Fc as q,Qa as r,Di as s,sl as t,xn as u,x as v,Ka as w,Ja as x,ll as y,oe as z,cl as A,An as B,ml as C,X as D,Cl as E,Dl as F,Cn as G,hr as H,Uc as I,Er as J,yu as K,wu as L,Au as M,ea as N,_u as O,Nl as P,Ll as Q,Ol as R,Ml as S,jl as T,Fl as U,Vl as V,Ul as W,Yl as X,Fe as Y,Zl as Z,Ql as _,G as $,K as aa,oa as ba,Lu as ca,Ou as da,Mu as ea,ju as fa,dt as ga,Fu as ha,Ue as ia,Be as ja,pe as ka,Ss as la,vs as ma,ic as na,He as oa,ze as pa,$s as qa,As as ra,Yn as sa,tr as ta,sc as ua,Is as va,oc as wa,Os as xa,Fs as ya,Xe as za,Vs as Aa,nr as Ba,P as Ca,Vr as Da,Ur as Ea,Br as Fa,Hu as Ga,ma as Ha,Hr as Ia,zr as Ja,nd as Ka,rd as La,Ca as Ma,id as Na,Gr as Oa,fe as Pa,yc as Qa,lr as Ra,Ge as Sa,tt as Ta,Ac as Ua,ld as Va,cd as Wa,ud as Xa,dd as Ya,pd as Za,fd as _a,gd as $a,md as ab,hd as bb,Zr as cb,Qr as db,wd as eb,ei as fb,kd as gb};
533
- //# sourceMappingURL=chunk-HSCZSNOX.js.map