agentix-cli 0.61.0 → 0.63.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-LQXWKBVY.js → App-B6WGWI3A.js} +2 -2
- package/dist/{ChatApp-75TL4LKW.js → ChatApp-BHRANF7Z.js} +2 -2
- package/dist/{agent-DH4FMMMY.js → agent-D2BHFDUA.js} +2 -2
- package/dist/{board-dashboard-C6AZHDHU.js → board-dashboard-SMCZBJKO.js} +489 -213
- package/dist/board-dashboard-SMCZBJKO.js.map +1 -0
- package/dist/{chunk-3XVTFNYM.js → chunk-2ZKDZ4FM.js} +2 -2
- package/dist/{chunk-WOPFHKBF.js → chunk-33YJIUYL.js} +2 -2
- package/dist/{chunk-E2PWCU2N.js → chunk-5QP56S4O.js} +2 -2
- package/dist/chunk-5UYXEO3I.js +131 -0
- package/dist/chunk-5UYXEO3I.js.map +1 -0
- package/dist/{chunk-DTEQNXK3.js → chunk-5WMHW4A6.js} +2 -2
- package/dist/{chunk-BCXKRD5L.js → chunk-7LETLAIH.js} +153 -152
- package/dist/chunk-7LETLAIH.js.map +1 -0
- package/dist/{chunk-2VQIPJH5.js → chunk-AZBOYKQA.js} +2 -2
- package/dist/{chunk-JORXRF4E.js → chunk-BHE5TJSN.js} +2 -2
- package/dist/chunk-BYJ3A55Y.js +13 -0
- package/dist/chunk-BYJ3A55Y.js.map +1 -0
- package/dist/{chunk-CRSXKQLZ.js → chunk-EA7H3EUX.js} +2 -2
- package/dist/{chunk-27P5NLTC.js → chunk-I2SD4XZ6.js} +2 -2
- package/dist/{chunk-JO3PSLWL.js → chunk-JZMKKDT3.js} +5 -5
- package/dist/{chunk-WBGC7MWX.js → chunk-LQ5J6COO.js} +2 -2
- package/dist/{chunk-N5KD3TVN.js → chunk-N42YWYIR.js} +7 -7
- package/dist/{chunk-N5KD3TVN.js.map → chunk-N42YWYIR.js.map} +1 -1
- package/dist/{chunk-S7TCVIET.js → chunk-OVF37EXJ.js} +9 -9
- package/dist/{chunk-S7TCVIET.js.map → chunk-OVF37EXJ.js.map} +1 -1
- package/dist/{chunk-YQCOX4R3.js → chunk-P4GOKVK2.js} +2 -2
- package/dist/{chunk-WIBMNQKJ.js → chunk-PMGPGMBZ.js} +2 -2
- package/dist/{chunk-NBGNPKAF.js → chunk-PTB2TPOC.js} +2 -2
- package/dist/{chunk-B3DCYBP4.js → chunk-TX3ZOO22.js} +2 -2
- package/dist/{chunk-E2BJVHBR.js → chunk-WGWNVLVW.js} +2 -2
- package/dist/{chunk-LXUG2X26.js → chunk-XT3E5MLX.js} +2 -2
- package/dist/{chunk-Y76THZUQ.js → chunk-ZGWW6FZF.js} +205 -206
- package/dist/chunk-ZGWW6FZF.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/client-YIBETZDJ.js +2 -0
- package/dist/{config-3XC7EYB7.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 +10 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/program-NPPLJAQ7.js +2 -0
- package/dist/{promote-UR2GSHKC.js → promote-KPEOVZ5V.js} +2 -2
- package/dist/query-WRWFAW5G.js +2 -0
- package/dist/{registry-PGALUW5L.js → registry-MRMQBYE4.js} +2 -2
- package/dist/{request-planner-NHE3IRJN.js → request-planner-PLBDCYKI.js} +2 -2
- package/dist/{review-candidates-6GKRSRBQ.js → review-candidates-LEO2N65G.js} +2 -2
- package/dist/{routing-AQKHAU3Z.js → routing-POORZC7A.js} +2 -2
- package/dist/schedule-tool-ZI4XBEN6.js +2 -0
- package/dist/scheduler-VPPKD4FY.js +2 -0
- package/dist/{seat-6FMW2QI4.js → seat-PBFG5R7D.js} +2 -2
- package/dist/{select-5VONJMLH.js → select-WORPEXHN.js} +2 -2
- package/dist/{set-enabled-YHD3IJJZ.js → set-enabled-HGQWVDUD.js} +2 -2
- package/dist/{tool-MXJGLJZ5.js → tool-T2BIWDXP.js} +2 -2
- package/dist/wiki-KTDNYDOD.js +2 -0
- package/package.json +2 -1
- package/dist/board-dashboard-C6AZHDHU.js.map +0 -1
- package/dist/chunk-BCXKRD5L.js.map +0 -1
- package/dist/chunk-RVEMQCWW.js +0 -130
- package/dist/chunk-RVEMQCWW.js.map +0 -1
- package/dist/chunk-S7CVSKOX.js +0 -13
- package/dist/chunk-S7CVSKOX.js.map +0 -1
- package/dist/chunk-Y76THZUQ.js.map +0 -1
- package/dist/client-QVZIZFV4.js +0 -2
- package/dist/config-mutator-HKU63FJM.js +0 -2
- package/dist/doctor-YFA4ZSRH.js +0 -2
- package/dist/program-L6VAFALE.js +0 -2
- package/dist/query-XUP3BMVS.js +0 -2
- package/dist/schedule-tool-6NMCLTIH.js +0 -2
- package/dist/scheduler-RAYGNDWT.js +0 -2
- package/dist/wiki-ZQLEYY24.js +0 -2
- /package/dist/{App-LQXWKBVY.js.map → App-B6WGWI3A.js.map} +0 -0
- /package/dist/{ChatApp-75TL4LKW.js.map → ChatApp-BHRANF7Z.js.map} +0 -0
- /package/dist/{agent-DH4FMMMY.js.map → agent-D2BHFDUA.js.map} +0 -0
- /package/dist/{chunk-3XVTFNYM.js.map → chunk-2ZKDZ4FM.js.map} +0 -0
- /package/dist/{chunk-WOPFHKBF.js.map → chunk-33YJIUYL.js.map} +0 -0
- /package/dist/{chunk-E2PWCU2N.js.map → chunk-5QP56S4O.js.map} +0 -0
- /package/dist/{chunk-DTEQNXK3.js.map → chunk-5WMHW4A6.js.map} +0 -0
- /package/dist/{chunk-2VQIPJH5.js.map → chunk-AZBOYKQA.js.map} +0 -0
- /package/dist/{chunk-JORXRF4E.js.map → chunk-BHE5TJSN.js.map} +0 -0
- /package/dist/{chunk-CRSXKQLZ.js.map → chunk-EA7H3EUX.js.map} +0 -0
- /package/dist/{chunk-27P5NLTC.js.map → chunk-I2SD4XZ6.js.map} +0 -0
- /package/dist/{chunk-JO3PSLWL.js.map → chunk-JZMKKDT3.js.map} +0 -0
- /package/dist/{chunk-WBGC7MWX.js.map → chunk-LQ5J6COO.js.map} +0 -0
- /package/dist/{chunk-YQCOX4R3.js.map → chunk-P4GOKVK2.js.map} +0 -0
- /package/dist/{chunk-WIBMNQKJ.js.map → chunk-PMGPGMBZ.js.map} +0 -0
- /package/dist/{chunk-NBGNPKAF.js.map → chunk-PTB2TPOC.js.map} +0 -0
- /package/dist/{chunk-B3DCYBP4.js.map → chunk-TX3ZOO22.js.map} +0 -0
- /package/dist/{chunk-E2BJVHBR.js.map → chunk-WGWNVLVW.js.map} +0 -0
- /package/dist/{chunk-LXUG2X26.js.map → chunk-XT3E5MLX.js.map} +0 -0
- /package/dist/{client-QVZIZFV4.js.map → client-YIBETZDJ.js.map} +0 -0
- /package/dist/{config-3XC7EYB7.js.map → config-EXNBBAZG.js.map} +0 -0
- /package/dist/{config-mutator-HKU63FJM.js.map → config-mutator-MFNZNWCZ.js.map} +0 -0
- /package/dist/{doctor-YFA4ZSRH.js.map → doctor-IITNYJU5.js.map} +0 -0
- /package/dist/{program-L6VAFALE.js.map → program-NPPLJAQ7.js.map} +0 -0
- /package/dist/{promote-UR2GSHKC.js.map → promote-KPEOVZ5V.js.map} +0 -0
- /package/dist/{query-XUP3BMVS.js.map → query-WRWFAW5G.js.map} +0 -0
- /package/dist/{registry-PGALUW5L.js.map → registry-MRMQBYE4.js.map} +0 -0
- /package/dist/{request-planner-NHE3IRJN.js.map → request-planner-PLBDCYKI.js.map} +0 -0
- /package/dist/{review-candidates-6GKRSRBQ.js.map → review-candidates-LEO2N65G.js.map} +0 -0
- /package/dist/{routing-AQKHAU3Z.js.map → routing-POORZC7A.js.map} +0 -0
- /package/dist/{schedule-tool-6NMCLTIH.js.map → schedule-tool-ZI4XBEN6.js.map} +0 -0
- /package/dist/{scheduler-RAYGNDWT.js.map → scheduler-VPPKD4FY.js.map} +0 -0
- /package/dist/{seat-6FMW2QI4.js.map → seat-PBFG5R7D.js.map} +0 -0
- /package/dist/{select-5VONJMLH.js.map → select-WORPEXHN.js.map} +0 -0
- /package/dist/{set-enabled-YHD3IJJZ.js.map → set-enabled-HGQWVDUD.js.map} +0 -0
- /package/dist/{tool-MXJGLJZ5.js.map → tool-T2BIWDXP.js.map} +0 -0
- /package/dist/{wiki-ZQLEYY24.js.map → wiki-KTDNYDOD.js.map} +0 -0
package/dist/chunk-RVEMQCWW.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import{g as je,h as Pe,i as Oe,k as Ne,l as Fe}from"./chunk-27P5NLTC.js";import{t as Be,u as We}from"./chunk-LXUG2X26.js";import{d as Me,e as Ue}from"./chunk-AQASR6KR.js";import{b as re}from"./chunk-WIBMNQKJ.js";import{q as Le}from"./chunk-JORXRF4E.js";import{w as De,z as nn}from"./chunk-S7TCVIET.js";import{existsSync as rn,readdirSync as sn,readFileSync as on,statSync as an}from"fs";import{resolve as ln}from"path";function ze(n,e,t=Date.now(),s=7){let r=s*864e5,i=new Map;for(let a of e){let o=i.get(a.workflowId);o?o.push(a):i.set(a.workflowId,[a])}return n.map(a=>{let o=i.get(a.id)??[],l=o.filter(m=>t-m.at<=r),c=o.filter(m=>t-m.at>r&&t-m.at<=r*2),u=l.filter(m=>m.status==="failed").length,d=o.filter(m=>m.status==="paused").length,g=o.length?Math.max(...o.map(m=>m.at)):null,f=o.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:a.id,name:a.name||a.id,state:f,lastRunAt:g,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((a,o)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[a.state]-l[o.state]||(o.lastRunAt??0)-(a.lastRunAt??0)})}var U=new Map;function _s(n,e=1e3){if(!rn(n))return[];let t=sn(n).filter(i=>i.endsWith(".jsonl")).map(i=>{let a=ln(n,i);return{path:a,mtime:an(a).mtimeMs}}).sort((i,a)=>a.mtime-i.mtime).slice(0,e),s=new Set(t.map(i=>i.path));for(let i of U.keys())s.has(i)||U.delete(i);let r=[];for(let{path:i,mtime:a}of t){let o=U.get(i);if(o&&o.mtime===a){o.summary&&r.push(o.summary);continue}let l=cn(i,a);U.set(i,{mtime:a,summary:l}),l&&r.push(l)}return r}function cn(n,e){try{let t=on(n,"utf-8").split(`
|
|
2
|
-
`).filter(Boolean);if(!t.length)return null;let s=JSON.parse(t[0]),r=s.run?.workflowId;if(!r)return null;let i=s.run?.status??"unknown";for(let a=t.length-1;a>=0;a--){let o=JSON.parse(t[a]),l=o.status??o.run?.status;if(l){i=l;break}}return{workflowId:r,status:i,at:e}}catch{return null}}var un={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},k={routines:200,summary:160,filters:6,filterValue:60,text:120},dn=(n,e,t)=>{try{return Le(n,e,t)}catch{return null}},He=864e5;function Cs(n){let e=n.now??Date.now(),t={...un,...n.thresholds},s=n.nextFire??dn,r=[];for(let o of n.crons){let l=n.cronRuns.get(o.id)??[],c=o.timezone||"UTC",u=l.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=l[0],g={id:`cron:${o.id}`,source:"cron",kind:"schedule",name:$(o.id,k.text),trigger:{schedule:$(o.schedule,k.text),timezone:c},agent:o.agent||null,enabled:o.enabled,state:o.enabled?"enabled":"disabled",nextRunAt:o.enabled?se(o.nextRun)??se(s(o.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:yn(d.status==="success"?void 0:d.errorSummary,k.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:Ve(u),sampledRuns:l.length,flags:[],attention:null};g.flags=Ke(g,u,o.schedule,c,null,e,t,s),r.push(Ge(g))}let i=new Map(ze(n.workflows.map(o=>({id:o.id,name:o.title})),n.workflowRuns,e).map(o=>[o.id,o])),a=new Map;for(let o of n.workflowRuns){let l=a.get(o.workflowId);l?l.push(o):a.set(o.workflowId,[o])}for(let o of n.workflows){let l=o.nodes.find(_=>_.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=o.state||"active",d=u==="active",g=(a.get(o.id)??[]).slice().sort((_,ne)=>ne.at-_.at),f=g.map(_=>({at:_.at,status:mn(_.status)})),m=f[0],h=l.type==="trigger.cron",y=typeof c.spec=="string"?c.spec:"",te=typeof c.timezone=="string"?c.timezone:"UTC",F={id:`workflow:${o.id}`,source:"workflow",kind:h?"schedule":"event",name:$(o.title||o.id,k.text),trigger:h?{schedule:$(y,k.text),timezone:te}:{event:$(typeof c.event=="string"?c.event:"",k.text),filters:hn(c.filter,o)},agent:pn(o),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:Ve(f),sampledRuns:g.length,flags:[],attention:null},M=Date.parse(o.updated||o.created||"");F.flags=h?Ke(F,f,y,te,Number.isFinite(M)?M:null,e,t,s):gn(F,i.get(o.id)?.state==="dormant",Number.isFinite(M)?M:null,e,t),r.push(Ge(F))}return r.sort(fn).slice(0,k.routines)}function Ve(n){let e=0;for(let t of n)if(!(t.status==="running"||t.status==="paused"||t.status==="unknown"))if(t.status==="failed"||t.status==="timeout")e++;else break;return e}function Ke(n,e,t,s,r,i,a,o){let l=[],c=e.length?e[0].at:null;if(!n.enabled){let g=qe(c,r,i,a);return g&&l.push(g),l}if(n.consecutiveFailures>=a.failStreak&&l.push({reason:"failing",detail:`${n.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<a.missedFires&&(d=o(t,u,s),!!d);g++)u=d;return d&&i>d.getTime()+a.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${a.missedFires} scheduled fires missed`}),l}function gn(n,e,t,s,r){let i=[],a=n.lastRun?Date.parse(n.lastRun.at):null;if(!n.enabled){let o=qe(a,t,s,r);return o&&i.push(o),i}return n.consecutiveFailures>=r.failStreak&&i.push({reason:"failing",detail:`${n.consecutiveFailures} failed runs in a row`}),a===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 qe(n,e,t,s){let r=Math.max(n??0,e??0);return r&&t-r<s.disabledDays*He?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((t-r)/He)} days`:"Disabled and never ran"}}function Ge(n){let e=new Set(n.flags.map(t=>t.reason));return n.attention=e.has("failing")?"critical":e.has("overdue")||e.has("dormant")||e.has("never-ran")?"warning":e.has("disabled-long")?"info":null,n}var Xe={critical:0,warning:1,info:2};function fn(n,e){let t=n.attention?Xe[n.attention]:3,s=e.attention?Xe[e.attention]:3;return t-s||Number(e.enabled)-Number(n.enabled)||n.name.localeCompare(e.name)}function mn(n){switch(n){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 pn(n){if(n.ownerAgent)return $(n.ownerAgent,k.text);let e=n.nodes.find(t=>t.type==="agent"&&typeof t.config?.agentId=="string"&&t.config.agentId);return e?$(String(e.config.agentId),k.text):null}function hn(n,e){let t=[],s=e?.project;if(s&&t.push($(`project=${s}`,k.filterValue)),n&&typeof n=="object"&&!Array.isArray(n))for(let[r,i]of Object.entries(n)){let a=Array.isArray(i)?i.map(String):i==null?[]:[String(i)];a.length&&t.push($(`${r}=${a.join(",")}`,k.filterValue))}return t.slice(0,k.filters)}function se(n){if(!n)return null;let e=n instanceof Date?n:new Date(n);return Number.isFinite(e.getTime())?e.toISOString():null}function $(n,e){return n.length<=e?n:n.slice(0,e-3)+"..."}function yn(n,e){return n===void 0?void 0:$(n,e)}import{createHash as bn,randomBytes as Je}from"crypto";import{existsSync as wn,mkdirSync as kn,readFileSync as Sn,writeFileSync as xn}from"fs";import{resolve as $n,dirname as vn}from"path";var ie="agx_live_",In=".agentx/tokens.json",Ye=class{file;constructor(e=process.cwd(),t=In){this.file=$n(e,t)}load(){if(!wn(this.file))return[];try{return JSON.parse(Sn(this.file,"utf-8"))}catch{return[]}}save(e){kn(vn(this.file),{recursive:!0}),xn(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 a of e.scopes)if(!_n(a))throw new Error(`Invalid scope: ${a}`);let t=Je(32).toString("hex"),s=ie+t,r={id:"tok_"+Je(4).toString("hex"),name:e.name.trim(),prefix:ie+t.slice(0,4),hash:Ze(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 t=this.load(),s=t.find(r=>r.id===e);return s?(s.revokedAt=new Date().toISOString(),this.save(t),s):null}isActive(e){let t=this.load().find(s=>s.id===e);return!!t&&!t.revokedAt&&!(t.expiresAt&&Date.parse(t.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(ie))return null;let t=Ze(e),s=this.load(),r=s.find(o=>o.hash===t);if(!r||r.revokedAt||r.expiresAt&&Date.parse(r.expiresAt)<Date.now())return null;let i=Date.now(),a=r.lastUsedAt?Date.parse(r.lastUsedAt):0;if(i-a>6e4){r.lastUsedAt=new Date(i).toISOString();try{this.save(s)}catch{}}return r}};function Ps(n,e){return!!(n.scopes.includes(e)||e.startsWith("agent:")&&n.scopes.includes("agent:*")||e==="dashboard:read"&&n.scopes.includes("dashboard:write"))}function _n(n){return n==="dashboard:read"||n==="dashboard:write"||n==="agent:*"||/^agent:[a-z0-9][a-z0-9_-]*$/.test(n)||n==="mesh:peer"||n==="app"}function Ze(n){return"sha256:"+bn("sha256").update(n).digest("hex")}function Os(n){let e=n.headers.authorization,t=Array.isArray(e)?e[0]:e;if(t&&t.toLowerCase().startsWith("bearer "))return t.slice(7).trim();if(n.url)try{let r=new URL(n.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}import{existsSync as oe,readdirSync as zn,readFileSync as Hn}from"fs";import{resolve as T}from"path";import{existsSync as An,mkdirSync as Rn,readdirSync as En,readFileSync as Cn,renameSync as Tn,writeFileSync as Dn}from"fs";import{resolve as et}from"path";var Qe=["discard","keep","pause","approve"],v={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Ln={defaultExpiryDays:3,maxExpiryDays:30};function C(n){return et(n,".agentx","approvals")}var jn=/^[a-z0-9][a-z0-9-]{0,80}$/;function tt(n){return jn.test(n)}function nt(n,e){if(!tt(e))throw new Error(`invalid card id: ${e}`);return et(C(n),`${e}.json`)}function Pn(n,e){let t=new Date(n).toISOString().slice(0,10),s=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${t}-${s||"card"}-${Math.random().toString(36).slice(2,6)}`}function B(n,e){Rn(C(n),{recursive:!0});let t=nt(n,e.id),s=`${t}.${process.pid}.tmp`;Dn(s,JSON.stringify(e,null,2)+`
|
|
4
|
-
`),Tn(s,t)}function j(n,e){if(!tt(e))return null;try{return JSON.parse(Cn(nt(n,e),"utf-8"))}catch{return null}}function P(n,e){let t=C(n);if(!An(t))return[];let s=[];for(let r of En(t).filter(i=>i.endsWith(".json")&&!i.startsWith("_")).sort()){let i=j(n,r.slice(0,-5));i&&(!e||i.status===e)&&s.push(i)}return s}function b(n){return typeof n=="string"?n.replace(/\s+/g," ").trim():""}function On(n,e,t){let s=e+t.maxExpiryDays*864e5,r,i=b(n);if(!i)r=e+t.defaultExpiryDays*864e5;else{let a=/^(\d+)\s*([hd])$/i.exec(i);if(a)r=e+Number(a[1])*(a[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 Nn(n,e={}){let t=e.now??Date.now(),s=e.settings??Ln,r=b(n.title),i=b(n.ask),a=b(n.recommend),o=b(n.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(!a)return{ok:!1,error:"recommend is required: your advice and why, in one line"};if(!o)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(a.length>v.recommend)return{ok:!1,error:`recommend is longer than ${v.recommend} characters`};let l=b(n.if_silent).toLowerCase();if(!Qe.includes(l))return{ok:!1,error:`if_silent must be one of ${Qe.join(", ")}`};let c=On(n.expires,t,s);if(!c.ok)return c;let u=b(n.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=n.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:Pn(t,r),title:r,ask:i,recommend:a,if_silent:l,expires:c.at,...u?{source:u}:{},raised_by:o,created_at:new Date(t).toISOString(),...d?{reply:d}:{},status:"pending"}}}function Us(n,e,t={}){let s=Nn(e,t);if(!s.ok)return s;let r=P(n,"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`}:(B(n,s.card),s)}function rt(n,e,t,s={}){let r=j(n,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),a={...r,status:"decided",verdict:t,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString(),...i?{note:i}:{}};return B(n,a),{ok:!0,card:a}}function Bs(n,e=Date.now()){let t=[];for(let s of P(n,"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()};B(n,r),t.push(r)}return t}function Ws(n){return P(n).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function zs(n,e,t=Date.now()){let s=j(n,e);!s||s.agent_notified_at||B(n,{...s,agent_notified_at:new Date(t).toISOString()})}function Hs(n){let e=n.status==="decided"?n.verdict==="yes"?"The operator said YES.":"The operator said NO.":`Nobody answered before it expired, so the default applied: ${n.outcome??n.if_silent}.`,t=[`[Approval result] Your decision card "${n.title}" (${n.id}) is closed.`,`Question: ${n.ask}`,e];return n.note&&t.push(`Operator note: ${n.note}`),n.source&&t.push(`Source: ${n.source}`),n.reply&&t.push(`You raised it from ${n.reply.channel} chat ${n.reply.chatId}; reply there if the requester should know.`),t.push("Act on this result now. Do not raise the same card again."),t.join(`
|
|
5
|
-
`)}import{mkdirSync as Fn,readFileSync as Mn,renameSync as Un,writeFileSync as Bn}from"fs";import{resolve as Wn}from"path";function st(n){return Wn(C(n),"_state.json")}function W(n){try{let e=JSON.parse(Mn(st(n),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{}}}catch{return{snoozed:{}}}}function it(n,e){Fn(C(n),{recursive:!0});let t=st(n),s=`${t}.${process.pid}.tmp`;Bn(s,JSON.stringify(e,null,2)+`
|
|
6
|
-
`),Un(s,t)}function ot(n,e,t,s=Date.now()){let r=W(n),i={};for(let[a,o]of Object.entries(r.snoozed))Date.parse(o)>s&&(i[a]=o);i[e]=t.toISOString(),it(n,{...r,snoozed:i})}function qs(n,e){it(n,{...W(n),lastDigest:e})}var at=["card","schedule","memory","wiki"],Vn=280;function ae(n,e=Vn){let t=n.replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e-1)}\u2026`:t}function lt(n){if(n.configPath)return T(n.configPath);let e=[T(n.root,"agentx.json"),T(n.root,".agentx","config.json")];return e.find(t=>oe(t))??e[0]}function le(n){return n.wikiDir?T(n.wikiDir):T(n.root,".agentx","wiki")}function Kn(n){return P(n.root,"pending").map(Gn)}function Gn(n){return{key:`card:${n.id}`,kind:"card",title:n.title,ask:n.ask,yes:`tell ${n.raised_by} yes`,no:`tell ${n.raised_by} no`,recommend:n.recommend,if_silent:n.if_silent,expires:n.expires,...n.source?{source:n.source}:{},raised_by:n.raised_by,created_at:n.created_at}}function Xn(n){let e=lt(n);if(!oe(e))return[];let t;try{t=JSON.parse(Hn(e,"utf-8"))}catch{return[]}let s=new Date(n.now??Date.now()),r=[];for(let[i,a]of Object.entries(t?.crons??{})){let o=a?.approval;if(!o||o.action!=="create"&&o.action!=="delete")continue;let l=a.timezone||"UTC",c=a.schedule?je(a.schedule):"",u=a.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${a.schedule})`:"no schedule",d=String(a.prompt??a.command??""),g=o.action==="create";r.push({key:`schedule:${i}`,kind:"schedule",title:g?`New schedule "${i}" for ${a.agent??"an agent"}`:`Delete schedule "${i}"`,ask:g?`Let ${a.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(o.requestedBy??"unknown"),created_at:String(o.requestedAt??""),detail:ae(`${d}${g&&a.schedule?` \xB7 first run ${Oe(Pe(a.schedule,l,s),l)}`:""}`),more:"agentx schedule list"})}return r}function ct(n){let e=T(n,".agentx","memory");return oe(e)?zn(e).filter(t=>t.endsWith(".jsonl")).map(t=>t.slice(0,-6)).sort():[]}function qn(n){let e=ct(n.root);if(e.length===0)return[];let t=new re(n.root),s=[];for(let r of e)for(let i of t.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 Jn(n){let e=n.sources.filter(t=>t.failure);return e.length?e.map(t=>`Recurring failure: ${t.agentId}'s ${t.failure.tool} fails with "${t.failure.errorClass}" in ${t.occurrences??1} sessions (${t.failure.runs} runs).`).join(" "):`${n.sources.length} source(s)${n.occurrences>1?`, seen in ${n.occurrences} sessions`:""}.`}function Yn(n){return Ue(le(n),"pending").map(e=>{let t=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:t.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:ae(`${Jn(t)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}var ut={card:Kn,schedule:Xn,memory:qn,wiki:Yn};function Zn(n,e){let t=n.expires?Date.parse(n.expires):1/0,s=e.expires?Date.parse(e.expires):1/0;return t!==s?t-s:(Date.parse(n.created_at)||0)-(Date.parse(e.created_at)||0)}function ii(n,e={}){let t=n.now??Date.now(),{snoozed:s}=W(n.root),r=[],i=[],a=0;for(let o of e.kinds??at){let l;try{l=ut[o](n)}catch(c){i.push({kind:o,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=s[c.key];if(u&&Date.parse(u)>t){if(!e.includeSnoozed){a++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(Zn),{items:r,snoozed:a,errors:i}}function Qn(n){let e=n.indexOf(":");if(e<=0)return null;let t=n.slice(0,e),s=n.slice(e+1);return!at.includes(t)||!s?null:{kind:t,ref:s}}function er(n,e,t){switch(e){case"card":return j(n.root,t)?.status==="pending";case"wiki":return Me(le(n),t)?.status==="pending";default:return ut[e](n).some(s=>s.key===`${e}:${t}`)}}async function oi(n,e,t,s={}){let r=Qn(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:i,ref:a}=r,o=n.now??Date.now(),l=s.by??"operator";if(t==="later"){if(!er(n,i,a))return{ok:!1,error:`nothing waiting for "${e}"`};let u=s.laterHours&&s.laterHours>0?s.laterHours:24,d=new Date(o+u*36e5);return ot(n.root,e,d,o),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=t==="yes";switch(i){case"card":{let u=rt(n.root,a,c?"yes":"no",{by:l,note:s.note,now:o});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}`}:u}case"schedule":{let u=await(c?Ne:Fe)(a,{configPath:lt(n),reload:n.reload});return u.success?{ok:!0,message:u.message}:{ok:!1,error:u.message}}case"memory":{let u=a.indexOf("/");if(u<=0)return{ok:!1,error:"memory keys look like memory:<agent>/<fact-id>"};let d=a.slice(0,u),g=a.slice(u+1);if(!ct(n.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new re(n.root);return f.held(d).some(m=>m.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=le(n),d=c?Be(u,a,{by:l,force:s.force,now:o}):We(u,a,{by:l,reason:s.note,now:o});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}}}var dt=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function li(n){return n==="/api/memory"||n.startsWith("/api/memory/")||n==="/approvals"||n.startsWith("/approvals/")||n==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(n)||n==="/traces"||n.startsWith("/traces/")||n==="/voice/history"||n.startsWith("/voice/history/")||n==="/voice/transcribe"||n==="/voice/speak"}function ci(n){return n==="/reload"||n==="/api/processes/kill"||n==="/send"||n==="/send/agent"||n==="/send/contact"||n==="/mesh/announce"||n==="/voice/settings"||n==="/voice/preview"||/^\/api\/tasks\/[^/]+\/(cancel|followup)$/.test(n)||/^\/crons\/[^/]+\/enabled$/.test(n)}function ui(n){return dt.has(n)}function di(n){if(n.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(n.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(dt.has(n.remoteAddress))return{allowed:!0,reason:"loopback"};if(n.acceptedTokens.size===0)return{allowed:!0,reason:"no-tokens-configured"};let e=n.authorizationHeader||"",t=e.startsWith("Bearer ")?e.slice(7).trim():"";return t&&n.acceptedTokens.has(t)?{allowed:!0,reason:"token"}:{allowed:!1,reason:"missing-or-invalid-token"}}function gi(n,e=process.env){let t=new Set;e.MESH_TOKEN&&t.add(e.MESH_TOKEN);for(let s of n.mesh?.peers||[])s.token&&t.add(s.token);return t}function fi(n,e,t=process.env){let s=i=>i.replace(/\/+$/,"");return(e===s(n.daemonUrl)?n.token:n.daemons.find(i=>s(i.url)===e)?.token)||t.MESH_TOKEN||void 0}function z(n){return(Array.isArray(n)?n[0]:n)?.trim()??""}function tr(n){try{return new URL(n).host.toLowerCase()}catch{return null}}function nr(n=process.env){return new Set((n.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function pi(n,e=nr()){let t=z(n.origin);if(t){if(e.has(t.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=tr(t),i=[z(n.host),z(n["x-forwarded-host"])].filter(Boolean).map(a=>a.toLowerCase());return r&&i.includes(r)?"same-origin":"foreign"}let s=z(n["sec-fetch-site"]).toLowerCase();return s==="cross-site"||s==="same-site"?"foreign":"none"}function hi(n){let e=(n||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{readFileSync as ue,writeFileSync as yt,existsSync as de,readdirSync as dr,statSync as gr}from"fs";import{resolve as ge,join as fr}from"path";import{existsSync as gt,mkdirSync as rr,readFileSync as sr,writeFileSync as ft}from"fs";import{dirname as ir,resolve as mt}from"path";import{z as p}from"zod";var or=p.object({type:p.enum(["gitlab","github"]),host:p.string().optional(),project:p.string(),iid:p.number().int().positive(),url:p.string()}),ar=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:or.optional(),importedAt:p.string().optional(),createdAt:p.string(),updatedAt:p.string(),blocker:p.string().optional(),doneNote:p.string().optional()}),lr=p.object({version:p.literal(1),items:p.array(ar).default([])}),H=class{constructor(e){this.path=e}jsonPath(){return mt(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return mt(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return gt(this.jsonPath())}load(){let e=this.jsonPath();if(!gt(e))return{version:1,items:[]};let t=sr(e,"utf-8");try{return lr.parse(JSON.parse(t))}catch(s){throw new Error(`Backlog file invalid (${e}): ${s.message}`)}}save(e){let t=this.jsonPath();rr(ir(t),{recursive:!0}),ft(t,JSON.stringify(e,null,2)+`
|
|
7
|
-
`),ft(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(t=>t.id===e)}add(e){let t=this.load();if(t.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 t.items.push(r),this.save(t),r}addMany(e){let t=this.load(),s=new Set(t.items.map(a=>a.id)),r=new Date().toISOString(),i=[];for(let a of e){if(s.has(a.id))continue;let o={...a,labels:a.labels??[],status:a.status??"todo",createdAt:a.createdAt??r,updatedAt:r};t.items.push(o),i.push(o),s.add(o.id)}return i.length&&this.save(t),i}update(e,t){let s=this.load(),r=s.items.findIndex(a=>a.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let i={...s.items[r],...t,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 t=this.load(),s=t.items.length;return t.items=t.items.filter(r=>r.id!==e),t.items.length===s?!1:(this.save(t),!0)}toMarkdown(e){let t=["# 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,a]of r)if(s[i].length){t.push(`## ${a}`,"");for(let o of s[i]){let l=i==="done"?"x":" ",c=o.assignee?`@${o.assignee} `:"",u=o.estimatedSeconds?` [time: ${Math.round(o.estimatedSeconds/60)}m]`:"",d=o.source?` (${o.source.type}: ${o.source.project}#${o.source.iid})`:"";t.push(`- [${l}] ${c}${o.title}${u}${d}`),o.source?.url&&t.push(` - <${o.source.url}>`),o.labels.length&&t.push(` - labels: ${o.labels.join(", ")}`),o.milestone&&t.push(` - milestone: ${o.milestone}`),o.blocker&&t.push(` - BLOCKED: ${o.blocker}`)}t.push("")}return t.join(`
|
|
8
|
-
`)}};function Si(n){return`${n.type}:${n.project}:${n.iid}`}function pt(n,e,t){let s=[];if(e.type==="gitlab"){let r=t.channels.gitlab?.agentMappings??[];for(let i of n){let a=r.find(o=>o.agentId===i);a?.gitlabUsernames?.length?s.push(a.gitlabUsernames[0]):s.push(i)}}else if(e.type==="github"){let r=t.channels.github?.agentMappings??[];for(let i of n){let a=r.find(o=>o.agentId===i);a?.githubUsernames?.length?s.push(a.githubUsernames[0]):s.push(i)}}return s}async function ce(n,e,t,s=()=>{}){return n.source?n.source.type==="gitlab"?cr(n.source,e,t,s):n.source.type==="github"?ur(n.source,e,t,s):{ok:!1,error:`unknown source.type ${n.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function cr(n,e,t,s){let r=t.channels.gitlab,i=r?.token,a=r?.host||(n.host?`https://${n.host}`:void 0);if(!i||!a)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let o=[],l=async(f,m={})=>fetch(`${a}/api/v4${f}`,{...m,headers:{"PRIVATE-TOKEN":i,"Content-Type":"application/json",...m.headers||{}}}),c=encodeURIComponent(n.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async m=>{try{let h=await fetch(`${a}/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 l(`/projects/${c}/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 l(`/projects/${c}/issues/${n.iid}`,{method:"PUT",body:JSON.stringify(g)});if(o.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let m=await f.text().catch(()=>"");return{ok:!1,attempts:o,error:`PUT issue ${f.status}: ${m.slice(0,200)}`,url:n.url}}}catch(f){return o.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:o,error:f.message,url:n.url}}if(e.note)try{let f=await l(`/projects/${c}/issues/${n.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){o.push({kind:"POST note",ok:!1,error:f.message})}return{ok:o.every(f=>f.ok),attempts:o,url:n.url}}async function ur(n,e,t,s){let i=t.channels.github?.token;if(!i)return{ok:!1,error:"github token not configured",attempts:[]};let a=[],o=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=n.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let g=await o(`/repos/${l}/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&&(c=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 o(`/repos/${l}/issues/${n.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),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let g=await o(`/repos/${l}/issues/${n.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(a.push({kind:"PATCH issue",ok:g.ok,status:g.status}),!g.ok){let f=await g.text().catch(()=>"");return{ok:!1,attempts:a,error:`PATCH issue ${g.status}: ${f.slice(0,200)}`,url:n.url}}}catch(g){return a.push({kind:"PATCH issue",ok:!1,error:g.message}),{ok:!1,attempts:a,error:g.message,url:n.url}}if(e.note)try{let g=await o(`/repos/${l}/issues/${n.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST comment",ok:g.ok,status:g.status})}catch(g){a.push({kind:"POST comment",ok:!1,error:g.message})}return{ok:a.every(g=>g.ok),attempts:a,url:n.url}}var fe=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,V=/@([a-z0-9_-]+)/i,ht=/\[time:\s*([0-9hm\s]+)\]/i;function mr(n){let e=n.match(/(\d+)\s*h/i),t=n.match(/(\d+)\s*m/i);return(e?parseInt(e[1],10)*3600:0)+(t?parseInt(t[1],10)*60:0)}var me=class{constructor(e,t,s=()=>{}){this.path=e;this.daemon=t;this.log=s;this.store=new H(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 t=ge(process.cwd(),this.path);yt(t,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 t=this.readMd(),s=[];for(let r=0;r<t.length;r++){let i=t[r].match(fe);if(!i||i[2].toLowerCase()==="x")continue;let o=i[3],l=o.match(V);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=o.match(ht),u=o.replace(V,"").replace(ht,"").trim();s.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?mr(c[1]):void 0,priority:r})}return s}async listAll(e={}){return this.store.exists()?this.store.list().map(t=>this.toWorkItem(t)):[]}async claim(e,t){if(!this.store.exists())return;let s=this.store.findById(t);if(!s)return;let r=this.store.update(t,{assignee:s.assignee||e,status:"doing"});if(r.source&&this.daemon){let i=pt([r.assignee||e],r.source,this.daemon);ce(r,{assigneeUsernames:i,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(a=>this.log(`[backlog-sync] claim failed for ${t}: ${a?.message??a}`))}}async report(e,t){if(this.store.exists()&&this.store.findById(e)){let o={};t.status==="done"?o.status="done":t.status==="blocked"?(o.status="blocked",o.blocker=t.blocker||t.note||void 0):t.status==="in-progress"&&(o.status="doing"),t.timeSeconds&&(o.estimatedSeconds=t.timeSeconds);let l=this.store.update(e,o);if(l.source&&this.daemon){let c={};t.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):t.status==="blocked"&&(c.addLabels=["Blocked"]),t.note&&(c.note=t.note),Object.keys(c).length&&ce(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(fe))throw new Error(`backlog line ${s} not a checkbox`);if(t.status==="done"){r[s]=i.replace(/- \[ \]/,"- [x]");let o=t.timeSeconds?` <!-- done by agent, ${Math.round(t.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(s+1,0,o)}else t.status==="blocked"?r.splice(s+1,0,` <!-- BLOCKED: ${t.blocker||t.note||"?"} -->`):t.note&&r.splice(s+1,0,` <!-- ${t.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let t={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:t,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},pe=class{constructor(e,t){this.root=e;this.glob=t}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,t){if(de(e))for(let s of dr(e)){let r=fr(e,s);gr(r).isDirectory()?this.walk(r,t):s.endsWith(".md")&&t.push(r)}}async listOpen(e){let t=[];this.walk(ge(process.cwd(),this.root),t);let s=[];for(let r of t){let i=ue(r,"utf-8").split(`
|
|
11
|
-
`);for(let a=0;a<i.length;a++){let o=i[a].match(fe);if(!o||o[2].toLowerCase()==="x")continue;let l=o[3].match(V);!l||l[1].toLowerCase()!==e.toLowerCase()||s.push({id:`wiki:${r}:${a}`,title:o[3].replace(V,"").trim(),assignee:l[1],priority:a})}}return s}async claim(){}async report(e,t){let s=e.split(":"),r=parseInt(s[s.length-1],10),i=s.slice(1,-1).join(":");if(!de(i))return;let a=ue(i,"utf-8").split(`
|
|
12
|
-
`);t.status==="done"&&a[r]&&(a[r]=a[r].replace(/- \[ \]/,"- [x]"),yt(i,a.join(`
|
|
13
|
-
`)))}},he=class{constructor(e,t,s,r,i){this.host=e;this.token=t;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[t,s]of Object.entries(this.agentUsernames))if(s.some(r=>r.toLowerCase()===e.toLowerCase()))return t}mapIssue(e,t){let s=e.references?.full?.split("#")[0]||t,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 o=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=o[0]?.username;return{id:`gitlab:${s}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:o,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:i,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,t={}){let s=await fetch(`${this.host}/api/v4${e}`,{...t,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...t.headers||{}}});if(!s.ok)throw new Error(`GitLab ${s.status}: ${await s.text().catch(()=>"")}`);return s.json()}async listOpen(e){let t=this.agentUsernames[e]||[];if(!t.length)return[];let s=[],r=this.projects.length?this.projects:["__ALL__"];for(let i of t)for(let a of r)try{let o=`assignee_username=${encodeURIComponent(i)}&state=opened&scope=all&per_page=20`,l=a==="__ALL__"?`/issues?${o}`:`/projects/${encodeURIComponent(a)}/issues?${o}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,a);d.assignee=e,s.push(d)}}catch(o){this.log(`[business] GitLab listOpen failed for ${i} on ${a}: ${o.message}`)}return s}async claim(e,t){let{project:s,iid:r,type:i}=this.parseId(t),a=`/projects/${encodeURIComponent(s)}/${i==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(a,{method:"PUT"})}catch(o){this.log(`[business] claim label update failed: ${o.message}`)}}async report(e,t){let{project:s,iid:r,type:i}=this.parseId(e),a=i==="issue"?"issues":"merge_requests";if(t.timeSeconds&&t.timeSeconds>0){let o=Math.max(1,Math.round(t.timeSeconds/60)),l=o>=60?`${Math.floor(o/60)}h${o%60?` ${o%60}m`:""}`:`${o}m`;try{await this.api(`/projects/${encodeURIComponent(s)}/${a}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(t.status==="done")try{await this.api(`/projects/${encodeURIComponent(s)}/${a}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(o){this.log(`[business] done label update failed: ${o.message}`)}else if(t.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(s)}/${a}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(o){this.log(`[business] blocked label update failed: ${o.message}`)}if(t.note)try{await this.api(`/projects/${encodeURIComponent(s)}/${a}/${r}/notes`,{method:"POST",body:JSON.stringify({body:t.note})})}catch(o){this.log(`[business] report note failed: ${o.message}`)}}async listAll(e={}){let t=e.sinceDays??30,s=new Date(Date.now()-t*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 a=this.projects.length?this.projects:["__ALL__"],o=[];for(let c of a)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let g of d)o.push(this.mapIssue(g,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=o;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,t){let{project:s,iid:r,type:i}=this.parseId(e),a=i==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(s)}/${a}/${r}?state_event=${t}`,{method:"PUT"})}async getItem(e){let{project:t,iid:s}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(t)}/issues/${s}?with_labels_details=true`);return{...this.mapIssue(r,t),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(a=>a.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,t){let{project:s,iid:r}=this.parseId(e),i;t.assigneeUsernames&&(i=(await Promise.all(t.assigneeUsernames.map(async u=>{try{let d=await this.api(`/users?username=${encodeURIComponent(u)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch{return null}}))).filter(u=>typeof u=="number"));let a;if(t.milestoneTitle!==void 0)if(t.milestoneTitle===null||t.milestoneTitle==="")a=0;else try{let c=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(t.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(a=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${t.milestoneTitle}": ${c.message}`)}let o={};t.title!==void 0&&(o.title=t.title),t.description!==void 0&&(o.description=t.description),t.labels!==void 0&&(o.labels=t.labels.join(",")),t.addLabels?.length&&(o.add_labels=t.addLabels.join(",")),t.removeLabels?.length&&(o.remove_labels=t.removeLabels.join(",")),i!==void 0&&(o.assignee_ids=i),a!==void 0&&(o.milestone_id=a);let l=await this.api(`/projects/${encodeURIComponent(s)}/issues/${r}`,{method:"PUT",body:JSON.stringify(o)});return this.mapIssue(l,s)}async listMembers(){let e=new Map;for(let t of this.projects)try{let s=await this.api(`/projects/${encodeURIComponent(t)}/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 ${t}: ${s.message}`)}return[...e.values()].sort((t,s)=>t.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 t=[...e.values()];return t.sort((s,r)=>s.state!==r.state?s.state==="active"?-1:1:s.title.localeCompare(r.title)),t}async create(e){let t=e.projectHint||this.projects[0];if(!t)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(t)}/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 a={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};s?.length&&(a.assignee_ids=s),i!==void 0&&(a.milestone_id=i);let o=await this.api(`/projects/${encodeURIComponent(t)}/issues`,{method:"POST",body:JSON.stringify(a)});return this.mapIssue(o,t)}async transition(e,t,s){await this.transitionMany(e,t?[t]:[],s?[s]:[])}async transitionMany(e,t,s){let{project:r,iid:i,type:a}=this.parseId(e),o=a==="issue"?"issues":"merge_requests",l=new URLSearchParams;t.length&&l.set("add_labels",t.join(",")),s.length&&l.set("remove_labels",s.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${o}/${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 Ri(n,e,t){let s=n.workSource;switch(s.type){case"backlog":return new me(s.path,e,t);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 o of r.agentMappings)o.gitlabUsernames.length&&(i[o.agentId]=o.gitlabUsernames);let a=s.projects.length?s.projects:r.routes.map(o=>o.project);return new he(r.host,r.token,a,i,t)}}}var ye="unmapped";function be(n,e=[]){if(!n)return ye;let t=e.find(r=>r.id===n);if(t?.client)return t.client;let s=n.indexOf("/");return s>0?n.slice(0,s):n}function pr(n){let e=new Map,t=n.projects??[],s=n.orgChart??{};for(let i of t)i.pm&&(e.has(i.pm)||e.set(i.pm,be(i.id,t)));let r=(i,a=new Set)=>{if(e.has(i))return e.get(i);if(a.has(i))return;a.add(i);let o=s[i]?.reportsTo;if(!o)return;let l=r(o,a);return l&&e.set(i,l),l};for(let i of Object.keys(s))r(i);return e}function hr(n,e,t=[]){if(!t.length)return;let s=t.filter(r=>!r.channel||r.channel===n);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 Ci(n,e){let t=hr(n.channel,{chatId:n.chatId,username:n.username},e.contactMap);if(t)return t.client;if(n.project)return be(n.project,e.projects);if(n.agentId){let s=pr(e).get(n.agentId);if(s)return s}return ye}function Ti(n,e){let t=String(n||"").split(":");if(t.length<3)return{agentId:e};let[s,r,...i]=t,a=i.join(":"),o={agentId:e||s,channel:r};return r==="gitlab"||r==="github"?o.project=a.split(":")[0]:r==="cron"||r==="api"||(o.chatId=a.split("@")[0]),o}var yr=n=>n===ye?"internal":"client";function br(n,e){let t=e.clients?.[n];return{id:n,name:t?.name||n,kind:t?.kind??yr(n),respondWithinMinutes:wr(t?.respondWithin),standing:t?.standing??[],declared:!!t}}function Di(n){let e=new Set;for(let t of n.projects??[])e.add(be(t.id,n.projects));for(let t of n.contactMap??[])e.add(t.client);for(let t of Object.keys(n.clients??{}))e.add(t);return[...e].sort().map(t=>br(t,n))}function wr(n){let e=/^(\d+)\s*([mhd])$/.exec(String(n??"").trim());if(!e)return;let t=Number(e[1]);return e[2]==="m"?t:e[2]==="h"?t*60:t*1440}var kr=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Sr=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function bt(n){if(!n||!n.includes("agentx:ui"))return{cleanText:n};let e=[...n.matchAll(Sr)];if(e.length===0)return{cleanText:n};let t=e[e.length-1],s=t[2],r=xr(s);if(!r)return{cleanText:n};let i=t.index??0,a=t[1]??"";return{cleanText:(n.slice(0,i)+a+n.slice(i+t[0].length)).trim(),ui:r}}function ji(n){if(!n||!n.includes("agentx:ui"))return n;let e=kr.exec(n);return e?n.slice(0,e.index).trimEnd():n}function xr(n){let e;try{e=JSON.parse(n)}catch{return null}if(!e||typeof e!="object")return null;let t={};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&&(t.buttons=s),r.length&&(t.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&&(t.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&&(t.media={type:s,url:r,...typeof i=="string"?{caption:i}:{}})}return!t.buttons&&!t.poll&&!t.media&&!t.skippedActions?null:t}import{execFile as Pr,execFileSync as Or}from"child_process";import{execFileSync as $r}from"child_process";import{existsSync as kt,mkdirSync as vr,readdirSync as Ir,readFileSync as St,renameSync as _r,writeFileSync as Ar}from"fs";import{homedir as xt}from"os";import{join as ke}from"path";var Se="siri:",$t="com.apple.ttsbundle.gryphon-neural_",vt=n=>!!n&&n.startsWith($t),Rr=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],Er=()=>{try{return $r("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},we;function xe(n={}){let e=n.platform!==void 0||n.exists!==void 0||n.prefDomain!==void 0;if(!e&&we!==void 0)return we;let{platform:t=process.platform,exists:s=kt,prefDomain:r=Er}=n,i=t==="darwin"&&Rr.every(a=>s(a))&&r();return e||(we=i),i}var Cr=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Tr={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"},Dr=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function Lr(n){let e=new Map;for(let t of n)for(let[,s,r,i]of t.matchAll(Dr)){let a=`${s}-${r}`,o=`${$t}${i}_${a}_premium`;e.has(o)||e.set(o,{id:o,name:i[0].toUpperCase()+i.slice(1),locale:a,quality:"premium",gender:Tr[i]??null,siri:!0})}return[...e.values()]}function K(n=Cr,e={}){if(!xe(e))return[];let t=[];for(let s of n){let r;try{r=Ir(s)}catch{continue}for(let i of r)try{t.push(St(ke(s,i,"Info.plist"),"latin1"))}catch{}}return Lr(t)}var wt=`#!/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
|
-
`,jr=(n=xt())=>ke(n,".agentx","voice","siri-say.sh");function It(n=xt()){let e=jr(n);return kt(e)&&St(e,"utf8")===wt||(vr(ke(n,".agentx","voice"),{recursive:!0}),Ar(`${e}.tmp`,wt,{mode:493}),_r(`${e}.tmp`,e)),e}var _t=`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")`,Nr=new Set(["Fred","Kathy","Ralph","Junior"]),Fr={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 At(n){let e=[];for(let t of n.split(`
|
|
108
|
-
`)){let[s,r,i,a,o]=t.split(" ");!s||!r||!i||s.includes(".siri_")||s.startsWith("com.apple.speech.synthesis.voice.")&&!Nr.has(r)||e.push({id:s,name:r,locale:i,quality:a==="3"?"premium":a==="2"?"enhanced":"standard",gender:o==="1"?"male":o==="2"?"female":Fr[r]??null})}return e}var Mr=10*60*1e3,D=null,$e=!1;function zi(n=Date.now()){if(process.platform!=="darwin")return[];if(D)n-D.at>Mr&&!$e&&($e=!0,Pr("osascript",["-l","JavaScript","-e",_t],{timeout:1e4},(e,t)=>{$e=!1,e||(D={at:Date.now(),voices:[...At(String(t)),...K()]})}));else try{D={at:n,voices:[...At(Or("osascript",["-l","JavaScript","-e",_t],{encoding:"utf8",timeout:1e4})),...K()]}}catch(e){ve(`[voice] could not list system voices: ${String(e?.message??e).split(`
|
|
109
|
-
`)[0]}`),D={at:n,voices:K()}}return D.voices}var ve=n=>process.stderr.write(n+`
|
|
110
|
-
`),Rt=new Set;function Hi(n){ve=n}function G(n,e){Rt.has(n)||(Rt.add(n),ve(e))}var Ur={premium:3,enhanced:2,standard:1},Br=new Set(["Grandma","Grandpa"]);function Et(n){let e=n.id.startsWith("com.apple.voice.")?2:n.id.startsWith("com.apple.eloquence.")&&!Br.has(n.name)?1:0;return Ur[n.quality]*10+e}var Ct=n=>n.toLowerCase().split(/[-_]/)[0];function Tt(n,e="en"){let t=e.toLowerCase().replace("_","-"),s=Ct(e),r=n.filter(i=>Ct(i.locale)===s);return(r.length?r:n).slice().sort((i,a)=>Et(a)-Et(i)||+(a.locale.toLowerCase()===t)-+(i.locale.toLowerCase()===t)||i.name.localeCompare(a.name)||i.locale.localeCompare(a.locale))}function Wr(n,e,t="en"){let s=n.trim();if(!s)return null;let r=e.find(c=>c.id===s);if(r)return r;if(s.toLowerCase().startsWith(Se)){let c=s.slice(Se.length).trim().toLowerCase(),u=Tt(e.filter(g=>g.siri&&g.name.toLowerCase()===c),t)[0];if(u||!c)return u??null;let d=Wr(c,e,t);return d&&G(`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),a=(i?i[1]:s.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),o=Tt(e.filter(c=>c.name.toLowerCase()===a),t);return(i?o.find(c=>c.quality===i[2].toLowerCase()):void 0)??o[0]??null}function Vi(n,e,t=new Set){let s=new Map;if(!e.length)return s;let r=new Set([...t].map(a=>a.toLowerCase())),i="female";for(let a of n){let o=a.gender==="female"||a.gender==="male",l=o?a.gender:i,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(o?e.find(d=>d.gender===l):void 0)??c[0]??e[s.size%e.length];s.set(a.id,u),r.add(u.name.toLowerCase()),o||(i=i==="female"?"male":"female")}return s}import{spawn as X}from"child_process";import{readFileSync as Kr,writeFileSync as Gr}from"fs";import{tmpdir as Xr}from"os";import{join as qr}from"path";var zr=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(" ")),Hr=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(" ")),Vr=/[éèêëàâçùûîïôœ]/;function Dt(n){let e=(n.match(/[-ۿ]/g)??[]).length,t=(n.match(/[a-zA-ZÀ-ÿ]/g)??[]).length;if(e&&e>=t)return"ar";let s=0,r=0;for(let i of n.toLowerCase().replace(/[’]/g,"'").match(/[a-zà-ÿœ']+/g)??[])zr.has(i)&&s++,Hr.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?r++:Vr.test(i)&&(r+=.5);return s===r?null:s>r?"en":"fr"}var Lt=n=>n&&n!==1?Math.round(175*n):null,q=n=>n&&n!==1?Math.min(1.2,Math.max(.7,n)):null;function Jr(){if(process.env.ELEVENLABS_API_KEY)return process.env.ELEVENLABS_API_KEY;for(let n of[`${process.env.HOME}/.elevenlabs/key`,`${process.env.HOME}/.agentx/elevenlabs-key.txt`])try{let e=Kr(n,"utf8").trim();if(e)return e}catch{}return null}function to(n=Jr()){let e=0;return async(t,s)=>{if(t.voice.provider==="system")return null;if(!n){if(t.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/${t.voice.elevenlabs}/stream?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":n,"Content-Type":"application/json"},body:JSON.stringify({text:t.text,model_id:"eleven_flash_v2_5",...q(t.voice.rate)?{voice_settings:{speed:q(t.voice.rate)}}:{}}),signal:s});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let i=qr(Xr(),`agentx-say-${process.pid}-${++e}.mp3`);return Gr(i,Buffer.from(await r.arrayBuffer())),i}catch(r){if(s.aborted||!t.voice.fallback)throw r;return G(`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 jt(n,e){let t=n.languages&&Dt(e);return t&&n.languages&&t in n.languages?n.languages[t]:n.system}var Yr=(n,e="")=>{let t=jt(n,e),s=Lt(n.rate);return[...t&&!vt(t)?["-v",t]:[],...s?["-r",String(s)]:[]]};function Zr(n,e,t){if(!t)return["say",Yr(n,e)];let s=jt(n,e);return["/bin/sh",[t,...s?[s]:[]]]}function no(n){let e=n.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function ro(n=Pt()){if(n)try{X("/bin/sh",[n,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Pt(n={},e){if(!xe(n))return null;try{return It(e)}catch(t){return G("siri-say",`[voice] could not write the Siri voice script (${String(t?.message??t).split(`
|
|
111
|
-
`)[0]}); Siri voices will not switch`),null}}var so=(n,e)=>{if(!n){let[t,s]=Zr(e.voice,e.text,Pt()),r=Lt(e.voice.rate),i=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,a=X(t,s,{stdio:["pipe","ignore","ignore"],env:i});return a.stdin?.on("error",()=>{}),a.stdin?.end(e.text),a}return process.platform==="darwin"?X("afplay",[n],{stdio:"ignore"}):X("mpg123",["-q",n],{stdio:"ignore"})};import{spawn as Qr}from"child_process";import{accessSync as es,constants as ts,readFileSync as Ot}from"fs";import{homedir as ns}from"os";import{basename as Y,delimiter as Nt,dirname as Ft,extname as rs,join as Z}from"path";var R={bytes:10*1024*1024,ms:2*60*1e3},ss={"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 Mt(n){let e=String(n||"").split(";")[0].trim().toLowerCase();return ss[e]??null}function Ut(n,e){let t=[];return n!=="local"&&e.key&&t.push("elevenlabs"),e.ffmpeg&&(e.mlx?t.push("mlx-whisper"):e.whisper&&t.push("whisper")),t}function Bt(n,e){return n==="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 J(n,e,t=process.env.PATH??""){let s=ns(),r=[Z(s,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...t.split(Nt).filter(Boolean)];for(let i of[e,...r.map(a=>Z(a,n))])if(i)try{return es(i,ts.X_OK),i}catch{}return null}function uo(n){return{key:n,mlx:J("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:J("whisper",process.env.AGENTX_WHISPER),ffmpeg:J("ffmpeg",process.env.AGENTX_FFMPEG)}}async function Wt(n,e){let t=e?Z(Ft(e),"ffprobe"):J("ffprobe");if(!t)return null;try{let s=await Vt(t,["-v","error","-show_entries","format=duration","-of","csv=p=0",n],1e4),r=parseFloat(s.trim());return Number.isFinite(r)?r:null}catch{return null}}async function zt(n,e,t,s){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Ot(n)],{type:e}),Y(n));let i=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":t},body:r,signal:s??AbortSignal.timeout(6e4)});if(!i.ok)throw new Error(`ElevenLabs ${i.status}: ${(await i.text().catch(()=>"")).slice(0,160)}`);let a=await i.json();if(typeof a.text!="string")throw new Error("ElevenLabs returned no text");return a.text.trim()}async function Ht(n,e,t,s,r){let i=n==="mlx-whisper"?["--model",process.env.AGENTX_MLX_MODEL||"mlx-community/whisper-large-v3-turbo","--output-format","txt","--output-dir",r,t]:[t,"--model",process.env.AGENTX_WHISPER_MODEL||"base","--output_format","txt","--output_dir",r,"--fp16","False"],a={...process.env,PATH:`${Ft(s)}${Nt}${process.env.PATH??""}`};await Vt(e,i,12e4,a);try{return Ot(Z(r,Y(t,rs(t))+".txt"),"utf8").trim()}catch{throw new Error(`${n} wrote no transcript`)}}function Vt(n,e,t,s=process.env){return new Promise((r,i)=>{let a=Qr(n,e,{stdio:["ignore","pipe","pipe"],env:s}),o="",l="",c=setTimeout(()=>{a.kill("SIGKILL"),i(new Error(`${Y(n)} took longer than ${t/1e3}s`))},t);a.stdout.on("data",u=>{o.length<4096&&(o+=u)}),a.stderr.on("data",u=>{l.length<4096&&(l+=u)}),a.on("error",u=>{clearTimeout(c),i(u)}),a.on("exit",u=>{clearTimeout(c),u===0?r(o):i(new Error(`${Y(n)} exited ${u}: ${l.trim().split(`
|
|
112
|
-
`).pop()?.slice(0,160)??""}`))})})}function Kt(n,e=800){let t=n;return t=t.replace(/```[\s\S]*?```/g,". "),t=t.replace(/`[^`]*`/g,""),t=t.replace(/\*\*(.*?)\*\*/g,"$1"),t=t.replace(/__(.*?)__/g,"$1"),t=t.replace(/\*([^*]+)\*/g,"$1"),t=t.replace(/_([^_]+)_/g,"$1"),t=t.replace(/~~(.*?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),t=t.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),t=t.replace(/^#{1,6}\s+/gm,""),t=t.replace(/^[\s]*[-*+]\s+/gm,". "),t=t.replace(/^[\s]*\d+\.\s+/gm,". "),t=t.replace(/^[-=_]{3,}$/gm,""),t=t.replace(/^>\s*/gm,""),t=t.replace(/https?:\/\/\S+/g,"link"),t=t.replace(/\/\w+(\/\w+)+/g,s=>s.split("/").filter(Boolean).join(" slash ")),t=t.replace(/&/g," and "),t=t.replace(/@/g," at "),t=t.replace(/=>/g," returns "),t=t.replace(/->/g," to "),t=t.replace(/\|/g," or "),t=t.replace(/\be\.g\./gi,"for example"),t=t.replace(/\bi\.e\./gi,"that is"),t=t.replace(/\betc\./gi,"etcetera"),t=t.replace(/\bvs\.?\b/gi,"versus"),t=t.replace(/\n{2,}/g,". "),t=t.replace(/\n/g," "),t=t.replace(/\s+/g," "),t=t.replace(/\.\s*\./g,"."),t=t.replace(/\s+([.,!?])/g,"$1"),t=t.trim().replace(/^[.,:;]+\s*/,""),t.length>e&&(t=t.slice(0,e).replace(/\s+\S*$/,"")+"..."),t}import{mkdtemp as is,rm as os,writeFile as as}from"fs/promises";import{tmpdir as ls}from"os";import{join as Gt}from"path";var cs=1500,us=64*1024;function So(n){return n==="/voice/transcribe"||n==="/voice/speak"}async function xo(n,e,t,s){return n.method!=="POST"?w(e,405,{error:"POST"}):t==="/voice/transcribe"?ds(n,e,s):ms(n,e,s)}async function ds(n,e,t){let s=String(n.headers["content-type"]||""),r=Mt(s);if(!r)return w(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let i=ys(n.headers["x-audio-duration-ms"]);if(i)return w(e,413,{error:i});let a=await Xt(n,R.bytes);if(!a)return w(e,413,{error:`The recording is larger than ${R.bytes/1024/1024} MB.`});if(!a.length)return w(e,400,{error:"The recording is empty."});let o=t.stt(),l=t.host(),c=Ut(o,l);if(!c.length)return w(e,503,{error:"Voice input isn't set up on this computer.",hint:Bt(o,l),setup:!1});let u=await is(Gt(ls(),"agentx-phone-voice-")),d;try{d=await gs(u,`speech.${r}`,a,s,l,c,t)}finally{await os(u,{recursive:!0,force:!0}).catch(()=>{})}w(e,d[0],d[1])}async function gs(n,e,t,s,r,i,a){let o=Gt(n,e);await as(o,t,{mode:384});let l=await Wt(o,r.ffmpeg);if(l!=null&&l*1e3>R.ms+2e3)return[413,{error:`The recording is longer than ${R.ms/6e4} minutes.`}];let c=[];for(let u of i)try{let d=await fs(u,o,s,r,n,a);return a.log(`[voice] phone recording transcribed with ${u} (${Math.round(t.length/1024)} KB)`),d?[200,{text:d,engine:u}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:u}]}catch(d){let g=String(d?.message??d).split(`
|
|
113
|
-
`)[0].slice(0,200);c.push(`${u}: ${g}`),a.log(`[voice] phone transcription with ${u} failed: ${g}`)}return[502,{error:"Speech to text failed on this computer.",detail:c.join("; ")}]}function fs(n,e,t,s,r,i){let a=i.engines?.[n];if(a)return a(e,t,s,r);if(n==="elevenlabs")return zt(e,t,s.key);let o=n==="mlx-whisper"?s.mlx:s.whisper;return Ht(n,o,e,s.ffmpeg,r)}async function ms(n,e,t){let s=await Xt(n,us);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:"",a=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!i)return w(e,400,{error:"agent is required"});let o=ps(typeof r?.text=="string"?r.text:"");if(!o)return w(e,422,{error:"Nothing in this answer can be said aloud."});let l=t.voiceOf(i,a);if(!l)return w(e,404,{error:`Unknown agent: ${i}`});let c=(d,g=503)=>w(e,g,{error:d,fallback:"browser",text:o});if(l.provider!=="elevenlabs")return c("This agent speaks with a system voice, which only plays on the computer.");let u=t.elevenLabsKey();if(!u)return c("No ElevenLabs key is set on this computer.");try{let d=await(t.synth??hs)(u,l,o);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(o.length)}),e.end(d)}catch(d){return t.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
|
|
114
|
-
`)[0].slice(0,160)}`),c("ElevenLabs could not speak this answer.",502)}}function ps(n){return Kt(bt(n).cleanText,cs)}async function hs(n,e,t){let s=q(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":n,"Content-Type":"application/json"},body:JSON.stringify({text:t,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())}function ys(n){let e=Number(Array.isArray(n)?n[0]:n);return Number.isFinite(e)&&e>R.ms+2e3?`The recording is longer than ${R.ms/6e4} minutes.`:null}function Xt(n,e){return Number(n.headers["content-length"])>e?(n.resume(),Promise.resolve(null)):new Promise((t,s)=>{let r=[],i=0;n.on("data",a=>{if(!(i>e)){if(i+=a.length,i>e){r.length=0,t(null);return}r.push(a)}}),n.on("end",()=>{i<=e&&t(Buffer.concat(r))}),n.on("error",s)})}function w(n,e,t){n.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),n.end(JSON.stringify(t))}import{existsSync as x,readFileSync as Re,writeFileSync as Ee,mkdirSync as Q,readdirSync as Ae,rmSync as bs,statSync as I}from"fs";import{resolve as qt,relative as ws,dirname as Ce,join as E,extname as O,basename as Te}from"path";var S=200*1024,Jt=new Set([".md",".markdown",".txt"]),L=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"]),ks=6,Ss=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function A(n,e){if(!n)throw new Error("Agent workspace is not configured.");let t=qt(n);if(x(t)||Q(t,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let s=qt(t,e);if(ws(t,s).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return s}function Yt(n){let e=O(n).toLowerCase();if(!Jt.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function Ie(n,e){let t=n.split(/\r?\n/).find(s=>s.trim().startsWith("#"));return t&&t.replace(/^#+\s*/,"").trim().slice(0,120)||e}function _o(n){let e=A(n,"."),t=[],s=new Set,r=[];try{r=Ae(e)}catch{}for(let o of Ss){let l=E(e,o);if(x(l)&&I(l).isFile()){let c=I(l).size,u=c>0&&c<S?_e(l):"";t.push({path:o,title:Ie(u,o),size:c,exists:!0}),s.add(o)}else t.push({path:o,title:o,size:0,exists:!1}),s.add(o)}for(let o of r){if(s.has(o))continue;let l=E(e,o);try{let c=I(l);if(!c.isFile()||!Jt.has(O(o).toLowerCase()))continue;let u=c.size>0&&c.size<S?_e(l):"";t.push({path:o,title:Ie(u,o),size:c.size,exists:!0})}catch{}}let i=[],a=E(e,".claude","skills");if(x(a))try{for(let o of Ae(a)){let l=E(a,o),c;try{c=I(l)}catch{continue}if(!c.isDirectory())continue;let u=E(l,"SKILL.md");if(!x(u))continue;let d=I(u),g=d.size<S?_e(u):"";i.push({slug:o,title:Ie(g,o),size:d.size,path:`.claude/skills/${o}/SKILL.md`})}}catch{}return i.sort((o,l)=>o.slug.localeCompare(l.slug)),{identity:t,skills:i,workspace:e}}function _e(n){try{return Re(n,"utf-8")}catch{return""}}function Ao(n,e){let t=A(n,e);if(Yt(t),!x(t))return{path:e,content:""};if(I(t).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:Re(t,"utf-8")}}function Ro(n,e,t){let s=A(n,e);Yt(s);let r=Buffer.from(t,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return Q(Ce(s),{recursive:!0}),Ee(s,r),{path:e,bytes:r.length}}function Eo(n,e,t={}){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(n,s);if(x(r))throw new Error(`Skill "${e}" already exists.`);Q(Ce(r),{recursive:!0});let i=t.content?.trim()?t.content:xs(e,t.title);return Ee(r,i),{slug:e,path:s}}function Co(n,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let t=A(n,`.claude/skills/${e}`);if(!x(t))throw new Error(`Skill "${e}" not found.`);if(!I(t).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return bs(t,{recursive:!0,force:!0}),{slug:e}}function To(n,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let t=A(n,`.claude/skills/${e}`);if(!x(t))throw new Error(`Skill "${e}" not found.`);let s=[];return r(t,"",0,s),s.sort((i,a)=>i.kind!==a.kind?i.kind==="dir"?-1:1:i.path.localeCompare(a.path)),s;function r(i,a,o,l){if(o>ks)return;let c=[];try{c=Ae(i)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=E(i,u),g=a?`${a}/${u}`:u,f;try{f=I(d)}catch{continue}if(f.isDirectory())l.push({path:`${g}/`,kind:"dir",size:0,editable:!1}),r(d,g,o+1,l);else if(f.isFile()){let m=O(u).toLowerCase(),h=L.has(m)||L.has(u.toLowerCase());l.push({path:g,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function Do(n,e,t){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!t||t.includes(".."))throw new Error(`Invalid file path: ${t}`);let s=A(n,`.claude/skills/${e}/${t}`);if(!x(s)||!I(s).isFile())throw new Error(`File not found: ${t}`);let r=O(s).toLowerCase(),i=Te(s).toLowerCase();if(!L.has(r)&&!L.has(i))throw new Error(`File type not editable: ${t}`);if(I(s).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${t}`);return{path:t,content:Re(s,"utf-8")}}function Lo(n,e,t,s){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!t||t.includes(".."))throw new Error(`Invalid file path: ${t}`);let r=A(n,`.claude/skills/${e}/${t}`),i=O(r).toLowerCase(),a=Te(r).toLowerCase();if(!L.has(i)&&!L.has(a))throw new Error(`File type not editable: ${t}`);let o=Buffer.from(s,"utf-8");if(o.length>S)throw new Error(`File too large (${o.length} > ${S} bytes).`);return Q(Ce(r),{recursive:!0}),Ee(r,o),{path:t,bytes:o.length}}function jo(n,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let t=A(n,`.claude/skills/${e}`);if(!x(t))throw new Error(`Skill "${e}" not found.`);let s=r=>x(E(t,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 xs(n,e){return`# ${e?.trim()||n}
|
|
115
|
-
|
|
116
|
-
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.
|
|
117
|
-
|
|
118
|
-
## When to use
|
|
119
|
-
- Trigger condition 1
|
|
120
|
-
- Trigger condition 2
|
|
121
|
-
|
|
122
|
-
## How to use
|
|
123
|
-
Document the arguments, commands, or files the skill expects. Example:
|
|
124
|
-
|
|
125
|
-
\`\`\`bash
|
|
126
|
-
# Example invocation
|
|
127
|
-
claude-code ${Te(n)} --arg value
|
|
128
|
-
\`\`\`
|
|
129
|
-
`}nn();var Zt={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Qt(n){return{...Zt,...n??{},regions:{...n?.regions??{}},buffer:{...Zt.buffer,...n?.buffer??{}}}}function No(n){try{return Qt(De(n).screen)}catch{return Qt(void 0)}}var $s=/^[a-z][\w-]*$/,en=["window","screen","menubar","notifications"];function N(n,e,t,s){let r=Number(n);if(n===""||n===null||!Number.isFinite(r)||!t(r))throw new Error(`${e} must be ${s}`);return r}var ee=(n,e)=>N(n,e,t=>Number.isInteger(t)&&t>0,"a whole number above 0");function tn(n){let e=typeof n=="string"?n.split(",").map(Number):[n?.x,n?.y,n?.width,n?.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 Fo(n,e){let t={...n??{}};if("maxPixels"in e&&(t.maxPixels=ee(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(t.timeoutMs=ee(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(t.intervalMs=ee(e.intervalMs,"intervalMs")),"stableMs"in e&&(t.stableMs=N(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(t.changeThreshold=N(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...t.regions??{}};for(let[i,a]of Object.entries(e.regions)){if(!$s.test(i))throw new Error(`region name "${i}" must be lowercase letters, digits, - or _`);a===null?delete r[i]:r[i]=tn(a)}t.regions=r}if(e.buffer&&typeof e.buffer=="object"){let r=e.buffer,i={...t.buffer??{}};"enabled"in r&&(i.enabled=!!r.enabled),"seconds"in r&&(i.seconds=N(r.seconds,"buffer.seconds",a=>a>0&&a<=120,"above 0 and at most 120")),"fps"in r&&(i.fps=N(r.fps,"buffer.fps",a=>a>0&&a<=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()),t.buffer=i}let s=t.buffer?.region;if(s!==void 0&&!en.includes(s)&&!t.regions?.[s])try{tn(s)}catch{throw new Error(`buffer.region "${s}" is not a region \u2014 use ${[...en,...Object.keys(t.regions??{})].join(", ")}, or x,y,w,h`)}return t}export{ze as a,_s as b,be as c,pr as d,hr as e,Ci as f,Ti as g,Di as h,bt as i,ji as j,k,Cs as l,Ye as m,Ps as n,Os as o,Qe as p,tt as q,j as r,Us as s,Bs as t,Ws as u,zs as v,Hs as w,W as x,qs as y,ii as z,oi as A,li as B,ci as C,ui as D,di as E,gi as F,fi as G,pi as H,hi as I,zi as J,Hi as K,G as L,Tt as M,Wr as N,Vi as O,Dt as P,Jr as Q,to as R,no as S,ro as T,Pt as U,so as V,R as W,Mt as X,uo as Y,Kt as Z,So as _,xo as $,ys as aa,Xt as ba,H as ca,Si as da,pt as ea,ce as fa,he as ga,Ri as ha,_o as ia,Ao as ja,Ro as ka,Eo as la,Co as ma,To as na,Do as oa,Lo as pa,jo as qa,Zt as ra,Qt as sa,No as ta,en as ua,Fo as va};
|
|
130
|
-
//# sourceMappingURL=chunk-RVEMQCWW.js.map
|