agentix-cli 0.79.4 → 0.80.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 (128) hide show
  1. package/dist/{App-PFMTQ7J5.js → App-2UCGXCX3.js} +2 -2
  2. package/dist/{ChatApp-ZBSU2F6J.js → ChatApp-IRPSBYC7.js} +2 -2
  3. package/dist/{agent-AMU6E27Z.js → agent-UPTK3HFR.js} +2 -2
  4. package/dist/{board-dashboard-OJSOA4OL.js → board-dashboard-GAUAYKWV.js} +337 -215
  5. package/dist/board-dashboard-GAUAYKWV.js.map +1 -0
  6. package/dist/{chunk-7QRCAHPX.js → chunk-2YJ2ZIYC.js} +2 -2
  7. package/dist/{chunk-T7GFKM63.js → chunk-36TJTWG3.js} +193 -197
  8. package/dist/chunk-36TJTWG3.js.map +1 -0
  9. package/dist/{chunk-EAYHYAF3.js → chunk-3GYCFRBK.js} +2 -2
  10. package/dist/chunk-445P5QPS.js +15 -0
  11. package/dist/{chunk-YKPISR5J.js.map → chunk-445P5QPS.js.map} +1 -1
  12. package/dist/{chunk-MGCTX2BB.js → chunk-4NUF3SXN.js} +2 -2
  13. package/dist/chunk-6TLQ4I32.js +57 -0
  14. package/dist/chunk-6TLQ4I32.js.map +1 -0
  15. package/dist/{chunk-XFCSJUGY.js → chunk-7EIUNFDF.js} +2 -2
  16. package/dist/{chunk-HTKSZZXK.js → chunk-AFSM3IY3.js} +2 -2
  17. package/dist/{chunk-M4XUZA3O.js → chunk-AIHWGU4P.js} +2 -2
  18. package/dist/{chunk-RD5EKHGZ.js → chunk-BBI3HG77.js} +2 -2
  19. package/dist/{chunk-WVYOXM45.js → chunk-BIJB7CNG.js} +2 -2
  20. package/dist/{chunk-R7WZUUYO.js → chunk-D3FDPA74.js} +2 -2
  21. package/dist/{chunk-ROIPXJ6L.js → chunk-ECEDX6C6.js} +191 -190
  22. package/dist/chunk-ECEDX6C6.js.map +1 -0
  23. package/dist/chunk-GTJIKXDB.js +2 -0
  24. package/dist/chunk-GTJIKXDB.js.map +1 -0
  25. package/dist/{chunk-EUVMKZUC.js → chunk-I2Z6D3MI.js} +2 -2
  26. package/dist/{chunk-LNQOJC57.js → chunk-KAFUQILA.js} +2 -2
  27. package/dist/{chunk-X6WZ54UJ.js → chunk-KBSBMOOL.js} +79 -79
  28. package/dist/chunk-KBSBMOOL.js.map +1 -0
  29. package/dist/chunk-NMFXY3QU.js +2 -0
  30. package/dist/chunk-NMFXY3QU.js.map +1 -0
  31. package/dist/{chunk-CNSPC4BZ.js → chunk-O67KV3DX.js} +2 -2
  32. package/dist/chunk-OVN5LVJY.js +11 -0
  33. package/dist/chunk-OVN5LVJY.js.map +1 -0
  34. package/dist/{chunk-WNI2P7S6.js → chunk-PHFOYJUB.js} +2 -2
  35. package/dist/{chunk-LPDQ2KK4.js → chunk-PT5Z5WW4.js} +2 -2
  36. package/dist/{chunk-6SJTBTDG.js → chunk-PXIGWFIQ.js} +2 -2
  37. package/dist/chunk-SHEUCITK.js +2 -0
  38. package/dist/chunk-SHEUCITK.js.map +1 -0
  39. package/dist/{chunk-2ZQ42Q4L.js → chunk-Z522XZBL.js} +2 -2
  40. package/dist/{chunk-5RRORS5S.js → chunk-Z6G26FWC.js} +57 -57
  41. package/dist/chunk-Z6G26FWC.js.map +1 -0
  42. package/dist/cli.js +1 -1
  43. package/dist/cli.js.map +1 -1
  44. package/dist/client-ABDGDO7S.js +2 -0
  45. package/dist/config-XPFCUOQT.js +2 -0
  46. package/dist/config-mutator-WYHQV2XF.js +2 -0
  47. package/dist/{doctor-DST4SVW4.js → doctor-XLLNQRRT.js} +2 -2
  48. package/dist/{facts-2K6UX5GD.js → facts-YY2364CP.js} +2 -2
  49. package/dist/{facts-2K6UX5GD.js.map → facts-YY2364CP.js.map} +1 -1
  50. package/dist/index.d.ts +74 -12
  51. package/dist/index.js +1 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/program-KZOBDSXQ.js +2 -0
  54. package/dist/{promote-CQCRZCYB.js → promote-YUZL3ZU2.js} +2 -2
  55. package/dist/query-3XH7I6WX.js +2 -0
  56. package/dist/registry-5OD2IN5G.js +2 -0
  57. package/dist/{request-planner-TNDIQMHS.js → request-planner-RNXA2QAH.js} +2 -2
  58. package/dist/{review-candidates-SXVIYCVE.js → review-candidates-THKWXS7S.js} +2 -2
  59. package/dist/routing-X45VX723.js +2 -0
  60. package/dist/schedule-tool-ZTL6UZCC.js +2 -0
  61. package/dist/scheduler-VH7IJ4VA.js +2 -0
  62. package/dist/seat-LQ47SSNN.js +2 -0
  63. package/dist/{select-WKMMUWLU.js → select-PRQP2B6G.js} +2 -2
  64. package/dist/{set-enabled-RIE3PLNJ.js → set-enabled-E2ML2E33.js} +2 -2
  65. package/dist/tool-4WPUUUE4.js +4 -0
  66. package/dist/tool-4WPUUUE4.js.map +1 -0
  67. package/dist/{tool-TAMRBONN.js → tool-67JK7SK6.js} +2 -2
  68. package/dist/tool-67JK7SK6.js.map +1 -0
  69. package/dist/wiki-AS5YHSR7.js +2 -0
  70. package/package.json +1 -1
  71. package/dist/board-dashboard-OJSOA4OL.js.map +0 -1
  72. package/dist/chunk-2ACZWM7F.js +0 -22
  73. package/dist/chunk-2ACZWM7F.js.map +0 -1
  74. package/dist/chunk-5RRORS5S.js.map +0 -1
  75. package/dist/chunk-7XB2CVC3.js +0 -2
  76. package/dist/chunk-7XB2CVC3.js.map +0 -1
  77. package/dist/chunk-ROIPXJ6L.js.map +0 -1
  78. package/dist/chunk-T7GFKM63.js.map +0 -1
  79. package/dist/chunk-X6WZ54UJ.js.map +0 -1
  80. package/dist/chunk-YKPISR5J.js +0 -15
  81. package/dist/client-XAE7NLE2.js +0 -2
  82. package/dist/config-5HAWFIEL.js +0 -2
  83. package/dist/config-mutator-Y7KAC4AC.js +0 -2
  84. package/dist/program-SSCPEHTW.js +0 -2
  85. package/dist/query-WSLKGCQN.js +0 -2
  86. package/dist/registry-6HKQKIBD.js +0 -2
  87. package/dist/routing-GQWG65DQ.js +0 -2
  88. package/dist/schedule-tool-WXRMJMW6.js +0 -2
  89. package/dist/scheduler-YW6JFH3Z.js +0 -2
  90. package/dist/seat-K2JSQIZ4.js +0 -2
  91. package/dist/tool-TAMRBONN.js.map +0 -1
  92. package/dist/wiki-WBRXHY7J.js +0 -2
  93. /package/dist/{App-PFMTQ7J5.js.map → App-2UCGXCX3.js.map} +0 -0
  94. /package/dist/{ChatApp-ZBSU2F6J.js.map → ChatApp-IRPSBYC7.js.map} +0 -0
  95. /package/dist/{agent-AMU6E27Z.js.map → agent-UPTK3HFR.js.map} +0 -0
  96. /package/dist/{chunk-7QRCAHPX.js.map → chunk-2YJ2ZIYC.js.map} +0 -0
  97. /package/dist/{chunk-EAYHYAF3.js.map → chunk-3GYCFRBK.js.map} +0 -0
  98. /package/dist/{chunk-MGCTX2BB.js.map → chunk-4NUF3SXN.js.map} +0 -0
  99. /package/dist/{chunk-XFCSJUGY.js.map → chunk-7EIUNFDF.js.map} +0 -0
  100. /package/dist/{chunk-HTKSZZXK.js.map → chunk-AFSM3IY3.js.map} +0 -0
  101. /package/dist/{chunk-M4XUZA3O.js.map → chunk-AIHWGU4P.js.map} +0 -0
  102. /package/dist/{chunk-RD5EKHGZ.js.map → chunk-BBI3HG77.js.map} +0 -0
  103. /package/dist/{chunk-WVYOXM45.js.map → chunk-BIJB7CNG.js.map} +0 -0
  104. /package/dist/{chunk-R7WZUUYO.js.map → chunk-D3FDPA74.js.map} +0 -0
  105. /package/dist/{chunk-EUVMKZUC.js.map → chunk-I2Z6D3MI.js.map} +0 -0
  106. /package/dist/{chunk-LNQOJC57.js.map → chunk-KAFUQILA.js.map} +0 -0
  107. /package/dist/{chunk-CNSPC4BZ.js.map → chunk-O67KV3DX.js.map} +0 -0
  108. /package/dist/{chunk-WNI2P7S6.js.map → chunk-PHFOYJUB.js.map} +0 -0
  109. /package/dist/{chunk-LPDQ2KK4.js.map → chunk-PT5Z5WW4.js.map} +0 -0
  110. /package/dist/{chunk-6SJTBTDG.js.map → chunk-PXIGWFIQ.js.map} +0 -0
  111. /package/dist/{chunk-2ZQ42Q4L.js.map → chunk-Z522XZBL.js.map} +0 -0
  112. /package/dist/{client-XAE7NLE2.js.map → client-ABDGDO7S.js.map} +0 -0
  113. /package/dist/{config-5HAWFIEL.js.map → config-XPFCUOQT.js.map} +0 -0
  114. /package/dist/{config-mutator-Y7KAC4AC.js.map → config-mutator-WYHQV2XF.js.map} +0 -0
  115. /package/dist/{doctor-DST4SVW4.js.map → doctor-XLLNQRRT.js.map} +0 -0
  116. /package/dist/{program-SSCPEHTW.js.map → program-KZOBDSXQ.js.map} +0 -0
  117. /package/dist/{promote-CQCRZCYB.js.map → promote-YUZL3ZU2.js.map} +0 -0
  118. /package/dist/{query-WSLKGCQN.js.map → query-3XH7I6WX.js.map} +0 -0
  119. /package/dist/{registry-6HKQKIBD.js.map → registry-5OD2IN5G.js.map} +0 -0
  120. /package/dist/{request-planner-TNDIQMHS.js.map → request-planner-RNXA2QAH.js.map} +0 -0
  121. /package/dist/{review-candidates-SXVIYCVE.js.map → review-candidates-THKWXS7S.js.map} +0 -0
  122. /package/dist/{routing-GQWG65DQ.js.map → routing-X45VX723.js.map} +0 -0
  123. /package/dist/{schedule-tool-WXRMJMW6.js.map → schedule-tool-ZTL6UZCC.js.map} +0 -0
  124. /package/dist/{scheduler-YW6JFH3Z.js.map → scheduler-VH7IJ4VA.js.map} +0 -0
  125. /package/dist/{seat-K2JSQIZ4.js.map → seat-LQ47SSNN.js.map} +0 -0
  126. /package/dist/{select-WKMMUWLU.js.map → select-PRQP2B6G.js.map} +0 -0
  127. /package/dist/{set-enabled-RIE3PLNJ.js.map → set-enabled-E2ML2E33.js.map} +0 -0
  128. /package/dist/{wiki-WBRXHY7J.js.map → wiki-AS5YHSR7.js.map} +0 -0
@@ -1,11 +1,11 @@
1
- import{q as Ot}from"./chunk-S2GAEH2F.js";import{a as Se}from"./chunk-7XB2CVC3.js";import{a as x}from"./chunk-CL53UVOF.js";import{t as Lt,u as Pt}from"./chunk-2ZQ42Q4L.js";import{d as Et,e as Tt}from"./chunk-AQASR6KR.js";import{b as we,u as wt,w as ne,x as xe,z as ke}from"./chunk-2ACZWM7F.js";import{a as At,b as It,c as Rt,d as _t,e as Ct,f as Dt}from"./chunk-Y4CYQV7G.js";import{g as xt,h as kt,i as St,k as vt,l as $t}from"./chunk-WVYOXM45.js";import{q as bt}from"./chunk-6SJTBTDG.js";import{E as yt,H as Wr,r as te,s as mt,t as ht,u as Fr}from"./chunk-YKPISR5J.js";import{existsSync as Ur,readdirSync as Br,readFileSync as zr,statSync as Hr}from"fs";import{resolve as Kr}from"path";function Nt(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let o of e){let a=s.get(o.workflowId);a?a.push(o):s.set(o.workflowId,[o])}return t.map(o=>{let a=s.get(o.id)??[],c=a.filter(g=>n-g.at<=r),l=a.filter(g=>n-g.at>r&&n-g.at<=r*2),d=c.filter(g=>g.status==="failed").length,u=a.filter(g=>g.status==="paused").length,p=a.length?Math.max(...a.map(g=>g.at)):null,f=a.length?l.length>0&&c.length===0?"dormant":c.length>0&&d*2>=c.length?"failing":c.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:p,recent:c.length,prior:l.length,failed:d,paused:u}}).sort((o,a)=>{let c={dormant:0,failing:1,active:2,quiet:3,never:4};return c[o.state]-c[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var re=new Map;function _a(t,e=1e3){if(!Ur(t))return[];let n=Br(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=Kr(t,s);return{path:o,mtime:Hr(o).mtimeMs}}).sort((s,o)=>o.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of re.keys())i.has(s)||re.delete(s);let r=[];for(let{path:s,mtime:o}of n){let a=re.get(s);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let c=Gr(s,o);re.set(s,{mtime:o,summary:c}),c&&r.push(c)}return r}function Gr(t,e){try{let n=zr(t,"utf-8").split(`
2
- `).filter(Boolean);if(!n.length)return null;let i=JSON.parse(n[0]),r=i.run?.workflowId;if(!r)return null;let s=i.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),c=a.status??a.run?.status;if(c){s=c;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var qr={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},Xr=(t,e,n)=>{try{return bt(t,e,n)}catch{return null}},Mt=864e5;function Ta(t){let e=t.now??Date.now(),n={...qr,...t.thresholds},i=t.nextFire??Xr,r=[];for(let a of t.crons){let c=t.cronRuns.get(a.id)??[],l=a.timezone||"UTC",d=c.map(f=>({at:Date.parse(f.startedAt),status:f.status})),u=c[0],p={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:A(a.id,k.text),trigger:{schedule:A(a.schedule,k.text),timezone:l},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?ve(a.nextRun)??ve(i(a.schedule,new Date(e),l)):null,lastRun:u?{at:u.startedAt,status:u.status,summary:ti(u.status==="success"?void 0:u.errorSummary,k.summary)}:null,lastSuccessAt:c.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:jt(d),sampledRuns:c.length,flags:[],attention:null};p.flags=Vt(p,d,a.schedule,l,null,e,n,i),r.push(Ft(p))}let s=new Map(Nt(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let c=o.get(a.workflowId);c?c.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let c=a.nodes.find(_=>_.type.startsWith("trigger."));if(!c||c.type!=="trigger.cron"&&c.type!=="trigger.hook")continue;let l=c.config??{},d=a.state||"active",u=d==="active",p=(o.get(a.id)??[]).slice().sort((_,be)=>be.at-_.at),f=p.map(_=>({at:_.at,status:Zr(_.status)})),g=f[0],h=c.type==="trigger.cron",y=typeof l.spec=="string"?l.spec:"",T=typeof l.timezone=="string"?l.timezone:"UTC",V={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:A(a.title||a.id,k.text),trigger:h?{schedule:A(y,k.text),timezone:T}:{event:A(typeof l.event=="string"?l.event:"",k.text),filters:ei(l.filter,a)},agent:Qr(a),enabled:u,state:d,nextRunAt:h&&u&&y?ve(i(y,new Date(e),T)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let _=f.find(be=>be.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:jt(f),sampledRuns:p.length,flags:[],attention:null},ee=Date.parse(a.updated||a.created||"");V.flags=h?Vt(V,f,y,T,Number.isFinite(ee)?ee:null,e,n,i):Jr(V,s.get(a.id)?.state==="dormant",Number.isFinite(ee)?ee:null,e,n),r.push(Ft(V))}return r.sort(Yr).slice(0,k.routines)}function jt(t){let e=0;for(let n of t)if(!(n.status==="running"||n.status==="paused"||n.status==="unknown"))if(n.status==="failed"||n.status==="timeout")e++;else break;return e}function Vt(t,e,n,i,r,s,o,a){let c=[],l=e.length?e[0].at:null;if(!t.enabled){let p=Ut(l,r,s,o);return p&&c.push(p),c}if(t.consecutiveFailures>=o.failStreak&&c.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),l===null)return c.push({reason:"never-ran",detail:"No persisted attempt"}),c;let d=new Date(l),u=null;for(let p=0;p<o.missedFires&&(u=a(n,d,i),!!u);p++)d=u;return u&&s>u.getTime()+o.graceMs&&c.push({reason:"overdue",detail:`No attempt since ${new Date(l).toISOString()}; ${o.missedFires} scheduled fires missed`}),c}function Jr(t,e,n,i,r){let s=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=Ut(o,n,i,r);return a&&s.push(a),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),o===null?s.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&s.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),s}function Ut(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*Mt?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/Mt)} days`:"Disabled and never ran"}}function Ft(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 Wt={critical:0,warning:1,info:2};function Yr(t,e){let n=t.attention?Wt[t.attention]:3,i=e.attention?Wt[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function Zr(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 Qr(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 ei(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 o=Array.isArray(s)?s.map(String):s==null?[]:[String(s)];o.length&&n.push(A(`${r}=${o.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function ve(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function A(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function ti(t,e){return t===void 0?void 0:A(t,e)}import{createHash as ni,randomBytes as Bt}from"crypto";import{existsSync as ri,mkdirSync as ii,readFileSync as si,writeFileSync as oi}from"fs";import{resolve as ai,dirname as ci}from"path";var $e="agx_live_",li=".agentx/tokens.json",zt=class{file;constructor(e=process.cwd(),n=li){this.file=ai(e,n)}load(){if(!ri(this.file))return[];try{return JSON.parse(si(this.file,"utf-8"))}catch{return[]}}save(e){ii(ci(this.file),{recursive:!0}),oi(this.file,JSON.stringify(e,null,2)+`
3
- `,"utf-8")}create(e){if(!e.name?.trim())throw new Error("Token name is required.");if(!Array.isArray(e.scopes)||e.scopes.length===0)throw new Error("At least one scope is required.");for(let o of e.scopes)if(!di(o))throw new Error(`Invalid scope: ${o}`);let n=Bt(32).toString("hex"),i=$e+n,r={id:"tok_"+Bt(4).toString("hex"),name:e.name.trim(),prefix:$e+n.slice(0,4),hash:Ht(i),scopes:[...e.scopes],createdAt:new Date().toISOString(),expiresAt:e.expiresInDays?new Date(Date.now()+e.expiresInDays*86400*1e3).toISOString():void 0},s=this.load();return s.push(r),this.save(s),{token:i,record:r}}list(){return this.load()}revoke(e){let n=this.load(),i=n.find(r=>r.id===e);return i?(i.revokedAt=new Date().toISOString(),this.save(n),i):null}isActive(e){let n=this.load().find(i=>i.id===e);return!!n&&!n.revokedAt&&!(n.expiresAt&&Date.parse(n.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith($e))return null;let n=Ht(e),i=this.load(),r=i.find(a=>a.hash===n);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let s=Date.now(),o=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(s-o>6e4){r.lastUsedAt=new Date(s).toISOString();try{this.save(i)}catch{}}return r}};function Ma(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function di(t){return t==="dashboard:read"||t==="dashboard:write"||t==="agent:*"||/^agent:[a-z0-9][a-z0-9_-]*$/.test(t)||t==="mesh:peer"||t==="app"}function Ht(t){return"sha256:"+ni("sha256").update(t).digest("hex")}function ja(t){let e=t.headers.authorization,n=Array.isArray(e)?e[0]:e;if(n&&n.toLowerCase().startsWith("bearer "))return n.slice(7).trim();if(t.url)try{let r=new URL(t.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}import{existsSync as Ie,readdirSync as Mi,readFileSync as ji}from"fs";import{resolve as W}from"path";import{randomBytes as qt}from"crypto";import{existsSync as pi,mkdirSync as fi,readdirSync as gi,readFileSync as mi,renameSync as Xt,unlinkSync as hi,writeFileSync as yi}from"fs";import{resolve as Jt}from"path";function Kt(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var ui=t=>t.trim().split(`
4
- `).pop()?.slice(0,300)||"no output";async function Gt(t,e,n,i=Se){let r=await i(t.bin,[...Kt(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${ui(r.stderr||r.stdout)}`}}async function Wa(t,e,n,i,r=Se){return(await r(t.bin,[...Kt(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var bi=2e3,wi=t=>Gt(t.wacli,t.to,t.text);function Ae(t){return Jt(t,".agentx","whatsapp-triage","drafts")}var xi=t=>/^[a-z0-9-]{8,64}$/.test(t),ie=(t,e)=>Jt(Ae(t),`${e}.json`);function Yt(t,e){fi(Ae(t),{recursive:!0});let n=ie(t,e.id),i=`${n}.${process.pid}.tmp`;yi(i,JSON.stringify(e,null,2)+`
5
- `,{mode:384}),Xt(i,n)}function Ga(t,e,n=Date.now()){let i=e.text.trim().slice(0,bi);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${qt(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return Yt(t,r),r}function se(t,e){if(!xi(e))return null;try{return JSON.parse(mi(ie(t,e),"utf-8"))}catch{return null}}function Zt(t,e){let n=Ae(t);return pi(n)?gi(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 Qt(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}.${qt(3).toString("hex")}.claim`;try{Xt(ie(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(i.send??wi)(r).catch(c=>({ok:!1,error:String(c?.message??c)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}Yt(t,o);try{hi(s)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{existsSync as ki,mkdirSync as Si,readdirSync as vi,readFileSync as $i,renameSync as Ai,writeFileSync as Ii}from"fs";import{resolve as nn}from"path";function en(t,e){let n=t.list?` in the "${t.list}" list`:"",i=[`This card came from the operator's reminder "${t.title}"${n} (id ${t.id}).`];return i.push(e?`Do what the operator chose, then tick the reminder off: remindctl complete ${t.id}`:"Leave the reminder open; it will come back at a later check-in."),i}var tn=["discard","keep","pause","approve"],I={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Ri={defaultExpiryDays:3,maxExpiryDays:30};function F(t){return nn(t,".agentx","approvals")}var _i=/^[a-z0-9][a-z0-9-]{0,80}$/;function rn(t){return _i.test(t)}function sn(t,e){if(!rn(e))throw new Error(`invalid card id: ${e}`);return nn(F(t),`${e}.json`)}function Ci(t,e){let n=new Date(t).toISOString().slice(0,10),i=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${n}-${i||"card"}-${Math.random().toString(36).slice(2,6)}`}function oe(t,e){Si(F(t),{recursive:!0});let n=sn(t,e.id),i=`${n}.${process.pid}.tmp`;Ii(i,JSON.stringify(e,null,2)+`
6
- `),Ai(i,n)}function L(t,e){if(!rn(e))return null;try{return JSON.parse($i(sn(t,e),"utf-8"))}catch{return null}}function P(t,e){let n=F(t);if(!ki(n))return[];let i=[];for(let r of vi(n).filter(s=>s.endsWith(".json")&&!s.startsWith("_")).sort()){let s=L(t,r.slice(0,-5));s&&(!e||s.status===e)&&i.push(s)}return i}function w(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function Di(t,e,n){let i=e+n.maxExpiryDays*864e5,r,s=w(t);if(!s)r=e+n.defaultExpiryDays*864e5;else{let o=/^(\d+)\s*([hd])$/i.exec(s);if(o)r=e+Number(o[1])*(o[2].toLowerCase()==="d"?864e5:36e5);else if(r=Date.parse(s),Number.isNaN(r))return{ok:!1,error:`expires must be an ISO date or time, or like "12h" / "3d" (got "${s}")`}}return r<=e?{ok:!1,error:"expires must be in the future"}:{ok:!0,at:new Date(Math.min(r,i)).toISOString()}}function Ei(t,e={}){let n=e.now??Date.now(),i=e.settings??Ri,r=w(t.title),s=w(t.ask),o=w(t.recommend),a=w(t.raised_by);if(!r)return{ok:!1,error:"title is required"};if(!s)return{ok:!1,error:"ask is required: the yes/no question"};if(!o)return{ok:!1,error:"recommend is required: your advice and why, in one line"};if(!a)return{ok:!1,error:"raised_by is required: the agent id"};if(r.length>I.title)return{ok:!1,error:`title is longer than ${I.title} characters`};if(s.length>I.ask)return{ok:!1,error:`ask is longer than ${I.ask} characters`};if(o.length>I.recommend)return{ok:!1,error:`recommend is longer than ${I.recommend} characters`};let c=w(t.if_silent).toLowerCase();if(!tn.includes(c))return{ok:!1,error:`if_silent must be one of ${tn.join(", ")}`};let l=Di(t.expires,n,i);if(!l.ok)return l;let d=w(t.source);if(d.length>I.source)return{ok:!1,error:`source is longer than ${I.source} characters`};if(d&&/^[a-z][a-z0-9+.-]*:/i.test(d)&&!/^https?:\/\//i.test(d))return{ok:!1,error:"source must be an http(s) link or a plain reference"};let u=Rt(t);if(!u.ok)return u;let p,f=t.reply;return f&&typeof f=="object"&&w(f.channel)&&w(f.chatId)&&(p={channel:w(f.channel),chatId:w(f.chatId),...w(f.accountId)?{accountId:w(f.accountId)}:{}}),{ok:!0,card:{id:Ci(n,r),title:r,ask:s,recommend:o,if_silent:c,expires:l.at,...d?{source:d}:{},raised_by:a,created_at:new Date(n).toISOString(),...p?{reply:p}:{},...u.value,...e.origin?{origin:e.origin}:{},status:"pending"}}}function ec(t,e,n={}){let i=Ei(e,n);if(!i.ok)return i;let r=P(t,"pending").filter(s=>s.raised_by===i.card.raised_by).length;return r>=I.pendingPerAgent?{ok:!1,error:`${i.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(oe(t,i.card),i)}function on(t,e,n,i={}){let r=L(t,e);if(!r)return{ok:!1,error:`no card "${e}"`};if(r.status!=="pending")return{ok:!1,error:`card "${e}" is already ${r.status}`};let s=Ct(r,n,i);if(!s.ok)return s;let o=w(i.note).slice(0,I.note),a={...r,status:"decided",verdict:n,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString(),...o?{note:o}:{},...s.choice?{choice:s.choice}:{},...s.text?{text:s.text}:{}};return oe(t,a),{ok:!0,card:a}}function tc(t,e=Date.now()){let n=[];for(let i of P(t,"pending")){if(Date.parse(i.expires)>e)continue;let r={...i,status:"expired",outcome:i.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};oe(t,r),n.push(r)}return n}function nc(t){return P(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function rc(t,e,n=Date.now()){let i=L(t,e);!i||i.agent_notified_at||oe(t,{...i,agent_notified_at:new Date(n).toISOString()})}function ic(t){let e=t.status==="decided"?t.verdict==="yes"?"The operator said YES.":"The operator said NO.":`Nobody answered before it expired, so the default applied: ${t.outcome??t.if_silent}.`,n=[`[Approval result] Your decision card "${t.title}" (${t.id}) is closed.`,`Question: ${t.ask}`,e];return t.status==="decided"&&t.verdict==="yes"&&n.push(...Dt(t)),t.note&&n.push(`Operator note: ${t.note}`),t.source&&n.push(`Source: ${t.source}`),t.origin&&n.push(...en(t.origin,t.status==="decided"&&t.verdict==="yes")),t.reply&&n.push(`You raised it from ${t.reply.channel} chat ${t.reply.chatId}; reply there if the requester should know.`),n.push("Act on this result now. Do not raise the same card again."),n.join(`
7
- `)}import{mkdirSync as Ti,readFileSync as Li,renameSync as Pi,writeFileSync as Oi}from"fs";import{resolve as Ni}from"path";function an(t){return Ni(F(t),"_state.json")}function C(t){try{let e=JSON.parse(Li(an(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{},...e?.popped&&typeof e.popped=="object"?{popped:e.popped}:{},...typeof e?.passAt=="string"?{passAt:e.passAt}:{},...Array.isArray(e?.wanted)?{wanted:e.wanted.filter(n=>typeof n=="string")}:{}}}catch{return{snoozed:{}}}}function K(t,e){Ti(F(t),{recursive:!0});let n=an(t),i=`${n}.${process.pid}.tmp`;Oi(i,JSON.stringify(e,null,2)+`
8
- `),Pi(i,n)}function cn(t,e,n,i=Date.now()){let r=C(t),s={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>i&&(s[o]=a);s[e]=n.toISOString(),K(t,{...r,snoozed:s})}function lc(t,e){K(t,{...C(t),lastDigest:e})}function ln(t,e,n,i=Date.now()){let r=C(t),s=new Set(n),o={};for(let[c,l]of Object.entries(r.popped??{}))s.has(c)&&(o[c]=l);o[e]=new Date(i).toISOString();let a=(r.wanted??[]).filter(c=>c!==e&&s.has(c));K(t,{...r,popped:o,wanted:a})}function dn(t,e){let n=C(t);K(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function dc(t,e=Date.now()){K(t,{...C(t),popped:{},passAt:new Date(e).toISOString()})}var un=["card","schedule","memory","wiki","whatsapp"],Vi=280;function G(t,e=Vi){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function pn(t){if(t.configPath)return W(t.configPath);let e=[W(t.root,"agentx.json"),W(t.root,".agentx","config.json")];return e.find(n=>Ie(n))??e[0]}function Re(t){return t.wikiDir?W(t.wikiDir):W(t.root,".agentx","wiki")}function Fi(t){return P(t.root,"pending").map(Wi)}function Wi(t){return{key:`card:${t.id}`,kind:"card",title:t.title,ask:t.ask,yes:`tell ${t.raised_by} yes`,no:`tell ${t.raised_by} no`,recommend:t.recommend,if_silent:t.if_silent,expires:t.expires,...t.source?{source:t.source}:{},raised_by:t.raised_by,created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.context||t.draft?{detail:G([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function Ui(t){let e=pn(t);if(!Ie(e))return[];let n;try{n=JSON.parse(ji(e,"utf-8"))}catch{return[]}let i=new Date(t.now??Date.now()),r=[];for(let[s,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let c=o.timezone||"UTC",l=o.schedule?xt(o.schedule):"",d=o.schedule?`${l.charAt(0).toLowerCase()}${l.slice(1)} (${o.schedule})`:"no schedule",u=String(o.prompt??o.command??""),p=a.action==="create";r.push({key:`schedule:${s}`,kind:"schedule",title:p?`New schedule "${s}" for ${o.agent??"an agent"}`:`Delete schedule "${s}"`,ask:p?`Let ${o.agent??"the agent"} run this ${d}?`:`Remove the schedule "${s}" (${d})?`,yes:p?"enable it":"remove it",no:p?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:G(`${u}${p&&o.schedule?` \xB7 first run ${St(kt(o.schedule,c,i),c)}`:""}`),more:"agentx schedule list"})}return r}function fn(t){let e=W(t,".agentx","memory");return Ie(e)?Mi(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function Bi(t){let e=fn(t.root);if(e.length===0)return[];let n=new we(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:G(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 Hi(t){return Tt(Re(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:G(`${zi(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function Ki(t){return Zt(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:G(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}var gn={card:Fi,schedule:Ui,memory:Bi,wiki:Hi,whatsapp:Ki};function Gi(t,e){let n=t.expires?Date.parse(t.expires):1/0,i=e.expires?Date.parse(e.expires):1/0;return n!==i?n-i:(Date.parse(t.created_at)||0)-(Date.parse(e.created_at)||0)}function kc(t,e={}){let n=t.now??Date.now(),{snoozed:i}=C(t.root),r=[],s=[],o=0;for(let a of e.kinds??un){let c;try{c=gn[a](t)}catch(l){s.push({kind:a,error:String(l?.message??l).slice(0,200)});continue}for(let l of c){let d=i[l.key];if(d&&Date.parse(d)>n){if(!e.includeSnoozed){o++;continue}l.snoozed_until=d}r.push(l)}}return r.sort(Gi),{items:r,snoozed:o,errors:s}}function qi(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),i=t.slice(e+1);return!un.includes(n)||!i?null:{kind:n,ref:i}}function Xi(t,e,n){switch(e){case"card":return L(t.root,n)?.status==="pending";case"wiki":return Et(Re(t),n)?.status==="pending";case"whatsapp":return se(t.root,n)?.status==="pending";default:return gn[e](t).some(i=>i.key===`${e}:${n}`)}}async function mn(t,e,n,i={}){let r=qi(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:s,ref:o}=r,a=t.now??Date.now(),c=i.by??"operator";if(n==="later"){if(!Xi(t,s,o))return{ok:!1,error:`nothing waiting for "${e}"`};let d=i.laterHours&&i.laterHours>0?i.laterHours:24,u=new Date(a+d*36e5);return cn(t.root,e,u,a),{ok:!0,message:`${e} put off until ${u.toISOString()}`}}let l=n==="yes";switch(s){case"card":{let d=on(t.root,o,l?"yes":"no",{by:c,note:i.note,now:a,choice:i.choice,text:i.text});return d.ok?{ok:!0,message:`${e}: ${d.card.raised_by} will be told ${l?"yes":"no"}${d.card.choice?` (${d.card.choice})`:""}`}:d}case"schedule":{let d=await(l?vt:$t)(o,{configPath:pn(t),reload:t.reload});return d.success?{ok:!0,message:d.message}:{ok:!1,error:d.message}}case"memory":{let d=o.indexOf("/");if(d<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let u=o.slice(0,d),p=o.slice(d+1);if(!fn(t.root).includes(u))return{ok:!1,error:`no memory for agent "${u}"`};let f=new we(t.root);return f.held(u).some(g=>g.id===p)?(f.review(u,p,l?"approved":"rejected",c),{ok:!0,message:`${e} ${l?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${p}" isn't waiting for review`}}case"wiki":{let d=Re(t),u=l?Lt(d,o,{by:c,force:i.force,now:a}):Pt(d,o,{by:c,reason:i.note,now:a});return u.ok?{ok:!0,message:l?`${u.proposal.article.path} written to the shared wiki`:`${e} rejected`}:u}case"whatsapp":{let d=await Qt(t.root,o,l?"yes":"no",{by:c,now:a,send:t.sendWhatsApp});return d.ok?{ok:!0,message:l?`${e}: sent to ${d.draft.chat_name||d.draft.to}`:`${e}: dropped, nothing sent`}:d}}}var hn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function vc(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/a2a/delegations"||t.startsWith("/a2a/delegations/")||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"||t==="/app-files"||t==="/calls"||t.startsWith("/calls/")||t==="/webrtc/camera"||t.startsWith("/webrtc/camera/")}function $c(t){return t==="/reload"||t==="/api/processes/kill"||t==="/send"||t==="/send/agent"||t==="/send/contact"||t==="/mesh/announce"||t==="/voice/settings"||t==="/voice/preview"||/^\/api\/tasks\/[^/]+\/(cancel|followup)$/.test(t)||/^\/crons\/[^/]+\/enabled$/.test(t)}function Ac(t){return hn.has(t)}function Ic(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(hn.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 Rc(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 _c(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 Ji(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function Yi(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Dc(t,e=Yi()){let n=ae(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=Ji(n),s=[ae(t.host),ae(t["x-forwarded-host"])].filter(Boolean).map(o=>o.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 Ec(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as Wn,mkdirSync as Is,readFileSync as Rs,renameSync as _s,writeFileSync as Cs}from"fs";import{homedir as Ds}from"os";import{dirname as Es,join as Ts}from"path";import{execFile as cs,execFileSync as ls}from"child_process";import{execFileSync as Zi}from"child_process";import{existsSync as bn,mkdirSync as Qi,readdirSync as es,readFileSync as wn,renameSync as ts,writeFileSync as ns}from"fs";import{homedir as xn}from"os";import{join as Ce}from"path";var v="siri:",kn="com.apple.ttsbundle.gryphon-neural_",Sn=t=>!!t&&t.startsWith(kn),rs=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],is=()=>{try{return Zi("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},_e;function De(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&_e!==void 0)return _e;let{platform:n=process.platform,exists:i=bn,prefDomain:r=is}=t,s=n==="darwin"&&rs.every(o=>i(o))&&r();return e||(_e=s),s}var vn=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],$n={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"},Ee=t=>$n[t.toLowerCase()]??null;function ce(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 ss=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function os(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(ss)){let o=`${i}-${r}`,a=`${kn}${s}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:s[0].toUpperCase()+s.slice(1),locale:o,quality:"premium",gender:$n[s]??null,siri:!0})}return[...e.values()]}function le(t=vn,e={}){if(!De(e))return[];let n=[];for(let i of t){let r;try{r=es(i)}catch{continue}for(let s of r)try{n.push(wn(Ce(i,s,"Info.plist"),"latin1"))}catch{}}return os(n)}var yn=`#!/bin/sh
1
+ import{a as $e}from"./chunk-GTJIKXDB.js";import{q as Ht}from"./chunk-S2GAEH2F.js";import{a as k}from"./chunk-CL53UVOF.js";import{t as Bt,u as zt}from"./chunk-Z522XZBL.js";import{d as Ft,e as Ut}from"./chunk-AQASR6KR.js";import{B as ve,b as xe,v as At,w as Rt,y as ne,z as Se}from"./chunk-6TLQ4I32.js";import{a as St}from"./chunk-N6EWZGIX.js";import{a as Ot,b as Nt,c as Mt,d as jt,e as Vt,f as Wt}from"./chunk-Y4CYQV7G.js";import{a as _t,b as Ct}from"./chunk-SHEUCITK.js";import{g as Dt,h as Et,i as Tt,k as Pt,l as Lt}from"./chunk-BIJB7CNG.js";import{q as It}from"./chunk-PXIGWFIQ.js";import{a as vt,b as $t}from"./chunk-AFSM3IY3.js";import{B as ke,E as wt,F as kt,I as xt,r as te,s as yt,t as bt,u as Hr}from"./chunk-445P5QPS.js";import{existsSync as qr,readdirSync as Kr,readFileSync as Gr,statSync as Xr}from"fs";import{resolve as Jr}from"path";function qt(t,e,n=Date.now(),i=7){let r=i*864e5,s=new Map;for(let o of e){let a=s.get(o.workflowId);a?a.push(o):s.set(o.workflowId,[o])}return t.map(o=>{let a=s.get(o.id)??[],c=a.filter(g=>n-g.at<=r),l=a.filter(g=>n-g.at>r&&n-g.at<=r*2),u=c.filter(g=>g.status==="failed").length,d=a.filter(g=>g.status==="paused").length,p=a.length?Math.max(...a.map(g=>g.at)):null,f=a.length?l.length>0&&c.length===0?"dormant":c.length>0&&u*2>=c.length?"failing":c.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:p,recent:c.length,prior:l.length,failed:u,paused:d}}).sort((o,a)=>{let c={dormant:0,failing:1,active:2,quiet:3,never:4};return c[o.state]-c[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var re=new Map;function Pa(t,e=1e3){if(!qr(t))return[];let n=Kr(t).filter(s=>s.endsWith(".jsonl")).map(s=>{let o=Jr(t,s);return{path:o,mtime:Xr(o).mtimeMs}}).sort((s,o)=>o.mtime-s.mtime).slice(0,e),i=new Set(n.map(s=>s.path));for(let s of re.keys())i.has(s)||re.delete(s);let r=[];for(let{path:s,mtime:o}of n){let a=re.get(s);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let c=Yr(s,o);re.set(s,{mtime:o,summary:c}),c&&r.push(c)}return r}function Yr(t,e){try{let n=Gr(t,"utf-8").split(`
2
+ `).filter(Boolean);if(!n.length)return null;let i=JSON.parse(n[0]),r=i.run?.workflowId;if(!r)return null;let s=i.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),c=a.status??a.run?.status;if(c){s=c;break}}return{workflowId:r,status:s,at:e}}catch{return null}}var Zr={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},x={routines:200,summary:160,filters:6,filterValue:60,text:120},Qr=(t,e,n)=>{try{return It(t,e,n)}catch{return null}},Kt=864e5;function Ma(t){let e=t.now??Date.now(),n={...Zr,...t.thresholds},i=t.nextFire??Qr,r=[];for(let a of t.crons){let c=t.cronRuns.get(a.id)??[],l=a.timezone||"UTC",u=c.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=c[0],p={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:I(a.id,x.text),trigger:{schedule:I(a.schedule,x.text),timezone:l},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?Ie(a.nextRun)??Ie(i(a.schedule,new Date(e),l)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:si(d.status==="success"?void 0:d.errorSummary,x.summary)}:null,lastSuccessAt:c.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:Gt(u),sampledRuns:c.length,flags:[],attention:null};p.flags=Xt(p,u,a.schedule,l,null,e,n,i),r.push(Jt(p))}let s=new Map(qt(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let c=o.get(a.workflowId);c?c.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let c=a.nodes.find(_=>_.type.startsWith("trigger."));if(!c||c.type!=="trigger.cron"&&c.type!=="trigger.hook")continue;let l=c.config??{},u=a.state||"active",d=u==="active",p=(o.get(a.id)??[]).slice().sort((_,we)=>we.at-_.at),f=p.map(_=>({at:_.at,status:ni(_.status)})),g=f[0],h=c.type==="trigger.cron",y=typeof l.spec=="string"?l.spec:"",T=typeof l.timezone=="string"?l.timezone:"UTC",F={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:I(a.title||a.id,x.text),trigger:h?{schedule:I(y,x.text),timezone:T}:{event:I(typeof l.event=="string"?l.event:"",x.text),filters:ii(l.filter,a)},agent:ri(a),enabled:d,state:u,nextRunAt:h&&d&&y?Ie(i(y,new Date(e),T)):null,lastRun:g?{at:new Date(g.at).toISOString(),status:g.status}:null,lastSuccessAt:(()=>{let _=f.find(we=>we.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:Gt(f),sampledRuns:p.length,flags:[],attention:null},ee=Date.parse(a.updated||a.created||"");F.flags=h?Xt(F,f,y,T,Number.isFinite(ee)?ee:null,e,n,i):ei(F,s.get(a.id)?.state==="dormant",Number.isFinite(ee)?ee:null,e,n),r.push(Jt(F))}return r.sort(ti).slice(0,x.routines)}function Gt(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 Xt(t,e,n,i,r,s,o,a){let c=[],l=e.length?e[0].at:null;if(!t.enabled){let p=Zt(l,r,s,o);return p&&c.push(p),c}if(t.consecutiveFailures>=o.failStreak&&c.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),l===null)return c.push({reason:"never-ran",detail:"No persisted attempt"}),c;let u=new Date(l),d=null;for(let p=0;p<o.missedFires&&(d=a(n,u,i),!!d);p++)u=d;return d&&s>d.getTime()+o.graceMs&&c.push({reason:"overdue",detail:`No attempt since ${new Date(l).toISOString()}; ${o.missedFires} scheduled fires missed`}),c}function ei(t,e,n,i,r){let s=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=Zt(o,n,i,r);return a&&s.push(a),s}return t.consecutiveFailures>=r.failStreak&&s.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),o===null?s.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&s.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),s}function Zt(t,e,n,i){let r=Math.max(t??0,e??0);return r&&n-r<i.disabledDays*Kt?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/Kt)} days`:"Disabled and never ran"}}function Jt(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 Yt={critical:0,warning:1,info:2};function ti(t,e){let n=t.attention?Yt[t.attention]:3,i=e.attention?Yt[e.attention]:3;return n-i||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function ni(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 ri(t){if(t.ownerAgent)return I(t.ownerAgent,x.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?I(String(e.config.agentId),x.text):null}function ii(t,e){let n=[],i=e?.project;if(i&&n.push(I(`project=${i}`,x.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,s]of Object.entries(t)){let o=Array.isArray(s)?s.map(String):s==null?[]:[String(s)];o.length&&n.push(I(`${r}=${o.join(",")}`,x.filterValue))}return n.slice(0,x.filters)}function Ie(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function I(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function si(t,e){return t===void 0?void 0:I(t,e)}import{createHash as oi,randomBytes as Qt}from"crypto";import{existsSync as ai,mkdirSync as ci,readFileSync as li,writeFileSync as ui}from"fs";import{resolve as di,dirname as pi}from"path";var Ae="agx_live_",fi=".agentx/tokens.json",en=class{file;constructor(e=process.cwd(),n=fi){this.file=di(e,n)}load(){if(!ai(this.file))return[];try{return JSON.parse(li(this.file,"utf-8"))}catch{return[]}}save(e){ci(pi(this.file),{recursive:!0}),ui(this.file,JSON.stringify(e,null,2)+`
3
+ `,"utf-8")}create(e){if(!e.name?.trim())throw new Error("Token name is required.");if(!Array.isArray(e.scopes)||e.scopes.length===0)throw new Error("At least one scope is required.");for(let o of e.scopes)if(!gi(o))throw new Error(`Invalid scope: ${o}`);let n=Qt(32).toString("hex"),i=Ae+n,r={id:"tok_"+Qt(4).toString("hex"),name:e.name.trim(),prefix:Ae+n.slice(0,4),hash:tn(i),scopes:[...e.scopes],createdAt:new Date().toISOString(),expiresAt:e.expiresInDays?new Date(Date.now()+e.expiresInDays*86400*1e3).toISOString():void 0},s=this.load();return s.push(r),this.save(s),{token:i,record:r}}list(){return this.load()}revoke(e){let n=this.load(),i=n.find(r=>r.id===e);return i?(i.revokedAt=new Date().toISOString(),this.save(n),i):null}isActive(e){let n=this.load().find(i=>i.id===e);return!!n&&!n.revokedAt&&!(n.expiresAt&&Date.parse(n.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(Ae))return null;let n=tn(e),i=this.load(),r=i.find(a=>a.hash===n);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let s=Date.now(),o=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(s-o>6e4){r.lastUsedAt=new Date(s).toISOString();try{this.save(i)}catch{}}return r}};function Ua(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function gi(t){return t==="dashboard:read"||t==="dashboard:write"||t==="agent:*"||/^agent:[a-z0-9][a-z0-9_-]*$/.test(t)||t==="mesh:peer"||t==="app"}function tn(t){return"sha256:"+oi("sha256").update(t).digest("hex")}function Ba(t){let e=t.headers.authorization,n=Array.isArray(e)?e[0]:e;if(n&&n.toLowerCase().startsWith("bearer "))return n.slice(7).trim();if(t.url)try{let r=new URL(t.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}import{existsSync as ae,readdirSync as Bi,readFileSync as zi}from"fs";import{resolve as O}from"path";import{randomBytes as sn}from"crypto";import{existsSync as hi,mkdirSync as yi,readdirSync as bi,readFileSync as wi,renameSync as on,unlinkSync as ki,writeFileSync as xi}from"fs";import{resolve as an}from"path";function nn(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var mi=t=>t.trim().split(`
4
+ `).pop()?.slice(0,300)||"no output";async function rn(t,e,n,i=$e){let r=await i(t.bin,[...nn(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${mi(r.stderr||r.stdout)}`}}async function qa(t,e,n,i,r=$e){return(await r(t.bin,[...nn(t),"--read-only","media","download","--chat",e,"--id",n,"--output",i],{timeoutMs:12e4})).code===0}var Si=2e3,vi=t=>rn(t.wacli,t.to,t.text);function Re(t){return an(t,".agentx","whatsapp-triage","drafts")}var $i=t=>/^[a-z0-9-]{8,64}$/.test(t),ie=(t,e)=>an(Re(t),`${e}.json`);function cn(t,e){yi(Re(t),{recursive:!0});let n=ie(t,e.id),i=`${n}.${process.pid}.tmp`;xi(i,JSON.stringify(e,null,2)+`
5
+ `,{mode:384}),on(i,n)}function Za(t,e,n=Date.now()){let i=e.text.trim().slice(0,Si);if(!i)throw new Error("empty draft");let r={...e,text:i,id:`${n.toString(36)}-${sn(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return cn(t,r),r}function se(t,e){if(!$i(e))return null;try{return JSON.parse(wi(ie(t,e),"utf-8"))}catch{return null}}function ln(t,e){let n=Re(t);return hi(n)?bi(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 un(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}.${sn(3).toString("hex")}.claim`;try{on(ie(t,e),s)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(i.send??vi)(r).catch(c=>({ok:!1,error:String(c?.message??c)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}cn(t,o);try{ki(s)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{existsSync as Ii,mkdirSync as Ai,readdirSync as Ri,readFileSync as _i,renameSync as Ci,writeFileSync as Di}from"fs";import{resolve as fn}from"path";function dn(t,e){let n=t.list?` in the "${t.list}" list`:"",i=[`This card came from the operator's reminder "${t.title}"${n} (id ${t.id}).`];return i.push(e?`Do what the operator chose, then tick the reminder off: remindctl complete ${t.id}`:"Leave the reminder open; it will come back at a later check-in."),i}var pn=["discard","keep","pause","approve"],A={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Ei={defaultExpiryDays:3,maxExpiryDays:30};function U(t){return fn(t,".agentx","approvals")}var Ti=/^[a-z0-9][a-z0-9-]{0,80}$/;function gn(t){return Ti.test(t)}function mn(t,e){if(!gn(e))throw new Error(`invalid card id: ${e}`);return fn(U(t),`${e}.json`)}function Pi(t,e){let n=new Date(t).toISOString().slice(0,10),i=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${n}-${i||"card"}-${Math.random().toString(36).slice(2,6)}`}function oe(t,e){Ai(U(t),{recursive:!0});let n=mn(t,e.id),i=`${n}.${process.pid}.tmp`;Di(i,JSON.stringify(e,null,2)+`
6
+ `),Ci(i,n)}function P(t,e){if(!gn(e))return null;try{return JSON.parse(_i(mn(t,e),"utf-8"))}catch{return null}}function L(t,e){let n=U(t);if(!Ii(n))return[];let i=[];for(let r of Ri(n).filter(s=>s.endsWith(".json")&&!s.startsWith("_")).sort()){let s=P(t,r.slice(0,-5));s&&(!e||s.status===e)&&i.push(s)}return i}function w(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function Li(t,e,n){let i=e+n.maxExpiryDays*864e5,r,s=w(t);if(!s)r=e+n.defaultExpiryDays*864e5;else{let o=/^(\d+)\s*([hd])$/i.exec(s);if(o)r=e+Number(o[1])*(o[2].toLowerCase()==="d"?864e5:36e5);else if(r=Date.parse(s),Number.isNaN(r))return{ok:!1,error:`expires must be an ISO date or time, or like "12h" / "3d" (got "${s}")`}}return r<=e?{ok:!1,error:"expires must be in the future"}:{ok:!0,at:new Date(Math.min(r,i)).toISOString()}}function Oi(t,e={}){let n=e.now??Date.now(),i=e.settings??Ei,r=w(t.title),s=w(t.ask),o=w(t.recommend),a=w(t.raised_by);if(!r)return{ok:!1,error:"title is required"};if(!s)return{ok:!1,error:"ask is required: the yes/no question"};if(!o)return{ok:!1,error:"recommend is required: your advice and why, in one line"};if(!a)return{ok:!1,error:"raised_by is required: the agent id"};if(r.length>A.title)return{ok:!1,error:`title is longer than ${A.title} characters`};if(s.length>A.ask)return{ok:!1,error:`ask is longer than ${A.ask} characters`};if(o.length>A.recommend)return{ok:!1,error:`recommend is longer than ${A.recommend} characters`};let c=w(t.if_silent).toLowerCase();if(!pn.includes(c))return{ok:!1,error:`if_silent must be one of ${pn.join(", ")}`};let l=Li(t.expires,n,i);if(!l.ok)return l;let u=w(t.source);if(u.length>A.source)return{ok:!1,error:`source is longer than ${A.source} characters`};if(u&&/^[a-z][a-z0-9+.-]*:/i.test(u)&&!/^https?:\/\//i.test(u))return{ok:!1,error:"source must be an http(s) link or a plain reference"};let d=Mt(t);if(!d.ok)return d;let p,f=t.reply;return f&&typeof f=="object"&&w(f.channel)&&w(f.chatId)&&(p={channel:w(f.channel),chatId:w(f.chatId),...w(f.accountId)?{accountId:w(f.accountId)}:{}}),{ok:!0,card:{id:Pi(n,r),title:r,ask:s,recommend:o,if_silent:c,expires:l.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...p?{reply:p}:{},...d.value,...e.origin?{origin:e.origin}:{},status:"pending"}}}function sc(t,e,n={}){let i=Oi(e,n);if(!i.ok)return i;let r=L(t,"pending").filter(s=>s.raised_by===i.card.raised_by).length;return r>=A.pendingPerAgent?{ok:!1,error:`${i.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(oe(t,i.card),i)}function hn(t,e,n,i={}){let r=P(t,e);if(!r)return{ok:!1,error:`no card "${e}"`};if(r.status!=="pending")return{ok:!1,error:`card "${e}" is already ${r.status}`};let s=Vt(r,n,i);if(!s.ok)return s;let o=w(i.note).slice(0,A.note),a={...r,status:"decided",verdict:n,decided_by:i.by??"operator",decided_at:new Date(i.now??Date.now()).toISOString(),...o?{note:o}:{},...s.choice?{choice:s.choice}:{},...s.text?{text:s.text}:{}};return oe(t,a),{ok:!0,card:a}}function oc(t,e=Date.now()){let n=[];for(let i of L(t,"pending")){if(Date.parse(i.expires)>e)continue;let r={...i,status:"expired",outcome:i.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};oe(t,r),n.push(r)}return n}function ac(t){return L(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function cc(t,e,n=Date.now()){let i=P(t,e);!i||i.agent_notified_at||oe(t,{...i,agent_notified_at:new Date(n).toISOString()})}function lc(t){let e=t.status==="decided"?t.verdict==="yes"?"The operator said YES.":"The operator said NO.":`Nobody answered before it expired, so the default applied: ${t.outcome??t.if_silent}.`,n=[`[Approval result] Your decision card "${t.title}" (${t.id}) is closed.`,`Question: ${t.ask}`,e];return t.status==="decided"&&t.verdict==="yes"&&n.push(...Wt(t)),t.note&&n.push(`Operator note: ${t.note}`),t.source&&n.push(`Source: ${t.source}`),t.origin&&n.push(...dn(t.origin,t.status==="decided"&&t.verdict==="yes")),t.reply&&n.push(`You raised it from ${t.reply.channel} chat ${t.reply.chatId}; reply there if the requester should know.`),n.push("Act on this result now. Do not raise the same card again."),n.join(`
7
+ `)}import{mkdirSync as Ni,readFileSync as Mi,renameSync as ji,writeFileSync as Vi}from"fs";import{resolve as Wi}from"path";function yn(t){return Wi(U(t),"_state.json")}function C(t){try{let e=JSON.parse(Mi(yn(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{},...e?.popped&&typeof e.popped=="object"?{popped:e.popped}:{},...typeof e?.passAt=="string"?{passAt:e.passAt}:{},...Array.isArray(e?.wanted)?{wanted:e.wanted.filter(n=>typeof n=="string")}:{}}}catch{return{snoozed:{}}}}function K(t,e){Ni(U(t),{recursive:!0});let n=yn(t),i=`${n}.${process.pid}.tmp`;Vi(i,JSON.stringify(e,null,2)+`
8
+ `),ji(i,n)}function bn(t,e,n,i=Date.now()){let r=C(t),s={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>i&&(s[o]=a);s[e]=n.toISOString(),K(t,{...r,snoozed:s})}function gc(t,e){K(t,{...C(t),lastDigest:e})}function wn(t,e,n,i=Date.now()){let r=C(t),s=new Set(n),o={};for(let[c,l]of Object.entries(r.popped??{}))s.has(c)&&(o[c]=l);o[e]=new Date(i).toISOString();let a=(r.wanted??[]).filter(c=>c!==e&&s.has(c));K(t,{...r,popped:o,wanted:a})}function kn(t,e){let n=C(t);K(t,{...n,wanted:[...(n.wanted??[]).filter(i=>i!==e),e]})}function mc(t,e=Date.now()){K(t,{...C(t),popped:{},passAt:new Date(e).toISOString()})}import{existsSync as Fi,readFileSync as Ui}from"fs";xt();function xn(t){let e=vt(t),n={};if(Fi(e))try{n=wt(JSON.parse(Ui(e,"utf-8")))}catch{n={}}let i=ke.safeParse(n?.requests);return i.success?i.data:ke.parse(void 0)}async function kc(t,e={}){return $t(n=>{let i=n.requests??={};for(let r of["enabled","channels","from","staleAfterHours","retentionDays"])t[r]!==void 0&&(i[r]=t[r])},{configPath:e.configPath,reload:e.reload})}var vn=["card","schedule","memory","wiki","whatsapp","request"],Hi=280;function j(t,e=Hi){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function _e(t){if(t.configPath)return O(t.configPath);let e=[O(t.root,"agentx.json"),O(t.root,".agentx","config.json")];return e.find(n=>ae(n))??e[0]}function Ce(t){return t.wikiDir?O(t.wikiDir):O(t.root,".agentx","wiki")}function qi(t){return L(t.root,"pending").map(Ki)}function Ki(t){return{key:`card:${t.id}`,kind:"card",title:t.title,ask:t.ask,yes:`tell ${t.raised_by} yes`,no:`tell ${t.raised_by} no`,recommend:t.recommend,if_silent:t.if_silent,expires:t.expires,...t.source?{source:t.source}:{},raised_by:t.raised_by,created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.context||t.draft?{detail:j([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function Gi(t){let e=_e(t);if(!ae(e))return[];let n;try{n=JSON.parse(zi(e,"utf-8"))}catch{return[]}let i=new Date(t.now??Date.now()),r=[];for(let[s,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let c=o.timezone||"UTC",l=o.schedule?Dt(o.schedule):"",u=o.schedule?`${l.charAt(0).toLowerCase()}${l.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),p=a.action==="create";r.push({key:`schedule:${s}`,kind:"schedule",title:p?`New schedule "${s}" for ${o.agent??"an agent"}`:`Delete schedule "${s}"`,ask:p?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${s}" (${u})?`,yes:p?"enable it":"remove it",no:p?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:j(`${d}${p&&o.schedule?` \xB7 first run ${Tt(Et(o.schedule,c,i),c)}`:""}`),more:"agentx schedule list"})}return r}function $n(t){let e=O(t,".agentx","memory");return ae(e)?Bi(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function Xi(t){let e=$n(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 Ji(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 Yi(t){return Ut(Ce(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:j(`${Ji(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function Zi(t){return ln(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 In(t){if(t.requests)return t.requests;if(O(t.root)!==process.cwd()||!ae(O(t.root,".agentx","db.sqlite")))return null;let e=St({quiet:!0});if(!e)return null;let n=Sn.get(e);return n||Sn.set(e,n=new At(e)),n}var Sn=new WeakMap;function Qi(t){let e=In(t);return e?e.listByState("needs_attention").map(n=>({key:`request:${n.id}`,kind:"request",title:`Request not finished: ${j(n.text,80)}`,ask:`Ask ${n.agentId} to pick it up again?`,yes:`hand it back to ${n.agentId}`,no:"drop the request",raised_by:n.agentId,created_at:new Date(n.createdAt).toISOString(),detail:j(`${n.attentionReason??"It needs attention"}. Asked on ${n.channel}: ${n.text}`),more:`agentx requests show ${n.id}`})):[]}var An={card:qi,schedule:Gi,memory:Xi,wiki:Yi,whatsapp:Zi,request:Qi};function es(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 Lc(t,e={}){let n=t.now??Date.now(),{snoozed:i}=C(t.root),r=[],s=[],o=0;for(let a of e.kinds??vn){let c;try{c=An[a](t)}catch(l){s.push({kind:a,error:String(l?.message??l).slice(0,200)});continue}for(let l of c){let u=i[l.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}l.snoozed_until=u}r.push(l)}}return r.sort(es),{items:r,snoozed:o,errors:s}}function ts(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),i=t.slice(e+1);return!vn.includes(n)||!i?null:{kind:n,ref:i}}function ns(t,e,n){switch(e){case"card":return P(t.root,n)?.status==="pending";case"wiki":return Ft(Ce(t),n)?.status==="pending";case"whatsapp":return se(t.root,n)?.status==="pending";default:return An[e](t).some(i=>i.key===`${e}:${n}`)}}async function Rn(t,e,n,i={}){let r=ts(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:s,ref:o}=r,a=t.now??Date.now(),c=i.by??"operator";if(n==="later"){if(!ns(t,s,o))return{ok:!1,error:`nothing waiting for "${e}"`};let u=i.laterHours&&i.laterHours>0?i.laterHours:24,d=new Date(a+u*36e5);return bn(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let l=n==="yes";switch(s){case"card":{let u=hn(t.root,o,l?"yes":"no",{by:c,note:i.note,now:a,choice:i.choice,text:i.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${l?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(l?Pt:Lt)(o,{configPath:_e(t),reload:t.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=o.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=o.slice(0,u),p=o.slice(u+1);if(!$n(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,l?"approved":"rejected",c),{ok:!0,message:`${e} ${l?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${p}" isn't waiting for review`}}case"wiki":{let u=Ce(t),d=l?Bt(u,o,{by:c,force:i.force,now:a}):zt(u,o,{by:c,reason:i.note,now:a});return d.ok?{ok:!0,message:l?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await un(t.root,o,l?"yes":"no",{by:c,now:a,send:t.sendWhatsApp});return u.ok?{ok:!0,message:l?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}case"request":{let u=In(t),d=u?.get(o);return!u||!d||d.state!=="needs_attention"?{ok:!1,error:`nothing waiting for "${e}"`}:l?xn(_e(t)).enabled?(u.requestPickup(o,a),{ok:!0,message:`${e}: ${d.agentId} will be asked to pick it up again`}):{ok:!1,error:"Requests are off, so nothing would hand it back. Turn them on (agentx requests settings --enabled on), or answer no to drop it."}:(u.close(o,"dropped",i.note?.trim()||`dropped by ${c}`,a),{ok:!0,message:`${e}: dropped`})}}}var _n=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Nc(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/requests"||t.startsWith("/requests/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/a2a/delegations"||t.startsWith("/a2a/delegations/")||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"||t==="/app-files"||t==="/calls"||t.startsWith("/calls/")||t==="/webrtc/camera"||t.startsWith("/webrtc/camera/")}function Mc(t){return t==="/reload"||t==="/api/processes/kill"||t==="/send"||t==="/send/agent"||t==="/send/contact"||t==="/mesh/announce"||t==="/voice/settings"||t==="/voice/preview"||/^\/api\/tasks\/[^/]+\/(cancel|followup)$/.test(t)||/^\/crons\/[^/]+\/enabled$/.test(t)}function jc(t){return _n.has(t)}function Vc(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(_n.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 Wc(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 Fc(t,e,n=process.env){let i=s=>s.replace(/\/+$/,"");return(e===i(t.daemonUrl)?t.token:t.daemons.find(s=>i(s.url)===e)?.token)||n.MESH_TOKEN||void 0}function ce(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function rs(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function is(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Bc(t,e=is()){let n=ce(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=rs(n),s=[ce(t.host),ce(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&s.includes(r)?"same-origin":"foreign"}let i=ce(t["sec-fetch-site"]).toLowerCase();return i==="cross-site"||i==="same-site"?"foreign":"none"}function zc(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as Qn,mkdirSync as Ps,readFileSync as Ls,renameSync as Os,writeFileSync as Ns}from"fs";import{homedir as Ms}from"os";import{dirname as js,join as Vs}from"path";import{execFile as ms,execFileSync as hs}from"child_process";import{execFileSync as ss}from"child_process";import{existsSync as Dn,mkdirSync as os,readdirSync as as,readFileSync as En,renameSync as cs,writeFileSync as ls}from"fs";import{homedir as Tn}from"os";import{join as Ee}from"path";var v="siri:",Pn="com.apple.ttsbundle.gryphon-neural_",Ln=t=>!!t&&t.startsWith(Pn),us=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],ds=()=>{try{return ss("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},De;function Te(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&De!==void 0)return De;let{platform:n=process.platform,exists:i=Dn,prefDomain:r=ds}=t,s=n==="darwin"&&us.every(o=>i(o))&&r();return e||(De=s),s}var On=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Nn={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"},Pe=t=>Nn[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 ps=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function fs(t){let e=new Map;for(let n of t)for(let[,i,r,s]of n.matchAll(ps)){let o=`${i}-${r}`,a=`${Pn}${s}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:s[0].toUpperCase()+s.slice(1),locale:o,quality:"premium",gender:Nn[s]??null,siri:!0})}return[...e.values()]}function ue(t=On,e={}){if(!Te(e))return[];let n=[];for(let i of t){let r;try{r=as(i)}catch{continue}for(let s of r)try{n.push(En(Ee(i,s,"Info.plist"),"latin1"))}catch{}}return fs(n)}var Cn=`#!/bin/sh
9
9
  # Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
10
10
  # siri-say.sh [voice] < text speak one line. A Siri voice id switches
11
11
  # the OS default for it; any other id is
@@ -17,7 +17,7 @@ D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
17
17
  dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
18
18
  stops="$dir/stop"
19
19
  read_s=\${AGENTX_SAY_READ_S:-5} stale_s=\${AGENTX_SAY_STALE_S:-30} max_s=\${AGENTX_SAY_MAX_S:-300}
20
- assets=\${AGENTX_SIRI_ASSET_DIRS:-"${vn.join(" ")}"}
20
+ assets=\${AGENTX_SIRI_ASSET_DIRS:-"${On.join(" ")}"}
21
21
  if [ "$1" = --stop ]; then
22
22
  mkdir -p "$dir" || exit 1
23
23
  # Queued lines see this change and drop. The owner's trap stops say,
@@ -110,30 +110,30 @@ wait "$say_pid"
110
110
  status=$?
111
111
  say_pid=
112
112
  finish $status
113
- `,as=(t=xn())=>Ce(t,".agentx","voice","siri-say.sh");function An(t=xn()){let e=as(t);return bn(e)&&wn(e,"utf8")===yn||(Qi(Ce(t,".agentx","voice"),{recursive:!0}),ns(`${e}.tmp`,yn,{mode:493}),ts(`${e}.tmp`,e)),e}var In=`ObjC.import("AVFoundation")
113
+ `,gs=(t=Tn())=>Ee(t,".agentx","voice","siri-say.sh");function Mn(t=Tn()){let e=gs(t);return Dn(e)&&En(e,"utf8")===Cn||(os(Ee(t,".agentx","voice"),{recursive:!0}),ls(`${e}.tmp`,Cn,{mode:493}),cs(`${e}.tmp`,e)),e}var jn=`ObjC.import("AVFoundation")
114
114
  const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
115
115
  for (let i = 0; i < vs.count; i++) {
116
116
  const v = vs.objectAtIndex(i)
117
117
  out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
118
118
  }
119
- out.join("\\n")`,ds=new Set(["Fred","Kathy","Ralph","Junior"]),us={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 Rn(t){let e=[];for(let n of t.split(`
120
- `)){let[i,r,s,o,a]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!ds.has(r)||e.push({id:i,name:r,locale:s,quality:o==="3"?"premium":o==="2"?"enhanced":"standard",gender:a==="1"?"male":a==="2"?"female":us[r]??null})}return e}var ps=10*60*1e3,Fc=60*1e3,U=null,Te=!1;function Le(t=Date.now(),e=ps){if(process.platform!=="darwin")return[];if(U)t-U.at>e&&!Te&&(Te=!0,cs("osascript",["-l","JavaScript","-e",In],{timeout:1e4},(n,i)=>{Te=!1,n||(U={at:Date.now(),voices:[...Rn(String(i)),...le()]})}));else try{U={at:t,voices:[...Rn(ls("osascript",["-l","JavaScript","-e",In],{encoding:"utf8",timeout:1e4})),...le()]}}catch(n){Pe(`[voice] could not list system voices: ${String(n?.message??n).split(`
121
- `)[0]}`),U={at:t,voices:le()}}return U.voices}var Pe=t=>process.stderr.write(t+`
122
- `),de=new Set;function Wc(t){Pe=t}function M(t,e){de.has(t)||(de.add(t),Pe(e))}function Dn(t){for(let e of de)t(e)&&de.delete(e)}var En=()=>{};function Uc(t){En=t}function Tn(t){try{En(t)}catch(e){M("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var fs={premium:3,enhanced:2,standard:1},gs=new Set(["Grandma","Grandpa"]);function _n(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!gs.has(t.name)?1:0;return fs[t.quality]*10+e}var B=t=>t.toLowerCase().split(/[-_]/)[0],Cn=t=>t.id.startsWith("com.apple.voice.");function Oe(t,e,n,i=new Set){let r=q(t.filter(a=>!a.siri&&B(a.locale)===B(e)),e);if(r.some(Cn)&&(r=r.filter(Cn)),n==="female"||n==="male"){let a=r.filter(c=>c.gender===n);a.length&&(r=a)}if(!r.length)return null;let s=r.filter(a=>a.quality===r[0].quality),o=new Set([...i].map(a=>a.toLowerCase()));return s.find(a=>!o.has(a.name.toLowerCase()))??s[0]}function q(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=B(e),r=t.filter(s=>B(s.locale)===i);return(r.length?r:t).slice().sort((s,o)=>_n(o)-_n(s)||+(o.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(o.name)||s.locale.localeCompare(o.locale))}function X(t,e,n="en"){let i=t.trim();if(!i)return null;let r=e.find(l=>l.id===i);if(r)return r;if(i.toLowerCase().startsWith(v)){let l=i.slice(v.length).trim().toLowerCase(),d=q(e.filter(p=>p.siri&&p.name.toLowerCase()===l),n)[0];if(d||!l)return d??null;let u=X(l,e.filter(p=>B(p.locale)===B(n)),n);return u&&M(`siri:${l}`,`[voice] Siri voice "${l}" is not installed; speaking with ${u.name} (${u.locale}) instead.`),u}e=e.filter(l=>!l.siri);let s=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(i),o=(s?s[1]:i.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=q(e.filter(l=>l.name.toLowerCase()===o),n);return(s?a.find(l=>l.quality===s[2].toLowerCase()):void 0)??a[0]??null}function Ln(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(o=>o.toLowerCase())),s="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",c=a?o.gender:s,l=e.filter(u=>!r.has(u.name.toLowerCase())),d=l.find(u=>u.gender===c)??(a?e.find(u=>u.gender===c):void 0)??l[0]??e[i.size%e.length];i.set(o.id,d),r.add(d.name.toLowerCase()),a||(s=s==="female"?"male":"female")}return i}mt();var Ne="system",ms=t=>t.trim().toLowerCase()===Ne,hs="21m00Tcm4TlvDq8ikWAM";function Me(t,e,n={},i=Le()){let r=e[t],s=r?.name||t,o=r?.voice,a=Ve(e,n,i).get(t)??null,c=xs(t,o?.system,o?.gender,n,i);return{agentId:t,name:s,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?pe(a):null,systemByLanguage:c,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Ss(s,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var pe=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function ys(t,e,n,i){if(!e||!n.length)return null;let r=X(e,n,i);return r||(M(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),Tn(e)),r}function Mn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(v))return{locale:e,gender:Ee(n.slice(v.length).trim())};let i=ce(n);return i?{locale:i.locale,gender:Ee(i.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var jn=t=>t.toLowerCase().split(/[-_]/)[0],Pn=(t,e)=>typeof t=="string"?t:t?.[jn(e)];function ue(t,e,n,i){if(e!==void 0)return ms(e)?null:ys(t,e,n,i)??void 0}var je=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function bs(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,o=[],a=ue("voice.system",Pn(e.system,r),n,r),c=()=>new Set([...i,...[...s.values()].flatMap(d=>d?[d.name]:[])]);for(let d of t){let u=Pn(d.system,r),p=ue(d.id,u,n,r),f=p!==void 0?p:u!==void 0&&n.length?ws(d,u,r,a,n,c()):a!==void 0&&je(a,d.gender)?a:void 0;f!==void 0?s.set(d.id,f):o.push({id:d.id,gender:d.gender??null})}let l=c();for(let[d,u]of Ln(o,q(n.filter(p=>!p.siri),r),l))s.set(d,u);return s}function ws(t,e,n,i,r,s){for(let a of t.fallbacks??[]){let c=ue(`${t.id}.fallbacks`,a,r,n);if(c!==void 0)return c}if(i!==void 0&&je(i,t.gender))return i;let o=Mn(e,n);return Oe(r,o.locale,t.gender??o.gender,s)??void 0}function xs(t,e,n,i,r){if(typeof e=="string")return{};let s={},o=(a,c,l)=>{if(!(!c||typeof c=="string"))for(let[d,u]of Object.entries(c)){let p=ue(`${a}.${d}`,u,r,d);p===void 0&&r.length&&(p=Oe(r,d,n??Mn(u,d).gender)??void 0),p!==void 0&&l(p)&&(s[jn(d)]=p)}};return o("voice.system",i.system,a=>je(a,n)),o(t,e,()=>!0),s}function Gc(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 Ve(t,e={},n=Le()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return bs(i,e,n)}function Fe(t,e){let n={provider:t.provider,elevenlabs:ks(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 ks(t,e){return t||e||process.env.AGENTX_VOICE_ID||hs}function Ss(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",i=/^You are (.+?)\.?$/i.exec(n.trim());if(!i)return`Hello, this is ${t}.`;let r=i[1].replace(/\s*\([^)]*\)/g,"").trim(),[s,...o]=r.split(/,\s*/),a=o.join(", ");return a&&s.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${a}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var vs=8*60*60*1e3,$s=500,On=class{constructor(e=vs){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Nn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Nn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>$s&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Nn=(t,e)=>`${t}\0${e}`;function Vn(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 qc(t,e,n,i={}){let r=e[t],s=Me(t,e,i),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:Fe(s),persona:o||`You are ${s.name}.`,introLine:Vn(s,n)}}var As="[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 Xc(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`${As}
123
- ${Vn(r,e.voice.introduce===!0&&!!i)}`}var Ls="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",Un=(t=Ds())=>Ts(t,".agentx","voice","health.json");function Ps(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===Ne)return!0;if(i.toLowerCase().startsWith(v)){let r=i.slice(v.length).trim().toLowerCase();return e.some(s=>s.siri&&s.name.toLowerCase()===r)}return X(i,e,n)!==null}function Os(t){let e=t.voice?.locale??"en",n=[],i=(r,s)=>{if(typeof s=="string")n.push({owner:r,name:s,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(s??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};i("voice.system",t.voice?.system);for(let[r,s]of Object.entries(t.agents))(s.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||i(r,s.voice?.system);return n}function Ns(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:o,perLanguage:a}of Os(t)){if(Ps(s,e,o))continue;i??=Ve(t.agents,t.voice,e);let c=n.get(s)??{voice:s,agents:[],speaksWith:{}};c.agents.includes(r)||c.agents.push(r);let l=i.get(r);r!=="voice.system"&&!a&&(c.speaksWith[r]=l?pe(l):"the OS default voice"),n.set(s,c)}return[...n.values()]}function We(t){let e=ce(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 Ms(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${We(n.voice)}: ${i}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
119
+ out.join("\\n")`,ys=new Set(["Fred","Kathy","Ralph","Junior"]),bs={Flo:"female",Sandy:"female",Shelley:"female",Grandma:"female",Kathy:"female",Eddy:"male",Reed:"male",Rocko:"male",Grandpa:"male",Fred:"male",Ralph:"male",Junior:"male"};function Vn(t){let e=[];for(let n of t.split(`
120
+ `)){let[i,r,s,o,a]=n.split(" ");!i||!r||!s||i.includes(".siri_")||i.startsWith("com.apple.speech.synthesis.voice.")&&!ys.has(r)||e.push({id:i,name:r,locale:s,quality:o==="3"?"premium":o==="2"?"enhanced":"standard",gender:a==="1"?"male":a==="2"?"female":bs[r]??null})}return e}var ws=10*60*1e3,Qc=60*1e3,B=null,Le=!1;function Oe(t=Date.now(),e=ws){if(process.platform!=="darwin")return[];if(B)t-B.at>e&&!Le&&(Le=!0,ms("osascript",["-l","JavaScript","-e",jn],{timeout:1e4},(n,i)=>{Le=!1,n||(B={at:Date.now(),voices:[...Vn(String(i)),...ue()]})}));else try{B={at:t,voices:[...Vn(hs("osascript",["-l","JavaScript","-e",jn],{encoding:"utf8",timeout:1e4})),...ue()]}}catch(n){Ne(`[voice] could not list system voices: ${String(n?.message??n).split(`
121
+ `)[0]}`),B={at:t,voices:ue()}}return B.voices}var Ne=t=>process.stderr.write(t+`
122
+ `),de=new Set;function el(t){Ne=t}function V(t,e){de.has(t)||(de.add(t),Ne(e))}function Un(t){for(let e of de)t(e)&&de.delete(e)}var Bn=()=>{};function tl(t){Bn=t}function zn(t){try{Bn(t)}catch(e){V("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var ks={premium:3,enhanced:2,standard:1},xs=new Set(["Grandma","Grandpa"]);function Wn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!xs.has(t.name)?1:0;return ks[t.quality]*10+e}var z=t=>t.toLowerCase().split(/[-_]/)[0],Fn=t=>t.id.startsWith("com.apple.voice.");function Me(t,e,n,i=new Set){let r=G(t.filter(a=>!a.siri&&z(a.locale)===z(e)),e);if(r.some(Fn)&&(r=r.filter(Fn)),n==="female"||n==="male"){let a=r.filter(c=>c.gender===n);a.length&&(r=a)}if(!r.length)return null;let s=r.filter(a=>a.quality===r[0].quality),o=new Set([...i].map(a=>a.toLowerCase()));return s.find(a=>!o.has(a.name.toLowerCase()))??s[0]}function G(t,e="en"){let n=e.toLowerCase().replace("_","-"),i=z(e),r=t.filter(s=>z(s.locale)===i);return(r.length?r:t).slice().sort((s,o)=>Wn(o)-Wn(s)||+(o.locale.toLowerCase()===n)-+(s.locale.toLowerCase()===n)||s.name.localeCompare(o.name)||s.locale.localeCompare(o.locale))}function X(t,e,n="en"){let i=t.trim();if(!i)return null;let r=e.find(l=>l.id===i);if(r)return r;if(i.toLowerCase().startsWith(v)){let l=i.slice(v.length).trim().toLowerCase(),u=G(e.filter(p=>p.siri&&p.name.toLowerCase()===l),n)[0];if(u||!l)return u??null;let d=X(l,e.filter(p=>z(p.locale)===z(n)),n);return d&&V(`siri:${l}`,`[voice] Siri voice "${l}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(l=>!l.siri);let s=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(i),o=(s?s[1]:i.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=G(e.filter(l=>l.name.toLowerCase()===o),n);return(s?a.find(l=>l.quality===s[2].toLowerCase()):void 0)??a[0]??null}function Hn(t,e,n=new Set){let i=new Map;if(!e.length)return i;let r=new Set([...n].map(o=>o.toLowerCase())),s="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",c=a?o.gender:s,l=e.filter(d=>!r.has(d.name.toLowerCase())),u=l.find(d=>d.gender===c)??(a?e.find(d=>d.gender===c):void 0)??l[0]??e[i.size%e.length];i.set(o.id,u),r.add(u.name.toLowerCase()),a||(s=s==="female"?"male":"female")}return i}yt();var je="system",Ss=t=>t.trim().toLowerCase()===je,vs="21m00Tcm4TlvDq8ikWAM";function Ve(t,e,n={},i=Oe()){let r=e[t],s=r?.name||t,o=r?.voice,a=Fe(e,n,i).get(t)??null,c=Rs(t,o?.system,o?.gender,n,i);return{agentId:t,name:s,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?fe(a):null,systemByLanguage:c,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Cs(s,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var fe=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function $s(t,e,n,i){if(!e||!n.length)return null;let r=X(e,n,i);return r||(V(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),zn(e)),r}function Xn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(v))return{locale:e,gender:Pe(n.slice(v.length).trim())};let i=le(n);return i?{locale:i.locale,gender:Pe(i.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var Jn=t=>t.toLowerCase().split(/[-_]/)[0],qn=(t,e)=>typeof t=="string"?t:t?.[Jn(e)];function pe(t,e,n,i){if(e!==void 0)return Ss(e)?null:$s(t,e,n,i)??void 0}var We=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Is(t,e,n,i=new Set){let r=e.locale??"en",s=new Map,o=[],a=pe("voice.system",qn(e.system,r),n,r),c=()=>new Set([...i,...[...s.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=qn(u.system,r),p=pe(u.id,d,n,r),f=p!==void 0?p:d!==void 0&&n.length?As(u,d,r,a,n,c()):a!==void 0&&We(a,u.gender)?a:void 0;f!==void 0?s.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let l=c();for(let[u,d]of Hn(o,G(n.filter(p=>!p.siri),r),l))s.set(u,d);return s}function As(t,e,n,i,r,s){for(let a of t.fallbacks??[]){let c=pe(`${t.id}.fallbacks`,a,r,n);if(c!==void 0)return c}if(i!==void 0&&We(i,t.gender))return i;let o=Xn(e,n);return Me(r,o.locale,t.gender??o.gender,s)??void 0}function Rs(t,e,n,i,r){if(typeof e=="string")return{};let s={},o=(a,c,l)=>{if(!(!c||typeof c=="string"))for(let[u,d]of Object.entries(c)){let p=pe(`${a}.${u}`,d,r,u);p===void 0&&r.length&&(p=Me(r,u,n??Xn(d,u).gender)??void 0),p!==void 0&&l(p)&&(s[Jn(u)]=p)}};return o("voice.system",i.system,a=>We(a,n)),o(t,e,()=>!0),s}function ol(t,e){let n=e?te(e):null;if(!n||!(n in t.systemByLanguage))return t;let i=t.systemByLanguage[n];return{...t,systemVoice:i?.id??null,systemVoiceName:i?fe(i):null}}function Fe(t,e={},n=Oe()){let i=Object.entries(t).map(([r,s])=>({id:r,system:s.voice?.system,gender:s.voice?.gender,fallbacks:s.voice?.fallbacks}));return Is(i,e,n)}function Ue(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||vs}function Cs(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",i=/^You are (.+?)\.?$/i.exec(n.trim());if(!i)return`Hello, this is ${t}.`;let r=i[1].replace(/\s*\([^)]*\)/g,"").trim(),[s,...o]=r.split(/,\s*/),a=o.join(", ");return a&&s.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${a}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var Ds=8*60*60*1e3,Es=500,Kn=class{constructor(e=Ds){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,i=Date.now()){let r=this.lastSpoke.get(Gn(e,n));return r===void 0||i-r>this.gapMs}spoke(e,n,i=Date.now()){let r=Gn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,i),this.lastSpoke.size>Es&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Gn=(t,e)=>`${t}\0${e}`;function Yn(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 al(t,e,n,i={}){let r=e[t],s=Ve(t,e,i),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:s.name,voice:Ue(s),persona:o||`You are ${s.name}.`,introLine:Yn(s,n)}}var Ts="[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 cl(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`${Ts}
123
+ ${Yn(r,e.voice.introduce===!0&&!!i)}`}var Ws="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",er=(t=Ms())=>Vs(t,".agentx","voice","health.json");function Fs(t,e,n){let i=t.trim();if(!i||i.toLowerCase()===je)return!0;if(i.toLowerCase().startsWith(v)){let r=i.slice(v.length).trim().toLowerCase();return e.some(s=>s.siri&&s.name.toLowerCase()===r)}return X(i,e,n)!==null}function Us(t){let e=t.voice?.locale??"en",n=[],i=(r,s)=>{if(typeof s=="string")n.push({owner:r,name:s,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(s??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};i("voice.system",t.voice?.system);for(let[r,s]of Object.entries(t.agents))(s.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||i(r,s.voice?.system);return n}function Bs(t,e){if(!e.length)return[];let n=new Map,i;for(let{owner:r,name:s,locale:o,perLanguage:a}of Us(t)){if(Fs(s,e,o))continue;i??=Fe(t.agents,t.voice,e);let c=n.get(s)??{voice:s,agents:[],speaksWith:{}};c.agents.includes(r)||c.agents.push(r);let l=i.get(r);r!=="voice.system"&&!a&&(c.speaksWith[r]=l?fe(l):"the OS default voice"),n.set(s,c)}return[...n.values()]}function Be(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 zs(t){let e=t.map(n=>{let i=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${Be(n.voice)}: ${i}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
124
124
  `)}
125
- Reinstall in ${Ls}. Agents switch back on their own once it is installed.`}}function js(t=Un()){if(!Wn(t))return null;try{let e=JSON.parse(Rs(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function Vs(t,e){Is(Es(t),{recursive:!0}),Cs(`${t}.tmp`,JSON.stringify(e,null,2)+`
126
- `),_s(`${t}.tmp`,t)}var Fn=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??Un(),s=new Map((js(r)?.missing??[]).map(u=>[u.voice,u])),o=Ns(e,n),a=o.map(u=>({...u,since:s.get(u.voice)?.since??i.toISOString(),...s.get(u.voice)?.notifiedAt?{notifiedAt:s.get(u.voice).notifiedAt}:{}})),c=[...s.keys()].filter(u=>!o.some(p=>p.voice===u));for(let u of c)this.deps.log(`[voice] ${We(u)} is installed again; its agents speak with it again`);c.length&&Dn(u=>c.some(p=>u===p||u.endsWith(`:${p}`)));let l=a.filter(u=>!u.notifiedAt);if(l.length){let{title:u,message:p}=Ms(l);try{await this.deps.notify(u,p);for(let f of l)f.notifiedAt=i.toISOString();this.deps.log(`[voice] told the owner: ${l.map(f=>We(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=a.length>0;let d={checkedAt:i.toISOString(),missing:a};return(!Wn(r)||JSON.stringify(a)!==JSON.stringify([...s.values()]))&&Vs(r,d),d}finally{this.running=!1}}};import{readFileSync as Be,writeFileSync as qn,existsSync as ze,readdirSync as qs,statSync as Xs}from"fs";import{resolve as He,join as Js}from"path";import{existsSync as Bn,mkdirSync as Fs,readFileSync as Ws,writeFileSync as zn}from"fs";import{dirname as Us,resolve as Hn}from"path";import{z as m}from"zod";var Bs=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),zs=m.object({id:m.string(),title:m.string(),description:m.string().optional(),assignee:m.string().optional(),labels:m.array(m.string()).default([]),milestone:m.string().optional(),status:m.enum(["todo","doing","blocked","done"]).default("todo"),priority:m.number().int().optional(),estimatedSeconds:m.number().int().optional(),source:Bs.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),Hs=m.object({version:m.literal(1),items:m.array(zs).default([])}),fe=class{constructor(e){this.path=e}jsonPath(){return Hn(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return Hn(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return Bn(this.jsonPath())}load(){let e=this.jsonPath();if(!Bn(e))return{version:1,items:[]};let n=Ws(e,"utf-8");try{return Hs.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();Fs(Us(n),{recursive:!0}),zn(n,JSON.stringify(e,null,2)+`
127
- `),zn(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(s=>s.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let i=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??i,updatedAt:i};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),i=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),s=[];for(let o of e){if(i.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),s.push(a),i.add(a.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let s={...i.items[r],...n,id:i.items[r].id,createdAt:i.items[r].createdAt,updatedAt:new Date().toISOString()};return i.items[r]=s,this.save(i),s}remove(e){let n=this.load(),i=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===i?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],i={doing:[],blocked:[],todo:[],done:[]};for(let s of e.items)i[s.status].push(s);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[s,o]of r)if(i[s].length){n.push(`## ${o}`,"");for(let a of i[s]){let c=s==="done"?"x":" ",l=a.assignee?`@${a.assignee} `:"",d=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",u=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${c}] ${l}${a.title}${d}${u}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
128
- `)}};function al(t){return`${t.type}:${t.project}:${t.iid}`}function Kn(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.gitlabUsernames?.length?i.push(o.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.githubUsernames?.length?i.push(o.githubUsernames[0]):i.push(s)}}return i}async function Ue(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?Ks(t.source,e,n,i):t.source.type==="github"?Gs(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function Ks(t,e,n,i){let r=n.channels.gitlab,s=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!s||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],c=async(f,g={})=>fetch(`${o}/api/v4${f}`,{...g,headers:{"PRIVATE-TOKEN":s,"Content-Type":"application/json",...g.headers||{}}}),l=encodeURIComponent(t.project),d;e.assigneeUsernames!==void 0&&(d=(await Promise.all(e.assigneeUsernames.map(async g=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(g)}`,{headers:{"PRIVATE-TOKEN":s}});if(!h.ok)return null;let y=await h.json();return Array.isArray(y)&&y[0]?.id?y[0].id:null}catch{return null}}))).filter(g=>typeof g=="number"));let u;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")u=0;else try{let f=await c(`/projects/${l}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let g=await f.json();Array.isArray(g)&&g[0]?.id&&(u=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(",")),d!==void 0&&(p.assignee_ids=d),u!==void 0&&(p.milestone_id=u),e.state&&(p.state_event=e.state==="closed"?"close":"reopen"),Object.keys(p).length)try{let f=await c(`/projects/${l}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(p)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let g=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${g.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await c(`/projects/${l}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function Gs(t,e,n,i){let s=n.channels.github?.token;if(!s)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(p,f={})=>fetch(`https://api.github.com${p}`,{...f,headers:{Authorization:`Bearer ${s}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),c=t.project,l;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")l=null;else try{let p=await a(`/repos/${c}/milestones?state=all&per_page=100`);if(p.ok){let f=await p.json(),g=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;g?.number&&(l=g.number)}}catch(p){i(`[backlog-sync] github milestone lookup failed: ${p.message}`)}let d;if(e.labels!==void 0)d=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let p=await a(`/repos/${c}/issues/${t.iid}`);if(p.ok){let f=await p.json(),g=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...g,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);d=[...h]}}catch(p){i(`[backlog-sync] github label fetch failed: ${p.message}`)}let u={};if(e.title!==void 0&&(u.title=e.title),e.description!==void 0&&(u.body=e.description),d!==void 0&&(u.labels=d),e.assigneeUsernames!==void 0&&(u.assignees=e.assigneeUsernames),l!==void 0&&(u.milestone=l),e.state&&(u.state=e.state),Object.keys(u).length)try{let p=await a(`/repos/${c}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(u)});if(o.push({kind:"PATCH issue",ok:p.ok,status:p.status}),!p.ok){let f=await p.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${p.status}: ${f.slice(0,200)}`,url:t.url}}}catch(p){return o.push({kind:"PATCH issue",ok:!1,error:p.message}),{ok:!1,attempts:o,error:p.message,url:t.url}}if(e.note)try{let p=await a(`/repos/${c}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:p.ok,status:p.status})}catch(p){o.push({kind:"POST comment",ok:!1,error:p.message})}return{ok:o.every(p=>p.ok),attempts:o,url:t.url}}var Ke=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,ge=/@([a-z0-9_-]+)/i,Gn=/\[time:\s*([0-9hm\s]+)\]/i;function Ys(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 Ge=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=He(process.cwd(),this.path);return ze(e)?Be(e,"utf-8").split(`
129
- `):[]}writeMd(e){let n=He(process.cwd(),this.path);qn(n,e.join(`
130
- `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(s=>s.status!=="done"&&(!s.assignee||s.assignee.toLowerCase()===e.toLowerCase())).map(s=>this.toWorkItem(s));let n=this.readMd(),i=[];for(let r=0;r<n.length;r++){let s=n[r].match(Ke);if(!s||s[2].toLowerCase()==="x")continue;let a=s[3],c=a.match(ge);if(c&&c[1].toLowerCase()!==e.toLowerCase())continue;let l=a.match(Gn),d=a.replace(ge,"").replace(Gn,"").trim();i.push({id:`backlog:${r}`,title:d||`Task at line ${r+1}`,assignee:c?c[1]:void 0,estimatedSeconds:l?Ys(l[1]):void 0,priority:r})}return i}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let i=this.store.findById(n);if(!i)return;let r=this.store.update(n,{assignee:i.assignee||e,status:"doing"});if(r.source&&this.daemon){let s=Kn([r.assignee||e],r.source,this.daemon);Ue(r,{assigneeUsernames:s,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(o=>this.log(`[backlog-sync] claim failed for ${n}: ${o?.message??o}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let a={};n.status==="done"?a.status="done":n.status==="blocked"?(a.status="blocked",a.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(a.status="doing"),n.timeSeconds&&(a.estimatedSeconds=n.timeSeconds);let c=this.store.update(e,a);if(c.source&&this.daemon){let l={};n.status==="done"?(l.addLabels=["Done"],l.removeLabels=["Doing"]):n.status==="blocked"&&(l.addLabels=["Blocked"]),n.note&&(l.note=n.note),Object.keys(l).length&&Ue(c,l,this.daemon,this.log).catch(d=>this.log(`[backlog-sync] report failed for ${e}: ${d?.message??d}`))}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(Ke))throw new Error(`backlog line ${i} not a checkbox`);if(n.status==="done"){r[i]=s.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(i+1,0,a)}else n.status==="blocked"?r.splice(i+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(i+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},qe=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(ze(e))for(let i of qs(e)){let r=Js(e,i);Xs(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(He(process.cwd(),this.root),n);let i=[];for(let r of n){let s=Be(r,"utf-8").split(`
131
- `);for(let o=0;o<s.length;o++){let a=s[o].match(Ke);if(!a||a[2].toLowerCase()==="x")continue;let c=a[3].match(ge);!c||c[1].toLowerCase()!==e.toLowerCase()||i.push({id:`wiki:${r}:${o}`,title:a[3].replace(ge,"").trim(),assignee:c[1],priority:o})}}return i}async claim(){}async report(e,n){let i=e.split(":"),r=parseInt(i[i.length-1],10),s=i.slice(1,-1).join(":");if(!ze(s))return;let o=Be(s,"utf-8").split(`
132
- `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),qn(s,o.join(`
133
- `)))}},Xe=class{constructor(e,n,i,r,s){this.host=e;this.token=n;this.projects=i;this.agentUsernames=r;this.log=s}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,i]of Object.entries(this.agentUsernames))if(i.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let i=e.references?.full?.split("#")[0]||n,r=[],s;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(s=e.labels.map(l=>({name:l.name,color:l.color,text_color:l.text_color})),r=s.map(l=>l.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(l=>({username:l.username,name:l.name,avatarUrl:l.avatar_url})),c=a[0]?.username;return{id:`gitlab:${i}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:c?this.usernameToAgent(c)||c:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:s,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let i=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!i.ok)throw new Error(`GitLab ${i.status}: ${await i.text().catch(()=>"")}`);return i.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let i=[],r=this.projects.length?this.projects:["__ALL__"];for(let s of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(s)}&state=opened&scope=all&per_page=20`,c=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,l=await this.api(c);for(let d of l){let u=this.mapIssue(d,o);u.assignee=e,i.push(u)}}catch(a){this.log(`[business] GitLab listOpen failed for ${s} on ${o}: ${a.message}`)}return i}async claim(e,n){let{project:i,iid:r,type:s}=this.parseId(n),o=`/projects/${encodeURIComponent(i)}/${s==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(a){this.log(`[business] claim label update failed: ${a.message}`)}}async report(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),c=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(c)}`,{method:"POST"})}catch(l){this.log(`[business] add_spent_time failed: ${l.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(a){this.log(`[business] done label update failed: ${a.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(a){this.log(`[business] blocked label update failed: ${a.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(a){this.log(`[business] report note failed: ${a.message}`)}}async listAll(e={}){let n=e.sinceDays??30,i=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,s=e.state??"opened";r.set("state",s),r.set("updated_after",i),r.set("scope","all"),r.set("per_page","100"),r.set("with_labels_details","true"),r.set("order_by","updated_at"),r.set("sort","desc"),e.labels?.length&&r.set("labels",e.labels.join(",")),e.milestone&&r.set("milestone",e.milestone),e.search&&r.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],a=[];for(let l of o)try{let d=l==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(l)}/issues?${r.toString()}`,u=await this.api(d);for(let p of u)a.push(this.mapIssue(p,l))}catch(d){this.log(`[business] GitLab listAll failed on ${l}: ${d.message}`)}let c=a;if(e.notLabels?.length){let l=new Set(e.notLabels);c=c.filter(d=>!(d.labels||[]).some(u=>l.has(u)))}if(e.withoutScopedPrefix){let l=e.withoutScopedPrefix+"::";c=c.filter(d=>!(d.labels||[]).some(u=>u.startsWith(l)))}return c}async setState(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:i}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${i}?with_labels_details=true`);return{...this.mapIssue(r,n),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(o=>o.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,n){let{project:i,iid:r}=this.parseId(e),s;n.assigneeUsernames&&(s=(await Promise.all(n.assigneeUsernames.map(async d=>{try{let u=await this.api(`/users?username=${encodeURIComponent(d)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch{return null}}))).filter(d=>typeof d=="number"));let o;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")o=0;else try{let l=await this.api(`/projects/${encodeURIComponent(i)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(o=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${l.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),s!==void 0&&(a.assignee_ids=s),o!==void 0&&(a.milestone_id=o);let c=await this.api(`/projects/${encodeURIComponent(i)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(c,i)}async listMembers(){let e=new Map;for(let n of this.projects)try{let i=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of i)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(i){this.log(`[board] listMembers failed for ${n}: ${i.message}`)}return[...e.values()].sort((n,i)=>n.username.localeCompare(i.username))}async listMilestones(){let e=new Map;for(let i of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(i)}/milestones?per_page=100`);for(let s of r)s.title&&!e.has(s.title)&&e.set(s.title,{id:s.id,title:s.title,state:s.state,dueDate:s.due_date})}catch(r){this.log(`[board] listMilestones failed for ${i}: ${r.message}`)}let n=[...e.values()];return n.sort((i,r)=>i.state!==r.state?i.state==="active"?-1:1:i.title.localeCompare(r.title)),n}async create(e){let n=e.projectHint||this.projects[0];if(!n)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let i,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(i=(await Promise.all(r.map(async l=>{try{let d=await this.api(`/users?username=${encodeURIComponent(l)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch(d){return this.log(`[board] user lookup failed for ${l}: ${d.message}`),null}}))).filter(l=>typeof l=="number"));let s;if(e.milestoneTitle)try{let c=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(s=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${c.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};i?.length&&(o.assignee_ids=i),s!==void 0&&(o.milestone_id=s);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,i){await this.transitionMany(e,n?[n]:[],i?[i]:[])}async transitionMany(e,n,i){let{project:r,iid:s,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",c=new URLSearchParams;n.length&&c.set("add_labels",n.join(",")),i.length&&c.set("remove_labels",i.join(",")),c.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${s}?${c.toString()}`,{method:"PUT"})}parseId(e){let i=e.replace(/^gitlab:/,"").split(":"),r=i.pop(),s=i.pop()==="mr"?"mr":"issue";return{project:i.join(":"),type:s,iid:r}}};function gl(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new Ge(i.path,e,n);case"wiki":return new qe(i.path,i.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let s={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(s[a.agentId]=a.gitlabUsernames);let o=i.projects.length?i.projects:r.routes.map(a=>a.project);return new Xe(r.host,r.token,o,s,n)}}}import{readFileSync as Xn}from"fs";import{homedir as Jn}from"os";import{join as Yn}from"path";var Zn=Yn(Jn(),"Library","DoNotDisturb","DB","Assertions.json"),Qn=Yn(Jn(),".agentx","focus.json");function er(t=Zn,e=Qn){let n=Zs(e);return n.active?n:Qs(t)}function Zs(t=Qn){try{if(JSON.parse(Xn(t,"utf-8"))?.active===!0)return{active:!0,mode:"widget",reason:"holding \u2014 switched on from the widget"}}catch{}return{active:!1,mode:null,reason:"widget hold is off"}}function Qs(t=Zn){let e;try{e=Xn(t,"utf-8")}catch(a){return a?.code==="EPERM"||a?.code==="EACCES"?{active:!1,mode:null,reason:"Focus database not readable \u2014 grant Full Disk Access to the app running agentx"}:{active:!1,mode:null,reason:"no Focus database on this machine"}}let n;try{n=JSON.parse(e)}catch{return{active:!1,mode:null,reason:"Focus database was not readable JSON"}}let r=(Array.isArray(n?.data)?n.data[0]:null)?.storeAssertionRecords;if(!Array.isArray(r)||r.length===0)return{active:!1,mode:null,reason:"no active Focus assertion"};let s=r[0],o=s?.assertionDetails?.assertionDetailsModeIdentifier??s?.assertionDetails?.assertionDetailsModeID??null;return{active:!0,mode:typeof o=="string"?o:null,reason:`Focus assertion present${o?` (${o})`:""}`}}function tr(t){return t.active?t.mode==="widget"?"holding (widget)":t.mode?`in ${(t.mode.split(".").pop()??t.mode).replace(/-/g," ")}`:"in Focus":"not in Focus"}var Je="unmapped";function Ye(t,e=[]){if(!t)return Je;let n=e.find(r=>r.id===t);if(n?.client)return n.client;let i=t.indexOf("/");return i>0?t.slice(0,i):t}function eo(t){let e=new Map,n=t.projects??[],i=t.orgChart??{};for(let s of n)s.pm&&(e.has(s.pm)||e.set(s.pm,Ye(s.id,n)));let r=(s,o=new Set)=>{if(e.has(s))return e.get(s);if(o.has(s))return;o.add(s);let a=i[s]?.reportsTo;if(!a)return;let c=r(a,o);return c&&e.set(s,c),c};for(let s of Object.keys(i))r(s);return e}function to(t,e,n=[]){if(!n.length)return;let i=n.filter(r=>!r.channel||r.channel===t);return i.find(r=>r.chatId&&e.chatId&&r.chatId===e.chatId)??i.find(r=>r.username&&e.username&&r.username===e.username)??i.find(r=>r.senderId&&e.senderId&&r.senderId===e.senderId)??i.find(r=>r.channel&&!r.chatId&&!r.username&&!r.senderId)}function xl(t,e){let n=to(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return Ye(t.project,e.projects);if(t.agentId){let i=eo(e).get(t.agentId);if(i)return i}return Je}function kl(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[i,r,...s]=n,o=s.join(":"),a={agentId:e||i,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var no=t=>t===Je?"internal":"client";function ro(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??no(t),respondWithinMinutes:io(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Sl(t){let e=new Set;for(let n of t.projects??[])e.add(Ye(n.id,t.projects));for(let n of t.contactMap??[])e.add(n.client);for(let n of Object.keys(t.clients??{}))e.add(n);return[...e].sort().map(n=>ro(n,t))}function io(t){let e=/^(\d+)\s*([mhd])$/.exec(String(t??"").trim());if(!e)return;let n=Number(e[1]);return e[2]==="m"?n:e[2]==="h"?n*60:n*1440}var so=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,oo=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function nr(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(oo)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=ao(i);if(!r)return{cleanText:t};let s=n.index??0,o=n[1]??"";return{cleanText:(t.slice(0,s)+o+t.slice(s+n[0].length)).trim(),ui:r}}function $l(t){if(!t||!t.includes("agentx:ui"))return t;let e=so.exec(t);return e?t.slice(0,e.index).trimEnd():t}function ao(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n={};if(Array.isArray(e.buttons)){let i=[],r=[],s=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?i.push({label:o.label,url:o.url}):typeof o.reply=="string"&&o.reply.trim()?r.push({label:o.label,reply:o.reply.trim()}):o.action!=null&&s.push(o.label));i.length&&(n.buttons=i),r.length&&(n.replies=r),s.length&&(n.skippedActions=s)}if(e.poll&&typeof e.poll=="object"){let i=e.poll.question,r=e.poll.options;typeof i=="string"&&i.trim()&&Array.isArray(r)&&r.filter(s=>typeof s=="string").length>=2&&(n.poll={question:i,options:r.filter(s=>typeof s=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:i,url:r,caption:s}=e.media;["image","document","audio","video"].includes(i)&&typeof r=="string"&&r&&(n.media={type:i,url:r,...typeof s=="string"?{caption:s}:{}})}if(Array.isArray(e.quickReplies)){let i=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());i.length&&(n.quickReplies=i)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function Il(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 O(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var rr=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(O)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${O(n)}`}cleanupExpired(){let e=Date.now();for(let[n,i]of this.pending){let r=i.filter(s=>s.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==i.length&&this.pending.set(n,r)}for(let[n,i]of this.recentRings)i<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,i){return this.addSubscriber(e,n,{kind:"sse",res:i})}subscribeInternal(e,n,i){return this.addSubscriber(e,n,{kind:"callback",deliver:i})}addSubscriber(e,n,i){let r={callId:e,recipient:n,sink:i};this.subs.add(r);let s=i.kind==="sse"?"sse":"internal";this.log(`subscribe[${s}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let c=Date.now(),l=a.filter(d=>d.expiresAt>c);for(let{signal:d}of l)this.deliverTo(r,d);this.pending.delete(o),l.length&&this.log(`flushed ${l.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${s}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
125
+ Reinstall in ${Ws}. Agents switch back on their own once it is installed.`}}function Hs(t=er()){if(!Qn(t))return null;try{let e=JSON.parse(Ls(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function qs(t,e){Ps(js(t),{recursive:!0}),Ns(`${t}.tmp`,JSON.stringify(e,null,2)+`
126
+ `),Os(`${t}.tmp`,t)}var Zn=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??er(),s=new Map((Hs(r)?.missing??[]).map(d=>[d.voice,d])),o=Bs(e,n),a=o.map(d=>({...d,since:s.get(d.voice)?.since??i.toISOString(),...s.get(d.voice)?.notifiedAt?{notifiedAt:s.get(d.voice).notifiedAt}:{}})),c=[...s.keys()].filter(d=>!o.some(p=>p.voice===d));for(let d of c)this.deps.log(`[voice] ${Be(d)} is installed again; its agents speak with it again`);c.length&&Un(d=>c.some(p=>d===p||d.endsWith(`:${p}`)));let l=a.filter(d=>!d.notifiedAt);if(l.length){let{title:d,message:p}=zs(l);try{await this.deps.notify(d,p);for(let f of l)f.notifiedAt=i.toISOString();this.deps.log(`[voice] told the owner: ${l.map(f=>Be(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=a.length>0;let u={checkedAt:i.toISOString(),missing:a};return(!Qn(r)||JSON.stringify(a)!==JSON.stringify([...s.values()]))&&qs(r,u),u}finally{this.running=!1}}};import{readFileSync as He,writeFileSync as or,existsSync as qe,readdirSync as to,statSync as no}from"fs";import{resolve as Ke,join as ro}from"path";import{existsSync as tr,mkdirSync as Ks,readFileSync as Gs,writeFileSync as nr}from"fs";import{dirname as Xs,resolve as rr}from"path";import{z as m}from"zod";var Js=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),Ys=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:Js.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),Zs=m.object({version:m.literal(1),items:m.array(Ys).default([])}),ge=class{constructor(e){this.path=e}jsonPath(){return rr(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return rr(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return tr(this.jsonPath())}load(){let e=this.jsonPath();if(!tr(e))return{version:1,items:[]};let n=Gs(e,"utf-8");try{return Zs.parse(JSON.parse(n))}catch(i){throw new Error(`Backlog file invalid (${e}): ${i.message}`)}}save(e){let n=this.jsonPath();Ks(Xs(n),{recursive:!0}),nr(n,JSON.stringify(e,null,2)+`
127
+ `),nr(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(s=>s.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let i=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??i,updatedAt:i};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),i=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),s=[];for(let o of e){if(i.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),s.push(a),i.add(a.id)}return s.length&&this.save(n),s}update(e,n){let i=this.load(),r=i.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let s={...i.items[r],...n,id:i.items[r].id,createdAt:i.items[r].createdAt,updatedAt:new Date().toISOString()};return i.items[r]=s,this.save(i),s}remove(e){let n=this.load(),i=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===i?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],i={doing:[],blocked:[],todo:[],done:[]};for(let s of e.items)i[s.status].push(s);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[s,o]of r)if(i[s].length){n.push(`## ${o}`,"");for(let a of i[s]){let c=s==="done"?"x":" ",l=a.assignee?`@${a.assignee} `:"",u=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",d=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${c}] ${l}${a.title}${u}${d}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
128
+ `)}};function kl(t){return`${t.type}:${t.project}:${t.iid}`}function ir(t,e,n){let i=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.gitlabUsernames?.length?i.push(o.gitlabUsernames[0]):i.push(s)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let s of t){let o=r.find(a=>a.agentId===s);o?.githubUsernames?.length?i.push(o.githubUsernames[0]):i.push(s)}}return i}async function ze(t,e,n,i=()=>{}){return t.source?t.source.type==="gitlab"?Qs(t.source,e,n,i):t.source.type==="github"?eo(t.source,e,n,i):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function Qs(t,e,n,i){let r=n.channels.gitlab,s=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!s||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],c=async(f,g={})=>fetch(`${o}/api/v4${f}`,{...g,headers:{"PRIVATE-TOKEN":s,"Content-Type":"application/json",...g.headers||{}}}),l=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async g=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(g)}`,{headers:{"PRIVATE-TOKEN":s}});if(!h.ok)return null;let y=await h.json();return Array.isArray(y)&&y[0]?.id?y[0].id:null}catch{return null}}))).filter(g=>typeof g=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await c(`/projects/${l}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let g=await f.json();Array.isArray(g)&&g[0]?.id&&(d=g[0].id)}}catch(f){i(`[backlog-sync] milestone lookup failed: ${f.message}`)}let p={};if(e.title!==void 0&&(p.title=e.title),e.description!==void 0&&(p.description=e.description),e.labels!==void 0&&(p.labels=e.labels.join(",")),e.addLabels?.length&&(p.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(p.remove_labels=e.removeLabels.join(",")),u!==void 0&&(p.assignee_ids=u),d!==void 0&&(p.milestone_id=d),e.state&&(p.state_event=e.state==="closed"?"close":"reopen"),Object.keys(p).length)try{let f=await c(`/projects/${l}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(p)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let g=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${g.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await c(`/projects/${l}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function eo(t,e,n,i){let s=n.channels.github?.token;if(!s)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(p,f={})=>fetch(`https://api.github.com${p}`,{...f,headers:{Authorization:`Bearer ${s}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),c=t.project,l;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")l=null;else try{let p=await a(`/repos/${c}/milestones?state=all&per_page=100`);if(p.ok){let f=await p.json(),g=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;g?.number&&(l=g.number)}}catch(p){i(`[backlog-sync] github milestone lookup failed: ${p.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let p=await a(`/repos/${c}/issues/${t.iid}`);if(p.ok){let f=await p.json(),g=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...g,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(p){i(`[backlog-sync] github label fetch failed: ${p.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),l!==void 0&&(d.milestone=l),e.state&&(d.state=e.state),Object.keys(d).length)try{let p=await a(`/repos/${c}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:p.ok,status:p.status}),!p.ok){let f=await p.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${p.status}: ${f.slice(0,200)}`,url:t.url}}}catch(p){return o.push({kind:"PATCH issue",ok:!1,error:p.message}),{ok:!1,attempts:o,error:p.message,url:t.url}}if(e.note)try{let p=await a(`/repos/${c}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:p.ok,status:p.status})}catch(p){o.push({kind:"POST comment",ok:!1,error:p.message})}return{ok:o.every(p=>p.ok),attempts:o,url:t.url}}var Ge=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,me=/@([a-z0-9_-]+)/i,sr=/\[time:\s*([0-9hm\s]+)\]/i;function io(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 Xe=class{constructor(e,n,i=()=>{}){this.path=e;this.daemon=n;this.log=i;this.store=new ge(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Ke(process.cwd(),this.path);return qe(e)?He(e,"utf-8").split(`
129
+ `):[]}writeMd(e){let n=Ke(process.cwd(),this.path);or(n,e.join(`
130
+ `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(s=>s.status!=="done"&&(!s.assignee||s.assignee.toLowerCase()===e.toLowerCase())).map(s=>this.toWorkItem(s));let n=this.readMd(),i=[];for(let r=0;r<n.length;r++){let s=n[r].match(Ge);if(!s||s[2].toLowerCase()==="x")continue;let a=s[3],c=a.match(me);if(c&&c[1].toLowerCase()!==e.toLowerCase())continue;let l=a.match(sr),u=a.replace(me,"").replace(sr,"").trim();i.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:c?c[1]:void 0,estimatedSeconds:l?io(l[1]):void 0,priority:r})}return i}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let i=this.store.findById(n);if(!i)return;let r=this.store.update(n,{assignee:i.assignee||e,status:"doing"});if(r.source&&this.daemon){let s=ir([r.assignee||e],r.source,this.daemon);ze(r,{assigneeUsernames:s,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(o=>this.log(`[backlog-sync] claim failed for ${n}: ${o?.message??o}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let a={};n.status==="done"?a.status="done":n.status==="blocked"?(a.status="blocked",a.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(a.status="doing"),n.timeSeconds&&(a.estimatedSeconds=n.timeSeconds);let c=this.store.update(e,a);if(c.source&&this.daemon){let l={};n.status==="done"?(l.addLabels=["Done"],l.removeLabels=["Doing"]):n.status==="blocked"&&(l.addLabels=["Blocked"]),n.note&&(l.note=n.note),Object.keys(l).length&&ze(c,l,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let i=parseInt(e.slice(8),10),r=this.readMd(),s=r[i];if(!s)throw new Error(`backlog line ${i} missing`);if(!s.match(Ge))throw new Error(`backlog line ${i} not a checkbox`);if(n.status==="done"){r[i]=s.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(i+1,0,a)}else n.status==="blocked"?r.splice(i+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(i+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},Je=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(qe(e))for(let i of to(e)){let r=ro(e,i);no(r).isDirectory()?this.walk(r,n):i.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Ke(process.cwd(),this.root),n);let i=[];for(let r of n){let s=He(r,"utf-8").split(`
131
+ `);for(let o=0;o<s.length;o++){let a=s[o].match(Ge);if(!a||a[2].toLowerCase()==="x")continue;let c=a[3].match(me);!c||c[1].toLowerCase()!==e.toLowerCase()||i.push({id:`wiki:${r}:${o}`,title:a[3].replace(me,"").trim(),assignee:c[1],priority:o})}}return i}async claim(){}async report(e,n){let i=e.split(":"),r=parseInt(i[i.length-1],10),s=i.slice(1,-1).join(":");if(!qe(s))return;let o=He(s,"utf-8").split(`
132
+ `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),or(s,o.join(`
133
+ `)))}},Ye=class{constructor(e,n,i,r,s){this.host=e;this.token=n;this.projects=i;this.agentUsernames=r;this.log=s}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,i]of Object.entries(this.agentUsernames))if(i.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let i=e.references?.full?.split("#")[0]||n,r=[],s;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(s=e.labels.map(l=>({name:l.name,color:l.color,text_color:l.text_color})),r=s.map(l=>l.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(l=>({username:l.username,name:l.name,avatarUrl:l.avatar_url})),c=a[0]?.username;return{id:`gitlab:${i}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:c?this.usernameToAgent(c)||c:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:s,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let i=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!i.ok)throw new Error(`GitLab ${i.status}: ${await i.text().catch(()=>"")}`);return i.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let i=[],r=this.projects.length?this.projects:["__ALL__"];for(let s of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(s)}&state=opened&scope=all&per_page=20`,c=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,l=await this.api(c);for(let u of l){let d=this.mapIssue(u,o);d.assignee=e,i.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${s} on ${o}: ${a.message}`)}return i}async claim(e,n){let{project:i,iid:r,type:s}=this.parseId(n),o=`/projects/${encodeURIComponent(i)}/${s==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(a){this.log(`[business] claim label update failed: ${a.message}`)}}async report(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),c=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(c)}`,{method:"POST"})}catch(l){this.log(`[business] add_spent_time failed: ${l.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(a){this.log(`[business] done label update failed: ${a.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(a){this.log(`[business] blocked label update failed: ${a.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(a){this.log(`[business] report note failed: ${a.message}`)}}async listAll(e={}){let n=e.sinceDays??30,i=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,s=e.state??"opened";r.set("state",s),r.set("updated_after",i),r.set("scope","all"),r.set("per_page","100"),r.set("with_labels_details","true"),r.set("order_by","updated_at"),r.set("sort","desc"),e.labels?.length&&r.set("labels",e.labels.join(",")),e.milestone&&r.set("milestone",e.milestone),e.search&&r.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],a=[];for(let l of o)try{let u=l==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(l)}/issues?${r.toString()}`,d=await this.api(u);for(let p of d)a.push(this.mapIssue(p,l))}catch(u){this.log(`[business] GitLab listAll failed on ${l}: ${u.message}`)}let c=a;if(e.notLabels?.length){let l=new Set(e.notLabels);c=c.filter(u=>!(u.labels||[]).some(d=>l.has(d)))}if(e.withoutScopedPrefix){let l=e.withoutScopedPrefix+"::";c=c.filter(u=>!(u.labels||[]).some(d=>d.startsWith(l)))}return c}async setState(e,n){let{project:i,iid:r,type:s}=this.parseId(e),o=s==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(i)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:i}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${i}?with_labels_details=true`);return{...this.mapIssue(r,n),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(o=>o.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,n){let{project:i,iid:r}=this.parseId(e),s;n.assigneeUsernames&&(s=(await Promise.all(n.assigneeUsernames.map(async u=>{try{let d=await this.api(`/users?username=${encodeURIComponent(u)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch{return null}}))).filter(u=>typeof u=="number"));let o;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")o=0;else try{let l=await this.api(`/projects/${encodeURIComponent(i)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(o=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${l.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),s!==void 0&&(a.assignee_ids=s),o!==void 0&&(a.milestone_id=o);let c=await this.api(`/projects/${encodeURIComponent(i)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(c,i)}async listMembers(){let e=new Map;for(let n of this.projects)try{let i=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of i)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(i){this.log(`[board] listMembers failed for ${n}: ${i.message}`)}return[...e.values()].sort((n,i)=>n.username.localeCompare(i.username))}async listMilestones(){let e=new Map;for(let i of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(i)}/milestones?per_page=100`);for(let s of r)s.title&&!e.has(s.title)&&e.set(s.title,{id:s.id,title:s.title,state:s.state,dueDate:s.due_date})}catch(r){this.log(`[board] listMilestones failed for ${i}: ${r.message}`)}let n=[...e.values()];return n.sort((i,r)=>i.state!==r.state?i.state==="active"?-1:1:i.title.localeCompare(r.title)),n}async create(e){let n=e.projectHint||this.projects[0];if(!n)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let i,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(i=(await Promise.all(r.map(async l=>{try{let u=await this.api(`/users?username=${encodeURIComponent(l)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${l}: ${u.message}`),null}}))).filter(l=>typeof l=="number"));let s;if(e.milestoneTitle)try{let c=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(s=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${c.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};i?.length&&(o.assignee_ids=i),s!==void 0&&(o.milestone_id=s);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,i){await this.transitionMany(e,n?[n]:[],i?[i]:[])}async transitionMany(e,n,i){let{project:r,iid:s,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",c=new URLSearchParams;n.length&&c.set("add_labels",n.join(",")),i.length&&c.set("remove_labels",i.join(",")),c.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${s}?${c.toString()}`,{method:"PUT"})}parseId(e){let i=e.replace(/^gitlab:/,"").split(":"),r=i.pop(),s=i.pop()==="mr"?"mr":"issue";return{project:i.join(":"),type:s,iid:r}}};function Rl(t,e,n){let i=t.workSource;switch(i.type){case"backlog":return new Xe(i.path,e,n);case"wiki":return new Je(i.path,i.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let s={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(s[a.agentId]=a.gitlabUsernames);let o=i.projects.length?i.projects:r.routes.map(a=>a.project);return new Ye(r.host,r.token,o,s,n)}}}var Ze="unmapped";function Qe(t,e=[]){if(!t)return Ze;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 so(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,Qe(s.id,n)));let r=(s,o=new Set)=>{if(e.has(s))return e.get(s);if(o.has(s))return;o.add(s);let a=i[s]?.reportsTo;if(!a)return;let c=r(a,o);return c&&e.set(s,c),c};for(let s of Object.keys(i))r(s);return e}function oo(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 Cl(t,e){let n=oo(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return Qe(t.project,e.projects);if(t.agentId){let i=so(e).get(t.agentId);if(i)return i}return Ze}function Dl(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[i,r,...s]=n,o=s.join(":"),a={agentId:e||i,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var ao=t=>t===Ze?"internal":"client";function co(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??ao(t),respondWithinMinutes:lo(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function El(t){let e=new Set;for(let n of t.projects??[])e.add(Qe(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=>co(n,t))}function lo(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 uo=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,po=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function ar(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(po)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],i=n[2],r=fo(i);if(!r)return{cleanText:t};let s=n.index??0,o=n[1]??"";return{cleanText:(t.slice(0,s)+o+t.slice(s+n[0].length)).trim(),ui:r}}function Pl(t){if(!t||!t.includes("agentx:ui"))return t;let e=uo.exec(t);return e?t.slice(0,e.index).trimEnd():t}function fo(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n={};if(Array.isArray(e.buttons)){let i=[],r=[],s=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?i.push({label:o.label,url:o.url}):typeof o.reply=="string"&&o.reply.trim()?r.push({label:o.label,reply:o.reply.trim()}):o.action!=null&&s.push(o.label));i.length&&(n.buttons=i),r.length&&(n.replies=r),s.length&&(n.skippedActions=s)}if(e.poll&&typeof e.poll=="object"){let i=e.poll.question,r=e.poll.options;typeof i=="string"&&i.trim()&&Array.isArray(r)&&r.filter(s=>typeof s=="string").length>=2&&(n.poll={question:i,options:r.filter(s=>typeof s=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:i,url:r,caption:s}=e.media;["image","document","audio","video"].includes(i)&&typeof r=="string"&&r&&(n.media={type:i,url:r,...typeof s=="string"?{caption:s}:{}})}if(Array.isArray(e.quickReplies)){let i=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());i.length&&(n.quickReplies=i)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function Ol(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 go=5*6e4;function N(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var cr=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],i=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(N)),this.log=i,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${N(n)}`}cleanupExpired(){let e=Date.now();for(let[n,i]of this.pending){let r=i.filter(s=>s.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==i.length&&this.pending.set(n,r)}for(let[n,i]of this.recentRings)i<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,i){return this.addSubscriber(e,n,{kind:"sse",res:i})}subscribeInternal(e,n,i){return this.addSubscriber(e,n,{kind:"callback",deliver:i})}addSubscriber(e,n,i){let r={callId:e,recipient:n,sink:i};this.subs.add(r);let s=i.kind==="sse"?"sse":"internal";this.log(`subscribe[${s}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let c=Date.now(),l=a.filter(u=>u.expiresAt>c);for(let{signal:u}of l)this.deliverTo(r,u);this.pending.delete(o),l.length&&this.log(`flushed ${l.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${s}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
134
134
  data: ${JSON.stringify(n)}
135
135
 
136
- `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=O(e.to);if(n===O(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&&O(i.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(O(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=O(e.to);for(let r of this.subs)r.callId===e.callId&&O(r.recipient)===i&&(this.deliverTo(r,e)?n++:this.subs.delete(r));return n}get subscriberCount(){return this.subs.size}shutdown(){this.cleanupTimer&&clearInterval(this.cleanupTimer);for(let e of this.subs)if(e.sink.kind==="sse")try{e.sink.res.end()}catch{}this.subs.clear(),this.pending.clear()}};import{execFile as Ro}from"child_process";import{mkdtempSync as xo,rmSync as ko,writeFileSync as So}from"fs";import{tmpdir as vo}from"os";import{join as cr}from"path";import{randomBytes as lo}from"crypto";var D={top:8,side:32,bottom:60},Ze={height:56,keep:52},ir=`
136
+ `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=N(e.to);if(n===N(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let i of this.subs)if(i.callId===e&&N(i.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(N(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let i=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>i)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,i+go),this.ringHandler)try{this.ringHandler(e)}catch(s){this.log(`ringHandler threw: ${s.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let i=this.pendingKey(e.callId,e.to),r=this.pending.get(i)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(i,r),this.log(`buffered ${e.kind} for call=${e.callId} to=${e.to} (no subscriber yet, ${r.length} pending)`)}return{ok:!0}}fanOut(e){let n=0,i=N(e.to);for(let r of this.subs)r.callId===e.callId&&N(r.recipient)===i&&(this.deliverTo(r,e)?n++:this.subs.delete(r));return n}get subscriberCount(){return this.subs.size}shutdown(){this.cleanupTimer&&clearInterval(this.cleanupTimer);for(let e of this.subs)if(e.sink.kind==="sse")try{e.sink.res.end()}catch{}this.subs.clear(),this.pending.clear()}};import{execFile as To}from"child_process";import{mkdtempSync as Io,rmSync as Ao,writeFileSync as Ro}from"fs";import{tmpdir as _o}from"os";import{join as fr}from"path";import{randomBytes as mo}from"crypto";var D={top:8,side:32,bottom:60},et={height:56,keep:52},lr=`
137
137
  :root {
138
138
  --ac-paper: #fafaf9; --ac-soft: #f4f4f2; --ac-edge: #e9e9e6;
139
139
  --ac-text: #0b1413; --ac-muted: #4a5856; --ac-subtle: #7c8987;
@@ -262,33 +262,33 @@ button.primary:hover:not(:disabled) { transform: translateY(-1px); background: v
262
262
  button.primary:disabled { opacity: .55; cursor: not-allowed; }
263
263
  kbd { font: 11px var(--ac-mono); color: var(--ac-subtle); }
264
264
  button.primary kbd { color: inherit; opacity: .7; }
265
- `;var sr=t=>t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),or=t=>`${t.getDate()} ${t.toLocaleDateString("en-US",{month:"short"})}`;function uo(t,e){let n=new Date(t);return Number.isNaN(n.getTime())?"":`since ${n.toDateString()===new Date(e).toDateString()?sr(n):or(n)}`}function po(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[or(n)],sr(n)].join(" ")}function fo(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 go(t){let e=(t.recommend??"").trim(),n=e.toLowerCase(),i=t.choices??[],r=-1;if(i.forEach((o,a)=>{!n.startsWith(o.toLowerCase())||!/^\s*($|[:,.;–—-](\s|$))/.test(e.slice(o.length))||(r<0||o.length>i[r].length)&&(r=a)}),r<0)return{index:r,why:e};let s=e.slice(i[r].length).replace(/^[\s:,.;–—-]+/,"");return{index:r,why:s.slice(0,1).toUpperCase()+s.slice(1)}}function mo(t){return t.draft?"Send":t.choices?.length?"Choose":"Yes"}var Qe=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>`,ho=Qe('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),yo=Qe('<path d="m6 15 6-6 6 6"/>'),bo=Qe('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function ar(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=lo(12).toString("base64"),s=t.choices??[],o=t.origin?.kind==="reminder",a=go(t),c=s.map((u,p)=>`<button class="opt" role="radio" aria-checked="false" data-i="${p}"><span class="n">${p+1}</span><span class="t">${x(u)}</span>${p===a.index?'<i class="dot"></i>':""}</button>`).join(""),l=t.recommend?`<span class="rec"><i class="dot"></i>${x(i)} recommends</span>`:"",d={choices:s,draft:t.draft??"",placeholder:It,chime:e.sound==="chime",volume:Math.min(1,Math.max(0,e.volume??.4)),theme:e.theme??"system",pick:e.pick&&e.pick<=s.length?e.pick-1:a.index};return`<!doctype html>
265
+ `;var ur=t=>t.toLocaleTimeString("en-GB",{hour:"2-digit",minute:"2-digit"}),dr=t=>`${t.getDate()} ${t.toLocaleDateString("en-US",{month:"short"})}`;function ho(t,e){let n=new Date(t);return Number.isNaN(n.getTime())?"":`since ${n.toDateString()===new Date(e).toDateString()?ur(n):dr(n)}`}function yo(t,e){let n=new Date(t),i=n.getTime()-e<6*864e5;return[n.toLocaleDateString("en-US",{weekday:"short"}),...i?[]:[dr(n)],ur(n)].join(" ")}function bo(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 wo(t){let e=(t.recommend??"").trim(),n=e.toLowerCase(),i=t.choices??[],r=-1;if(i.forEach((o,a)=>{!n.startsWith(o.toLowerCase())||!/^\s*($|[:,.;–—-](\s|$))/.test(e.slice(o.length))||(r<0||o.length>i[r].length)&&(r=a)}),r<0)return{index:r,why:e};let s=e.slice(i[r].length).replace(/^[\s:,.;–—-]+/,"");return{index:r,why:s.slice(0,1).toUpperCase()+s.slice(1)}}function ko(t){return t.draft?"Send":t.choices?.length?"Choose":"Yes"}var tt=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>`,xo=tt('<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>'),So=tt('<path d="m6 15 6-6 6 6"/>'),vo=tt('<rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/>');function pr(t,e={}){let n=e.now??Date.now(),i=e.from||t.raised_by,r=mo(12).toString("base64"),s=t.choices??[],o=t.origin?.kind==="reminder",a=wo(t),c=s.map((d,p)=>`<button class="opt" role="radio" aria-checked="false" data-i="${p}"><span class="n">${p+1}</span><span class="t">${k(d)}</span>${p===a.index?'<i class="dot"></i>':""}</button>`).join(""),l=t.recommend?`<span class="rec"><i class="dot"></i>${k(i)} recommends</span>`:"",u={choices:s,draft:t.draft??"",placeholder:Nt,chime:e.sound==="chime",volume:Math.min(1,Math.max(0,e.volume??.4)),theme:e.theme??"system",pick:e.pick&&e.pick<=s.length?e.pick-1:a.index};return`<!doctype html>
266
266
  <html lang="en"><head><meta charset="utf-8">
267
267
  <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; script-src 'nonce-${r}'">
268
268
  <title>AgentX</title>
269
- <style>${ir}</style></head>
269
+ <style>${lr}</style></head>
270
270
  <body><div class="wrap"><main class="card${e.still?" still":""}">
271
- <div class="head" title="Drag to move"><span class="avatar">${x(fo(i))}</span>
272
- <div class="who"><b>${x(i)}</b><span>${x(uo(t.created_at,n))}</span></div>
271
+ <div class="head" title="Drag to move"><span class="avatar">${k(bo(i))}</span>
272
+ <div class="who"><b>${k(i)}</b><span>${k(ho(t.created_at,n))}</span></div>
273
273
  <span class="kind${o?"":" decision"}">${o?"Reminder":"Decision"}</span>
274
- <button class="fold" id="fold" title="Shrink" aria-label="Shrink the card" aria-expanded="true">${yo}</button></div>
275
- <div class="body"><h1 dir="auto">${x(t.title)}</h1>
276
- ${t.context?`<p class="context" dir="auto">${x(t.context)}</p>`:""}
277
- <p class="ask" dir="auto">${x(t.ask)}</p>
274
+ <button class="fold" id="fold" title="Shrink" aria-label="Shrink the card" aria-expanded="true">${So}</button></div>
275
+ <div class="body"><h1 dir="auto">${k(t.title)}</h1>
276
+ ${t.context?`<p class="context" dir="auto">${k(t.context)}</p>`:""}
277
+ <p class="ask" dir="auto">${k(t.ask)}</p>
278
278
  ${c||l?`<div class="label-row">${c?'<span class="label">Pick one</span>':""}${l}</div>`:""}
279
279
  ${c?`<div class="options" role="radiogroup">${c}</div>`:""}
280
- ${a.why?`<p class="why" dir="auto">${x(a.why)}</p>`:""}
280
+ ${a.why?`<p class="why" dir="auto">${k(a.why)}</p>`:""}
281
281
  ${t.draft?`<div class="label-row" id="msg"><span class="label">Message</span><span class="edited"><i class="dot"></i>Edited</span><button class="reset" id="reset">Reset</button></div>
282
282
  <textarea id="text" dir="auto" rows="2" spellcheck="true"></textarea>`:""}
283
- <div class="notes"><div>${ho}<span>If you don't answer by ${x(po(t.expires,n))}: ${x(t.if_silent)}.</span></div>
284
- <div>${bo}<span>Nothing goes out until you click.</span></div></div>
283
+ <div class="notes"><div>${xo}<span>If you don't answer by ${k(yo(t.expires,n))}: ${k(t.if_silent)}.</span></div>
284
+ <div>${vo}<span>Nothing goes out until you click.</span></div></div>
285
285
  </div><div class="foot"><button class="btn later" id="later">Not now<kbd>esc</kbd></button>
286
286
  <button class="btn" id="no">No</button>
287
- <button class="btn primary" id="yes">${mo(t)}<kbd>\u2318\u21A9</kbd></button></div>
287
+ <button class="btn primary" id="yes">${ko(t)}<kbd>\u2318\u21A9</kbd></button></div>
288
288
  </main></div>
289
- <script type="application/json" id="data">${JSON.stringify(d).replace(/</g,"\\u003c")}</script>
290
- <script nonce="${r}">${wo}</script>
291
- </body></html>`}var wo=`
289
+ <script type="application/json" id="data">${JSON.stringify(u).replace(/</g,"\\u003c")}</script>
290
+ <script nonce="${r}">${$o}</script>
291
+ </body></html>`}var $o=`
292
292
  (function () {
293
293
  var d = JSON.parse(document.getElementById("data").textContent);
294
294
  var root = document.documentElement;
@@ -377,10 +377,10 @@ ${t.draft?`<div class="label-row" id="msg"><span class="label">Message</span><sp
377
377
  });
378
378
  } catch (e) {}
379
379
  })();
380
- `;var $o=440,Ao=`
380
+ `;var Co=440,Do=`
381
381
  ObjC.import("Cocoa"); ObjC.import("WebKit")
382
382
  function run(argv) {
383
- var path = argv[0], side = ${D.side}, gripTop = ${D.top}, gripEnd = ${D.top+Ze.height}, keep = ${Ze.keep}, w = Number(argv[1]) + 2 * side, h = 420, secs = Number(argv[2]), capture = argv[3] || ""
383
+ var path = argv[0], side = ${D.side}, gripTop = ${D.top}, gripEnd = ${D.top+et.height}, keep = ${et.keep}, w = Number(argv[1]) + 2 * side, h = 420, secs = Number(argv[2]), capture = argv[3] || ""
384
384
  var app = $.NSApplication.sharedApplication
385
385
  app.setActivationPolicy($.NSApplicationActivationPolicyAccessory)
386
386
  ObjC.registerSubclass({ name: "AgentXCardView", superclass: "WKWebView", methods: {
@@ -450,21 +450,21 @@ function run(argv) {
450
450
  }
451
451
  function gone(why) { return JSON.stringify({ action: "dismiss", why: why }) }
452
452
  function quoted(s) { return "'" + String(s).replace(/'/g, "'\\\\''") + "'" }
453
- `;function Io(t,e){let n=t.trim().split(`
454
- `).pop()??"",i;try{i=JSON.parse(n)}catch{return{action:"dismiss"}}if(i?.action==="no")return{action:"no"};if(i?.action==="dismiss"&&dr.includes(i.why))return{action:"dismiss",why:i.why};if(i?.action!=="yes")return{action:"dismiss"};let r=e.choices??[],s;if(r.length){if(typeof i.choice!="string"||!r.includes(i.choice))return{action:"dismiss"};s=i.choice}let o;return e.draft&&(o=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
455
- `).trim():"",!o||o.length>At.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...o?{text:o}:{}}}async function lr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=xo(cr(vo(),"agentx-card-"));try{let s=cr(r,"card.html");So(s,ar(t,{...e,still:!!e.capture}),{mode:384});let o=["-l","JavaScript","-e",Ao,s,String($o),String(i),...e.capture?[e.capture]:[]],a=await n("/usr/bin/osascript",o,(i+10)*1e3);return a.ok?Io(a.stdout,t):null}finally{ko(r,{recursive:!0,force:!0})}}var dr=["not now","timed out","closed"],_o=(t,e,n)=>new Promise(i=>{try{Ro(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),ur=160,pr=15e3;function Co(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>ur?e.slice(0,ur):e}async function Do(t,e,n,i){let r=e.sound==="chime"?i?"":"Glass":e.sound,s=r?Ot(r):null;if(s&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),s],pr),e.speak){let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",Co(t)],pr)}}function mr(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function Eo(t,e,n){return mr(["on run argv","activate","set opts to items 3 thru -1 of argv",'set pick to choose from list opts with title (item 1 of argv) with prompt (item 2 of argv) OK button name "Next" cancel button name "Not now"','if pick is false then return ""',"return item 1 of pick","end run"],[t,e,...n])}function fr(t,e,n,i,r){return mr(["on run argv","activate","set AppleScript's text item delimiters to linefeed","set btns to text items of (item 3 of argv)","set secs to (item 5 of argv) as integer","if (count of argv) > 5 then","set r to display dialog (item 2 of argv) with title (item 1 of argv) default answer (item 6 of argv) buttons btns default button (item 4 of argv) giving up after secs","else","set r to display dialog (item 2 of argv) with title (item 1 of argv) buttons btns default button (item 4 of argv) giving up after secs","end if",'if gave up of r then return ""',"if (count of argv) > 5 then return (button returned of r) & linefeed & (text returned of r)","return button returned of r","end run"],[t,e,n.join(`
456
- `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function gr(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
457
- `);return n<0?{button:e,text:""}:{button:e.slice(0,n),text:e.slice(n+1)}}function et(t){return[t.ask,t.recommend?`Recommended: ${t.recommend}`:"",`From ${t.raised_by}`].filter(Boolean).join(`
453
+ `;function Eo(t,e){let n=t.trim().split(`
454
+ `).pop()??"",i;try{i=JSON.parse(n)}catch{return{action:"dismiss"}}if(i?.action==="no")return{action:"no"};if(i?.action==="dismiss"&&mr.includes(i.why))return{action:"dismiss",why:i.why};if(i?.action!=="yes")return{action:"dismiss"};let r=e.choices??[],s;if(r.length){if(typeof i.choice!="string"||!r.includes(i.choice))return{action:"dismiss"};s=i.choice}let o;return e.draft&&(o=typeof i.text=="string"?i.text.replace(/\r\n?/g,`
455
+ `).trim():"",!o||o.length>Ot.text)?{action:"dismiss"}:{action:"yes",...s?{choice:s}:{},...o?{text:o}:{}}}async function gr(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=Io(fr(_o(),"agentx-card-"));try{let s=fr(r,"card.html");Ro(s,pr(t,{...e,still:!!e.capture}),{mode:384});let o=["-l","JavaScript","-e",Do,s,String(Co),String(i),...e.capture?[e.capture]:[]],a=await n("/usr/bin/osascript",o,(i+10)*1e3);return a.ok?Eo(a.stdout,t):null}finally{Ao(r,{recursive:!0,force:!0})}}var mr=["not now","timed out","closed"],Po=(t,e,n)=>new Promise(i=>{try{To(t,e,{timeout:n},(r,s)=>i({ok:!r,stdout:String(s??"")}))}catch{i({ok:!1,stdout:""})}}),hr=160,yr=15e3;function Lo(t){let e=(t.say||t.title).replace(/\s+/g," ").trim();return e.length>hr?e.slice(0,hr):e}async function Oo(t,e,n,i){let r=e.sound==="chime"?i?"":"Glass":e.sound,s=r?Ht(r):null;if(s&&await n("/usr/bin/afplay",["-v",String(Math.min(1,Math.max(0,e.volume))),s],yr),e.speak){let o=e.voice&&/^[\w .()-]+$/.test(e.voice)?["-v",e.voice]:[];await n("/usr/bin/say",[...o,"--",Lo(t)],yr)}}function kr(t,e){return[...t.flatMap(n=>["-e",n]),...e]}function No(t,e,n){return kr(["on run argv","activate","set opts to items 3 thru -1 of argv",'set pick to choose from list opts with title (item 1 of argv) with prompt (item 2 of argv) OK button name "Next" cancel button name "Not now"','if pick is false then return ""',"return item 1 of pick","end run"],[t,e,...n])}function br(t,e,n,i,r){return kr(["on run argv","activate","set AppleScript's text item delimiters to linefeed","set btns to text items of (item 3 of argv)","set secs to (item 5 of argv) as integer","if (count of argv) > 5 then","set r to display dialog (item 2 of argv) with title (item 1 of argv) default answer (item 6 of argv) buttons btns default button (item 4 of argv) giving up after secs","else","set r to display dialog (item 2 of argv) with title (item 1 of argv) buttons btns default button (item 4 of argv) giving up after secs","end if",'if gave up of r then return ""',"if (count of argv) > 5 then return (button returned of r) & linefeed & (text returned of r)","return button returned of r","end run"],[t,e,n.join(`
456
+ `),n[n.length-1],String(i),...r!==void 0?[r]:[]])}function wr(t){let e=t.replace(/\n$/,"");if(!e)return null;let n=e.indexOf(`
457
+ `);return n<0?{button:e,text:""}:{button:e.slice(0,n),text:e.slice(n+1)}}function nt(t){return[t.ask,t.recommend?`Recommended: ${t.recommend}`:"",`From ${t.raised_by}`].filter(Boolean).join(`
458
458
 
459
- `)}async function hr(t,e,n={}){let i=n.run??_o,r=(e.style??"card")==="card",s=Do(t,e,i,r).catch(()=>{});if(r){let o=await lr(t,{timeoutSeconds:e.timeoutSeconds,sound:e.sound,volume:e.volume,theme:e.theme,from:n.from,capture:n.capture,pick:n.pick},i).catch(()=>null);if(o)return o}return await s,To(t,e,i)}async function To(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=(i+5)*1e3,s=`${t.raised_by}: ${t.title}`,o;if(t.choices?.length){let l=await n("/usr/bin/osascript",Eo(s,et(t),t.choices),r);if(o=l.stdout.replace(/\n$/,""),!l.ok||!t.choices.includes(o))return{action:"dismiss"};if(!t.draft)return{action:"yes",choice:o}}if(t.draft){let l=o?`${o}
459
+ `)}async function xr(t,e,n={}){let i=n.run??Po,r=(e.style??"card")==="card",s=Oo(t,e,i,r).catch(()=>{});if(r){let o=await gr(t,{timeoutSeconds:e.timeoutSeconds,sound:e.sound,volume:e.volume,theme:e.theme,from:n.from,capture:n.capture,pick:n.pick},i).catch(()=>null);if(o)return o}return await s,Mo(t,e,i)}async function Mo(t,e,n){let i=Math.max(10,Math.round(e.timeoutSeconds)),r=(i+5)*1e3,s=`${t.raised_by}: ${t.title}`,o;if(t.choices?.length){let l=await n("/usr/bin/osascript",No(s,nt(t),t.choices),r);if(o=l.stdout.replace(/\n$/,""),!l.ok||!t.choices.includes(o))return{action:"dismiss"};if(!t.draft)return{action:"yes",choice:o}}if(t.draft){let l=o?`${o}
460
460
 
461
- Message (edit it if you like):`:`${et(t)}
461
+ Message (edit it if you like):`:`${nt(t)}
462
462
 
463
- Message (edit it if you like):`,u=await n("/usr/bin/osascript",fr(s,l,o?["Cancel","Send"]:["Not now","No","Send"],i,_t(t.draft,o)),r),p=u.ok?gr(u.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...o?{choice:o}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let a=await n("/usr/bin/osascript",fr(s,et(t),["Not now","No","Yes"],i),r),c=a.ok?gr(a.stdout):null;return c?.button==="Yes"?{action:"yes"}:c?.button==="No"?{action:"no"}:{action:"dismiss"}}var Lo=24*36e5,tt=!1;function Po(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=C(t.root),o=r?Date.parse(r):NaN,a=P(t.root,"pending").filter(l=>Date.parse(l.expires)>e),c=a.find(l=>s.includes(`card:${l.id}`));if(c)return c;for(let l of a){let d=`card:${l.id}`;if(n[d])continue;let u=i[d];if(u&&Date.parse(u)>e)continue;let p=Date.parse(l.created_at);if(!(e-p>Lo&&!(p<=o)))return l}return null}async function Zl(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(tt)return"busy";let r=Po(e);if(!r)return"none";let s=(t.focus??er)();if(s.active)return"held";tt=!0;let o=`card:${r.id}`;try{let a=P(e.root,"pending").map(d=>`card:${d.id}`);ln(e.root,o,a,e.now),i(`[approvals] popup: showing ${o} from ${r.raised_by}`);let c=await(t.show??hr)(r,n,{from:t.agentName?.(r.raised_by)});if(c.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${c.why??"no answer"} (${tr(s)} when shown)`),"shown";if(L(e.root,r.id)?.status!=="pending")return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let l=await mn(e,o,c.action,{by:"operator (popup)",...c.action==="yes"?{choice:c.choice,text:c.text}:{}});return i(l.ok?`[approvals] popup: ${l.message}`:`[approvals] popup: ${o} not recorded: ${l.error}`),"shown"}catch(a){return i(`[approvals] popup failed for ${o}: ${a?.message??a}`),"shown"}finally{tt=!1}}function Ql(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:")?L(t.root,e.slice(5)):null;return i?i.status!=="pending"?{ok:!1,error:`${e} is already ${i.status}`}:(dn(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 Oo,fstatSync as No,openSync as Mo,realpathSync as yr}from"fs";import{isAbsolute as jo,resolve as br,sep as wr}from"path";var sd="/app-files",Vo=/^[A-Za-z0-9_.:-]{1,64}$/;function Fo(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 ${ke}/ first`};if(!xe(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=yr(br(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=yr(jo(e)?e:br(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+wr))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${ke}/ first`};let s=xe(r);return s?{ok:!0,path:r,...s}:{ok:!1,status:415,error:"this type of file is not served"}}function Wo(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 Uo(t,e,n){return{"Content-Type":t,"Content-Disposition":Wo(e,n),"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; img-src 'self'; media-src 'self'; sandbox","Cache-Control":"private, max-age=3600","Accept-Ranges":"bytes"}}function Bo(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let i,r;return n[1]?(i=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(i=Math.max(0,e-Number(n[2])),r=e-1),i>r||i>=e?"unsatisfiable":{start:i,end:r}}function od(t,e,n,i){let r=(T,V)=>{e.writeHead(T,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(V))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let s=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!Vo.test(s))return r(400,{error:"bad agent id"});let a=i.workspaceOf(s);if(!a)return r(404,{error:`no agent "${s}" on this computer`});let c=Fo(a,o,i.cwd);if(!c.ok)return i.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${s}: ${c.error}`),r(c.status,{error:c.error});let l;try{l=Mo(c.path,"r")}catch{return r(404,{error:"file not found"})}let d;try{let T=No(l);if(!T.isFile())return J(l),r(404,{error:"not a file"});d=T.size}catch{return J(l),r(404,{error:"file not found"})}if(d>ne.bytes)return J(l),r(413,{error:`the file is larger than ${ne.bytes/1024/1024} MB`});let u=c.path.split(wr).pop()||"file",p=Uo(c.mime,u,c.kind),f=Bo(t.headers.range,d);if(f==="unsatisfiable"){J(l),e.writeHead(416,{...p,"Content-Range":`bytes */${d}`}),e.end();return}let{start:g,end:h}=f??{start:0,end:d-1};if(e.writeHead(f?206:200,{...p,"Content-Length":String(d?h-g+1:0),...f?{"Content-Range":`bytes ${g}-${h}/${d}`}:{}}),t.method==="HEAD"||d===0){J(l),e.end();return}let y=Oo("",{fd:l,start:g,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as Y}from"child_process";import{readFileSync as zo,writeFileSync as Ho}from"fs";import{tmpdir as Ko}from"os";import{join as Go}from"path";mt();var xr=t=>t&&t!==1?Math.round(175*t):null,me=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function qo(){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=zo(t,"utf8").trim();if(e)return e}catch{}return null}function md(t=qo()){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=Go(Ko(),`agentx-say-${process.pid}-${++e}.mp3`);return Ho(s,Buffer.from(await r.arrayBuffer())),s}catch(r){if(i.aborted||!n.voice.fallback)throw r;return M(`elevenlabs:${String(r?.message??r).slice(0,40)}`,`[voice] ElevenLabs failed (${String(r?.message??r).slice(0,160)}); speaking with the system voice`),null}}}function kr(t,e){let n=t.languages&&te(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var Xo=(t,e="")=>{let n=kr(t,e),i=xr(t.rate);return[...n&&!Sn(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function Jo(t,e,n){if(!n)return["say",Xo(t,e)];let i=kr(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function hd(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function yd(t=nt()){if(t)try{Y("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function bd(t=nt()){if(t)try{Y("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function nt(t={},e){if(!De(t))return null;try{return An(e)}catch(n){return M("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
464
- `)[0]}); Siri voices will not switch`),null}}var wd=(t,e)=>{if(!t){let[n,i]=Jo(e.voice,e.text,nt()),r=xr(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=Y(n,i,{stdio:["pipe","ignore","ignore"],env:s});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?Y("afplay",[t],{stdio:"ignore"}):Y("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Sr}from"child_process";import{accessSync as Yo,constants as Zo,readFileSync as vr}from"fs";import{homedir as Qo}from"os";import{basename as z,delimiter as $r,dirname as ea,extname as ta,join as rt}from"path";var N={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Ar(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)>N.ms+2e3?{status:413,error:st()}:null}var st=()=>`The recording is longer than ${N.ms/6e4} minutes.`,na={"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 Ir(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return na[e]??null}function Rr(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 ot(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 it(t,e,n=process.env.PATH??""){let i=Qo(),r=[rt(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split($r).filter(Boolean)];for(let s of[e,...r.map(o=>rt(o,t))])if(s)try{return Yo(s,Zo.X_OK),s}catch{}return null}function Ad(t){return{key:t,mlx:it("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:it("whisper",process.env.AGENTX_WHISPER),ffmpeg:ra()}}var ra=()=>it("ffmpeg",process.env.AGENTX_FFMPEG);async function _r(t,e){return e?ia(t,e):null}async function ia(t,e){let n=String(N.ms/1e3+5);try{let r=[...(await sa(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 Cr(t,e,n,i){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([vr(t)],{type:e}),z(t));let s=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:i??AbortSignal.timeout(6e4)});if(!s.ok)throw new Error(`ElevenLabs ${s.status}: ${(await s.text().catch(()=>"")).slice(0,160)}`);let o=await s.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Dr(t,e,n,i,r){let s=t==="mlx-whisper"?["--model",process.env.AGENTX_MLX_MODEL||"mlx-community/whisper-large-v3-turbo","--output-format","txt","--output-dir",r,n]:[n,"--model",process.env.AGENTX_WHISPER_MODEL||"base","--output_format","txt","--output_dir",r,"--fp16","False"],o={...process.env,PATH:`${ea(i)}${$r}${process.env.PATH??""}`};await oa(e,s,12e4,o);try{return vr(rt(r,z(n,ta(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function sa(t,e,n){return new Promise((i,r)=>{let s=Sr(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${z(t)} took too long`))},n);s.stderr.on("data",c=>{o=(o+c).slice(-8192)}),s.on("error",c=>{clearTimeout(a),r(c)}),s.on("exit",c=>{clearTimeout(a),c===0?i(o):r(new Error(`${z(t)} exited ${c}`))})})}function oa(t,e,n,i=process.env){return new Promise((r,s)=>{let o=Sr(t,e,{stdio:["ignore","pipe","pipe"],env:i}),a="",c="",l=setTimeout(()=>{o.kill("SIGKILL"),s(new Error(`${z(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",d=>{a.length<4096&&(a+=d)}),o.stderr.on("data",d=>{c.length<4096&&(c+=d)}),o.on("error",d=>{clearTimeout(l),s(d)}),o.on("exit",d=>{clearTimeout(l),d===0?r(a):s(new Error(`${z(t)} exited ${d}: ${c.trim().split(`
465
- `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as aa,rm as ca,writeFile as la}from"fs/promises";import{tmpdir as da}from"os";import{join as Er}from"path";Fr();var ua=64*1024,pa=2,at=0;function Nd(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function Md(t,e,n,i){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?fa(t,e,i):ha(t,e,i)}async function fa(t,e,n){let i=String(t.headers["content-type"]||""),r=Ir(i);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=Ar(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),b(e,s.status,{error:s.error});let o=await Tr(t,N.bytes);if(!o)return b(e,413,{error:wa()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(at>=pa)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),c=n.host(),l=Rr(a,c);if(!c.ffmpeg&&!n.allowUnmeasured?.()){let u=n.nodeName?`on ${n.nodeName}`:"on this computer",p=l.length?"":" "+ot(a,c);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${u} for voice input from the phone.${p}`,setup:!1})}if(!l.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:ot(a,c),setup:!1});at++;let d;try{let u=await aa(Er(da(),"agentx-phone-voice-"));try{d=await ga(u,`speech.${r}`,o,i,c,l,n)}finally{await ca(u,{recursive:!0,force:!0}).catch(()=>{})}}finally{at--}b(e,d[0],d[1])}async function ga(t,e,n,i,r,s,o){let a=Er(t,e);if(await la(a,n,{mode:384}),r.ffmpeg){let l=await(o.measure??_r)(a,r.ffmpeg);if(l==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(l*1e3>N.ms+2e3)return[413,{error:st()}]}let c=[];for(let l of s)try{let d=await ma(l,a,i,r,t,o);return o.log(`[voice] phone recording transcribed with ${l} (${Math.round(n.length/1024)} KB)`),d?[200,{text:d,engine:l}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:l}]}catch(d){let u=String(d?.message??d).split(`
466
- `)[0].slice(0,200);c.push(`${l}: ${u}`),o.log(`[voice] phone transcription with ${l} failed: ${u}`)}return[502,{error:"Speech to text failed on this computer.",detail:c.join("; ")}]}function ma(t,e,n,i,r,s){let o=s.engines?.[t];if(o)return o(e,n,i,r);if(t==="elevenlabs")return Cr(e,n,i.key);let a=t==="mlx-whisper"?i.mlx:i.whisper;return Dr(t,a,e,i.ffmpeg,r)}async function ha(t,e,n){let i=await Tr(t,ua);if(!i)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(i.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let s=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!s)return b(e,400,{error:"agent is required"});let a=ya(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let c=n.voiceOf(s,o);if(!c)return b(e,404,{error:`Unknown agent: ${s}`});let l=(u,p=200)=>b(e,p,{fallback:"browser",reason:u,text:a});if(c.provider!=="elevenlabs")return l("This agent speaks with a system voice, which only plays on the computer.");let d=n.elevenLabsKey();if(!d)return l("No ElevenLabs key is set on this computer.");try{let u=await(n.synth??ba)(d,c,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":u.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(u)}catch(u){return n.log(`[voice] phone answer synthesis failed: ${String(u?.message??u).split(`
467
- `)[0].slice(0,160)}`),l("ElevenLabs could not speak this answer.",502)}}function ya(t,e){let n=nr(wt(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return ht(n,e)}async function ba(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 wa=()=>`The recording is larger than ${N.bytes/1024/1024} MB, more than ${N.ms/6e4} minutes of speech.`;function jd(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Fe(Me(t,r,n.voice)):null}function Tr(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,i)=>{let r=[],s=0;t.on("data",o=>{if(!(s>e)){if(s+=o.length,s>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{s<=e&&n(Buffer.concat(r))}),t.on("error",i)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as $,readFileSync as ut,writeFileSync as pt,mkdirSync as he,readdirSync as dt,rmSync as xa,statSync as R}from"fs";import{resolve as Lr,relative as ka,dirname as ft,join as j,extname as Z,basename as gt}from"path";var S=200*1024,Pr=new Set([".md",".markdown",".txt"]),H=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"]),Sa=6,va=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function E(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Lr(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=Lr(n,e);if(ka(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Or(t){let e=Z(t).toLowerCase();if(!Pr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function ct(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function Ud(t){let e=E(t,"."),n=[],i=new Set,r=[];try{r=dt(e)}catch{}for(let a of va){let c=j(e,a);if($(c)&&R(c).isFile()){let l=R(c).size,d=l>0&&l<S?lt(c):"";n.push({path:a,title:ct(d,a),size:l,exists:!0}),i.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),i.add(a)}for(let a of r){if(i.has(a))continue;let c=j(e,a);try{let l=R(c);if(!l.isFile()||!Pr.has(Z(a).toLowerCase()))continue;let d=l.size>0&&l.size<S?lt(c):"";n.push({path:a,title:ct(d,a),size:l.size,exists:!0})}catch{}}let s=[],o=j(e,".claude","skills");if($(o))try{for(let a of dt(o)){let c=j(o,a),l;try{l=R(c)}catch{continue}if(!l.isDirectory())continue;let d=j(c,"SKILL.md");if(!$(d))continue;let u=R(d),p=u.size<S?lt(d):"";s.push({slug:a,title:ct(p,a),size:u.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return s.sort((a,c)=>a.slug.localeCompare(c.slug)),{identity:n,skills:s,workspace:e}}function lt(t){try{return ut(t,"utf-8")}catch{return""}}function Bd(t,e){let n=E(t,e);if(Or(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:ut(n,"utf-8")}}function zd(t,e,n){let i=E(t,e);Or(i);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return he(ft(i),{recursive:!0}),pt(i,r),{path:e,bytes:r.length}}function Hd(t,e,n={}){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Skill slug must be lowercase (letters, digits, -, _) and start with a letter or digit.");let i=`.claude/skills/${e}/SKILL.md`,r=E(t,i);if($(r))throw new Error(`Skill "${e}" already exists.`);he(ft(r),{recursive:!0});let s=n.content?.trim()?n.content:$a(e,n.title);return pt(r,s),{slug:e,path:i}}function Kd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);if(!R(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return xa(n,{recursive:!0,force:!0}),{slug:e}}function Gd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=[];return r(n,"",0,i),i.sort((s,o)=>s.kind!==o.kind?s.kind==="dir"?-1:1:s.path.localeCompare(o.path)),i;function r(s,o,a,c){if(a>Sa)return;let l=[];try{l=dt(s)}catch{return}for(let d of l){if(d==="node_modules"||d===".git")continue;let u=j(s,d),p=o?`${o}/${d}`:d,f;try{f=R(u)}catch{continue}if(f.isDirectory())c.push({path:`${p}/`,kind:"dir",size:0,editable:!1}),r(u,p,a+1,c);else if(f.isFile()){let g=Z(d).toLowerCase(),h=H.has(g)||H.has(d.toLowerCase());c.push({path:p,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function qd(t,e,n){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let i=E(t,`.claude/skills/${e}/${n}`);if(!$(i)||!R(i).isFile())throw new Error(`File not found: ${n}`);let r=Z(i).toLowerCase(),s=gt(i).toLowerCase();if(!H.has(r)&&!H.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:ut(i,"utf-8")}}function Xd(t,e,n,i){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let r=E(t,`.claude/skills/${e}/${n}`),s=Z(r).toLowerCase(),o=gt(r).toLowerCase();if(!H.has(s)&&!H.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(i,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return he(ft(r),{recursive:!0}),pt(r,a),{path:n,bytes:a.length}}function Jd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=r=>$(j(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 $a(t,e){return`# ${e?.trim()||t}
463
+ Message (edit it if you like):`,d=await n("/usr/bin/osascript",br(s,l,o?["Cancel","Send"]:["Not now","No","Send"],i,jt(t.draft,o)),r),p=d.ok?wr(d.stdout):null;if(p?.button==="Send"){let f=p.text.trim();return f?{action:"yes",...o?{choice:o}:{},text:f}:{action:"dismiss"}}return p?.button==="No"?{action:"no"}:{action:"dismiss"}}let a=await n("/usr/bin/osascript",br(s,nt(t),["Not now","No","Yes"],i),r),c=a.ok?wr(a.stdout):null;return c?.button==="Yes"?{action:"yes"}:c?.button==="No"?{action:"no"}:{action:"dismiss"}}var jo=24*36e5,rt=!1;function Vo(t){let e=t.now??Date.now(),{popped:n={},snoozed:i,passAt:r,wanted:s=[]}=C(t.root),o=r?Date.parse(r):NaN,a=L(t.root,"pending").filter(l=>Date.parse(l.expires)>e),c=a.find(l=>s.includes(`card:${l.id}`));if(c)return c;for(let l of a){let u=`card:${l.id}`;if(n[u])continue;let d=i[u];if(d&&Date.parse(d)>e)continue;let p=Date.parse(l.created_at);if(!(e-p>jo&&!(p<=o)))return l}return null}async function au(t){let{ctx:e,settings:n,log:i}=t;if(!n.enabled||(t.platform??process.platform)!=="darwin")return"off";if(rt)return"busy";let r=Vo(e);if(!r)return"none";let s=(t.focus??_t)();if(s.active)return"held";rt=!0;let o=`card:${r.id}`;try{let a=L(e.root,"pending").map(u=>`card:${u.id}`);wn(e.root,o,a,e.now),i(`[approvals] popup: showing ${o} from ${r.raised_by}`);let c=await(t.show??xr)(r,n,{from:t.agentName?.(r.raised_by)});if(c.action==="dismiss")return i(`[approvals] popup: ${o} left waiting: ${c.why??"no answer"} (${Ct(s)} when shown)`),"shown";if(P(e.root,r.id)?.status!=="pending")return i(`[approvals] popup: ${o} was answered elsewhere; popup answer ignored`),"shown";let l=await Rn(e,o,c.action,{by:"operator (popup)",...c.action==="yes"?{choice:c.choice,text:c.text}:{}});return i(l.ok?`[approvals] popup: ${l.message}`:`[approvals] popup: ${o} not recorded: ${l.error}`),"shown"}catch(a){return i(`[approvals] popup failed for ${o}: ${a?.message??a}`),"shown"}finally{rt=!1}}function cu(t,e,n){if(!n)return{ok:!1,error:"the Mac popup is off; turn it on with `agentx approvals settings --popup on`"};let i=e.startsWith("card:")?P(t.root,e.slice(5)):null;return i?i.status!=="pending"?{ok:!1,error:`${e} is already ${i.status}`}:(kn(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 Wo,fstatSync as Fo,openSync as Uo,realpathSync as Sr}from"fs";import{isAbsolute as Bo,resolve as vr,sep as $r}from"path";var gu="/app-files",zo=/^[A-Za-z0-9_.:-]{1,64}$/;function Ho(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 ${ve}/ first`};if(!Se(e))return{ok:!1,status:415,error:"this type of file is not served"};let i;try{i=Sr(vr(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=Sr(Bo(e)?e:vr(i,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(i+$r))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${ve}/ first`};let s=Se(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 Ko(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 Go(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 mu(t,e,n,i){let r=(T,F)=>{e.writeHead(T,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(F))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let s=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!zo.test(s))return r(400,{error:"bad agent id"});let a=i.workspaceOf(s);if(!a)return r(404,{error:`no agent "${s}" on this computer`});let c=Ho(a,o,i.cwd);if(!c.ok)return i.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${s}: ${c.error}`),r(c.status,{error:c.error});let l;try{l=Uo(c.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let T=Fo(l);if(!T.isFile())return J(l),r(404,{error:"not a file"});u=T.size}catch{return J(l),r(404,{error:"file not found"})}if(u>ne.bytes)return J(l),r(413,{error:`the file is larger than ${ne.bytes/1024/1024} MB`});let d=c.path.split($r).pop()||"file",p=Ko(c.mime,d,c.kind),f=Go(t.headers.range,u);if(f==="unsatisfiable"){J(l),e.writeHead(416,{...p,"Content-Range":`bytes */${u}`}),e.end();return}let{start:g,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...p,"Content-Length":String(u?h-g+1:0),...f?{"Content-Range":`bytes ${g}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){J(l),e.end();return}let y=Wo("",{fd:l,start:g,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as Y}from"child_process";import{readFileSync as Xo,writeFileSync as Jo}from"fs";import{tmpdir as Yo}from"os";import{join as Zo}from"path";yt();var Ir=t=>t&&t!==1?Math.round(175*t):null,he=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function Qo(){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=Xo(t,"utf8").trim();if(e)return e}catch{}return null}function $u(t=Qo()){let e=0;return async(n,i)=>{if(n.voice.provider==="system")return null;if(!t){if(n.voice.fallback)return null;throw new Error("ElevenLabs is the voice provider but no key is set")}try{let r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${n.voice.elevenlabs}/stream?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n.text,model_id:"eleven_flash_v2_5",...he(n.voice.rate)?{voice_settings:{speed:he(n.voice.rate)}}:{}}),signal:i});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let s=Zo(Yo(),`agentx-say-${process.pid}-${++e}.mp3`);return Jo(s,Buffer.from(await r.arrayBuffer())),s}catch(r){if(i.aborted||!n.voice.fallback)throw r;return V(`elevenlabs:${String(r?.message??r).slice(0,40)}`,`[voice] ElevenLabs failed (${String(r?.message??r).slice(0,160)}); speaking with the system voice`),null}}}function Ar(t,e){let n=t.languages&&te(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var ea=(t,e="")=>{let n=Ar(t,e),i=Ir(t.rate);return[...n&&!Ln(n)?["-v",n]:[],...i?["-r",String(i)]:[]]};function ta(t,e,n){if(!n)return["say",ea(t,e)];let i=Ar(t,e);return["/bin/sh",[n,...i?[i]:[]]]}function Iu(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Au(t=it()){if(t)try{Y("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Ru(t=it()){if(t)try{Y("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function it(t={},e){if(!Te(t))return null;try{return Mn(e)}catch(n){return V("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
464
+ `)[0]}); Siri voices will not switch`),null}}var _u=(t,e)=>{if(!t){let[n,i]=ta(e.voice,e.text,it()),r=Ir(e.voice.rate),s=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=Y(n,i,{stdio:["pipe","ignore","ignore"],env:s});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?Y("afplay",[t],{stdio:"ignore"}):Y("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Rr}from"child_process";import{accessSync as na,constants as ra,readFileSync as _r}from"fs";import{homedir as ia}from"os";import{basename as H,delimiter as Cr,dirname as sa,extname as oa,join as st}from"path";var M={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Dr(t){let e=Array.isArray(t)?t[0]:t;return!e||!/^\d{1,9}$/.test(e.trim())?{status:400,error:"Say how long the recording is (X-Audio-Duration-Ms)."}:Number(e)>M.ms+2e3?{status:413,error:at()}:null}var at=()=>`The recording is longer than ${M.ms/6e4} minutes.`,aa={"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 Er(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return aa[e]??null}function Tr(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 ct(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 ot(t,e,n=process.env.PATH??""){let i=ia(),r=[st(i,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Cr).filter(Boolean)];for(let s of[e,...r.map(o=>st(o,t))])if(s)try{return na(s,ra.X_OK),s}catch{}return null}function Lu(t){return{key:t,mlx:ot("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:ot("whisper",process.env.AGENTX_WHISPER),ffmpeg:ca()}}var ca=()=>ot("ffmpeg",process.env.AGENTX_FFMPEG);async function Pr(t,e){return e?la(t,e):null}async function la(t,e){let n=String(M.ms/1e3+5);try{let r=[...(await ua(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 Lr(t,e,n,i){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([_r(t)],{type:e}),H(t));let s=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:i??AbortSignal.timeout(6e4)});if(!s.ok)throw new Error(`ElevenLabs ${s.status}: ${(await s.text().catch(()=>"")).slice(0,160)}`);let o=await s.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Or(t,e,n,i,r){let s=t==="mlx-whisper"?["--model",process.env.AGENTX_MLX_MODEL||"mlx-community/whisper-large-v3-turbo","--output-format","txt","--output-dir",r,n]:[n,"--model",process.env.AGENTX_WHISPER_MODEL||"base","--output_format","txt","--output_dir",r,"--fp16","False"],o={...process.env,PATH:`${sa(i)}${Cr}${process.env.PATH??""}`};await da(e,s,12e4,o);try{return _r(st(r,H(n,oa(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function ua(t,e,n){return new Promise((i,r)=>{let s=Rr(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{s.kill("SIGKILL"),r(new Error(`${H(t)} took too long`))},n);s.stderr.on("data",c=>{o=(o+c).slice(-8192)}),s.on("error",c=>{clearTimeout(a),r(c)}),s.on("exit",c=>{clearTimeout(a),c===0?i(o):r(new Error(`${H(t)} exited ${c}`))})})}function da(t,e,n,i=process.env){return new Promise((r,s)=>{let o=Rr(t,e,{stdio:["ignore","pipe","pipe"],env:i}),a="",c="",l=setTimeout(()=>{o.kill("SIGKILL"),s(new Error(`${H(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{c.length<4096&&(c+=u)}),o.on("error",u=>{clearTimeout(l),s(u)}),o.on("exit",u=>{clearTimeout(l),u===0?r(a):s(new Error(`${H(t)} exited ${u}: ${c.trim().split(`
465
+ `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as pa,rm as fa,writeFile as ga}from"fs/promises";import{tmpdir as ma}from"os";import{join as Nr}from"path";Hr();var ha=64*1024,ya=2,lt=0;function Hu(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function qu(t,e,n,i){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?ba(t,e,i):xa(t,e,i)}async function ba(t,e,n){let i=String(t.headers["content-type"]||""),r=Er(i);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let s=Dr(t.headers["x-audio-duration-ms"]);if(s)return t.resume(),b(e,s.status,{error:s.error});let o=await Mr(t,M.bytes);if(!o)return b(e,413,{error:$a()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(lt>=ya)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),c=n.host(),l=Tr(a,c);if(!c.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",p=l.length?"":" "+ct(a,c);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${p}`,setup:!1})}if(!l.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:ct(a,c),setup:!1});lt++;let u;try{let d=await pa(Nr(ma(),"agentx-phone-voice-"));try{u=await wa(d,`speech.${r}`,o,i,c,l,n)}finally{await fa(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{lt--}b(e,u[0],u[1])}async function wa(t,e,n,i,r,s,o){let a=Nr(t,e);if(await ga(a,n,{mode:384}),r.ffmpeg){let l=await(o.measure??Pr)(a,r.ffmpeg);if(l==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(l*1e3>M.ms+2e3)return[413,{error:at()}]}let c=[];for(let l of s)try{let u=await ka(l,a,i,r,t,o);return o.log(`[voice] phone recording transcribed with ${l} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:l}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:l}]}catch(u){let d=String(u?.message??u).split(`
466
+ `)[0].slice(0,200);c.push(`${l}: ${d}`),o.log(`[voice] phone transcription with ${l} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:c.join("; ")}]}function ka(t,e,n,i,r,s){let o=s.engines?.[t];if(o)return o(e,n,i,r);if(t==="elevenlabs")return Lr(e,n,i.key);let a=t==="mlx-whisper"?i.mlx:i.whisper;return Or(t,a,e,i.ffmpeg,r)}async function xa(t,e,n){let i=await Mr(t,ha);if(!i)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(i.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let s=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!s)return b(e,400,{error:"agent is required"});let a=Sa(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let c=n.voiceOf(s,o);if(!c)return b(e,404,{error:`Unknown agent: ${s}`});let l=(d,p=200)=>b(e,p,{fallback:"browser",reason:d,text:a});if(c.provider!=="elevenlabs")return l("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return l("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??va)(u,c,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(d)}catch(d){return n.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
467
+ `)[0].slice(0,160)}`),l("ElevenLabs could not speak this answer.",502)}}function Sa(t,e){let n=ar(Rt(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return bt(n,e)}async function va(t,e,n){let i=he(e.rate),r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(e.elevenlabs)}?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n,model_id:"eleven_flash_v2_5",...i?{voice_settings:{speed:i}}:{}}),signal:AbortSignal.timeout(6e4)});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text().catch(()=>"")).slice(0,160)}`);return Buffer.from(await r.arrayBuffer())}var $a=()=>`The recording is larger than ${M.bytes/1024/1024} MB, more than ${M.ms/6e4} minutes of speech.`;function Ku(t,e,n,i){if(e)return i.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Ue(Ve(t,r,n.voice)):null}function Mr(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,i)=>{let r=[],s=0;t.on("data",o=>{if(!(s>e)){if(s+=o.length,s>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{s<=e&&n(Buffer.concat(r))}),t.on("error",i)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as $,readFileSync as ft,writeFileSync as gt,mkdirSync as ye,readdirSync as pt,rmSync as Ia,statSync as R}from"fs";import{resolve as jr,relative as Aa,dirname as mt,join as W,extname as Z,basename as ht}from"path";var S=200*1024,Vr=new Set([".md",".markdown",".txt"]),q=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),Ra=6,_a=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function E(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=jr(t);if($(n)||ye(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let i=jr(n,e);if(Aa(n,i).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return i}function Wr(t){let e=Z(t).toLowerCase();if(!Vr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function ut(t,e){let n=t.split(/\r?\n/).find(i=>i.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function Yu(t){let e=E(t,"."),n=[],i=new Set,r=[];try{r=pt(e)}catch{}for(let a of _a){let c=W(e,a);if($(c)&&R(c).isFile()){let l=R(c).size,u=l>0&&l<S?dt(c):"";n.push({path:a,title:ut(u,a),size:l,exists:!0}),i.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),i.add(a)}for(let a of r){if(i.has(a))continue;let c=W(e,a);try{let l=R(c);if(!l.isFile()||!Vr.has(Z(a).toLowerCase()))continue;let u=l.size>0&&l.size<S?dt(c):"";n.push({path:a,title:ut(u,a),size:l.size,exists:!0})}catch{}}let s=[],o=W(e,".claude","skills");if($(o))try{for(let a of pt(o)){let c=W(o,a),l;try{l=R(c)}catch{continue}if(!l.isDirectory())continue;let u=W(c,"SKILL.md");if(!$(u))continue;let d=R(u),p=d.size<S?dt(u):"";s.push({slug:a,title:ut(p,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return s.sort((a,c)=>a.slug.localeCompare(c.slug)),{identity:n,skills:s,workspace:e}}function dt(t){try{return ft(t,"utf-8")}catch{return""}}function Zu(t,e){let n=E(t,e);if(Wr(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:ft(n,"utf-8")}}function Qu(t,e,n){let i=E(t,e);Wr(i);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return ye(mt(i),{recursive:!0}),gt(i,r),{path:e,bytes:r.length}}function ed(t,e,n={}){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Skill slug must be lowercase (letters, digits, -, _) and start with a letter or digit.");let i=`.claude/skills/${e}/SKILL.md`,r=E(t,i);if($(r))throw new Error(`Skill "${e}" already exists.`);ye(mt(r),{recursive:!0});let s=n.content?.trim()?n.content:Ca(e,n.title);return gt(r,s),{slug:e,path:i}}function td(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);if(!R(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return Ia(n,{recursive:!0,force:!0}),{slug:e}}function nd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=[];return r(n,"",0,i),i.sort((s,o)=>s.kind!==o.kind?s.kind==="dir"?-1:1:s.path.localeCompare(o.path)),i;function r(s,o,a,c){if(a>Ra)return;let l=[];try{l=pt(s)}catch{return}for(let u of l){if(u==="node_modules"||u===".git")continue;let d=W(s,u),p=o?`${o}/${u}`:u,f;try{f=R(d)}catch{continue}if(f.isDirectory())c.push({path:`${p}/`,kind:"dir",size:0,editable:!1}),r(d,p,a+1,c);else if(f.isFile()){let g=Z(u).toLowerCase(),h=q.has(g)||q.has(u.toLowerCase());c.push({path:p,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function rd(t,e,n){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let i=E(t,`.claude/skills/${e}/${n}`);if(!$(i)||!R(i).isFile())throw new Error(`File not found: ${n}`);let r=Z(i).toLowerCase(),s=ht(i).toLowerCase();if(!q.has(r)&&!q.has(s))throw new Error(`File type not editable: ${n}`);if(R(i).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:ft(i,"utf-8")}}function id(t,e,n,i){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let r=E(t,`.claude/skills/${e}/${n}`),s=Z(r).toLowerCase(),o=ht(r).toLowerCase();if(!q.has(s)&&!q.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(i,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return ye(mt(r),{recursive:!0}),gt(r,a),{path:n,bytes:a.length}}function sd(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=E(t,`.claude/skills/${e}`);if(!$(n))throw new Error(`Skill "${e}" not found.`);let i=r=>$(W(n,r));return i("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:i("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:i("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:i("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:i("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function Ca(t,e){return`# ${e?.trim()||t}
468
468
 
469
469
  Describe what this skill does and when the agent should use it. Keep it under ~5 lines \u2014 the agent reads this to decide whether to invoke the skill.
470
470
 
@@ -477,7 +477,7 @@ Document the arguments, commands, or files the skill expects. Example:
477
477
 
478
478
  \`\`\`bash
479
479
  # Example invocation
480
- claude-code ${gt(t)} --arg value
480
+ claude-code ${ht(t)} --arg value
481
481
  \`\`\`
482
- `}Wr();var Nr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Mr(t){return{...Nr,...t??{},regions:{...t?.regions??{}},buffer:{...Nr.buffer,...t?.buffer??{}}}}function Qd(t){try{return Mr(yt(t).screen)}catch{return Mr(void 0)}}var Aa=/^[a-z][\w-]*$/,jr=["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 ye=(t,e)=>Q(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function Vr(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 eu(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=ye(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=ye(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=ye(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Q(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Q(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,o]of Object.entries(e.regions)){if(!Aa.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);o===null?delete r[s]:r[s]=Vr(o)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,s={...n.buffer??{}};"enabled"in r&&(s.enabled=!!r.enabled),"seconds"in r&&(s.seconds=Q(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Q(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=ye(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&&!jr.includes(i)&&!n.regions?.[i])try{Vr(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...jr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{er as a,tr as b,Nt as c,_a as d,Ye as e,eo as f,to as g,xl as h,kl as i,Sl as j,nr as k,$l as l,Il as m,O as n,rr as o,k as p,Ta as q,zt as r,Ma as s,Ht as t,ja as u,tn as v,I as w,F as x,rn as y,L as z,ec as A,tc as B,nc as C,rc as D,ic as E,Wa as F,wi as G,Ga as H,Qt as I,C as J,lc as K,dc as L,kc as M,mn as N,hr as O,Zl as P,Ql as Q,sd as R,Uo as S,od as T,vc as U,$c as V,Ac as W,Ic as X,Rc as Y,_c as Z,Dc as _,Ec as $,Fc as aa,Le as ba,Wc as ca,Uc as da,q as ea,X as fa,qo as ga,md as ha,hd as ia,yd as ja,bd as ka,nt as la,wd as ma,Ne as na,Me as oa,pe as pa,bs as qa,xs as ra,Gc as sa,Ve as ta,Fe as ua,ks as va,Ss as wa,On as xa,Vn as ya,qc as za,As as Aa,Xc as Ba,Ls as Ca,Ns as Da,We as Ea,js as Fa,Fn as Ga,N as Ha,Ar as Ia,Ir as Ja,Rr as Ka,Ad as La,ra as Ma,Cr as Na,Dr as Oa,Nd as Pa,Md as Qa,wa as Ra,jd as Sa,Tr as Ta,fe as Ua,al as Va,Kn as Wa,Ue as Xa,Xe as Ya,gl as Za,Ud as _a,Bd as $a,zd as ab,Hd as bb,Kd as cb,Gd as db,qd as eb,Xd as fb,Jd as gb,Nr as hb,Mr as ib,Qd as jb,jr as kb,eu as lb};
483
- //# sourceMappingURL=chunk-5RRORS5S.js.map
482
+ `}xt();var Fr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Ur(t){return{...Fr,...t??{},regions:{...t?.regions??{}},buffer:{...Fr.buffer,...t?.buffer??{}}}}function cd(t){try{return Ur(kt(t).screen)}catch{return Ur(void 0)}}var Da=/^[a-z][\w-]*$/,Br=["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 zr(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 ld(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=be(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=be(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=be(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=Q(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=Q(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[s,o]of Object.entries(e.regions)){if(!Da.test(s))throw new Error(`region name "${s}" must be lowercase letters, digits, - or _`);o===null?delete r[s]:r[s]=zr(o)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,s={...n.buffer??{}};"enabled"in r&&(s.enabled=!!r.enabled),"seconds"in r&&(s.seconds=Q(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(s.fps=Q(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(s.maxPixels=be(r.maxPixels,"buffer.maxPixels")),"region"in r&&(s.region=String(r.region).trim()),n.buffer=s}let i=n.buffer?.region;if(i!==void 0&&!Br.includes(i)&&!n.regions?.[i])try{zr(i)}catch{throw new Error(`buffer.region "${i}" is not a region \u2014 use ${[...Br,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{qt as a,Pa as b,Qe as c,so as d,oo as e,Cl as f,Dl as g,El as h,ar as i,Pl as j,Ol as k,N as l,cr as m,x as n,Ma as o,en as p,Ua as q,tn as r,Ba as s,pn as t,A as u,U as v,gn as w,P as x,sc as y,oc as z,ac as A,cc as B,lc as C,qa as D,vi as E,Za as F,un as G,C as H,gc as I,mc as J,xn as K,kc as L,In as M,Lc as N,Rn as O,xr as P,au as Q,cu as R,gu as S,Ko as T,mu as U,Nc as V,Mc as W,jc as X,Vc as Y,Wc as Z,Fc as _,Bc as $,zc as aa,Qc as ba,Oe as ca,el as da,tl as ea,G as fa,X as ga,Qo as ha,$u as ia,Iu as ja,Au as ka,Ru as la,it as ma,_u as na,je as oa,Ve as pa,fe as qa,Is as ra,Rs as sa,ol as ta,Fe as ua,Ue as va,_s as wa,Cs as xa,Kn as ya,Yn as za,al as Aa,Ts as Ba,cl as Ca,Ws as Da,Bs as Ea,Be as Fa,Hs as Ga,Zn as Ha,M as Ia,Dr as Ja,Er as Ka,Tr as La,Lu as Ma,ca as Na,Lr as Oa,Or as Pa,Hu as Qa,qu as Ra,$a as Sa,Ku as Ta,Mr as Ua,ge as Va,kl as Wa,ir as Xa,ze as Ya,Ye as Za,Rl as _a,Yu as $a,Zu as ab,Qu as bb,ed as cb,td as db,nd as eb,rd as fb,id as gb,sd as hb,Fr as ib,Ur as jb,cd as kb,Br as lb,ld as mb};
483
+ //# sourceMappingURL=chunk-Z6G26FWC.js.map