agentix-cli 0.62.0 → 0.64.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.
- package/apps/mac-voice/Sources/AgentXVoice/SettingsWindow.swift +48 -26
- package/dist/{App-OWUIYVPJ.js → App-B6WGWI3A.js} +2 -2
- package/dist/{ChatApp-6HZRTQ3D.js → ChatApp-BHRANF7Z.js} +2 -2
- package/dist/{agent-NPPA34M3.js → agent-3M5EI4S6.js} +2 -2
- package/dist/{board-dashboard-27XK4IL5.js → board-dashboard-JBRO26JC.js} +604 -218
- package/dist/board-dashboard-JBRO26JC.js.map +1 -0
- package/dist/{chunk-6YERP2RV.js → chunk-2ZKDZ4FM.js} +2 -2
- package/dist/{chunk-5Z4QLJ6A.js → chunk-5QP56S4O.js} +2 -2
- package/dist/{chunk-UIWQKR7G.js → chunk-5WMHW4A6.js} +2 -2
- package/dist/{chunk-GUJB53QU.js → chunk-62EJKQFX.js} +2 -2
- package/dist/{chunk-UHO7YMOU.js → chunk-AZBOYKQA.js} +2 -2
- package/dist/{chunk-YZ3RTZ5G.js → chunk-BHE5TJSN.js} +2 -2
- package/dist/chunk-BYJ3A55Y.js +13 -0
- package/dist/chunk-BYJ3A55Y.js.map +1 -0
- package/dist/{chunk-KAFO5QZR.js → chunk-C4CDVE2E.js} +28 -28
- package/dist/chunk-C4CDVE2E.js.map +1 -0
- package/dist/{chunk-W7YVQGCO.js → chunk-EA7H3EUX.js} +2 -2
- package/dist/{chunk-JB46DY2K.js → chunk-HYKILAEJ.js} +217 -217
- package/dist/chunk-HYKILAEJ.js.map +1 -0
- package/dist/{chunk-NBFNAM5F.js → chunk-I2SD4XZ6.js} +2 -2
- package/dist/{chunk-RSPBTNCJ.js → chunk-KZDG26LI.js} +2 -2
- package/dist/{chunk-JZZLM6N6.js → chunk-LQ5J6COO.js} +2 -2
- package/dist/{chunk-V3LTLSCV.js → chunk-N42YWYIR.js} +7 -7
- package/dist/{chunk-V3LTLSCV.js.map → chunk-N42YWYIR.js.map} +1 -1
- package/dist/{chunk-CLJQLSSQ.js → chunk-NNXHRO7H.js} +8 -7
- package/dist/chunk-NNXHRO7H.js.map +1 -0
- package/dist/{chunk-HCFAFVUZ.js → chunk-OVF37EXJ.js} +9 -9
- package/dist/{chunk-HCFAFVUZ.js.map → chunk-OVF37EXJ.js.map} +1 -1
- package/dist/{chunk-GYUOAUYL.js → chunk-P4GOKVK2.js} +2 -2
- package/dist/{chunk-MTBQONW5.js → chunk-PTB2TPOC.js} +2 -2
- package/dist/chunk-S2VETB7B.js +131 -0
- package/dist/chunk-S2VETB7B.js.map +1 -0
- package/dist/{chunk-7ACTZO5L.js → chunk-VUB6XYWD.js} +54 -54
- package/dist/chunk-VUB6XYWD.js.map +1 -0
- package/dist/{chunk-H5VC7XG6.js → chunk-VVQDKHF5.js} +153 -152
- package/dist/chunk-VVQDKHF5.js.map +1 -0
- package/dist/{chunk-RHGUWBXI.js → chunk-WGWNVLVW.js} +2 -2
- package/dist/{chunk-XYXYVZM6.js → chunk-WMDDQVCI.js} +2 -2
- package/dist/{chunk-PFJZ6SQR.js → chunk-XT3E5MLX.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/client-YIBETZDJ.js +2 -0
- package/dist/{config-UGFFAXYA.js → config-EXNBBAZG.js} +2 -2
- package/dist/config-mutator-MFNZNWCZ.js +2 -0
- package/dist/doctor-IITNYJU5.js +2 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/dist/processes-TGFDGQYY.js +2 -0
- package/dist/program-FSRL275V.js +2 -0
- package/dist/{promote-NTEGYFVS.js → promote-KPEOVZ5V.js} +2 -2
- package/dist/query-WRWFAW5G.js +2 -0
- package/dist/{registry-N5TDGYMN.js → registry-T4R7LVFZ.js} +2 -2
- package/dist/{request-planner-GU77ZWEF.js → request-planner-PLBDCYKI.js} +2 -2
- package/dist/{review-candidates-7NZJEIQ7.js → review-candidates-LEO2N65G.js} +2 -2
- package/dist/{routing-TAUSISYI.js → routing-POORZC7A.js} +2 -2
- package/dist/schedule-tool-ZI4XBEN6.js +2 -0
- package/dist/scheduler-VPPKD4FY.js +2 -0
- package/dist/{seat-TEFB62NU.js → seat-PBFG5R7D.js} +2 -2
- package/dist/{select-GY4C2M53.js → select-WORPEXHN.js} +2 -2
- package/dist/{set-enabled-6KFM4ZL2.js → set-enabled-HGQWVDUD.js} +2 -2
- package/dist/{tool-FZXIYBKQ.js → tool-T2BIWDXP.js} +2 -2
- package/dist/wiki-KTDNYDOD.js +2 -0
- package/package.json +2 -1
- package/dist/board-dashboard-27XK4IL5.js.map +0 -1
- package/dist/chunk-7ACTZO5L.js.map +0 -1
- package/dist/chunk-CLJQLSSQ.js.map +0 -1
- package/dist/chunk-H5VC7XG6.js.map +0 -1
- package/dist/chunk-JB46DY2K.js.map +0 -1
- package/dist/chunk-JZLCBA26.js +0 -131
- package/dist/chunk-JZLCBA26.js.map +0 -1
- package/dist/chunk-KAFO5QZR.js.map +0 -1
- package/dist/chunk-S7CVSKOX.js +0 -13
- package/dist/chunk-S7CVSKOX.js.map +0 -1
- package/dist/client-JPOD4A4G.js +0 -2
- package/dist/config-mutator-BRSI7NZ2.js +0 -2
- package/dist/doctor-47ZKWQZT.js +0 -2
- package/dist/processes-NNXSRQSV.js +0 -2
- package/dist/program-EO2R3G65.js +0 -2
- package/dist/query-3WNSFLKI.js +0 -2
- package/dist/schedule-tool-Y26PGA26.js +0 -2
- package/dist/scheduler-UTKCOJ3M.js +0 -2
- package/dist/wiki-OFQC6OMS.js +0 -2
- /package/dist/{App-OWUIYVPJ.js.map → App-B6WGWI3A.js.map} +0 -0
- /package/dist/{ChatApp-6HZRTQ3D.js.map → ChatApp-BHRANF7Z.js.map} +0 -0
- /package/dist/{agent-NPPA34M3.js.map → agent-3M5EI4S6.js.map} +0 -0
- /package/dist/{chunk-6YERP2RV.js.map → chunk-2ZKDZ4FM.js.map} +0 -0
- /package/dist/{chunk-5Z4QLJ6A.js.map → chunk-5QP56S4O.js.map} +0 -0
- /package/dist/{chunk-UIWQKR7G.js.map → chunk-5WMHW4A6.js.map} +0 -0
- /package/dist/{chunk-GUJB53QU.js.map → chunk-62EJKQFX.js.map} +0 -0
- /package/dist/{chunk-UHO7YMOU.js.map → chunk-AZBOYKQA.js.map} +0 -0
- /package/dist/{chunk-YZ3RTZ5G.js.map → chunk-BHE5TJSN.js.map} +0 -0
- /package/dist/{chunk-W7YVQGCO.js.map → chunk-EA7H3EUX.js.map} +0 -0
- /package/dist/{chunk-NBFNAM5F.js.map → chunk-I2SD4XZ6.js.map} +0 -0
- /package/dist/{chunk-RSPBTNCJ.js.map → chunk-KZDG26LI.js.map} +0 -0
- /package/dist/{chunk-JZZLM6N6.js.map → chunk-LQ5J6COO.js.map} +0 -0
- /package/dist/{chunk-GYUOAUYL.js.map → chunk-P4GOKVK2.js.map} +0 -0
- /package/dist/{chunk-MTBQONW5.js.map → chunk-PTB2TPOC.js.map} +0 -0
- /package/dist/{chunk-RHGUWBXI.js.map → chunk-WGWNVLVW.js.map} +0 -0
- /package/dist/{chunk-XYXYVZM6.js.map → chunk-WMDDQVCI.js.map} +0 -0
- /package/dist/{chunk-PFJZ6SQR.js.map → chunk-XT3E5MLX.js.map} +0 -0
- /package/dist/{client-JPOD4A4G.js.map → client-YIBETZDJ.js.map} +0 -0
- /package/dist/{config-UGFFAXYA.js.map → config-EXNBBAZG.js.map} +0 -0
- /package/dist/{config-mutator-BRSI7NZ2.js.map → config-mutator-MFNZNWCZ.js.map} +0 -0
- /package/dist/{doctor-47ZKWQZT.js.map → doctor-IITNYJU5.js.map} +0 -0
- /package/dist/{processes-NNXSRQSV.js.map → processes-TGFDGQYY.js.map} +0 -0
- /package/dist/{program-EO2R3G65.js.map → program-FSRL275V.js.map} +0 -0
- /package/dist/{promote-NTEGYFVS.js.map → promote-KPEOVZ5V.js.map} +0 -0
- /package/dist/{query-3WNSFLKI.js.map → query-WRWFAW5G.js.map} +0 -0
- /package/dist/{registry-N5TDGYMN.js.map → registry-T4R7LVFZ.js.map} +0 -0
- /package/dist/{request-planner-GU77ZWEF.js.map → request-planner-PLBDCYKI.js.map} +0 -0
- /package/dist/{review-candidates-7NZJEIQ7.js.map → review-candidates-LEO2N65G.js.map} +0 -0
- /package/dist/{routing-TAUSISYI.js.map → routing-POORZC7A.js.map} +0 -0
- /package/dist/{schedule-tool-Y26PGA26.js.map → schedule-tool-ZI4XBEN6.js.map} +0 -0
- /package/dist/{scheduler-UTKCOJ3M.js.map → scheduler-VPPKD4FY.js.map} +0 -0
- /package/dist/{seat-TEFB62NU.js.map → seat-PBFG5R7D.js.map} +0 -0
- /package/dist/{select-GY4C2M53.js.map → select-WORPEXHN.js.map} +0 -0
- /package/dist/{set-enabled-6KFM4ZL2.js.map → set-enabled-HGQWVDUD.js.map} +0 -0
- /package/dist/{tool-FZXIYBKQ.js.map → tool-T2BIWDXP.js.map} +0 -0
- /package/dist/{wiki-OFQC6OMS.js.map → wiki-KTDNYDOD.js.map} +0 -0
package/dist/chunk-JZLCBA26.js
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import{g as We,h as ze,i as He,k as Ke,l as Ge}from"./chunk-NBFNAM5F.js";import{t as Je,u as Ye}from"./chunk-PFJZ6SQR.js";import{d as Xe,e as qe}from"./chunk-AQASR6KR.js";import{b as re}from"./chunk-CLJQLSSQ.js";import{q as Be}from"./chunk-YZ3RTZ5G.js";import{w as Fe,z as bn}from"./chunk-HCFAFVUZ.js";import{existsSync as wn,readdirSync as kn,readFileSync as Sn,statSync as xn}from"fs";import{resolve as $n}from"path";function Ze(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)??[],c=a.filter(m=>n-m.at<=r),l=a.filter(m=>n-m.at>r&&n-m.at<=r*2),u=c.filter(m=>m.status==="failed").length,d=a.filter(m=>m.status==="paused").length,g=a.length?Math.max(...a.map(m=>m.at)):null,f=a.length?l.length>0&&c.length===0?"dormant":c.length>0&&u*2>=c.length?"failing":c.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:g,recent:c.length,prior:l.length,failed:u,paused:d}}).sort((o,a)=>{let c={dormant:0,failing:1,active:2,quiet:3,never:4};return c[o.state]-c[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var B=new Map;function ni(t,e=1e3){if(!wn(t))return[];let n=kn(t).filter(i=>i.endsWith(".jsonl")).map(i=>{let o=$n(t,i);return{path:o,mtime:xn(o).mtimeMs}}).sort((i,o)=>o.mtime-i.mtime).slice(0,e),s=new Set(n.map(i=>i.path));for(let i of B.keys())s.has(i)||B.delete(i);let r=[];for(let{path:i,mtime:o}of n){let a=B.get(i);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let c=vn(i,o);B.set(i,{mtime:o,summary:c}),c&&r.push(c)}return r}function vn(t,e){try{let n=Sn(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]),c=a.status??a.run?.status;if(c){i=c;break}}return{workflowId:r,status:i,at:e}}catch{return null}}var In={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},_n=(t,e,n)=>{try{return Be(t,e,n)}catch{return null}},Qe=864e5;function oi(t){let e=t.now??Date.now(),n={...In,...t.thresholds},s=t.nextFire??_n,r=[];for(let a of t.crons){let c=t.cronRuns.get(a.id)??[],l=a.timezone||"UTC",u=c.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=c[0],g={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,k.text),trigger:{schedule:$(a.schedule,k.text),timezone:l},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),l)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:Dn(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:c.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:et(u),sampledRuns:c.length,flags:[],attention:null};g.flags=tt(g,u,a.schedule,l,null,e,n,s),r.push(nt(g))}let i=new Map(Ze(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let c=o.get(a.workflowId);c?c.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let c=a.nodes.find(_=>_.type.startsWith("trigger."));if(!c||c.type!=="trigger.cron"&&c.type!=="trigger.hook")continue;let l=c.config??{},u=a.state||"active",d=u==="active",g=(o.get(a.id)??[]).slice().sort((_,ne)=>ne.at-_.at),f=g.map(_=>({at:_.at,status:Cn(_.status)})),m=f[0],h=c.type==="trigger.cron",y=typeof l.spec=="string"?l.spec:"",te=typeof l.timezone=="string"?l.timezone:"UTC",U={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,k.text),trigger:h?{schedule:$(y,k.text),timezone:te}:{event:$(typeof l.event=="string"?l.event:"",k.text),filters:En(l.filter,a)},agent:Tn(a),enabled:d,state:u,nextRunAt:h&&d&&y?se(s(y,new Date(e),te)):null,lastRun:m?{at:new Date(m.at).toISOString(),status:m.status}:null,lastSuccessAt:(()=>{let _=f.find(ne=>ne.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:et(f),sampledRuns:g.length,flags:[],attention:null},F=Date.parse(a.updated||a.created||"");U.flags=h?tt(U,f,y,te,Number.isFinite(F)?F:null,e,n,s):An(U,i.get(a.id)?.state==="dormant",Number.isFinite(F)?F:null,e,n),r.push(nt(U))}return r.sort(Rn).slice(0,k.routines)}function et(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 tt(t,e,n,s,r,i,o,a){let c=[],l=e.length?e[0].at:null;if(!t.enabled){let g=st(l,r,i,o);return g&&c.push(g),c}if(t.consecutiveFailures>=o.failStreak&&c.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),l===null)return c.push({reason:"never-ran",detail:"No persisted attempt"}),c;let u=new Date(l),d=null;for(let g=0;g<o.missedFires&&(d=a(n,u,s),!!d);g++)u=d;return d&&i>d.getTime()+o.graceMs&&c.push({reason:"overdue",detail:`No attempt since ${new Date(l).toISOString()}; ${o.missedFires} scheduled fires missed`}),c}function An(t,e,n,s,r){let i=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=st(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 st(t,e,n,s){let r=Math.max(t??0,e??0);return r&&n-r<s.disabledDays*Qe?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/Qe)} days`:"Disabled and never ran"}}function nt(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 rt={critical:0,warning:1,info:2};function Rn(t,e){let n=t.attention?rt[t.attention]:3,s=e.attention?rt[e.attention]:3;return n-s||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function Cn(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 Tn(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 En(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 Dn(t,e){return t===void 0?void 0:$(t,e)}import{createHash as Ln,randomBytes as it}from"crypto";import{existsSync as Pn,mkdirSync as jn,readFileSync as On,writeFileSync as Mn}from"fs";import{resolve as Nn,dirname as Vn}from"path";var ie="agx_live_",Un=".agentx/tokens.json",ot=class{file;constructor(e=process.cwd(),n=Un){this.file=Nn(e,n)}load(){if(!Pn(this.file))return[];try{return JSON.parse(On(this.file,"utf-8"))}catch{return[]}}save(e){jn(Vn(this.file),{recursive:!0}),Mn(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(!Fn(o))throw new Error(`Invalid scope: ${o}`);let n=it(32).toString("hex"),s=ie+n,r={id:"tok_"+it(4).toString("hex"),name:e.name.trim(),prefix:ie+n.slice(0,4),hash:at(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(ie))return null;let n=at(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 di(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function Fn(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 at(t){return"sha256:"+Ln("sha256").update(t).digest("hex")}function gi(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 oe,readdirSync as sr,readFileSync as ir}from"fs";import{resolve as E}from"path";import{existsSync as Bn,mkdirSync as Wn,readdirSync as zn,readFileSync as Hn,renameSync as Kn,writeFileSync as Gn}from"fs";import{resolve as ct}from"path";var lt=["discard","keep","pause","approve"],v={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Xn={defaultExpiryDays:3,maxExpiryDays:30};function T(t){return ct(t,".agentx","approvals")}var qn=/^[a-z0-9][a-z0-9-]{0,80}$/;function ut(t){return qn.test(t)}function dt(t,e){if(!ut(e))throw new Error(`invalid card id: ${e}`);return ct(T(t),`${e}.json`)}function Jn(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 W(t,e){Wn(T(t),{recursive:!0});let n=dt(t,e.id),s=`${n}.${process.pid}.tmp`;Gn(s,JSON.stringify(e,null,2)+`
|
|
4
|
-
`),Kn(s,n)}function O(t,e){if(!ut(e))return null;try{return JSON.parse(Hn(dt(t,e),"utf-8"))}catch{return null}}function M(t,e){let n=T(t);if(!Bn(n))return[];let s=[];for(let r of zn(n).filter(i=>i.endsWith(".json")&&!i.startsWith("_")).sort()){let i=O(t,r.slice(0,-5));i&&(!e||i.status===e)&&s.push(i)}return s}function b(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function Yn(t,e,n){let s=e+n.maxExpiryDays*864e5,r,i=b(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 Zn(t,e={}){let n=e.now??Date.now(),s=e.settings??Xn,r=b(t.title),i=b(t.ask),o=b(t.recommend),a=b(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>v.title)return{ok:!1,error:`title is longer than ${v.title} characters`};if(i.length>v.ask)return{ok:!1,error:`ask is longer than ${v.ask} characters`};if(o.length>v.recommend)return{ok:!1,error:`recommend is longer than ${v.recommend} characters`};let c=b(t.if_silent).toLowerCase();if(!lt.includes(c))return{ok:!1,error:`if_silent must be one of ${lt.join(", ")}`};let l=Yn(t.expires,n,s);if(!l.ok)return l;let u=b(t.source);if(u.length>v.source)return{ok:!1,error:`source is longer than ${v.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,g=t.reply;return g&&typeof g=="object"&&b(g.channel)&&b(g.chatId)&&(d={channel:b(g.channel),chatId:b(g.chatId),...b(g.accountId)?{accountId:b(g.accountId)}:{}}),{ok:!0,card:{id:Jn(n,r),title:r,ask:i,recommend:o,if_silent:c,expires:l.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...d?{reply:d}:{},status:"pending"}}}function hi(t,e,n={}){let s=Zn(e,n);if(!s.ok)return s;let r=M(t,"pending").filter(i=>i.raised_by===s.card.raised_by).length;return r>=v.pendingPerAgent?{ok:!1,error:`${s.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(W(t,s.card),s)}function gt(t,e,n,s={}){let r=O(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=b(s.note).slice(0,v.note),o={...r,status:"decided",verdict:n,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString(),...i?{note:i}:{}};return W(t,o),{ok:!0,card:o}}function yi(t,e=Date.now()){let n=[];for(let s of M(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()};W(t,r),n.push(r)}return n}function bi(t){return M(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function wi(t,e,n=Date.now()){let s=O(t,e);!s||s.agent_notified_at||W(t,{...s,agent_notified_at:new Date(n).toISOString()})}function ki(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.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(`
|
|
5
|
-
`)}import{mkdirSync as Qn,readFileSync as er,renameSync as tr,writeFileSync as nr}from"fs";import{resolve as rr}from"path";function ft(t){return rr(T(t),"_state.json")}function z(t){try{let e=JSON.parse(er(ft(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{}}}catch{return{snoozed:{}}}}function mt(t,e){Qn(T(t),{recursive:!0});let n=ft(t),s=`${n}.${process.pid}.tmp`;nr(s,JSON.stringify(e,null,2)+`
|
|
6
|
-
`),tr(s,n)}function pt(t,e,n,s=Date.now()){let r=z(t),i={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>s&&(i[o]=a);i[e]=n.toISOString(),mt(t,{...r,snoozed:i})}function Ii(t,e){mt(t,{...z(t),lastDigest:e})}var ht=["card","schedule","memory","wiki"],or=280;function ae(t,e=or){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 E(t.configPath);let e=[E(t.root,"agentx.json"),E(t.root,".agentx","config.json")];return e.find(n=>oe(n))??e[0]}function le(t){return t.wikiDir?E(t.wikiDir):E(t.root,".agentx","wiki")}function ar(t){return M(t.root,"pending").map(lr)}function lr(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}}function cr(t){let e=yt(t);if(!oe(e))return[];let n;try{n=JSON.parse(ir(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 c=o.timezone||"UTC",l=o.schedule?We(o.schedule):"",u=o.schedule?`${l.charAt(0).toLowerCase()}${l.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:ae(`${d}${g&&o.schedule?` \xB7 first run ${He(ze(o.schedule,c,s),c)}`:""}`),more:"agentx schedule list"})}return r}function bt(t){let e=E(t,".agentx","memory");return oe(e)?sr(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function ur(t){let e=bt(t.root);if(e.length===0)return[];let n=new re(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:ae(i.content),more:`agentx memory facts held --agent ${r}`});return s}function dr(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 gr(t){return qe(le(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:ae(`${dr(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}var wt={card:ar,schedule:cr,memory:ur,wiki:gr};function fr(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 ji(t,e={}){let n=t.now??Date.now(),{snoozed:s}=z(t.root),r=[],i=[],o=0;for(let a of e.kinds??ht){let c;try{c=wt[a](t)}catch(l){i.push({kind:a,error:String(l?.message??l).slice(0,200)});continue}for(let l of c){let u=s[l.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}l.snoozed_until=u}r.push(l)}}return r.sort(fr),{items:r,snoozed:o,errors:i}}function mr(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),s=t.slice(e+1);return!ht.includes(n)||!s?null:{kind:n,ref:s}}function pr(t,e,n){switch(e){case"card":return O(t.root,n)?.status==="pending";case"wiki":return Xe(le(t),n)?.status==="pending";default:return wt[e](t).some(s=>s.key===`${e}:${n}`)}}async function Oi(t,e,n,s={}){let r=mr(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(),c=s.by??"operator";if(n==="later"){if(!pr(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 pt(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let l=n==="yes";switch(i){case"card":{let u=gt(t.root,o,l?"yes":"no",{by:c,note:s.note,now:a});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${l?"yes":"no"}`}:u}case"schedule":{let u=await(l?Ke:Ge)(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(!bt(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new re(t.root);return f.held(d).some(m=>m.id===g)?(f.review(d,g,l?"approved":"rejected",c),{ok:!0,message:`${e} ${l?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${g}" isn't waiting for review`}}case"wiki":{let u=le(t),d=l?Je(u,o,{by:c,force:s.force,now:a}):Ye(u,o,{by:c,reason:s.note,now:a});return d.ok?{ok:!0,message:l?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}}}var kt=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Ni(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"}function Vi(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 Ui(t){return kt.has(t)}function Fi(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(kt.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 Bi(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 Wi(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 H(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function hr(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function yr(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Hi(t,e=yr()){let n=H(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=hr(n),i=[H(t.host),H(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&i.includes(r)?"same-origin":"foreign"}let s=H(t["sec-fetch-site"]).toLowerCase();return s==="cross-site"||s==="same-site"?"foreign":"none"}function Ki(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{readFileSync as ue,writeFileSync as _t,existsSync as de,readdirSync as _r,statSync as Ar}from"fs";import{resolve as ge,join as Rr}from"path";import{existsSync as St,mkdirSync as br,readFileSync as wr,writeFileSync as xt}from"fs";import{dirname as kr,resolve as $t}from"path";import{z as p}from"zod";var Sr=p.object({type:p.enum(["gitlab","github"]),host:p.string().optional(),project:p.string(),iid:p.number().int().positive(),url:p.string()}),xr=p.object({id:p.string(),title:p.string(),description:p.string().optional(),assignee:p.string().optional(),labels:p.array(p.string()).default([]),milestone:p.string().optional(),status:p.enum(["todo","doing","blocked","done"]).default("todo"),priority:p.number().int().optional(),estimatedSeconds:p.number().int().optional(),source:Sr.optional(),importedAt:p.string().optional(),createdAt:p.string(),updatedAt:p.string(),blocker:p.string().optional(),doneNote:p.string().optional()}),$r=p.object({version:p.literal(1),items:p.array(xr).default([])}),K=class{constructor(e){this.path=e}jsonPath(){return $t(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return $t(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return St(this.jsonPath())}load(){let e=this.jsonPath();if(!St(e))return{version:1,items:[]};let n=wr(e,"utf-8");try{return $r.parse(JSON.parse(n))}catch(s){throw new Error(`Backlog file invalid (${e}): ${s.message}`)}}save(e){let n=this.jsonPath();br(kr(n),{recursive:!0}),xt(n,JSON.stringify(e,null,2)+`
|
|
7
|
-
`),xt(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 c=i==="done"?"x":" ",l=a.assignee?`@${a.assignee} `:"",u=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",d=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${c}] ${l}${a.title}${u}${d}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
|
|
8
|
-
`)}};function Yi(t){return`${t.type}:${t.project}:${t.iid}`}function vt(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 ce(t,e,n,s=()=>{}){return t.source?t.source.type==="gitlab"?vr(t.source,e,n,s):t.source.type==="github"?Ir(t.source,e,n,s):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function vr(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=[],c=async(f,m={})=>fetch(`${o}/api/v4${f}`,{...m,headers:{"PRIVATE-TOKEN":i,"Content-Type":"application/json",...m.headers||{}}}),l=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async m=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(m)}`,{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(m=>typeof m=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await c(`/projects/${l}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let m=await f.json();Array.isArray(m)&&m[0]?.id&&(d=m[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 c(`/projects/${l}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(g)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let m=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${m.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await c(`/projects/${l}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function Ir(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||{}}}),c=t.project,l;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")l=null;else try{let g=await a(`/repos/${c}/milestones?state=all&per_page=100`);if(g.ok){let f=await g.json(),m=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;m?.number&&(l=m.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/${c}/issues/${t.iid}`);if(g.ok){let f=await g.json(),m=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...m,...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),l!==void 0&&(d.milestone=l),e.state&&(d.state=e.state),Object.keys(d).length)try{let g=await a(`/repos/${c}/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/${c}/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 fe=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,G=/@([a-z0-9_-]+)/i,It=/\[time:\s*([0-9hm\s]+)\]/i;function Cr(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 me=class{constructor(e,n,s=()=>{}){this.path=e;this.daemon=n;this.log=s;this.store=new K(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=ge(process.cwd(),this.path);return de(e)?ue(e,"utf-8").split(`
|
|
9
|
-
`):[]}writeMd(e){let n=ge(process.cwd(),this.path);_t(n,e.join(`
|
|
10
|
-
`))}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(fe);if(!i||i[2].toLowerCase()==="x")continue;let a=i[3],c=a.match(G);if(c&&c[1].toLowerCase()!==e.toLowerCase())continue;let l=a.match(It),u=a.replace(G,"").replace(It,"").trim();s.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:c?c[1]:void 0,estimatedSeconds:l?Cr(l[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=vt([r.assignee||e],r.source,this.daemon);ce(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 c=this.store.update(e,a);if(c.source&&this.daemon){let l={};n.status==="done"?(l.addLabels=["Done"],l.removeLabels=["Doing"]):n.status==="blocked"&&(l.addLabels=["Blocked"]),n.note&&(l.note=n.note),Object.keys(l).length&&ce(c,l,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let s=parseInt(e.slice(8),10),r=this.readMd(),i=r[s];if(!i)throw new Error(`backlog line ${s} missing`);if(!i.match(fe))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"}}},pe=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(de(e))for(let s of _r(e)){let r=Rr(e,s);Ar(r).isDirectory()?this.walk(r,n):s.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(ge(process.cwd(),this.root),n);let s=[];for(let r of n){let i=ue(r,"utf-8").split(`
|
|
11
|
-
`);for(let o=0;o<i.length;o++){let a=i[o].match(fe);if(!a||a[2].toLowerCase()==="x")continue;let c=a[3].match(G);!c||c[1].toLowerCase()!==e.toLowerCase()||s.push({id:`wiki:${r}:${o}`,title:a[3].replace(G,"").trim(),assignee:c[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(!de(i))return;let o=ue(i,"utf-8").split(`
|
|
12
|
-
`);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),_t(i,o.join(`
|
|
13
|
-
`)))}},he=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(l=>({name:l.name,color:l.color,text_color:l.text_color})),r=i.map(l=>l.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(l=>({username:l.username,name:l.name,avatarUrl:l.avatar_url})),c=a[0]?.username;return{id:`gitlab:${s}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:c?this.usernameToAgent(c)||c:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails: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`,c=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,l=await this.api(c);for(let u of l){let d=this.mapIssue(u,o);d.assignee=e,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)),c=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(c)}`,{method:"POST"})}catch(l){this.log(`[business] add_spent_time failed: ${l.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 l of o)try{let u=l==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(l)}/issues?${r.toString()}`,d=await this.api(u);for(let g of d)a.push(this.mapIssue(g,l))}catch(u){this.log(`[business] GitLab listAll failed on ${l}: ${u.message}`)}let c=a;if(e.notLabels?.length){let l=new Set(e.notLabels);c=c.filter(u=>!(u.labels||[]).some(d=>l.has(d)))}if(e.withoutScopedPrefix){let l=e.withoutScopedPrefix+"::";c=c.filter(u=>!(u.labels||[]).some(d=>d.startsWith(l)))}return c}async setState(e,n){let{project: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 l=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(o=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${l.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),i!==void 0&&(a.assignee_ids=i),o!==void 0&&(a.milestone_id=o);let c=await this.api(`/projects/${encodeURIComponent(s)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(c,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 l=>{try{let u=await this.api(`/users?username=${encodeURIComponent(l)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${l}: ${u.message}`),null}}))).filter(l=>typeof l=="number"));let i;if(e.milestoneTitle)try{let c=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(i=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${c.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};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",c=new URLSearchParams;n.length&&c.set("add_labels",n.join(",")),s.length&&c.set("remove_labels",s.join(",")),c.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${i}?${c.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 so(t,e,n){let s=t.workSource;switch(s.type){case"backlog":return new me(s.path,e,n);case"wiki":return new pe(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 he(r.host,r.token,o,i,n)}}}var ye="unmapped";function be(t,e=[]){if(!t)return ye;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 Tr(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,be(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 c=r(a,o);return c&&e.set(i,c),c};for(let i of Object.keys(s))r(i);return e}function Er(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 oo(t,e){let n=Er(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return be(t.project,e.projects);if(t.agentId){let s=Tr(e).get(t.agentId);if(s)return s}return ye}function ao(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 Dr=t=>t===ye?"internal":"client";function Lr(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??Dr(t),respondWithinMinutes:Pr(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function lo(t){let e=new Set;for(let n of t.projects??[])e.add(be(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=>Lr(n,t))}function Pr(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 jr=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Or=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function At(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(Or)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],s=n[2],r=Mr(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 uo(t){if(!t||!t.includes("agentx:ui"))return t;let e=jr.exec(t);return e?t.slice(0,e.index).trimEnd():t}function Mr(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=[];for(let i of e.buttons)!i||typeof i.label!="string"||(typeof i.url=="string"&&/^https?:\/\//i.test(i.url)?s.push({label:i.label,url:i.url}):i.action!=null&&r.push(i.label));s.length&&(n.buttons=s),r.length&&(n.skippedActions=r)}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}:{}})}return!n.buttons&&!n.poll&&!n.media&&!n.skippedActions?null:n}import{execFile as Jr,execFileSync as Yr}from"child_process";import{execFileSync as Nr}from"child_process";import{existsSync as Ct,mkdirSync as Vr,readdirSync as Ur,readFileSync as Tt,renameSync as Fr,writeFileSync as Br}from"fs";import{homedir as Et}from"os";import{join as ke}from"path";var Se="siri:",Dt="com.apple.ttsbundle.gryphon-neural_",Lt=t=>!!t&&t.startsWith(Dt),Wr=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],zr=()=>{try{return Nr("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},we;function xe(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&we!==void 0)return we;let{platform:n=process.platform,exists:s=Ct,prefDomain:r=zr}=t,i=n==="darwin"&&Wr.every(o=>s(o))&&r();return e||(we=i),i}var Hr=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Kr={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"},Gr=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function Xr(t){let e=new Map;for(let n of t)for(let[,s,r,i]of n.matchAll(Gr)){let o=`${s}-${r}`,a=`${Dt}${i}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:i[0].toUpperCase()+i.slice(1),locale:o,quality:"premium",gender:Kr[i]??null,siri:!0})}return[...e.values()]}function X(t=Hr,e={}){if(!xe(e))return[];let n=[];for(let s of t){let r;try{r=Ur(s)}catch{continue}for(let i of r)try{n.push(Tt(ke(s,i,"Info.plist"),"latin1"))}catch{}}return Xr(n)}var Rt=`#!/bin/sh
|
|
14
|
-
# Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
|
|
15
|
-
# siri-say.sh [voice] < text speak one line. A Siri voice id switches
|
|
16
|
-
# the OS default for it; any other id is
|
|
17
|
-
# passed to say -v.
|
|
18
|
-
# siri-say.sh --stop silence the line speaking, drop the queue.
|
|
19
|
-
# AGENTX_SAY_RATE=<words a minute> sets the speed; unset, say's own.
|
|
20
|
-
D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
|
|
21
|
-
dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
|
|
22
|
-
stops="$dir/stop"
|
|
23
|
-
read_s=\${AGENTX_SAY_READ_S:-5} stale_s=\${AGENTX_SAY_STALE_S:-30} max_s=\${AGENTX_SAY_MAX_S:-300}
|
|
24
|
-
if [ "$1" = --stop ]; then
|
|
25
|
-
mkdir -p "$dir" || exit 1
|
|
26
|
-
# Queued lines see this change and drop. The owner's trap stops say,
|
|
27
|
-
# restores the voice, and frees the lock.
|
|
28
|
-
echo "$$ $(date +%s)" > "$stops"
|
|
29
|
-
owner=$(cat "$lock/pid" 2>/dev/null)
|
|
30
|
-
[ -n "$owner" ] && kill "$owner" 2>/dev/null
|
|
31
|
-
exit 0
|
|
32
|
-
fi
|
|
33
|
-
case "$1" in com.apple.ttsbundle.gryphon-neural_*) siri=$1 voice= ;; *) siri= voice=$1 ;; esac
|
|
34
|
-
rate=\${AGENTX_SAY_RATE:-}
|
|
35
|
-
case "$rate" in *[!0-9]*) rate= ;; esac
|
|
36
|
-
case "$siri" in *[!A-Za-z0-9._-]*) echo "bad voice id" >&2; exit 2;; esac
|
|
37
|
-
# Not macOS, or no pref tools: speak as is and never touch a pref.
|
|
38
|
-
if [ "$(uname)" != Darwin ] || ! command -v defaults >/dev/null || ! command -v plutil >/dev/null; then
|
|
39
|
-
if [ -n "$voice" ]; then exec say \${rate:+-r "$rate"} -v "$voice"; else exec say \${rate:+-r "$rate"}; fi
|
|
40
|
-
fi
|
|
41
|
-
mkdir -p "$dir" || exit 1
|
|
42
|
-
mine=$(cat "$stops" 2>/dev/null)
|
|
43
|
-
stopped() { [ "$(cat "$stops" 2>/dev/null)" != "$mine" ]; }
|
|
44
|
-
txt=$(mktemp "\${TMPDIR:-/tmp}/agentx-say.XXXXXX") || exit 1
|
|
45
|
-
say_pid= dog=
|
|
46
|
-
restore() {
|
|
47
|
-
[ -f "$saved" ] || return 0
|
|
48
|
-
if [ -s "$saved" ]; then defaults write $D $K "$(cat "$saved")"; else defaults delete $D $K 2>/dev/null; fi
|
|
49
|
-
rm -f "$saved"
|
|
50
|
-
}
|
|
51
|
-
finish() {
|
|
52
|
-
[ -n "$say_pid" ] && kill "$say_pid" 2>/dev/null
|
|
53
|
-
[ -n "$dog" ] && { pkill -P "$dog" 2>/dev/null; kill "$dog" 2>/dev/null; }
|
|
54
|
-
restore; rm -rf "$lock"; rm -f "$txt"; exit "$1"
|
|
55
|
-
}
|
|
56
|
-
drop() { rm -f "$txt"; exit 75; }
|
|
57
|
-
# The whole text first, before the lock: a writer that never closes stdin
|
|
58
|
-
# must not hold up every other speaker.
|
|
59
|
-
exec 3<&0 0</dev/null
|
|
60
|
-
cat <&3 > "$txt" & cat_pid=$!
|
|
61
|
-
exec 3<&-
|
|
62
|
-
n=0
|
|
63
|
-
while kill -0 "$cat_pid" 2>/dev/null; do
|
|
64
|
-
if [ $n -ge $((read_s * 10)) ]; then
|
|
65
|
-
kill "$cat_pid" 2>/dev/null; echo "stdin never closed; nothing said" >&2; rm -f "$txt"; exit 3
|
|
66
|
-
fi
|
|
67
|
-
sleep 0.1; n=$((n + 1))
|
|
68
|
-
done
|
|
69
|
-
# One speaker at a time. A lock whose owner died is taken over. A line
|
|
70
|
-
# that waits past stale_s, or that a stop overtook, is dropped unsaid.
|
|
71
|
-
n=0
|
|
72
|
-
while ! mkdir "$lock" 2>/dev/null; do
|
|
73
|
-
stopped && drop
|
|
74
|
-
if [ $n -ge $((stale_s * 10)) ]; then echo "waited \${stale_s}s for the speaker; dropped" >&2; drop; fi
|
|
75
|
-
owner=$(cat "$lock/pid" 2>/dev/null)
|
|
76
|
-
if [ -n "$owner" ] && ! kill -0 "$owner" 2>/dev/null; then rm -rf "$lock"
|
|
77
|
-
elif [ -z "$owner" ] && [ -n "$(find "$lock" -maxdepth 0 -mmin +1 2>/dev/null)" ]; then rm -rf "$lock"
|
|
78
|
-
else sleep 0.1; n=$((n + 1)); fi
|
|
79
|
-
done
|
|
80
|
-
echo $$ > "$lock/pid"
|
|
81
|
-
trap 'finish 143' TERM INT HUP
|
|
82
|
-
stopped && finish 75
|
|
83
|
-
restore
|
|
84
|
-
if [ -n "$siri" ]; then
|
|
85
|
-
lang=$(defaults read -g AppleLanguages 2>/dev/null | sed -n '2s/^[^A-Za-z]*\\([A-Za-z]*\\).*/\\1/p')
|
|
86
|
-
defaults export $D - 2>/dev/null | plutil -extract $K xml1 -o "$saved.tmp" - 2>/dev/null || : > "$saved.tmp"
|
|
87
|
-
mv "$saved.tmp" "$saved"
|
|
88
|
-
defaults write $D $K -array "\${lang:-en}" "{ _type = \\"Speech.VoiceSelection\\"; _version = 0; voiceId = \\"$siri\\"; }"
|
|
89
|
-
fi
|
|
90
|
-
# A watchdog: no line runs past its length's worth of speech (a hung say
|
|
91
|
-
# held the lock for minutes), capped at max_s.
|
|
92
|
-
limit=$((5 + $(wc -w < "$txt") * 6 / 10))
|
|
93
|
-
[ $limit -gt $max_s ] && limit=$max_s
|
|
94
|
-
if [ -n "$voice" ]; then say \${rate:+-r "$rate"} -v "$voice" -f "$txt" & else say \${rate:+-r "$rate"} -f "$txt" & fi
|
|
95
|
-
say_pid=$!
|
|
96
|
-
( sleep "$limit"; echo "say ran past \${limit}s; stopped" >&2; kill "$say_pid" 2>/dev/null ) & dog=$!
|
|
97
|
-
wait "$say_pid"
|
|
98
|
-
status=$?
|
|
99
|
-
say_pid=
|
|
100
|
-
finish $status
|
|
101
|
-
`,qr=(t=Et())=>ke(t,".agentx","voice","siri-say.sh");function Pt(t=Et()){let e=qr(t);return Ct(e)&&Tt(e,"utf8")===Rt||(Vr(ke(t,".agentx","voice"),{recursive:!0}),Br(`${e}.tmp`,Rt,{mode:493}),Fr(`${e}.tmp`,e)),e}var jt=`ObjC.import("AVFoundation")
|
|
102
|
-
const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
|
|
103
|
-
for (let i = 0; i < vs.count; i++) {
|
|
104
|
-
const v = vs.objectAtIndex(i)
|
|
105
|
-
out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
|
|
106
|
-
}
|
|
107
|
-
out.join("\\n")`,Zr=new Set(["Fred","Kathy","Ralph","Junior"]),Qr={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 Ot(t){let e=[];for(let n of t.split(`
|
|
108
|
-
`)){let[s,r,i,o,a]=n.split(" ");!s||!r||!i||s.includes(".siri_")||s.startsWith("com.apple.speech.synthesis.voice.")&&!Zr.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":Qr[r]??null})}return e}var es=10*60*1e3,D=null,$e=!1;function ve(t=Date.now()){if(process.platform!=="darwin")return[];if(D)t-D.at>es&&!$e&&($e=!0,Jr("osascript",["-l","JavaScript","-e",jt],{timeout:1e4},(e,n)=>{$e=!1,e||(D={at:Date.now(),voices:[...Ot(String(n)),...X()]})}));else try{D={at:t,voices:[...Ot(Yr("osascript",["-l","JavaScript","-e",jt],{encoding:"utf8",timeout:1e4})),...X()]}}catch(e){Ie(`[voice] could not list system voices: ${String(e?.message??e).split(`
|
|
109
|
-
`)[0]}`),D={at:t,voices:X()}}return D.voices}var Ie=t=>process.stderr.write(t+`
|
|
110
|
-
`),Mt=new Set;function ko(t){Ie=t}function L(t,e){Mt.has(t)||(Mt.add(t),Ie(e))}var ts={premium:3,enhanced:2,standard:1},ns=new Set(["Grandma","Grandpa"]);function Nt(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!ns.has(t.name)?1:0;return ts[t.quality]*10+e}var Vt=t=>t.toLowerCase().split(/[-_]/)[0];function q(t,e="en"){let n=e.toLowerCase().replace("_","-"),s=Vt(e),r=t.filter(i=>Vt(i.locale)===s);return(r.length?r:t).slice().sort((i,o)=>Nt(o)-Nt(i)||+(o.locale.toLowerCase()===n)-+(i.locale.toLowerCase()===n)||i.name.localeCompare(o.name)||i.locale.localeCompare(o.locale))}function _e(t,e,n="en"){let s=t.trim();if(!s)return null;let r=e.find(l=>l.id===s);if(r)return r;if(s.toLowerCase().startsWith(Se)){let l=s.slice(Se.length).trim().toLowerCase(),u=q(e.filter(g=>g.siri&&g.name.toLowerCase()===l),n)[0];if(u||!l)return u??null;let d=_e(l,e,n);return d&&L(`siri:${l}`,`[voice] Siri voice "${l}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(l=>!l.siri);let i=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(s),o=(i?i[1]:s.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=q(e.filter(l=>l.name.toLowerCase()===o),n);return(i?a.find(l=>l.quality===i[2].toLowerCase()):void 0)??a[0]??null}function Ut(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",c=a?o.gender:i,l=e.filter(d=>!r.has(d.name.toLowerCase())),u=l.find(d=>d.gender===c)??(a?e.find(d=>d.gender===c):void 0)??l[0]??e[s.size%e.length];s.set(o.id,u),r.add(u.name.toLowerCase()),a||(i=i==="female"?"male":"female")}return s}import{spawn as Y}from"child_process";import{readFileSync as os,writeFileSync as as}from"fs";import{tmpdir as ls}from"os";import{join as cs}from"path";var rs=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(" ")),ss=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(" ")),is=/[éèêëàâçùûîïôœ]/;function J(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)??[])rs.has(i)&&s++,ss.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?r++:is.test(i)&&(r+=.5);return s===r?null:s>r?"en":"fr"}var Ft=t=>t&&t!==1?Math.round(175*t):null,Z=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function us(){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=os(t,"utf8").trim();if(e)return e}catch{}return null}function To(t=us()){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",...Z(n.voice.rate)?{voice_settings:{speed:Z(n.voice.rate)}}:{}}),signal:s});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let i=cs(ls(),`agentx-say-${process.pid}-${++e}.mp3`);return as(i,Buffer.from(await r.arrayBuffer())),i}catch(r){if(s.aborted||!n.voice.fallback)throw r;return L(`elevenlabs:${String(r?.message??r).slice(0,40)}`,`[voice] ElevenLabs failed (${String(r?.message??r).slice(0,160)}); speaking with the system voice`),null}}}function Bt(t,e){let n=t.languages&&J(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var ds=(t,e="")=>{let n=Bt(t,e),s=Ft(t.rate);return[...n&&!Lt(n)?["-v",n]:[],...s?["-r",String(s)]:[]]};function gs(t,e,n){if(!n)return["say",ds(t,e)];let s=Bt(t,e);return["/bin/sh",[n,...s?[s]:[]]]}function Eo(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Do(t=Wt()){if(t)try{Y("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Wt(t={},e){if(!xe(t))return null;try{return Pt(e)}catch(n){return L("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
|
|
111
|
-
`)[0]}); Siri voices will not switch`),null}}var Lo=(t,e)=>{if(!t){let[n,s]=gs(e.voice,e.text,Wt()),r=Ft(e.voice.rate),i=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=Y(n,s,{stdio:["pipe","ignore","ignore"],env:i});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?Y("afplay",[t],{stdio:"ignore"}):Y("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as zt}from"child_process";import{accessSync as fs,constants as ms,readFileSync as Ht}from"fs";import{homedir as ps}from"os";import{basename as P,delimiter as Kt,dirname as hs,extname as ys,join as Re}from"path";var R={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Gt(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)>R.ms+2e3?{status:413,error:Ce()}:null}var Ce=()=>`The recording is longer than ${R.ms/6e4} minutes.`,bs={"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 Xt(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return bs[e]??null}function qt(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 Jt(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 Ae(t,e,n=process.env.PATH??""){let s=ps(),r=[Re(s,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(Kt).filter(Boolean)];for(let i of[e,...r.map(o=>Re(o,t))])if(i)try{return fs(i,ms.X_OK),i}catch{}return null}function Vo(t){return{key:t,mlx:Ae("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:Ae("whisper",process.env.AGENTX_WHISPER),ffmpeg:Ae("ffmpeg",process.env.AGENTX_FFMPEG)}}async function Yt(t,e){return e?ws(t,e):null}async function ws(t,e){let n=String(R.ms/1e3+5);try{let r=[...(await ks(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 Zt(t,e,n,s){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Ht(t)],{type:e}),P(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 Qt(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:`${hs(s)}${Kt}${process.env.PATH??""}`};await Ss(e,i,12e4,o);try{return Ht(Re(r,P(n,ys(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function ks(t,e,n){return new Promise((s,r)=>{let i=zt(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{i.kill("SIGKILL"),r(new Error(`${P(t)} took too long`))},n);i.stderr.on("data",c=>{o=(o+c).slice(-8192)}),i.on("error",c=>{clearTimeout(a),r(c)}),i.on("exit",c=>{clearTimeout(a),c===0?s(o):r(new Error(`${P(t)} exited ${c}`))})})}function Ss(t,e,n,s=process.env){return new Promise((r,i)=>{let o=zt(t,e,{stdio:["ignore","pipe","pipe"],env:s}),a="",c="",l=setTimeout(()=>{o.kill("SIGKILL"),i(new Error(`${P(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{c.length<4096&&(c+=u)}),o.on("error",u=>{clearTimeout(l),i(u)}),o.on("exit",u=>{clearTimeout(l),u===0?r(a):i(new Error(`${P(t)} exited ${u}: ${c.trim().split(`
|
|
112
|
-
`).pop()?.slice(0,160)??""}`))})})}function en(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}var xs="system",$s=t=>t.trim().toLowerCase()===xs,vs="21m00Tcm4TlvDq8ikWAM";function Ee(t,e,n={},s=ve()){let r=e[t],i=r?.name||t,o=r?.voice,a=Rs(e,n,s).get(t)??null,c=As(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?sn(a):null,systemByLanguage:c,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Ts(i,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var sn=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function Is(t,e,n,s){if(!e||!n.length)return null;let r=_e(e,n,s);return r||L(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),r}var on=t=>t.toLowerCase().split(/[-_]/)[0],tn=(t,e)=>typeof t=="string"?t:t?.[on(e)];function Te(t,e,n,s){if(e!==void 0)return $s(e)?null:Is(t,e,n,s)??void 0}var an=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function _s(t,e,n,s=new Set){let r=e.locale??"en",i=new Map,o=[],a=Te("voice.system",tn(e.system,r),n,r);for(let l of t){let u=Te(l.id,tn(l.system,r),n,r),d=u!==void 0?u:a!==void 0&&an(a,l.gender)?a:void 0;d!==void 0?i.set(l.id,d):o.push({id:l.id,gender:l.gender??null})}let c=new Set([...s,...[...i.values()].flatMap(l=>l?[l.name]:[])]);for(let[l,u]of Ut(o,q(n.filter(d=>!d.siri),r),c))i.set(l,u);return i}function As(t,e,n,s,r){if(typeof e=="string")return{};let i={},o=(a,c,l)=>{if(!(!c||typeof c=="string"))for(let[u,d]of Object.entries(c)){let g=Te(`${a}.${u}`,d,r,u);g!==void 0&&l(g)&&(i[on(u)]=g)}};return o("voice.system",s.system,a=>an(a,n)),o(t,e,()=>!0),i}function zo(t,e){let n=e?J(e):null;if(!n||!(n in t.systemByLanguage))return t;let s=t.systemByLanguage[n];return{...t,systemVoice:s?.id??null,systemVoiceName:s?sn(s):null}}function Rs(t,e={},n=ve()){let s=Object.entries(t).map(([r,i])=>({id:r,system:i.voice?.system,gender:i.voice?.gender}));return _s(s,e,n)}function De(t,e){let n={provider:t.provider,elevenlabs:Cs(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 Cs(t,e){return t||e||process.env.AGENTX_VOICE_ID||vs}function Ts(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 Es=8*60*60*1e3,Ds=500,nn=class{constructor(e=Es){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,s=Date.now()){let r=this.lastSpoke.get(rn(e,n));return r===void 0||s-r>this.gapMs}spoke(e,n,s=Date.now()){let r=rn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,s),this.lastSpoke.size>Ds&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},rn=(t,e)=>`${t}\0${e}`;function ln(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 Ho(t,e,n,s={}){let r=e[t],i=Ee(t,e,s),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:i.name,voice:De(i),persona:o||`You are ${i.name}.`,introLine:ln(i,n)}}var Ls="[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 Ko(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`${Ls}
|
|
113
|
-
${ln(r,e.voice.introduce===!0&&!!s)}`}import{mkdtemp as Ps,rm as js,writeFile as Os}from"fs/promises";import{tmpdir as Ms}from"os";import{join as cn}from"path";var Ns=1500,Vs=64*1024,Us=2,Le=0;function na(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function ra(t,e,n,s){return t.method!=="POST"?w(e,405,{error:"POST"}):n==="/voice/transcribe"?Fs(t,e,s):zs(t,e,s)}async function Fs(t,e,n){let s=String(t.headers["content-type"]||""),r=Xt(s);if(!r)return w(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let i=Gt(t.headers["x-audio-duration-ms"]);if(i)return t.resume(),w(e,i.status,{error:i.error});let o=await un(t,R.bytes);if(!o)return w(e,413,{error:Gs()});if(!o.length)return w(e,400,{error:"The recording is empty."});if(Le>=Us)return w(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),c=n.host(),l=qt(a,c);if(!l.length)return w(e,503,{error:"Voice input isn't set up on this computer.",hint:Jt(a,c),setup:!1});Le++;let u;try{let d=await Ps(cn(Ms(),"agentx-phone-voice-"));try{u=await Bs(d,`speech.${r}`,o,s,c,l,n)}finally{await js(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{Le--}w(e,u[0],u[1])}async function Bs(t,e,n,s,r,i,o){let a=cn(t,e);if(await Os(a,n,{mode:384}),r.ffmpeg){let l=await(o.measure??Yt)(a,r.ffmpeg);if(l==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(l*1e3>R.ms+2e3)return[413,{error:Ce()}]}let c=[];for(let l of i)try{let u=await Ws(l,a,s,r,t,o);return o.log(`[voice] phone recording transcribed with ${l} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:l}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:l}]}catch(u){let d=String(u?.message??u).split(`
|
|
114
|
-
`)[0].slice(0,200);c.push(`${l}: ${d}`),o.log(`[voice] phone transcription with ${l} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:c.join("; ")}]}function Ws(t,e,n,s,r,i){let o=i.engines?.[t];if(o)return o(e,n,s,r);if(t==="elevenlabs")return Zt(e,n,s.key);let a=t==="mlx-whisper"?s.mlx:s.whisper;return Qt(t,a,e,s.ffmpeg,r)}async function zs(t,e,n){let s=await un(t,Vs);if(!s)return w(e,413,{error:"request too large"});let r;try{r=JSON.parse(s.toString("utf8")||"{}")}catch{return w(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 w(e,400,{error:"agent is required"});let a=Hs(typeof r?.text=="string"?r.text:"");if(!a)return w(e,422,{error:"Nothing in this answer can be said aloud."});let c=n.voiceOf(i,o);if(!c)return w(e,404,{error:`Unknown agent: ${i}`});let l=(d,g=200)=>w(e,g,{fallback:"browser",reason:d,text:a});if(c.provider!=="elevenlabs")return l("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return l("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??Ks)(u,c,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(d)}catch(d){return n.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
|
|
115
|
-
`)[0].slice(0,160)}`),l("ElevenLabs could not speak this answer.",502)}}function Hs(t){return en(At(t).cleanText,Ns)}async function Ks(t,e,n){let s=Z(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 Gs=()=>`The recording is larger than ${R.bytes/1024/1024} MB, more than ${R.ms/6e4} minutes of speech.`;function sa(t,e,n,s){if(e)return s.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?De(Ee(t,r,n.voice)):null}function un(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 w(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as x,readFileSync as Me,writeFileSync as Ne,mkdirSync as Q,readdirSync as Oe,rmSync as Xs,statSync as I}from"fs";import{resolve as dn,relative as qs,dirname as Ve,join as C,extname as N,basename as Ue}from"path";var S=200*1024,gn=new Set([".md",".markdown",".txt"]),j=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"]),Js=6,Ys=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function A(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=dn(t);if(x(n)||Q(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let s=dn(n,e);if(qs(n,s).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return s}function fn(t){let e=N(t).toLowerCase();if(!gn.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function Pe(t,e){let n=t.split(/\r?\n/).find(s=>s.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function la(t){let e=A(t,"."),n=[],s=new Set,r=[];try{r=Oe(e)}catch{}for(let a of Ys){let c=C(e,a);if(x(c)&&I(c).isFile()){let l=I(c).size,u=l>0&&l<S?je(c):"";n.push({path:a,title:Pe(u,a),size:l,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 c=C(e,a);try{let l=I(c);if(!l.isFile()||!gn.has(N(a).toLowerCase()))continue;let u=l.size>0&&l.size<S?je(c):"";n.push({path:a,title:Pe(u,a),size:l.size,exists:!0})}catch{}}let i=[],o=C(e,".claude","skills");if(x(o))try{for(let a of Oe(o)){let c=C(o,a),l;try{l=I(c)}catch{continue}if(!l.isDirectory())continue;let u=C(c,"SKILL.md");if(!x(u))continue;let d=I(u),g=d.size<S?je(u):"";i.push({slug:a,title:Pe(g,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return i.sort((a,c)=>a.slug.localeCompare(c.slug)),{identity:n,skills:i,workspace:e}}function je(t){try{return Me(t,"utf-8")}catch{return""}}function ca(t,e){let n=A(t,e);if(fn(n),!x(n))return{path:e,content:""};if(I(n).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:Me(n,"utf-8")}}function ua(t,e,n){let s=A(t,e);fn(s);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return Q(Ve(s),{recursive:!0}),Ne(s,r),{path:e,bytes:r.length}}function da(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=A(t,s);if(x(r))throw new Error(`Skill "${e}" already exists.`);Q(Ve(r),{recursive:!0});let i=n.content?.trim()?n.content:Zs(e,n.title);return Ne(r,i),{slug:e,path:s}}function ga(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=A(t,`.claude/skills/${e}`);if(!x(n))throw new Error(`Skill "${e}" not found.`);if(!I(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return Xs(n,{recursive:!0,force:!0}),{slug:e}}function fa(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=A(t,`.claude/skills/${e}`);if(!x(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,c){if(a>Js)return;let l=[];try{l=Oe(i)}catch{return}for(let u of l){if(u==="node_modules"||u===".git")continue;let d=C(i,u),g=o?`${o}/${u}`:u,f;try{f=I(d)}catch{continue}if(f.isDirectory())c.push({path:`${g}/`,kind:"dir",size:0,editable:!1}),r(d,g,a+1,c);else if(f.isFile()){let m=N(u).toLowerCase(),h=j.has(m)||j.has(u.toLowerCase());c.push({path:g,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function ma(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=A(t,`.claude/skills/${e}/${n}`);if(!x(s)||!I(s).isFile())throw new Error(`File not found: ${n}`);let r=N(s).toLowerCase(),i=Ue(s).toLowerCase();if(!j.has(r)&&!j.has(i))throw new Error(`File type not editable: ${n}`);if(I(s).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:Me(s,"utf-8")}}function pa(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=A(t,`.claude/skills/${e}/${n}`),i=N(r).toLowerCase(),o=Ue(r).toLowerCase();if(!j.has(i)&&!j.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 Q(Ve(r),{recursive:!0}),Ne(r,a),{path:n,bytes:a.length}}function ha(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=A(t,`.claude/skills/${e}`);if(!x(n))throw new Error(`Skill "${e}" not found.`);let s=r=>x(C(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 Zs(t,e){return`# ${e?.trim()||t}
|
|
116
|
-
|
|
117
|
-
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.
|
|
118
|
-
|
|
119
|
-
## When to use
|
|
120
|
-
- Trigger condition 1
|
|
121
|
-
- Trigger condition 2
|
|
122
|
-
|
|
123
|
-
## How to use
|
|
124
|
-
Document the arguments, commands, or files the skill expects. Example:
|
|
125
|
-
|
|
126
|
-
\`\`\`bash
|
|
127
|
-
# Example invocation
|
|
128
|
-
claude-code ${Ue(t)} --arg value
|
|
129
|
-
\`\`\`
|
|
130
|
-
`}bn();var mn={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function pn(t){return{...mn,...t??{},regions:{...t?.regions??{}},buffer:{...mn.buffer,...t?.buffer??{}}}}function wa(t){try{return pn(Fe(t).screen)}catch{return pn(void 0)}}var Qs=/^[a-z][\w-]*$/,hn=["window","screen","menubar","notifications"];function V(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 ee=(t,e)=>V(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function yn(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 ka(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=ee(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=ee(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=ee(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=V(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=V(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(!Qs.test(i))throw new Error(`region name "${i}" must be lowercase letters, digits, - or _`);o===null?delete r[i]:r[i]=yn(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=V(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(i.fps=V(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(i.maxPixels=ee(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&&!hn.includes(s)&&!n.regions?.[s])try{yn(s)}catch{throw new Error(`buffer.region "${s}" is not a region \u2014 use ${[...hn,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{Ze as a,ni as b,be as c,Tr as d,Er as e,oo as f,ao as g,lo as h,At as i,uo as j,k,oi as l,ot as m,di as n,gi as o,lt as p,ut as q,O as r,hi as s,yi as t,bi as u,wi as v,ki as w,z as x,Ii as y,ji as z,Oi as A,Ni as B,Vi as C,Ui as D,Fi as E,Bi as F,Wi as G,Hi as H,Ki as I,ve as J,ko as K,q as L,_e as M,us as N,To as O,Eo as P,Do as Q,Wt as R,Lo as S,R as T,Gt as U,Xt as V,Vo as W,en as X,xs as Y,Ee as Z,sn as _,_s as $,As as aa,zo as ba,Rs as ca,De as da,Cs as ea,Ts as fa,nn as ga,ln as ha,Ho as ia,Ls as ja,Ko as ka,na as la,ra as ma,Gs as na,sa as oa,un as pa,K as qa,Yi as ra,vt as sa,ce as ta,he as ua,so as va,la as wa,ca as xa,ua as ya,da as za,ga as Aa,fa as Ba,ma as Ca,pa as Da,ha as Ea,mn as Fa,pn as Ga,wa as Ha,hn as Ia,ka as Ja};
|
|
131
|
-
//# sourceMappingURL=chunk-JZLCBA26.js.map
|