agentix-cli 0.79.2 → 0.79.3

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.
@@ -1,156 +0,0 @@
1
- import{a as we}from"./chunk-7XB2CVC3.js";import{t as $t,u as It}from"./chunk-2ZQ42Q4L.js";import{d as xt,e as vt}from"./chunk-AQASR6KR.js";import{b as ye,u as ft,w as Q,x as be,z as ke}from"./chunk-2ACZWM7F.js";import{c as kt,e as wt,f as St}from"./chunk-Y4CYQV7G.js";import{g as pt,h as mt,i as ht,k as yt,l as bt}from"./chunk-WVYOXM45.js";import{q as gt}from"./chunk-6SJTBTDG.js";import{E as dt,H as lr,r as Z,s as ct,t as ut,u as ar}from"./chunk-YKPISR5J.js";import{existsSync as cr,readdirSync as ur,readFileSync as dr,statSync as gr}from"fs";import{resolve as fr}from"path";function At(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 ee=new Map;function xo(t,e=1e3){if(!cr(t))return[];let n=ur(t).filter(i=>i.endsWith(".jsonl")).map(i=>{let o=fr(t,i);return{path:o,mtime:gr(o).mtimeMs}}).sort((i,o)=>o.mtime-i.mtime).slice(0,e),s=new Set(n.map(i=>i.path));for(let i of ee.keys())s.has(i)||ee.delete(i);let r=[];for(let{path:i,mtime:o}of n){let a=ee.get(i);if(a&&a.mtime===o){a.summary&&r.push(a.summary);continue}let l=pr(i,o);ee.set(i,{mtime:o,summary:l}),l&&r.push(l)}return r}function pr(t,e){try{let n=dr(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 mr={failStreak:3,disabledDays:30,missedFires:2,graceMs:15*6e4},w={routines:200,summary:160,filters:6,filterValue:60,text:120},hr=(t,e,n)=>{try{return gt(t,e,n)}catch{return null}},_t=864e5;function Ao(t){let e=t.now??Date.now(),n={...mr,...t.thresholds},s=t.nextFire??hr,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?Se(a.nextRun)??Se(s(a.schedule,new Date(e),c)):null,lastRun:d?{at:d.startedAt,status:d.status,summary:xr(d.status==="success"?void 0:d.errorSummary,w.summary)}:null,lastSuccessAt:l.find(f=>f.status==="success")?.startedAt??null,consecutiveFailures:Rt(u),sampledRuns:l.length,flags:[],attention:null};g.flags=Ct(g,u,a.schedule,c,null,e,n,s),r.push(Dt(g))}let i=new Map(At(t.workflows.map(a=>({id:a.id,name:a.title})),t.workflowRuns,e).map(a=>[a.id,a])),o=new Map;for(let a of t.workflowRuns){let l=o.get(a.workflowId);l?l.push(a):o.set(a.workflowId,[a])}for(let a of t.workflows){let l=a.nodes.find(_=>_.type.startsWith("trigger."));if(!l||l.type!=="trigger.cron"&&l.type!=="trigger.hook")continue;let c=l.config??{},u=a.state||"active",d=u==="active",g=(o.get(a.id)??[]).slice().sort((_,he)=>he.at-_.at),f=g.map(_=>({at:_.at,status:kr(_.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:Sr(c.filter,a)},agent:wr(a),enabled:d,state:u,nextRunAt:h&&d&&y?Se(s(y,new Date(e),C)):null,lastRun:p?{at:new Date(p.at).toISOString(),status:p.status}:null,lastSuccessAt:(()=>{let _=f.find(he=>he.status==="success");return _?new Date(_.at).toISOString():null})(),consecutiveFailures:Rt(f),sampledRuns:g.length,flags:[],attention:null},Y=Date.parse(a.updated||a.created||"");O.flags=h?Ct(O,f,y,C,Number.isFinite(Y)?Y:null,e,n,s):yr(O,i.get(a.id)?.state==="dormant",Number.isFinite(Y)?Y:null,e,n),r.push(Dt(O))}return r.sort(br).slice(0,w.routines)}function Rt(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 Ct(t,e,n,s,r,i,o,a){let l=[],c=e.length?e[0].at:null;if(!t.enabled){let g=Et(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 yr(t,e,n,s,r){let i=[],o=t.lastRun?Date.parse(t.lastRun.at):null;if(!t.enabled){let a=Et(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 Et(t,e,n,s){let r=Math.max(t??0,e??0);return r&&n-r<s.disabledDays*_t?null:{reason:"disabled-long",detail:r?`Disabled; no activity for ${Math.floor((n-r)/_t)} days`:"Disabled and never ran"}}function Dt(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 Tt={critical:0,warning:1,info:2};function br(t,e){let n=t.attention?Tt[t.attention]:3,s=e.attention?Tt[e.attention]:3;return n-s||Number(e.enabled)-Number(t.enabled)||t.name.localeCompare(e.name)}function kr(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 wr(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 Sr(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 Se(t){if(!t)return null;let e=t instanceof Date?t:new Date(t);return Number.isFinite(e.getTime())?e.toISOString():null}function $(t,e){return t.length<=e?t:t.slice(0,e-3)+"..."}function xr(t,e){return t===void 0?void 0:$(t,e)}import{createHash as vr,randomBytes as Lt}from"crypto";import{existsSync as $r,mkdirSync as Ir,readFileSync as Ar,writeFileSync as _r}from"fs";import{resolve as Rr,dirname as Cr}from"path";var xe="agx_live_",Dr=".agentx/tokens.json",Ot=class{file;constructor(e=process.cwd(),n=Dr){this.file=Rr(e,n)}load(){if(!$r(this.file))return[];try{return JSON.parse(Ar(this.file,"utf-8"))}catch{return[]}}save(e){Ir(Cr(this.file),{recursive:!0}),_r(this.file,JSON.stringify(e,null,2)+`
3
- `,"utf-8")}create(e){if(!e.name?.trim())throw new Error("Token name is required.");if(!Array.isArray(e.scopes)||e.scopes.length===0)throw new Error("At least one scope is required.");for(let o of e.scopes)if(!Tr(o))throw new Error(`Invalid scope: ${o}`);let n=Lt(32).toString("hex"),s=xe+n,r={id:"tok_"+Lt(4).toString("hex"),name:e.name.trim(),prefix:xe+n.slice(0,4),hash:Pt(s),scopes:[...e.scopes],createdAt:new Date().toISOString(),expiresAt:e.expiresInDays?new Date(Date.now()+e.expiresInDays*86400*1e3).toISOString():void 0},i=this.load();return i.push(r),this.save(i),{token:s,record:r}}list(){return this.load()}revoke(e){let n=this.load(),s=n.find(r=>r.id===e);return s?(s.revokedAt=new Date().toISOString(),this.save(n),s):null}isActive(e){let n=this.load().find(s=>s.id===e);return!!n&&!n.revokedAt&&!(n.expiresAt&&Date.parse(n.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(xe))return null;let n=Pt(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 To(t,e){return!!(t.scopes.includes(e)||e.startsWith("agent:")&&t.scopes.includes("agent:*")||e==="dashboard:read"&&t.scopes.includes("dashboard:write"))}function Tr(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 Pt(t){return"sha256:"+vr("sha256").update(t).digest("hex")}function Eo(t){let e=t.headers.authorization,n=Array.isArray(e)?e[0]:e;if(n&&n.toLowerCase().startsWith("bearer "))return n.slice(7).trim();if(t.url)try{let r=new URL(t.url,"http://localhost").searchParams.get("token");if(r)return r}catch{}return null}import{existsSync as $e,readdirSync as ss,readFileSync as is}from"fs";import{resolve as M}from"path";import{randomBytes as Vt}from"crypto";import{existsSync as Lr,mkdirSync as Or,readdirSync as Pr,readFileSync as jr,renameSync as Nt,unlinkSync as Mr,writeFileSync as Vr}from"fs";import{resolve as Ft}from"path";function jt(t){return[...t.account?["--account",t.account]:[],...t.store?["--store",t.store]:[]]}var Er=t=>t.trim().split(`
4
- `).pop()?.slice(0,300)||"no output";async function Mt(t,e,n,s=we){let r=await s(t.bin,[...jt(t),"send","text","--to",e,"--message",n,"--no-preview"],{timeoutMs:6e4});return r.code===0?{ok:!0}:{ok:!1,error:`wacli send failed: ${Er(r.stderr||r.stdout)}`}}async function Po(t,e,n,s,r=we){return(await r(t.bin,[...jt(t),"--read-only","media","download","--chat",e,"--id",n,"--output",s],{timeoutMs:12e4})).code===0}var Nr=2e3,Fr=t=>Mt(t.wacli,t.to,t.text);function ve(t){return Ft(t,".agentx","whatsapp-triage","drafts")}var Ur=t=>/^[a-z0-9-]{8,64}$/.test(t),te=(t,e)=>Ft(ve(t),`${e}.json`);function Ut(t,e){Or(ve(t),{recursive:!0});let n=te(t,e.id),s=`${n}.${process.pid}.tmp`;Vr(s,JSON.stringify(e,null,2)+`
5
- `,{mode:384}),Nt(s,n)}function Uo(t,e,n=Date.now()){let s=e.text.trim().slice(0,Nr);if(!s)throw new Error("empty draft");let r={...e,text:s,id:`${n.toString(36)}-${Vt(4).toString("hex")}`,status:"pending",created_at:new Date(n).toISOString()};return Ut(t,r),r}function ne(t,e){if(!Ur(e))return null;try{return JSON.parse(jr(te(t,e),"utf-8"))}catch{return null}}function Wt(t,e){let n=ve(t);return Lr(n)?Pr(n).filter(s=>s.endsWith(".json")).map(s=>ne(t,s.slice(0,-5))).filter(s=>!!s&&(!e||s.status===e)).sort((s,r)=>s.created_at.localeCompare(r.created_at)):[]}async function Bt(t,e,n,s={}){let r=ne(t,e);if(!r||r.status!=="pending")return{ok:!1,error:`no reply draft "${e}" is waiting`};let i=`${te(t,e)}.${process.pid}.${Vt(3).toString("hex")}.claim`;try{Nt(te(t,e),i)}catch{return{ok:!1,error:`reply draft "${e}" is already being decided`}}let o={...r,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString()};if(n==="no")o.status="rejected";else{let a=await(s.send??Fr)(r).catch(l=>({ok:!1,error:String(l?.message??l)}));a.ok?o.status="sent":(o.status="failed",o.error=a.error)}Ut(t,o);try{Mr(i)}catch{}return o.status==="failed"?{ok:!1,error:o.error??"send failed"}:{ok:!0,draft:o}}import{existsSync as Wr,mkdirSync as Br,readdirSync as Hr,readFileSync as zr,renameSync as Kr,writeFileSync as Gr}from"fs";import{resolve as Kt}from"path";function Ht(t,e){let n=t.list?` in the "${t.list}" list`:"",s=[`This card came from the operator's reminder "${t.title}"${n} (id ${t.id}).`];return s.push(e?`Do what the operator chose, then tick the reminder off: remindctl complete ${t.id}`:"Leave the reminder open; it will come back at a later check-in."),s}var zt=["discard","keep","pause","approve"],I={title:120,ask:300,recommend:300,source:500,note:500,pendingPerAgent:25},Xr={defaultExpiryDays:3,maxExpiryDays:30};function P(t){return Kt(t,".agentx","approvals")}var Jr=/^[a-z0-9][a-z0-9-]{0,80}$/;function Gt(t){return Jr.test(t)}function Xt(t,e){if(!Gt(e))throw new Error(`invalid card id: ${e}`);return Kt(P(t),`${e}.json`)}function qr(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 re(t,e){Br(P(t),{recursive:!0});let n=Xt(t,e.id),s=`${n}.${process.pid}.tmp`;Gr(s,JSON.stringify(e,null,2)+`
6
- `),Kr(s,n)}function W(t,e){if(!Gt(e))return null;try{return JSON.parse(zr(Xt(t,e),"utf-8"))}catch{return null}}function B(t,e){let n=P(t);if(!Wr(n))return[];let s=[];for(let r of Hr(n).filter(i=>i.endsWith(".json")&&!i.startsWith("_")).sort()){let i=W(t,r.slice(0,-5));i&&(!e||i.status===e)&&s.push(i)}return s}function k(t){return typeof t=="string"?t.replace(/\s+/g," ").trim():""}function Yr(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 Zr(t,e={}){let n=e.now??Date.now(),s=e.settings??Xr,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(!zt.includes(l))return{ok:!1,error:`if_silent must be one of ${zt.join(", ")}`};let c=Yr(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=kt(t);if(!d.ok)return d;let g,f=t.reply;return f&&typeof f=="object"&&k(f.channel)&&k(f.chatId)&&(g={channel:k(f.channel),chatId:k(f.chatId),...k(f.accountId)?{accountId:k(f.accountId)}:{}}),{ok:!0,card:{id:qr(n,r),title:r,ask:i,recommend:o,if_silent:l,expires:c.at,...u?{source:u}:{},raised_by:a,created_at:new Date(n).toISOString(),...g?{reply:g}:{},...d.value,...e.origin?{origin:e.origin}:{},status:"pending"}}}function Xo(t,e,n={}){let s=Zr(e,n);if(!s.ok)return s;let r=B(t,"pending").filter(i=>i.raised_by===s.card.raised_by).length;return r>=I.pendingPerAgent?{ok:!1,error:`${s.card.raised_by} already has ${r} cards waiting; wait for decisions before raising more`}:(re(t,s.card),s)}function Jt(t,e,n,s={}){let r=W(t,e);if(!r)return{ok:!1,error:`no card "${e}"`};if(r.status!=="pending")return{ok:!1,error:`card "${e}" is already ${r.status}`};let i=wt(r,n,s);if(!i.ok)return i;let o=k(s.note).slice(0,I.note),a={...r,status:"decided",verdict:n,decided_by:s.by??"operator",decided_at:new Date(s.now??Date.now()).toISOString(),...o?{note:o}:{},...i.choice?{choice:i.choice}:{},...i.text?{text:i.text}:{}};return re(t,a),{ok:!0,card:a}}function Jo(t,e=Date.now()){let n=[];for(let s of B(t,"pending")){if(Date.parse(s.expires)>e)continue;let r={...s,status:"expired",outcome:s.if_silent,decided_by:"expiry",decided_at:new Date(e).toISOString()};re(t,r),n.push(r)}return n}function qo(t){return B(t).filter(e=>e.status!=="pending"&&!e.agent_notified_at)}function Yo(t,e,n=Date.now()){let s=W(t,e);!s||s.agent_notified_at||re(t,{...s,agent_notified_at:new Date(n).toISOString()})}function Zo(t){let e=t.status==="decided"?t.verdict==="yes"?"The operator said YES.":"The operator said NO.":`Nobody answered before it expired, so the default applied: ${t.outcome??t.if_silent}.`,n=[`[Approval result] Your decision card "${t.title}" (${t.id}) is closed.`,`Question: ${t.ask}`,e];return t.status==="decided"&&t.verdict==="yes"&&n.push(...St(t)),t.note&&n.push(`Operator note: ${t.note}`),t.source&&n.push(`Source: ${t.source}`),t.origin&&n.push(...Ht(t.origin,t.status==="decided"&&t.verdict==="yes")),t.reply&&n.push(`You raised it from ${t.reply.channel} chat ${t.reply.chatId}; reply there if the requester should know.`),n.push("Act on this result now. Do not raise the same card again."),n.join(`
7
- `)}import{mkdirSync as Qr,readFileSync as es,renameSync as ts,writeFileSync as ns}from"fs";import{resolve as rs}from"path";function qt(t){return rs(P(t),"_state.json")}function j(t){try{let e=JSON.parse(es(qt(t),"utf-8"));return{snoozed:e&&typeof e.snoozed=="object"&&e.snoozed?e.snoozed:{},...typeof e?.lastDigest=="string"?{lastDigest:e.lastDigest}:{},...e?.popped&&typeof e.popped=="object"?{popped:e.popped}:{},...typeof e?.passAt=="string"?{passAt:e.passAt}:{}}}catch{return{snoozed:{}}}}function se(t,e){Qr(P(t),{recursive:!0});let n=qt(t),s=`${n}.${process.pid}.tmp`;ns(s,JSON.stringify(e,null,2)+`
8
- `),ts(s,n)}function Yt(t,e,n,s=Date.now()){let r=j(t),i={};for(let[o,a]of Object.entries(r.snoozed))Date.parse(a)>s&&(i[o]=a);i[e]=n.toISOString(),se(t,{...r,snoozed:i})}function ra(t,e){se(t,{...j(t),lastDigest:e})}function sa(t,e,n,s=Date.now()){let r=j(t),i=new Set(n),o={};for(let[a,l]of Object.entries(r.popped??{}))i.has(a)&&(o[a]=l);o[e]=new Date(s).toISOString(),se(t,{...r,popped:o})}function ia(t,e=Date.now()){se(t,{...j(t),popped:{},passAt:new Date(e).toISOString()})}var Zt=["card","schedule","memory","wiki","whatsapp"],os=280;function H(t,e=os){let n=t.replace(/\s+/g," ").trim();return n.length>e?`${n.slice(0,e-1)}\u2026`:n}function Qt(t){if(t.configPath)return M(t.configPath);let e=[M(t.root,"agentx.json"),M(t.root,".agentx","config.json")];return e.find(n=>$e(n))??e[0]}function Ie(t){return t.wikiDir?M(t.wikiDir):M(t.root,".agentx","wiki")}function as(t){return B(t.root,"pending").map(ls)}function ls(t){return{key:`card:${t.id}`,kind:"card",title:t.title,ask:t.ask,yes:`tell ${t.raised_by} yes`,no:`tell ${t.raised_by} no`,recommend:t.recommend,if_silent:t.if_silent,expires:t.expires,...t.source?{source:t.source}:{},raised_by:t.raised_by,created_at:t.created_at,...t.choices?{choices:t.choices,more:`agentx approvals popup card:${t.id}`}:{},...t.context||t.draft?{detail:H([t.context,t.draft?`Suggested message: ${t.draft}`:""].filter(Boolean).join(" \xB7 "))}:{}}}function cs(t){let e=Qt(t);if(!$e(e))return[];let n;try{n=JSON.parse(is(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?pt(o.schedule):"",u=o.schedule?`${c.charAt(0).toLowerCase()}${c.slice(1)} (${o.schedule})`:"no schedule",d=String(o.prompt??o.command??""),g=a.action==="create";r.push({key:`schedule:${i}`,kind:"schedule",title:g?`New schedule "${i}" for ${o.agent??"an agent"}`:`Delete schedule "${i}"`,ask:g?`Let ${o.agent??"the agent"} run this ${u}?`:`Remove the schedule "${i}" (${u})?`,yes:g?"enable it":"remove it",no:g?"drop the request":"keep the schedule",raised_by:String(a.requestedBy??"unknown"),created_at:String(a.requestedAt??""),detail:H(`${d}${g&&o.schedule?` \xB7 first run ${ht(mt(o.schedule,l,s),l)}`:""}`),more:"agentx schedule list"})}return r}function en(t){let e=M(t,".agentx","memory");return $e(e)?ss(e).filter(n=>n.endsWith(".jsonl")).map(n=>n.slice(0,-6)).sort():[]}function us(t){let e=en(t.root);if(e.length===0)return[];let n=new ye(t.root),s=[];for(let r of e)for(let i of n.held(r))s.push({key:`memory:${r}/${i.id}`,kind:"memory",title:`Fact ${r} learned from ${i.source.channel}`,ask:`Let ${r} use this fact in its prompts?`,yes:"use it",no:"keep it out for good",raised_by:r,created_at:i.createdAt,detail:H(i.content),more:`agentx memory facts held --agent ${r}`});return s}function ds(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 gs(t){return vt(Ie(t),"pending").map(e=>{let n=e.evidence;return{key:`wiki:${e.id}`,kind:"wiki",title:e.article.title,ask:e.replaces?`Update "${e.article.path}" in the shared wiki?`:`Add "${e.article.path}" to the shared wiki?`,yes:"write the article",no:"decline it",raised_by:n.agents.join(", ")||"wiki promote",created_at:e.createdAt,detail:H(`${ds(n)} ${e.article.content}`),more:`agentx wiki proposals show ${e.id}`}})}function fs(t){return Wt(t.root,"pending").map(e=>({key:`whatsapp:${e.id}`,kind:"whatsapp",title:`WhatsApp reply to ${e.chat_name||e.to}`,ask:`Send this to ${e.chat_name||e.to}? "${e.text}"`,yes:"send it on WhatsApp",no:"drop the draft",raised_by:e.agent,created_at:e.created_at,detail:H(`${e.triage}: ${e.summary}`),more:"agentx whatsapp triage log"}))}var tn={card:as,schedule:cs,memory:us,wiki:gs,whatsapp:fs};function ps(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 ha(t,e={}){let n=t.now??Date.now(),{snoozed:s}=j(t.root),r=[],i=[],o=0;for(let a of e.kinds??Zt){let l;try{l=tn[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(ps),{items:r,snoozed:o,errors:i}}function ms(t){let e=t.indexOf(":");if(e<=0)return null;let n=t.slice(0,e),s=t.slice(e+1);return!Zt.includes(n)||!s?null:{kind:n,ref:s}}function hs(t,e,n){switch(e){case"card":return W(t.root,n)?.status==="pending";case"wiki":return xt(Ie(t),n)?.status==="pending";case"whatsapp":return ne(t.root,n)?.status==="pending";default:return tn[e](t).some(s=>s.key===`${e}:${n}`)}}async function ya(t,e,n,s={}){let r=ms(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(!hs(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 Yt(t.root,e,d,a),{ok:!0,message:`${e} put off until ${d.toISOString()}`}}let c=n==="yes";switch(i){case"card":{let u=Jt(t.root,o,c?"yes":"no",{by:l,note:s.note,now:a,choice:s.choice,text:s.text});return u.ok?{ok:!0,message:`${e}: ${u.card.raised_by} will be told ${c?"yes":"no"}${u.card.choice?` (${u.card.choice})`:""}`}:u}case"schedule":{let u=await(c?yt:bt)(o,{configPath:Qt(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(!en(t.root).includes(d))return{ok:!1,error:`no memory for agent "${d}"`};let f=new ye(t.root);return f.held(d).some(p=>p.id===g)?(f.review(d,g,c?"approved":"rejected",l),{ok:!0,message:`${e} ${c?"approved: the agent may use it":"rejected: it stays out of prompts"}`}):{ok:!1,error:`fact "${g}" isn't waiting for review`}}case"wiki":{let u=Ie(t),d=c?$t(u,o,{by:l,force:s.force,now:a}):It(u,o,{by:l,reason:s.note,now:a});return d.ok?{ok:!0,message:c?`${d.proposal.article.path} written to the shared wiki`:`${e} rejected`}:d}case"whatsapp":{let u=await Bt(t.root,o,c?"yes":"no",{by:l,now:a,send:t.sendWhatsApp});return u.ok?{ok:!0,message:c?`${e}: sent to ${u.draft.chat_name||u.draft.to}`:`${e}: dropped, nothing sent`}:u}}}var nn=new Set(["127.0.0.1","::1","::ffff:127.0.0.1"]);function ka(t){return t==="/api/memory"||t.startsWith("/api/memory/")||t==="/approvals"||t.startsWith("/approvals/")||t==="/events/recent"||/^\/agents\/[^/]+\/events$/.test(t)||t==="/a2a/delegations"||t.startsWith("/a2a/delegations/")||t==="/traces"||t.startsWith("/traces/")||t==="/voice/history"||t.startsWith("/voice/history/")||t==="/voice/transcribe"||t==="/voice/speak"||t==="/app-files"||t==="/calls"||t.startsWith("/calls/")||t==="/webrtc/camera"||t.startsWith("/webrtc/camera/")}function wa(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 Sa(t){return nn.has(t)}function xa(t){if(t.foreignBrowser)return{allowed:!1,reason:"foreign-browser-origin"};if(t.enforcementDisabled)return{allowed:!0,reason:"disabled"};if(nn.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 va(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 $a(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 ie(t){return(Array.isArray(t)?t[0]:t)?.trim()??""}function ys(t){try{return new URL(t).host.toLowerCase()}catch{return null}}function bs(t=process.env){return new Set((t.AGENTX_ALLOWED_ORIGINS||"").split(",").map(e=>e.trim().replace(/\/+$/,"").toLowerCase()).filter(Boolean))}function Aa(t,e=bs()){let n=ie(t.origin);if(n){if(e.has(n.replace(/\/+$/,"").toLowerCase()))return"same-origin";let r=ys(n),i=[ie(t.host),ie(t["x-forwarded-host"])].filter(Boolean).map(o=>o.toLowerCase());return r&&i.includes(r)?"same-origin":"foreign"}let s=ie(t["sec-fetch-site"]).toLowerCase();return s==="cross-site"||s==="same-site"?"foreign":"none"}function _a(t){let e=(t||"GET").toUpperCase();return e!=="GET"&&e!=="HEAD"}import{existsSync as Rn,mkdirSync as Gs,readFileSync as Xs,renameSync as Js,writeFileSync as qs}from"fs";import{homedir as Ys}from"os";import{dirname as Zs,join as Qs}from"path";import{execFile as Cs,execFileSync as Ds}from"child_process";import{execFileSync as ks}from"child_process";import{existsSync as sn,mkdirSync as ws,readdirSync as Ss,readFileSync as on,renameSync as xs,writeFileSync as vs}from"fs";import{homedir as an}from"os";import{join as _e}from"path";var x="siri:",ln="com.apple.ttsbundle.gryphon-neural_",cn=t=>!!t&&t.startsWith(ln),$s=["/usr/bin/say","/usr/bin/defaults","/usr/bin/plutil"],Is=()=>{try{return ks("/usr/bin/defaults",["read","com.apple.Accessibility"],{stdio:"ignore",timeout:5e3}),!0}catch{return!1}},Ae;function Re(t={}){let e=t.platform!==void 0||t.exists!==void 0||t.prefDomain!==void 0;if(!e&&Ae!==void 0)return Ae;let{platform:n=process.platform,exists:s=sn,prefDomain:r=Is}=t,i=n==="darwin"&&$s.every(o=>s(o))&&r();return e||(Ae=i),i}var un=["/System/Library/AssetsV2/com_apple_MobileAsset_Trial_Siri_SiriTextToSpeech/purpose_auto","/System/Library/AssetsV2/com_apple_MobileAsset_UAF_Siri_TextToSpeech/purpose_auto"],dn={aaron:"male",damon:"male",daniel:"male",pierre:"male",samer:"male",arthur:"male",gordon:"male",martin:"male",nora:"female",simone:"female",marie:"female",soha:"female",martha:"female",catherine:"female",helena:"female",nicky:"female"},Ce=t=>dn[t.toLowerCase()]??null;function oe(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 As=/com\.apple\.siri\.tts\.voice\.([a-z]{2})_([A-Z]{2})\.([a-z]+)\.neural\.premium/g;function _s(t){let e=new Map;for(let n of t)for(let[,s,r,i]of n.matchAll(As)){let o=`${s}-${r}`,a=`${ln}${i}_${o}_premium`;e.has(a)||e.set(a,{id:a,name:i[0].toUpperCase()+i.slice(1),locale:o,quality:"premium",gender:dn[i]??null,siri:!0})}return[...e.values()]}function ae(t=un,e={}){if(!Re(e))return[];let n=[];for(let s of t){let r;try{r=Ss(s)}catch{continue}for(let i of r)try{n.push(on(_e(s,i,"Info.plist"),"latin1"))}catch{}}return _s(n)}var rn=`#!/bin/sh
9
- # Written by agentx; shared by the daemon and AgentX Voice. Do not edit.
10
- # siri-say.sh [voice] < text speak one line. A Siri voice id switches
11
- # the OS default for it; any other id is
12
- # passed to say -v.
13
- # siri-say.sh --stop silence the line speaking, drop the queue.
14
- # siri-say.sh --restore put back a voice a killed line left switched.
15
- # AGENTX_SAY_RATE=<words a minute> sets the speed; unset, say's own.
16
- D=com.apple.Accessibility K=SpokenContentDefaultVoiceSelectionsByLanguage
17
- dir="$HOME/.agentx/voice" lock="$HOME/.agentx/voice/siri.lock" saved="$HOME/.agentx/voice/siri-saved.plist"
18
- stops="$dir/stop"
19
- read_s=\${AGENTX_SAY_READ_S:-5} stale_s=\${AGENTX_SAY_STALE_S:-30} max_s=\${AGENTX_SAY_MAX_S:-300}
20
- assets=\${AGENTX_SIRI_ASSET_DIRS:-"${un.join(" ")}"}
21
- if [ "$1" = --stop ]; then
22
- mkdir -p "$dir" || exit 1
23
- # Queued lines see this change and drop. The owner's trap stops say,
24
- # restores the voice, and frees the lock.
25
- echo "$$ $(date +%s)" > "$stops"
26
- owner=$(cat "$lock/pid" 2>/dev/null)
27
- [ -n "$owner" ] && kill "$owner" 2>/dev/null
28
- exit 0
29
- fi
30
- mode=speak
31
- [ "$1" = --restore ] && { mode=restore; set --; }
32
- case "$1" in com.apple.ttsbundle.gryphon-neural_*) siri=$1 voice= ;; *) siri= voice=$1 ;; esac
33
- rate=\${AGENTX_SAY_RATE:-}
34
- case "$rate" in *[!0-9]*) rate= ;; esac
35
- case "$siri" in *[!A-Za-z0-9._-]*) echo "bad voice id" >&2; exit 2;; esac
36
- # Not macOS, or no pref tools: speak as is and never touch a pref.
37
- if [ "$(uname)" != Darwin ] || ! command -v defaults >/dev/null || ! command -v plutil >/dev/null; then
38
- [ "$mode" = restore ] && exit 0
39
- if [ -n "$voice" ]; then exec say \${rate:+-r "$rate"} -v "$voice"; else exec say \${rate:+-r "$rate"}; fi
40
- fi
41
- mkdir -p "$dir" || exit 1
42
- mine=$(cat "$stops" 2>/dev/null)
43
- stopped() { [ "$(cat "$stops" 2>/dev/null)" != "$mine" ]; }
44
- txt=$(mktemp "\${TMPDIR:-/tmp}/agentx-say.XXXXXX") || exit 1
45
- say_pid= dog=
46
- restore() {
47
- [ -f "$saved" ] || return 0
48
- if [ -s "$saved" ]; then defaults write $D $K "$(cat "$saved")"; else defaults delete $D $K 2>/dev/null; fi
49
- rm -f "$saved"
50
- }
51
- finish() {
52
- [ -n "$say_pid" ] && kill "$say_pid" 2>/dev/null
53
- [ -n "$dog" ] && { pkill -P "$dog" 2>/dev/null; kill "$dog" 2>/dev/null; }
54
- restore; rm -rf "$lock"; rm -f "$txt"; exit "$1"
55
- }
56
- drop() { rm -f "$txt"; exit 75; }
57
- # A Siri voice whose asset macOS purged: switching to it makes the OS
58
- # speak a fallback of its own (Eloquence Flo), so leave the pref alone.
59
- if [ -n "$siri" ]; then
60
- s=\${siri#com.apple.ttsbundle.gryphon-neural_} ; name=\${s%%_*} ; s=\${s#*_} ; loc=$(printf %s "\${s%%_*}" | tr - _)
61
- found=
62
- for a in $assets; do
63
- grep -aqs "com.apple.siri.tts.voice.$loc.$name.neural.premium" "$a"/*/Info.plist && { found=1; break; }
64
- done
65
- [ -z "$found" ] && { echo "Siri voice $siri is not installed; speaking with the OS default" >&2; siri=; }
66
- fi
67
- # The whole text first, before the lock: a writer that never closes stdin
68
- # must not hold up every other speaker.
69
- [ "$mode" = restore ] && exec 0</dev/null
70
- exec 3<&0 0</dev/null
71
- cat <&3 > "$txt" & cat_pid=$!
72
- exec 3<&-
73
- n=0
74
- while kill -0 "$cat_pid" 2>/dev/null; do
75
- if [ $n -ge $((read_s * 10)) ]; then
76
- kill "$cat_pid" 2>/dev/null; echo "stdin never closed; nothing said" >&2; rm -f "$txt"; exit 3
77
- fi
78
- sleep 0.1; n=$((n + 1))
79
- done
80
- # One speaker at a time. A lock whose owner died is taken over. A line
81
- # that waits past stale_s, or that a stop overtook, is dropped unsaid.
82
- n=0
83
- while ! mkdir "$lock" 2>/dev/null; do
84
- stopped && drop
85
- if [ $n -ge $((stale_s * 10)) ]; then echo "waited \${stale_s}s for the speaker; dropped" >&2; drop; fi
86
- owner=$(cat "$lock/pid" 2>/dev/null)
87
- if [ -n "$owner" ] && ! kill -0 "$owner" 2>/dev/null; then rm -rf "$lock"
88
- elif [ -z "$owner" ] && [ -n "$(find "$lock" -maxdepth 0 -mmin +1 2>/dev/null)" ]; then rm -rf "$lock"
89
- else sleep 0.1; n=$((n + 1)); fi
90
- done
91
- echo $$ > "$lock/pid"
92
- trap 'finish 143' TERM INT HUP
93
- stopped && finish 75
94
- [ "$mode" = restore ] && finish 0
95
- restore
96
- if [ -n "$siri" ]; then
97
- lang=$(defaults read -g AppleLanguages 2>/dev/null | sed -n '2s/^[^A-Za-z]*\\([A-Za-z]*\\).*/\\1/p')
98
- defaults export $D - 2>/dev/null | plutil -extract $K xml1 -o "$saved.tmp" - 2>/dev/null || : > "$saved.tmp"
99
- mv "$saved.tmp" "$saved"
100
- defaults write $D $K -array "\${lang:-en}" "{ _type = \\"Speech.VoiceSelection\\"; _version = 0; voiceId = \\"$siri\\"; }"
101
- fi
102
- # A watchdog: no line runs past its length's worth of speech (a hung say
103
- # held the lock for minutes), capped at max_s.
104
- limit=$((5 + $(wc -w < "$txt") * 6 / 10))
105
- [ $limit -gt $max_s ] && limit=$max_s
106
- if [ -n "$voice" ]; then say \${rate:+-r "$rate"} -v "$voice" -f "$txt" & else say \${rate:+-r "$rate"} -f "$txt" & fi
107
- say_pid=$!
108
- ( sleep "$limit"; echo "say ran past \${limit}s; stopped" >&2; kill "$say_pid" 2>/dev/null ) & dog=$!
109
- wait "$say_pid"
110
- status=$?
111
- say_pid=
112
- finish $status
113
- `,Rs=(t=an())=>_e(t,".agentx","voice","siri-say.sh");function gn(t=an()){let e=Rs(t);return sn(e)&&on(e,"utf8")===rn||(ws(_e(t,".agentx","voice"),{recursive:!0}),vs(`${e}.tmp`,rn,{mode:493}),xs(`${e}.tmp`,e)),e}var fn=`ObjC.import("AVFoundation")
114
- const vs = $.AVSpeechSynthesisVoice.speechVoices, out = []
115
- for (let i = 0; i < vs.count; i++) {
116
- const v = vs.objectAtIndex(i)
117
- out.push([v.identifier.js, v.name.js, v.language.js, Number(v.quality), Number(v.gender)].join("\\t"))
118
- }
119
- out.join("\\n")`,Ts=new Set(["Fred","Kathy","Ralph","Junior"]),Es={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 pn(t){let e=[];for(let n of t.split(`
120
- `)){let[s,r,i,o,a]=n.split(" ");!s||!r||!i||s.includes(".siri_")||s.startsWith("com.apple.speech.synthesis.voice.")&&!Ts.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":Es[r]??null})}return e}var Ls=10*60*1e3,ja=60*1e3,V=null,De=!1;function Te(t=Date.now(),e=Ls){if(process.platform!=="darwin")return[];if(V)t-V.at>e&&!De&&(De=!0,Cs("osascript",["-l","JavaScript","-e",fn],{timeout:1e4},(n,s)=>{De=!1,n||(V={at:Date.now(),voices:[...pn(String(s)),...ae()]})}));else try{V={at:t,voices:[...pn(Ds("osascript",["-l","JavaScript","-e",fn],{encoding:"utf8",timeout:1e4})),...ae()]}}catch(n){Ee(`[voice] could not list system voices: ${String(n?.message??n).split(`
121
- `)[0]}`),V={at:t,voices:ae()}}return V.voices}var Ee=t=>process.stderr.write(t+`
122
- `),le=new Set;function Ma(t){Ee=t}function E(t,e){le.has(t)||(le.add(t),Ee(e))}function yn(t){for(let e of le)t(e)&&le.delete(e)}var bn=()=>{};function Va(t){bn=t}function kn(t){try{bn(t)}catch(e){E("missing-hook",`[voice] missing-voice check failed: ${e?.message??e}`)}}var Os={premium:3,enhanced:2,standard:1},Ps=new Set(["Grandma","Grandpa"]);function mn(t){let e=t.id.startsWith("com.apple.voice.")?2:t.id.startsWith("com.apple.eloquence.")&&!Ps.has(t.name)?1:0;return Os[t.quality]*10+e}var N=t=>t.toLowerCase().split(/[-_]/)[0],hn=t=>t.id.startsWith("com.apple.voice.");function Le(t,e,n,s=new Set){let r=z(t.filter(a=>!a.siri&&N(a.locale)===N(e)),e);if(r.some(hn)&&(r=r.filter(hn)),n==="female"||n==="male"){let a=r.filter(l=>l.gender===n);a.length&&(r=a)}if(!r.length)return null;let i=r.filter(a=>a.quality===r[0].quality),o=new Set([...s].map(a=>a.toLowerCase()));return i.find(a=>!o.has(a.name.toLowerCase()))??i[0]}function z(t,e="en"){let n=e.toLowerCase().replace("_","-"),s=N(e),r=t.filter(i=>N(i.locale)===s);return(r.length?r:t).slice().sort((i,o)=>mn(o)-mn(i)||+(o.locale.toLowerCase()===n)-+(i.locale.toLowerCase()===n)||i.name.localeCompare(o.name)||i.locale.localeCompare(o.locale))}function K(t,e,n="en"){let s=t.trim();if(!s)return null;let r=e.find(c=>c.id===s);if(r)return r;if(s.toLowerCase().startsWith(x)){let c=s.slice(x.length).trim().toLowerCase(),u=z(e.filter(g=>g.siri&&g.name.toLowerCase()===c),n)[0];if(u||!c)return u??null;let d=K(c,e.filter(g=>N(g.locale)===N(n)),n);return d&&E(`siri:${c}`,`[voice] Siri voice "${c}" is not installed; speaking with ${d.name} (${d.locale}) instead.`),d}e=e.filter(c=>!c.siri);let i=/^(.+?)\s*\((premium|enhanced)\)$/i.exec(s),o=(i?i[1]:s.replace(/\s*\(.*\)\s*$/,"")).trim().toLowerCase(),a=z(e.filter(c=>c.name.toLowerCase()===o),n);return(i?a.find(c=>c.quality===i[2].toLowerCase()):void 0)??a[0]??null}function wn(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}ct();var Oe="system",js=t=>t.trim().toLowerCase()===Oe,Ms="21m00Tcm4TlvDq8ikWAM";function Pe(t,e,n={},s=Te()){let r=e[t],i=r?.name||t,o=r?.voice,a=Me(e,n,s).get(t)??null,l=Us(t,o?.system,o?.gender,n,s);return{agentId:t,name:i,provider:o?.provider??n.provider??"system",elevenlabsVoiceId:o?.elevenlabsVoiceId||null,systemVoice:a?.id??null,systemVoiceName:a?ue(a):null,systemByLanguage:l,fallback:(n.fallback??"system")==="system",gender:o?.gender??null,style:o?.style||null,intro:o?.intro||Bs(i,r?.systemPrompt),...o?.rate?{rate:o.rate}:{},...o?.priority?{priority:o.priority}:{}}}var ue=t=>`${t.name}${t.siri?" (Siri)":t.quality==="standard"?"":` (${t.quality[0].toUpperCase()}${t.quality.slice(1)})`} ${t.locale}`;function Vs(t,e,n,s){if(!e||!n.length)return null;let r=K(e,n,s);return r||(E(`${t}:${e}`,`[voice] ${t}: system voice "${e}" is not installed; using the next choice. Run \`agentx voice list\` to see installed voices.`),kn(e)),r}function $n(t,e){let n=t.trim();if(n.toLowerCase().startsWith(x))return{locale:e,gender:Ce(n.slice(x.length).trim())};let s=oe(n);return s?{locale:s.locale,gender:Ce(s.name)}:{locale:/^com\.apple\.voice\.[a-z]+\.([a-z]{2}-[A-Z]{2})\./.exec(n)?.[1]??e,gender:null}}var In=t=>t.toLowerCase().split(/[-_]/)[0],Sn=(t,e)=>typeof t=="string"?t:t?.[In(e)];function ce(t,e,n,s){if(e!==void 0)return js(e)?null:Vs(t,e,n,s)??void 0}var je=(t,e)=>!t||!t.gender||t.gender==="neutral"||!e||e==="neutral"||t.gender===e;function Ns(t,e,n,s=new Set){let r=e.locale??"en",i=new Map,o=[],a=ce("voice.system",Sn(e.system,r),n,r),l=()=>new Set([...s,...[...i.values()].flatMap(u=>u?[u.name]:[])]);for(let u of t){let d=Sn(u.system,r),g=ce(u.id,d,n,r),f=g!==void 0?g:d!==void 0&&n.length?Fs(u,d,r,a,n,l()):a!==void 0&&je(a,u.gender)?a:void 0;f!==void 0?i.set(u.id,f):o.push({id:u.id,gender:u.gender??null})}let c=l();for(let[u,d]of wn(o,z(n.filter(g=>!g.siri),r),c))i.set(u,d);return i}function Fs(t,e,n,s,r,i){for(let a of t.fallbacks??[]){let l=ce(`${t.id}.fallbacks`,a,r,n);if(l!==void 0)return l}if(s!==void 0&&je(s,t.gender))return s;let o=$n(e,n);return Le(r,o.locale,t.gender??o.gender,i)??void 0}function Us(t,e,n,s,r){if(typeof e=="string")return{};let i={},o=(a,l,c)=>{if(!(!l||typeof l=="string"))for(let[u,d]of Object.entries(l)){let g=ce(`${a}.${u}`,d,r,u);g===void 0&&r.length&&(g=Le(r,u,n??$n(d,u).gender)??void 0),g!==void 0&&c(g)&&(i[In(u)]=g)}};return o("voice.system",s.system,a=>je(a,n)),o(t,e,()=>!0),i}function Ba(t,e){let n=e?Z(e):null;if(!n||!(n in t.systemByLanguage))return t;let s=t.systemByLanguage[n];return{...t,systemVoice:s?.id??null,systemVoiceName:s?ue(s):null}}function Me(t,e={},n=Te()){let s=Object.entries(t).map(([r,i])=>({id:r,system:i.voice?.system,gender:i.voice?.gender,fallbacks:i.voice?.fallbacks}));return Ns(s,e,n)}function Ve(t,e){let n={provider:t.provider,elevenlabs:Ws(e,t.elevenlabsVoiceId),system:t.systemVoice,fallback:t.fallback},s=Object.entries(t.systemByLanguage??{});return s.length&&(n.languages=Object.fromEntries(s.map(([r,i])=>[r,i?.id??null]))),t.rate&&t.rate!==1&&(n.rate=t.rate),t.priority&&t.priority!=="normal"&&(n.priority=t.priority),n}function Ws(t,e){return t||e||process.env.AGENTX_VOICE_ID||Ms}function Bs(t,e){let n=(e??"").split(/(?<=\.)\s/)[0]??"",s=/^You are (.+?)\.?$/i.exec(n.trim());if(!s)return`Hello, this is ${t}.`;let r=s[1].replace(/\s*\([^)]*\)/g,"").trim(),[i,...o]=r.split(/,\s*/),a=o.join(", ");return a&&i.toLowerCase()===t.toLowerCase()?`Hello, this is ${t}, ${a}.`:!/^an? /i.test(r)&&r.toLowerCase().includes(t.toLowerCase())?`Hello, this is ${r}.`:`Hello, this is ${t}, ${r}.`}var Hs=8*60*60*1e3,zs=500,xn=class{constructor(e=Hs){this.gapMs=e}lastSpoke=new Map;needsIntro(e,n,s=Date.now()){let r=this.lastSpoke.get(vn(e,n));return r===void 0||s-r>this.gapMs}spoke(e,n,s=Date.now()){let r=vn(e,n);this.lastSpoke.delete(r),this.lastSpoke.set(r,s),this.lastSpoke.size>zs&&this.lastSpoke.delete(this.lastSpoke.keys().next().value)}},vn=(t,e)=>`${t}\0${e}`;function An(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 Ha(t,e,n,s={}){let r=e[t],i=Pe(t,e,s),o=(r?.systemPrompt??"").split(/\n\s*\n/)[0].slice(0,600).trim();return{agentId:t,name:i.name,voice:Ve(i),persona:o||`You are ${i.name}.`,introLine:An(i,n)}}var Ks="[VOICE MODE] This question arrived by voice and your reply will be spoken aloud by a TTS engine. Answer in two or three short sentences. Plain language, no markdown, no code blocks, no bullet points, no URLs. Speak conversationally.";function za(t){let e=t;if(e?.channel!=="voice"||!e.voice||typeof e.voice!="object")return;let n=i=>typeof i=="string"?i.replace(/\s+/g," ").slice(0,200):"",s=n(e.voice.intro),r={agentId:"",name:"",provider:"system",elevenlabsVoiceId:null,systemVoice:null,systemVoiceName:null,systemByLanguage:{},fallback:!0,gender:null,style:n(e.voice.style)||null,intro:s||"Hello."};return`${Ks}
123
- ${An(r,e.voice.introduce===!0&&!!s)}`}var ei="System Settings \u203A Accessibility \u203A Spoken Content \u203A System voice \u203A Manage Voices",Cn=(t=Ys())=>Qs(t,".agentx","voice","health.json");function ti(t,e,n){let s=t.trim();if(!s||s.toLowerCase()===Oe)return!0;if(s.toLowerCase().startsWith(x)){let r=s.slice(x.length).trim().toLowerCase();return e.some(i=>i.siri&&i.name.toLowerCase()===r)}return K(s,e,n)!==null}function ni(t){let e=t.voice?.locale??"en",n=[],s=(r,i)=>{if(typeof i=="string")n.push({owner:r,name:i,locale:e,perLanguage:!1});else for(let[o,a]of Object.entries(i??{}))n.push({owner:r,name:a,locale:o,perLanguage:!0})};s("voice.system",t.voice?.system);for(let[r,i]of Object.entries(t.agents))(i.voice?.provider??t.voice?.provider??"system")!=="system"&&t.voice?.fallback==="none"||s(r,i.voice?.system);return n}function ri(t,e){if(!e.length)return[];let n=new Map,s;for(let{owner:r,name:i,locale:o,perLanguage:a}of ni(t)){if(ti(i,e,o))continue;s??=Me(t.agents,t.voice,e);let l=n.get(i)??{voice:i,agents:[],speaksWith:{}};l.agents.includes(r)||l.agents.push(r);let c=s.get(r);r!=="voice.system"&&!a&&(l.speaksWith[r]=c?ue(c):"the OS default voice"),n.set(i,l)}return[...n.values()]}function Ne(t){let e=oe(t);if(e)return`Siri ${e.name[0].toUpperCase()}${e.name.slice(1)} (${e.locale})`;if(t.toLowerCase().startsWith(x)){let n=t.slice(x.length).trim();return`Siri ${n[0]?.toUpperCase()??""}${n.slice(1)}`}return t}function si(t){let e=t.map(n=>{let s=n.agents.map(r=>n.speaksWith[r]?`${r} (now ${n.speaksWith[r]})`:r).join(", ");return`\u2022 ${Ne(n.voice)}: ${s}`});return{title:t.length===1?"AgentX: a voice is not installed":`AgentX: ${t.length} voices are not installed`,message:`${e.join(`
124
- `)}
125
- Reinstall in ${ei}. Agents switch back on their own once it is installed.`}}function ii(t=Cn()){if(!Rn(t))return null;try{let e=JSON.parse(Xs(t,"utf8"));return e&&Array.isArray(e.missing)?e:null}catch{return null}}function oi(t,e){Gs(Zs(t),{recursive:!0}),qs(`${t}.tmp`,JSON.stringify(e,null,2)+`
126
- `),Js(`${t}.tmp`,t)}var _n=class{constructor(e){this.deps=e}running=!1;missingNow=!1;hasMissing(){return this.missingNow}async check(e,n,s=new Date){if(this.running||!n.length)return null;this.running=!0;try{let r=this.deps.file??Cn(),i=new Map((ii(r)?.missing??[]).map(d=>[d.voice,d])),o=ri(e,n),a=o.map(d=>({...d,since:i.get(d.voice)?.since??s.toISOString(),...i.get(d.voice)?.notifiedAt?{notifiedAt:i.get(d.voice).notifiedAt}:{}})),l=[...i.keys()].filter(d=>!o.some(g=>g.voice===d));for(let d of l)this.deps.log(`[voice] ${Ne(d)} is installed again; its agents speak with it again`);l.length&&yn(d=>l.some(g=>d===g||d.endsWith(`:${g}`)));let c=a.filter(d=>!d.notifiedAt);if(c.length){let{title:d,message:g}=si(c);try{await this.deps.notify(d,g);for(let f of c)f.notifiedAt=s.toISOString();this.deps.log(`[voice] told the owner: ${c.map(f=>Ne(f.voice)).join(", ")} not installed`)}catch(f){this.deps.log(`[voice] could not send the missing-voice notice: ${f?.message??f}`)}}this.missingNow=a.length>0;let u={checkedAt:s.toISOString(),missing:a};return(!Rn(r)||JSON.stringify(a)!==JSON.stringify([...i.values()]))&&oi(r,u),u}finally{this.running=!1}}};import{readFileSync as Ue,writeFileSync as Pn,existsSync as We,readdirSync as mi,statSync as hi}from"fs";import{resolve as Be,join as yi}from"path";import{existsSync as Dn,mkdirSync as ai,readFileSync as li,writeFileSync as Tn}from"fs";import{dirname as ci,resolve as En}from"path";import{z as m}from"zod";var ui=m.object({type:m.enum(["gitlab","github"]),host:m.string().optional(),project:m.string(),iid:m.number().int().positive(),url:m.string()}),di=m.object({id:m.string(),title:m.string(),description:m.string().optional(),assignee:m.string().optional(),labels:m.array(m.string()).default([]),milestone:m.string().optional(),status:m.enum(["todo","doing","blocked","done"]).default("todo"),priority:m.number().int().optional(),estimatedSeconds:m.number().int().optional(),source:ui.optional(),importedAt:m.string().optional(),createdAt:m.string(),updatedAt:m.string(),blocker:m.string().optional(),doneNote:m.string().optional()}),gi=m.object({version:m.literal(1),items:m.array(di).default([])}),de=class{constructor(e){this.path=e}jsonPath(){return En(process.cwd(),this.path).replace(/\.md$/i,".json")}mdPath(){return En(process.cwd(),this.path).replace(/\.json$/i,".md")}exists(){return Dn(this.jsonPath())}load(){let e=this.jsonPath();if(!Dn(e))return{version:1,items:[]};let n=li(e,"utf-8");try{return gi.parse(JSON.parse(n))}catch(s){throw new Error(`Backlog file invalid (${e}): ${s.message}`)}}save(e){let n=this.jsonPath();ai(ci(n),{recursive:!0}),Tn(n,JSON.stringify(e,null,2)+`
127
- `),Tn(this.mdPath(),this.toMarkdown(e))}list(){return this.load().items}findById(e){return this.list().find(n=>n.id===e)}add(e){let n=this.load();if(n.items.some(i=>i.id===e.id))throw new Error(`backlog item ${e.id} already exists`);let s=new Date().toISOString(),r={...e,labels:e.labels??[],status:e.status??"todo",createdAt:e.createdAt??s,updatedAt:s};return n.items.push(r),this.save(n),r}addMany(e){let n=this.load(),s=new Set(n.items.map(o=>o.id)),r=new Date().toISOString(),i=[];for(let o of e){if(s.has(o.id))continue;let a={...o,labels:o.labels??[],status:o.status??"todo",createdAt:o.createdAt??r,updatedAt:r};n.items.push(a),i.push(a),s.add(a.id)}return i.length&&this.save(n),i}update(e,n){let s=this.load(),r=s.items.findIndex(o=>o.id===e);if(r<0)throw new Error(`backlog item ${e} not found`);let i={...s.items[r],...n,id:s.items[r].id,createdAt:s.items[r].createdAt,updatedAt:new Date().toISOString()};return s.items[r]=i,this.save(s),i}remove(e){let n=this.load(),s=n.items.length;return n.items=n.items.filter(r=>r.id!==e),n.items.length===s?!1:(this.save(n),!0)}toMarkdown(e){let n=["# Backlog","","_Generated from `backlog.json`. Do not edit by hand \u2014 use `agentx backlog` commands._",""],s={doing:[],blocked:[],todo:[],done:[]};for(let i of e.items)s[i.status].push(i);let r=[["doing","Doing"],["blocked","Blocked"],["todo","To Do"],["done","Done"]];for(let[i,o]of r)if(s[i].length){n.push(`## ${o}`,"");for(let a of s[i]){let l=i==="done"?"x":" ",c=a.assignee?`@${a.assignee} `:"",u=a.estimatedSeconds?` [time: ${Math.round(a.estimatedSeconds/60)}m]`:"",d=a.source?` (${a.source.type}: ${a.source.project}#${a.source.iid})`:"";n.push(`- [${l}] ${c}${a.title}${u}${d}`),a.source?.url&&n.push(` - <${a.source.url}>`),a.labels.length&&n.push(` - labels: ${a.labels.join(", ")}`),a.milestone&&n.push(` - milestone: ${a.milestone}`),a.blocker&&n.push(` - BLOCKED: ${a.blocker}`)}n.push("")}return n.join(`
128
- `)}};function rl(t){return`${t.type}:${t.project}:${t.iid}`}function Ln(t,e,n){let s=[];if(e.type==="gitlab"){let r=n.channels.gitlab?.agentMappings??[];for(let i of t){let o=r.find(a=>a.agentId===i);o?.gitlabUsernames?.length?s.push(o.gitlabUsernames[0]):s.push(i)}}else if(e.type==="github"){let r=n.channels.github?.agentMappings??[];for(let i of t){let o=r.find(a=>a.agentId===i);o?.githubUsernames?.length?s.push(o.githubUsernames[0]):s.push(i)}}return s}async function Fe(t,e,n,s=()=>{}){return t.source?t.source.type==="gitlab"?fi(t.source,e,n,s):t.source.type==="github"?pi(t.source,e,n,s):{ok:!1,error:`unknown source.type ${t.source.type}`,attempts:[]}:{ok:!0,attempts:[]}}async function fi(t,e,n,s){let r=n.channels.gitlab,i=r?.token,o=r?.host||(t.host?`https://${t.host}`:void 0);if(!i||!o)return{ok:!1,error:"gitlab token/host not configured",attempts:[]};let a=[],l=async(f,p={})=>fetch(`${o}/api/v4${f}`,{...p,headers:{"PRIVATE-TOKEN":i,"Content-Type":"application/json",...p.headers||{}}}),c=encodeURIComponent(t.project),u;e.assigneeUsernames!==void 0&&(u=(await Promise.all(e.assigneeUsernames.map(async p=>{try{let h=await fetch(`${o}/api/v4/users?username=${encodeURIComponent(p)}`,{headers:{"PRIVATE-TOKEN":i}});if(!h.ok)return null;let y=await h.json();return Array.isArray(y)&&y[0]?.id?y[0].id:null}catch{return null}}))).filter(p=>typeof p=="number"));let d;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")d=0;else try{let f=await l(`/projects/${c}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);if(f.ok){let p=await f.json();Array.isArray(p)&&p[0]?.id&&(d=p[0].id)}}catch(f){s(`[backlog-sync] milestone lookup failed: ${f.message}`)}let g={};if(e.title!==void 0&&(g.title=e.title),e.description!==void 0&&(g.description=e.description),e.labels!==void 0&&(g.labels=e.labels.join(",")),e.addLabels?.length&&(g.add_labels=e.addLabels.join(",")),e.removeLabels?.length&&(g.remove_labels=e.removeLabels.join(",")),u!==void 0&&(g.assignee_ids=u),d!==void 0&&(g.milestone_id=d),e.state&&(g.state_event=e.state==="closed"?"close":"reopen"),Object.keys(g).length)try{let f=await l(`/projects/${c}/issues/${t.iid}`,{method:"PUT",body:JSON.stringify(g)});if(a.push({kind:"PUT issue",ok:f.ok,status:f.status}),!f.ok){let p=await f.text().catch(()=>"");return{ok:!1,attempts:a,error:`PUT issue ${f.status}: ${p.slice(0,200)}`,url:t.url}}}catch(f){return a.push({kind:"PUT issue",ok:!1,error:f.message}),{ok:!1,attempts:a,error:f.message,url:t.url}}if(e.note)try{let f=await l(`/projects/${c}/issues/${t.iid}/notes`,{method:"POST",body:JSON.stringify({body:e.note})});a.push({kind:"POST note",ok:f.ok,status:f.status})}catch(f){a.push({kind:"POST note",ok:!1,error:f.message})}return{ok:a.every(f=>f.ok),attempts:a,url:t.url}}async function pi(t,e,n,s){let i=n.channels.github?.token;if(!i)return{ok:!1,error:"github token not configured",attempts:[]};let o=[],a=async(g,f={})=>fetch(`https://api.github.com${g}`,{...f,headers:{Authorization:`Bearer ${i}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28",...f.headers||{}}}),l=t.project,c;if(e.milestoneTitle!==void 0)if(e.milestoneTitle===null||e.milestoneTitle==="")c=null;else try{let g=await a(`/repos/${l}/milestones?state=all&per_page=100`);if(g.ok){let f=await g.json(),p=Array.isArray(f)?f.find(h=>h.title===e.milestoneTitle):null;p?.number&&(c=p.number)}}catch(g){s(`[backlog-sync] github milestone lookup failed: ${g.message}`)}let u;if(e.labels!==void 0)u=e.labels;else if(e.addLabels?.length||e.removeLabels?.length)try{let g=await a(`/repos/${l}/issues/${t.iid}`);if(g.ok){let f=await g.json(),p=Array.isArray(f.labels)?f.labels.map(y=>typeof y=="string"?y:y.name):[],h=new Set([...p,...e.addLabels??[]]);for(let y of e.removeLabels??[])h.delete(y);u=[...h]}}catch(g){s(`[backlog-sync] github label fetch failed: ${g.message}`)}let d={};if(e.title!==void 0&&(d.title=e.title),e.description!==void 0&&(d.body=e.description),u!==void 0&&(d.labels=u),e.assigneeUsernames!==void 0&&(d.assignees=e.assigneeUsernames),c!==void 0&&(d.milestone=c),e.state&&(d.state=e.state),Object.keys(d).length)try{let g=await a(`/repos/${l}/issues/${t.iid}`,{method:"PATCH",body:JSON.stringify(d)});if(o.push({kind:"PATCH issue",ok:g.ok,status:g.status}),!g.ok){let f=await g.text().catch(()=>"");return{ok:!1,attempts:o,error:`PATCH issue ${g.status}: ${f.slice(0,200)}`,url:t.url}}}catch(g){return o.push({kind:"PATCH issue",ok:!1,error:g.message}),{ok:!1,attempts:o,error:g.message,url:t.url}}if(e.note)try{let g=await a(`/repos/${l}/issues/${t.iid}/comments`,{method:"POST",body:JSON.stringify({body:e.note})});o.push({kind:"POST comment",ok:g.ok,status:g.status})}catch(g){o.push({kind:"POST comment",ok:!1,error:g.message})}return{ok:o.every(g=>g.ok),attempts:o,url:t.url}}var He=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,ge=/@([a-z0-9_-]+)/i,On=/\[time:\s*([0-9hm\s]+)\]/i;function bi(t){let e=t.match(/(\d+)\s*h/i),n=t.match(/(\d+)\s*m/i);return(e?parseInt(e[1],10)*3600:0)+(n?parseInt(n[1],10)*60:0)}var ze=class{constructor(e,n,s=()=>{}){this.path=e;this.daemon=n;this.log=s;this.store=new de(this.path)}type="backlog";capabilities={listAll:!0,create:!1,transition:!1,labels:!0,search:!1};store;getStore(){return this.store}readMd(){let e=Be(process.cwd(),this.path);return We(e)?Ue(e,"utf-8").split(`
129
- `):[]}writeMd(e){let n=Be(process.cwd(),this.path);Pn(n,e.join(`
130
- `))}async listOpen(e){if(this.store.exists())return this.store.list().filter(i=>i.status!=="done"&&(!i.assignee||i.assignee.toLowerCase()===e.toLowerCase())).map(i=>this.toWorkItem(i));let n=this.readMd(),s=[];for(let r=0;r<n.length;r++){let i=n[r].match(He);if(!i||i[2].toLowerCase()==="x")continue;let a=i[3],l=a.match(ge);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let c=a.match(On),u=a.replace(ge,"").replace(On,"").trim();s.push({id:`backlog:${r}`,title:u||`Task at line ${r+1}`,assignee:l?l[1]:void 0,estimatedSeconds:c?bi(c[1]):void 0,priority:r})}return s}async listAll(e={}){return this.store.exists()?this.store.list().map(n=>this.toWorkItem(n)):[]}async claim(e,n){if(!this.store.exists())return;let s=this.store.findById(n);if(!s)return;let r=this.store.update(n,{assignee:s.assignee||e,status:"doing"});if(r.source&&this.daemon){let i=Ln([r.assignee||e],r.source,this.daemon);Fe(r,{assigneeUsernames:i,addLabels:["Doing"],removeLabels:["To Do"]},this.daemon,this.log).catch(o=>this.log(`[backlog-sync] claim failed for ${n}: ${o?.message??o}`))}}async report(e,n){if(this.store.exists()&&this.store.findById(e)){let a={};n.status==="done"?a.status="done":n.status==="blocked"?(a.status="blocked",a.blocker=n.blocker||n.note||void 0):n.status==="in-progress"&&(a.status="doing"),n.timeSeconds&&(a.estimatedSeconds=n.timeSeconds);let l=this.store.update(e,a);if(l.source&&this.daemon){let c={};n.status==="done"?(c.addLabels=["Done"],c.removeLabels=["Doing"]):n.status==="blocked"&&(c.addLabels=["Blocked"]),n.note&&(c.note=n.note),Object.keys(c).length&&Fe(l,c,this.daemon,this.log).catch(u=>this.log(`[backlog-sync] report failed for ${e}: ${u?.message??u}`))}return}if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let s=parseInt(e.slice(8),10),r=this.readMd(),i=r[s];if(!i)throw new Error(`backlog line ${s} missing`);if(!i.match(He))throw new Error(`backlog line ${s} not a checkbox`);if(n.status==="done"){r[s]=i.replace(/- \[ \]/,"- [x]");let a=n.timeSeconds?` <!-- done by agent, ${Math.round(n.timeSeconds/60)}m -->`:" <!-- done by agent -->";r.splice(s+1,0,a)}else n.status==="blocked"?r.splice(s+1,0,` <!-- BLOCKED: ${n.blocker||n.note||"?"} -->`):n.note&&r.splice(s+1,0,` <!-- ${n.note.replace(/-->/g,"\u2014 >")} -->`);this.writeMd(r)}toWorkItem(e){let n={todo:"todo",doing:"doing",blocked:"onhold",done:"done"}[e.status];return{id:e.id,title:e.title,description:e.description,assignee:e.assignee,estimatedSeconds:e.estimatedSeconds,priority:e.priority,labels:e.labels,stage:n,milestone:e.milestone,url:e.source?.url,updatedAt:e.updatedAt,state:e.status==="done"?"closed":"opened"}}},Ke=class{constructor(e,n){this.root=e;this.glob=n}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,n){if(We(e))for(let s of mi(e)){let r=yi(e,s);hi(r).isDirectory()?this.walk(r,n):s.endsWith(".md")&&n.push(r)}}async listOpen(e){let n=[];this.walk(Be(process.cwd(),this.root),n);let s=[];for(let r of n){let i=Ue(r,"utf-8").split(`
131
- `);for(let o=0;o<i.length;o++){let a=i[o].match(He);if(!a||a[2].toLowerCase()==="x")continue;let l=a[3].match(ge);!l||l[1].toLowerCase()!==e.toLowerCase()||s.push({id:`wiki:${r}:${o}`,title:a[3].replace(ge,"").trim(),assignee:l[1],priority:o})}}return s}async claim(){}async report(e,n){let s=e.split(":"),r=parseInt(s[s.length-1],10),i=s.slice(1,-1).join(":");if(!We(i))return;let o=Ue(i,"utf-8").split(`
132
- `);n.status==="done"&&o[r]&&(o[r]=o[r].replace(/- \[ \]/,"- [x]"),Pn(i,o.join(`
133
- `)))}},Ge=class{constructor(e,n,s,r,i){this.host=e;this.token=n;this.projects=s;this.agentUsernames=r;this.log=i}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[n,s]of Object.entries(this.agentUsernames))if(s.some(r=>r.toLowerCase()===e.toLowerCase()))return n}mapIssue(e,n){let s=e.references?.full?.split("#")[0]||n,r=[],i;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(i=e.labels.map(c=>({name:c.name,color:c.color,text_color:c.text_color})),r=i.map(c=>c.name)):r=e.labels);let a=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(c=>({username:c.username,name:c.name,avatarUrl:c.avatar_url})),l=a[0]?.username;return{id:`gitlab:${s}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:a,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:r,labelDetails:i,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,n={}){let s=await fetch(`${this.host}/api/v4${e}`,{...n,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...n.headers||{}}});if(!s.ok)throw new Error(`GitLab ${s.status}: ${await s.text().catch(()=>"")}`);return s.json()}async listOpen(e){let n=this.agentUsernames[e]||[];if(!n.length)return[];let s=[],r=this.projects.length?this.projects:["__ALL__"];for(let i of n)for(let o of r)try{let a=`assignee_username=${encodeURIComponent(i)}&state=opened&scope=all&per_page=20`,l=o==="__ALL__"?`/issues?${a}`:`/projects/${encodeURIComponent(o)}/issues?${a}`,c=await this.api(l);for(let u of c){let d=this.mapIssue(u,o);d.assignee=e,s.push(d)}}catch(a){this.log(`[business] GitLab listOpen failed for ${i} on ${o}: ${a.message}`)}return s}async claim(e,n){let{project:s,iid:r,type:i}=this.parseId(n),o=`/projects/${encodeURIComponent(s)}/${i==="issue"?"issues":"merge_requests"}/${r}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(a){this.log(`[business] claim label update failed: ${a.message}`)}}async report(e,n){let{project:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";if(n.timeSeconds&&n.timeSeconds>0){let a=Math.max(1,Math.round(n.timeSeconds/60)),l=a>=60?`${Math.floor(a/60)}h${a%60?` ${a%60}m`:""}`:`${a}m`;try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(c){this.log(`[business] add_spent_time failed: ${c.message}`)}}if(n.status==="done")try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(a){this.log(`[business] done label update failed: ${a.message}`)}else if(n.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?add_labels=Blocked`,{method:"PUT"})}catch(a){this.log(`[business] blocked label update failed: ${a.message}`)}if(n.note)try{await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}/notes`,{method:"POST",body:JSON.stringify({body:n.note})})}catch(a){this.log(`[business] report note failed: ${a.message}`)}}async listAll(e={}){let n=e.sinceDays??30,s=new Date(Date.now()-n*24*36e5).toISOString(),r=new URLSearchParams,i=e.state??"opened";r.set("state",i),r.set("updated_after",s),r.set("scope","all"),r.set("per_page","100"),r.set("with_labels_details","true"),r.set("order_by","updated_at"),r.set("sort","desc"),e.labels?.length&&r.set("labels",e.labels.join(",")),e.milestone&&r.set("milestone",e.milestone),e.search&&r.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],a=[];for(let c of o)try{let u=c==="__ALL__"?`/issues?${r.toString()}`:`/projects/${encodeURIComponent(c)}/issues?${r.toString()}`,d=await this.api(u);for(let g of d)a.push(this.mapIssue(g,c))}catch(u){this.log(`[business] GitLab listAll failed on ${c}: ${u.message}`)}let l=a;if(e.notLabels?.length){let c=new Set(e.notLabels);l=l.filter(u=>!(u.labels||[]).some(d=>c.has(d)))}if(e.withoutScopedPrefix){let c=e.withoutScopedPrefix+"::";l=l.filter(u=>!(u.labels||[]).some(d=>d.startsWith(c)))}return l}async setState(e,n){let{project:s,iid:r,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(s)}/${o}/${r}?state_event=${n}`,{method:"PUT"})}async getItem(e){let{project:n,iid:s}=this.parseId(e);try{let r=await this.api(`/projects/${encodeURIComponent(n)}/issues/${s}?with_labels_details=true`);return{...this.mapIssue(r,n),descriptionHtml:r.description_html||void 0,createdAt:r.created_at,author:r.author?{username:r.author.username,name:r.author.name,avatarUrl:r.author.avatar_url}:void 0,allLabels:Array.isArray(r.labels)?typeof r.labels[0]=="object"?r.labels.map(o=>o.name):r.labels:[]}}catch(r){return this.log(`[board] GitLab getItem failed for ${e}: ${r.message}`),null}}async updateItem(e,n){let{project:s,iid:r}=this.parseId(e),i;n.assigneeUsernames&&(i=(await Promise.all(n.assigneeUsernames.map(async u=>{try{let d=await this.api(`/users?username=${encodeURIComponent(u)}`);return Array.isArray(d)&&d[0]?.id?d[0].id:null}catch{return null}}))).filter(u=>typeof u=="number"));let o;if(n.milestoneTitle!==void 0)if(n.milestoneTitle===null||n.milestoneTitle==="")o=0;else try{let c=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(n.milestoneTitle)}`);Array.isArray(c)&&c[0]?.id&&(o=c[0].id)}catch(c){this.log(`[board] milestone lookup failed for "${n.milestoneTitle}": ${c.message}`)}let a={};n.title!==void 0&&(a.title=n.title),n.description!==void 0&&(a.description=n.description),n.labels!==void 0&&(a.labels=n.labels.join(",")),n.addLabels?.length&&(a.add_labels=n.addLabels.join(",")),n.removeLabels?.length&&(a.remove_labels=n.removeLabels.join(",")),i!==void 0&&(a.assignee_ids=i),o!==void 0&&(a.milestone_id=o);let l=await this.api(`/projects/${encodeURIComponent(s)}/issues/${r}`,{method:"PUT",body:JSON.stringify(a)});return this.mapIssue(l,s)}async listMembers(){let e=new Map;for(let n of this.projects)try{let s=await this.api(`/projects/${encodeURIComponent(n)}/members/all?per_page=100`);for(let r of s)r.username&&!e.has(r.username)&&e.set(r.username,{username:r.username,name:r.name,avatarUrl:r.avatar_url})}catch(s){this.log(`[board] listMembers failed for ${n}: ${s.message}`)}return[...e.values()].sort((n,s)=>n.username.localeCompare(s.username))}async listMilestones(){let e=new Map;for(let s of this.projects)try{let r=await this.api(`/projects/${encodeURIComponent(s)}/milestones?per_page=100`);for(let i of r)i.title&&!e.has(i.title)&&e.set(i.title,{id:i.id,title:i.title,state:i.state,dueDate:i.due_date})}catch(r){this.log(`[board] listMilestones failed for ${s}: ${r.message}`)}let n=[...e.values()];return n.sort((s,r)=>s.state!==r.state?s.state==="active"?-1:1:s.title.localeCompare(r.title)),n}async create(e){let n=e.projectHint||this.projects[0];if(!n)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let s,r=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];r.length&&(s=(await Promise.all(r.map(async c=>{try{let u=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(u)&&u[0]?.id?u[0].id:null}catch(u){return this.log(`[board] user lookup failed for ${c}: ${u.message}`),null}}))).filter(c=>typeof c=="number"));let i;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(i=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};s?.length&&(o.assignee_ids=s),i!==void 0&&(o.milestone_id=i);let a=await this.api(`/projects/${encodeURIComponent(n)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(a,n)}async transition(e,n,s){await this.transitionMany(e,n?[n]:[],s?[s]:[])}async transitionMany(e,n,s){let{project:r,iid:i,type:o}=this.parseId(e),a=o==="issue"?"issues":"merge_requests",l=new URLSearchParams;n.length&&l.set("add_labels",n.join(",")),s.length&&l.set("remove_labels",s.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(r)}/${a}/${i}?${l.toString()}`,{method:"PUT"})}parseId(e){let s=e.replace(/^gitlab:/,"").split(":"),r=s.pop(),i=s.pop()==="mr"?"mr":"issue";return{project:s.join(":"),type:i,iid:r}}};function ul(t,e,n){let s=t.workSource;switch(s.type){case"backlog":return new ze(s.path,e,n);case"wiki":return new Ke(s.path,s.glob);case"gitlab":{let r=e.channels.gitlab;if(!r?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let i={};for(let a of r.agentMappings)a.gitlabUsernames.length&&(i[a.agentId]=a.gitlabUsernames);let o=s.projects.length?s.projects:r.routes.map(a=>a.project);return new Ge(r.host,r.token,o,i,n)}}}var Xe="unmapped";function Je(t,e=[]){if(!t)return Xe;let n=e.find(r=>r.id===t);if(n?.client)return n.client;let s=t.indexOf("/");return s>0?t.slice(0,s):t}function ki(t){let e=new Map,n=t.projects??[],s=t.orgChart??{};for(let i of n)i.pm&&(e.has(i.pm)||e.set(i.pm,Je(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 wi(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 gl(t,e){let n=wi(t.channel,{chatId:t.chatId,username:t.username},e.contactMap);if(n)return n.client;if(t.project)return Je(t.project,e.projects);if(t.agentId){let s=ki(e).get(t.agentId);if(s)return s}return Xe}function fl(t,e){let n=String(t||"").split(":");if(n.length<3)return{agentId:e};let[s,r,...i]=n,o=i.join(":"),a={agentId:e||s,channel:r};return r==="gitlab"||r==="github"?a.project=o.split(":")[0]:r==="cron"||r==="api"||(a.chatId=o.split("@")[0]),a}var Si=t=>t===Xe?"internal":"client";function xi(t,e){let n=e.clients?.[t];return{id:t,name:n?.name||t,kind:n?.kind??Si(t),respondWithinMinutes:vi(n?.respondWithin),standing:n?.standing??[],declared:!!n}}function pl(t){let e=new Set;for(let n of t.projects??[])e.add(Je(n.id,t.projects));for(let n of t.contactMap??[])e.add(n.client);for(let n of Object.keys(t.clients??{}))e.add(n);return[...e].sort().map(n=>xi(n,t))}function vi(t){let e=/^(\d+)\s*([mhd])$/.exec(String(t??"").trim());if(!e)return;let n=Number(e[1]);return e[2]==="m"?n:e[2]==="h"?n*60:n*1440}var $i=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n/i,Ii=/(^|\n)[ \t]*```[ \t]*agentx:ui[ \t]*\r?\n([\s\S]*?)\r?\n[ \t]*```[ \t]*(?=\n|$)/gi;function jn(t){if(!t||!t.includes("agentx:ui"))return{cleanText:t};let e=[...t.matchAll(Ii)];if(e.length===0)return{cleanText:t};let n=e[e.length-1],s=n[2],r=Ai(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 hl(t){if(!t||!t.includes("agentx:ui"))return t;let e=$i.exec(t);return e?t.slice(0,e.index).trimEnd():t}function Ai(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 bl(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 _i=5*6e4;function D(t){return t.toLowerCase().replace(/[^a-z0-9]/g,"")}var Mn=class{subs=new Set;log;forwarder;localName;allowedCallers;pending=new Map;cleanupTimer;ringHandler;recentRings=new Map;constructor(e,n=[],s=console.error.bind(console,"[webrtc]")){this.localName=e,this.allowedCallers=new Set(n.map(D)),this.log=s,this.cleanupTimer=setInterval(()=>this.cleanupExpired(),1e4)}pendingKey(e,n){return`${e}|${D(n)}`}cleanupExpired(){let e=Date.now();for(let[n,s]of this.pending){let r=s.filter(i=>i.expiresAt>e);r.length===0?this.pending.delete(n):r.length!==s.length&&this.pending.set(n,r)}for(let[n,s]of this.recentRings)s<=e&&this.recentRings.delete(n)}setForwarder(e){this.forwarder=e}setRingHandler(e){this.ringHandler=e}subscribe(e,n,s){return this.addSubscriber(e,n,{kind:"sse",res:s})}subscribeInternal(e,n,s){return this.addSubscriber(e,n,{kind:"callback",deliver:s})}addSubscriber(e,n,s){let r={callId:e,recipient:n,sink:s};this.subs.add(r);let i=s.kind==="sse"?"sse":"internal";this.log(`subscribe[${i}] call=${e} as=${n} (${this.subs.size} total)`);let o=this.pendingKey(e,n),a=this.pending.get(o);if(a&&a.length){let l=Date.now(),c=a.filter(u=>u.expiresAt>l);for(let{signal:u}of c)this.deliverTo(r,u);this.pending.delete(o),c.length&&this.log(`flushed ${c.length} buffered signal(s) to new subscriber call=${e} as=${n}`)}return()=>{this.subs.delete(r),this.log(`unsubscribe[${i}] call=${e} as=${n} (${this.subs.size} remaining)`)}}deliverTo(e,n){try{return e.sink.kind==="sse"?e.sink.res.write(`event: signal
134
- data: ${JSON.stringify(n)}
135
-
136
- `):e.sink.deliver(n),!0}catch{return!1}}async handleOutgoing(e){let n=D(e.to);if(n===D(this.localName)||this.hasSubscriberFor(e.callId,n))return this.fanOut(e),{ok:!0};if(!this.forwarder)return{ok:!1,error:"mesh forwarder not wired"};let r=await this.forwarder(e.to,e);return r?{ok:r}:{ok:!1,error:`forward to "${e.to}" failed`}}hasSubscriberFor(e,n){for(let s of this.subs)if(s.callId===e&&D(s.recipient)===n)return!0;return!1}handleIncoming(e){if((e.kind==="offer"||e.kind==="ring")&&this.allowedCallers.size>0&&!this.allowedCallers.has(D(e.from)))return this.log(`reject inbound ${e.kind} from "${e.from}": not in allowedCallers`),{ok:!1,error:"caller not allowed"};if(e.kind==="ring"){let s=Date.now(),r=this.recentRings.get(e.callId);if(r&&r>s)return this.log(`dedup ring for call=${e.callId} (already notified)`),{ok:!0};if(this.recentRings.set(e.callId,s+_i),this.ringHandler)try{this.ringHandler(e)}catch(i){this.log(`ringHandler threw: ${i.message}`)}else this.log(`ring received for call=${e.callId} but no handler wired`);return{ok:!0}}if(this.fanOut(e)===0){let s=this.pendingKey(e.callId,e.to),r=this.pending.get(s)||[];r.push({signal:e,expiresAt:Date.now()+3e4}),this.pending.set(s,r),this.log(`buffered ${e.kind} for call=${e.callId} to=${e.to} (no subscriber yet, ${r.length} pending)`)}return{ok:!0}}fanOut(e){let n=0,s=D(e.to);for(let r of this.subs)r.callId===e.callId&&D(r.recipient)===s&&(this.deliverTo(r,e)?n++:this.subs.delete(r));return n}get subscriberCount(){return this.subs.size}shutdown(){this.cleanupTimer&&clearInterval(this.cleanupTimer);for(let e of this.subs)if(e.sink.kind==="sse")try{e.sink.res.end()}catch{}this.subs.clear(),this.pending.clear()}};import{closeSync as G,createReadStream as Ri,fstatSync as Ci,openSync as Di,realpathSync as Vn}from"fs";import{isAbsolute as Ti,resolve as Nn,sep as Fn}from"path";var $l="/app-files",Ei=/^[A-Za-z0-9_.:-]{1,64}$/;function Li(t,e,n=process.cwd()){if(!e||e.length>Q.pathChars||e.includes("\0"))return{ok:!1,status:400,error:"bad file path"};if(e.split(/[\\/]/).includes(".."))return{ok:!1,status:403,error:`the path leaves the workspace: copy the file into ${ke}/ first`};if(!be(e))return{ok:!1,status:415,error:"this type of file is not served"};let s;try{s=Vn(Nn(n,t))}catch{return{ok:!1,status:404,error:"the agent's workspace is missing"}}let r;try{r=Vn(Ti(e)?e:Nn(s,e))}catch{return{ok:!1,status:404,error:"file not found"}}if(!r.startsWith(s+Fn))return{ok:!1,status:403,error:`the file is outside the agent's workspace: copy it into ${ke}/ first`};let i=be(r);return i?{ok:!0,path:r,...i}:{ok:!1,status:415,error:"this type of file is not served"}}function Oi(t,e){let n=t.replace(/[^\x20-\x7e]/g,"_").replace(/["\\;]/g,"_").slice(0,120)||"file";return`${e==="file"?"attachment":"inline"}; filename="${n}"; filename*=UTF-8''${encodeURIComponent(t.slice(0,120))}`}function Pi(t,e,n){return{"Content-Type":t,"Content-Disposition":Oi(e,n),"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; img-src 'self'; media-src 'self'; sandbox","Cache-Control":"private, max-age=3600","Accept-Ranges":"bytes"}}function ji(t,e){let n=/^bytes=(\d*)-(\d*)$/.exec(String(t||"").trim());if(!n||!n[1]&&!n[2])return null;let s,r;return n[1]?(s=Number(n[1]),r=n[2]?Math.min(Number(n[2]),e-1):e-1):(s=Math.max(0,e-Number(n[2])),r=e-1),s>r||s>=e?"unsatisfiable":{start:s,end:r}}function Il(t,e,n,s){let r=(C,O)=>{e.writeHead(C,{"Content-Type":"application/json","Cache-Control":"no-store","X-Content-Type-Options":"nosniff"}),e.end(JSON.stringify(O))};if(t.method!=="GET"&&t.method!=="HEAD")return r(405,{error:"GET only"});let i=n.searchParams.get("agent")||"",o=n.searchParams.get("file")||"";if(!Ei.test(i))return r(400,{error:"bad agent id"});let a=s.workspaceOf(i);if(!a)return r(404,{error:`no agent "${i}" on this computer`});let l=Li(a,o,s.cwd);if(!l.ok)return s.log?.(`[app-files] refused ${JSON.stringify(o.slice(0,200))} from ${i}: ${l.error}`),r(l.status,{error:l.error});let c;try{c=Di(l.path,"r")}catch{return r(404,{error:"file not found"})}let u;try{let C=Ci(c);if(!C.isFile())return G(c),r(404,{error:"not a file"});u=C.size}catch{return G(c),r(404,{error:"file not found"})}if(u>Q.bytes)return G(c),r(413,{error:`the file is larger than ${Q.bytes/1024/1024} MB`});let d=l.path.split(Fn).pop()||"file",g=Pi(l.mime,d,l.kind),f=ji(t.headers.range,u);if(f==="unsatisfiable"){G(c),e.writeHead(416,{...g,"Content-Range":`bytes */${u}`}),e.end();return}let{start:p,end:h}=f??{start:0,end:u-1};if(e.writeHead(f?206:200,{...g,"Content-Length":String(u?h-p+1:0),...f?{"Content-Range":`bytes ${p}-${h}/${u}`}:{}}),t.method==="HEAD"||u===0){G(c),e.end();return}let y=Ri("",{fd:c,start:p,end:h,autoClose:!0});y.on("error",()=>e.destroy()),e.on("close",()=>y.destroy()),y.pipe(e)}import{spawn as X}from"child_process";import{readFileSync as Mi,writeFileSync as Vi}from"fs";import{tmpdir as Ni}from"os";import{join as Fi}from"path";ct();var Un=t=>t&&t!==1?Math.round(175*t):null,fe=t=>t&&t!==1?Math.min(1.2,Math.max(.7,t)):null;function Ui(){if(process.env.ELEVENLABS_API_KEY)return process.env.ELEVENLABS_API_KEY;for(let t of[`${process.env.HOME}/.elevenlabs/key`,`${process.env.HOME}/.agentx/elevenlabs-key.txt`])try{let e=Mi(t,"utf8").trim();if(e)return e}catch{}return null}function Ol(t=Ui()){let e=0;return async(n,s)=>{if(n.voice.provider==="system")return null;if(!t){if(n.voice.fallback)return null;throw new Error("ElevenLabs is the voice provider but no key is set")}try{let r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${n.voice.elevenlabs}/stream?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n.text,model_id:"eleven_flash_v2_5",...fe(n.voice.rate)?{voice_settings:{speed:fe(n.voice.rate)}}:{}}),signal:s});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text()).slice(0,160)}`);let i=Fi(Ni(),`agentx-say-${process.pid}-${++e}.mp3`);return Vi(i,Buffer.from(await r.arrayBuffer())),i}catch(r){if(s.aborted||!n.voice.fallback)throw r;return E(`elevenlabs:${String(r?.message??r).slice(0,40)}`,`[voice] ElevenLabs failed (${String(r?.message??r).slice(0,160)}); speaking with the system voice`),null}}}function Wn(t,e){let n=t.languages&&Z(e);return n&&t.languages&&n in t.languages?t.languages[n]:t.system}var Wi=(t,e="")=>{let n=Wn(t,e),s=Un(t.rate);return[...n&&!cn(n)?["-v",n]:[],...s?["-r",String(s)]:[]]};function Bi(t,e,n){if(!n)return["say",Wi(t,e)];let s=Wn(t,e);return["/bin/sh",[n,...s?[s]:[]]]}function Pl(t){let e=t.split(/\s+/).filter(Boolean).length;return Math.min(300,5+Math.floor(e*6/10))*1e3}function jl(t=qe()){if(t)try{X("/bin/sh",[t,"--stop"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function Ml(t=qe()){if(t)try{X("/bin/sh",[t,"--restore"],{stdio:"ignore"}).on("error",()=>{})}catch{}}function qe(t={},e){if(!Re(t))return null;try{return gn(e)}catch(n){return E("siri-say",`[voice] could not write the Siri voice script (${String(n?.message??n).split(`
137
- `)[0]}); Siri voices will not switch`),null}}var Vl=(t,e)=>{if(!t){let[n,s]=Bi(e.voice,e.text,qe()),r=Un(e.voice.rate),i=r?{...process.env,AGENTX_SAY_RATE:String(r)}:process.env,o=X(n,s,{stdio:["pipe","ignore","ignore"],env:i});return o.stdin?.on("error",()=>{}),o.stdin?.end(e.text),o}return process.platform==="darwin"?X("afplay",[t],{stdio:"ignore"}):X("mpg123",["-q",t],{stdio:"ignore"})};import{spawn as Bn}from"child_process";import{accessSync as Hi,constants as zi,readFileSync as Hn}from"fs";import{homedir as Ki}from"os";import{basename as F,delimiter as zn,dirname as Gi,extname as Xi,join as Ye}from"path";var T={ms:2*60*1e3,bitsPerSecond:64e3,bytes:2*1024*1024};function Kn(t){let e=Array.isArray(t)?t[0]:t;return!e||!/^\d{1,9}$/.test(e.trim())?{status:400,error:"Say how long the recording is (X-Audio-Duration-Ms)."}:Number(e)>T.ms+2e3?{status:413,error:Qe()}:null}var Qe=()=>`The recording is longer than ${T.ms/6e4} minutes.`,Ji={"audio/webm":"webm","video/webm":"webm","audio/ogg":"ogg","audio/mp4":"m4a","video/mp4":"m4a","audio/x-m4a":"m4a","audio/aac":"aac","audio/mpeg":"mp3","audio/wav":"wav","audio/x-wav":"wav","audio/wave":"wav"};function Gn(t){let e=String(t||"").split(";")[0].trim().toLowerCase();return Ji[e]??null}function Xn(t,e){let n=[];return t!=="local"&&e.key&&n.push("elevenlabs"),e.ffmpeg&&(e.mlx?n.push("mlx-whisper"):e.whisper&&n.push("whisper")),n}function et(t,e){return t==="local"&&e.key&&!e.ffmpeg?"Speech to text is set to local, and this computer has no ffmpeg.":(e.mlx||e.whisper)&&!e.ffmpeg?"This computer has Whisper but no ffmpeg to read the recording.":"Add an ElevenLabs key on this computer, or install mlx-whisper and ffmpeg."}function Ze(t,e,n=process.env.PATH??""){let s=Ki(),r=[Ye(s,".local","bin"),"/opt/homebrew/bin","/usr/local/bin",...n.split(zn).filter(Boolean)];for(let i of[e,...r.map(o=>Ye(o,t))])if(i)try{return Hi(i,zi.X_OK),i}catch{}return null}function Hl(t){return{key:t,mlx:Ze("mlx_whisper",process.env.AGENTX_MLX_WHISPER),whisper:Ze("whisper",process.env.AGENTX_WHISPER),ffmpeg:qi()}}var qi=()=>Ze("ffmpeg",process.env.AGENTX_FFMPEG);async function Jn(t,e){return e?Yi(t,e):null}async function Yi(t,e){let n=String(T.ms/1e3+5);try{let r=[...(await Zi(e,["-nostdin","-hide_banner","-t",n,"-i",t,"-f","null","-"],3e4)).matchAll(/time=(\d+):(\d+):(\d+(?:\.\d+)?)/g)],i=r[r.length-1];return i?Number(i[1])*3600+Number(i[2])*60+Number(i[3]):null}catch{return null}}async function qn(t,e,n,s){let r=new FormData;r.set("model_id",process.env.AGENTX_STT_MODEL||"scribe_v1"),r.set("file",new Blob([Hn(t)],{type:e}),F(t));let i=await fetch("https://api.elevenlabs.io/v1/speech-to-text",{method:"POST",headers:{"xi-api-key":n},body:r,signal:s??AbortSignal.timeout(6e4)});if(!i.ok)throw new Error(`ElevenLabs ${i.status}: ${(await i.text().catch(()=>"")).slice(0,160)}`);let o=await i.json();if(typeof o.text!="string")throw new Error("ElevenLabs returned no text");return o.text.trim()}async function Yn(t,e,n,s,r){let i=t==="mlx-whisper"?["--model",process.env.AGENTX_MLX_MODEL||"mlx-community/whisper-large-v3-turbo","--output-format","txt","--output-dir",r,n]:[n,"--model",process.env.AGENTX_WHISPER_MODEL||"base","--output_format","txt","--output_dir",r,"--fp16","False"],o={...process.env,PATH:`${Gi(s)}${zn}${process.env.PATH??""}`};await Qi(e,i,12e4,o);try{return Hn(Ye(r,F(n,Xi(n))+".txt"),"utf8").trim()}catch{throw new Error(`${t} wrote no transcript`)}}function Zi(t,e,n){return new Promise((s,r)=>{let i=Bn(t,e,{stdio:["ignore","ignore","pipe"]}),o="",a=setTimeout(()=>{i.kill("SIGKILL"),r(new Error(`${F(t)} took too long`))},n);i.stderr.on("data",l=>{o=(o+l).slice(-8192)}),i.on("error",l=>{clearTimeout(a),r(l)}),i.on("exit",l=>{clearTimeout(a),l===0?s(o):r(new Error(`${F(t)} exited ${l}`))})})}function Qi(t,e,n,s=process.env){return new Promise((r,i)=>{let o=Bn(t,e,{stdio:["ignore","pipe","pipe"],env:s}),a="",l="",c=setTimeout(()=>{o.kill("SIGKILL"),i(new Error(`${F(t)} took longer than ${n/1e3}s`))},n);o.stdout.on("data",u=>{a.length<4096&&(a+=u)}),o.stderr.on("data",u=>{l.length<4096&&(l+=u)}),o.on("error",u=>{clearTimeout(c),i(u)}),o.on("exit",u=>{clearTimeout(c),u===0?r(a):i(new Error(`${F(t)} exited ${u}: ${l.trim().split(`
138
- `).pop()?.slice(0,160)??""}`))})})}import{mkdtemp as eo,rm as to,writeFile as no}from"fs/promises";import{tmpdir as ro}from"os";import{join as Zn}from"path";ar();var so=64*1024,io=2,tt=0;function tc(t){return t==="/voice/transcribe"||t==="/voice/speak"}async function nc(t,e,n,s){return t.method!=="POST"?b(e,405,{error:"POST"}):n==="/voice/transcribe"?oo(t,e,s):co(t,e,s)}async function oo(t,e,n){let s=String(t.headers["content-type"]||""),r=Gn(s);if(!r)return b(e,415,{error:"Send the recording as audio (webm, mp4, ogg, mp3 or wav)."});let i=Kn(t.headers["x-audio-duration-ms"]);if(i)return t.resume(),b(e,i.status,{error:i.error});let o=await Qn(t,T.bytes);if(!o)return b(e,413,{error:fo()});if(!o.length)return b(e,400,{error:"The recording is empty."});if(tt>=io)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=Xn(a,l);if(!l.ffmpeg&&!n.allowUnmeasured?.()){let d=n.nodeName?`on ${n.nodeName}`:"on this computer",g=c.length?"":" "+et(a,l);return b(e,503,{error:"Voice input isn't set up on this computer.",hint:`Install ffmpeg ${d} for voice input from the phone.${g}`,setup:!1})}if(!c.length)return b(e,503,{error:"Voice input isn't set up on this computer.",hint:et(a,l),setup:!1});tt++;let u;try{let d=await eo(Zn(ro(),"agentx-phone-voice-"));try{u=await ao(d,`speech.${r}`,o,s,l,c,n)}finally{await to(d,{recursive:!0,force:!0}).catch(()=>{})}}finally{tt--}b(e,u[0],u[1])}async function ao(t,e,n,s,r,i,o){let a=Zn(t,e);if(await no(a,n,{mode:384}),r.ffmpeg){let c=await(o.measure??Jn)(a,r.ffmpeg);if(c==null)return[422,{error:"This computer couldn't read the recording. Try again."}];if(c*1e3>T.ms+2e3)return[413,{error:Qe()}]}let l=[];for(let c of i)try{let u=await lo(c,a,s,r,t,o);return o.log(`[voice] phone recording transcribed with ${c} (${Math.round(n.length/1024)} KB)`),u?[200,{text:u,engine:c}]:[422,{error:"No words were heard. Hold the orb and speak, then let go.",engine:c}]}catch(u){let d=String(u?.message??u).split(`
139
- `)[0].slice(0,200);l.push(`${c}: ${d}`),o.log(`[voice] phone transcription with ${c} failed: ${d}`)}return[502,{error:"Speech to text failed on this computer.",detail:l.join("; ")}]}function lo(t,e,n,s,r,i){let o=i.engines?.[t];if(o)return o(e,n,s,r);if(t==="elevenlabs")return qn(e,n,s.key);let a=t==="mlx-whisper"?s.mlx:s.whisper;return Yn(t,a,e,s.ffmpeg,r)}async function co(t,e,n){let s=await Qn(t,so);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=uo(typeof r?.text=="string"?r.text:"",n.spokenMaxChars?.());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??go)(u,l,a);e.writeHead(200,{"Content-Type":"audio/mpeg","Content-Length":d.length,"Cache-Control":"no-store","X-Spoken-Chars":String(a.length)}),e.end(d)}catch(d){return n.log(`[voice] phone answer synthesis failed: ${String(d?.message??d).split(`
140
- `)[0].slice(0,160)}`),c("ElevenLabs could not speak this answer.",502)}}function uo(t,e){let n=jn(ft(t).text).cleanText.replace(/!\[[^\]\n]*\]\([^)\n]*\)/g,"");return ut(n,e)}async function go(t,e,n){let s=fe(e.rate),r=await fetch(`https://api.elevenlabs.io/v1/text-to-speech/${encodeURIComponent(e.elevenlabs)}?output_format=mp3_44100_128`,{method:"POST",headers:{"xi-api-key":t,"Content-Type":"application/json"},body:JSON.stringify({text:n,model_id:"eleven_flash_v2_5",...s?{voice_settings:{speed:s}}:{}}),signal:AbortSignal.timeout(6e4)});if(!r.ok)throw new Error(`ElevenLabs ${r.status}: ${(await r.text().catch(()=>"")).slice(0,160)}`);return Buffer.from(await r.arrayBuffer())}var fo=()=>`The recording is larger than ${T.bytes/1024/1024} MB, more than ${T.ms/6e4} minutes of speech.`;function rc(t,e,n,s){if(e)return s.speakerOn(e,t,!1)?.voice??null;let r=n.agents??{};return r[t]?Ve(Pe(t,r,n.voice)):null}function Qn(t,e){return Number(t.headers["content-length"])>e?(t.resume(),Promise.resolve(null)):new Promise((n,s)=>{let r=[],i=0;t.on("data",o=>{if(!(i>e)){if(i+=o.length,i>e){r.length=0,n(null);return}r.push(o)}}),t.on("end",()=>{i<=e&&n(Buffer.concat(r))}),t.on("error",s)})}function b(t,e,n){t.writeHead(e,{"Content-Type":"application/json","Cache-Control":"no-store"}),t.end(JSON.stringify(n))}import{existsSync as v,readFileSync as it,writeFileSync as ot,mkdirSync as pe,readdirSync as st,rmSync as po,statSync as A}from"fs";import{resolve as er,relative as mo,dirname as at,join as L,extname as J,basename as lt}from"path";var S=200*1024,tr=new Set([".md",".markdown",".txt"]),U=new Set([".md",".markdown",".txt",".json",".jsonc",".yaml",".yml",".toml",".sh",".bash",".zsh",".py",".js",".mjs",".ts",".tsx",".jsx",".css",".html",".lock",".cfg",".ini",".env",".gitignore"]),ho=6,yo=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=er(t);if(v(n)||pe(n,{recursive:!0}),!e||e.startsWith("/")||e.match(/^[a-zA-Z]:/))throw new Error(`Path must be relative to the workspace: ${e}`);let s=er(n,e);if(mo(n,s).startsWith(".."))throw new Error(`Path escapes the workspace: ${e}`);return s}function nr(t){let e=J(t).toLowerCase();if(!tr.has(e))throw new Error(`Only text files (.md, .markdown, .txt) can be edited from the admin panel (got ${e}).`)}function nt(t,e){let n=t.split(/\r?\n/).find(s=>s.trim().startsWith("#"));return n&&n.replace(/^#+\s*/,"").trim().slice(0,120)||e}function ac(t){let e=R(t,"."),n=[],s=new Set,r=[];try{r=st(e)}catch{}for(let a of yo){let l=L(e,a);if(v(l)&&A(l).isFile()){let c=A(l).size,u=c>0&&c<S?rt(l):"";n.push({path:a,title:nt(u,a),size:c,exists:!0}),s.add(a)}else n.push({path:a,title:a,size:0,exists:!1}),s.add(a)}for(let a of r){if(s.has(a))continue;let l=L(e,a);try{let c=A(l);if(!c.isFile()||!tr.has(J(a).toLowerCase()))continue;let u=c.size>0&&c.size<S?rt(l):"";n.push({path:a,title:nt(u,a),size:c.size,exists:!0})}catch{}}let i=[],o=L(e,".claude","skills");if(v(o))try{for(let a of st(o)){let l=L(o,a),c;try{c=A(l)}catch{continue}if(!c.isDirectory())continue;let u=L(l,"SKILL.md");if(!v(u))continue;let d=A(u),g=d.size<S?rt(u):"";i.push({slug:a,title:nt(g,a),size:d.size,path:`.claude/skills/${a}/SKILL.md`})}}catch{}return i.sort((a,l)=>a.slug.localeCompare(l.slug)),{identity:n,skills:i,workspace:e}}function rt(t){try{return it(t,"utf-8")}catch{return""}}function lc(t,e){let n=R(t,e);if(nr(n),!v(n))return{path:e,content:""};if(A(n).size>S)throw new Error(`File is too large to edit in the admin panel (> ${S/1024} KB).`);return{path:e,content:it(n,"utf-8")}}function cc(t,e,n){let s=R(t,e);nr(s);let r=Buffer.from(n,"utf-8");if(r.length>S)throw new Error(`File too large (${r.length} > ${S} bytes).`);return pe(at(s),{recursive:!0}),ot(s,r),{path:e,bytes:r.length}}function uc(t,e,n={}){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error("Skill slug must be lowercase (letters, digits, -, _) and start with a letter or digit.");let s=`.claude/skills/${e}/SKILL.md`,r=R(t,s);if(v(r))throw new Error(`Skill "${e}" already exists.`);pe(at(r),{recursive:!0});let i=n.content?.trim()?n.content:bo(e,n.title);return ot(r,i),{slug:e,path:s}}function dc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);if(!A(n).isDirectory())throw new Error(`Skill path is not a directory: ${e}`);return po(n,{recursive:!0,force:!0}),{slug:e}}function gc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=[];return r(n,"",0,s),s.sort((i,o)=>i.kind!==o.kind?i.kind==="dir"?-1:1:i.path.localeCompare(o.path)),s;function r(i,o,a,l){if(a>ho)return;let c=[];try{c=st(i)}catch{return}for(let u of c){if(u==="node_modules"||u===".git")continue;let d=L(i,u),g=o?`${o}/${u}`:u,f;try{f=A(d)}catch{continue}if(f.isDirectory())l.push({path:`${g}/`,kind:"dir",size:0,editable:!1}),r(d,g,a+1,l);else if(f.isFile()){let p=J(u).toLowerCase(),h=U.has(p)||U.has(u.toLowerCase());l.push({path:g,kind:"file",size:f.size,editable:h&&f.size<S})}}}}function fc(t,e,n){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let s=R(t,`.claude/skills/${e}/${n}`);if(!v(s)||!A(s).isFile())throw new Error(`File not found: ${n}`);let r=J(s).toLowerCase(),i=lt(s).toLowerCase();if(!U.has(r)&&!U.has(i))throw new Error(`File type not editable: ${n}`);if(A(s).size>S)throw new Error(`File too large to edit (> ${S/1024} KB): ${n}`);return{path:n,content:it(s,"utf-8")}}function pc(t,e,n,s){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);if(!n||n.includes(".."))throw new Error(`Invalid file path: ${n}`);let r=R(t,`.claude/skills/${e}/${n}`),i=J(r).toLowerCase(),o=lt(r).toLowerCase();if(!U.has(i)&&!U.has(o))throw new Error(`File type not editable: ${n}`);let a=Buffer.from(s,"utf-8");if(a.length>S)throw new Error(`File too large (${a.length} > ${S} bytes).`);return pe(at(r),{recursive:!0}),ot(r,a),{path:n,bytes:a.length}}function mc(t,e){if(!/^[a-z0-9][a-z0-9_-]*$/.test(e))throw new Error(`Invalid skill slug: ${e}`);let n=R(t,`.claude/skills/${e}`);if(!v(n))throw new Error(`Skill "${e}" not found.`);let s=r=>v(L(n,r));return s("pnpm-lock.yaml")?{manager:"pnpm",file:"pnpm-lock.yaml",command:"pnpm install"}:s("yarn.lock")?{manager:"yarn",file:"yarn.lock",command:"yarn install"}:s("package.json")?{manager:"npm",file:"package.json",command:"npm install"}:s("requirements.txt")?{manager:"pip",file:"requirements.txt",command:"pip install -r requirements.txt"}:s("Gemfile")?{manager:"bundle",file:"Gemfile",command:"bundle install"}:{manager:null,file:null,command:null}}function bo(t,e){return`# ${e?.trim()||t}
141
-
142
- Describe what this skill does and when the agent should use it. Keep it under ~5 lines \u2014 the agent reads this to decide whether to invoke the skill.
143
-
144
- ## When to use
145
- - Trigger condition 1
146
- - Trigger condition 2
147
-
148
- ## How to use
149
- Document the arguments, commands, or files the skill expects. Example:
150
-
151
- \`\`\`bash
152
- # Example invocation
153
- claude-code ${lt(t)} --arg value
154
- \`\`\`
155
- `}lr();var rr={maxPixels:12e5,timeoutMs:5e3,intervalMs:100,changeThreshold:.015,stableMs:400,regions:{},buffer:{enabled:!1,seconds:10,fps:2,region:"screen",maxPixels:3e5}};function sr(t){return{...rr,...t??{},regions:{...t?.regions??{}},buffer:{...rr.buffer,...t?.buffer??{}}}}function bc(t){try{return sr(dt(t).screen)}catch{return sr(void 0)}}var ko=/^[a-z][\w-]*$/,ir=["window","screen","menubar","notifications"];function q(t,e,n,s){let r=Number(t);if(t===""||t===null||!Number.isFinite(r)||!n(r))throw new Error(`${e} must be ${s}`);return r}var me=(t,e)=>q(t,e,n=>Number.isInteger(n)&&n>0,"a whole number above 0");function or(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 kc(t,e){let n={...t??{}};if("maxPixels"in e&&(n.maxPixels=me(e.maxPixels,"maxPixels")),"timeoutMs"in e&&(n.timeoutMs=me(e.timeoutMs,"timeoutMs")),"intervalMs"in e&&(n.intervalMs=me(e.intervalMs,"intervalMs")),"stableMs"in e&&(n.stableMs=q(e.stableMs,"stableMs",r=>Number.isInteger(r)&&r>=0,"a whole number, 0 or more")),"changeThreshold"in e&&(n.changeThreshold=q(e.changeThreshold,"changeThreshold",r=>r>=0&&r<=1,"between 0 and 1")),e.regions&&typeof e.regions=="object"){let r={...n.regions??{}};for(let[i,o]of Object.entries(e.regions)){if(!ko.test(i))throw new Error(`region name "${i}" must be lowercase letters, digits, - or _`);o===null?delete r[i]:r[i]=or(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=q(r.seconds,"buffer.seconds",o=>o>0&&o<=120,"above 0 and at most 120")),"fps"in r&&(i.fps=q(r.fps,"buffer.fps",o=>o>0&&o<=10,"above 0 and at most 10")),"maxPixels"in r&&(i.maxPixels=me(r.maxPixels,"buffer.maxPixels")),"region"in r&&(i.region=String(r.region).trim()),n.buffer=i}let s=n.buffer?.region;if(s!==void 0&&!ir.includes(s)&&!n.regions?.[s])try{or(s)}catch{throw new Error(`buffer.region "${s}" is not a region \u2014 use ${[...ir,...Object.keys(n.regions??{})].join(", ")}, or x,y,w,h`)}return n}export{At as a,xo as b,Je as c,ki as d,wi as e,gl as f,fl as g,pl as h,jn as i,hl as j,bl as k,D as l,Mn as m,w as n,Ao as o,Ot as p,To as q,Pt as r,Eo as s,zt as t,I as u,P as v,Gt as w,W as x,B as y,Xo as z,Jo as A,qo as B,Yo as C,Zo as D,Po as E,Fr as F,Uo as G,Bt as H,j as I,ra as J,sa as K,ia as L,ha as M,ya as N,$l as O,Pi as P,Il as Q,ka as R,wa as S,Sa as T,xa as U,va as V,$a as W,Aa as X,_a as Y,ja as Z,Te as _,Ma as $,Va as aa,z as ba,K as ca,Ui as da,Ol as ea,Pl as fa,jl as ga,Ml as ha,qe as ia,Vl as ja,Oe as ka,Pe as la,ue as ma,Ns as na,Us as oa,Ba as pa,Me as qa,Ve as ra,Ws as sa,Bs as ta,xn as ua,An as va,Ha as wa,Ks as xa,za as ya,ei as za,ri as Aa,Ne as Ba,ii as Ca,_n as Da,T as Ea,Kn as Fa,Gn as Ga,Xn as Ha,Hl as Ia,qi as Ja,qn as Ka,Yn as La,tc as Ma,nc as Na,fo as Oa,rc as Pa,Qn as Qa,de as Ra,rl as Sa,Ln as Ta,Fe as Ua,Ge as Va,ul as Wa,ac as Xa,lc as Ya,cc as Za,uc as _a,dc as $a,gc as ab,fc as bb,pc as cb,mc as db,rr as eb,sr as fb,bc as gb,ir as hb,kc as ib};
156
- //# sourceMappingURL=chunk-H7SL56KH.js.map