agentix-cli 0.76.0 → 0.78.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 (118) hide show
  1. package/dist/{App-NCTXMA2P.js → App-UNWLWLH5.js} +2 -2
  2. package/dist/{ChatApp-CQIQEKZ2.js → ChatApp-UBSOVFRK.js} +2 -2
  3. package/dist/{agent-5GQLISLJ.js → agent-XWWWL5RV.js} +2 -2
  4. package/dist/{board-dashboard-E4CXJUK5.js → board-dashboard-ABEIELBC.js} +4 -4
  5. package/dist/{chunk-7GC42WAK.js → chunk-2XICJMS6.js} +31 -31
  6. package/dist/chunk-2XICJMS6.js.map +1 -0
  7. package/dist/{chunk-GT6ZDLXU.js → chunk-4EJ65BMF.js} +509 -238
  8. package/dist/chunk-4EJ65BMF.js.map +1 -0
  9. package/dist/{chunk-A4ACRRRP.js → chunk-4STRKIUA.js} +2 -2
  10. package/dist/{chunk-SC6Q5M4C.js → chunk-53J2D2ZJ.js} +2 -2
  11. package/dist/{chunk-PK6EBDBU.js → chunk-6HUDHMAC.js} +2 -2
  12. package/dist/{chunk-LQRBGQIR.js → chunk-CL53UVOF.js} +11 -11
  13. package/dist/chunk-CL53UVOF.js.map +1 -0
  14. package/dist/{chunk-62EJKQFX.js → chunk-CPXZWVKN.js} +2 -2
  15. package/dist/{chunk-SZZSUW42.js → chunk-DBXN7I2X.js} +5 -5
  16. package/dist/{chunk-SZZSUW42.js.map → chunk-DBXN7I2X.js.map} +1 -1
  17. package/dist/{chunk-URINHGJF.js → chunk-FSVUSXJB.js} +155 -155
  18. package/dist/chunk-FSVUSXJB.js.map +1 -0
  19. package/dist/{chunk-CW42OBFL.js → chunk-FWDWHZ6H.js} +2 -2
  20. package/dist/{chunk-IYLQBBON.js → chunk-GTZDTKDW.js} +2 -2
  21. package/dist/{chunk-2KOWJNQJ.js → chunk-GX4U2ILS.js} +2 -2
  22. package/dist/{chunk-N3Y3NORE.js → chunk-H4RCKWJA.js} +2 -2
  23. package/dist/{chunk-LQ3PEMBH.js → chunk-IMVW5ZSY.js} +2 -2
  24. package/dist/{chunk-72P53PGX.js → chunk-JQXP3JWF.js} +2 -2
  25. package/dist/{chunk-EAMSULHF.js → chunk-JVJYCR67.js} +2 -2
  26. package/dist/{chunk-B556VD7A.js → chunk-KEPK7ZZ2.js} +2 -2
  27. package/dist/{chunk-QGTQ4PIL.js → chunk-LQJNRSCT.js} +2 -2
  28. package/dist/{chunk-ZPM7SSJM.js → chunk-NWP44FEW.js} +2 -2
  29. package/dist/{chunk-C4CDVE2E.js → chunk-O5U5NVLR.js} +9 -9
  30. package/dist/chunk-O5U5NVLR.js.map +1 -0
  31. package/dist/{chunk-P27P7GFY.js → chunk-R7AS5M32.js} +5 -5
  32. package/dist/{chunk-676OIOHG.js → chunk-SLQZ4AHG.js} +39 -39
  33. package/dist/chunk-SLQZ4AHG.js.map +1 -0
  34. package/dist/{chunk-PDSCFOC4.js → chunk-TVORP6BW.js} +2 -2
  35. package/dist/{chunk-MODPTVA6.js → chunk-U6XM4M5V.js} +2 -2
  36. package/dist/{chunk-SY7ENNNK.js → chunk-WEUF5WRR.js} +2 -2
  37. package/dist/chunk-Y4CYQV7G.js +3 -0
  38. package/dist/chunk-Y4CYQV7G.js.map +1 -0
  39. package/dist/cli.js +1 -1
  40. package/dist/client-OAAE3KM5.js +2 -0
  41. package/dist/{config-QLCPWIJN.js → config-44LINWKG.js} +2 -2
  42. package/dist/config-mutator-P6QEABPU.js +2 -0
  43. package/dist/{doctor-74P5CWVW.js → doctor-OXR3VXX6.js} +2 -2
  44. package/dist/index.d.ts +131 -17
  45. package/dist/index.js +1 -1
  46. package/dist/processes-5EXCTSD5.js +2 -0
  47. package/dist/program-X7ROPRQP.js +2 -0
  48. package/dist/{promote-VFL66JD2.js → promote-72BY34SI.js} +2 -2
  49. package/dist/{query-MCCWN6XA.js → query-AJO3NOO6.js} +2 -2
  50. package/dist/{registry-43X3DQTI.js → registry-AFNYREN2.js} +2 -2
  51. package/dist/{request-planner-GSGBUGNG.js → request-planner-Q74NYFRJ.js} +2 -2
  52. package/dist/{review-candidates-4Z6QTMN2.js → review-candidates-ZBBIPFJT.js} +2 -2
  53. package/dist/{routing-T66LO3JY.js → routing-7VU524EZ.js} +2 -2
  54. package/dist/schedule-tool-6RRXRW5K.js +2 -0
  55. package/dist/scheduler-WA4KTCCU.js +2 -0
  56. package/dist/{seat-4H7TTV5X.js → seat-MKY332GD.js} +2 -2
  57. package/dist/{select-YCVNOR5Q.js → select-FZX63JK5.js} +2 -2
  58. package/dist/{set-enabled-6UGUPYW4.js → set-enabled-RNDSUIYU.js} +2 -2
  59. package/dist/{tool-EID3ZKQK.js → tool-XBSFEGWW.js} +3 -3
  60. package/dist/tool-XBSFEGWW.js.map +1 -0
  61. package/dist/wiki-ZOK6XGIX.js +2 -0
  62. package/package.json +1 -1
  63. package/dist/chunk-676OIOHG.js.map +0 -1
  64. package/dist/chunk-7GC42WAK.js.map +0 -1
  65. package/dist/chunk-C4CDVE2E.js.map +0 -1
  66. package/dist/chunk-GT6ZDLXU.js.map +0 -1
  67. package/dist/chunk-LQRBGQIR.js.map +0 -1
  68. package/dist/chunk-R5BXA7TL.js +0 -3
  69. package/dist/chunk-R5BXA7TL.js.map +0 -1
  70. package/dist/chunk-URINHGJF.js.map +0 -1
  71. package/dist/client-HLCKITQJ.js +0 -2
  72. package/dist/config-mutator-BCTMKRPT.js +0 -2
  73. package/dist/processes-TGFDGQYY.js +0 -2
  74. package/dist/program-ONWCNXKS.js +0 -2
  75. package/dist/schedule-tool-ORNG6HMN.js +0 -2
  76. package/dist/scheduler-VIWJITKR.js +0 -2
  77. package/dist/tool-EID3ZKQK.js.map +0 -1
  78. package/dist/wiki-SHHIVZPT.js +0 -2
  79. /package/dist/{App-NCTXMA2P.js.map → App-UNWLWLH5.js.map} +0 -0
  80. /package/dist/{ChatApp-CQIQEKZ2.js.map → ChatApp-UBSOVFRK.js.map} +0 -0
  81. /package/dist/{agent-5GQLISLJ.js.map → agent-XWWWL5RV.js.map} +0 -0
  82. /package/dist/{board-dashboard-E4CXJUK5.js.map → board-dashboard-ABEIELBC.js.map} +0 -0
  83. /package/dist/{chunk-A4ACRRRP.js.map → chunk-4STRKIUA.js.map} +0 -0
  84. /package/dist/{chunk-SC6Q5M4C.js.map → chunk-53J2D2ZJ.js.map} +0 -0
  85. /package/dist/{chunk-PK6EBDBU.js.map → chunk-6HUDHMAC.js.map} +0 -0
  86. /package/dist/{chunk-62EJKQFX.js.map → chunk-CPXZWVKN.js.map} +0 -0
  87. /package/dist/{chunk-CW42OBFL.js.map → chunk-FWDWHZ6H.js.map} +0 -0
  88. /package/dist/{chunk-IYLQBBON.js.map → chunk-GTZDTKDW.js.map} +0 -0
  89. /package/dist/{chunk-2KOWJNQJ.js.map → chunk-GX4U2ILS.js.map} +0 -0
  90. /package/dist/{chunk-N3Y3NORE.js.map → chunk-H4RCKWJA.js.map} +0 -0
  91. /package/dist/{chunk-LQ3PEMBH.js.map → chunk-IMVW5ZSY.js.map} +0 -0
  92. /package/dist/{chunk-72P53PGX.js.map → chunk-JQXP3JWF.js.map} +0 -0
  93. /package/dist/{chunk-EAMSULHF.js.map → chunk-JVJYCR67.js.map} +0 -0
  94. /package/dist/{chunk-B556VD7A.js.map → chunk-KEPK7ZZ2.js.map} +0 -0
  95. /package/dist/{chunk-QGTQ4PIL.js.map → chunk-LQJNRSCT.js.map} +0 -0
  96. /package/dist/{chunk-ZPM7SSJM.js.map → chunk-NWP44FEW.js.map} +0 -0
  97. /package/dist/{chunk-P27P7GFY.js.map → chunk-R7AS5M32.js.map} +0 -0
  98. /package/dist/{chunk-PDSCFOC4.js.map → chunk-TVORP6BW.js.map} +0 -0
  99. /package/dist/{chunk-MODPTVA6.js.map → chunk-U6XM4M5V.js.map} +0 -0
  100. /package/dist/{chunk-SY7ENNNK.js.map → chunk-WEUF5WRR.js.map} +0 -0
  101. /package/dist/{client-HLCKITQJ.js.map → client-OAAE3KM5.js.map} +0 -0
  102. /package/dist/{config-QLCPWIJN.js.map → config-44LINWKG.js.map} +0 -0
  103. /package/dist/{config-mutator-BCTMKRPT.js.map → config-mutator-P6QEABPU.js.map} +0 -0
  104. /package/dist/{doctor-74P5CWVW.js.map → doctor-OXR3VXX6.js.map} +0 -0
  105. /package/dist/{processes-TGFDGQYY.js.map → processes-5EXCTSD5.js.map} +0 -0
  106. /package/dist/{program-ONWCNXKS.js.map → program-X7ROPRQP.js.map} +0 -0
  107. /package/dist/{promote-VFL66JD2.js.map → promote-72BY34SI.js.map} +0 -0
  108. /package/dist/{query-MCCWN6XA.js.map → query-AJO3NOO6.js.map} +0 -0
  109. /package/dist/{registry-43X3DQTI.js.map → registry-AFNYREN2.js.map} +0 -0
  110. /package/dist/{request-planner-GSGBUGNG.js.map → request-planner-Q74NYFRJ.js.map} +0 -0
  111. /package/dist/{review-candidates-4Z6QTMN2.js.map → review-candidates-ZBBIPFJT.js.map} +0 -0
  112. /package/dist/{routing-T66LO3JY.js.map → routing-7VU524EZ.js.map} +0 -0
  113. /package/dist/{schedule-tool-ORNG6HMN.js.map → schedule-tool-6RRXRW5K.js.map} +0 -0
  114. /package/dist/{scheduler-VIWJITKR.js.map → scheduler-WA4KTCCU.js.map} +0 -0
  115. /package/dist/{seat-4H7TTV5X.js.map → seat-MKY332GD.js.map} +0 -0
  116. /package/dist/{select-YCVNOR5Q.js.map → select-FZX63JK5.js.map} +0 -0
  117. /package/dist/{set-enabled-6UGUPYW4.js.map → set-enabled-RNDSUIYU.js.map} +0 -0
  118. /package/dist/{wiki-SHHIVZPT.js.map → wiki-ZOK6XGIX.js.map} +0 -0
@@ -1,11 +1,11 @@
1
- import{a as we}from"./chunk-7XB2CVC3.js";import{t as xt,u as vt}from"./chunk-EAMSULHF.js";import{d as kt,e as St}from"./chunk-AQASR6KR.js";import{b as he,t as dt,v as Z,w as ye,y as be}from"./chunk-QGTQ4PIL.js";import{a as yt,c as bt,d as wt}from"./chunk-R5BXA7TL.js";import{g as gt,h as ft,i as pt,k as mt,l as ht}from"./chunk-A4ACRRRP.js";import{q as ut}from"./chunk-CW42OBFL.js";import{A as ct,D as ir}from"./chunk-SZZSUW42.js";import{existsSync as or,readdirSync as ar,readFileSync as lr,statSync as cr}from"fs";import{resolve as ur}from"path";function $t(t,e,n=Date.now(),s=7){let r=s*864e5,i=new Map;for(let o of e){let a=i.get(o.workflowId);a?a.push(o):i.set(o.workflowId,[o])}return t.map(o=>{let a=i.get(o.id)??[],l=a.filter(p=>n-p.at<=r),c=a.filter(p=>n-p.at>r&&n-p.at<=r*2),u=l.filter(p=>p.status==="failed").length,d=a.filter(p=>p.status==="paused").length,g=a.length?Math.max(...a.map(p=>p.at)):null,f=a.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:g,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((o,a)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[o.state]-l[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var Q=new Map;function vo(t,e=1e3){if(!or(t))return[];let n=ar(t).filter(i=>i.endsWith(".jsonl")).map(i=>{let o=ur(t,i);return{path:o,mtime:cr(o).mtimeMs}}).sort((i,o)=>o.mtime-i.mtime).slice(0,e),s=new Set(n.map(i=>i.path));for(let i of Q.keys())s.has(i)||Q.delete(i);let r=[];for(let{path:i,mtime:o}of n){let a=Q.get(i);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=dr(i,o);Q.set(i,{mtime:o,summary:l}),l&&r.push(l)}return r}function dr(t,e){try{let n=lr(t,"utf-8").split(`
2
- `).filter(Boolean);if(!n.length)return null;let s=JSON.parse(n[0]),r=s.run?.workflowId;if(!r)return null;let i=s.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),l=a.status??a.run?.status;if(l){i=l;break}}return{workflowId:r,status:i,at:e}}catch{return null}}var gr={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},fr=(t,e,n)=>{try{return ut(t,e,n)}catch{return null}},It=864e5;function Ao(t){let e=t.now??Date.now(),n={...gr,...t.thresholds},s=t.nextFire??fr,r=[];for(let a of t.crons){let l=t.cronRuns.get(a.id)??[],c=a.timezone||"UTC",u=l.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=l[0],g={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,k.text),trigger:{schedule:$(a.schedule,k.text),timezone:c},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?ke(a.nextRun)??ke(s(a.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:wr(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:_t(u),sampledRuns:l.length,flags:[],attention:null};g.flags=At(g,u,a.schedule,c,null,e,n,s),r.push(Rt(g))}let i=new Map($t(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 l=o.get(a.workflowId);l?l.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let l=a.nodes.find(A=>A.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=a.state||"active",d=u==="active",g=(o.get(a.id)??[]).slice().sort((A,me)=>me.at-A.at),f=g.map(A=>({at:A.at,status:hr(A.status)})),p=f[0],h=l.type==="trigger.cron",y=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",O={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,k.text),trigger:h?{schedule:$(y,k.text),timezone:C}:{event:$(typeof c.event=="string"?c.event:"",k.text),filters:br(c.filter,a)},agent:yr(a),enabled:d,state:u,nextRunAt:h&&d&&y?ke(s(y,new Date(e),C)):null,lastRun:p?{at:new Date(p.at).toISOString(),status:p.status}:null,lastSuccessAt:(()=>{let A=f.find(me=>me.status==="success");return A?new Date(A.at).toISOString():null})(),consecutiveFailures:_t(f),sampledRuns:g.length,flags:[],attention:null},Y=Date.parse(a.updated||a.created||"");O.flags=h?At(O,f,y,C,Number.isFinite(Y)?Y:null,e,n,s):pr(O,i.get(a.id)?.state==="dormant",Number.isFinite(Y)?Y:null,e,n),r.push(Rt(O))}return r.sort(mr).slice(0,k.routines)}function _t(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 At(t,e,n,s,r,i,o,a){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let g=Dt(c,r,i,o);return g&&l.push(g),l}if(t.consecutiveFailures>=o.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let g=0;g<o.missedFires&&(d=a(n,u,s),!!d);g++)u=d;return d&&i>d.getTime()+o.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${o.missedFires} scheduled fires missed`}),l}function pr(t,e,n,s,r){let i=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=Dt(o,n,s,r);return a&&i.push(a),i}return t.consecutiveFailures>=r.failStreak&&i.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),o===null?i.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&i.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),i}function Dt(t,e,n,s){let r=Math.max(t??0,e??0);return r&&n-r<s.disabledDays*It?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/It)} days`:"Disabled and never ran"}}function Rt(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 Ct={critical:0,warning:1,info:2};function mr(t,e){let n=t.attention?Ct[t.attention]:3,s=e.attention?Ct[e.attention]:3;return n-s||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function hr(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 yr(t){if(t.ownerAgent)return $(t.ownerAgent,k.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?$(String(e.config.agentId),k.text):null}function br(t,e){let n=[],s=e?.project;if(s&&n.push($(`project=${s}`,k.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,i]of Object.entries(t)){let o=Array.isArray(i)?i.map(String):i==null?[]:[String(i)];o.length&&n.push($(`${r}=${o.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function ke(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function $(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function wr(t,e){return t===void 0?void 0:$(t,e)}import{createHash as kr,randomBytes as Tt}from"crypto";import{existsSync as Sr,mkdirSync as xr,readFileSync as vr,writeFileSync as $r}from"fs";import{resolve as Ir,dirname as _r}from"path";var Se="agx_live_",Ar=".agentx/tokens.json",Et=class{file;constructor(e=process.cwd(),n=Ar){this.file=Ir(e,n)}load(){if(!Sr(this.file))return[];try{return JSON.parse(vr(this.file,"utf-8"))}catch{return[]}}save(e){xr(_r(this.file),{recursive:!0}),$r(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(!Rr(o))throw new Error(`Invalid scope: ${o}`);let n=Tt(32).toString("hex"),s=Se+n,r={id:"tok_"+Tt(4).toString("hex"),name:e.name.trim(),prefix:Se+n.slice(0,4),hash:Lt(s),scopes:[...e.scopes],createdAt:new Date().toISOString(),expiresAt:e.expiresInDays?new Date(Date.now()+e.expiresInDays*86400*1e3).toISOString():void 0},i=this.load();return i.push(r),this.save(i),{token:s,record:r}}list(){return this.load()}revoke(e){let n=this.load(),s=n.find(r=>r.id===e);return s?(s.revokedAt=new Date().toISOString(),this.save(n),s):null}isActive(e){let n=this.load().find(s=>s.id===e);return!!n&&!n.revokedAt&&!(n.expiresAt&&Date.parse(n.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(Se))return null;let n=Lt(e),s=this.load(),r=s.find(a=>a.hash===n);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let i=Date.now(),o=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(i-o>6e4){r.lastUsedAt=new Date(i).toISOString();try{this.save(s)}catch{}}return r}};function Eo(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function Rr(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 Lt(t){return"sha256:"+kr("sha256").update(t).digest("hex")}function Lo(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 $e,readdirSync as ts,readFileSync as ns}from"fs";import{resolve as j}from"path";import{randomBytes as jt}from"crypto";import{existsSync as Dr,mkdirSync as Tr,readdirSync as Er,readFileSync as Lr,renameSync as Vt,unlinkSync as Or,writeFileSync as Pr}from"fs";import{resolve as Mt}from"path";function Ot(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var Cr=t=>t.trim().split(`
4
- `).pop()?.slice(0,300)||"no output";async function Pt(t,e,n,s=we){let r=await s(t.bin,[...Ot(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${Cr(r.stderr||r.stdout)}`}}async function jo(t,e,n,s,r=we){return(await r(t.bin,[...Ot(t),"--read-only","media","download","--chat",e,"--id",n,"--output",s],{timeoutMs:12e4})).code===0}var jr=2e3,Vr=t=>Pt(t.wacli,t.to,t.text);function xe(t){return Mt(t,".agentx","whatsapp-triage","drafts")}var Mr=t=>/^[a-z0-9-]{8,64}$/.test(t),ee=(t,e)=>Mt(xe(t),`${e}.json`);function Nt(t,e){Tr(xe(t),{recursive:!0});let n=ee(t,e.id),s=`${n}.${process.pid}.tmp`;Pr(s,JSON.stringify(e,null,2)+`
5
- `,{mode:384}),Vt(s,n)}function Wo(t,e,n=Date.now()){let s=e.text.trim().slice(0,jr);if(!s)throw new Error("empty draft");let r={...e,text:s,id:`${n.toString(36)}-${jt(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return Nt(t,r),r}function te(t,e){if(!Mr(e))return null;try{return JSON.parse(Lr(ee(t,e),"utf-8"))}catch{return null}}function Ft(t,e){let n=xe(t);return Dr(n)?Er(n).filter(s=>s.endsWith(".json")).map(s=>te(t,s.slice(0,-5))).filter(s=>!!s&&(!e||s.status===e)).sort((s,r)=>s.created_at.localeCompare(r.created_at)):[]}async function Ut(t,e,n,s={}){let r=te(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let i=`${ee(t,e)}.${process.pid}.${jt(3).toString("hex")}.claim`;try{Vt(ee(t,e),i)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(s.send??Vr)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}Nt(t,o);try{Or(i)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{existsSync as Nr,mkdirSync as Fr,readdirSync as Ur,readFileSync as Wr,renameSync as Br,writeFileSync as Hr}from"fs";import{resolve as Bt}from"path";var Wt=["discard","keep","pause","approve"],I={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},zr={defaultExpiryDays:3,maxExpiryDays:30};function P(t){return Bt(t,".agentx","approvals")}var Kr=/^[a-z0-9][a-z0-9-]{0,80}$/;function Ht(t){return Kr.test(t)}function zt(t,e){if(!Ht(e))throw new Error(`invalid card id: ${e}`);return Bt(P(t),`${e}.json`)}function Gr(t,e){let n=new Date(t).toISOString().slice(0,10),s=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${n}-${s||"card"}-${Math.random().toString(36).slice(2,6)}`}function ne(t,e){Fr(P(t),{recursive:!0});let n=zt(t,e.id),s=`${n}.${process.pid}.tmp`;Hr(s,JSON.stringify(e,null,2)+`
6
- `),Br(s,n)}function U(t,e){if(!Ht(e))return null;try{return JSON.parse(Wr(zt(t,e),"utf-8"))}catch{return null}}function W(t,e){let n=P(t);if(!Nr(n))return[];let s=[];for(let r of Ur(n).filter(i=>i.endsWith(".json")&&!i.startsWith("_")).sort()){let i=U(t,r.slice(0,-5));i&&(!e||i.status===e)&&s.push(i)}return s}function w(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function Xr(t,e,n){let s=e+n.maxExpiryDays*864e5,r,i=w(t);if(!i)r=e+n.defaultExpiryDays*864e5;else{let o=/^(\d+)\s*([hd])$/i.exec(i);if(o)r=e+Number(o[1])*(o[2].toLowerCase()==="d"?864e5:36e5);else if(r=Date.parse(i),Number.isNaN(r))return{ok:!1,error:`expires must be an ISO date or time, or like "12h" / "3d" (got "${i}")`}}return r<=e?{ok:!1,error:"expires must be in the future"}:{ok:!0,at:new Date(Math.min(r,s)).toISOString()}}function qr(t,e={}){let n=e.now??Date.now(),s=e.settings??zr,r=w(t.title),i=w(t.ask),o=w(t.recommend),a=w(t.raised_by);if(!r)return{ok:!1,error:"title is required"};if(!i)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(i.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 l=w(t.if_silent).toLowerCase();if(!Wt.includes(l))return{ok:!1,error:`if_silent must be one of ${Wt.join(", ")}`};let c=Xr(t.expires,n,s);if(!c.ok)return c;let u=w(t.source);if(u.length>I.source)return{ok:!1,error:`source is longer than ${I.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=yt(t);if(!d.ok)return d;let g,f=t.reply;return f&&typeof f=="object"&&w(f.channel)&&w(f.chatId)&&(g={channel:w(f.channel),chatId:w(f.chatId),...w(f.accountId)?{accountId:w(f.accountId)}:{}}),{ok:!0,card:{id:Gr(n,r),title:r,ask:i,recommend:o,if_silent:l,expires:c.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...g?{reply:g}:{},...d.value,status:"pending"}}}function Go(t,e,n={}){let s=qr(e,n);if(!s.ok)return s;let r=W(t,"pending").filter(i=>i.raised_by===s.card.raised_by).length;return r>=I.pendingPerAgent?{ok:!1,error:`${s.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(ne(t,s.card),s)}function Kt(t,e,n,s={}){let r=U(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 i=bt(r,n,s);if(!i.ok)return i;let o=w(s.note).slice(0,I.note),a={...r,status:"decided",verdict:n,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString(),...o?{note:o}:{},...i.choice?{choice:i.choice}:{},...i.text?{text:i.text}:{}};return ne(t,a),{ok:!0,card:a}}function Xo(t,e=Date.now()){let n=[];for(let s of W(t,"pending")){if(Date.parse(s.expires)>e)continue;let r={...s,status:"expired",outcome:s.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};ne(t,r),n.push(r)}return n}function qo(t){return W(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function Jo(t,e,n=Date.now()){let s=U(t,e);!s||s.agent_notified_at||ne(t,{...s,agent_notified_at:new Date(n).toISOString()})}function Yo(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.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 Jr,readFileSync as Yr,renameSync as Zr,writeFileSync as Qr}from"fs";import{resolve as es}from"path";function Gt(t){return es(P(t),"_state.json")}function B(t){try{let e=JSON.parse(Yr(Gt(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}:{}}}catch{return{snoozed:{}}}}function ve(t,e){Jr(P(t),{recursive:!0});let n=Gt(t),s=`${n}.${process.pid}.tmp`;Qr(s,JSON.stringify(e,null,2)+`
8
- `),Zr(s,n)}function Xt(t,e,n,s=Date.now()){let r=B(t),i={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>s&&(i[o]=a);i[e]=n.toISOString(),ve(t,{...r,snoozed:i})}function na(t,e){ve(t,{...B(t),lastDigest:e})}function ra(t,e,n,s=Date.now()){let r=B(t),i=new Set(n),o={};for(let[a,l]of Object.entries(r.popped??{}))i.has(a)&&(o[a]=l);o[e]=new Date(s).toISOString(),ve(t,{...r,popped:o})}var qt=["card","schedule","memory","wiki","whatsapp"],rs=280;function H(t,e=rs){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Jt(t){if(t.configPath)return j(t.configPath);let e=[j(t.root,"agentx.json"),j(t.root,".agentx","config.json")];return e.find(n=>$e(n))??e[0]}function Ie(t){return t.wikiDir?j(t.wikiDir):j(t.root,".agentx","wiki")}function ss(t){return W(t.root,"pending").map(is)}function is(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.draft?{detail:H(`Suggested message: ${t.draft}`)}:{}}}function os(t){let e=Jt(t);if(!$e(e))return[];let n;try{n=JSON.parse(ns(e,"utf-8"))}catch{return[]}let s=new Date(t.now??Date.now()),r=[];for(let[i,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let l=o.timezone||"UTC",c=o.schedule?gt(o.schedule):"",u=o.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),g=a.action==="create";r.push({key:`schedule:${i}`,kind:"schedule",title:g?`New schedule "${i}" for ${o.agent??"an agent"}`:`Delete schedule "${i}"`,ask:g?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${i}" (${u})?`,yes:g?"enable it":"remove it",no:g?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:H(`${d}${g&&o.schedule?` \xB7 first run ${pt(ft(o.schedule,l,s),l)}`:""}`),more:"agentx schedule list"})}return r}function Yt(t){let e=j(t,".agentx","memory");return $e(e)?ts(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function as(t){let e=Yt(t.root);if(e.length===0)return[];let n=new he(t.root),s=[];for(let r of e)for(let i of n.held(r))s.push({key:`memory:${r}/${i.id}`,kind:"memory",title:`Fact ${r} learned from ${i.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:i.createdAt,detail:H(i.content),more:`agentx memory facts held --agent ${r}`});return s}function ls(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 cs(t){return St(Ie(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:H(`${ls(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function us(t){return Ft(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:H(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}var Zt={card:ss,schedule:os,memory:as,wiki:cs,whatsapp:us};function ds(t,e){let n=t.expires?Date.parse(t.expires):1/0,s=e.expires?Date.parse(e.expires):1/0;return n!==s?n-s:(Date.parse(t.created_at)||0)-(Date.parse(e.created_at)||0)}function pa(t,e={}){let n=t.now??Date.now(),{snoozed:s}=B(t.root),r=[],i=[],o=0;for(let a of e.kinds??qt){let l;try{l=Zt[a](t)}catch(c){i.push({kind:a,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=s[c.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(ds),{items:r,snoozed:o,errors:i}}function gs(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),s=t.slice(e+1);return!qt.includes(n)||!s?null:{kind:n,ref:s}}function fs(t,e,n){switch(e){case"card":return U(t.root,n)?.status==="pending";case"wiki":return kt(Ie(t),n)?.status==="pending";case"whatsapp":return te(t.root,n)?.status==="pending";default:return Zt[e](t).some(s=>s.key===`${e}:${n}`)}}async function ma(t,e,n,s={}){let r=gs(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:i,ref:o}=r,a=t.now??Date.now(),l=s.by??"operator";if(n==="later"){if(!fs(t,i,o))return{ok:!1,error:`nothing waiting for "${e}"`};let u=s.laterHours&&s.laterHours>0?s.laterHours:24,d=new Date(a+u*36e5);return Xt(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(i){case"card":{let u=Kt(t.root,o,c?"yes":"no",{by:l,note:s.note,now:a,choice:s.choice,text:s.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(c?mt:ht)(o,{configPath:Jt(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),g=o.slice(u+1);if(!Yt(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new he(t.root);return f.held(d).some(p=>p.id===g)?(f.review(d,g,c?"approved":"rejected",l),{ok:!0,message:`${e} ${c?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${g}" isn't waiting for review`}}case"wiki":{let u=Ie(t),d=c?xt(u,o,{by:l,force:s.force,now:a}):vt(u,o,{by:l,reason:s.note,now:a});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await Ut(t.root,o,c?"yes":"no",{by:l,now:a,send:t.sendWhatsApp});return u.ok?{ok:!0,message:c?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}}}var Qt=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function ya(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 ba(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 wa(t){return Qt.has(t)}function ka(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(Qt.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 Sa(t,e=process.env){let n=new Set;e.MESH_TOKEN&&n.add(e.MESH_TOKEN);for(let s of t.mesh?.peers||[])s.token&&n.add(s.token);return n}function xa(t,e,n=process.env){let s=i=>i.replace(/\/+$/,"");return(e===s(t.daemonUrl)?t.token:t.daemons.find(i=>s(i.url)===e)?.token)||n.MESH_TOKEN||void 0}function re(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function ps(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function ms(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function $a(t,e=ms()){let n=re(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=ps(n),i=[re(t.host),re(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&i.includes(r)?"same-origin":"foreign"}let s=re(t["sec-fetch-site"]).toLowerCase();return s==="cross-site"||s==="same-site"?"foreign":"none"}function Ia(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as In,mkdirSync as Gs,readFileSync as Xs,renameSync as qs,writeFileSync as Js}from"fs";import{homedir as Ys}from"os";import{dirname as Zs,join as Qs}from"path";import{execFile as _s,execFileSync as As}from"child_process";import{execFileSync as hs}from"child_process";import{existsSync as tn,mkdirSync as ys,readdirSync as bs,readFileSync as nn,renameSync as ws,writeFileSync as ks}from"fs";import{homedir as rn}from"os";import{join as Ae}from"path";var x="siri:",sn="com.apple.ttsbundle.gryphon-neural_",on=t=>!!t&&t.startsWith(sn),Ss=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],xs=()=>{try{return hs("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},_e;function Re(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:s=tn,prefDomain:r=xs}=t,i=n==="darwin"&&Ss.every(o=>s(o))&&r();return e||(_e=i),i}var an=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],ln={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"},Ce=t=>ln[t.toLowerCase()]??null;function se(t){let e=/^com\.apple\.ttsbundle\.gryphon-neural_([a-z]+)_([a-z]{2}-[A-Z]{2})_premium$/.exec(t);return e?{name:e[1],locale:e[2]}:null}var vs=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function $s(t){let e=new Map;for(let n of t)for(let[,s,r,i]of n.matchAll(vs)){let o=`${s}-${r}`,a=`${sn}${i}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:i[0].toUpperCase()+i.slice(1),locale:o,quality:"premium",gender:ln[i]??null,siri:!0})}return[...e.values()]}function ie(t=an,e={}){if(!Re(e))return[];let n=[];for(let s of t){let r;try{r=bs(s)}catch{continue}for(let i of r)try{n.push(nn(Ae(s,i,"Info.plist"),"latin1"))}catch{}}return $s(n)}var en=`#!/bin/sh
1
+ import{a as ke}from"./chunk-7XB2CVC3.js";import{t as xt,u as vt}from"./chunk-JVJYCR67.js";import{d as kt,e as St}from"./chunk-AQASR6KR.js";import{b as ye,t as dt,v as Z,w as be,y as we}from"./chunk-LQJNRSCT.js";import{c as yt,e as bt,f as wt}from"./chunk-Y4CYQV7G.js";import{g as gt,h as ft,i as pt,k as mt,l as ht}from"./chunk-4STRKIUA.js";import{q as ut}from"./chunk-FWDWHZ6H.js";import{A as ct,D as or}from"./chunk-DBXN7I2X.js";import{existsSync as ar,readdirSync as lr,readFileSync as cr,statSync as ur}from"fs";import{resolve as dr}from"path";function $t(t,e,n=Date.now(),s=7){let r=s*864e5,i=new Map;for(let o of e){let a=i.get(o.workflowId);a?a.push(o):i.set(o.workflowId,[o])}return t.map(o=>{let a=i.get(o.id)??[],l=a.filter(p=>n-p.at<=r),c=a.filter(p=>n-p.at>r&&n-p.at<=r*2),u=l.filter(p=>p.status==="failed").length,d=a.filter(p=>p.status==="paused").length,g=a.length?Math.max(...a.map(p=>p.at)):null,f=a.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:g,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((o,a)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[o.state]-l[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var Q=new Map;function $o(t,e=1e3){if(!ar(t))return[];let n=lr(t).filter(i=>i.endsWith(".jsonl")).map(i=>{let o=dr(t,i);return{path:o,mtime:ur(o).mtimeMs}}).sort((i,o)=>o.mtime-i.mtime).slice(0,e),s=new Set(n.map(i=>i.path));for(let i of Q.keys())s.has(i)||Q.delete(i);let r=[];for(let{path:i,mtime:o}of n){let a=Q.get(i);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=gr(i,o);Q.set(i,{mtime:o,summary:l}),l&&r.push(l)}return r}function gr(t,e){try{let n=cr(t,"utf-8").split(`
2
+ `).filter(Boolean);if(!n.length)return null;let s=JSON.parse(n[0]),r=s.run?.workflowId;if(!r)return null;let i=s.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),l=a.status??a.run?.status;if(l){i=l;break}}return{workflowId:r,status:i,at:e}}catch{return null}}var fr={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},pr=(t,e,n)=>{try{return ut(t,e,n)}catch{return null}},It=864e5;function Ro(t){let e=t.now??Date.now(),n={...fr,...t.thresholds},s=t.nextFire??pr,r=[];for(let a of t.crons){let l=t.cronRuns.get(a.id)??[],c=a.timezone||"UTC",u=l.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=l[0],g={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,k.text),trigger:{schedule:$(a.schedule,k.text),timezone:c},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?Se(a.nextRun)??Se(s(a.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:kr(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:At(u),sampledRuns:l.length,flags:[],attention:null};g.flags=_t(g,u,a.schedule,c,null,e,n,s),r.push(Rt(g))}let i=new Map($t(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 l=o.get(a.workflowId);l?l.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let l=a.nodes.find(_=>_.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=a.state||"active",d=u==="active",g=(o.get(a.id)??[]).slice().sort((_,he)=>he.at-_.at),f=g.map(_=>({at:_.at,status:yr(_.status)})),p=f[0],h=l.type==="trigger.cron",y=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",O={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,k.text),trigger:h?{schedule:$(y,k.text),timezone:C}:{event:$(typeof c.event=="string"?c.event:"",k.text),filters:wr(c.filter,a)},agent:br(a),enabled:d,state:u,nextRunAt:h&&d&&y?Se(s(y,new Date(e),C)):null,lastRun:p?{at:new Date(p.at).toISOString(),status:p.status}:null,lastSuccessAt:(()=>{let _=f.find(he=>he.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:At(f),sampledRuns:g.length,flags:[],attention:null},Y=Date.parse(a.updated||a.created||"");O.flags=h?_t(O,f,y,C,Number.isFinite(Y)?Y:null,e,n,s):mr(O,i.get(a.id)?.state==="dormant",Number.isFinite(Y)?Y:null,e,n),r.push(Rt(O))}return r.sort(hr).slice(0,k.routines)}function At(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 _t(t,e,n,s,r,i,o,a){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let g=Dt(c,r,i,o);return g&&l.push(g),l}if(t.consecutiveFailures>=o.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let g=0;g<o.missedFires&&(d=a(n,u,s),!!d);g++)u=d;return d&&i>d.getTime()+o.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${o.missedFires} scheduled fires missed`}),l}function mr(t,e,n,s,r){let i=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=Dt(o,n,s,r);return a&&i.push(a),i}return t.consecutiveFailures>=r.failStreak&&i.push({reason:"failing",detail:`${t.consecutiveFailures} failed runs in a row`}),o===null?i.push({reason:"never-ran",detail:"No run recorded for this trigger"}):e&&i.push({reason:"dormant",detail:"Fired in the prior week, silent in the last one"}),i}function Dt(t,e,n,s){let r=Math.max(t??0,e??0);return r&&n-r<s.disabledDays*It?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/It)} days`:"Disabled and never ran"}}function Rt(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 Ct={critical:0,warning:1,info:2};function hr(t,e){let n=t.attention?Ct[t.attention]:3,s=e.attention?Ct[e.attention]:3;return n-s||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function yr(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 br(t){if(t.ownerAgent)return $(t.ownerAgent,k.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?$(String(e.config.agentId),k.text):null}function wr(t,e){let n=[],s=e?.project;if(s&&n.push($(`project=${s}`,k.filterValue)),t&&typeof t=="object"&&!Array.isArray(t))for(let[r,i]of Object.entries(t)){let o=Array.isArray(i)?i.map(String):i==null?[]:[String(i)];o.length&&n.push($(`${r}=${o.join(",")}`,k.filterValue))}return n.slice(0,k.filters)}function Se(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function $(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function kr(t,e){return t===void 0?void 0:$(t,e)}import{createHash as Sr,randomBytes as Tt}from"crypto";import{existsSync as xr,mkdirSync as vr,readFileSync as $r,writeFileSync as Ir}from"fs";import{resolve as Ar,dirname as _r}from"path";var xe="agx_live_",Rr=".agentx/tokens.json",Et=class{file;constructor(e=process.cwd(),n=Rr){this.file=Ar(e,n)}load(){if(!xr(this.file))return[];try{return JSON.parse($r(this.file,"utf-8"))}catch{return[]}}save(e){vr(_r(this.file),{recursive:!0}),Ir(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(!Cr(o))throw new Error(`Invalid scope: ${o}`);let n=Tt(32).toString("hex"),s=xe+n,r={id:"tok_"+Tt(4).toString("hex"),name:e.name.trim(),prefix:xe+n.slice(0,4),hash:Lt(s),scopes:[...e.scopes],createdAt:new Date().toISOString(),expiresAt:e.expiresInDays?new Date(Date.now()+e.expiresInDays*86400*1e3).toISOString():void 0},i=this.load();return i.push(r),this.save(i),{token:s,record:r}}list(){return this.load()}revoke(e){let n=this.load(),s=n.find(r=>r.id===e);return s?(s.revokedAt=new Date().toISOString(),this.save(n),s):null}isActive(e){let n=this.load().find(s=>s.id===e);return!!n&&!n.revokedAt&&!(n.expiresAt&&Date.parse(n.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(xe))return null;let n=Lt(e),s=this.load(),r=s.find(a=>a.hash===n);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let i=Date.now(),o=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(i-o>6e4){r.lastUsedAt=new Date(i).toISOString();try{this.save(s)}catch{}}return r}};function Lo(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function Cr(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 Lt(t){return"sha256:"+Sr("sha256").update(t).digest("hex")}function Oo(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 $e,readdirSync as ns,readFileSync as rs}from"fs";import{resolve as V}from"path";import{randomBytes as jt}from"crypto";import{existsSync as Tr,mkdirSync as Er,readdirSync as Lr,readFileSync as Or,renameSync as Vt,unlinkSync as Pr,writeFileSync as jr}from"fs";import{resolve as Mt}from"path";function Ot(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var Dr=t=>t.trim().split(`
4
+ `).pop()?.slice(0,300)||"no output";async function Pt(t,e,n,s=ke){let r=await s(t.bin,[...Ot(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${Dr(r.stderr||r.stdout)}`}}async function Vo(t,e,n,s,r=ke){return(await r(t.bin,[...Ot(t),"--read-only","media","download","--chat",e,"--id",n,"--output",s],{timeoutMs:12e4})).code===0}var Vr=2e3,Mr=t=>Pt(t.wacli,t.to,t.text);function ve(t){return Mt(t,".agentx","whatsapp-triage","drafts")}var Nr=t=>/^[a-z0-9-]{8,64}$/.test(t),ee=(t,e)=>Mt(ve(t),`${e}.json`);function Nt(t,e){Er(ve(t),{recursive:!0});let n=ee(t,e.id),s=`${n}.${process.pid}.tmp`;jr(s,JSON.stringify(e,null,2)+`
5
+ `,{mode:384}),Vt(s,n)}function Bo(t,e,n=Date.now()){let s=e.text.trim().slice(0,Vr);if(!s)throw new Error("empty draft");let r={...e,text:s,id:`${n.toString(36)}-${jt(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return Nt(t,r),r}function te(t,e){if(!Nr(e))return null;try{return JSON.parse(Or(ee(t,e),"utf-8"))}catch{return null}}function Ft(t,e){let n=ve(t);return Tr(n)?Lr(n).filter(s=>s.endsWith(".json")).map(s=>te(t,s.slice(0,-5))).filter(s=>!!s&&(!e||s.status===e)).sort((s,r)=>s.created_at.localeCompare(r.created_at)):[]}async function Ut(t,e,n,s={}){let r=te(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let i=`${ee(t,e)}.${process.pid}.${jt(3).toString("hex")}.claim`;try{Vt(ee(t,e),i)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(s.send??Mr)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}Nt(t,o);try{Pr(i)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{existsSync as Fr,mkdirSync as Ur,readdirSync as Wr,readFileSync as Br,renameSync as Hr,writeFileSync as zr}from"fs";import{resolve as Ht}from"path";function Wt(t,e){let n=t.list?` in the "${t.list}" list`:"",s=[`This card came from the operator's reminder "${t.title}"${n} (id ${t.id}).`];return s.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."),s}var Bt=["discard","keep","pause","approve"],I={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Kr={defaultExpiryDays:3,maxExpiryDays:30};function P(t){return Ht(t,".agentx","approvals")}var Gr=/^[a-z0-9][a-z0-9-]{0,80}$/;function zt(t){return Gr.test(t)}function Kt(t,e){if(!zt(e))throw new Error(`invalid card id: ${e}`);return Ht(P(t),`${e}.json`)}function Xr(t,e){let n=new Date(t).toISOString().slice(0,10),s=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${n}-${s||"card"}-${Math.random().toString(36).slice(2,6)}`}function ne(t,e){Ur(P(t),{recursive:!0});let n=Kt(t,e.id),s=`${n}.${process.pid}.tmp`;zr(s,JSON.stringify(e,null,2)+`
6
+ `),Hr(s,n)}function W(t,e){if(!zt(e))return null;try{return JSON.parse(Br(Kt(t,e),"utf-8"))}catch{return null}}function B(t,e){let n=P(t);if(!Fr(n))return[];let s=[];for(let r of Wr(n).filter(i=>i.endsWith(".json")&&!i.startsWith("_")).sort()){let i=W(t,r.slice(0,-5));i&&(!e||i.status===e)&&s.push(i)}return s}function w(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function qr(t,e,n){let s=e+n.maxExpiryDays*864e5,r,i=w(t);if(!i)r=e+n.defaultExpiryDays*864e5;else{let o=/^(\d+)\s*([hd])$/i.exec(i);if(o)r=e+Number(o[1])*(o[2].toLowerCase()==="d"?864e5:36e5);else if(r=Date.parse(i),Number.isNaN(r))return{ok:!1,error:`expires must be an ISO date or time, or like "12h" / "3d" (got "${i}")`}}return r<=e?{ok:!1,error:"expires must be in the future"}:{ok:!0,at:new Date(Math.min(r,s)).toISOString()}}function Jr(t,e={}){let n=e.now??Date.now(),s=e.settings??Kr,r=w(t.title),i=w(t.ask),o=w(t.recommend),a=w(t.raised_by);if(!r)return{ok:!1,error:"title is required"};if(!i)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(i.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 l=w(t.if_silent).toLowerCase();if(!Bt.includes(l))return{ok:!1,error:`if_silent must be one of ${Bt.join(", ")}`};let c=qr(t.expires,n,s);if(!c.ok)return c;let u=w(t.source);if(u.length>I.source)return{ok:!1,error:`source is longer than ${I.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=yt(t);if(!d.ok)return d;let g,f=t.reply;return f&&typeof f=="object"&&w(f.channel)&&w(f.chatId)&&(g={channel:w(f.channel),chatId:w(f.chatId),...w(f.accountId)?{accountId:w(f.accountId)}:{}}),{ok:!0,card:{id:Xr(n,r),title:r,ask:i,recommend:o,if_silent:l,expires:c.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...g?{reply:g}:{},...d.value,...e.origin?{origin:e.origin}:{},status:"pending"}}}function Jo(t,e,n={}){let s=Jr(e,n);if(!s.ok)return s;let r=B(t,"pending").filter(i=>i.raised_by===s.card.raised_by).length;return r>=I.pendingPerAgent?{ok:!1,error:`${s.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(ne(t,s.card),s)}function Gt(t,e,n,s={}){let r=W(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 i=bt(r,n,s);if(!i.ok)return i;let o=w(s.note).slice(0,I.note),a={...r,status:"decided",verdict:n,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString(),...o?{note:o}:{},...i.choice?{choice:i.choice}:{},...i.text?{text:i.text}:{}};return ne(t,a),{ok:!0,card:a}}function Yo(t,e=Date.now()){let n=[];for(let s of B(t,"pending")){if(Date.parse(s.expires)>e)continue;let r={...s,status:"expired",outcome:s.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};ne(t,r),n.push(r)}return n}function Zo(t){return B(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function Qo(t,e,n=Date.now()){let s=W(t,e);!s||s.agent_notified_at||ne(t,{...s,agent_notified_at:new Date(n).toISOString()})}function ea(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(...Wt(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 Yr,readFileSync as Zr,renameSync as Qr,writeFileSync as es}from"fs";import{resolve as ts}from"path";function Xt(t){return ts(P(t),"_state.json")}function j(t){try{let e=JSON.parse(Zr(Xt(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}:{}}}catch{return{snoozed:{}}}}function re(t,e){Yr(P(t),{recursive:!0});let n=Xt(t),s=`${n}.${process.pid}.tmp`;es(s,JSON.stringify(e,null,2)+`
8
+ `),Qr(s,n)}function qt(t,e,n,s=Date.now()){let r=j(t),i={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>s&&(i[o]=a);i[e]=n.toISOString(),re(t,{...r,snoozed:i})}function ia(t,e){re(t,{...j(t),lastDigest:e})}function oa(t,e,n,s=Date.now()){let r=j(t),i=new Set(n),o={};for(let[a,l]of Object.entries(r.popped??{}))i.has(a)&&(o[a]=l);o[e]=new Date(s).toISOString(),re(t,{...r,popped:o})}function aa(t,e=Date.now()){re(t,{...j(t),popped:{},passAt:new Date(e).toISOString()})}var Jt=["card","schedule","memory","wiki","whatsapp"],ss=280;function H(t,e=ss){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Yt(t){if(t.configPath)return V(t.configPath);let e=[V(t.root,"agentx.json"),V(t.root,".agentx","config.json")];return e.find(n=>$e(n))??e[0]}function Ie(t){return t.wikiDir?V(t.wikiDir):V(t.root,".agentx","wiki")}function is(t){return B(t.root,"pending").map(os)}function os(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:H([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function as(t){let e=Yt(t);if(!$e(e))return[];let n;try{n=JSON.parse(rs(e,"utf-8"))}catch{return[]}let s=new Date(t.now??Date.now()),r=[];for(let[i,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let l=o.timezone||"UTC",c=o.schedule?gt(o.schedule):"",u=o.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),g=a.action==="create";r.push({key:`schedule:${i}`,kind:"schedule",title:g?`New schedule "${i}" for ${o.agent??"an agent"}`:`Delete schedule "${i}"`,ask:g?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${i}" (${u})?`,yes:g?"enable it":"remove it",no:g?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:H(`${d}${g&&o.schedule?` \xB7 first run ${pt(ft(o.schedule,l,s),l)}`:""}`),more:"agentx schedule list"})}return r}function Zt(t){let e=V(t,".agentx","memory");return $e(e)?ns(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function ls(t){let e=Zt(t.root);if(e.length===0)return[];let n=new ye(t.root),s=[];for(let r of e)for(let i of n.held(r))s.push({key:`memory:${r}/${i.id}`,kind:"memory",title:`Fact ${r} learned from ${i.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:i.createdAt,detail:H(i.content),more:`agentx memory facts held --agent ${r}`});return s}function cs(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 us(t){return St(Ie(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:H(`${cs(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function ds(t){return Ft(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:H(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}var Qt={card:is,schedule:as,memory:ls,wiki:us,whatsapp:ds};function gs(t,e){let n=t.expires?Date.parse(t.expires):1/0,s=e.expires?Date.parse(e.expires):1/0;return n!==s?n-s:(Date.parse(t.created_at)||0)-(Date.parse(e.created_at)||0)}function ba(t,e={}){let n=t.now??Date.now(),{snoozed:s}=j(t.root),r=[],i=[],o=0;for(let a of e.kinds??Jt){let l;try{l=Qt[a](t)}catch(c){i.push({kind:a,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=s[c.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(gs),{items:r,snoozed:o,errors:i}}function fs(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),s=t.slice(e+1);return!Jt.includes(n)||!s?null:{kind:n,ref:s}}function ps(t,e,n){switch(e){case"card":return W(t.root,n)?.status==="pending";case"wiki":return kt(Ie(t),n)?.status==="pending";case"whatsapp":return te(t.root,n)?.status==="pending";default:return Qt[e](t).some(s=>s.key===`${e}:${n}`)}}async function wa(t,e,n,s={}){let r=fs(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:i,ref:o}=r,a=t.now??Date.now(),l=s.by??"operator";if(n==="later"){if(!ps(t,i,o))return{ok:!1,error:`nothing waiting for "${e}"`};let u=s.laterHours&&s.laterHours>0?s.laterHours:24,d=new Date(a+u*36e5);return qt(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(i){case"card":{let u=Gt(t.root,o,c?"yes":"no",{by:l,note:s.note,now:a,choice:s.choice,text:s.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(c?mt:ht)(o,{configPath:Yt(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),g=o.slice(u+1);if(!Zt(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new ye(t.root);return f.held(d).some(p=>p.id===g)?(f.review(d,g,c?"approved":"rejected",l),{ok:!0,message:`${e} ${c?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${g}" isn't waiting for review`}}case"wiki":{let u=Ie(t),d=c?xt(u,o,{by:l,force:s.force,now:a}):vt(u,o,{by:l,reason:s.note,now:a});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await Ut(t.root,o,c?"yes":"no",{by:l,now:a,send:t.sendWhatsApp});return u.ok?{ok:!0,message:c?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}}}var en=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Sa(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 xa(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 va(t){return en.has(t)}function $a(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(en.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 Ia(t,e=process.env){let n=new Set;e.MESH_TOKEN&&n.add(e.MESH_TOKEN);for(let s of t.mesh?.peers||[])s.token&&n.add(s.token);return n}function Aa(t,e,n=process.env){let s=i=>i.replace(/\/+$/,"");return(e===s(t.daemonUrl)?t.token:t.daemons.find(i=>s(i.url)===e)?.token)||n.MESH_TOKEN||void 0}function se(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function ms(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function hs(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Ra(t,e=hs()){let n=se(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=ms(n),i=[se(t.host),se(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&i.includes(r)?"same-origin":"foreign"}let s=se(t["sec-fetch-site"]).toLowerCase();return s==="cross-site"||s==="same-site"?"foreign":"none"}function Ca(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as An,mkdirSync as Xs,readFileSync as qs,renameSync as Js,writeFileSync as Ys}from"fs";import{homedir as Zs}from"os";import{dirname as Qs,join as ei}from"path";import{execFile as _s,execFileSync as Rs}from"child_process";import{execFileSync as ys}from"child_process";import{existsSync as nn,mkdirSync as bs,readdirSync as ws,readFileSync as rn,renameSync as ks,writeFileSync as Ss}from"fs";import{homedir as sn}from"os";import{join as _e}from"path";var x="siri:",on="com.apple.ttsbundle.gryphon-neural_",an=t=>!!t&&t.startsWith(on),xs=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],vs=()=>{try{return ys("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},Ae;function Re(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&Ae!==void 0)return Ae;let{platform:n=process.platform,exists:s=nn,prefDomain:r=vs}=t,i=n==="darwin"&&xs.every(o=>s(o))&&r();return e||(Ae=i),i}var ln=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],cn={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"},Ce=t=>cn[t.toLowerCase()]??null;function ie(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 $s=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function Is(t){let e=new Map;for(let n of t)for(let[,s,r,i]of n.matchAll($s)){let o=`${s}-${r}`,a=`${on}${i}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:i[0].toUpperCase()+i.slice(1),locale:o,quality:"premium",gender:cn[i]??null,siri:!0})}return[...e.values()]}function oe(t=ln,e={}){if(!Re(e))return[];let n=[];for(let s of t){let r;try{r=ws(s)}catch{continue}for(let i of r)try{n.push(rn(_e(s,i,"Info.plist"),"latin1"))}catch{}}return Is(n)}var tn=`#!/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:-"${an.join(" ")}"}
20
+ assets=\${AGENTX_SIRI_ASSET_DIRS:-"${ln.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,34 +110,34 @@ wait "$say_pid"
110
110
  status=$?
111
111
  say_pid=
112
112
  finish $status
113
- `,Is=(t=rn())=>Ae(t,".agentx","voice","siri-say.sh");function cn(t=rn()){let e=Is(t);return tn(e)&&nn(e,"utf8")===en||(ys(Ae(t,".agentx","voice"),{recursive:!0}),ks(`${e}.tmp`,en,{mode:493}),ws(`${e}.tmp`,e)),e}var un=`ObjC.import("AVFoundation")
113
+ `,As=(t=sn())=>_e(t,".agentx","voice","siri-say.sh");function un(t=sn()){let e=As(t);return nn(e)&&rn(e,"utf8")===tn||(bs(_e(t,".agentx","voice"),{recursive:!0}),Ss(`${e}.tmp`,tn,{mode:493}),ks(`${e}.tmp`,e)),e}var dn=`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")`,Rs=new Set(["Fred","Kathy","Ralph","Junior"]),Cs={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 dn(t){let e=[];for(let n of t.split(`
120
- `)){let[s,r,i,o,a]=n.split(" ");!s||!r||!i||s.includes(".siri_")||s.startsWith("com.apple.speech.synthesis.voice.")&&!Rs.has(r)||e.push({id:s,name:r,locale:i,quality:o==="3"?"premium":o==="2"?"enhanced":"standard",gender:a==="1"?"male":a==="2"?"female":Cs[r]??null})}return e}var Ds=10*60*1e3,Oa=60*1e3,V=null,De=!1;function Te(t=Date.now(),e=Ds){if(process.platform!=="darwin")return[];if(V)t-V.at>e&&!De&&(De=!0,_s("osascript",["-l","JavaScript","-e",un],{timeout:1e4},(n,s)=>{De=!1,n||(V={at:Date.now(),voices:[...dn(String(s)),...ie()]})}));else try{V={at:t,voices:[...dn(As("osascript",["-l","JavaScript","-e",un],{encoding:"utf8",timeout:1e4})),...ie()]}}catch(n){Ee(`[voice] could not list system voices: ${String(n?.message??n).split(`
121
- `)[0]}`),V={at:t,voices:ie()}}return V.voices}var Ee=t=>process.stderr.write(t+`
122
- `),oe=new Set;function Pa(t){Ee=t}function E(t,e){oe.has(t)||(oe.add(t),Ee(e))}function pn(t){for(let e of oe)t(e)&&oe.delete(e)}var mn=()=>{};function ja(t){mn=t}function hn(t){try{mn(t)}catch(e){E("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var Ts={premium:3,enhanced:2,standard:1},Es=new Set(["Grandma","Grandpa"]);function gn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!Es.has(t.name)?1:0;return Ts[t.quality]*10+e}var M=t=>t.toLowerCase().split(/[-_]/)[0],fn=t=>t.id.startsWith("com.apple.voice.");function Le(t,e,n,s=new Set){let r=z(t.filter(a=>!a.siri&&M(a.locale)===M(e)),e);if(r.some(fn)&&(r=r.filter(fn)),n==="female"||n==="male"){let a=r.filter(l=>l.gender===n);a.length&&(r=a)}if(!r.length)return null;let i=r.filter(a=>a.quality===r[0].quality),o=new Set([...s].map(a=>a.toLowerCase()));return i.find(a=>!o.has(a.name.toLowerCase()))??i[0]}function z(t,e="en"){let n=e.toLowerCase().replace("_","-"),s=M(e),r=t.filter(i=>M(i.locale)===s);return(r.length?r:t).slice().sort((i,o)=>gn(o)-gn(i)||+(o.locale.toLowerCase()===n)-+(i.locale.toLowerCase()===n)||i.name.localeCompare(o.name)||i.locale.localeCompare(o.locale))}function K(t,e,n="en"){let s=t.trim();if(!s)return null;let r=e.find(c=>c.id===s);if(r)return r;if(s.toLowerCase().startsWith(x)){let c=s.slice(x.length).trim().toLowerCase(),u=z(e.filter(g=>g.siri&&g.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=K(c,e.filter(g=>M(g.locale)===M(n)),n);return d&&E(`siri:${c}`,`[voice] Siri voice "${c}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(c=>!c.siri);let i=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(s),o=(i?i[1]:s.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=z(e.filter(c=>c.name.toLowerCase()===o),n);return(i?a.find(c=>c.quality===i[2].toLowerCase()):void 0)??a[0]??null}function yn(t,e,n=new Set){let s=new Map;if(!e.length)return s;let r=new Set([...n].map(o=>o.toLowerCase())),i="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",l=a?o.gender:i,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(a?e.find(d=>d.gender===l):void 0)??c[0]??e[s.size%e.length];s.set(o.id,u),r.add(u.name.toLowerCase()),a||(i=i==="female"?"male":"female")}return s}var Ls=new Set("the and is are was were i you he she we they it this that to of in for with not but yes what have has will would can your my".split(" ")),Os=new Set("le la les des du de un une et est sont je tu il elle nous vous ils elles ce cette c'est pas pour que qui avec dans sur au aux mais tr\xE8s oui non merci bonjour votre mon".split(" ")),Ps=/[éèêëàâçùûîïôœ]/;function ae(t){let e=(t.match(/[؀-ۿ]/g)??[]).length,n=(t.match(/[a-zA-ZÀ-ÿ]/g)??[]).length;if(e&&e>=n)return"ar";let s=0,r=0;for(let i of t.toLowerCase().replace(/[’]/g,"'").match(/[a-zà-ÿœ']+/g)??[])Ls.has(i)&&s++,Os.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?r++:Ps.test(i)&&(r+=.5);return s===r?null:s>r?"en":"fr"}var Oe="system",js=t=>t.trim().toLowerCase()===Oe,Vs="21m00Tcm4TlvDq8ikWAM";function Pe(t,e,n={},s=Te()){let r=e[t],i=r?.name||t,o=r?.voice,a=Ve(e,n,s).get(t)??null,l=Us(t,o?.system,o?.gender,n,s);return{agentId:t,name:i,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?ce(a):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Bs(i,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var ce=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function Ms(t,e,n,s){if(!e||!n.length)return null;let r=K(e,n,s);return r||(E(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),hn(e)),r}function Sn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(x))return{locale:e,gender:Ce(n.slice(x.length).trim())};let s=se(n);return s?{locale:s.locale,gender:Ce(s.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var xn=t=>t.toLowerCase().split(/[-_]/)[0],bn=(t,e)=>typeof t=="string"?t:t?.[xn(e)];function le(t,e,n,s){if(e!==void 0)return js(e)?null:Ms(t,e,n,s)??void 0}var je=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Ns(t,e,n,s=new Set){let r=e.locale??"en",i=new Map,o=[],a=le("voice.system",bn(e.system,r),n,r),l=()=>new Set([...s,...[...i.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=bn(u.system,r),g=le(u.id,d,n,r),f=g!==void 0?g:d!==void 0&&n.length?Fs(u,d,r,a,n,l()):a!==void 0&&je(a,u.gender)?a:void 0;f!==void 0?i.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of yn(o,z(n.filter(g=>!g.siri),r),c))i.set(u,d);return i}function Fs(t,e,n,s,r,i){for(let a of t.fallbacks??[]){let l=le(`${t.id}.fallbacks`,a,r,n);if(l!==void 0)return l}if(s!==void 0&&je(s,t.gender))return s;let o=Sn(e,n);return Le(r,o.locale,t.gender??o.gender,i)??void 0}function Us(t,e,n,s,r){if(typeof e=="string")return{};let i={},o=(a,l,c)=>{if(!(!l||typeof l=="string"))for(let[u,d]of Object.entries(l)){let g=le(`${a}.${u}`,d,r,u);g===void 0&&r.length&&(g=Le(r,u,n??Sn(d,u).gender)??void 0),g!==void 0&&c(g)&&(i[xn(u)]=g)}};return o("voice.system",s.system,a=>je(a,n)),o(t,e,()=>!0),i}function Wa(t,e){let n=e?ae(e):null;if(!n||!(n in t.systemByLanguage))return t;let s=t.systemByLanguage[n];return{...t,systemVoice:s?.id??null,systemVoiceName:s?ce(s):null}}function Ve(t,e={},n=Te()){let s=Object.entries(t).map(([r,i])=>({id:r,system:i.voice?.system,gender:i.voice?.gender,fallbacks:i.voice?.fallbacks}));return Ns(s,e,n)}function Me(t,e){let n={provider:t.provider,elevenlabs:Ws(e,t.elevenlabsVoiceId),system:t.systemVoice,fallback:t.fallback},s=Object.entries(t.systemByLanguage??{});return s.length&&(n.languages=Object.fromEntries(s.map(([r,i])=>[r,i?.id??null]))),t.rate&&t.rate!==1&&(n.rate=t.rate),t.priority&&t.priority!=="normal"&&(n.priority=t.priority),n}function Ws(t,e){return t||e||process.env.AGENTX_VOICE_ID||Vs}function Bs(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",s=/^You are (.+?)\.?$/i.exec(n.trim());if(!s)return`Hello, this is ${t}.`;let r=s[1].replace(/\s*\([^)]*\)/g,"").trim(),[i,...o]=r.split(/,\s*/),a=o.join(", ");return a&&i.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 Hs=8*60*60*1e3,zs=500,wn=class{constructor(e=Hs){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,s=Date.now()){let r=this.lastSpoke.get(kn(e,n));return r===void 0||s-r>this.gapMs}spoke(e,n,s=Date.now()){let r=kn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,s),this.lastSpoke.size>zs&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},kn=(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 Ba(t,e,n,s={}){let r=e[t],i=Pe(t,e,s),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:i.name,voice:Me(i),persona:o||`You are ${i.name}.`,introLine:vn(i,n)}}var Ks="[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 Ha(t){let e=t;if(e?.channel!=="voice"||!e.voice||typeof e.voice!="object")return;let n=i=>typeof i=="string"?i.replace(/\s+/g," ").slice(0,200):"",s=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:s||"Hello."};return`${Ks}
123
- ${vn(r,e.voice.introduce===!0&&!!s)}`}var ei="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",_n=(t=Ys())=>Qs(t,".agentx","voice","health.json");function ti(t,e,n){let s=t.trim();if(!s||s.toLowerCase()===Oe)return!0;if(s.toLowerCase().startsWith(x)){let r=s.slice(x.length).trim().toLowerCase();return e.some(i=>i.siri&&i.name.toLowerCase()===r)}return K(s,e,n)!==null}function ni(t){let e=t.voice?.locale??"en",n=[],s=(r,i)=>{if(typeof i=="string")n.push({owner:r,name:i,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(i??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};s("voice.system",t.voice?.system);for(let[r,i]of Object.entries(t.agents))(i.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||s(r,i.voice?.system);return n}function ri(t,e){if(!e.length)return[];let n=new Map,s;for(let{owner:r,name:i,locale:o,perLanguage:a}of ni(t)){if(ti(i,e,o))continue;s??=Ve(t.agents,t.voice,e);let l=n.get(i)??{voice:i,agents:[],speaksWith:{}};l.agents.includes(r)||l.agents.push(r);let c=s.get(r);r!=="voice.system"&&!a&&(l.speaksWith[r]=c?ce(c):"the OS default voice"),n.set(i,l)}return[...n.values()]}function Ne(t){let e=se(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(x)){let n=t.slice(x.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function si(t){let e=t.map(n=>{let s=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${Ne(n.voice)}: ${s}`});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")`,Cs=new Set(["Fred","Kathy","Ralph","Junior"]),Ds={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 gn(t){let e=[];for(let n of t.split(`
120
+ `)){let[s,r,i,o,a]=n.split(" ");!s||!r||!i||s.includes(".siri_")||s.startsWith("com.apple.speech.synthesis.voice.")&&!Cs.has(r)||e.push({id:s,name:r,locale:i,quality:o==="3"?"premium":o==="2"?"enhanced":"standard",gender:a==="1"?"male":a==="2"?"female":Ds[r]??null})}return e}var Ts=10*60*1e3,Ma=60*1e3,M=null,De=!1;function Te(t=Date.now(),e=Ts){if(process.platform!=="darwin")return[];if(M)t-M.at>e&&!De&&(De=!0,_s("osascript",["-l","JavaScript","-e",dn],{timeout:1e4},(n,s)=>{De=!1,n||(M={at:Date.now(),voices:[...gn(String(s)),...oe()]})}));else try{M={at:t,voices:[...gn(Rs("osascript",["-l","JavaScript","-e",dn],{encoding:"utf8",timeout:1e4})),...oe()]}}catch(n){Ee(`[voice] could not list system voices: ${String(n?.message??n).split(`
121
+ `)[0]}`),M={at:t,voices:oe()}}return M.voices}var Ee=t=>process.stderr.write(t+`
122
+ `),ae=new Set;function Na(t){Ee=t}function E(t,e){ae.has(t)||(ae.add(t),Ee(e))}function mn(t){for(let e of ae)t(e)&&ae.delete(e)}var hn=()=>{};function Fa(t){hn=t}function yn(t){try{hn(t)}catch(e){E("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var Es={premium:3,enhanced:2,standard:1},Ls=new Set(["Grandma","Grandpa"]);function fn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!Ls.has(t.name)?1:0;return Es[t.quality]*10+e}var N=t=>t.toLowerCase().split(/[-_]/)[0],pn=t=>t.id.startsWith("com.apple.voice.");function Le(t,e,n,s=new Set){let r=z(t.filter(a=>!a.siri&&N(a.locale)===N(e)),e);if(r.some(pn)&&(r=r.filter(pn)),n==="female"||n==="male"){let a=r.filter(l=>l.gender===n);a.length&&(r=a)}if(!r.length)return null;let i=r.filter(a=>a.quality===r[0].quality),o=new Set([...s].map(a=>a.toLowerCase()));return i.find(a=>!o.has(a.name.toLowerCase()))??i[0]}function z(t,e="en"){let n=e.toLowerCase().replace("_","-"),s=N(e),r=t.filter(i=>N(i.locale)===s);return(r.length?r:t).slice().sort((i,o)=>fn(o)-fn(i)||+(o.locale.toLowerCase()===n)-+(i.locale.toLowerCase()===n)||i.name.localeCompare(o.name)||i.locale.localeCompare(o.locale))}function K(t,e,n="en"){let s=t.trim();if(!s)return null;let r=e.find(c=>c.id===s);if(r)return r;if(s.toLowerCase().startsWith(x)){let c=s.slice(x.length).trim().toLowerCase(),u=z(e.filter(g=>g.siri&&g.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=K(c,e.filter(g=>N(g.locale)===N(n)),n);return d&&E(`siri:${c}`,`[voice] Siri voice "${c}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(c=>!c.siri);let i=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(s),o=(i?i[1]:s.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=z(e.filter(c=>c.name.toLowerCase()===o),n);return(i?a.find(c=>c.quality===i[2].toLowerCase()):void 0)??a[0]??null}function bn(t,e,n=new Set){let s=new Map;if(!e.length)return s;let r=new Set([...n].map(o=>o.toLowerCase())),i="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",l=a?o.gender:i,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(a?e.find(d=>d.gender===l):void 0)??c[0]??e[s.size%e.length];s.set(o.id,u),r.add(u.name.toLowerCase()),a||(i=i==="female"?"male":"female")}return s}var Os=new Set("the and is are was were i you he she we they it this that to of in for with not but yes what have has will would can your my".split(" ")),Ps=new Set("le la les des du de un une et est sont je tu il elle nous vous ils elles ce cette c'est pas pour que qui avec dans sur au aux mais tr\xE8s oui non merci bonjour votre mon".split(" ")),js=/[éèêëàâçùûîïôœ]/;function le(t){let e=(t.match(/[؀-ۿ]/g)??[]).length,n=(t.match(/[a-zA-ZÀ-ÿ]/g)??[]).length;if(e&&e>=n)return"ar";let s=0,r=0;for(let i of t.toLowerCase().replace(/[’]/g,"'").match(/[a-zà-ÿœ']+/g)??[])Os.has(i)&&s++,Ps.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?r++:js.test(i)&&(r+=.5);return s===r?null:s>r?"en":"fr"}var Oe="system",Vs=t=>t.trim().toLowerCase()===Oe,Ms="21m00Tcm4TlvDq8ikWAM";function Pe(t,e,n={},s=Te()){let r=e[t],i=r?.name||t,o=r?.voice,a=Ve(e,n,s).get(t)??null,l=Ws(t,o?.system,o?.gender,n,s);return{agentId:t,name:i,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?ue(a):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Hs(i,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var ue=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function Ns(t,e,n,s){if(!e||!n.length)return null;let r=K(e,n,s);return r||(E(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),yn(e)),r}function xn(t,e){let n=t.trim();if(n.toLowerCase().startsWith(x))return{locale:e,gender:Ce(n.slice(x.length).trim())};let s=ie(n);return s?{locale:s.locale,gender:Ce(s.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var vn=t=>t.toLowerCase().split(/[-_]/)[0],wn=(t,e)=>typeof t=="string"?t:t?.[vn(e)];function ce(t,e,n,s){if(e!==void 0)return Vs(e)?null:Ns(t,e,n,s)??void 0}var je=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Fs(t,e,n,s=new Set){let r=e.locale??"en",i=new Map,o=[],a=ce("voice.system",wn(e.system,r),n,r),l=()=>new Set([...s,...[...i.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=wn(u.system,r),g=ce(u.id,d,n,r),f=g!==void 0?g:d!==void 0&&n.length?Us(u,d,r,a,n,l()):a!==void 0&&je(a,u.gender)?a:void 0;f!==void 0?i.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of bn(o,z(n.filter(g=>!g.siri),r),c))i.set(u,d);return i}function Us(t,e,n,s,r,i){for(let a of t.fallbacks??[]){let l=ce(`${t.id}.fallbacks`,a,r,n);if(l!==void 0)return l}if(s!==void 0&&je(s,t.gender))return s;let o=xn(e,n);return Le(r,o.locale,t.gender??o.gender,i)??void 0}function Ws(t,e,n,s,r){if(typeof e=="string")return{};let i={},o=(a,l,c)=>{if(!(!l||typeof l=="string"))for(let[u,d]of Object.entries(l)){let g=ce(`${a}.${u}`,d,r,u);g===void 0&&r.length&&(g=Le(r,u,n??xn(d,u).gender)??void 0),g!==void 0&&c(g)&&(i[vn(u)]=g)}};return o("voice.system",s.system,a=>je(a,n)),o(t,e,()=>!0),i}function Ka(t,e){let n=e?le(e):null;if(!n||!(n in t.systemByLanguage))return t;let s=t.systemByLanguage[n];return{...t,systemVoice:s?.id??null,systemVoiceName:s?ue(s):null}}function Ve(t,e={},n=Te()){let s=Object.entries(t).map(([r,i])=>({id:r,system:i.voice?.system,gender:i.voice?.gender,fallbacks:i.voice?.fallbacks}));return Fs(s,e,n)}function Me(t,e){let n={provider:t.provider,elevenlabs:Bs(e,t.elevenlabsVoiceId),system:t.systemVoice,fallback:t.fallback},s=Object.entries(t.systemByLanguage??{});return s.length&&(n.languages=Object.fromEntries(s.map(([r,i])=>[r,i?.id??null]))),t.rate&&t.rate!==1&&(n.rate=t.rate),t.priority&&t.priority!=="normal"&&(n.priority=t.priority),n}function Bs(t,e){return t||e||process.env.AGENTX_VOICE_ID||Ms}function Hs(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",s=/^You are (.+?)\.?$/i.exec(n.trim());if(!s)return`Hello, this is ${t}.`;let r=s[1].replace(/\s*\([^)]*\)/g,"").trim(),[i,...o]=r.split(/,\s*/),a=o.join(", ");return a&&i.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 zs=8*60*60*1e3,Ks=500,kn=class{constructor(e=zs){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,s=Date.now()){let r=this.lastSpoke.get(Sn(e,n));return r===void 0||s-r>this.gapMs}spoke(e,n,s=Date.now()){let r=Sn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,s),this.lastSpoke.size>Ks&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},Sn=(t,e)=>`${t}\0${e}`;function $n(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 Ga(t,e,n,s={}){let r=e[t],i=Pe(t,e,s),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:i.name,voice:Me(i),persona:o||`You are ${i.name}.`,introLine:$n(i,n)}}var Gs="[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 Xa(t){let e=t;if(e?.channel!=="voice"||!e.voice||typeof e.voice!="object")return;let n=i=>typeof i=="string"?i.replace(/\s+/g," ").slice(0,200):"",s=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:s||"Hello."};return`${Gs}
123
+ ${$n(r,e.voice.introduce===!0&&!!s)}`}var ti="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",_n=(t=Zs())=>ei(t,".agentx","voice","health.json");function ni(t,e,n){let s=t.trim();if(!s||s.toLowerCase()===Oe)return!0;if(s.toLowerCase().startsWith(x)){let r=s.slice(x.length).trim().toLowerCase();return e.some(i=>i.siri&&i.name.toLowerCase()===r)}return K(s,e,n)!==null}function ri(t){let e=t.voice?.locale??"en",n=[],s=(r,i)=>{if(typeof i=="string")n.push({owner:r,name:i,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(i??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};s("voice.system",t.voice?.system);for(let[r,i]of Object.entries(t.agents))(i.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||s(r,i.voice?.system);return n}function si(t,e){if(!e.length)return[];let n=new Map,s;for(let{owner:r,name:i,locale:o,perLanguage:a}of ri(t)){if(ni(i,e,o))continue;s??=Ve(t.agents,t.voice,e);let l=n.get(i)??{voice:i,agents:[],speaksWith:{}};l.agents.includes(r)||l.agents.push(r);let c=s.get(r);r!=="voice.system"&&!a&&(l.speaksWith[r]=c?ue(c):"the OS default voice"),n.set(i,l)}return[...n.values()]}function Ne(t){let e=ie(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(x)){let n=t.slice(x.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function ii(t){let e=t.map(n=>{let s=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${Ne(n.voice)}: ${s}`});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 ${ei}. Agents switch back on their own once it is installed.`}}function ii(t=_n()){if(!In(t))return null;try{let e=JSON.parse(Xs(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function oi(t,e){Gs(Zs(t),{recursive:!0}),Js(`${t}.tmp`,JSON.stringify(e,null,2)+`
126
- `),qs(`${t}.tmp`,t)}var $n=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,s=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??_n(),i=new Map((ii(r)?.missing??[]).map(d=>[d.voice,d])),o=ri(e,n),a=o.map(d=>({...d,since:i.get(d.voice)?.since??s.toISOString(),...i.get(d.voice)?.notifiedAt?{notifiedAt:i.get(d.voice).notifiedAt}:{}})),l=[...i.keys()].filter(d=>!o.some(g=>g.voice===d));for(let d of l)this.deps.log(`[voice] ${Ne(d)} is installed again; its agents speak with it again`);l.length&&pn(d=>l.some(g=>d===g||d.endsWith(`:${g}`)));let c=a.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:g}=si(c);try{await this.deps.notify(d,g);for(let f of c)f.notifiedAt=s.toISOString();this.deps.log(`[voice] told the owner: ${c.map(f=>Ne(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:s.toISOString(),missing:a};return(!In(r)||JSON.stringify(a)!==JSON.stringify([...i.values()]))&&oi(r,u),u}finally{this.running=!1}}};import{readFileSync as Ue,writeFileSync as En,existsSync as We,readdirSync as mi,statSync as hi}from"fs";import{resolve as Be,join as yi}from"path";import{existsSync as An,mkdirSync as ai,readFileSync as li,writeFileSync as Rn}from"fs";import{dirname as ci,resolve as Cn}from"path";import{z as m}from"zod";var ui=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),di=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:ui.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),gi=m.object({version:m.literal(1),items:m.array(di).default([])}),ue=class{constructor(e){this.path=e}jsonPath(){return Cn(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return Cn(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return An(this.jsonPath())}load(){let e=this.jsonPath();if(!An(e))return{version:1,items:[]};let n=li(e,"utf-8");try{return gi.parse(JSON.parse(n))}catch(s){throw new Error(`Backlog file invalid (${e}): ${s.message}`)}}save(e){let n=this.jsonPath();ai(ci(n),{recursive:!0}),Rn(n,JSON.stringify(e,null,2)+`
127
- `),Rn(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(i=>i.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let s=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??s,updatedAt:s};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),s=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),i=[];for(let o of e){if(s.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),i.push(a),s.add(a.id)}return i.length&&this.save(n),i}update(e,n){let s=this.load(),r=s.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let i={...s.items[r],...n,id:s.items[r].id,createdAt:s.items[r].createdAt,updatedAt:new Date().toISOString()};return s.items[r]=i,this.save(s),i}remove(e){let n=this.load(),s=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===s?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],s={doing:[],blocked:[],todo:[],done:[]};for(let i of e.items)s[i.status].push(i);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[i,o]of r)if(s[i].length){n.push(`## ${o}`,"");for(let a of s[i]){let l=i==="done"?"x":" ",c=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(`- [${l}] ${c}${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 nl(t){return`${t.type}:${t.project}:${t.iid}`}function Dn(t,e,n){let s=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let i of t){let o=r.find(a=>a.agentId===i);o?.gitlabUsernames?.length?s.push(o.gitlabUsernames[0]):s.push(i)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let i of t){let o=r.find(a=>a.agentId===i);o?.githubUsernames?.length?s.push(o.githubUsernames[0]):s.push(i)}}return s}async function Fe(t,e,n,s=()=>{}){return t.source?t.source.type==="gitlab"?fi(t.source,e,n,s):t.source.type==="github"?pi(t.source,e,n,s):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function fi(t,e,n,s){let r=n.channels.gitlab,i=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!i||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],l=async(f,p={})=>fetch(`${o}/api/v4${f}`,{...p,headers:{"PRIVATE-TOKEN":i,"Content-Type":"application/json",...p.headers||{}}}),c=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async p=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(p)}`,{headers:{"PRIVATE-TOKEN":i}});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(p=>typeof p=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await l(`/projects/${c}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let p=await f.json();Array.isArray(p)&&p[0]?.id&&(d=p[0].id)}}catch(f){s(`[backlog-sync] milestone lookup failed: ${f.message}`)}let g={};if(e.title!==void 0&&(g.title=e.title),e.description!==void 0&&(g.description=e.description),e.labels!==void 0&&(g.labels=e.labels.join(",")),e.addLabels?.length&&(g.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(g.remove_labels=e.removeLabels.join(",")),u!==void 0&&(g.assignee_ids=u),d!==void 0&&(g.milestone_id=d),e.state&&(g.state_event=e.state==="closed"?"close":"reopen"),Object.keys(g).length)try{let f=await l(`/projects/${c}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(g)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let p=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${p.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 l(`/projects/${c}/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 pi(t,e,n,s){let i=n.channels.github?.token;if(!i)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(g,f={})=>fetch(`https://api.github.com${g}`,{...f,headers:{Authorization:`Bearer ${i}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),l=t.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let g=await a(`/repos/${l}/milestones?state=all&per_page=100`);if(g.ok){let f=await g.json(),p=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;p?.number&&(c=p.number)}}catch(g){s(`[backlog-sync] github milestone lookup failed: ${g.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let g=await a(`/repos/${l}/issues/${t.iid}`);if(g.ok){let f=await g.json(),p=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...p,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(g){s(`[backlog-sync] github label fetch failed: ${g.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let g=await a(`/repos/${l}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:g.ok,status:g.status}),!g.ok){let f=await g.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${g.status}: ${f.slice(0,200)}`,url:t.url}}}catch(g){return o.push({kind:"PATCH issue",ok:!1,error:g.message}),{ok:!1,attempts:o,error:g.message,url:t.url}}if(e.note)try{let g=await a(`/repos/${l}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:g.ok,status:g.status})}catch(g){o.push({kind:"POST comment",ok:!1,error:g.message})}return{ok:o.every(g=>g.ok),attempts:o,url:t.url}}var He=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,de=/@([a-z0-9_-]+)/i,Tn=/\[time:\s*([0-9hm\s]+)\]/i;function bi(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 ze=class{constructor(e,n,s=()=>{}){this.path=e;this.daemon=n;this.log=s;this.store=new ue(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Be(process.cwd(),this.path);return We(e)?Ue(e,"utf-8").split(`
129
- `):[]}writeMd(e){let n=Be(process.cwd(),this.path);En(n,e.join(`
130
- `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(i=>i.status!=="done"&&(!i.assignee||i.assignee.toLowerCase()===e.toLowerCase())).map(i=>this.toWorkItem(i));let n=this.readMd(),s=[];for(let r=0;r<n.length;r++){let i=n[r].match(He);if(!i||i[2].toLowerCase()==="x")continue;let a=i[3],l=a.match(de);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=a.match(Tn),u=a.replace(de,"").replace(Tn,"").trim();s.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?bi(c[1]):void 0,priority:r})}return s}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 s=this.store.findById(n);if(!s)return;let r=this.store.update(n,{assignee:s.assignee||e,status:"doing"});if(r.source&&this.daemon){let i=Dn([r.assignee||e],r.source,this.daemon);Fe(r,{assigneeUsernames:i,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 l=this.store.update(e,a);if(l.source&&this.daemon){let c={};n.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):n.status==="blocked"&&(c.addLabels=["Blocked"]),n.note&&(c.note=n.note),Object.keys(c).length&&Fe(l,c,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let s=parseInt(e.slice(8),10),r=this.readMd(),i=r[s];if(!i)throw new Error(`backlog line ${s} missing`);if(!i.match(He))throw new Error(`backlog line ${s} not a checkbox`);if(n.status==="done"){r[s]=i.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(s+1,0,a)}else n.status==="blocked"?r.splice(s+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(s+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},Ke=class{constructor(e,n){this.root=e;this.glob=n}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,n){if(We(e))for(let s of mi(e)){let r=yi(e,s);hi(r).isDirectory()?this.walk(r,n):s.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Be(process.cwd(),this.root),n);let s=[];for(let r of n){let i=Ue(r,"utf-8").split(`
131
- `);for(let o=0;o<i.length;o++){let a=i[o].match(He);if(!a||a[2].toLowerCase()==="x")continue;let l=a[3].match(de);!l||l[1].toLowerCase()!==e.toLowerCase()||s.push({id:`wiki:${r}:${o}`,title:a[3].replace(de,"").trim(),assignee:l[1],priority:o})}}return s}async claim(){}async report(e,n){let s=e.split(":"),r=parseInt(s[s.length-1],10),i=s.slice(1,-1).join(":");if(!We(i))return;let o=Ue(i,"utf-8").split(`
132
- `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),En(i,o.join(`
133
- `)))}},Ge=class{constructor(e,n,s,r,i){this.host=e;this.token=n;this.projects=s;this.agentUsernames=r;this.log=i}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,s]of Object.entries(this.agentUsernames))if(s.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let s=e.references?.full?.split("#")[0]||n,r=[],i;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(i=e.labels.map(c=>({name:c.name,color:c.color,text_color:c.text_color})),r=i.map(c=>c.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=a[0]?.username;return{id:`gitlab:${s}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:i,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let s=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!s.ok)throw new Error(`GitLab ${s.status}: ${await s.text().catch(()=>"")}`);return s.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let s=[],r=this.projects.length?this.projects:["__ALL__"];for(let i of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(i)}&state=opened&scope=all&per_page=20`,l=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,o);d.assignee=e,s.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${i} on ${o}: ${a.message}`)}return s}async claim(e,n){let{project:s,iid:r,type:i}=this.parseId(n),o=`/projects/${encodeURIComponent(s)}/${i==="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:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),l=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(s)}/${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(s)}/${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(s)}/${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,s=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,i=e.state??"opened";r.set("state",i),r.set("updated_after",s),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 c of o)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let g of d)a.push(this.mapIssue(g,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=a;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,n){let{project:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:s}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${s}?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:s,iid:r}=this.parseId(e),i;n.assigneeUsernames&&(i=(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 c=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(o=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${c.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(",")),i!==void 0&&(a.assignee_ids=i),o!==void 0&&(a.milestone_id=o);let l=await this.api(`/projects/${encodeURIComponent(s)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(l,s)}async listMembers(){let e=new Map;for(let n of this.projects)try{let s=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of s)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(s){this.log(`[board] listMembers failed for ${n}: ${s.message}`)}return[...e.values()].sort((n,s)=>n.username.localeCompare(s.username))}async listMilestones(){let e=new Map;for(let s of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(s)}/milestones?per_page=100`);for(let i of r)i.title&&!e.has(i.title)&&e.set(i.title,{id:i.id,title:i.title,state:i.state,dueDate:i.due_date})}catch(r){this.log(`[board] listMilestones failed for ${s}: ${r.message}`)}let n=[...e.values()];return n.sort((s,r)=>s.state!==r.state?s.state==="active"?-1:1:s.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 s,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(s=(await Promise.all(r.map(async c=>{try{let u=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${c}: ${u.message}`),null}}))).filter(c=>typeof c=="number"));let i;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(i=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};s?.length&&(o.assignee_ids=s),i!==void 0&&(o.milestone_id=i);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,s){await this.transitionMany(e,n?[n]:[],s?[s]:[])}async transitionMany(e,n,s){let{project:r,iid:i,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",l=new URLSearchParams;n.length&&l.set("add_labels",n.join(",")),s.length&&l.set("remove_labels",s.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${i}?${l.toString()}`,{method:"PUT"})}parseId(e){let s=e.replace(/^gitlab:/,"").split(":"),r=s.pop(),i=s.pop()==="mr"?"mr":"issue";return{project:s.join(":"),type:i,iid:r}}};function cl(t,e,n){let s=t.workSource;switch(s.type){case"backlog":return new ze(s.path,e,n);case"wiki":return new Ke(s.path,s.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let i={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(i[a.agentId]=a.gitlabUsernames);let o=s.projects.length?s.projects:r.routes.map(a=>a.project);return new Ge(r.host,r.token,o,i,n)}}}var Xe="unmapped";function qe(t,e=[]){if(!t)return Xe;let n=e.find(r=>r.id===t);if(n?.client)return n.client;let s=t.indexOf("/");return s>0?t.slice(0,s):t}function wi(t){let e=new Map,n=t.projects??[],s=t.orgChart??{};for(let i of n)i.pm&&(e.has(i.pm)||e.set(i.pm,qe(i.id,n)));let r=(i,o=new Set)=>{if(e.has(i))return e.get(i);if(o.has(i))return;o.add(i);let a=s[i]?.reportsTo;if(!a)return;let l=r(a,o);return l&&e.set(i,l),l};for(let i of Object.keys(s))r(i);return e}function ki(t,e,n=[]){if(!n.length)return;let s=n.filter(r=>!r.channel||r.channel===t);return s.find(r=>r.chatId&&e.chatId&&r.chatId===e.chatId)??s.find(r=>r.username&&e.username&&r.username===e.username)??s.find(r=>r.senderId&&e.senderId&&r.senderId===e.senderId)??s.find(r=>r.channel&&!r.chatId&&!r.username&&!r.senderId)}function dl(t,e){let n=ki(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 s=wi(e).get(t.agentId);if(s)return s}return Xe}function gl(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[s,r,...i]=n,o=i.join(":"),a={agentId:e||s,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var Si=t=>t===Xe?"internal":"client";function xi(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??Si(t),respondWithinMinutes:vi(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function fl(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=>xi(n,t))}function vi(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 $i=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Ii=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function Ln(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(Ii)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],s=n[2],r=_i(s);if(!r)return{cleanText:t};let i=n.index??0,o=n[1]??"";return{cleanText:(t.slice(0,i)+o+t.slice(i+n[0].length)).trim(),ui:r}}function ml(t){if(!t||!t.includes("agentx:ui"))return t;let e=$i.exec(t);return e?t.slice(0,e.index).trimEnd():t}function _i(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 s=[],r=[],i=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?s.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&&i.push(o.label));s.length&&(n.buttons=s),r.length&&(n.replies=r),i.length&&(n.skippedActions=i)}if(e.poll&&typeof e.poll=="object"){let s=e.poll.question,r=e.poll.options;typeof s=="string"&&s.trim()&&Array.isArray(r)&&r.filter(i=>typeof i=="string").length>=2&&(n.poll={question:s,options:r.filter(i=>typeof i=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:s,url:r,caption:i}=e.media;["image","document","audio","video"].includes(s)&&typeof r=="string"&&r&&(n.media={type:s,url:r,...typeof i=="string"?{caption:i}:{}})}if(Array.isArray(e.quickReplies)){let s=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());s.length&&(n.quickReplies=s)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function yl(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 Ai=5*6e4;function D(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var On=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],s=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(D)),this.log=s,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${D(n)}`}cleanupExpired(){let e=Date.now();for(let[n,s]of this.pending){let r=s.filter(i=>i.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==s.length&&this.pending.set(n,r)}for(let[n,s]of this.recentRings)s<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,s){return this.addSubscriber(e,n,{kind:"sse",res:s})}subscribeInternal(e,n,s){return this.addSubscriber(e,n,{kind:"callback",deliver:s})}addSubscriber(e,n,s){let r={callId:e,recipient:n,sink:s};this.subs.add(r);let i=s.kind==="sse"?"sse":"internal";this.log(`subscribe[${i}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let l=Date.now(),c=a.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(o),c.length&&this.log(`flushed ${c.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${i}] 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 ${ti}. Agents switch back on their own once it is installed.`}}function oi(t=_n()){if(!An(t))return null;try{let e=JSON.parse(qs(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function ai(t,e){Xs(Qs(t),{recursive:!0}),Ys(`${t}.tmp`,JSON.stringify(e,null,2)+`
126
+ `),Js(`${t}.tmp`,t)}var In=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,s=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??_n(),i=new Map((oi(r)?.missing??[]).map(d=>[d.voice,d])),o=si(e,n),a=o.map(d=>({...d,since:i.get(d.voice)?.since??s.toISOString(),...i.get(d.voice)?.notifiedAt?{notifiedAt:i.get(d.voice).notifiedAt}:{}})),l=[...i.keys()].filter(d=>!o.some(g=>g.voice===d));for(let d of l)this.deps.log(`[voice] ${Ne(d)} is installed again; its agents speak with it again`);l.length&&mn(d=>l.some(g=>d===g||d.endsWith(`:${g}`)));let c=a.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:g}=ii(c);try{await this.deps.notify(d,g);for(let f of c)f.notifiedAt=s.toISOString();this.deps.log(`[voice] told the owner: ${c.map(f=>Ne(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:s.toISOString(),missing:a};return(!An(r)||JSON.stringify(a)!==JSON.stringify([...i.values()]))&&ai(r,u),u}finally{this.running=!1}}};import{readFileSync as Ue,writeFileSync as Ln,existsSync as We,readdirSync as hi,statSync as yi}from"fs";import{resolve as Be,join as bi}from"path";import{existsSync as Rn,mkdirSync as li,readFileSync as ci,writeFileSync as Cn}from"fs";import{dirname as ui,resolve as Dn}from"path";import{z as m}from"zod";var di=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),gi=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:di.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),fi=m.object({version:m.literal(1),items:m.array(gi).default([])}),de=class{constructor(e){this.path=e}jsonPath(){return Dn(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return Dn(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return Rn(this.jsonPath())}load(){let e=this.jsonPath();if(!Rn(e))return{version:1,items:[]};let n=ci(e,"utf-8");try{return fi.parse(JSON.parse(n))}catch(s){throw new Error(`Backlog file invalid (${e}): ${s.message}`)}}save(e){let n=this.jsonPath();li(ui(n),{recursive:!0}),Cn(n,JSON.stringify(e,null,2)+`
127
+ `),Cn(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(i=>i.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let s=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??s,updatedAt:s};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),s=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),i=[];for(let o of e){if(s.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),i.push(a),s.add(a.id)}return i.length&&this.save(n),i}update(e,n){let s=this.load(),r=s.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let i={...s.items[r],...n,id:s.items[r].id,createdAt:s.items[r].createdAt,updatedAt:new Date().toISOString()};return s.items[r]=i,this.save(s),i}remove(e){let n=this.load(),s=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===s?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],s={doing:[],blocked:[],todo:[],done:[]};for(let i of e.items)s[i.status].push(i);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[i,o]of r)if(s[i].length){n.push(`## ${o}`,"");for(let a of s[i]){let l=i==="done"?"x":" ",c=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(`- [${l}] ${c}${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 ol(t){return`${t.type}:${t.project}:${t.iid}`}function Tn(t,e,n){let s=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let i of t){let o=r.find(a=>a.agentId===i);o?.gitlabUsernames?.length?s.push(o.gitlabUsernames[0]):s.push(i)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let i of t){let o=r.find(a=>a.agentId===i);o?.githubUsernames?.length?s.push(o.githubUsernames[0]):s.push(i)}}return s}async function Fe(t,e,n,s=()=>{}){return t.source?t.source.type==="gitlab"?pi(t.source,e,n,s):t.source.type==="github"?mi(t.source,e,n,s):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function pi(t,e,n,s){let r=n.channels.gitlab,i=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!i||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],l=async(f,p={})=>fetch(`${o}/api/v4${f}`,{...p,headers:{"PRIVATE-TOKEN":i,"Content-Type":"application/json",...p.headers||{}}}),c=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async p=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(p)}`,{headers:{"PRIVATE-TOKEN":i}});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(p=>typeof p=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await l(`/projects/${c}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let p=await f.json();Array.isArray(p)&&p[0]?.id&&(d=p[0].id)}}catch(f){s(`[backlog-sync] milestone lookup failed: ${f.message}`)}let g={};if(e.title!==void 0&&(g.title=e.title),e.description!==void 0&&(g.description=e.description),e.labels!==void 0&&(g.labels=e.labels.join(",")),e.addLabels?.length&&(g.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(g.remove_labels=e.removeLabels.join(",")),u!==void 0&&(g.assignee_ids=u),d!==void 0&&(g.milestone_id=d),e.state&&(g.state_event=e.state==="closed"?"close":"reopen"),Object.keys(g).length)try{let f=await l(`/projects/${c}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(g)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let p=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${p.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 l(`/projects/${c}/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 mi(t,e,n,s){let i=n.channels.github?.token;if(!i)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(g,f={})=>fetch(`https://api.github.com${g}`,{...f,headers:{Authorization:`Bearer ${i}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),l=t.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let g=await a(`/repos/${l}/milestones?state=all&per_page=100`);if(g.ok){let f=await g.json(),p=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;p?.number&&(c=p.number)}}catch(g){s(`[backlog-sync] github milestone lookup failed: ${g.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let g=await a(`/repos/${l}/issues/${t.iid}`);if(g.ok){let f=await g.json(),p=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...p,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(g){s(`[backlog-sync] github label fetch failed: ${g.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let g=await a(`/repos/${l}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:g.ok,status:g.status}),!g.ok){let f=await g.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${g.status}: ${f.slice(0,200)}`,url:t.url}}}catch(g){return o.push({kind:"PATCH issue",ok:!1,error:g.message}),{ok:!1,attempts:o,error:g.message,url:t.url}}if(e.note)try{let g=await a(`/repos/${l}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:g.ok,status:g.status})}catch(g){o.push({kind:"POST comment",ok:!1,error:g.message})}return{ok:o.every(g=>g.ok),attempts:o,url:t.url}}var He=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,ge=/@([a-z0-9_-]+)/i,En=/\[time:\s*([0-9hm\s]+)\]/i;function wi(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 ze=class{constructor(e,n,s=()=>{}){this.path=e;this.daemon=n;this.log=s;this.store=new de(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Be(process.cwd(),this.path);return We(e)?Ue(e,"utf-8").split(`
129
+ `):[]}writeMd(e){let n=Be(process.cwd(),this.path);Ln(n,e.join(`
130
+ `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(i=>i.status!=="done"&&(!i.assignee||i.assignee.toLowerCase()===e.toLowerCase())).map(i=>this.toWorkItem(i));let n=this.readMd(),s=[];for(let r=0;r<n.length;r++){let i=n[r].match(He);if(!i||i[2].toLowerCase()==="x")continue;let a=i[3],l=a.match(ge);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=a.match(En),u=a.replace(ge,"").replace(En,"").trim();s.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?wi(c[1]):void 0,priority:r})}return s}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 s=this.store.findById(n);if(!s)return;let r=this.store.update(n,{assignee:s.assignee||e,status:"doing"});if(r.source&&this.daemon){let i=Tn([r.assignee||e],r.source,this.daemon);Fe(r,{assigneeUsernames:i,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 l=this.store.update(e,a);if(l.source&&this.daemon){let c={};n.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):n.status==="blocked"&&(c.addLabels=["Blocked"]),n.note&&(c.note=n.note),Object.keys(c).length&&Fe(l,c,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let s=parseInt(e.slice(8),10),r=this.readMd(),i=r[s];if(!i)throw new Error(`backlog line ${s} missing`);if(!i.match(He))throw new Error(`backlog line ${s} not a checkbox`);if(n.status==="done"){r[s]=i.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(s+1,0,a)}else n.status==="blocked"?r.splice(s+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(s+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},Ke=class{constructor(e,n){this.root=e;this.glob=n}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,n){if(We(e))for(let s of hi(e)){let r=bi(e,s);yi(r).isDirectory()?this.walk(r,n):s.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Be(process.cwd(),this.root),n);let s=[];for(let r of n){let i=Ue(r,"utf-8").split(`
131
+ `);for(let o=0;o<i.length;o++){let a=i[o].match(He);if(!a||a[2].toLowerCase()==="x")continue;let l=a[3].match(ge);!l||l[1].toLowerCase()!==e.toLowerCase()||s.push({id:`wiki:${r}:${o}`,title:a[3].replace(ge,"").trim(),assignee:l[1],priority:o})}}return s}async claim(){}async report(e,n){let s=e.split(":"),r=parseInt(s[s.length-1],10),i=s.slice(1,-1).join(":");if(!We(i))return;let o=Ue(i,"utf-8").split(`
132
+ `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),Ln(i,o.join(`
133
+ `)))}},Ge=class{constructor(e,n,s,r,i){this.host=e;this.token=n;this.projects=s;this.agentUsernames=r;this.log=i}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,s]of Object.entries(this.agentUsernames))if(s.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let s=e.references?.full?.split("#")[0]||n,r=[],i;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(i=e.labels.map(c=>({name:c.name,color:c.color,text_color:c.text_color})),r=i.map(c=>c.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=a[0]?.username;return{id:`gitlab:${s}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:i,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let s=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!s.ok)throw new Error(`GitLab ${s.status}: ${await s.text().catch(()=>"")}`);return s.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let s=[],r=this.projects.length?this.projects:["__ALL__"];for(let i of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(i)}&state=opened&scope=all&per_page=20`,l=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,o);d.assignee=e,s.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${i} on ${o}: ${a.message}`)}return s}async claim(e,n){let{project:s,iid:r,type:i}=this.parseId(n),o=`/projects/${encodeURIComponent(s)}/${i==="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:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),l=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(s)}/${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(s)}/${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(s)}/${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,s=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,i=e.state??"opened";r.set("state",i),r.set("updated_after",s),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 c of o)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let g of d)a.push(this.mapIssue(g,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=a;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,n){let{project:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:s}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${s}?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:s,iid:r}=this.parseId(e),i;n.assigneeUsernames&&(i=(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 c=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(o=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${c.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(",")),i!==void 0&&(a.assignee_ids=i),o!==void 0&&(a.milestone_id=o);let l=await this.api(`/projects/${encodeURIComponent(s)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(l,s)}async listMembers(){let e=new Map;for(let n of this.projects)try{let s=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of s)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(s){this.log(`[board] listMembers failed for ${n}: ${s.message}`)}return[...e.values()].sort((n,s)=>n.username.localeCompare(s.username))}async listMilestones(){let e=new Map;for(let s of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(s)}/milestones?per_page=100`);for(let i of r)i.title&&!e.has(i.title)&&e.set(i.title,{id:i.id,title:i.title,state:i.state,dueDate:i.due_date})}catch(r){this.log(`[board] listMilestones failed for ${s}: ${r.message}`)}let n=[...e.values()];return n.sort((s,r)=>s.state!==r.state?s.state==="active"?-1:1:s.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 s,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(s=(await Promise.all(r.map(async c=>{try{let u=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${c}: ${u.message}`),null}}))).filter(c=>typeof c=="number"));let i;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(i=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};s?.length&&(o.assignee_ids=s),i!==void 0&&(o.milestone_id=i);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,s){await this.transitionMany(e,n?[n]:[],s?[s]:[])}async transitionMany(e,n,s){let{project:r,iid:i,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",l=new URLSearchParams;n.length&&l.set("add_labels",n.join(",")),s.length&&l.set("remove_labels",s.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${i}?${l.toString()}`,{method:"PUT"})}parseId(e){let s=e.replace(/^gitlab:/,"").split(":"),r=s.pop(),i=s.pop()==="mr"?"mr":"issue";return{project:s.join(":"),type:i,iid:r}}};function fl(t,e,n){let s=t.workSource;switch(s.type){case"backlog":return new ze(s.path,e,n);case"wiki":return new Ke(s.path,s.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let i={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(i[a.agentId]=a.gitlabUsernames);let o=s.projects.length?s.projects:r.routes.map(a=>a.project);return new Ge(r.host,r.token,o,i,n)}}}var Xe="unmapped";function qe(t,e=[]){if(!t)return Xe;let n=e.find(r=>r.id===t);if(n?.client)return n.client;let s=t.indexOf("/");return s>0?t.slice(0,s):t}function ki(t){let e=new Map,n=t.projects??[],s=t.orgChart??{};for(let i of n)i.pm&&(e.has(i.pm)||e.set(i.pm,qe(i.id,n)));let r=(i,o=new Set)=>{if(e.has(i))return e.get(i);if(o.has(i))return;o.add(i);let a=s[i]?.reportsTo;if(!a)return;let l=r(a,o);return l&&e.set(i,l),l};for(let i of Object.keys(s))r(i);return e}function Si(t,e,n=[]){if(!n.length)return;let s=n.filter(r=>!r.channel||r.channel===t);return s.find(r=>r.chatId&&e.chatId&&r.chatId===e.chatId)??s.find(r=>r.username&&e.username&&r.username===e.username)??s.find(r=>r.senderId&&e.senderId&&r.senderId===e.senderId)??s.find(r=>r.channel&&!r.chatId&&!r.username&&!r.senderId)}function ml(t,e){let n=Si(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 s=ki(e).get(t.agentId);if(s)return s}return Xe}function hl(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[s,r,...i]=n,o=i.join(":"),a={agentId:e||s,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var xi=t=>t===Xe?"internal":"client";function vi(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??xi(t),respondWithinMinutes:$i(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function yl(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=>vi(n,t))}function $i(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 Ii=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Ai=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function On(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(Ai)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],s=n[2],r=_i(s);if(!r)return{cleanText:t};let i=n.index??0,o=n[1]??"";return{cleanText:(t.slice(0,i)+o+t.slice(i+n[0].length)).trim(),ui:r}}function wl(t){if(!t||!t.includes("agentx:ui"))return t;let e=Ii.exec(t);return e?t.slice(0,e.index).trimEnd():t}function _i(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 s=[],r=[],i=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?s.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&&i.push(o.label));s.length&&(n.buttons=s),r.length&&(n.replies=r),i.length&&(n.skippedActions=i)}if(e.poll&&typeof e.poll=="object"){let s=e.poll.question,r=e.poll.options;typeof s=="string"&&s.trim()&&Array.isArray(r)&&r.filter(i=>typeof i=="string").length>=2&&(n.poll={question:s,options:r.filter(i=>typeof i=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:s,url:r,caption:i}=e.media;["image","document","audio","video"].includes(s)&&typeof r=="string"&&r&&(n.media={type:s,url:r,...typeof i=="string"?{caption:i}:{}})}if(Array.isArray(e.quickReplies)){let s=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());s.length&&(n.quickReplies=s)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function Sl(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 Ri=5*6e4;function D(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var Pn=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],s=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(D)),this.log=s,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${D(n)}`}cleanupExpired(){let e=Date.now();for(let[n,s]of this.pending){let r=s.filter(i=>i.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==s.length&&this.pending.set(n,r)}for(let[n,s]of this.recentRings)s<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,s){return this.addSubscriber(e,n,{kind:"sse",res:s})}subscribeInternal(e,n,s){return this.addSubscriber(e,n,{kind:"callback",deliver:s})}addSubscriber(e,n,s){let r={callId:e,recipient:n,sink:s};this.subs.add(r);let i=s.kind==="sse"?"sse":"internal";this.log(`subscribe[${i}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let l=Date.now(),c=a.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(o),c.length&&this.log(`flushed ${c.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${i}] 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=D(e.to);if(n===D(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let s of this.subs)if(s.callId===e&&D(s.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(D(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let s=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>s)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,s+Ai),this.ringHandler)try{this.ringHandler(e)}catch(i){this.log(`ringHandler threw: ${i.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let s=this.pendingKey(e.callId,e.to),r=this.pending.get(s)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(s,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,s=D(e.to);for(let r of this.subs)r.callId===e.callId&&D(r.recipient)===s&&(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{closeSync as G,createReadStream as Ri,fstatSync as Ci,openSync as Di,realpathSync as Pn}from"fs";import{isAbsolute as Ti,resolve as jn,sep as Vn}from"path";var vl="/app-files",Ei=/^[A-Za-z0-9_.:-]{1,64}$/;function Li(t,e,n=process.cwd()){if(!e||e.length>Z.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 ${be}/ first`};if(!ye(e))return{ok:!1,status:415,error:"this type of file is not served"};let s;try{s=Pn(jn(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=Pn(Ti(e)?e:jn(s,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(s+Vn))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${be}/ first`};let i=ye(r);return i?{ok:!0,path:r,...i}:{ok:!1,status:415,error:"this type of file is not served"}}function Oi(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 Pi(t,e,n){return{"Content-Type":t,"Content-Disposition":Oi(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 ji(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let s,r;return n[1]?(s=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(s=Math.max(0,e-Number(n[2])),r=e-1),s>r||s>=e?"unsatisfiable":{start:s,end:r}}function $l(t,e,n,s){let r=(C,O)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(O))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let i=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!Ei.test(i))return r(400,{error:"bad agent id"});let a=s.workspaceOf(i);if(!a)return r(404,{error:`no agent "${i}" on this computer`});let l=Li(a,o,s.cwd);if(!l.ok)return s.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${i}: ${l.error}`),r(l.status,{error:l.error});let c;try{c=Di(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=Ci(c);if(!C.isFile())return G(c),r(404,{error:"not a file"});u=C.size}catch{return G(c),r(404,{error:"file not found"})}if(u>Z.bytes)return G(c),r(413,{error:`the file is larger than ${Z.bytes/1024/1024} MB`});let d=l.path.split(Vn).pop()||"file",g=Pi(l.mime,d,l.kind),f=ji(t.headers.range,u);if(f==="unsatisfiable"){G(c),e.writeHead(416,{...g,"Content-Range":`bytes */${u}`}),e.end();return}let{start:p,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...g,"Content-Length":String(u?h-p+1:0),...f?{"Content-Range":`bytes ${p}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){G(c),e.end();return}let y=Ri("",{fd:c,start:p,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as X}from"child_process";import{readFileSync as Vi,writeFileSync as Mi}from"fs";import{tmpdir as Ni}from"os";import{join as Fi}from"path";var Mn=t=>t&&t!==1?Math.round(175*t):null,ge=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function Ui(){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=Vi(t,"utf8").trim();if(e)return e}catch{}return null}function Ll(t=Ui()){let e=0;return async(n,s)=>{if(n.voice.provider==="system")return null;if(!t){if(n.voice.fallback)return null;throw new Error("ElevenLabs is the voice provider but no key is set")}try{let r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${n.voice.elevenlabs}/stream?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n.text,model_id:"eleven_flash_v2_5",...ge(n.voice.rate)?{voice_settings:{speed:ge(n.voice.rate)}}:{}}),signal:s});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let i=Fi(Ni(),`agentx-say-${process.pid}-${++e}.mp3`);return Mi(i,Buffer.from(await r.arrayBuffer())),i}catch(r){if(s.aborted||!n.voice.fallback)throw r;return E(`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 Nn(t,e){let n=t.languages&&ae(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var Wi=(t,e="")=>{let n=Nn(t,e),s=Mn(t.rate);return[...n&&!on(n)?["-v",n]:[],...s?["-r",String(s)]:[]]};function Bi(t,e,n){if(!n)return["say",Wi(t,e)];let s=Nn(t,e);return["/bin/sh",[n,...s?[s]:[]]]}function Ol(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Pl(t=Je()){if(t)try{X("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function jl(t=Je()){if(t)try{X("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Je(t={},e){if(!Re(t))return null;try{return cn(e)}catch(n){return E("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
137
- `)[0]}); Siri voices will not switch`),null}}var Vl=(t,e)=>{if(!t){let[n,s]=Bi(e.voice,e.text,Je()),r=Mn(e.voice.rate),i=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=X(n,s,{stdio:["pipe","ignore","ignore"],env:i});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?X("afplay",[t],{stdio:"ignore"}):X("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Fn}from"child_process";import{accessSync as Hi,constants as zi,readFileSync as Un}from"fs";import{homedir as Ki}from"os";import{basename as N,delimiter as Wn,dirname as Gi,extname as Xi,join as Ye}from"path";var T={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Bn(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)>T.ms+2e3?{status:413,error:Qe()}:null}var Qe=()=>`The recording is longer than ${T.ms/6e4} minutes.`,qi={"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 Hn(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return qi[e]??null}function zn(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 et(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 Ze(t,e,n=process.env.PATH??""){let s=Ki(),r=[Ye(s,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Wn).filter(Boolean)];for(let i of[e,...r.map(o=>Ye(o,t))])if(i)try{return Hi(i,zi.X_OK),i}catch{}return null}function Bl(t){return{key:t,mlx:Ze("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:Ze("whisper",process.env.AGENTX_WHISPER),ffmpeg:Ji()}}var Ji=()=>Ze("ffmpeg",process.env.AGENTX_FFMPEG);async function Kn(t,e){return e?Yi(t,e):null}async function Yi(t,e){let n=String(T.ms/1e3+5);try{let r=[...(await Zi(e,["-nostdin","-hide_banner","-t",n,"-i",t,"-f","null","-"],3e4)).matchAll(/time=(\d+):(\d+):(\d+(?:\.\d+)?)/g)],i=r[r.length-1];return i?Number(i[1])*3600+Number(i[2])*60+Number(i[3]):null}catch{return null}}async function Gn(t,e,n,s){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Un(t)],{type:e}),N(t));let i=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:s??AbortSignal.timeout(6e4)});if(!i.ok)throw new Error(`ElevenLabs ${i.status}: ${(await i.text().catch(()=>"")).slice(0,160)}`);let o=await i.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Xn(t,e,n,s,r){let i=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:`${Gi(s)}${Wn}${process.env.PATH??""}`};await Qi(e,i,12e4,o);try{return Un(Ye(r,N(n,Xi(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function Zi(t,e,n){return new Promise((s,r)=>{let i=Fn(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{i.kill("SIGKILL"),r(new Error(`${N(t)} took too long`))},n);i.stderr.on("data",l=>{o=(o+l).slice(-8192)}),i.on("error",l=>{clearTimeout(a),r(l)}),i.on("exit",l=>{clearTimeout(a),l===0?s(o):r(new Error(`${N(t)} exited ${l}`))})})}function Qi(t,e,n,s=process.env){return new Promise((r,i)=>{let o=Fn(t,e,{stdio:["ignore","pipe","pipe"],env:s}),a="",l="",c=setTimeout(()=>{o.kill("SIGKILL"),i(new Error(`${N(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{l.length<4096&&(l+=u)}),o.on("error",u=>{clearTimeout(c),i(u)}),o.on("exit",u=>{clearTimeout(c),u===0?r(a):i(new Error(`${N(t)} exited ${u}: ${l.trim().split(`
138
- `).pop()?.slice(0,160)??""}`))})})}function qn(t,e=800){let n=t;return n=n.replace(/```[\s\S]*?```/g,". "),n=n.replace(/`[^`]*`/g,""),n=n.replace(/\*\*(.*?)\*\*/g,"$1"),n=n.replace(/__(.*?)__/g,"$1"),n=n.replace(/\*([^*]+)\*/g,"$1"),n=n.replace(/_([^_]+)_/g,"$1"),n=n.replace(/~~(.*?)~~/g,"$1"),n=n.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),n=n.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),n=n.replace(/^#{1,6}\s+/gm,""),n=n.replace(/^[\s]*[-*+]\s+/gm,". "),n=n.replace(/^[\s]*\d+\.\s+/gm,". "),n=n.replace(/^[-=_]{3,}$/gm,""),n=n.replace(/^>\s*/gm,""),n=n.replace(/https?:\/\/\S+/g,"link"),n=n.replace(/\/\w+(\/\w+)+/g,s=>s.split("/").filter(Boolean).join(" slash ")),n=n.replace(/&/g," and "),n=n.replace(/@/g," at "),n=n.replace(/=>/g," returns "),n=n.replace(/->/g," to "),n=n.replace(/\|/g," or "),n=n.replace(/\be\.g\./gi,"for example"),n=n.replace(/\bi\.e\./gi,"that is"),n=n.replace(/\betc\./gi,"etcetera"),n=n.replace(/\bvs\.?\b/gi,"versus"),n=n.replace(/\n{2,}/g,". "),n=n.replace(/\n/g," "),n=n.replace(/\s+/g," "),n=n.replace(/\.\s*\./g,"."),n=n.replace(/\s+([.,!?])/g,"$1"),n=n.trim().replace(/^[.,:;]+\s*/,""),n.length>e&&(n=n.slice(0,e).replace(/\s+\S*$/,"")+"..."),n}import{mkdtemp as eo,rm as to,writeFile as no}from"fs/promises";import{tmpdir as ro}from"os";import{join as Jn}from"path";var so=1500,io=64*1024,oo=2,tt=0;function tc(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function nc(t,e,n,s){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?ao(t,e,s):uo(t,e,s)}async function ao(t,e,n){let s=String(t.headers["content-type"]||""),r=Hn(s);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let i=Bn(t.headers["x-audio-duration-ms"]);if(i)return t.resume(),b(e,i.status,{error:i.error});let o=await Yn(t,T.bytes);if(!o)return b(e,413,{error:po()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(tt>=oo)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),l=n.host(),c=zn(a,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",g=c.length?"":" "+et(a,l);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${g}`,setup:!1})}if(!c.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:et(a,l),setup:!1});tt++;let u;try{let d=await eo(Jn(ro(),"agentx-phone-voice-"));try{u=await lo(d,`speech.${r}`,o,s,l,c,n)}finally{await to(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{tt--}b(e,u[0],u[1])}async function lo(t,e,n,s,r,i,o){let a=Jn(t,e);if(await no(a,n,{mode:384}),r.ffmpeg){let c=await(o.measure??Kn)(a,r.ffmpeg);if(c==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(c*1e3>T.ms+2e3)return[413,{error:Qe()}]}let l=[];for(let c of i)try{let u=await co(c,a,s,r,t,o);return o.log(`[voice] phone recording transcribed with ${c} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:c}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:c}]}catch(u){let d=String(u?.message??u).split(`
139
- `)[0].slice(0,200);l.push(`${c}: ${d}`),o.log(`[voice] phone transcription with ${c} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:l.join("; ")}]}function co(t,e,n,s,r,i){let o=i.engines?.[t];if(o)return o(e,n,s,r);if(t==="elevenlabs")return Gn(e,n,s.key);let a=t==="mlx-whisper"?s.mlx:s.whisper;return Xn(t,a,e,s.ffmpeg,r)}async function uo(t,e,n){let s=await Yn(t,io);if(!s)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(s.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let i=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!i)return b(e,400,{error:"agent is required"});let a=go(typeof r?.text=="string"?r.text:"");if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let l=n.voiceOf(i,o);if(!l)return b(e,404,{error:`Unknown agent: ${i}`});let c=(d,g=200)=>b(e,g,{fallback:"browser",reason:d,text:a});if(l.provider!=="elevenlabs")return c("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return c("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??fo)(u,l,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(`
140
- `)[0].slice(0,160)}`),c("ElevenLabs could not speak this answer.",502)}}function go(t){let e=Ln(dt(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return qn(e,so)}async function fo(t,e,n){let s=ge(e.rate),r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(e.elevenlabs)}?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n,model_id:"eleven_flash_v2_5",...s?{voice_settings:{speed:s}}:{}}),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 po=()=>`The recording is larger than ${T.bytes/1024/1024} MB, more than ${T.ms/6e4} minutes of speech.`;function rc(t,e,n,s){if(e)return s.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Me(Pe(t,r,n.voice)):null}function Yn(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,s)=>{let r=[],i=0;t.on("data",o=>{if(!(i>e)){if(i+=o.length,i>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{i<=e&&n(Buffer.concat(r))}),t.on("error",s)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as v,readFileSync as it,writeFileSync as ot,mkdirSync as fe,readdirSync as st,rmSync as mo,statSync as _}from"fs";import{resolve as Zn,relative as ho,dirname as at,join as L,extname as q,basename as lt}from"path";var S=200*1024,Qn=new Set([".md",".markdown",".txt"]),F=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),yo=6,bo=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function R(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Zn(t);if(v(n)||fe(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let s=Zn(n,e);if(ho(n,s).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return s}function er(t){let e=q(t).toLowerCase();if(!Qn.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function nt(t,e){let n=t.split(/\r?\n/).find(s=>s.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function ac(t){let e=R(t,"."),n=[],s=new Set,r=[];try{r=st(e)}catch{}for(let a of bo){let l=L(e,a);if(v(l)&&_(l).isFile()){let c=_(l).size,u=c>0&&c<S?rt(l):"";n.push({path:a,title:nt(u,a),size:c,exists:!0}),s.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),s.add(a)}for(let a of r){if(s.has(a))continue;let l=L(e,a);try{let c=_(l);if(!c.isFile()||!Qn.has(q(a).toLowerCase()))continue;let u=c.size>0&&c.size<S?rt(l):"";n.push({path:a,title:nt(u,a),size:c.size,exists:!0})}catch{}}let i=[],o=L(e,".claude","skills");if(v(o))try{for(let a of st(o)){let l=L(o,a),c;try{c=_(l)}catch{continue}if(!c.isDirectory())continue;let u=L(l,"SKILL.md");if(!v(u))continue;let d=_(u),g=d.size<S?rt(u):"";i.push({slug:a,title:nt(g,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return i.sort((a,l)=>a.slug.localeCompare(l.slug)),{identity:n,skills:i,workspace:e}}function rt(t){try{return it(t,"utf-8")}catch{return""}}function lc(t,e){let n=R(t,e);if(er(n),!v(n))return{path:e,content:""};if(_(n).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:it(n,"utf-8")}}function cc(t,e,n){let s=R(t,e);er(s);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return fe(at(s),{recursive:!0}),ot(s,r),{path:e,bytes:r.length}}function uc(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 s=`.claude/skills/${e}/SKILL.md`,r=R(t,s);if(v(r))throw new Error(`Skill "${e}" already exists.`);fe(at(r),{recursive:!0});let i=n.content?.trim()?n.content:wo(e,n.title);return ot(r,i),{slug:e,path:s}}function dc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);if(!_(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return mo(n,{recursive:!0,force:!0}),{slug:e}}function gc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=[];return r(n,"",0,s),s.sort((i,o)=>i.kind!==o.kind?i.kind==="dir"?-1:1:i.path.localeCompare(o.path)),s;function r(i,o,a,l){if(a>yo)return;let c=[];try{c=st(i)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=L(i,u),g=o?`${o}/${u}`:u,f;try{f=_(d)}catch{continue}if(f.isDirectory())l.push({path:`${g}/`,kind:"dir",size:0,editable:!1}),r(d,g,a+1,l);else if(f.isFile()){let p=q(u).toLowerCase(),h=F.has(p)||F.has(u.toLowerCase());l.push({path:g,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function fc(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 s=R(t,`.claude/skills/${e}/${n}`);if(!v(s)||!_(s).isFile())throw new Error(`File not found: ${n}`);let r=q(s).toLowerCase(),i=lt(s).toLowerCase();if(!F.has(r)&&!F.has(i))throw new Error(`File type not editable: ${n}`);if(_(s).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:it(s,"utf-8")}}function pc(t,e,n,s){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=R(t,`.claude/skills/${e}/${n}`),i=q(r).toLowerCase(),o=lt(r).toLowerCase();if(!F.has(i)&&!F.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(s,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return fe(at(r),{recursive:!0}),ot(r,a),{path:n,bytes:a.length}}function mc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=r=>v(L(n,r));return s("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:s("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:s("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:s("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:s("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function wo(t,e){return`# ${e?.trim()||t}
136
+ `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=D(e.to);if(n===D(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let s of this.subs)if(s.callId===e&&D(s.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(D(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let s=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>s)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,s+Ri),this.ringHandler)try{this.ringHandler(e)}catch(i){this.log(`ringHandler threw: ${i.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let s=this.pendingKey(e.callId,e.to),r=this.pending.get(s)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(s,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,s=D(e.to);for(let r of this.subs)r.callId===e.callId&&D(r.recipient)===s&&(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{closeSync as G,createReadStream as Ci,fstatSync as Di,openSync as Ti,realpathSync as jn}from"fs";import{isAbsolute as Ei,resolve as Vn,sep as Mn}from"path";var _l="/app-files",Li=/^[A-Za-z0-9_.:-]{1,64}$/;function Oi(t,e,n=process.cwd()){if(!e||e.length>Z.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 ${we}/ first`};if(!be(e))return{ok:!1,status:415,error:"this type of file is not served"};let s;try{s=jn(Vn(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=jn(Ei(e)?e:Vn(s,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(s+Mn))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${we}/ first`};let i=be(r);return i?{ok:!0,path:r,...i}:{ok:!1,status:415,error:"this type of file is not served"}}function Pi(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 ji(t,e,n){return{"Content-Type":t,"Content-Disposition":Pi(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 Vi(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let s,r;return n[1]?(s=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(s=Math.max(0,e-Number(n[2])),r=e-1),s>r||s>=e?"unsatisfiable":{start:s,end:r}}function Rl(t,e,n,s){let r=(C,O)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(O))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let i=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!Li.test(i))return r(400,{error:"bad agent id"});let a=s.workspaceOf(i);if(!a)return r(404,{error:`no agent "${i}" on this computer`});let l=Oi(a,o,s.cwd);if(!l.ok)return s.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${i}: ${l.error}`),r(l.status,{error:l.error});let c;try{c=Ti(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=Di(c);if(!C.isFile())return G(c),r(404,{error:"not a file"});u=C.size}catch{return G(c),r(404,{error:"file not found"})}if(u>Z.bytes)return G(c),r(413,{error:`the file is larger than ${Z.bytes/1024/1024} MB`});let d=l.path.split(Mn).pop()||"file",g=ji(l.mime,d,l.kind),f=Vi(t.headers.range,u);if(f==="unsatisfiable"){G(c),e.writeHead(416,{...g,"Content-Range":`bytes */${u}`}),e.end();return}let{start:p,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...g,"Content-Length":String(u?h-p+1:0),...f?{"Content-Range":`bytes ${p}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){G(c),e.end();return}let y=Ci("",{fd:c,start:p,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as X}from"child_process";import{readFileSync as Mi,writeFileSync as Ni}from"fs";import{tmpdir as Fi}from"os";import{join as Ui}from"path";var Nn=t=>t&&t!==1?Math.round(175*t):null,fe=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function Wi(){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=Mi(t,"utf8").trim();if(e)return e}catch{}return null}function Vl(t=Wi()){let e=0;return async(n,s)=>{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",...fe(n.voice.rate)?{voice_settings:{speed:fe(n.voice.rate)}}:{}}),signal:s});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let i=Ui(Fi(),`agentx-say-${process.pid}-${++e}.mp3`);return Ni(i,Buffer.from(await r.arrayBuffer())),i}catch(r){if(s.aborted||!n.voice.fallback)throw r;return E(`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 Fn(t,e){let n=t.languages&&le(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var Bi=(t,e="")=>{let n=Fn(t,e),s=Nn(t.rate);return[...n&&!an(n)?["-v",n]:[],...s?["-r",String(s)]:[]]};function Hi(t,e,n){if(!n)return["say",Bi(t,e)];let s=Fn(t,e);return["/bin/sh",[n,...s?[s]:[]]]}function Ml(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Nl(t=Je()){if(t)try{X("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Fl(t=Je()){if(t)try{X("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Je(t={},e){if(!Re(t))return null;try{return un(e)}catch(n){return E("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
137
+ `)[0]}); Siri voices will not switch`),null}}var Ul=(t,e)=>{if(!t){let[n,s]=Hi(e.voice,e.text,Je()),r=Nn(e.voice.rate),i=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=X(n,s,{stdio:["pipe","ignore","ignore"],env:i});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?X("afplay",[t],{stdio:"ignore"}):X("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Un}from"child_process";import{accessSync as zi,constants as Ki,readFileSync as Wn}from"fs";import{homedir as Gi}from"os";import{basename as F,delimiter as Bn,dirname as Xi,extname as qi,join as Ye}from"path";var T={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Hn(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)>T.ms+2e3?{status:413,error:Qe()}:null}var Qe=()=>`The recording is longer than ${T.ms/6e4} minutes.`,Ji={"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 zn(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return Ji[e]??null}function Kn(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 et(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 Ze(t,e,n=process.env.PATH??""){let s=Gi(),r=[Ye(s,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Bn).filter(Boolean)];for(let i of[e,...r.map(o=>Ye(o,t))])if(i)try{return zi(i,Ki.X_OK),i}catch{}return null}function Gl(t){return{key:t,mlx:Ze("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:Ze("whisper",process.env.AGENTX_WHISPER),ffmpeg:Yi()}}var Yi=()=>Ze("ffmpeg",process.env.AGENTX_FFMPEG);async function Gn(t,e){return e?Zi(t,e):null}async function Zi(t,e){let n=String(T.ms/1e3+5);try{let r=[...(await Qi(e,["-nostdin","-hide_banner","-t",n,"-i",t,"-f","null","-"],3e4)).matchAll(/time=(\d+):(\d+):(\d+(?:\.\d+)?)/g)],i=r[r.length-1];return i?Number(i[1])*3600+Number(i[2])*60+Number(i[3]):null}catch{return null}}async function Xn(t,e,n,s){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Wn(t)],{type:e}),F(t));let i=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:s??AbortSignal.timeout(6e4)});if(!i.ok)throw new Error(`ElevenLabs ${i.status}: ${(await i.text().catch(()=>"")).slice(0,160)}`);let o=await i.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function qn(t,e,n,s,r){let i=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:`${Xi(s)}${Bn}${process.env.PATH??""}`};await eo(e,i,12e4,o);try{return Wn(Ye(r,F(n,qi(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function Qi(t,e,n){return new Promise((s,r)=>{let i=Un(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{i.kill("SIGKILL"),r(new Error(`${F(t)} took too long`))},n);i.stderr.on("data",l=>{o=(o+l).slice(-8192)}),i.on("error",l=>{clearTimeout(a),r(l)}),i.on("exit",l=>{clearTimeout(a),l===0?s(o):r(new Error(`${F(t)} exited ${l}`))})})}function eo(t,e,n,s=process.env){return new Promise((r,i)=>{let o=Un(t,e,{stdio:["ignore","pipe","pipe"],env:s}),a="",l="",c=setTimeout(()=>{o.kill("SIGKILL"),i(new Error(`${F(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{l.length<4096&&(l+=u)}),o.on("error",u=>{clearTimeout(c),i(u)}),o.on("exit",u=>{clearTimeout(c),u===0?r(a):i(new Error(`${F(t)} exited ${u}: ${l.trim().split(`
138
+ `).pop()?.slice(0,160)??""}`))})})}function Jn(t,e=800){let n=t;return n=n.replace(/```[\s\S]*?```/g,". "),n=n.replace(/`[^`]*`/g,""),n=n.replace(/\*\*(.*?)\*\*/g,"$1"),n=n.replace(/__(.*?)__/g,"$1"),n=n.replace(/\*([^*]+)\*/g,"$1"),n=n.replace(/_([^_]+)_/g,"$1"),n=n.replace(/~~(.*?)~~/g,"$1"),n=n.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),n=n.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),n=n.replace(/^#{1,6}\s+/gm,""),n=n.replace(/^[\s]*[-*+]\s+/gm,". "),n=n.replace(/^[\s]*\d+\.\s+/gm,". "),n=n.replace(/^[-=_]{3,}$/gm,""),n=n.replace(/^>\s*/gm,""),n=n.replace(/https?:\/\/\S+/g,"link"),n=n.replace(/\/\w+(\/\w+)+/g,s=>s.split("/").filter(Boolean).join(" slash ")),n=n.replace(/&/g," and "),n=n.replace(/@/g," at "),n=n.replace(/=>/g," returns "),n=n.replace(/->/g," to "),n=n.replace(/\|/g," or "),n=n.replace(/\be\.g\./gi,"for example"),n=n.replace(/\bi\.e\./gi,"that is"),n=n.replace(/\betc\./gi,"etcetera"),n=n.replace(/\bvs\.?\b/gi,"versus"),n=n.replace(/\n{2,}/g,". "),n=n.replace(/\n/g," "),n=n.replace(/\s+/g," "),n=n.replace(/\.\s*\./g,"."),n=n.replace(/\s+([.,!?])/g,"$1"),n=n.trim().replace(/^[.,:;]+\s*/,""),n.length>e&&(n=n.slice(0,e).replace(/\s+\S*$/,"")+"..."),n}import{mkdtemp as to,rm as no,writeFile as ro}from"fs/promises";import{tmpdir as so}from"os";import{join as Yn}from"path";var io=1500,oo=64*1024,ao=2,tt=0;function ic(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function oc(t,e,n,s){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?lo(t,e,s):go(t,e,s)}async function lo(t,e,n){let s=String(t.headers["content-type"]||""),r=zn(s);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let i=Hn(t.headers["x-audio-duration-ms"]);if(i)return t.resume(),b(e,i.status,{error:i.error});let o=await Zn(t,T.bytes);if(!o)return b(e,413,{error:mo()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(tt>=ao)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),l=n.host(),c=Kn(a,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",g=c.length?"":" "+et(a,l);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${g}`,setup:!1})}if(!c.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:et(a,l),setup:!1});tt++;let u;try{let d=await to(Yn(so(),"agentx-phone-voice-"));try{u=await co(d,`speech.${r}`,o,s,l,c,n)}finally{await no(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{tt--}b(e,u[0],u[1])}async function co(t,e,n,s,r,i,o){let a=Yn(t,e);if(await ro(a,n,{mode:384}),r.ffmpeg){let c=await(o.measure??Gn)(a,r.ffmpeg);if(c==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(c*1e3>T.ms+2e3)return[413,{error:Qe()}]}let l=[];for(let c of i)try{let u=await uo(c,a,s,r,t,o);return o.log(`[voice] phone recording transcribed with ${c} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:c}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:c}]}catch(u){let d=String(u?.message??u).split(`
139
+ `)[0].slice(0,200);l.push(`${c}: ${d}`),o.log(`[voice] phone transcription with ${c} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:l.join("; ")}]}function uo(t,e,n,s,r,i){let o=i.engines?.[t];if(o)return o(e,n,s,r);if(t==="elevenlabs")return Xn(e,n,s.key);let a=t==="mlx-whisper"?s.mlx:s.whisper;return qn(t,a,e,s.ffmpeg,r)}async function go(t,e,n){let s=await Zn(t,oo);if(!s)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(s.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let i=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!i)return b(e,400,{error:"agent is required"});let a=fo(typeof r?.text=="string"?r.text:"");if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let l=n.voiceOf(i,o);if(!l)return b(e,404,{error:`Unknown agent: ${i}`});let c=(d,g=200)=>b(e,g,{fallback:"browser",reason:d,text:a});if(l.provider!=="elevenlabs")return c("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return c("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??po)(u,l,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(`
140
+ `)[0].slice(0,160)}`),c("ElevenLabs could not speak this answer.",502)}}function fo(t){let e=On(dt(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return Jn(e,io)}async function po(t,e,n){let s=fe(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",...s?{voice_settings:{speed:s}}:{}}),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 mo=()=>`The recording is larger than ${T.bytes/1024/1024} MB, more than ${T.ms/6e4} minutes of speech.`;function ac(t,e,n,s){if(e)return s.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Me(Pe(t,r,n.voice)):null}function Zn(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,s)=>{let r=[],i=0;t.on("data",o=>{if(!(i>e)){if(i+=o.length,i>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{i<=e&&n(Buffer.concat(r))}),t.on("error",s)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as v,readFileSync as it,writeFileSync as ot,mkdirSync as pe,readdirSync as st,rmSync as ho,statSync as A}from"fs";import{resolve as Qn,relative as yo,dirname as at,join as L,extname as q,basename as lt}from"path";var S=200*1024,er=new Set([".md",".markdown",".txt"]),U=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),bo=6,wo=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function R(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Qn(t);if(v(n)||pe(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let s=Qn(n,e);if(yo(n,s).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return s}function tr(t){let e=q(t).toLowerCase();if(!er.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function nt(t,e){let n=t.split(/\r?\n/).find(s=>s.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function dc(t){let e=R(t,"."),n=[],s=new Set,r=[];try{r=st(e)}catch{}for(let a of wo){let l=L(e,a);if(v(l)&&A(l).isFile()){let c=A(l).size,u=c>0&&c<S?rt(l):"";n.push({path:a,title:nt(u,a),size:c,exists:!0}),s.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),s.add(a)}for(let a of r){if(s.has(a))continue;let l=L(e,a);try{let c=A(l);if(!c.isFile()||!er.has(q(a).toLowerCase()))continue;let u=c.size>0&&c.size<S?rt(l):"";n.push({path:a,title:nt(u,a),size:c.size,exists:!0})}catch{}}let i=[],o=L(e,".claude","skills");if(v(o))try{for(let a of st(o)){let l=L(o,a),c;try{c=A(l)}catch{continue}if(!c.isDirectory())continue;let u=L(l,"SKILL.md");if(!v(u))continue;let d=A(u),g=d.size<S?rt(u):"";i.push({slug:a,title:nt(g,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return i.sort((a,l)=>a.slug.localeCompare(l.slug)),{identity:n,skills:i,workspace:e}}function rt(t){try{return it(t,"utf-8")}catch{return""}}function gc(t,e){let n=R(t,e);if(tr(n),!v(n))return{path:e,content:""};if(A(n).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:it(n,"utf-8")}}function fc(t,e,n){let s=R(t,e);tr(s);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return pe(at(s),{recursive:!0}),ot(s,r),{path:e,bytes:r.length}}function pc(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 s=`.claude/skills/${e}/SKILL.md`,r=R(t,s);if(v(r))throw new Error(`Skill "${e}" already exists.`);pe(at(r),{recursive:!0});let i=n.content?.trim()?n.content:ko(e,n.title);return ot(r,i),{slug:e,path:s}}function mc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);if(!A(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return ho(n,{recursive:!0,force:!0}),{slug:e}}function hc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=[];return r(n,"",0,s),s.sort((i,o)=>i.kind!==o.kind?i.kind==="dir"?-1:1:i.path.localeCompare(o.path)),s;function r(i,o,a,l){if(a>bo)return;let c=[];try{c=st(i)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=L(i,u),g=o?`${o}/${u}`:u,f;try{f=A(d)}catch{continue}if(f.isDirectory())l.push({path:`${g}/`,kind:"dir",size:0,editable:!1}),r(d,g,a+1,l);else if(f.isFile()){let p=q(u).toLowerCase(),h=U.has(p)||U.has(u.toLowerCase());l.push({path:g,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function yc(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 s=R(t,`.claude/skills/${e}/${n}`);if(!v(s)||!A(s).isFile())throw new Error(`File not found: ${n}`);let r=q(s).toLowerCase(),i=lt(s).toLowerCase();if(!U.has(r)&&!U.has(i))throw new Error(`File type not editable: ${n}`);if(A(s).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:it(s,"utf-8")}}function bc(t,e,n,s){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=R(t,`.claude/skills/${e}/${n}`),i=q(r).toLowerCase(),o=lt(r).toLowerCase();if(!U.has(i)&&!U.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(s,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return pe(at(r),{recursive:!0}),ot(r,a),{path:n,bytes:a.length}}function wc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=r=>v(L(n,r));return s("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:s("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:s("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:s("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:s("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function ko(t,e){return`# ${e?.trim()||t}
141
141
 
142
142
  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.
143
143
 
@@ -152,5 +152,5 @@ Document the arguments, commands, or files the skill expects. Example:
152
152
  # Example invocation
153
153
  claude-code ${lt(t)} --arg value
154
154
  \`\`\`
155
- `}ir();var tr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function nr(t){return{...tr,...t??{},regions:{...t?.regions??{}},buffer:{...tr.buffer,...t?.buffer??{}}}}function bc(t){try{return nr(ct(t).screen)}catch{return nr(void 0)}}var ko=/^[a-z][\w-]*$/,rr=["window","screen","menubar","notifications"];function J(t,e,n,s){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${s}`);return r}var pe=(t,e)=>J(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function sr(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 wc(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=pe(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=pe(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=pe(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=J(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=J(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[i,o]of Object.entries(e.regions)){if(!ko.test(i))throw new Error(`region name "${i}" must be lowercase letters, digits, - or _`);o===null?delete r[i]:r[i]=sr(o)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,i={...n.buffer??{}};"enabled"in r&&(i.enabled=!!r.enabled),"seconds"in r&&(i.seconds=J(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(i.fps=J(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(i.maxPixels=pe(r.maxPixels,"buffer.maxPixels")),"region"in r&&(i.region=String(r.region).trim()),n.buffer=i}let s=n.buffer?.region;if(s!==void 0&&!rr.includes(s)&&!n.regions?.[s])try{sr(s)}catch{throw new Error(`buffer.region "${s}" is not a region \u2014 use ${[...rr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{$t as a,vo as b,qe as c,wi as d,ki as e,dl as f,gl as g,fl as h,Ln as i,ml as j,yl as k,D as l,On as m,k as n,Ao as o,Et as p,Eo as q,Lt as r,Lo as s,Wt as t,Ht as u,U as v,W as w,Go as x,Xo as y,qo as z,Jo as A,Yo as B,jo as C,Vr as D,Wo as E,Ut as F,B as G,na as H,ra as I,pa as J,ma as K,vl as L,Pi as M,$l as N,ya as O,ba as P,wa as Q,ka as R,Sa as S,xa as T,$a as U,Ia as V,Oa as W,Te as X,Pa as Y,ja as Z,z as _,K as $,Ui as aa,Ll as ba,Ol as ca,Pl as da,jl as ea,Je as fa,Vl as ga,Oe as ha,Pe as ia,ce as ja,Ns as ka,Us as la,Wa as ma,Ve as na,Me as oa,Ws as pa,Bs as qa,wn as ra,vn as sa,Ba as ta,Ks as ua,Ha as va,ei as wa,ri as xa,Ne as ya,ii as za,$n as Aa,T as Ba,Bn as Ca,Hn as Da,zn as Ea,Bl as Fa,Ji as Ga,Gn as Ha,Xn as Ia,qn as Ja,tc as Ka,nc as La,po as Ma,rc as Na,Yn as Oa,ue as Pa,nl as Qa,Dn as Ra,Fe as Sa,Ge as Ta,cl as Ua,ac as Va,lc as Wa,cc as Xa,uc as Ya,dc as Za,gc as _a,fc as $a,pc as ab,mc as bb,tr as cb,nr as db,bc as eb,rr as fb,wc as gb};
156
- //# sourceMappingURL=chunk-7GC42WAK.js.map
155
+ `}or();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 rr(t){return{...nr,...t??{},regions:{...t?.regions??{}},buffer:{...nr.buffer,...t?.buffer??{}}}}function xc(t){try{return rr(ct(t).screen)}catch{return rr(void 0)}}var So=/^[a-z][\w-]*$/,sr=["window","screen","menubar","notifications"];function J(t,e,n,s){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${s}`);return r}var me=(t,e)=>J(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function ir(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 vc(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=me(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=me(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=me(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=J(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=J(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[i,o]of Object.entries(e.regions)){if(!So.test(i))throw new Error(`region name "${i}" must be lowercase letters, digits, - or _`);o===null?delete r[i]:r[i]=ir(o)}n.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,i={...n.buffer??{}};"enabled"in r&&(i.enabled=!!r.enabled),"seconds"in r&&(i.seconds=J(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(i.fps=J(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(i.maxPixels=me(r.maxPixels,"buffer.maxPixels")),"region"in r&&(i.region=String(r.region).trim()),n.buffer=i}let s=n.buffer?.region;if(s!==void 0&&!sr.includes(s)&&!n.regions?.[s])try{ir(s)}catch{throw new Error(`buffer.region "${s}" is not a region \u2014 use ${[...sr,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{$t as a,$o as b,qe as c,ki as d,Si as e,ml as f,hl as g,yl as h,On as i,wl as j,Sl as k,D as l,Pn as m,k as n,Ro as o,Et as p,Lo as q,Lt as r,Oo as s,Bt as t,P as u,zt as v,W as w,B as x,Jo as y,Yo as z,Zo as A,Qo as B,ea as C,Vo as D,Mr as E,Bo as F,Ut as G,j as H,ia as I,oa as J,aa as K,ba as L,wa as M,_l as N,ji as O,Rl as P,Sa as Q,xa as R,va as S,$a as T,Ia as U,Aa as V,Ra as W,Ca as X,Ma as Y,Te as Z,Na as _,Fa as $,z as aa,K as ba,Wi as ca,Vl as da,Ml as ea,Nl as fa,Fl as ga,Je as ha,Ul as ia,Oe as ja,Pe as ka,ue as la,Fs as ma,Ws as na,Ka as oa,Ve as pa,Me as qa,Bs as ra,Hs as sa,kn as ta,$n as ua,Ga as va,Gs as wa,Xa as xa,ti as ya,si as za,Ne as Aa,oi as Ba,In as Ca,T as Da,Hn as Ea,zn as Fa,Kn as Ga,Gl as Ha,Yi as Ia,Xn as Ja,qn as Ka,Jn as La,ic as Ma,oc as Na,mo as Oa,ac as Pa,Zn as Qa,de as Ra,ol as Sa,Tn as Ta,Fe as Ua,Ge as Va,fl as Wa,dc as Xa,gc as Ya,fc as Za,pc as _a,mc as $a,hc as ab,yc as bb,bc as cb,wc as db,nr as eb,rr as fb,xc as gb,sr as hb,vc as ib};
156
+ //# sourceMappingURL=chunk-2XICJMS6.js.map