agentix-cli 0.70.1 → 0.72.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/CallModel.swift +55 -0
- package/apps/mac-voice/Sources/AgentXVoice/Calls.swift +172 -0
- package/apps/mac-voice/Sources/AgentXVoice/Panel.swift +28 -3
- package/apps/mac-voice/Sources/AgentXVoice/StatusMenu.swift +2 -0
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +108 -4
- package/dist/{App-LFQTOADB.js → App-244WEQJR.js} +2 -2
- package/dist/{ChatApp-RNMG2HWX.js → ChatApp-SFP6SHUU.js} +2 -2
- package/dist/{agent-7IW6472I.js → agent-PMNBXRFW.js} +2 -2
- package/dist/{board-dashboard-MYWXVYU3.js → board-dashboard-J34PSEJS.js} +491 -217
- package/dist/board-dashboard-J34PSEJS.js.map +1 -0
- package/dist/{chunk-4HCQEGXO.js → chunk-335JCO5R.js} +184 -179
- package/dist/chunk-335JCO5R.js.map +1 -0
- package/dist/{chunk-FEQ4W4XA.js → chunk-55N4VTWX.js} +2 -2
- package/dist/{chunk-5FD7HE2J.js → chunk-576L7ZFD.js} +2 -2
- package/dist/{chunk-D3RJMC37.js → chunk-7XR5LGLD.js} +2 -2
- package/dist/{chunk-YFROK44Z.js → chunk-DMWFRKWR.js} +2 -2
- package/dist/{chunk-7334DGUO.js → chunk-FMUOVVXX.js} +2 -2
- package/dist/chunk-FWQVXZ5T.js +154 -0
- package/dist/chunk-FWQVXZ5T.js.map +1 -0
- package/dist/{chunk-KTGPH77J.js → chunk-J6RZOP7Z.js} +2 -2
- package/dist/{chunk-DXAWW7ZQ.js → chunk-MESWF2ZM.js} +2 -2
- package/dist/chunk-MYVHVJWZ.js +2 -0
- package/dist/chunk-MYVHVJWZ.js.map +1 -0
- package/dist/{chunk-2DWDXT7G.js → chunk-OSHG52OO.js} +65 -65
- package/dist/chunk-OSHG52OO.js.map +1 -0
- package/dist/{chunk-MTPCD4NV.js → chunk-OWRPCMGW.js} +236 -211
- package/dist/chunk-OWRPCMGW.js.map +1 -0
- package/dist/{chunk-RKZGENSE.js → chunk-PBRI3MTE.js} +2 -2
- package/dist/{chunk-KTNOY4LW.js → chunk-PC5LKW3L.js} +2 -2
- package/dist/{chunk-4J4YVJFH.js → chunk-PHSYP22H.js} +2 -2
- package/dist/{chunk-7PWXCN22.js → chunk-PY54XYAG.js} +2 -2
- package/dist/{chunk-LKA5UUGT.js → chunk-QKV7FN67.js} +2 -2
- package/dist/chunk-RAYOK4GI.js +15 -0
- package/dist/chunk-RAYOK4GI.js.map +1 -0
- package/dist/{chunk-RN7G3D53.js → chunk-TT4T6CB3.js} +2 -2
- package/dist/{chunk-3ZRFES25.js → chunk-UFPWMNUW.js} +2 -2
- package/dist/{chunk-MOUSATFW.js → chunk-VWMO4C72.js} +2 -2
- package/dist/{chunk-O2QVQVOV.js → chunk-YVLFX35J.js} +2 -2
- package/dist/{chunk-N4EIYNN4.js → chunk-Z5TXWHDN.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/client-L4JAPXTE.js +2 -0
- package/dist/config-X7BHZ75G.js +2 -0
- package/dist/config-mutator-R2KBGTZJ.js +2 -0
- package/dist/doctor-5VFQVAVC.js +2 -0
- package/dist/index.d.ts +151 -11
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/opencode-launch-ECMEY2QZ.js +2 -0
- package/dist/opencode-launch-ECMEY2QZ.js.map +1 -0
- package/dist/opencode-process-ENS4MXHM.js +2 -0
- package/dist/program-6C3G65YA.js +2 -0
- package/dist/{promote-USGFU5NN.js → promote-36XF4LH7.js} +2 -2
- package/dist/{query-NLSKOIWJ.js → query-YFZ6GWHU.js} +2 -2
- package/dist/registry-WJSGG62F.js +2 -0
- package/dist/{request-planner-VOWMXWRI.js → request-planner-OXRWVBXI.js} +2 -2
- package/dist/{review-candidates-F6RLNHS2.js → review-candidates-5XZWP2BN.js} +2 -2
- package/dist/{routing-2LAWEIUG.js → routing-XEPCPLVM.js} +2 -2
- package/dist/schedule-tool-WQCO2YUG.js +2 -0
- package/dist/scheduler-4NQ62XDK.js +2 -0
- package/dist/{seat-4LLK2XBM.js → seat-FGFHW363.js} +2 -2
- package/dist/{select-NJHTHKEQ.js → select-N6CIZF2S.js} +2 -2
- package/dist/{set-enabled-HPR6VJCG.js → set-enabled-L7Z6H7EG.js} +2 -2
- package/dist/{tool-XQMGKZP5.js → tool-OSH6GHIF.js} +2 -2
- package/dist/wiki-E46QDRS7.js +2 -0
- package/dist/wiki-E46QDRS7.js.map +1 -0
- package/package.json +1 -1
- package/dist/board-dashboard-MYWXVYU3.js.map +0 -1
- package/dist/chunk-2DWDXT7G.js.map +0 -1
- package/dist/chunk-4HCQEGXO.js.map +0 -1
- package/dist/chunk-E6CYC4HQ.js +0 -131
- package/dist/chunk-E6CYC4HQ.js.map +0 -1
- package/dist/chunk-MTPCD4NV.js.map +0 -1
- package/dist/chunk-XXBW7CFN.js +0 -15
- package/dist/chunk-XXBW7CFN.js.map +0 -1
- package/dist/client-IQIBHXVS.js +0 -2
- package/dist/config-7AK5TI2D.js +0 -2
- package/dist/config-mutator-EI5JNMY4.js +0 -2
- package/dist/doctor-CTWQODQG.js +0 -2
- package/dist/program-ZKGWGTPV.js +0 -2
- package/dist/registry-T7SCVP55.js +0 -2
- package/dist/schedule-tool-GOQFT2XQ.js +0 -2
- package/dist/scheduler-GJVRJQ7K.js +0 -2
- package/dist/wiki-RQ5P4WWJ.js +0 -2
- /package/dist/{App-LFQTOADB.js.map → App-244WEQJR.js.map} +0 -0
- /package/dist/{ChatApp-RNMG2HWX.js.map → ChatApp-SFP6SHUU.js.map} +0 -0
- /package/dist/{agent-7IW6472I.js.map → agent-PMNBXRFW.js.map} +0 -0
- /package/dist/{chunk-FEQ4W4XA.js.map → chunk-55N4VTWX.js.map} +0 -0
- /package/dist/{chunk-5FD7HE2J.js.map → chunk-576L7ZFD.js.map} +0 -0
- /package/dist/{chunk-D3RJMC37.js.map → chunk-7XR5LGLD.js.map} +0 -0
- /package/dist/{chunk-YFROK44Z.js.map → chunk-DMWFRKWR.js.map} +0 -0
- /package/dist/{chunk-7334DGUO.js.map → chunk-FMUOVVXX.js.map} +0 -0
- /package/dist/{chunk-KTGPH77J.js.map → chunk-J6RZOP7Z.js.map} +0 -0
- /package/dist/{chunk-DXAWW7ZQ.js.map → chunk-MESWF2ZM.js.map} +0 -0
- /package/dist/{chunk-RKZGENSE.js.map → chunk-PBRI3MTE.js.map} +0 -0
- /package/dist/{chunk-KTNOY4LW.js.map → chunk-PC5LKW3L.js.map} +0 -0
- /package/dist/{chunk-4J4YVJFH.js.map → chunk-PHSYP22H.js.map} +0 -0
- /package/dist/{chunk-7PWXCN22.js.map → chunk-PY54XYAG.js.map} +0 -0
- /package/dist/{chunk-LKA5UUGT.js.map → chunk-QKV7FN67.js.map} +0 -0
- /package/dist/{chunk-RN7G3D53.js.map → chunk-TT4T6CB3.js.map} +0 -0
- /package/dist/{chunk-3ZRFES25.js.map → chunk-UFPWMNUW.js.map} +0 -0
- /package/dist/{chunk-MOUSATFW.js.map → chunk-VWMO4C72.js.map} +0 -0
- /package/dist/{chunk-O2QVQVOV.js.map → chunk-YVLFX35J.js.map} +0 -0
- /package/dist/{chunk-N4EIYNN4.js.map → chunk-Z5TXWHDN.js.map} +0 -0
- /package/dist/{client-IQIBHXVS.js.map → client-L4JAPXTE.js.map} +0 -0
- /package/dist/{config-7AK5TI2D.js.map → config-X7BHZ75G.js.map} +0 -0
- /package/dist/{config-mutator-EI5JNMY4.js.map → config-mutator-R2KBGTZJ.js.map} +0 -0
- /package/dist/{doctor-CTWQODQG.js.map → doctor-5VFQVAVC.js.map} +0 -0
- /package/dist/{program-ZKGWGTPV.js.map → opencode-process-ENS4MXHM.js.map} +0 -0
- /package/dist/{promote-USGFU5NN.js.map → program-6C3G65YA.js.map} +0 -0
- /package/dist/{query-NLSKOIWJ.js.map → promote-36XF4LH7.js.map} +0 -0
- /package/dist/{registry-T7SCVP55.js.map → query-YFZ6GWHU.js.map} +0 -0
- /package/dist/{routing-2LAWEIUG.js.map → registry-WJSGG62F.js.map} +0 -0
- /package/dist/{request-planner-VOWMXWRI.js.map → request-planner-OXRWVBXI.js.map} +0 -0
- /package/dist/{review-candidates-F6RLNHS2.js.map → review-candidates-5XZWP2BN.js.map} +0 -0
- /package/dist/{schedule-tool-GOQFT2XQ.js.map → routing-XEPCPLVM.js.map} +0 -0
- /package/dist/{scheduler-GJVRJQ7K.js.map → schedule-tool-WQCO2YUG.js.map} +0 -0
- /package/dist/{seat-4LLK2XBM.js.map → scheduler-4NQ62XDK.js.map} +0 -0
- /package/dist/{wiki-RQ5P4WWJ.js.map → seat-FGFHW363.js.map} +0 -0
- /package/dist/{select-NJHTHKEQ.js.map → select-N6CIZF2S.js.map} +0 -0
- /package/dist/{set-enabled-HPR6VJCG.js.map → set-enabled-L7Z6H7EG.js.map} +0 -0
- /package/dist/{tool-XQMGKZP5.js.map → tool-OSH6GHIF.js.map} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{A as x,v as m,w as $}from"./chunk-RAYOK4GI.js";x();import{readFileSync as S,writeFileSync as P,existsSync as b}from"fs";import{resolve as f}from"path";function w(r){if(r)return f(r);let e=[f(process.cwd(),"agentx.json"),f(process.cwd(),".agentx/config.json")];for(let n of e)if(b(n))return n;return e[0]}function v(r){return JSON.parse(JSON.stringify(r))}async function O(r){try{let e=await fetch(`${r.replace(/\/$/,"")}/reload`,{method:"POST",signal:AbortSignal.timeout(3e3)});return e.ok?{ok:!0}:{ok:!1,reason:`HTTP ${e.status}`}}catch(e){return{ok:!1,reason:e?.cause?.code||e?.message||"unreachable"}}}async function J(r,e={}){let{validate:n=!0,dryRun:t=!1,reload:s=!0,configPath:u,daemonUrl:c}=e,o=w(u);if(!b(o))return{success:!1,path:o,error:`Config not found at ${o}. Run \`agentx init\` first.`};let d;try{d=S(o,"utf-8")}catch(a){return{success:!1,path:o,error:`Cannot read ${o}: ${a.message}`}}let g;try{g=JSON.parse(d)}catch(a){return{success:!1,path:o,error:`Invalid JSON in ${o}: ${a.message}`}}let i=v(g);try{await r(i)}catch(a){return{success:!1,path:o,error:`Mutator threw: ${a.message}`}}if(n){let a=$(i),l=m.safeParse(a);if(!l.success){let k=l.error.issues.map(y=>` ${y.path.join(".")||"<root>"}: ${y.message}`).join(`
|
|
2
2
|
`);return{success:!1,path:o,error:`Validation failed:
|
|
3
3
|
${k}`,after:i}}}if(t)return{success:!0,path:o,after:i,dryRun:!0};try{P(o,JSON.stringify(i,null,2)+`
|
|
4
4
|
`)}catch(a){return{success:!1,path:o,error:`Write failed: ${a.message}`,after:i}}let p=!1,h;if(s){let a=c||R(i),l=await O(a);l.ok?p=!0:h=l.reason}return{success:!0,path:o,after:i,reloaded:p,reloadSkipped:h}}function R(r){let e=r?.node?.bind;if(!e)return"http://127.0.0.1:18800";let[n,t]=e.split(":");return`http://${n==="0.0.0.0"||n==="::"?"127.0.0.1":n}:${t}`}function N(r,e,n){let t=e.split("."),s=r;for(let u=0;u<t.length-1;u++){let c=t[u];(s[c]===void 0||s[c]===null)&&(s[c]={}),s=s[c]}s[t[t.length-1]]=n}function j(r,e){let n=e.split("."),t=r;for(let s of n){if(t==null)return;t=t[s]}return t}function A(r,e){let n=e.split("."),t=r;for(let s=0;s<n.length-1;s++){if(t==null)return;t=t[n[s]]}t!=null&&delete t[n[n.length-1]]}export{w as a,J as b,N as c,j as d,A as e};
|
|
5
|
-
//# sourceMappingURL=chunk-
|
|
5
|
+
//# sourceMappingURL=chunk-55N4VTWX.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{q as p}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
import{q as p}from"./chunk-DMWFRKWR.js";import{b as i,c as u,d as l,e as c}from"./chunk-55N4VTWX.js";import d from"cronstrue";var f=Intl.DateTimeFormat().resolvedOptions().timeZone,m=600,E='Try: "every morning at 9", "weekdays at 6pm", "every 15 minutes", "every monday at 10am", "1st of every month at noon", "daily at 9:30am", "every hour"',g=/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;function w(e){return g.test(e)}function x(e){try{return new Intl.DateTimeFormat("en-US",{timeZone:e}),!0}catch{return!1}}function $(e){return e?e.split(",").map(r=>r.trim().toLowerCase()).filter(r=>r==="log"||r==="notify"||r==="disable"):["log"]}function S(e){let r=[...e.onError??["log"]];e.notify&&!r.includes("notify")&&r.push("notify");let t={enabled:e.enabled??!0,schedule:e.parsed.cron,timezone:e.timezone||f,agent:e.agent,prompt:e.prompt,timeout:e.timeout??m,onError:r};return e.model&&(t.model=e.model),e.notify&&(t.notify=e.notify),e.createdBy&&(t.createdBy=e.createdBy),e.approval&&(t.approval=e.approval),t}function P(e){try{return d.toString(e,{use24HourTimeFormat:!1})}catch{return e}}function T(e,r,t=new Date){try{return p(e,t,r)}catch{return null}}function A(e,r){if(!e)return"unknown (no match within a year)";try{return`${new Intl.DateTimeFormat("en-GB",{timeZone:r,weekday:"short",day:"2-digit",month:"short",year:"numeric",hour:"2-digit",minute:"2-digit",hour12:!1}).format(e)} (${r})`}catch{return e.toISOString()}}function h(e){return e?.approval?.action==="create"}async function D(e,r={}){let t="",o=await i(n=>{let a=l(n,`crons.${e}`);if(!a)throw new Error(`cron "${e}" not found`);let s=a.approval;if(!s)throw new Error(`cron "${e}" has no pending request`);s.action==="create"?(delete a.approval,a.enabled=!0,t=`${e} approved and enabled (requested by ${s.requestedBy})`):(c(n,`crons.${e}`),t=`${e} deletion approved; job removed (requested by ${s.requestedBy})`)},{configPath:r.configPath,reload:r.reload});return o.success?{success:!0,message:t,result:o}:{success:!1,message:o.error||"failed",result:o}}async function I(e,r={}){let t="",o=await i(n=>{let a=l(n,`crons.${e}`);if(!a)throw new Error(`cron "${e}" not found`);let s=a.approval;if(!s)throw new Error(`cron "${e}" has no pending request`);s.action==="create"?(c(n,`crons.${e}`),t=`${e} rejected; pending job removed`):(delete a.approval,t=`${e} deletion rejected; job kept`)},{configPath:r.configPath,reload:r.reload});return o.success?{success:!0,message:t,result:o}:{success:!1,message:o.error||"failed",result:o}}async function O(e,r,t={}){return i(o=>{let n=l(o,`crons.${e}`);if(!n)throw new Error(`cron "${e}" not found`);if(r&&h(n))throw new Error(`cron "${e}" is awaiting approval; run \`agentx schedule approve ${e}\``);u(o,`crons.${e}.enabled`,r)},{configPath:t.configPath,reload:t.reload})}export{f as a,E as b,w as c,x as d,$ as e,S as f,P as g,T as h,A as i,h as j,D as k,I as l,O as m};
|
|
2
|
+
//# sourceMappingURL=chunk-576L7ZFD.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{A as b,x as m}from"./chunk-RAYOK4GI.js";b();function w(t){let e=typeof t.node=="string"?t.node:"",n=typeof t.token=="string"?t.token:"";if(!e||!n)try{let o=m(t.config);e||(e=o.dashboard?.daemonUrl||""),n||(n=o.dashboard?.token||"")}catch{}return e||(e="http://localhost:18800"),{baseUrl:e.replace(/\/+$/,""),token:n}}async function d(t,e,n){let o={Accept:"application/json"};t.token&&(o.Authorization=`Bearer ${t.token}`);let r=await fetch(`${t.baseUrl}${e}`,{headers:o,signal:n});if(!r.ok)throw new Error(`GET ${e} \u2192 HTTP ${r.status}`);return await r.json()}function R(t,e){return d(t,"/agents",e)}async function S(t,e){return(await d(t,"/api/processes",e)).processes??[]}function P(t,e){return d(t,"/crons",e)}async function h(t,e,n,o){let r={Accept:"application/json","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}${e}`,{method:"POST",headers:r,body:JSON.stringify(n),signal:o}),a=await s.text(),i;try{i=a?JSON.parse(a):{}}catch{i={raw:a}}if(!s.ok)throw new Error(i?.error||`POST ${e} \u2192 HTTP ${s.status}`);return i}function A(t,e,n="tui"){return h(t,"/api/processes/kill",{...e,reason:n})}function C(t,e,n,o){return h(t,"/task",{agent:e,message:n,context:o??{channel:"tui",chatId:"tui:operator"}})}async function $(t,e,n,o={}){let r={Accept:"text/event-stream","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}/task`,{method:"POST",headers:r,body:JSON.stringify({agent:e,message:n,stream:!0,context:{channel:o.channel??"chat-cli",chatId:o.chatId??"chat-cli:operator"}}),signal:o.signal});if(!s.ok||!s.body){let g=await s.text().catch(()=>"");throw new Error(`POST /task (stream) \u2192 HTTP ${s.status}${g?`: ${g.slice(0,200)}`:""}`)}let a=s.body.getReader(),i=new TextDecoder,u={content:""},c="";try{for(;;){let{done:g,value:p}=await a.read();if(g)break;c+=i.decode(p,{stream:!0});let l;for(;(l=c.indexOf(`
|
|
2
2
|
|
|
3
3
|
`))>=0;){let k=c.slice(0,l);c=c.slice(l+2);let f=x(k);f&&T(f,o,u)}}}finally{try{a.releaseLock()}catch{}}return u}function T(t,e,n){let{event:o,data:r}=t;switch(o){case"text":r?.text&&(n.content+=r.text,e.onText?.(r.text));break;case"thinking":r?.text&&e.onThinking?.(r.text);break;case"tool":e.onTool?.(r);break;case"done":typeof r?.content=="string"&&(n.content=r.content),n.usage=r?.usage,n.duration=r?.duration;break;case"error":n.error=r?.error,n.errorKind=r?.errorKind;break}}function x(t){let e="message",n="";for(let r of t.split(`
|
|
4
4
|
`))r.startsWith("event: ")?e=r.slice(7).trim():r.startsWith("data: ")&&(n=r.slice(6));if(!n)return null;let o;try{o=JSON.parse(n)}catch{o=n}return{event:e,data:o}}export{w as a,R as b,S as c,P as d,A as e,C as f,$ as g};
|
|
5
|
-
//# sourceMappingURL=chunk-
|
|
5
|
+
//# sourceMappingURL=chunk-7XR5LGLD.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as S,c as O}from"./chunk-
|
|
1
|
+
import{b as S,c as O}from"./chunk-55N4VTWX.js";import{a as I,b as X}from"./chunk-FCPTN6NF.js";import{a as F,b as oe}from"./chunk-7I7IEX4S.js";import{d as M}from"./chunk-QIJLFPWE.js";import{execFile as Le}from"child_process";import{writeFileSync as ee,mkdirSync as w,existsSync as b,readFileSync as $e}from"fs";import{resolve as _}from"path";var ce=["off","shadow","authoritative"],ae={telegram:"INTENT_LEDGER_MODE_TELEGRAM",slack:"INTENT_LEDGER_MODE_SLACK",whatsapp:"INTENT_LEDGER_MODE_WHATSAPP",discord:"INTENT_LEDGER_MODE_DISCORD",gitlab:"INTENT_LEDGER_MODE_GITLAB",github:"INTENT_LEDGER_MODE_GITHUB",workflow:"INTENT_LEDGER_MODE_WORKFLOW",cron:"INTENT_LEDGER_MODE_CRON",mesh:"INTENT_LEDGER_MODE_MESH"},de="INTENT_LEDGER_MODE";function B(n,e=process.env){let t=P(e[ae[n]]);if(t)return t;let i=P(e[de]);return i||"off"}function P(n){if(typeof n!="string")return null;let e=n.trim().toLowerCase();return ce.includes(e)?e:null}X();import ue from"better-sqlite3";import{existsSync as Pe,mkdirSync as le}from"fs";import{dirname as ge,resolve as me}from"path";var T=class{db;path;constructor(e={}){this.path=me(process.cwd(),e.path??".agentx/intent/ledger.sqlite"),le(ge(this.path),{recursive:!0}),this.db=new ue(this.path),this.db.pragma("journal_mode = WAL"),this.db.pragma("synchronous = NORMAL"),this.db.pragma("foreign_keys = ON"),fe(this.db)}close(){this.db.close()}schemaVersion(){return this.db.prepare("SELECT MAX(v) AS v FROM schema_version").get().v??0}recordEvent(e){if(e.sourceEventId!==null){let i=this.findEventBySourceId(e.source,e.sourceEventId);if(i)return i}let t={id:e.id??I(e.ts),ts:e.ts,source:e.source,sourceEventId:e.sourceEventId,project:e.project,subject:e.subject,intent:e.intent,rawJson:e.rawJson};return this.db.prepare(`INSERT INTO intent_events (id, ts, source, source_event_id, project, subject, intent, raw_json)
|
|
2
2
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`).run(t.id,t.ts,t.source,t.sourceEventId,t.project,t.subject,t.intent,t.rawJson),t}findEventBySourceId(e,t){let i=this.db.prepare(`SELECT id, ts, source, source_event_id, project, subject, intent, raw_json
|
|
3
3
|
FROM intent_events WHERE source = ? AND source_event_id = ?`).get(e,t);return i?U(i):null}getEventById(e){let t=this.db.prepare(`SELECT id, ts, source, source_event_id, project, subject, intent, raw_json
|
|
4
4
|
FROM intent_events WHERE id = ?`).get(e);return t?U(t):null}recordDecision(e){this.db.prepare(`INSERT INTO intent_decisions (event_id, decided_at, decided_by, agent_id, outcome, reason)
|
|
@@ -123,4 +123,4 @@ ${r.prompt}`,r.maxOutputTokens),agentId:r.agent,autonomy:r.autonomy,timeoutMinut
|
|
|
123
123
|
`);return t.length<=e?t.join(`
|
|
124
124
|
`):t.slice(-e).join(`
|
|
125
125
|
`)}function Ce(n,e,t){return new Promise((i,r)=>{Le("/bin/sh",["-c",n],{timeout:e,maxBuffer:8*1024*1024,...t?{env:t}:{}},(s,c,o)=>{if(s&&s.killed){r(new Error(`command timed out after ${Math.round(e/1e3)}s`));return}i({stdout:String(c??""),stderr:String(o??""),code:s?typeof s.code=="number"?s.code:1:0})})})}export{T as a,G as b,it as c,De as d,rt as e,st as f,$ as g,Q as h,B as i,je as j,V as k,K as l,at as m,Ae as n,ne as o,ie as p,re as q,we as r,C as s};
|
|
126
|
-
//# sourceMappingURL=chunk-
|
|
126
|
+
//# sourceMappingURL=chunk-DMWFRKWR.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{a as D,b as _}from"./chunk-RKPAVWXF.js";import{a as q,b as O,c as R,d as B,f as b,g as S,h as E,i as w,j as y}from"./chunk-
|
|
1
|
+
import{a as D,b as _}from"./chunk-RKPAVWXF.js";import{a as q,b as O,c as R,d as B,f as b,g as S,h as E,i as w,j as y}from"./chunk-576L7ZFD.js";import{a as T,b as C,c as I,d as x,e as P}from"./chunk-55N4VTWX.js";import{existsSync as X,readFileSync as F}from"fs";var J=new Set(["cron","heartbeat","api","a2a","mesh"]),M=160;function s(n){return typeof n=="string"&&n.trim()?n.trim():void 0}function A(n,e=M){let t=n.replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e-1)}\u2026`:t}function V(n){let e=T(n);if(!X(e))throw new Error(`config not found at ${e}`);return JSON.parse(F(e,"utf-8"))}function W(n,e){return n?.agents?.[e]?.admin===!0}function Y(n,e,t){return W(n,t.agentId)||e?.createdBy===t.agentId}function Z(n,e){let t=e?.createdBy?`agent "${e.createdBy}"`:"the operator";return`Not allowed: "${n}" was created by ${t}. Agents manage only schedules they created (unless configured admin).`}function K(n,e){let t=s(n.notify);if(t!=="none"){if(t&&t!=="here"){let r=t.split(":");return r.length<2||!r[0]||!r[1]?"invalid":{channel:r[0],chatId:r.slice(1).join(":")}}if(e.channel&&e.chatId&&!J.has(e.channel))return{channel:e.channel,chatId:e.chatId,...e.accountId?{accountId:e.accountId}:{}}}}function Q(n,e,t){let r=e.timezone||"UTC",u=e.enabled&&!y(e)?w(E(e.schedule,r,t),r):"\u2014",h=e.approval?`pending ${e.approval.action} approval`:e.enabled?"active":"paused",p=[`- ${n} [${h}] ${e.schedule} \u2014 ${S(e.schedule)} (${r})`,` agent: ${e.agent}; created by: ${e.createdBy||"operator"}; next: ${u}`];return e.notify&&p.push(` notify: ${e.notify.channel} ${e.notify.chatId}`),e.command?p.push(` command: ${A(String(e.command))}`):e.prompt&&p.push(` prompt: ${A(String(e.prompt))}`),p.join(`
|
|
2
2
|
`)}async function k(n,e,t){let r=n?.notifications?.destination;if(!r?.channel||!r?.chatId)return"No operator notification destination is configured (notifications.destination); the operator must check `agentx schedule list`.";if(!e.notifyOperator)return"Operator notification is unavailable in this context.";try{return await e.notifyOperator({channel:r.channel,chatId:r.chatId,accountId:r.accountId},t),"The operator has been notified."}catch(u){return`Could not notify the operator (${u?.message??u}); the request is still recorded.`}}async function re(n,e,t={}){let r=(s(n.action)||"list").toLowerCase(),u=t.now?t.now():new Date,h;try{h=V(t.configPath)}catch(a){return`Error: ${a.message}`}let p=h.crons||{};if(r==="list"){let a=n.mine===!0,l=Object.entries(p).filter(([,i])=>!a||e&&i?.createdBy===e.agentId);return l.length?l.map(([i,f])=>Q(i,f,u)).join(`
|
|
3
3
|
`):a?"You have no schedules.":"No schedules."}if(!e?.agentId)return"Error: caller agent is unknown (AGENTX_AGENT_ID not set). Pass callerAgentId.";if(!h.agents?.[e.agentId])return`Error: caller "${e.agentId}" is not an agent on this node.`;let o=s(n.id),m=a=>C(a,{configPath:t.configPath,reload:t.reload});if(r==="create"){let a=s(n.when),l=s(n.prompt);if(!a||!l)return"Error: create needs `when` (plain English) and `prompt`.";let i=D(a);if(!i)return`Error: couldn't parse "${a}". ${O}.`;let f=s(n.agent)||e.agentId;if(!h.agents?.[f])return`Error: agent "${f}" not found on this node.`;let g=s(n.timezone)||q;if(!B(g))return`Error: unknown timezone "${g}".`;let d=o||_(i.matched,f);if(!R(d))return`Error: invalid id "${d}" (letters, digits, "-" and "_" only).`;if(p[d])return`Error: a schedule "${d}" already exists. Pick another \`id\`.`;let $=K(n,e);if($==="invalid")return'Error: `notify` must be "here", "none", or "channel:chatId".';let z={action:"create",requestedBy:e.agentId,requestedAt:u.toISOString()},L=b({parsed:i,agent:f,prompt:l,timezone:g,notify:$,enabled:!1,createdBy:e.agentId,approval:z}),v=await m(U=>I(U,`crons.${d}`,L));if(!v.success)return`Error: ${v.error}`;let N=w(E(i.cron,g,u),g),G=[`Schedule approval requested by ${e.agentId}`,`Create: ${d}`,`When: ${i.human} \u2014 cron \`${i.cron}\` (${g})`,`Next fire: ${N}`,`Agent: ${f}`,$?`Notify: ${$.channel} ${$.chatId}`:"Notify: none",`Prompt: ${A(l,400)}`,"",`Approve: agentx schedule approve ${d}`,`Reject: agentx schedule reject ${d}`].join(`
|
|
4
4
|
`),H=await k(h,t,G);return[`Requested schedule "${d}": ${i.human} (cron ${i.cron}, ${g}); next fire would be ${N}.`,"It is saved DISABLED and will not run until the operator approves it.",H].join(`
|
|
5
5
|
`)}if(!o)return`Error: ${r} needs \`id\`.`;let c=p[o];if(!c)return`Error: schedule "${o}" not found.`;if(!Y(h,c,e))return Z(o,c);if(r==="pause"||r==="resume"){let a=r==="resume";if(a&&y(c))return`"${o}" is still awaiting operator approval; it can't be resumed until approved.`;if(c.enabled===a)return`"${o}" is already ${a?"active":"paused"}.`;let l=await m(i=>I(i,`crons.${o}.enabled`,a));return l.success?`"${o}" ${a?"resumed":"paused"}.`:`Error: ${l.error}`}if(r==="delete"){if(y(c)&&c.approval.requestedBy===e.agentId){let d=await m($=>P($,`crons.${o}`));return d.success?`Withdrew the pending request "${o}".`:`Error: ${d.error}`}if(y(c))return`"${o}" is a creation request still awaiting approval; only its requester or the operator (\`agentx schedule reject ${o}\`) can drop it.`;if(c.approval?.action==="delete")return`Deletion of "${o}" is already awaiting approval.`;let a={action:"delete",requestedBy:e.agentId,requestedAt:u.toISOString()},l=await m(d=>{if(!x(d,`crons.${o}`))throw new Error(`schedule "${o}" not found`);I(d,`crons.${o}.approval`,a)});if(!l.success)return`Error: ${l.error}`;let i=c.timezone||"UTC",f=[`Schedule approval requested by ${e.agentId}`,`Delete: ${o}`,`When: ${S(c.schedule)} \u2014 cron \`${c.schedule}\` (${i})`,`Next fire: ${c.enabled?w(E(c.schedule,i,u),i):"\u2014 (paused)"}`,`Agent: ${c.agent}`,"",`Approve: agentx schedule approve ${o}`,`Reject: agentx schedule reject ${o}`].join(`
|
|
6
6
|
`),g=await k(h,t,f);return[`Deletion of "${o}" requested. It keeps its current state until the operator approves.`,g].join(`
|
|
7
7
|
`)}return`Error: unknown action "${r}". Use list, create, pause, resume or delete.`}function oe(n,e=process.env){let t=s(e.AGENTX_AGENT_ID)||s(n.callerAgentId);if(!t)return null;let r=!!(s(e.AGENTX_CHANNEL)&&s(e.AGENTX_CHAT_ID)),u=s(r?e.AGENTX_CHANNEL:n.channel),h=s(r?e.AGENTX_CHAT_ID:n.chatId),p=s(n.accountId);return{agentId:t,channel:u,chatId:h,...p?{accountId:p}:{}}}export{re as a,oe as b};
|
|
8
|
-
//# sourceMappingURL=chunk-
|
|
8
|
+
//# sourceMappingURL=chunk-FMUOVVXX.js.map
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import{t as pt,u as mt}from"./chunk-VWMO4C72.js";import{d as gt,e as ft}from"./chunk-AQASR6KR.js";import{b as fe,t as ot,v as J,w as pe,y as me}from"./chunk-PBRI3MTE.js";import{g as at,h as lt,i as ct,k as ut,l as dt}from"./chunk-576L7ZFD.js";import{q as it}from"./chunk-DMWFRKWR.js";import{A as Hn,x as st}from"./chunk-RAYOK4GI.js";import{existsSync as zn,readdirSync as Kn,readFileSync as Gn,statSync as Xn}from"fs";import{resolve as qn}from"path";function ht(t,e,n=Date.now(),s=7){let r=s*864e5,i=new Map;for(let o of e){let a=i.get(o.workflowId);a?a.push(o):i.set(o.workflowId,[o])}return t.map(o=>{let a=i.get(o.id)??[],l=a.filter(p=>n-p.at<=r),c=a.filter(p=>n-p.at>r&&n-p.at<=r*2),u=l.filter(p=>p.status==="failed").length,d=a.filter(p=>p.status==="paused").length,g=a.length?Math.max(...a.map(p=>p.at)):null,f=a.length?c.length>0&&l.length===0?"dormant":l.length>0&&u*2>=l.length?"failing":l.length>0?"active":"quiet":"never";return{id:o.id,name:o.name||o.id,state:f,lastRunAt:g,recent:l.length,prior:c.length,failed:u,paused:d}}).sort((o,a)=>{let l={dormant:0,failing:1,active:2,quiet:3,never:4};return l[o.state]-l[a.state]||(a.lastRunAt??0)-(o.lastRunAt??0)})}var Y=new Map;function Ji(t,e=1e3){if(!zn(t))return[];let n=Kn(t).filter(i=>i.endsWith(".jsonl")).map(i=>{let o=qn(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 Y.keys())s.has(i)||Y.delete(i);let r=[];for(let{path:i,mtime:o}of n){let a=Y.get(i);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=Jn(i,o);Y.set(i,{mtime:o,summary:l}),l&&r.push(l)}return r}function Jn(t,e){try{let n=Gn(t,"utf-8").split(`
|
|
2
|
+
`).filter(Boolean);if(!n.length)return null;let s=JSON.parse(n[0]),r=s.run?.workflowId;if(!r)return null;let i=s.run?.status??"unknown";for(let o=n.length-1;o>=0;o--){let a=JSON.parse(n[o]),l=a.status??a.run?.status;if(l){i=l;break}}return{workflowId:r,status:i,at:e}}catch{return null}}var Yn={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},w={routines:200,summary:160,filters:6,filterValue:60,text:120},Zn=(t,e,n)=>{try{return it(t,e,n)}catch{return null}},yt=864e5;function eo(t){let e=t.now??Date.now(),n={...Yn,...t.thresholds},s=t.nextFire??Zn,r=[];for(let a of t.crons){let l=t.cronRuns.get(a.id)??[],c=a.timezone||"UTC",u=l.map(f=>({at:Date.parse(f.startedAt),status:f.status})),d=l[0],g={id:`cron:${a.id}`,source:"cron",kind:"schedule",name:$(a.id,w.text),trigger:{schedule:$(a.schedule,w.text),timezone:c},agent:a.agent||null,enabled:a.enabled,state:a.enabled?"enabled":"disabled",nextRunAt:a.enabled?he(a.nextRun)??he(s(a.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:sr(d.status==="success"?void 0:d.errorSummary,w.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:bt(u),sampledRuns:l.length,flags:[],attention:null};g.flags=kt(g,u,a.schedule,c,null,e,n,s),r.push(wt(g))}let i=new Map(ht(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let l=o.get(a.workflowId);l?l.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let l=a.nodes.find(_=>_.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=a.state||"active",d=u==="active",g=(o.get(a.id)??[]).slice().sort((_,ge)=>ge.at-_.at),f=g.map(_=>({at:_.at,status:tr(_.status)})),p=f[0],h=l.type==="trigger.cron",y=typeof c.spec=="string"?c.spec:"",C=typeof c.timezone=="string"?c.timezone:"UTC",O={id:`workflow:${a.id}`,source:"workflow",kind:h?"schedule":"event",name:$(a.title||a.id,w.text),trigger:h?{schedule:$(y,w.text),timezone:C}:{event:$(typeof c.event=="string"?c.event:"",w.text),filters:rr(c.filter,a)},agent:nr(a),enabled:d,state:u,nextRunAt:h&&d&&y?he(s(y,new Date(e),C)):null,lastRun:p?{at:new Date(p.at).toISOString(),status:p.status}:null,lastSuccessAt:(()=>{let _=f.find(ge=>ge.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:bt(f),sampledRuns:g.length,flags:[],attention:null},q=Date.parse(a.updated||a.created||"");O.flags=h?kt(O,f,y,C,Number.isFinite(q)?q:null,e,n,s):Qn(O,i.get(a.id)?.state==="dormant",Number.isFinite(q)?q:null,e,n),r.push(wt(O))}return r.sort(er).slice(0,w.routines)}function bt(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 kt(t,e,n,s,r,i,o,a){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let g=xt(c,r,i,o);return g&&l.push(g),l}if(t.consecutiveFailures>=o.failStreak&&l.push({reason:"failing",detail:`${t.consecutiveFailures} failed attempts in a row`}),c===null)return l.push({reason:"never-ran",detail:"No persisted attempt"}),l;let u=new Date(c),d=null;for(let g=0;g<o.missedFires&&(d=a(n,u,s),!!d);g++)u=d;return d&&i>d.getTime()+o.graceMs&&l.push({reason:"overdue",detail:`No attempt since ${new Date(c).toISOString()}; ${o.missedFires} scheduled fires missed`}),l}function Qn(t,e,n,s,r){let i=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=xt(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 xt(t,e,n,s){let r=Math.max(t??0,e??0);return r&&n-r<s.disabledDays*yt?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/yt)} days`:"Disabled and never ran"}}function wt(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 St={critical:0,warning:1,info:2};function er(t,e){let n=t.attention?St[t.attention]:3,s=e.attention?St[e.attention]:3;return n-s||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function tr(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 nr(t){if(t.ownerAgent)return $(t.ownerAgent,w.text);let e=t.nodes.find(n=>n.type==="agent"&&typeof n.config?.agentId=="string"&&n.config.agentId);return e?$(String(e.config.agentId),w.text):null}function rr(t,e){let n=[],s=e?.project;if(s&&n.push($(`project=${s}`,w.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(",")}`,w.filterValue))}return n.slice(0,w.filters)}function he(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 sr(t,e){return t===void 0?void 0:$(t,e)}import{createHash as ir,randomBytes as vt}from"crypto";import{existsSync as or,mkdirSync as ar,readFileSync as lr,writeFileSync as cr}from"fs";import{resolve as ur,dirname as dr}from"path";var ye="agx_live_",gr=".agentx/tokens.json",$t=class{file;constructor(e=process.cwd(),n=gr){this.file=ur(e,n)}load(){if(!or(this.file))return[];try{return JSON.parse(lr(this.file,"utf-8"))}catch{return[]}}save(e){ar(dr(this.file),{recursive:!0}),cr(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(!fr(o))throw new Error(`Invalid scope: ${o}`);let n=vt(32).toString("hex"),s=ye+n,r={id:"tok_"+vt(4).toString("hex"),name:e.name.trim(),prefix:ye+n.slice(0,4),hash:It(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(ye))return null;let n=It(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 io(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function fr(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 It(t){return"sha256:"+ir("sha256").update(t).digest("hex")}function oo(t){let e=t.headers.authorization,n=Array.isArray(e)?e[0]:e;if(n&&n.toLowerCase().startsWith("bearer "))return n.slice(7).trim();if(t.url)try{let r=new URL(t.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}import{existsSync as be,readdirSync as Tr,readFileSync as Er}from"fs";import{resolve as j}from"path";import{existsSync as pr,mkdirSync as mr,readdirSync as hr,readFileSync as yr,renameSync as br,writeFileSync as kr}from"fs";import{resolve as _t}from"path";var At=["discard","keep","pause","approve"],I={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},wr={defaultExpiryDays:3,maxExpiryDays:30};function P(t){return _t(t,".agentx","approvals")}var Sr=/^[a-z0-9][a-z0-9-]{0,80}$/;function Rt(t){return Sr.test(t)}function Ct(t,e){if(!Rt(e))throw new Error(`invalid card id: ${e}`);return _t(P(t),`${e}.json`)}function xr(t,e){let n=new Date(t).toISOString().slice(0,10),s=e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"").slice(0,40);return`${n}-${s||"card"}-${Math.random().toString(36).slice(2,6)}`}function Z(t,e){mr(P(t),{recursive:!0});let n=Ct(t,e.id),s=`${n}.${process.pid}.tmp`;kr(s,JSON.stringify(e,null,2)+`
|
|
4
|
+
`),br(s,n)}function U(t,e){if(!Rt(e))return null;try{return JSON.parse(yr(Ct(t,e),"utf-8"))}catch{return null}}function W(t,e){let n=P(t);if(!pr(n))return[];let s=[];for(let r of hr(n).filter(i=>i.endsWith(".json")&&!i.startsWith("_")).sort()){let i=U(t,r.slice(0,-5));i&&(!e||i.status===e)&&s.push(i)}return s}function k(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function vr(t,e,n){let s=e+n.maxExpiryDays*864e5,r,i=k(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 $r(t,e={}){let n=e.now??Date.now(),s=e.settings??wr,r=k(t.title),i=k(t.ask),o=k(t.recommend),a=k(t.raised_by);if(!r)return{ok:!1,error:"title is required"};if(!i)return{ok:!1,error:"ask is required: the yes/no question"};if(!o)return{ok:!1,error:"recommend is required: your advice and why, in one line"};if(!a)return{ok:!1,error:"raised_by is required: the agent id"};if(r.length>I.title)return{ok:!1,error:`title is longer than ${I.title} characters`};if(i.length>I.ask)return{ok:!1,error:`ask is longer than ${I.ask} characters`};if(o.length>I.recommend)return{ok:!1,error:`recommend is longer than ${I.recommend} characters`};let l=k(t.if_silent).toLowerCase();if(!At.includes(l))return{ok:!1,error:`if_silent must be one of ${At.join(", ")}`};let c=vr(t.expires,n,s);if(!c.ok)return c;let u=k(t.source);if(u.length>I.source)return{ok:!1,error:`source is longer than ${I.source} characters`};if(u&&/^[a-z][a-z0-9+.-]*:/i.test(u)&&!/^https?:\/\//i.test(u))return{ok:!1,error:"source must be an http(s) link or a plain reference"};let d,g=t.reply;return g&&typeof g=="object"&&k(g.channel)&&k(g.chatId)&&(d={channel:k(g.channel),chatId:k(g.chatId),...k(g.accountId)?{accountId:k(g.accountId)}:{}}),{ok:!0,card:{id:xr(n,r),title:r,ask:i,recommend:o,if_silent:l,expires:c.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...d?{reply:d}:{},status:"pending"}}}function uo(t,e,n={}){let s=$r(e,n);if(!s.ok)return s;let r=W(t,"pending").filter(i=>i.raised_by===s.card.raised_by).length;return r>=I.pendingPerAgent?{ok:!1,error:`${s.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(Z(t,s.card),s)}function Tt(t,e,n,s={}){let r=U(t,e);if(!r)return{ok:!1,error:`no card "${e}"`};if(r.status!=="pending")return{ok:!1,error:`card "${e}" is already ${r.status}`};let i=k(s.note).slice(0,I.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 Z(t,o),{ok:!0,card:o}}function go(t,e=Date.now()){let n=[];for(let s of W(t,"pending")){if(Date.parse(s.expires)>e)continue;let r={...s,status:"expired",outcome:s.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};Z(t,r),n.push(r)}return n}function fo(t){return W(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function po(t,e,n=Date.now()){let s=U(t,e);!s||s.agent_notified_at||Z(t,{...s,agent_notified_at:new Date(n).toISOString()})}function mo(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 Ir,readFileSync as Ar,renameSync as _r,writeFileSync as Rr}from"fs";import{resolve as Cr}from"path";function Et(t){return Cr(P(t),"_state.json")}function Q(t){try{let e=JSON.parse(Ar(Et(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 Dt(t,e){Ir(P(t),{recursive:!0});let n=Et(t),s=`${n}.${process.pid}.tmp`;Rr(s,JSON.stringify(e,null,2)+`
|
|
6
|
+
`),_r(s,n)}function Lt(t,e,n,s=Date.now()){let r=Q(t),i={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>s&&(i[o]=a);i[e]=n.toISOString(),Dt(t,{...r,snoozed:i})}function wo(t,e){Dt(t,{...Q(t),lastDigest:e})}var Ot=["card","schedule","memory","wiki"],Dr=280;function ke(t,e=Dr){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Pt(t){if(t.configPath)return j(t.configPath);let e=[j(t.root,"agentx.json"),j(t.root,".agentx","config.json")];return e.find(n=>be(n))??e[0]}function we(t){return t.wikiDir?j(t.wikiDir):j(t.root,".agentx","wiki")}function Lr(t){return W(t.root,"pending").map(Or)}function Or(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 Pr(t){let e=Pt(t);if(!be(e))return[];let n;try{n=JSON.parse(Er(e,"utf-8"))}catch{return[]}let s=new Date(t.now??Date.now()),r=[];for(let[i,o]of Object.entries(n?.crons??{})){let a=o?.approval;if(!a||a.action!=="create"&&a.action!=="delete")continue;let l=o.timezone||"UTC",c=o.schedule?at(o.schedule):"",u=o.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),g=a.action==="create";r.push({key:`schedule:${i}`,kind:"schedule",title:g?`New schedule "${i}" for ${o.agent??"an agent"}`:`Delete schedule "${i}"`,ask:g?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${i}" (${u})?`,yes:g?"enable it":"remove it",no:g?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:ke(`${d}${g&&o.schedule?` \xB7 first run ${ct(lt(o.schedule,l,s),l)}`:""}`),more:"agentx schedule list"})}return r}function jt(t){let e=j(t,".agentx","memory");return be(e)?Tr(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function jr(t){let e=jt(t.root);if(e.length===0)return[];let n=new fe(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:ke(i.content),more:`agentx memory facts held --agent ${r}`});return s}function Vr(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 Mr(t){return ft(we(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:ke(`${Vr(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}var Vt={card:Lr,schedule:Pr,memory:jr,wiki:Mr};function Nr(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 To(t,e={}){let n=t.now??Date.now(),{snoozed:s}=Q(t.root),r=[],i=[],o=0;for(let a of e.kinds??Ot){let l;try{l=Vt[a](t)}catch(c){i.push({kind:a,error:String(c?.message??c).slice(0,200)});continue}for(let c of l){let u=s[c.key];if(u&&Date.parse(u)>n){if(!e.includeSnoozed){o++;continue}c.snoozed_until=u}r.push(c)}}return r.sort(Nr),{items:r,snoozed:o,errors:i}}function Fr(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),s=t.slice(e+1);return!Ot.includes(n)||!s?null:{kind:n,ref:s}}function Ur(t,e,n){switch(e){case"card":return U(t.root,n)?.status==="pending";case"wiki":return gt(we(t),n)?.status==="pending";default:return Vt[e](t).some(s=>s.key===`${e}:${n}`)}}async function Eo(t,e,n,s={}){let r=Fr(e);if(!r)return{ok:!1,error:`unknown item "${e}": use a key from \`agentx approvals list\``};let{kind:i,ref:o}=r,a=t.now??Date.now(),l=s.by??"operator";if(n==="later"){if(!Ur(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 Lt(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(i){case"card":{let u=Tt(t.root,o,c?"yes":"no",{by:l,note:s.note,now:a});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}`}:u}case"schedule":{let u=await(c?ut:dt)(o,{configPath:Pt(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(!jt(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new fe(t.root);return f.held(d).some(p=>p.id===g)?(f.review(d,g,c?"approved":"rejected",l),{ok:!0,message:`${e} ${c?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${g}" isn't waiting for review`}}case"wiki":{let u=we(t),d=c?pt(u,o,{by:l,force:s.force,now:a}):mt(u,o,{by:l,reason:s.note,now:a});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}}}var Mt=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function Lo(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/a2a/delegations"||t.startsWith("/a2a/delegations/")||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"||t==="/app-files"||t==="/calls"||t.startsWith("/calls/")}function Oo(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 Po(t){return Mt.has(t)}function jo(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(Mt.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 Vo(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 Mo(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 ee(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function Wr(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function Br(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Fo(t,e=Br()){let n=ee(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=Wr(n),i=[ee(t.host),ee(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&i.includes(r)?"same-origin":"foreign"}let s=ee(t["sec-fetch-site"]).toLowerCase();return s==="cross-site"||s==="same-site"?"foreign":"none"}function Uo(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as un,mkdirSync as Ss,readFileSync as xs,renameSync as vs,writeFileSync as $s}from"fs";import{homedir as Is}from"os";import{dirname as As,join as _s}from"path";import{execFile as es,execFileSync as ts}from"child_process";import{execFileSync as Hr}from"child_process";import{existsSync as Ft,mkdirSync as zr,readdirSync as Kr,readFileSync as Ut,renameSync as Gr,writeFileSync as Xr}from"fs";import{homedir as Wt}from"os";import{join as xe}from"path";var x="siri:",Bt="com.apple.ttsbundle.gryphon-neural_",Ht=t=>!!t&&t.startsWith(Bt),qr=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],Jr=()=>{try{return Hr("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},Se;function ve(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&Se!==void 0)return Se;let{platform:n=process.platform,exists:s=Ft,prefDomain:r=Jr}=t,i=n==="darwin"&&qr.every(o=>s(o))&&r();return e||(Se=i),i}var zt=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],Kt={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"},$e=t=>Kt[t.toLowerCase()]??null;function te(t){let e=/^com\.apple\.ttsbundle\.gryphon-neural_([a-z]+)_([a-z]{2}-[A-Z]{2})_premium$/.exec(t);return e?{name:e[1],locale:e[2]}:null}var Yr=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function Zr(t){let e=new Map;for(let n of t)for(let[,s,r,i]of n.matchAll(Yr)){let o=`${s}-${r}`,a=`${Bt}${i}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:i[0].toUpperCase()+i.slice(1),locale:o,quality:"premium",gender:Kt[i]??null,siri:!0})}return[...e.values()]}function ne(t=zt,e={}){if(!ve(e))return[];let n=[];for(let s of t){let r;try{r=Kr(s)}catch{continue}for(let i of r)try{n.push(Ut(xe(s,i,"Info.plist"),"latin1"))}catch{}}return Zr(n)}var Nt=`#!/bin/sh
|
|
7
|
+
# Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
|
|
8
|
+
# siri-say.sh [voice] < text speak one line. A Siri voice id switches
|
|
9
|
+
# the OS default for it; any other id is
|
|
10
|
+
# passed to say -v.
|
|
11
|
+
# siri-say.sh --stop silence the line speaking, drop the queue.
|
|
12
|
+
# siri-say.sh --restore put back a voice a killed line left switched.
|
|
13
|
+
# AGENTX_SAY_RATE=<words a minute> sets the speed; unset, say's own.
|
|
14
|
+
D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
|
|
15
|
+
dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
|
|
16
|
+
stops="$dir/stop"
|
|
17
|
+
read_s=\${AGENTX_SAY_READ_S:-5} stale_s=\${AGENTX_SAY_STALE_S:-30} max_s=\${AGENTX_SAY_MAX_S:-300}
|
|
18
|
+
assets=\${AGENTX_SIRI_ASSET_DIRS:-"${zt.join(" ")}"}
|
|
19
|
+
if [ "$1" = --stop ]; then
|
|
20
|
+
mkdir -p "$dir" || exit 1
|
|
21
|
+
# Queued lines see this change and drop. The owner's trap stops say,
|
|
22
|
+
# restores the voice, and frees the lock.
|
|
23
|
+
echo "$$ $(date +%s)" > "$stops"
|
|
24
|
+
owner=$(cat "$lock/pid" 2>/dev/null)
|
|
25
|
+
[ -n "$owner" ] && kill "$owner" 2>/dev/null
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
mode=speak
|
|
29
|
+
[ "$1" = --restore ] && { mode=restore; set --; }
|
|
30
|
+
case "$1" in com.apple.ttsbundle.gryphon-neural_*) siri=$1 voice= ;; *) siri= voice=$1 ;; esac
|
|
31
|
+
rate=\${AGENTX_SAY_RATE:-}
|
|
32
|
+
case "$rate" in *[!0-9]*) rate= ;; esac
|
|
33
|
+
case "$siri" in *[!A-Za-z0-9._-]*) echo "bad voice id" >&2; exit 2;; esac
|
|
34
|
+
# Not macOS, or no pref tools: speak as is and never touch a pref.
|
|
35
|
+
if [ "$(uname)" != Darwin ] || ! command -v defaults >/dev/null || ! command -v plutil >/dev/null; then
|
|
36
|
+
[ "$mode" = restore ] && exit 0
|
|
37
|
+
if [ -n "$voice" ]; then exec say \${rate:+-r "$rate"} -v "$voice"; else exec say \${rate:+-r "$rate"}; fi
|
|
38
|
+
fi
|
|
39
|
+
mkdir -p "$dir" || exit 1
|
|
40
|
+
mine=$(cat "$stops" 2>/dev/null)
|
|
41
|
+
stopped() { [ "$(cat "$stops" 2>/dev/null)" != "$mine" ]; }
|
|
42
|
+
txt=$(mktemp "\${TMPDIR:-/tmp}/agentx-say.XXXXXX") || exit 1
|
|
43
|
+
say_pid= dog=
|
|
44
|
+
restore() {
|
|
45
|
+
[ -f "$saved" ] || return 0
|
|
46
|
+
if [ -s "$saved" ]; then defaults write $D $K "$(cat "$saved")"; else defaults delete $D $K 2>/dev/null; fi
|
|
47
|
+
rm -f "$saved"
|
|
48
|
+
}
|
|
49
|
+
finish() {
|
|
50
|
+
[ -n "$say_pid" ] && kill "$say_pid" 2>/dev/null
|
|
51
|
+
[ -n "$dog" ] && { pkill -P "$dog" 2>/dev/null; kill "$dog" 2>/dev/null; }
|
|
52
|
+
restore; rm -rf "$lock"; rm -f "$txt"; exit "$1"
|
|
53
|
+
}
|
|
54
|
+
drop() { rm -f "$txt"; exit 75; }
|
|
55
|
+
# A Siri voice whose asset macOS purged: switching to it makes the OS
|
|
56
|
+
# speak a fallback of its own (Eloquence Flo), so leave the pref alone.
|
|
57
|
+
if [ -n "$siri" ]; then
|
|
58
|
+
s=\${siri#com.apple.ttsbundle.gryphon-neural_} ; name=\${s%%_*} ; s=\${s#*_} ; loc=$(printf %s "\${s%%_*}" | tr - _)
|
|
59
|
+
found=
|
|
60
|
+
for a in $assets; do
|
|
61
|
+
grep -aqs "com.apple.siri.tts.voice.$loc.$name.neural.premium" "$a"/*/Info.plist && { found=1; break; }
|
|
62
|
+
done
|
|
63
|
+
[ -z "$found" ] && { echo "Siri voice $siri is not installed; speaking with the OS default" >&2; siri=; }
|
|
64
|
+
fi
|
|
65
|
+
# The whole text first, before the lock: a writer that never closes stdin
|
|
66
|
+
# must not hold up every other speaker.
|
|
67
|
+
[ "$mode" = restore ] && exec 0</dev/null
|
|
68
|
+
exec 3<&0 0</dev/null
|
|
69
|
+
cat <&3 > "$txt" & cat_pid=$!
|
|
70
|
+
exec 3<&-
|
|
71
|
+
n=0
|
|
72
|
+
while kill -0 "$cat_pid" 2>/dev/null; do
|
|
73
|
+
if [ $n -ge $((read_s * 10)) ]; then
|
|
74
|
+
kill "$cat_pid" 2>/dev/null; echo "stdin never closed; nothing said" >&2; rm -f "$txt"; exit 3
|
|
75
|
+
fi
|
|
76
|
+
sleep 0.1; n=$((n + 1))
|
|
77
|
+
done
|
|
78
|
+
# One speaker at a time. A lock whose owner died is taken over. A line
|
|
79
|
+
# that waits past stale_s, or that a stop overtook, is dropped unsaid.
|
|
80
|
+
n=0
|
|
81
|
+
while ! mkdir "$lock" 2>/dev/null; do
|
|
82
|
+
stopped && drop
|
|
83
|
+
if [ $n -ge $((stale_s * 10)) ]; then echo "waited \${stale_s}s for the speaker; dropped" >&2; drop; fi
|
|
84
|
+
owner=$(cat "$lock/pid" 2>/dev/null)
|
|
85
|
+
if [ -n "$owner" ] && ! kill -0 "$owner" 2>/dev/null; then rm -rf "$lock"
|
|
86
|
+
elif [ -z "$owner" ] && [ -n "$(find "$lock" -maxdepth 0 -mmin +1 2>/dev/null)" ]; then rm -rf "$lock"
|
|
87
|
+
else sleep 0.1; n=$((n + 1)); fi
|
|
88
|
+
done
|
|
89
|
+
echo $$ > "$lock/pid"
|
|
90
|
+
trap 'finish 143' TERM INT HUP
|
|
91
|
+
stopped && finish 75
|
|
92
|
+
[ "$mode" = restore ] && finish 0
|
|
93
|
+
restore
|
|
94
|
+
if [ -n "$siri" ]; then
|
|
95
|
+
lang=$(defaults read -g AppleLanguages 2>/dev/null | sed -n '2s/^[^A-Za-z]*\\([A-Za-z]*\\).*/\\1/p')
|
|
96
|
+
defaults export $D - 2>/dev/null | plutil -extract $K xml1 -o "$saved.tmp" - 2>/dev/null || : > "$saved.tmp"
|
|
97
|
+
mv "$saved.tmp" "$saved"
|
|
98
|
+
defaults write $D $K -array "\${lang:-en}" "{ _type = \\"Speech.VoiceSelection\\"; _version = 0; voiceId = \\"$siri\\"; }"
|
|
99
|
+
fi
|
|
100
|
+
# A watchdog: no line runs past its length's worth of speech (a hung say
|
|
101
|
+
# held the lock for minutes), capped at max_s.
|
|
102
|
+
limit=$((5 + $(wc -w < "$txt") * 6 / 10))
|
|
103
|
+
[ $limit -gt $max_s ] && limit=$max_s
|
|
104
|
+
if [ -n "$voice" ]; then say \${rate:+-r "$rate"} -v "$voice" -f "$txt" & else say \${rate:+-r "$rate"} -f "$txt" & fi
|
|
105
|
+
say_pid=$!
|
|
106
|
+
( sleep "$limit"; echo "say ran past \${limit}s; stopped" >&2; kill "$say_pid" 2>/dev/null ) & dog=$!
|
|
107
|
+
wait "$say_pid"
|
|
108
|
+
status=$?
|
|
109
|
+
say_pid=
|
|
110
|
+
finish $status
|
|
111
|
+
`,Qr=(t=Wt())=>xe(t,".agentx","voice","siri-say.sh");function Gt(t=Wt()){let e=Qr(t);return Ft(e)&&Ut(e,"utf8")===Nt||(zr(xe(t,".agentx","voice"),{recursive:!0}),Xr(`${e}.tmp`,Nt,{mode:493}),Gr(`${e}.tmp`,e)),e}var Xt=`ObjC.import("AVFoundation")
|
|
112
|
+
const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
|
|
113
|
+
for (let i = 0; i < vs.count; i++) {
|
|
114
|
+
const v = vs.objectAtIndex(i)
|
|
115
|
+
out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
|
|
116
|
+
}
|
|
117
|
+
out.join("\\n")`,ns=new Set(["Fred","Kathy","Ralph","Junior"]),rs={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 qt(t){let e=[];for(let n of t.split(`
|
|
118
|
+
`)){let[s,r,i,o,a]=n.split(" ");!s||!r||!i||s.includes(".siri_")||s.startsWith("com.apple.speech.synthesis.voice.")&&!ns.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":rs[r]??null})}return e}var ss=10*60*1e3,Jo=60*1e3,V=null,Ie=!1;function Ae(t=Date.now(),e=ss){if(process.platform!=="darwin")return[];if(V)t-V.at>e&&!Ie&&(Ie=!0,es("osascript",["-l","JavaScript","-e",Xt],{timeout:1e4},(n,s)=>{Ie=!1,n||(V={at:Date.now(),voices:[...qt(String(s)),...ne()]})}));else try{V={at:t,voices:[...qt(ts("osascript",["-l","JavaScript","-e",Xt],{encoding:"utf8",timeout:1e4})),...ne()]}}catch(n){_e(`[voice] could not list system voices: ${String(n?.message??n).split(`
|
|
119
|
+
`)[0]}`),V={at:t,voices:ne()}}return V.voices}var _e=t=>process.stderr.write(t+`
|
|
120
|
+
`),re=new Set;function Yo(t){_e=t}function D(t,e){re.has(t)||(re.add(t),_e(e))}function Zt(t){for(let e of re)t(e)&&re.delete(e)}var Qt=()=>{};function Zo(t){Qt=t}function en(t){try{Qt(t)}catch(e){D("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var is={premium:3,enhanced:2,standard:1},os=new Set(["Grandma","Grandpa"]);function Jt(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!os.has(t.name)?1:0;return is[t.quality]*10+e}var M=t=>t.toLowerCase().split(/[-_]/)[0],Yt=t=>t.id.startsWith("com.apple.voice.");function Re(t,e,n,s=new Set){let r=B(t.filter(a=>!a.siri&&M(a.locale)===M(e)),e);if(r.some(Yt)&&(r=r.filter(Yt)),n==="female"||n==="male"){let a=r.filter(l=>l.gender===n);a.length&&(r=a)}if(!r.length)return null;let i=r.filter(a=>a.quality===r[0].quality),o=new Set([...s].map(a=>a.toLowerCase()));return i.find(a=>!o.has(a.name.toLowerCase()))??i[0]}function B(t,e="en"){let n=e.toLowerCase().replace("_","-"),s=M(e),r=t.filter(i=>M(i.locale)===s);return(r.length?r:t).slice().sort((i,o)=>Jt(o)-Jt(i)||+(o.locale.toLowerCase()===n)-+(i.locale.toLowerCase()===n)||i.name.localeCompare(o.name)||i.locale.localeCompare(o.locale))}function H(t,e,n="en"){let s=t.trim();if(!s)return null;let r=e.find(c=>c.id===s);if(r)return r;if(s.toLowerCase().startsWith(x)){let c=s.slice(x.length).trim().toLowerCase(),u=B(e.filter(g=>g.siri&&g.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=H(c,e.filter(g=>M(g.locale)===M(n)),n);return d&&D(`siri:${c}`,`[voice] Siri voice "${c}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(c=>!c.siri);let i=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(s),o=(i?i[1]:s.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=B(e.filter(c=>c.name.toLowerCase()===o),n);return(i?a.find(c=>c.quality===i[2].toLowerCase()):void 0)??a[0]??null}function tn(t,e,n=new Set){let s=new Map;if(!e.length)return s;let r=new Set([...n].map(o=>o.toLowerCase())),i="female";for(let o of t){let a=o.gender==="female"||o.gender==="male",l=a?o.gender:i,c=e.filter(d=>!r.has(d.name.toLowerCase())),u=c.find(d=>d.gender===l)??(a?e.find(d=>d.gender===l):void 0)??c[0]??e[s.size%e.length];s.set(o.id,u),r.add(u.name.toLowerCase()),a||(i=i==="female"?"male":"female")}return s}var as=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(" ")),ls=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(" ")),cs=/[éèêëàâçùûîïôœ]/;function se(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)??[])as.has(i)&&s++,ls.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?r++:cs.test(i)&&(r+=.5);return s===r?null:s>r?"en":"fr"}var Ce="system",us=t=>t.trim().toLowerCase()===Ce,ds="21m00Tcm4TlvDq8ikWAM";function Te(t,e,n={},s=Ae()){let r=e[t],i=r?.name||t,o=r?.voice,a=De(e,n,s).get(t)??null,l=ms(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?oe(a):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||ys(i,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var oe=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function gs(t,e,n,s){if(!e||!n.length)return null;let r=H(e,n,s);return r||(D(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),en(e)),r}function on(t,e){let n=t.trim();if(n.toLowerCase().startsWith(x))return{locale:e,gender:$e(n.slice(x.length).trim())};let s=te(n);return s?{locale:s.locale,gender:$e(s.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var an=t=>t.toLowerCase().split(/[-_]/)[0],nn=(t,e)=>typeof t=="string"?t:t?.[an(e)];function ie(t,e,n,s){if(e!==void 0)return us(e)?null:gs(t,e,n,s)??void 0}var Ee=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function fs(t,e,n,s=new Set){let r=e.locale??"en",i=new Map,o=[],a=ie("voice.system",nn(e.system,r),n,r),l=()=>new Set([...s,...[...i.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=nn(u.system,r),g=ie(u.id,d,n,r),f=g!==void 0?g:d!==void 0&&n.length?ps(u,d,r,a,n,l()):a!==void 0&&Ee(a,u.gender)?a:void 0;f!==void 0?i.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of tn(o,B(n.filter(g=>!g.siri),r),c))i.set(u,d);return i}function ps(t,e,n,s,r,i){for(let a of t.fallbacks??[]){let l=ie(`${t.id}.fallbacks`,a,r,n);if(l!==void 0)return l}if(s!==void 0&&Ee(s,t.gender))return s;let o=on(e,n);return Re(r,o.locale,t.gender??o.gender,i)??void 0}function ms(t,e,n,s,r){if(typeof e=="string")return{};let i={},o=(a,l,c)=>{if(!(!l||typeof l=="string"))for(let[u,d]of Object.entries(l)){let g=ie(`${a}.${u}`,d,r,u);g===void 0&&r.length&&(g=Re(r,u,n??on(d,u).gender)??void 0),g!==void 0&&c(g)&&(i[an(u)]=g)}};return o("voice.system",s.system,a=>Ee(a,n)),o(t,e,()=>!0),i}function sa(t,e){let n=e?se(e):null;if(!n||!(n in t.systemByLanguage))return t;let s=t.systemByLanguage[n];return{...t,systemVoice:s?.id??null,systemVoiceName:s?oe(s):null}}function De(t,e={},n=Ae()){let s=Object.entries(t).map(([r,i])=>({id:r,system:i.voice?.system,gender:i.voice?.gender,fallbacks:i.voice?.fallbacks}));return fs(s,e,n)}function Le(t,e){let n={provider:t.provider,elevenlabs:hs(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 hs(t,e){return t||e||process.env.AGENTX_VOICE_ID||ds}function ys(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 bs=8*60*60*1e3,ks=500,rn=class{constructor(e=bs){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,s=Date.now()){let r=this.lastSpoke.get(sn(e,n));return r===void 0||s-r>this.gapMs}spoke(e,n,s=Date.now()){let r=sn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,s),this.lastSpoke.size>ks&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},sn=(t,e)=>`${t}\0${e}`;function 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 ia(t,e,n,s={}){let r=e[t],i=Te(t,e,s),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:i.name,voice:Le(i),persona:o||`You are ${i.name}.`,introLine:ln(i,n)}}var ws="[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 oa(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`${ws}
|
|
121
|
+
${ln(r,e.voice.introduce===!0&&!!s)}`}var Rs="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",dn=(t=Is())=>_s(t,".agentx","voice","health.json");function Cs(t,e,n){let s=t.trim();if(!s||s.toLowerCase()===Ce)return!0;if(s.toLowerCase().startsWith(x)){let r=s.slice(x.length).trim().toLowerCase();return e.some(i=>i.siri&&i.name.toLowerCase()===r)}return H(s,e,n)!==null}function Ts(t){let e=t.voice?.locale??"en",n=[],s=(r,i)=>{if(typeof i=="string")n.push({owner:r,name:i,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(i??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};s("voice.system",t.voice?.system);for(let[r,i]of Object.entries(t.agents))(i.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||s(r,i.voice?.system);return n}function Es(t,e){if(!e.length)return[];let n=new Map,s;for(let{owner:r,name:i,locale:o,perLanguage:a}of Ts(t)){if(Cs(i,e,o))continue;s??=De(t.agents,t.voice,e);let l=n.get(i)??{voice:i,agents:[],speaksWith:{}};l.agents.includes(r)||l.agents.push(r);let c=s.get(r);r!=="voice.system"&&!a&&(l.speaksWith[r]=c?oe(c):"the OS default voice"),n.set(i,l)}return[...n.values()]}function Oe(t){let e=te(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(x)){let n=t.slice(x.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function Ds(t){let e=t.map(n=>{let s=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${Oe(n.voice)}: ${s}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
|
|
122
|
+
`)}
|
|
123
|
+
Reinstall in ${Rs}. Agents switch back on their own once it is installed.`}}function Ls(t=dn()){if(!un(t))return null;try{let e=JSON.parse(xs(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function Os(t,e){Ss(As(t),{recursive:!0}),$s(`${t}.tmp`,JSON.stringify(e,null,2)+`
|
|
124
|
+
`),vs(`${t}.tmp`,t)}var cn=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,s=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??dn(),i=new Map((Ls(r)?.missing??[]).map(d=>[d.voice,d])),o=Es(e,n),a=o.map(d=>({...d,since:i.get(d.voice)?.since??s.toISOString(),...i.get(d.voice)?.notifiedAt?{notifiedAt:i.get(d.voice).notifiedAt}:{}})),l=[...i.keys()].filter(d=>!o.some(g=>g.voice===d));for(let d of l)this.deps.log(`[voice] ${Oe(d)} is installed again; its agents speak with it again`);l.length&&Zt(d=>l.some(g=>d===g||d.endsWith(`:${g}`)));let c=a.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:g}=Ds(c);try{await this.deps.notify(d,g);for(let f of c)f.notifiedAt=s.toISOString();this.deps.log(`[voice] told the owner: ${c.map(f=>Oe(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=a.length>0;let u={checkedAt:s.toISOString(),missing:a};return(!un(r)||JSON.stringify(a)!==JSON.stringify([...i.values()]))&&Os(r,u),u}finally{this.running=!1}}};import{readFileSync as je,writeFileSync as yn,existsSync as Ve,readdirSync as Bs,statSync as Hs}from"fs";import{resolve as Me,join as zs}from"path";import{existsSync as gn,mkdirSync as Ps,readFileSync as js,writeFileSync as fn}from"fs";import{dirname as Vs,resolve as pn}from"path";import{z as m}from"zod";var Ms=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),Ns=m.object({id:m.string(),title:m.string(),description:m.string().optional(),assignee:m.string().optional(),labels:m.array(m.string()).default([]),milestone:m.string().optional(),status:m.enum(["todo","doing","blocked","done"]).default("todo"),priority:m.number().int().optional(),estimatedSeconds:m.number().int().optional(),source:Ms.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),Fs=m.object({version:m.literal(1),items:m.array(Ns).default([])}),ae=class{constructor(e){this.path=e}jsonPath(){return pn(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return pn(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return gn(this.jsonPath())}load(){let e=this.jsonPath();if(!gn(e))return{version:1,items:[]};let n=js(e,"utf-8");try{return Fs.parse(JSON.parse(n))}catch(s){throw new Error(`Backlog file invalid (${e}): ${s.message}`)}}save(e){let n=this.jsonPath();Ps(Vs(n),{recursive:!0}),fn(n,JSON.stringify(e,null,2)+`
|
|
125
|
+
`),fn(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(i=>i.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let s=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??s,updatedAt:s};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),s=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),i=[];for(let o of e){if(s.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),i.push(a),s.add(a.id)}return i.length&&this.save(n),i}update(e,n){let s=this.load(),r=s.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let i={...s.items[r],...n,id:s.items[r].id,createdAt:s.items[r].createdAt,updatedAt:new Date().toISOString()};return s.items[r]=i,this.save(s),i}remove(e){let n=this.load(),s=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===s?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],s={doing:[],blocked:[],todo:[],done:[]};for(let i of e.items)s[i.status].push(i);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[i,o]of r)if(s[i].length){n.push(`## ${o}`,"");for(let a of s[i]){let l=i==="done"?"x":" ",c=a.assignee?`@${a.assignee} `:"",u=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",d=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${l}] ${c}${a.title}${u}${d}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
|
|
126
|
+
`)}};function ba(t){return`${t.type}:${t.project}:${t.iid}`}function mn(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 Pe(t,e,n,s=()=>{}){return t.source?t.source.type==="gitlab"?Us(t.source,e,n,s):t.source.type==="github"?Ws(t.source,e,n,s):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function Us(t,e,n,s){let r=n.channels.gitlab,i=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!i||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],l=async(f,p={})=>fetch(`${o}/api/v4${f}`,{...p,headers:{"PRIVATE-TOKEN":i,"Content-Type":"application/json",...p.headers||{}}}),c=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async p=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(p)}`,{headers:{"PRIVATE-TOKEN":i}});if(!h.ok)return null;let y=await h.json();return Array.isArray(y)&&y[0]?.id?y[0].id:null}catch{return null}}))).filter(p=>typeof p=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await l(`/projects/${c}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let p=await f.json();Array.isArray(p)&&p[0]?.id&&(d=p[0].id)}}catch(f){s(`[backlog-sync] milestone lookup failed: ${f.message}`)}let g={};if(e.title!==void 0&&(g.title=e.title),e.description!==void 0&&(g.description=e.description),e.labels!==void 0&&(g.labels=e.labels.join(",")),e.addLabels?.length&&(g.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(g.remove_labels=e.removeLabels.join(",")),u!==void 0&&(g.assignee_ids=u),d!==void 0&&(g.milestone_id=d),e.state&&(g.state_event=e.state==="closed"?"close":"reopen"),Object.keys(g).length)try{let f=await l(`/projects/${c}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(g)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let p=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${p.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await l(`/projects/${c}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function Ws(t,e,n,s){let i=n.channels.github?.token;if(!i)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(g,f={})=>fetch(`https://api.github.com${g}`,{...f,headers:{Authorization:`Bearer ${i}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),l=t.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let g=await a(`/repos/${l}/milestones?state=all&per_page=100`);if(g.ok){let f=await g.json(),p=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;p?.number&&(c=p.number)}}catch(g){s(`[backlog-sync] github milestone lookup failed: ${g.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let g=await a(`/repos/${l}/issues/${t.iid}`);if(g.ok){let f=await g.json(),p=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...p,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(g){s(`[backlog-sync] github label fetch failed: ${g.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let g=await a(`/repos/${l}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:g.ok,status:g.status}),!g.ok){let f=await g.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${g.status}: ${f.slice(0,200)}`,url:t.url}}}catch(g){return o.push({kind:"PATCH issue",ok:!1,error:g.message}),{ok:!1,attempts:o,error:g.message,url:t.url}}if(e.note)try{let g=await a(`/repos/${l}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:g.ok,status:g.status})}catch(g){o.push({kind:"POST comment",ok:!1,error:g.message})}return{ok:o.every(g=>g.ok),attempts:o,url:t.url}}var Ne=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,le=/@([a-z0-9_-]+)/i,hn=/\[time:\s*([0-9hm\s]+)\]/i;function Ks(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 Fe=class{constructor(e,n,s=()=>{}){this.path=e;this.daemon=n;this.log=s;this.store=new ae(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Me(process.cwd(),this.path);return Ve(e)?je(e,"utf-8").split(`
|
|
127
|
+
`):[]}writeMd(e){let n=Me(process.cwd(),this.path);yn(n,e.join(`
|
|
128
|
+
`))}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(Ne);if(!i||i[2].toLowerCase()==="x")continue;let a=i[3],l=a.match(le);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=a.match(hn),u=a.replace(le,"").replace(hn,"").trim();s.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?Ks(c[1]):void 0,priority:r})}return s}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let s=this.store.findById(n);if(!s)return;let r=this.store.update(n,{assignee:s.assignee||e,status:"doing"});if(r.source&&this.daemon){let i=mn([r.assignee||e],r.source,this.daemon);Pe(r,{assigneeUsernames:i,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(o=>this.log(`[backlog-sync] claim failed for ${n}: ${o?.message??o}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let a={};n.status==="done"?a.status="done":n.status==="blocked"?(a.status="blocked",a.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(a.status="doing"),n.timeSeconds&&(a.estimatedSeconds=n.timeSeconds);let l=this.store.update(e,a);if(l.source&&this.daemon){let c={};n.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):n.status==="blocked"&&(c.addLabels=["Blocked"]),n.note&&(c.note=n.note),Object.keys(c).length&&Pe(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(Ne))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"}}},Ue=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(Ve(e))for(let s of Bs(e)){let r=zs(e,s);Hs(r).isDirectory()?this.walk(r,n):s.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Me(process.cwd(),this.root),n);let s=[];for(let r of n){let i=je(r,"utf-8").split(`
|
|
129
|
+
`);for(let o=0;o<i.length;o++){let a=i[o].match(Ne);if(!a||a[2].toLowerCase()==="x")continue;let l=a[3].match(le);!l||l[1].toLowerCase()!==e.toLowerCase()||s.push({id:`wiki:${r}:${o}`,title:a[3].replace(le,"").trim(),assignee:l[1],priority:o})}}return s}async claim(){}async report(e,n){let s=e.split(":"),r=parseInt(s[s.length-1],10),i=s.slice(1,-1).join(":");if(!Ve(i))return;let o=je(i,"utf-8").split(`
|
|
130
|
+
`);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),yn(i,o.join(`
|
|
131
|
+
`)))}},We=class{constructor(e,n,s,r,i){this.host=e;this.token=n;this.projects=s;this.agentUsernames=r;this.log=i}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,s]of Object.entries(this.agentUsernames))if(s.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let s=e.references?.full?.split("#")[0]||n,r=[],i;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(i=e.labels.map(c=>({name:c.name,color:c.color,text_color:c.text_color})),r=i.map(c=>c.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=a[0]?.username;return{id:`gitlab:${s}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:i,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let s=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!s.ok)throw new Error(`GitLab ${s.status}: ${await s.text().catch(()=>"")}`);return s.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let s=[],r=this.projects.length?this.projects:["__ALL__"];for(let i of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(i)}&state=opened&scope=all&per_page=20`,l=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,o);d.assignee=e,s.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${i} on ${o}: ${a.message}`)}return s}async claim(e,n){let{project:s,iid:r,type:i}=this.parseId(n),o=`/projects/${encodeURIComponent(s)}/${i==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(a){this.log(`[business] claim label update failed: ${a.message}`)}}async report(e,n){let{project:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),l=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(a){this.log(`[business] done label update failed: ${a.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(a){this.log(`[business] blocked label update failed: ${a.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(a){this.log(`[business] report note failed: ${a.message}`)}}async listAll(e={}){let n=e.sinceDays??30,s=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,i=e.state??"opened";r.set("state",i),r.set("updated_after",s),r.set("scope","all"),r.set("per_page","100"),r.set("with_labels_details","true"),r.set("order_by","updated_at"),r.set("sort","desc"),e.labels?.length&&r.set("labels",e.labels.join(",")),e.milestone&&r.set("milestone",e.milestone),e.search&&r.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],a=[];for(let c of o)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let g of d)a.push(this.mapIssue(g,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=a;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,n){let{project:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:s}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${s}?with_labels_details=true`);return{...this.mapIssue(r,n),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(o=>o.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,n){let{project:s,iid:r}=this.parseId(e),i;n.assigneeUsernames&&(i=(await Promise.all(n.assigneeUsernames.map(async u=>{try{let d=await this.api(`/users?username=${encodeURIComponent(u)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch{return null}}))).filter(u=>typeof u=="number"));let o;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")o=0;else try{let c=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(o=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${c.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),i!==void 0&&(a.assignee_ids=i),o!==void 0&&(a.milestone_id=o);let l=await this.api(`/projects/${encodeURIComponent(s)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(l,s)}async listMembers(){let e=new Map;for(let n of this.projects)try{let s=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of s)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(s){this.log(`[board] listMembers failed for ${n}: ${s.message}`)}return[...e.values()].sort((n,s)=>n.username.localeCompare(s.username))}async listMilestones(){let e=new Map;for(let s of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(s)}/milestones?per_page=100`);for(let i of r)i.title&&!e.has(i.title)&&e.set(i.title,{id:i.id,title:i.title,state:i.state,dueDate:i.due_date})}catch(r){this.log(`[board] listMilestones failed for ${s}: ${r.message}`)}let n=[...e.values()];return n.sort((s,r)=>s.state!==r.state?s.state==="active"?-1:1:s.title.localeCompare(r.title)),n}async create(e){let n=e.projectHint||this.projects[0];if(!n)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let s,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(s=(await Promise.all(r.map(async c=>{try{let u=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${c}: ${u.message}`),null}}))).filter(c=>typeof c=="number"));let i;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(i=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};s?.length&&(o.assignee_ids=s),i!==void 0&&(o.milestone_id=i);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,s){await this.transitionMany(e,n?[n]:[],s?[s]:[])}async transitionMany(e,n,s){let{project:r,iid:i,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",l=new URLSearchParams;n.length&&l.set("add_labels",n.join(",")),s.length&&l.set("remove_labels",s.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${i}?${l.toString()}`,{method:"PUT"})}parseId(e){let s=e.replace(/^gitlab:/,"").split(":"),r=s.pop(),i=s.pop()==="mr"?"mr":"issue";return{project:s.join(":"),type:i,iid:r}}};function Ia(t,e,n){let s=t.workSource;switch(s.type){case"backlog":return new Fe(s.path,e,n);case"wiki":return new Ue(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 We(r.host,r.token,o,i,n)}}}var Be="unmapped";function He(t,e=[]){if(!t)return Be;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 Gs(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,He(i.id,n)));let r=(i,o=new Set)=>{if(e.has(i))return e.get(i);if(o.has(i))return;o.add(i);let a=s[i]?.reportsTo;if(!a)return;let l=r(a,o);return l&&e.set(i,l),l};for(let i of Object.keys(s))r(i);return e}function Xs(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 _a(t,e){let n=Xs(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return He(t.project,e.projects);if(t.agentId){let s=Gs(e).get(t.agentId);if(s)return s}return Be}function Ra(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 qs=t=>t===Be?"internal":"client";function Js(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??qs(t),respondWithinMinutes:Ys(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function Ca(t){let e=new Set;for(let n of t.projects??[])e.add(He(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=>Js(n,t))}function Ys(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 Zs=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Qs=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function bn(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(Qs)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],s=n[2],r=ei(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 Ea(t){if(!t||!t.includes("agentx:ui"))return t;let e=Zs.exec(t);return e?t.slice(0,e.index).trimEnd():t}function ei(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n={};if(Array.isArray(e.buttons)){let s=[],r=[],i=[];for(let o of e.buttons)!o||typeof o.label!="string"||(typeof o.url=="string"&&/^https?:\/\//i.test(o.url)?s.push({label:o.label,url:o.url}):typeof o.reply=="string"&&o.reply.trim()?r.push({label:o.label,reply:o.reply.trim()}):o.action!=null&&i.push(o.label));s.length&&(n.buttons=s),r.length&&(n.replies=r),i.length&&(n.skippedActions=i)}if(e.poll&&typeof e.poll=="object"){let s=e.poll.question,r=e.poll.options;typeof s=="string"&&s.trim()&&Array.isArray(r)&&r.filter(i=>typeof i=="string").length>=2&&(n.poll={question:s,options:r.filter(i=>typeof i=="string"),multiple:e.poll.multiple===!0})}if(e.media&&typeof e.media=="object"){let{type:s,url:r,caption:i}=e.media;["image","document","audio","video"].includes(s)&&typeof r=="string"&&r&&(n.media={type:s,url:r,...typeof i=="string"?{caption:i}:{}})}if(Array.isArray(e.quickReplies)){let s=e.quickReplies.filter(r=>typeof r=="string"&&r.trim()).map(r=>r.trim());s.length&&(n.quickReplies=s)}return!n.buttons&&!n.poll&&!n.media&&!n.quickReplies&&!n.replies&&!n.skippedActions?null:n}function La(t,e){let n=`${e}/call?to=${encodeURIComponent(t.from)}&callId=${encodeURIComponent(t.callId)}`;return t.reason==="camera"?`\u{1F4F7} ${t.from} is sharing a phone camera \u2014 tap to watch: ${n}&watch=1`:`\u{1F4DE} ${t.from} is calling \u2014 tap to join: ${n}`}var ti=5*6e4;function T(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var kn=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],s=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(T)),this.log=s,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${T(n)}`}cleanupExpired(){let e=Date.now();for(let[n,s]of this.pending){let r=s.filter(i=>i.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==s.length&&this.pending.set(n,r)}for(let[n,s]of this.recentRings)s<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,s){return this.addSubscriber(e,n,{kind:"sse",res:s})}subscribeInternal(e,n,s){return this.addSubscriber(e,n,{kind:"callback",deliver:s})}addSubscriber(e,n,s){let r={callId:e,recipient:n,sink:s};this.subs.add(r);let i=s.kind==="sse"?"sse":"internal";this.log(`subscribe[${i}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let l=Date.now(),c=a.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(o),c.length&&this.log(`flushed ${c.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${i}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
|
|
132
|
+
data: ${JSON.stringify(n)}
|
|
133
|
+
|
|
134
|
+
`):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=T(e.to);if(n===T(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let s of this.subs)if(s.callId===e&&T(s.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(T(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let s=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>s)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,s+ti),this.ringHandler)try{this.ringHandler(e)}catch(i){this.log(`ringHandler threw: ${i.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let s=this.pendingKey(e.callId,e.to),r=this.pending.get(s)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(s,r),this.log(`buffered ${e.kind} for call=${e.callId} to=${e.to} (no subscriber yet, ${r.length} pending)`)}return{ok:!0}}fanOut(e){let n=0,s=T(e.to);for(let r of this.subs)r.callId===e.callId&&T(r.recipient)===s&&(this.deliverTo(r,e)?n++:this.subs.delete(r));return n}get subscriberCount(){return this.subs.size}shutdown(){this.cleanupTimer&&clearInterval(this.cleanupTimer);for(let e of this.subs)if(e.sink.kind==="sse")try{e.sink.res.end()}catch{}this.subs.clear(),this.pending.clear()}};import{closeSync as z,createReadStream as ni,fstatSync as ri,openSync as si,realpathSync as wn}from"fs";import{isAbsolute as ii,resolve as Sn,sep as xn}from"path";var Na="/app-files",oi=/^[A-Za-z0-9_.:-]{1,64}$/;function ai(t,e,n=process.cwd()){if(!e||e.length>J.pathChars||e.includes("\0"))return{ok:!1,status:400,error:"bad file path"};if(e.split(/[\\/]/).includes(".."))return{ok:!1,status:403,error:`the path leaves the workspace: copy the file into ${me}/ first`};if(!pe(e))return{ok:!1,status:415,error:"this type of file is not served"};let s;try{s=wn(Sn(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=wn(ii(e)?e:Sn(s,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(s+xn))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${me}/ first`};let i=pe(r);return i?{ok:!0,path:r,...i}:{ok:!1,status:415,error:"this type of file is not served"}}function li(t,e){let n=t.replace(/[^\x20-\x7e]/g,"_").replace(/["\\;]/g,"_").slice(0,120)||"file";return`${e==="file"?"attachment":"inline"}; filename="${n}"; filename*=UTF-8''${encodeURIComponent(t.slice(0,120))}`}function ci(t,e,n){return{"Content-Type":t,"Content-Disposition":li(e,n),"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; img-src 'self'; media-src 'self'; sandbox","Cache-Control":"private, max-age=3600","Accept-Ranges":"bytes"}}function ui(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let s,r;return n[1]?(s=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(s=Math.max(0,e-Number(n[2])),r=e-1),s>r||s>=e?"unsatisfiable":{start:s,end:r}}function Fa(t,e,n,s){let r=(C,O)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(O))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let i=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!oi.test(i))return r(400,{error:"bad agent id"});let a=s.workspaceOf(i);if(!a)return r(404,{error:`no agent "${i}" on this computer`});let l=ai(a,o,s.cwd);if(!l.ok)return s.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${i}: ${l.error}`),r(l.status,{error:l.error});let c;try{c=si(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=ri(c);if(!C.isFile())return z(c),r(404,{error:"not a file"});u=C.size}catch{return z(c),r(404,{error:"file not found"})}if(u>J.bytes)return z(c),r(413,{error:`the file is larger than ${J.bytes/1024/1024} MB`});let d=l.path.split(xn).pop()||"file",g=ci(l.mime,d,l.kind),f=ui(t.headers.range,u);if(f==="unsatisfiable"){z(c),e.writeHead(416,{...g,"Content-Range":`bytes */${u}`}),e.end();return}let{start:p,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...g,"Content-Length":String(u?h-p+1:0),...f?{"Content-Range":`bytes ${p}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){z(c),e.end();return}let y=ni("",{fd:c,start:p,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as K}from"child_process";import{readFileSync as di,writeFileSync as gi}from"fs";import{tmpdir as fi}from"os";import{join as pi}from"path";var vn=t=>t&&t!==1?Math.round(175*t):null,ce=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function mi(){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=di(t,"utf8").trim();if(e)return e}catch{}return null}function qa(t=mi()){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",...ce(n.voice.rate)?{voice_settings:{speed:ce(n.voice.rate)}}:{}}),signal:s});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let i=pi(fi(),`agentx-say-${process.pid}-${++e}.mp3`);return gi(i,Buffer.from(await r.arrayBuffer())),i}catch(r){if(s.aborted||!n.voice.fallback)throw r;return D(`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 $n(t,e){let n=t.languages&&se(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var hi=(t,e="")=>{let n=$n(t,e),s=vn(t.rate);return[...n&&!Ht(n)?["-v",n]:[],...s?["-r",String(s)]:[]]};function yi(t,e,n){if(!n)return["say",hi(t,e)];let s=$n(t,e);return["/bin/sh",[n,...s?[s]:[]]]}function Ja(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function Ya(t=ze()){if(t)try{K("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Za(t=ze()){if(t)try{K("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function ze(t={},e){if(!ve(t))return null;try{return Gt(e)}catch(n){return D("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
|
|
135
|
+
`)[0]}); Siri voices will not switch`),null}}var Qa=(t,e)=>{if(!t){let[n,s]=yi(e.voice,e.text,ze()),r=vn(e.voice.rate),i=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=K(n,s,{stdio:["pipe","ignore","ignore"],env:i});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?K("afplay",[t],{stdio:"ignore"}):K("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as In}from"child_process";import{accessSync as bi,constants as ki,readFileSync as An}from"fs";import{homedir as wi}from"os";import{basename as N,delimiter as _n,dirname as Si,extname as xi,join as Ke}from"path";var E={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Rn(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)>E.ms+2e3?{status:413,error:Xe()}:null}var Xe=()=>`The recording is longer than ${E.ms/6e4} minutes.`,vi={"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 Cn(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return vi[e]??null}function Tn(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 qe(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 Ge(t,e,n=process.env.PATH??""){let s=wi(),r=[Ke(s,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(_n).filter(Boolean)];for(let i of[e,...r.map(o=>Ke(o,t))])if(i)try{return bi(i,ki.X_OK),i}catch{}return null}function il(t){return{key:t,mlx:Ge("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:Ge("whisper",process.env.AGENTX_WHISPER),ffmpeg:$i()}}var $i=()=>Ge("ffmpeg",process.env.AGENTX_FFMPEG);async function En(t,e){return e?Ii(t,e):null}async function Ii(t,e){let n=String(E.ms/1e3+5);try{let r=[...(await Ai(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 Dn(t,e,n,s){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([An(t)],{type:e}),N(t));let i=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:s??AbortSignal.timeout(6e4)});if(!i.ok)throw new Error(`ElevenLabs ${i.status}: ${(await i.text().catch(()=>"")).slice(0,160)}`);let o=await i.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Ln(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:`${Si(s)}${_n}${process.env.PATH??""}`};await _i(e,i,12e4,o);try{return An(Ke(r,N(n,xi(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function Ai(t,e,n){return new Promise((s,r)=>{let i=In(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{i.kill("SIGKILL"),r(new Error(`${N(t)} took too long`))},n);i.stderr.on("data",l=>{o=(o+l).slice(-8192)}),i.on("error",l=>{clearTimeout(a),r(l)}),i.on("exit",l=>{clearTimeout(a),l===0?s(o):r(new Error(`${N(t)} exited ${l}`))})})}function _i(t,e,n,s=process.env){return new Promise((r,i)=>{let o=In(t,e,{stdio:["ignore","pipe","pipe"],env:s}),a="",l="",c=setTimeout(()=>{o.kill("SIGKILL"),i(new Error(`${N(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{l.length<4096&&(l+=u)}),o.on("error",u=>{clearTimeout(c),i(u)}),o.on("exit",u=>{clearTimeout(c),u===0?r(a):i(new Error(`${N(t)} exited ${u}: ${l.trim().split(`
|
|
136
|
+
`).pop()?.slice(0,160)??""}`))})})}function On(t,e=800){let n=t;return n=n.replace(/```[\s\S]*?```/g,". "),n=n.replace(/`[^`]*`/g,""),n=n.replace(/\*\*(.*?)\*\*/g,"$1"),n=n.replace(/__(.*?)__/g,"$1"),n=n.replace(/\*([^*]+)\*/g,"$1"),n=n.replace(/_([^_]+)_/g,"$1"),n=n.replace(/~~(.*?)~~/g,"$1"),n=n.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),n=n.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),n=n.replace(/^#{1,6}\s+/gm,""),n=n.replace(/^[\s]*[-*+]\s+/gm,". "),n=n.replace(/^[\s]*\d+\.\s+/gm,". "),n=n.replace(/^[-=_]{3,}$/gm,""),n=n.replace(/^>\s*/gm,""),n=n.replace(/https?:\/\/\S+/g,"link"),n=n.replace(/\/\w+(\/\w+)+/g,s=>s.split("/").filter(Boolean).join(" slash ")),n=n.replace(/&/g," and "),n=n.replace(/@/g," at "),n=n.replace(/=>/g," returns "),n=n.replace(/->/g," to "),n=n.replace(/\|/g," or "),n=n.replace(/\be\.g\./gi,"for example"),n=n.replace(/\bi\.e\./gi,"that is"),n=n.replace(/\betc\./gi,"etcetera"),n=n.replace(/\bvs\.?\b/gi,"versus"),n=n.replace(/\n{2,}/g,". "),n=n.replace(/\n/g," "),n=n.replace(/\s+/g," "),n=n.replace(/\.\s*\./g,"."),n=n.replace(/\s+([.,!?])/g,"$1"),n=n.trim().replace(/^[.,:;]+\s*/,""),n.length>e&&(n=n.slice(0,e).replace(/\s+\S*$/,"")+"..."),n}import{mkdtemp as Ri,rm as Ci,writeFile as Ti}from"fs/promises";import{tmpdir as Ei}from"os";import{join as Pn}from"path";var Di=1500,Li=64*1024,Oi=2,Je=0;function yl(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function bl(t,e,n,s){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?Pi(t,e,s):Mi(t,e,s)}async function Pi(t,e,n){let s=String(t.headers["content-type"]||""),r=Cn(s);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let i=Rn(t.headers["x-audio-duration-ms"]);if(i)return t.resume(),b(e,i.status,{error:i.error});let o=await jn(t,E.bytes);if(!o)return b(e,413,{error:Ui()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(Je>=Oi)return b(e,429,{error:"This computer is already writing down other recordings. Try again in a moment."});let a=n.stt(),l=n.host(),c=Tn(a,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",g=c.length?"":" "+qe(a,l);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${g}`,setup:!1})}if(!c.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:qe(a,l),setup:!1});Je++;let u;try{let d=await Ri(Pn(Ei(),"agentx-phone-voice-"));try{u=await ji(d,`speech.${r}`,o,s,l,c,n)}finally{await Ci(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{Je--}b(e,u[0],u[1])}async function ji(t,e,n,s,r,i,o){let a=Pn(t,e);if(await Ti(a,n,{mode:384}),r.ffmpeg){let c=await(o.measure??En)(a,r.ffmpeg);if(c==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(c*1e3>E.ms+2e3)return[413,{error:Xe()}]}let l=[];for(let c of i)try{let u=await Vi(c,a,s,r,t,o);return o.log(`[voice] phone recording transcribed with ${c} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:c}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:c}]}catch(u){let d=String(u?.message??u).split(`
|
|
137
|
+
`)[0].slice(0,200);l.push(`${c}: ${d}`),o.log(`[voice] phone transcription with ${c} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:l.join("; ")}]}function Vi(t,e,n,s,r,i){let o=i.engines?.[t];if(o)return o(e,n,s,r);if(t==="elevenlabs")return Dn(e,n,s.key);let a=t==="mlx-whisper"?s.mlx:s.whisper;return Ln(t,a,e,s.ffmpeg,r)}async function Mi(t,e,n){let s=await jn(t,Li);if(!s)return b(e,413,{error:"request too large"});let r;try{r=JSON.parse(s.toString("utf8")||"{}")}catch{return b(e,400,{error:"expected JSON"})}let i=typeof r?.agent=="string"?r.agent:"",o=typeof r?.peer=="string"&&r.peer?r.peer:void 0;if(!i)return b(e,400,{error:"agent is required"});let a=Ni(typeof r?.text=="string"?r.text:"");if(!a)return b(e,422,{error:"Nothing in this answer can be said aloud."});let l=n.voiceOf(i,o);if(!l)return b(e,404,{error:`Unknown agent: ${i}`});let c=(d,g=200)=>b(e,g,{fallback:"browser",reason:d,text:a});if(l.provider!=="elevenlabs")return c("This agent speaks with a system voice, which only plays on the computer.");let u=n.elevenLabsKey();if(!u)return c("No ElevenLabs key is set on this computer.");try{let d=await(n.synth??Fi)(u,l,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(d)}catch(d){return n.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
|
|
138
|
+
`)[0].slice(0,160)}`),c("ElevenLabs could not speak this answer.",502)}}function Ni(t){let e=bn(ot(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return On(e,Di)}async function Fi(t,e,n){let s=ce(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 Ui=()=>`The recording is larger than ${E.bytes/1024/1024} MB, more than ${E.ms/6e4} minutes of speech.`;function kl(t,e,n,s){if(e)return s.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Le(Te(t,r,n.voice)):null}function jn(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,s)=>{let r=[],i=0;t.on("data",o=>{if(!(i>e)){if(i+=o.length,i>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{i<=e&&n(Buffer.concat(r))}),t.on("error",s)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as v,readFileSync as et,writeFileSync as tt,mkdirSync as ue,readdirSync as Qe,rmSync as Wi,statSync as A}from"fs";import{resolve as Vn,relative as Bi,dirname as nt,join as L,extname as G,basename as rt}from"path";var S=200*1024,Mn=new Set([".md",".markdown",".txt"]),F=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),Hi=6,zi=new Set(["CLAUDE.md","SOUL.md","IDENTITY.md","PERSONA.md","AGENT.md","BOOTSTRAP.md"]);function R(t,e){if(!t)throw new Error("Agent workspace is not configured.");let n=Vn(t);if(v(n)||ue(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let s=Vn(n,e);if(Bi(n,s).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return s}function Nn(t){let e=G(t).toLowerCase();if(!Mn.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function Ye(t,e){let n=t.split(/\r?\n/).find(s=>s.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function vl(t){let e=R(t,"."),n=[],s=new Set,r=[];try{r=Qe(e)}catch{}for(let a of zi){let l=L(e,a);if(v(l)&&A(l).isFile()){let c=A(l).size,u=c>0&&c<S?Ze(l):"";n.push({path:a,title:Ye(u,a),size:c,exists:!0}),s.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),s.add(a)}for(let a of r){if(s.has(a))continue;let l=L(e,a);try{let c=A(l);if(!c.isFile()||!Mn.has(G(a).toLowerCase()))continue;let u=c.size>0&&c.size<S?Ze(l):"";n.push({path:a,title:Ye(u,a),size:c.size,exists:!0})}catch{}}let i=[],o=L(e,".claude","skills");if(v(o))try{for(let a of Qe(o)){let l=L(o,a),c;try{c=A(l)}catch{continue}if(!c.isDirectory())continue;let u=L(l,"SKILL.md");if(!v(u))continue;let d=A(u),g=d.size<S?Ze(u):"";i.push({slug:a,title:Ye(g,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return i.sort((a,l)=>a.slug.localeCompare(l.slug)),{identity:n,skills:i,workspace:e}}function Ze(t){try{return et(t,"utf-8")}catch{return""}}function $l(t,e){let n=R(t,e);if(Nn(n),!v(n))return{path:e,content:""};if(A(n).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:et(n,"utf-8")}}function Il(t,e,n){let s=R(t,e);Nn(s);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return ue(nt(s),{recursive:!0}),tt(s,r),{path:e,bytes:r.length}}function Al(t,e,n={}){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Skill slug must be lowercase (letters, digits, -, _) and start with a letter or digit.");let s=`.claude/skills/${e}/SKILL.md`,r=R(t,s);if(v(r))throw new Error(`Skill "${e}" already exists.`);ue(nt(r),{recursive:!0});let i=n.content?.trim()?n.content:Ki(e,n.title);return tt(r,i),{slug:e,path:s}}function _l(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);if(!A(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return Wi(n,{recursive:!0,force:!0}),{slug:e}}function Rl(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=[];return r(n,"",0,s),s.sort((i,o)=>i.kind!==o.kind?i.kind==="dir"?-1:1:i.path.localeCompare(o.path)),s;function r(i,o,a,l){if(a>Hi)return;let c=[];try{c=Qe(i)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=L(i,u),g=o?`${o}/${u}`:u,f;try{f=A(d)}catch{continue}if(f.isDirectory())l.push({path:`${g}/`,kind:"dir",size:0,editable:!1}),r(d,g,a+1,l);else if(f.isFile()){let p=G(u).toLowerCase(),h=F.has(p)||F.has(u.toLowerCase());l.push({path:g,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function Cl(t,e,n){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let s=R(t,`.claude/skills/${e}/${n}`);if(!v(s)||!A(s).isFile())throw new Error(`File not found: ${n}`);let r=G(s).toLowerCase(),i=rt(s).toLowerCase();if(!F.has(r)&&!F.has(i))throw new Error(`File type not editable: ${n}`);if(A(s).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:et(s,"utf-8")}}function Tl(t,e,n,s){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let r=R(t,`.claude/skills/${e}/${n}`),i=G(r).toLowerCase(),o=rt(r).toLowerCase();if(!F.has(i)&&!F.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(s,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return ue(nt(r),{recursive:!0}),tt(r,a),{path:n,bytes:a.length}}function El(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=r=>v(L(n,r));return s("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:s("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:s("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:s("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:s("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function Ki(t,e){return`# ${e?.trim()||t}
|
|
139
|
+
|
|
140
|
+
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.
|
|
141
|
+
|
|
142
|
+
## When to use
|
|
143
|
+
- Trigger condition 1
|
|
144
|
+
- Trigger condition 2
|
|
145
|
+
|
|
146
|
+
## How to use
|
|
147
|
+
Document the arguments, commands, or files the skill expects. Example:
|
|
148
|
+
|
|
149
|
+
\`\`\`bash
|
|
150
|
+
# Example invocation
|
|
151
|
+
claude-code ${rt(t)} --arg value
|
|
152
|
+
\`\`\`
|
|
153
|
+
`}Hn();var Fn={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function Un(t){return{...Fn,...t??{},regions:{...t?.regions??{}},buffer:{...Fn.buffer,...t?.buffer??{}}}}function Ol(t){try{return Un(st(t).screen)}catch{return Un(void 0)}}var Gi=/^[a-z][\w-]*$/,Wn=["window","screen","menubar","notifications"];function X(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 de=(t,e)=>X(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function Bn(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 Pl(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=de(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=de(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=de(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=X(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=X(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(!Gi.test(i))throw new Error(`region name "${i}" must be lowercase letters, digits, - or _`);o===null?delete r[i]:r[i]=Bn(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=X(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(i.fps=X(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(i.maxPixels=de(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&&!Wn.includes(s)&&!n.regions?.[s])try{Bn(s)}catch{throw new Error(`buffer.region "${s}" is not a region \u2014 use ${[...Wn,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{ht as a,Ji as b,He as c,Gs as d,Xs as e,_a as f,Ra as g,Ca as h,bn as i,Ea as j,La as k,T as l,kn as m,w as n,eo as o,$t as p,io as q,It as r,oo as s,At as t,Rt as u,U as v,uo as w,go as x,fo as y,po as z,mo as A,Q as B,wo as C,To as D,Eo as E,Na as F,ci as G,Fa as H,Lo as I,Oo as J,Po as K,jo as L,Vo as M,Mo as N,Fo as O,Uo as P,Jo as Q,Ae as R,Yo as S,Zo as T,B as U,H as V,mi as W,qa as X,Ja as Y,Ya as Z,Za as _,ze as $,Qa as aa,Ce as ba,Te as ca,oe as da,fs as ea,ms as fa,sa as ga,De as ha,Le as ia,hs as ja,ys as ka,rn as la,ln as ma,ia as na,ws as oa,oa as pa,Rs as qa,Es as ra,Oe as sa,Ls as ta,cn as ua,E as va,Rn as wa,Cn as xa,il as ya,$i as za,On as Aa,yl as Ba,bl as Ca,Ui as Da,kl as Ea,jn as Fa,ae as Ga,ba as Ha,mn as Ia,Pe as Ja,We as Ka,Ia as La,vl as Ma,$l as Na,Il as Oa,Al as Pa,_l as Qa,Rl as Ra,Cl as Sa,Tl as Ta,El as Ua,Fn as Va,Un as Wa,Ol as Xa,Wn as Ya,Pl as Za};
|
|
154
|
+
//# sourceMappingURL=chunk-FWQVXZ5T.js.map
|