agentix-cli 0.115.0 → 0.116.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/mac-voice/Sources/AgentXVoice/AnswerView.swift +24 -2
- package/apps/mac-voice/Sources/AgentXVoice/ListenAgain.swift +26 -0
- package/apps/mac-voice/Sources/AgentXVoice/main.swift +54 -0
- package/dist/{App-6OMMZW2M.js → App-7Z2PWARZ.js} +2 -2
- package/dist/{ChatApp-EDDROHNA.js → ChatApp-GFAIRLGZ.js} +2 -2
- package/dist/{agent-VPM3EEUB.js → agent-LXLZGVW3.js} +2 -2
- package/dist/{board-dashboard-4GQ7RTH3.js → board-dashboard-CPCSSVZE.js} +255 -224
- package/dist/board-dashboard-CPCSSVZE.js.map +1 -0
- package/dist/chunk-6LCP6SVR.js +482 -0
- package/dist/chunk-6LCP6SVR.js.map +1 -0
- package/dist/{chunk-MG5LRE5B.js → chunk-7IF3LXAU.js} +2 -2
- package/dist/{chunk-7T7IXLLA.js → chunk-AWQIUI7N.js} +2 -2
- package/dist/{chunk-5FY7PWXW.js → chunk-B65YTB3T.js} +2 -2
- package/dist/chunk-BRL3UPFW.js +2 -0
- package/dist/chunk-BRL3UPFW.js.map +1 -0
- package/dist/{chunk-EVXL6X2R.js → chunk-CCL73Z2P.js} +56 -56
- package/dist/{chunk-EVXL6X2R.js.map → chunk-CCL73Z2P.js.map} +1 -1
- package/dist/{chunk-ECBVOIIK.js → chunk-CKYSGX54.js} +171 -171
- package/dist/chunk-CKYSGX54.js.map +1 -0
- package/dist/chunk-DMHQIACQ.js +3 -0
- package/dist/chunk-DMHQIACQ.js.map +1 -0
- package/dist/{chunk-K3BG77KK.js → chunk-EKOVLUKH.js} +2 -2
- package/dist/{chunk-S4XSVAAG.js → chunk-ELWKTURG.js} +2 -2
- package/dist/chunk-EMGB23H5.js +3 -0
- package/dist/chunk-EMGB23H5.js.map +1 -0
- package/dist/{chunk-IGORU3XR.js → chunk-FBEMUCBO.js} +2 -2
- package/dist/{chunk-IGORU3XR.js.map → chunk-FBEMUCBO.js.map} +1 -1
- package/dist/chunk-GRMCAO3Q.js +2 -0
- package/dist/chunk-GRMCAO3Q.js.map +1 -0
- package/dist/{chunk-CJJULHPJ.js → chunk-HOY2GIKV.js} +4 -4
- package/dist/{chunk-YE4HKOS5.js → chunk-HSYNOMM2.js} +2 -2
- package/dist/{chunk-PITMPRVP.js → chunk-IEZ6OYFJ.js} +2 -2
- package/dist/{chunk-BXYKFWAI.js → chunk-J3SIOMDL.js} +2 -2
- package/dist/{chunk-PX2AOZ5G.js → chunk-JLCJVPRC.js} +2 -2
- package/dist/{chunk-QLB76BGE.js → chunk-KI4CIUVJ.js} +2 -2
- package/dist/{chunk-2NYP4OQU.js → chunk-LNY6N73E.js} +4 -4
- package/dist/{chunk-2NYP4OQU.js.map → chunk-LNY6N73E.js.map} +1 -1
- package/dist/{chunk-KTF4YF4M.js → chunk-R277UDDQ.js} +2 -2
- package/dist/{chunk-4STXRZZS.js → chunk-S56ZGAFM.js} +2 -2
- package/dist/{chunk-SDOSQ6TJ.js → chunk-UUMNP47Q.js} +2 -2
- package/dist/{chunk-UQX2HY5M.js → chunk-WRICEAR6.js} +2 -2
- package/dist/{chunk-J5TZ6QGD.js → chunk-Y3CZE54A.js} +2 -2
- package/dist/{chunk-BU4LE2RT.js → chunk-YMNQYODO.js} +2 -2
- package/dist/cli.js +1 -1
- package/dist/{client-VUNPLVCG.js → client-CU5GNTKR.js} +2 -2
- package/dist/{config-HE2LGTTG.js → config-ITVBNUWW.js} +2 -2
- package/dist/config-mutator-5YRHHA2I.js +2 -0
- package/dist/doctor-MLD3XCYE.js +2 -0
- package/dist/index.d.ts +17 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/{program-53CQJEUZ.js → program-IBOVOVZI.js} +191 -187
- package/dist/program-IBOVOVZI.js.map +1 -0
- package/dist/{promote-4PPJJ6AW.js → promote-JMJPWZI7.js} +2 -2
- package/dist/push-DID6RZYI.js +2 -0
- package/dist/push-bridge-IFUQLIMF.js +2 -0
- package/dist/push-store-L5QHMSST.js +2 -0
- package/dist/{query-ETDKC7WC.js → query-QGPVKGYY.js} +2 -2
- package/dist/{registry-AMETOJ3S.js → registry-PZNC5XYT.js} +2 -2
- package/dist/{request-planner-VFWWT5XR.js → request-planner-M4IKDZBU.js} +2 -2
- package/dist/{review-candidates-2PI4CGZO.js → review-candidates-6DNRBJZ6.js} +2 -2
- package/dist/routing-7NSB6O2S.js +2 -0
- package/dist/schedule-tool-ZP7H55EL.js +2 -0
- package/dist/scheduler-XV5UQQYH.js +2 -0
- package/dist/{seat-TVNR245I.js → seat-ZRCUQCUP.js} +2 -2
- package/dist/{select-KY7B4HAS.js → select-OLNLTEBR.js} +2 -2
- package/dist/{set-enabled-NEINY2I2.js → set-enabled-LG3ESZDC.js} +2 -2
- package/dist/token-store-AY6OBDVI.js +2 -0
- package/dist/token-store-AY6OBDVI.js.map +1 -0
- package/dist/{tool-MQQ2W5LJ.js → tool-RBXRPIBV.js} +2 -2
- package/dist/{tool-5JGMWH62.js → tool-S6U42ULD.js} +2 -2
- package/dist/wiki-XKQN5CWR.js +2 -0
- package/dist/wiki-XKQN5CWR.js.map +1 -0
- package/package.json +1 -1
- package/dist/board-dashboard-4GQ7RTH3.js.map +0 -1
- package/dist/chunk-2QSG53RN.js +0 -482
- package/dist/chunk-2QSG53RN.js.map +0 -1
- package/dist/chunk-ACFQBLPX.js +0 -3
- package/dist/chunk-ACFQBLPX.js.map +0 -1
- package/dist/chunk-ECBVOIIK.js.map +0 -1
- package/dist/config-mutator-22AVTST2.js +0 -2
- package/dist/doctor-6RDRST4G.js +0 -2
- package/dist/program-53CQJEUZ.js.map +0 -1
- package/dist/push-HEDA6P3B.js +0 -2
- package/dist/push-HEDA6P3B.js.map +0 -1
- package/dist/push-store-5VJ4FNI4.js +0 -2
- package/dist/routing-M7MDLD7Q.js +0 -2
- package/dist/schedule-tool-2EQ53IOQ.js +0 -2
- package/dist/scheduler-YGVINPZF.js +0 -2
- package/dist/token-store-YBSU2DTV.js +0 -2
- package/dist/wiki-COAUQ6TQ.js +0 -2
- /package/dist/{App-6OMMZW2M.js.map → App-7Z2PWARZ.js.map} +0 -0
- /package/dist/{ChatApp-EDDROHNA.js.map → ChatApp-GFAIRLGZ.js.map} +0 -0
- /package/dist/{agent-VPM3EEUB.js.map → agent-LXLZGVW3.js.map} +0 -0
- /package/dist/{chunk-MG5LRE5B.js.map → chunk-7IF3LXAU.js.map} +0 -0
- /package/dist/{chunk-7T7IXLLA.js.map → chunk-AWQIUI7N.js.map} +0 -0
- /package/dist/{chunk-5FY7PWXW.js.map → chunk-B65YTB3T.js.map} +0 -0
- /package/dist/{chunk-K3BG77KK.js.map → chunk-EKOVLUKH.js.map} +0 -0
- /package/dist/{chunk-S4XSVAAG.js.map → chunk-ELWKTURG.js.map} +0 -0
- /package/dist/{chunk-CJJULHPJ.js.map → chunk-HOY2GIKV.js.map} +0 -0
- /package/dist/{chunk-YE4HKOS5.js.map → chunk-HSYNOMM2.js.map} +0 -0
- /package/dist/{chunk-PITMPRVP.js.map → chunk-IEZ6OYFJ.js.map} +0 -0
- /package/dist/{chunk-BXYKFWAI.js.map → chunk-J3SIOMDL.js.map} +0 -0
- /package/dist/{chunk-PX2AOZ5G.js.map → chunk-JLCJVPRC.js.map} +0 -0
- /package/dist/{chunk-QLB76BGE.js.map → chunk-KI4CIUVJ.js.map} +0 -0
- /package/dist/{chunk-KTF4YF4M.js.map → chunk-R277UDDQ.js.map} +0 -0
- /package/dist/{chunk-4STXRZZS.js.map → chunk-S56ZGAFM.js.map} +0 -0
- /package/dist/{chunk-SDOSQ6TJ.js.map → chunk-UUMNP47Q.js.map} +0 -0
- /package/dist/{chunk-UQX2HY5M.js.map → chunk-WRICEAR6.js.map} +0 -0
- /package/dist/{chunk-J5TZ6QGD.js.map → chunk-Y3CZE54A.js.map} +0 -0
- /package/dist/{chunk-BU4LE2RT.js.map → chunk-YMNQYODO.js.map} +0 -0
- /package/dist/{client-VUNPLVCG.js.map → client-CU5GNTKR.js.map} +0 -0
- /package/dist/{config-HE2LGTTG.js.map → config-ITVBNUWW.js.map} +0 -0
- /package/dist/{config-mutator-22AVTST2.js.map → config-mutator-5YRHHA2I.js.map} +0 -0
- /package/dist/{doctor-6RDRST4G.js.map → doctor-MLD3XCYE.js.map} +0 -0
- /package/dist/{promote-4PPJJ6AW.js.map → promote-JMJPWZI7.js.map} +0 -0
- /package/dist/{push-store-5VJ4FNI4.js.map → push-DID6RZYI.js.map} +0 -0
- /package/dist/{query-ETDKC7WC.js.map → push-bridge-IFUQLIMF.js.map} +0 -0
- /package/dist/{registry-AMETOJ3S.js.map → push-store-L5QHMSST.js.map} +0 -0
- /package/dist/{routing-M7MDLD7Q.js.map → query-QGPVKGYY.js.map} +0 -0
- /package/dist/{schedule-tool-2EQ53IOQ.js.map → registry-PZNC5XYT.js.map} +0 -0
- /package/dist/{request-planner-VFWWT5XR.js.map → request-planner-M4IKDZBU.js.map} +0 -0
- /package/dist/{review-candidates-2PI4CGZO.js.map → review-candidates-6DNRBJZ6.js.map} +0 -0
- /package/dist/{scheduler-YGVINPZF.js.map → routing-7NSB6O2S.js.map} +0 -0
- /package/dist/{seat-TVNR245I.js.map → schedule-tool-ZP7H55EL.js.map} +0 -0
- /package/dist/{token-store-YBSU2DTV.js.map → scheduler-XV5UQQYH.js.map} +0 -0
- /package/dist/{wiki-COAUQ6TQ.js.map → seat-ZRCUQCUP.js.map} +0 -0
- /package/dist/{select-KY7B4HAS.js.map → select-OLNLTEBR.js.map} +0 -0
- /package/dist/{set-enabled-NEINY2I2.js.map → set-enabled-LG3ESZDC.js.map} +0 -0
- /package/dist/{tool-MQQ2W5LJ.js.map → tool-RBXRPIBV.js.map} +0 -0
- /package/dist/{tool-5JGMWH62.js.map → tool-S6U42ULD.js.map} +0 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{a as l}from"./chunk-JWDJMFU6.js";import{mkdirSync as U,readFileSync as D,renameSync as F,writeFileSync as H}from"fs";import{dirname as K,resolve as J}from"path";function P(e,t=160){if(!e)return e;let r=e.replace(/\s+/g," ").trim();return r.length>t?r.slice(0,t-1)+"\u2026":r}function C(e){let t=new Map;for(let n of e.cronRuns??[]){let s=t.get(n.jobId);(!s||s.startedAt<n.startedAt)&&t.set(n.jobId,n)}let r={success:0,failed:0};for(let n of e.cronRuns??[])n.status==="success"?r.success++:r.failed++;return{id:e.id,name:e.name,url:e.url,reachable:e.reachable,error:P(e.error),uptimeSec:e.uptimeSec,inflight:e.inflight,restart:e.restart?.state&&e.restart.state!=="none"?e.restart:void 0,agents:e.agents.map(n=>({id:n.id,name:n.name,tier:n.tier,active:n.active,errors:n.errors,lastActive:n.lastActive,last:n.lastSummary?{text:P(n.lastSummary.text),at:n.lastSummary.at,ok:n.lastSummary.ok}:void 0})),crons:{today:r,items:(e.crons??[]).map(n=>{let s=t.get(n.id);return{id:n.id,enabled:n.enabled,schedule:n.schedule,agent:n.agent,nextRun:n.nextRun,consecutiveErrors:n.consecutiveErrors,last:s?{status:s.status,at:s.startedAt,text:P(s.status==="success"?s.responseSummary:s.errorSummary)}:void 0}})}}}function j(e){let t=[];for(let r of e)for(let n of r.agents)for(let s of n.runningTasks??[])t.push({node:r.url,nodeName:r.name,agentId:n.id,agentName:n.name,taskId:s.id,preview:P(s.messagePreview),channel:s.channel,startedAt:s.startedAt});return t.sort((r,n)=>r.startedAt<n.startedAt?1:-1)}var E=/^\/api\/app\/tasks\/(cancel|followup)$/;async function L(e,t,r,n,s,o){let i=new URL(e.url||r,"http://localhost");if(n==="GET"&&(r==="/api/app/fleet"||r==="/api/app/activity")){let c=O(i.searchParams.get("timezone")),d=await o.snapshot({date:$(c),timezone:c});return r==="/api/app/activity"?b(t,200,{ts:d.ts,tasks:j(d.nodes)}):b(t,200,{ts:d.ts,nodes:d.nodes.map(C)})}if(n==="GET"&&r==="/api/app/approvals")return b(t,200,{nodes:await o.approvals()});if(n!=="POST")return!1;let p=r.match(E);if(!(p||["/api/app/nodes/restart","/api/app/nodes/reload","/api/app/crons/toggle","/api/app/approvals/decide"].includes(r)))return!1;let a;try{a=await A(e)}catch(c){return b(t,400,{error:c.message})}let h=w(a.node);if(!h)return b(t,400,{error:"node is required"});let y=`operator (phone: ${s})`,u;if(p){let c=w(a.taskId);if(!c)return b(t,400,{error:"taskId is required"});let d=`/api/tasks/${encodeURIComponent(c)}/${p[1]}`;if(p[1]==="cancel")u=await o.nodePost(h,d,{reason:`cancelled by ${y}`});else{let k=w(a.message);if(!k)return b(t,400,{error:"message is required"});u=await o.nodePost(h,d,{message:k,sender:y})}}else if(r==="/api/app/nodes/restart")u=await o.nodePost(h,a.cancel===!0?"/daemon/restart/cancel":"/daemon/restart",{});else if(r==="/api/app/nodes/reload")u=await o.nodePost(h,"/reload",{});else if(r==="/api/app/crons/toggle"){let c=w(a.cronId);if(!c||typeof a.enabled!="boolean")return b(t,400,{error:"cronId and enabled (true or false) are required"});u=await o.nodePost(h,`/crons/${encodeURIComponent(c)}/enabled`,{enabled:a.enabled})}else{let c=w(a.key),d=a.action;if(!c||d!=="yes"&&d!=="no"&&d!=="later")return b(t,400,{error:"key and action (yes, no or later) are required"});u=await o.decide(h,c,d,y)}return b(t,u.status,u.body)}function w(e){return typeof e=="string"?e.trim():""}function O(e){if(!e)return"UTC";try{return new Intl.DateTimeFormat("en-US",{timeZone:e}),e}catch{return"UTC"}}function $(e,t=new Date){return new Intl.DateTimeFormat("en-CA",{timeZone:e,year:"numeric",month:"2-digit",day:"2-digit"}).format(t)}async function A(e,t=16*1024){let r=0,n=[];for await(let i of e){if(r+=i.length,r>t)throw new Error("body too large");n.push(i)}let s=Buffer.concat(n).toString("utf-8").trim();if(!s)return{};let o=JSON.parse(s);if(!o||typeof o!="object"||Array.isArray(o))throw new Error("expected a JSON object");return o}function b(e,t,r){return e.writeHead(t,{"Content-Type":"application/json","Cache-Control":"no-store"}),e.end(JSON.stringify(r)),!0}function I(e){return e==="/api/app/push"||e.startsWith("/api/app/push/")||e==="/api/app/alerts"}var M=2048,x=/^[A-Za-z0-9_-]{8,256}$/;async function Q(e,t,r,n,s,o){if(!I(r))return!1;let i={};if(n==="POST")try{i=await A(e)}catch(a){return R(t,400,{error:a.message})}let p={path:r,method:n,body:i,device:{id:s.id,name:s.name}};if(!o.forward){let a=z(p,o);return R(t,a.status,a.body)}let m;try{m=await o.forward(p),S.note(p,m)}catch(a){m=q(p,`${o.reason??"Can't reach the computer that sends notifications"}: ${a?.message??a}`)}return R(t,m.status,m.body)}var v=class{phones=new Map;file=null;persistTo(t){if(this.file!==t){this.file=t;try{let r=JSON.parse(D(t,"utf-8"));for(let[n,s]of Object.entries(r??{}))s&&typeof s=="object"&&typeof s.subscribed=="boolean"&&this.phones.set(n,{subscribed:s.subscribed,prefs:G(s.prefs)})}catch{}}}note(t,r){if(r.status!==200||!r.body||typeof r.body!="object")return;let n=r.body,s=this.phones.get(t.device.id)??{subscribed:!1,prefs:{}};if(t.method==="GET"&&t.path==="/api/app/push")s.subscribed=n.available===!0&&Number(n.subscriptions)>0,s.prefs=N(n);else if(t.path==="/api/app/push/prefs")s.prefs={...s.prefs,...N(n)};else if(t.path==="/api/app/push/subscribe")s.subscribed=!0;else if(t.path==="/api/app/push/unsubscribe")n.removed&&(s.subscribed=!1);else return;this.phones.set(t.device.id,s),this.save()}save(){if(this.file)try{U(K(this.file),{recursive:!0});let t=`${this.file}.${process.pid}.tmp`;H(t,JSON.stringify(Object.fromEntries(this.phones))+`
|
|
2
|
+
`,{encoding:"utf-8",mode:384}),F(t,this.file)}catch{}}on(t,r){return this.phones.get(t)?.prefs[l[r].field]??l[r].default}finishOn(t){return!!this.phones.get(t)?.subscribed&&this.on(t,"finish")}},S=new v;function Y(){return S.persistTo(J(process.cwd(),".agentx/push-relayed.json")),S}function N(e){let t={};for(let r of Object.values(l))typeof e[r.field]=="boolean"&&(t[r.field]=e[r.field]);return t}function G(e){return e&&typeof e=="object"&&!Array.isArray(e)?N(e):{}}function q(e,t){return e.method==="GET"&&e.path==="/api/app/push"?{status:200,body:{available:!1,reason:t,publicKey:null,subscriptions:0,...T()}}:e.method==="GET"&&e.path==="/api/app/alerts"?{status:200,body:{items:[],error:t}}:{status:502,body:{error:t}}}function z(e,t){let{path:r,method:n,body:s,device:o}=e;if(!I(r))return{status:404,body:{error:"not found"}};let i=t.store(),p=i?t.publicKey():null,m=i?p?void 0:"This computer has no push keys yet. On it, run: agentx app push-keys":t.reason??"Notifications are not set up on this computer.";if(n==="GET"&&r==="/api/app/push")return g(200,{available:!m,reason:m??null,publicKey:p,subscriptions:i&&p?i.list(o.id).filter(u=>u.publicKey===p).length:0,...i?i.prefs.all(o.id):T()});if(n==="GET"&&r==="/api/app/alerts")return g(200,{items:i?i.recent(t.keepRecent,o.id):[]});if(n!=="POST"||r!=="/api/app/push/subscribe"&&r!=="/api/app/push/unsubscribe"&&r!=="/api/app/push/prefs")return g(404,{error:"not found"});if(!i||m)return g(503,{error:m});if(r==="/api/app/push/prefs"){let u=Object.keys(l).filter(f=>s[l[f].field]!==void 0),c=u.map(f=>l[f].field).join(", "),d=Object.values(l).map(f=>f.field).join(" or ");if(u.length===0)return g(400,{error:`send ${d}, true or false`});if(u.some(f=>typeof s[l[f].field]!="boolean"))return g(400,{error:`${c} must be true or false`});let k={};for(let f of u)i.prefs.set(o.id,f,s[l[f].field]),k[l[f].field]=s[l[f].field];return g(200,{ok:!0,...k})}let a=B(s.endpoint,t.allowedHosts);if(!a){let u="";try{u=new URL(String(s.endpoint)).hostname}catch{}return g(400,{error:`not a known push service${u?`: ${u}`:""} (see channels.push.allowedHosts)`})}if(r==="/api/app/push/unsubscribe")return g(200,{ok:!0,removed:i.unsubscribe(a,o.id)});let h=s.keys?.p256dh,y=s.keys?.auth;return typeof h!="string"||!x.test(h)||typeof y!="string"||!x.test(y)?g(400,{error:"keys.p256dh and keys.auth are required"}):s.publicKey!==void 0&&s.publicKey!==p?g(409,{error:"this computer's push keys changed; turn notifications on again"}):(i.subscribe({endpoint:a,p256dh:h,auth:y,deviceId:o.id,deviceName:o.name,publicKey:p}),g(200,{ok:!0}))}function g(e,t){return{status:e,body:t}}function T(){let e={};for(let t of Object.values(l))e[t.field]=t.default;return e}function B(e,t){if(typeof e!="string"||e.length>M)return null;try{let r=new URL(e);if(r.protocol!=="https:"||r.port||r.username||r.password)return null;let n=r.hostname.toLowerCase();return t.some(o=>{let i=o.toLowerCase().replace(/^\.+|\.+$/g,"");return!!i&&(n===i||n.endsWith("."+i))})?e:null}catch{return null}}function R(e,t,r){return e.writeHead(t,{"Content-Type":"application/json","Cache-Control":"no-store"}),e.end(JSON.stringify(r)),!0}export{L as a,A as b,I as c,Q as d,S as e,Y as f,z as g};
|
|
3
|
+
//# sourceMappingURL=chunk-DMHQIACQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/daemon/app-push.ts","../src/daemon/app-fleet.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from \"http\"\nimport { mkdirSync, readFileSync, renameSync, writeFileSync } from \"fs\"\nimport { dirname, resolve } from \"path\"\nimport type { TokenRecord } from \"./token-store\"\nimport type { PushStore } from \"@/channels/push-store\"\nimport { PUSH_PREFS, type PushPrefName } from \"@/channels/push-prefs\"\nimport { readJson } from \"./app-fleet\"\n\n// --- Phone app: notifications (/api/app/push*, /api/app/alerts) ---\n//\n// Phase 4 of the mobile epic. Runs behind the device-token check in\n// app-routes.ts. A phone subscribes here; the daemon's PushAdapter reads the\n// same table to deliver. Each subscription is tied to the phone's device\n// token, so `agentx app revoke` also stops that phone's notifications.\n//\n// On a node that relays pushes (channels.push.relayTo), `forward` is set and\n// every call goes to the push host instead, through this node's daemon and\n// the mesh (push-bridge.ts), so a phone paired with any node can turn\n// notifications on (#711).\n\nexport interface AppPushDeps {\n /** Null when this node doesn't send pushes itself; `reason` says why. */\n store: () => PushStore | null\n /** VAPID public key the browser subscribes with, or null without keys. */\n publicKey: () => string | null\n keepRecent: number\n /** channels.push.allowedHosts: push services a phone may subscribe with. */\n allowedHosts: string[]\n reason?: string\n /** Set on a relaying node: sends each call to the push host. */\n forward?: (call: AppPushCall) => Promise<AppPushResult>\n}\n\n/** One phone-app push request, as handled here or by the push host. */\nexport interface AppPushCall {\n path: string\n method: string\n body: Record<string, any>\n device: { id: string; name: string }\n}\n\nexport interface AppPushResult {\n status: number\n body: unknown\n}\n\n/** The routes this module answers. */\nexport function isAppPushPath(path: string): boolean {\n return path === \"/api/app/push\" || path.startsWith(\"/api/app/push/\") || path === \"/api/app/alerts\"\n}\n\nconst MAX_ENDPOINT = 2048\nconst B64URL = /^[A-Za-z0-9_-]{8,256}$/\n\nexport async function handleAppPush(\n req: IncomingMessage,\n res: ServerResponse,\n path: string,\n method: string,\n device: TokenRecord,\n deps: AppPushDeps,\n): Promise<boolean> {\n if (!isAppPushPath(path)) return false\n let body: Record<string, any> = {}\n if (method === \"POST\") {\n try { body = await readJson(req) } catch (e: any) { return json(res, 400, { error: e.message }) }\n }\n const call: AppPushCall = { path, method, body, device: { id: device.id, name: device.name } }\n if (!deps.forward) {\n const out = runAppPush(call, deps)\n return json(res, out.status, out.body)\n }\n let out: AppPushResult\n try {\n out = await deps.forward(call)\n relayedPush.note(call, out)\n } catch (e: any) {\n out = unreachable(call, `${deps.reason ?? \"Can't reach the computer that sends notifications\"}: ${e?.message ?? e}`)\n }\n return json(res, out.status, out.body)\n}\n\n/** On a relaying node: what the push host last said about each phone, for\n * the checks that must answer at once (a finish notification, the\n * announcement switch). Filled from the phone's own calls on their way\n * through, so it is as fresh as the phone's last look at Alerts. */\nexport class RelayedPushState {\n private phones = new Map<string, { subscribed: boolean; prefs: Record<string, boolean> }>()\n private file: string | null = null\n\n /** Keeps the state in `file` too, so a dashboard restart doesn't stop\n * finish notifications until the phone next opens Alerts. Loads it the\n * first time; later calls with the same file do nothing. */\n persistTo(file: string): void {\n if (this.file === file) return\n this.file = file\n try {\n const saved = JSON.parse(readFileSync(file, \"utf-8\")) as Record<string, any>\n for (const [id, p] of Object.entries(saved ?? {})) {\n if (p && typeof p === \"object\" && typeof p.subscribed === \"boolean\") {\n this.phones.set(id, { subscribed: p.subscribed, prefs: pickPrefsFrom(p.prefs) })\n }\n }\n } catch { /* none yet, or unreadable: start empty */ }\n }\n\n note(call: AppPushCall, out: AppPushResult): void {\n if (out.status !== 200 || !out.body || typeof out.body !== \"object\") return\n const body = out.body as Record<string, any>\n const phone = this.phones.get(call.device.id) ?? { subscribed: false, prefs: {} }\n if (call.method === \"GET\" && call.path === \"/api/app/push\") {\n phone.subscribed = body.available === true && Number(body.subscriptions) > 0\n phone.prefs = pickPrefs(body)\n } else if (call.path === \"/api/app/push/prefs\") {\n phone.prefs = { ...phone.prefs, ...pickPrefs(body) }\n } else if (call.path === \"/api/app/push/subscribe\") {\n phone.subscribed = true\n } else if (call.path === \"/api/app/push/unsubscribe\") {\n if (body.removed) phone.subscribed = false\n } else {\n return\n }\n this.phones.set(call.device.id, phone)\n this.save()\n }\n\n private save(): void {\n if (!this.file) return\n try {\n mkdirSync(dirname(this.file), { recursive: true })\n const tmp = `${this.file}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.phones)) + \"\\n\", { encoding: \"utf-8\", mode: 0o600 })\n renameSync(tmp, this.file)\n } catch { /* kept in memory; written again at the next change */ }\n }\n\n /** A switch as last seen, or its default. */\n on(deviceId: string, name: PushPrefName): boolean {\n return this.phones.get(deviceId)?.prefs[PUSH_PREFS[name].field] ?? PUSH_PREFS[name].default\n }\n\n /** Subscribed and wanting finish notifications, as far as last seen. */\n finishOn(deviceId: string): boolean {\n return !!this.phones.get(deviceId)?.subscribed && this.on(deviceId, \"finish\")\n }\n}\n\n/** One per dashboard process. */\nexport const relayedPush = new RelayedPushState()\n\n/** relayedPush, kept in .agentx/ of the folder the dashboard runs in. */\nexport function relayedPushHere(): RelayedPushState {\n relayedPush.persistTo(resolve(process.cwd(), \".agentx/push-relayed.json\"))\n return relayedPush\n}\n\nfunction pickPrefs(body: Record<string, any>): Record<string, boolean> {\n const out: Record<string, boolean> = {}\n for (const p of Object.values(PUSH_PREFS)) if (typeof body[p.field] === \"boolean\") out[p.field] = body[p.field]\n return out\n}\n\nfunction pickPrefsFrom(v: unknown): Record<string, boolean> {\n return v && typeof v === \"object\" && !Array.isArray(v) ? pickPrefs(v as Record<string, any>) : {}\n}\n\n/** What a relaying node answers when the push host can't be reached: the\n * Alerts card says why instead of failing to load. */\nfunction unreachable(call: AppPushCall, reason: string): AppPushResult {\n if (call.method === \"GET\" && call.path === \"/api/app/push\") {\n return { status: 200, body: { available: false, reason, publicKey: null, subscriptions: 0, ...prefDefaults() } }\n }\n if (call.method === \"GET\" && call.path === \"/api/app/alerts\") return { status: 200, body: { items: [], error: reason } }\n return { status: 502, body: { error: reason } }\n}\n\n/** Answers one call against this node's own subscriptions table. Used for\n * a phone paired here, and by the push host for a phone paired with a\n * relaying node (push-bridge.ts), whose device id is then scoped to it. */\nexport function runAppPush(call: AppPushCall, deps: AppPushDeps): AppPushResult {\n const { path, method, body, device } = call\n if (!isAppPushPath(path)) return { status: 404, body: { error: \"not found\" } }\n const store = deps.store()\n const publicKey = store ? deps.publicKey() : null\n const unavailable = !store\n ? deps.reason ?? \"Notifications are not set up on this computer.\"\n : !publicKey ? \"This computer has no push keys yet. On it, run: agentx app push-keys\" : undefined\n\n if (method === \"GET\" && path === \"/api/app/push\") {\n return ok(200, {\n available: !unavailable,\n reason: unavailable ?? null,\n publicKey,\n // Only rows made with the current key count, so a phone subscribed\n // before `push-keys --force` sees 0 and subscribes again.\n subscriptions: store && publicKey ? store.list(device.id).filter((s) => s.publicKey === publicKey).length : 0,\n // Per-phone switches (push-prefs.ts): chatFinish, announce.\n ...(store ? store.prefs.all(device.id) : prefDefaults()),\n })\n }\n if (method === \"GET\" && path === \"/api/app/alerts\") {\n return ok(200, { items: store ? store.recent(deps.keepRecent, device.id) : [] })\n }\n if (method !== \"POST\" || (path !== \"/api/app/push/subscribe\" && path !== \"/api/app/push/unsubscribe\" && path !== \"/api/app/push/prefs\")) {\n return ok(404, { error: \"not found\" })\n }\n if (!store || unavailable) return ok(503, { error: unavailable })\n\n if (path === \"/api/app/push/prefs\") {\n // Any of the switches, each true or false; answers with those it set.\n const changes = (Object.keys(PUSH_PREFS) as PushPrefName[]).filter((n) => body[PUSH_PREFS[n].field] !== undefined)\n const fields = changes.map((n) => PUSH_PREFS[n].field).join(\", \")\n const all = Object.values(PUSH_PREFS).map((p) => p.field).join(\" or \")\n if (changes.length === 0) return ok(400, { error: `send ${all}, true or false` })\n if (changes.some((n) => typeof body[PUSH_PREFS[n].field] !== \"boolean\")) return ok(400, { error: `${fields} must be true or false` })\n const out: Record<string, boolean> = {}\n for (const n of changes) {\n store.prefs.set(device.id, n, body[PUSH_PREFS[n].field])\n out[PUSH_PREFS[n].field] = body[PUSH_PREFS[n].field]\n }\n return ok(200, { ok: true, ...out })\n }\n const endpoint = validEndpoint(body.endpoint, deps.allowedHosts)\n if (!endpoint) {\n let host = \"\"\n try { host = new URL(String(body.endpoint)).hostname } catch { /* not a URL */ }\n return ok(400, { error: `not a known push service${host ? `: ${host}` : \"\"} (see channels.push.allowedHosts)` })\n }\n\n if (path === \"/api/app/push/unsubscribe\") {\n return ok(200, { ok: true, removed: store.unsubscribe(endpoint, device.id) })\n }\n const p256dh = body.keys?.p256dh\n const auth = body.keys?.auth\n if (typeof p256dh !== \"string\" || !B64URL.test(p256dh) || typeof auth !== \"string\" || !B64URL.test(auth)) {\n return ok(400, { error: \"keys.p256dh and keys.auth are required\" })\n }\n // An endpoint belongs to one browser. If another device had it (a phone\n // re-paired under a new name), the latest pairing takes it over.\n // The browser subscribed with the key GET /api/app/push just handed it;\n // `publicKey` in the body must match it, so a stale page can't store a\n // subscription made with replaced keys.\n if (body.publicKey !== undefined && body.publicKey !== publicKey) {\n return ok(409, { error: \"this computer's push keys changed; turn notifications on again\" })\n }\n store.subscribe({ endpoint, p256dh, auth, deviceId: device.id, deviceName: device.name, publicKey: publicKey! })\n return ok(200, { ok: true })\n}\n\nfunction ok(status: number, body: unknown): AppPushResult {\n return { status, body }\n}\n\nfunction prefDefaults(): Record<string, boolean> {\n const out: Record<string, boolean> = {}\n for (const p of Object.values(PUSH_PREFS)) out[p.field] = p.default\n return out\n}\n\n/** The endpoint if it is https on an allowed push-service host (or a\n * subdomain of one). The daemon POSTs to whatever is stored, so a name\n * that merely looks public (and may resolve inside the network) is refused. */\nexport function validEndpoint(v: unknown, allowedHosts: string[]): string | null {\n if (typeof v !== \"string\" || v.length > MAX_ENDPOINT) return null\n try {\n const u = new URL(v)\n if (u.protocol !== \"https:\" || u.port || u.username || u.password) return null\n const host = u.hostname.toLowerCase()\n const ok = allowedHosts.some((h) => {\n const allowed = h.toLowerCase().replace(/^\\.+|\\.+$/g, \"\")\n return !!allowed && (host === allowed || host.endsWith(\".\" + allowed))\n })\n return ok ? v : null\n } catch {\n return null\n }\n}\n\nfunction json(res: ServerResponse, status: number, body: unknown): true {\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" })\n res.end(JSON.stringify(body))\n return true\n}\n","import type { IncomingMessage, ServerResponse } from \"http\"\n\n// --- Phone app: fleet, activity and control (/api/app/fleet, …) ---\n//\n// Phase 3 of the mobile epic. Runs behind the device-token check in\n// app-routes.ts, so every handler here may assume a paired phone.\n//\n// Reads reuse the dashboard's live snapshot (every node the dashboard can\n// see, including peers found through /mesh) and trim it to what a phone\n// shows: short previews, never full prompts, replies or errors. Writes go\n// to a node daemon through the dashboard's allowlisted, token-carrying POST\n// (AppFleetDeps.nodePost), the same path the desktop task and restart\n// buttons use, so the phone gets no power the dashboard doesn't already have.\n\nexport const PREVIEW_CHARS = 160\n\nexport interface SnapshotNode {\n id: string\n name: string\n url: string\n reachable: boolean\n error?: string\n uptimeSec?: number\n inflight?: number\n restart?: { state: string; requestedAt?: string; deadline?: string }\n agents: Array<{\n id: string\n name: string\n tier?: string\n color?: string\n active: number\n errors: number\n lastActive?: string\n lastSummary?: { text: string; at: string; ok: boolean }\n runningTasks?: Array<{ id: string; messagePreview: string; channel: string; chatId?: string; sender?: string; startedAt: string }>\n }>\n crons?: Array<{ id: string; enabled: boolean; schedule: string; agent: string; kind?: string; nextRun?: string; consecutiveErrors: number }>\n cronRuns?: Array<{ jobId: string; startedAt: string; status: string; responseSummary?: string; errorSummary?: string; isRetry?: boolean }>\n}\n\nexport interface ApprovalItem {\n key: string\n title: string\n ask?: string\n recommend?: string\n /** What yes and no do, in words. */\n yes?: string\n no?: string\n raisedBy?: string\n expires?: string\n}\n\nexport interface NodeApprovals {\n node: string\n nodeName: string\n items: ApprovalItem[]\n error?: string\n}\n\nexport interface NodeReply { status: number; body: any }\n\nexport interface AppFleetDeps {\n snapshot(day?: { date: string; timezone: string }): Promise<{ ts: string; nodes: SnapshotNode[] }>\n /** POST to a node daemon on the dashboard's allowlist, with its token. */\n nodePost(nodeUrl: string, path: string, body: unknown): Promise<NodeReply>\n approvals(): Promise<NodeApprovals[]>\n /** `by` names the phone, e.g. \"operator (phone: My phone)\". */\n decide(nodeUrl: string, key: string, action: \"yes\" | \"no\" | \"later\", by: string): Promise<NodeReply>\n}\n\nexport function clip(text: string | undefined, max = PREVIEW_CHARS): string | undefined {\n if (!text) return text\n const flat = text.replace(/\\s+/g, \" \").trim()\n return flat.length > max ? flat.slice(0, max - 1) + \"…\" : flat\n}\n\n/** One node, trimmed for the Fleet tab. Cron outcomes come from the node's\n * persisted run files (cronRuns), never the scheduler's counters. */\nexport function summarizeNode(n: SnapshotNode) {\n const lastRun = new Map<string, NonNullable<SnapshotNode[\"cronRuns\"]>[number]>()\n for (const r of n.cronRuns ?? []) {\n const prev = lastRun.get(r.jobId)\n if (!prev || prev.startedAt < r.startedAt) lastRun.set(r.jobId, r)\n }\n const today = { success: 0, failed: 0 }\n for (const r of n.cronRuns ?? []) {\n if (r.status === \"success\") today.success++\n else today.failed++\n }\n return {\n id: n.id,\n name: n.name,\n url: n.url,\n reachable: n.reachable,\n error: clip(n.error),\n uptimeSec: n.uptimeSec,\n inflight: n.inflight,\n restart: n.restart?.state && n.restart.state !== \"none\" ? n.restart : undefined,\n agents: n.agents.map((a) => ({\n id: a.id,\n name: a.name,\n tier: a.tier,\n active: a.active,\n errors: a.errors,\n lastActive: a.lastActive,\n last: a.lastSummary ? { text: clip(a.lastSummary.text), at: a.lastSummary.at, ok: a.lastSummary.ok } : undefined,\n })),\n crons: {\n today,\n items: (n.crons ?? []).map((c) => {\n const r = lastRun.get(c.id)\n return {\n id: c.id,\n enabled: c.enabled,\n schedule: c.schedule,\n agent: c.agent,\n nextRun: c.nextRun,\n consecutiveErrors: c.consecutiveErrors,\n last: r ? { status: r.status, at: r.startedAt, text: clip(r.status === \"success\" ? r.responseSummary : r.errorSummary) } : undefined,\n }\n }),\n },\n }\n}\n\n/** Every running task across the fleet, newest first. */\nexport function summarizeActivity(nodes: SnapshotNode[]) {\n const tasks = []\n for (const n of nodes) {\n for (const a of n.agents) {\n for (const t of a.runningTasks ?? []) {\n tasks.push({\n node: n.url,\n nodeName: n.name,\n agentId: a.id,\n agentName: a.name,\n taskId: t.id,\n preview: clip(t.messagePreview),\n channel: t.channel,\n startedAt: t.startedAt,\n })\n }\n }\n }\n return tasks.sort((x, y) => (x.startedAt < y.startedAt ? 1 : -1))\n}\n\nconst TASK_ACTION = /^\\/api\\/app\\/tasks\\/(cancel|followup)$/\n\n/** Handles /api/app/{fleet,activity,tasks,nodes,crons,approvals}. Returns\n * false for any other path so the caller can fall through. */\nexport async function handleAppFleet(\n req: IncomingMessage,\n res: ServerResponse,\n path: string,\n method: string,\n device: string,\n deps: AppFleetDeps,\n): Promise<boolean> {\n const url = new URL(req.url || path, \"http://localhost\")\n\n if (method === \"GET\" && (path === \"/api/app/fleet\" || path === \"/api/app/activity\")) {\n const timezone = validTimezone(url.searchParams.get(\"timezone\"))\n const snap = await deps.snapshot({ date: dateIn(timezone), timezone })\n if (path === \"/api/app/activity\") return json(res, 200, { ts: snap.ts, tasks: summarizeActivity(snap.nodes) })\n return json(res, 200, { ts: snap.ts, nodes: snap.nodes.map(summarizeNode) })\n }\n\n if (method === \"GET\" && path === \"/api/app/approvals\") {\n return json(res, 200, { nodes: await deps.approvals() })\n }\n\n if (method !== \"POST\") return false\n const taskAction = path.match(TASK_ACTION)\n const known = taskAction || [\n \"/api/app/nodes/restart\", \"/api/app/nodes/reload\", \"/api/app/crons/toggle\", \"/api/app/approvals/decide\",\n ].includes(path)\n if (!known) return false\n\n let body: Record<string, unknown>\n try { body = await readJson(req) } catch (e: any) { return json(res, 400, { error: e.message }) }\n const node = str(body.node)\n if (!node) return json(res, 400, { error: \"node is required\" })\n const by = `operator (phone: ${device})`\n\n let reply: NodeReply\n if (taskAction) {\n const taskId = str(body.taskId)\n if (!taskId) return json(res, 400, { error: \"taskId is required\" })\n const upstream = `/api/tasks/${encodeURIComponent(taskId)}/${taskAction[1]}`\n if (taskAction[1] === \"cancel\") {\n reply = await deps.nodePost(node, upstream, { reason: `cancelled by ${by}` })\n } else {\n const message = str(body.message)\n if (!message) return json(res, 400, { error: \"message is required\" })\n reply = await deps.nodePost(node, upstream, { message, sender: by })\n }\n } else if (path === \"/api/app/nodes/restart\") {\n reply = await deps.nodePost(node, body.cancel === true ? \"/daemon/restart/cancel\" : \"/daemon/restart\", {})\n } else if (path === \"/api/app/nodes/reload\") {\n reply = await deps.nodePost(node, \"/reload\", {})\n } else if (path === \"/api/app/crons/toggle\") {\n const cronId = str(body.cronId)\n if (!cronId || typeof body.enabled !== \"boolean\") return json(res, 400, { error: \"cronId and enabled (true or false) are required\" })\n reply = await deps.nodePost(node, `/crons/${encodeURIComponent(cronId)}/enabled`, { enabled: body.enabled })\n } else {\n const key = str(body.key)\n const action = body.action\n if (!key || (action !== \"yes\" && action !== \"no\" && action !== \"later\")) {\n return json(res, 400, { error: \"key and action (yes, no or later) are required\" })\n }\n reply = await deps.decide(node, key, action, by)\n }\n return json(res, reply.status, reply.body)\n}\n\nfunction str(v: unknown): string {\n return typeof v === \"string\" ? v.trim() : \"\"\n}\n\nfunction validTimezone(tz: string | null): string {\n if (!tz) return \"UTC\"\n try { new Intl.DateTimeFormat(\"en-US\", { timeZone: tz }); return tz } catch { return \"UTC\" }\n}\n\n/** YYYY-MM-DD for \"today\" in the phone's time zone. */\nexport function dateIn(timezone: string, now = new Date()): string {\n return new Intl.DateTimeFormat(\"en-CA\", { timeZone: timezone, year: \"numeric\", month: \"2-digit\", day: \"2-digit\" }).format(now)\n}\n\nexport async function readJson(req: IncomingMessage, limit = 16 * 1024): Promise<Record<string, unknown>> {\n let size = 0\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n size += (chunk as Buffer).length\n if (size > limit) throw new Error(\"body too large\")\n chunks.push(chunk as Buffer)\n }\n const raw = Buffer.concat(chunks).toString(\"utf-8\").trim()\n if (!raw) return {}\n const parsed = JSON.parse(raw)\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error(\"expected a JSON object\")\n return parsed\n}\n\nfunction json(res: ServerResponse, status: number, body: unknown): true {\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" })\n res.end(JSON.stringify(body))\n return true\n}\n"],"mappings":"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","names":["mkdirSync","readFileSync","renameSync","writeFileSync","dirname","resolve","clip","text","max","flat","summarizeNode","n","lastRun","r","prev","today","a","c","summarizeActivity","nodes","tasks","t","x","y","TASK_ACTION","handleAppFleet","req","res","path","method","device","deps","url","timezone","validTimezone","snap","dateIn","json","taskAction","body","readJson","e","node","str","by","reply","taskId","upstream","message","cronId","key","action","v","tz","now","limit","size","chunks","chunk","raw","parsed","status","isAppPushPath","path","MAX_ENDPOINT","B64URL","handleAppPush","req","res","method","device","deps","body","readJson","e","json","call","out","runAppPush","relayedPush","unreachable","RelayedPushState","file","saved","readFileSync","id","p","pickPrefsFrom","phone","pickPrefs","mkdirSync","dirname","tmp","writeFileSync","renameSync","deviceId","name","PUSH_PREFS","relayedPushHere","resolve","v","reason","prefDefaults","store","publicKey","unavailable","ok","s","changes","n","fields","all","endpoint","validEndpoint","host","p256dh","auth","status","allowedHosts","u","h","allowed"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as o}from"./chunk-
|
|
2
|
-
//# sourceMappingURL=chunk-
|
|
1
|
+
import{a as o}from"./chunk-KI4CIUVJ.js";import{resolve as a}from"path";import{existsSync as d,readdirSync as c,mkdirSync as l}from"fs";var g=class{baseDir;agentsDir;mode;sharedStore;agentStores=new Map;log;constructor(t=a(process.cwd(),".agentx/wiki"),e=console.error.bind(console,"[wiki-hub]"),r="graph"){this.baseDir=t,this.agentsDir=a(t,"agents"),this.mode=r,this.log=e,l(this.agentsDir,{recursive:!0}),this.sharedStore=new o(t,e)}getMode(){return this.mode}getAgentWiki(t){let e=`${t}:${this.mode}`;if(this.agentStores.has(e))return this.agentStores.get(e);let r=a(this.agentsDir,t,this.mode),i=new o(r,this.log);return this.agentStores.set(e,i),i}getBaseDir(){return this.baseDir}getSharedStore(){return this.sharedStore}listAgents(){let t=new Set,e=this.sharedStore.listEntries();for(let r of e)t.add(r.agentId);if(d(this.agentsDir))for(let r of c(this.agentsDir))!r.startsWith("_")&&!r.startsWith(".")&&t.add(r);return[...t].sort()}getAgentEntries(t){return this.sharedStore.listEntries({agentId:t})}getUnabsorbedEntries(t){let e=this.getAgentWiki(t),r=this.getAgentEntries(t),i=new Set,n=e.rebuildIndex();for(let s of n.articles)if(s.sources)for(let h of s.sources)i.add(h);return r.filter(s=>!i.has(s.id))}summary(){return this.listAgents().map(e=>{let r=this.getAgentEntries(e),n=this.getAgentWiki(e).rebuildIndex(),s=this.getUnabsorbedEntries(e);return{agentId:e,totalEntries:r.length,totalArticles:n.articles.length,unabsorbed:s.length,articles:n.articles}})}};export{g as a};
|
|
2
|
+
//# sourceMappingURL=chunk-EKOVLUKH.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{a as D,b as _}from"./chunk-RKPAVWXF.js";import{a as q,b as O,c as R,d as B,f as b,g as S,h as E,i as w,j as y}from"./chunk-
|
|
1
|
+
import{a as D,b as _}from"./chunk-RKPAVWXF.js";import{a as q,b as O,c as R,d as B,f as b,g as S,h as E,i as w,j as y}from"./chunk-Y3CZE54A.js";import{a as T,b as C,c as I,d as x,e as P}from"./chunk-JLCJVPRC.js";import{existsSync as X,readFileSync as F}from"fs";var J=new Set(["cron","heartbeat","api","a2a","mesh"]),M=160;function s(n){return typeof n=="string"&&n.trim()?n.trim():void 0}function A(n,e=M){let t=n.replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e-1)}\u2026`:t}function V(n){let e=T(n);if(!X(e))throw new Error(`config not found at ${e}`);return JSON.parse(F(e,"utf-8"))}function W(n,e){return n?.agents?.[e]?.admin===!0}function Y(n,e,t){return W(n,t.agentId)||e?.createdBy===t.agentId}function Z(n,e){let t=e?.createdBy?`agent "${e.createdBy}"`:"the operator";return`Not allowed: "${n}" was created by ${t}. Agents manage only schedules they created (unless configured admin).`}function K(n,e){let t=s(n.notify);if(t!=="none"){if(t&&t!=="here"){let r=t.split(":");return r.length<2||!r[0]||!r[1]?"invalid":{channel:r[0],chatId:r.slice(1).join(":")}}if(e.channel&&e.chatId&&!J.has(e.channel))return{channel:e.channel,chatId:e.chatId,...e.accountId?{accountId:e.accountId}:{}}}}function Q(n,e,t){let r=e.timezone||"UTC",u=e.enabled&&!y(e)?w(E(e.schedule,r,t),r):"\u2014",h=e.approval?`pending ${e.approval.action} approval`:e.enabled?"active":"paused",p=[`- ${n} [${h}] ${e.schedule} \u2014 ${S(e.schedule)} (${r})`,` agent: ${e.agent}; created by: ${e.createdBy||"operator"}; next: ${u}`];return e.notify&&p.push(` notify: ${e.notify.channel} ${e.notify.chatId}`),e.command?p.push(` command: ${A(String(e.command))}`):e.prompt&&p.push(` prompt: ${A(String(e.prompt))}`),p.join(`
|
|
2
2
|
`)}async function k(n,e,t){let r=n?.notifications?.destination;if(!r?.channel||!r?.chatId)return"No operator notification destination is configured (notifications.destination); the operator must check `agentx schedule list`.";if(!e.notifyOperator)return"Operator notification is unavailable in this context.";try{return await e.notifyOperator({channel:r.channel,chatId:r.chatId,accountId:r.accountId},t),"The operator has been notified."}catch(u){return`Could not notify the operator (${u?.message??u}); the request is still recorded.`}}async function re(n,e,t={}){let r=(s(n.action)||"list").toLowerCase(),u=t.now?t.now():new Date,h;try{h=V(t.configPath)}catch(a){return`Error: ${a.message}`}let p=h.crons||{};if(r==="list"){let a=n.mine===!0,l=Object.entries(p).filter(([,i])=>!a||e&&i?.createdBy===e.agentId);return l.length?l.map(([i,f])=>Q(i,f,u)).join(`
|
|
3
3
|
`):a?"You have no schedules.":"No schedules."}if(!e?.agentId)return"Error: caller agent is unknown (AGENTX_AGENT_ID not set). Pass callerAgentId.";if(!h.agents?.[e.agentId])return`Error: caller "${e.agentId}" is not an agent on this node.`;let o=s(n.id),m=a=>C(a,{configPath:t.configPath,reload:t.reload});if(r==="create"){let a=s(n.when),l=s(n.prompt);if(!a||!l)return"Error: create needs `when` (plain English) and `prompt`.";let i=D(a);if(!i)return`Error: couldn't parse "${a}". ${O}.`;let f=s(n.agent)||e.agentId;if(!h.agents?.[f])return`Error: agent "${f}" not found on this node.`;let g=s(n.timezone)||q;if(!B(g))return`Error: unknown timezone "${g}".`;let d=o||_(i.matched,f);if(!R(d))return`Error: invalid id "${d}" (letters, digits, "-" and "_" only).`;if(p[d])return`Error: a schedule "${d}" already exists. Pick another \`id\`.`;let $=K(n,e);if($==="invalid")return'Error: `notify` must be "here", "none", or "channel:chatId".';let z={action:"create",requestedBy:e.agentId,requestedAt:u.toISOString()},L=b({parsed:i,agent:f,prompt:l,timezone:g,notify:$,enabled:!1,createdBy:e.agentId,approval:z}),v=await m(U=>I(U,`crons.${d}`,L));if(!v.success)return`Error: ${v.error}`;let N=w(E(i.cron,g,u),g),G=[`Schedule approval requested by ${e.agentId}`,`Create: ${d}`,`When: ${i.human} \u2014 cron \`${i.cron}\` (${g})`,`Next fire: ${N}`,`Agent: ${f}`,$?`Notify: ${$.channel} ${$.chatId}`:"Notify: none",`Prompt: ${A(l,400)}`,"",`Approve: agentx schedule approve ${d}`,`Reject: agentx schedule reject ${d}`].join(`
|
|
4
4
|
`),H=await k(h,t,G);return[`Requested schedule "${d}": ${i.human} (cron ${i.cron}, ${g}); next fire would be ${N}.`,"It is saved DISABLED and will not run until the operator approves it.",H].join(`
|
|
5
5
|
`)}if(!o)return`Error: ${r} needs \`id\`.`;let c=p[o];if(!c)return`Error: schedule "${o}" not found.`;if(!Y(h,c,e))return Z(o,c);if(r==="pause"||r==="resume"){let a=r==="resume";if(a&&y(c))return`"${o}" is still awaiting operator approval; it can't be resumed until approved.`;if(c.enabled===a)return`"${o}" is already ${a?"active":"paused"}.`;let l=await m(i=>I(i,`crons.${o}.enabled`,a));return l.success?`"${o}" ${a?"resumed":"paused"}.`:`Error: ${l.error}`}if(r==="delete"){if(y(c)&&c.approval.requestedBy===e.agentId){let d=await m($=>P($,`crons.${o}`));return d.success?`Withdrew the pending request "${o}".`:`Error: ${d.error}`}if(y(c))return`"${o}" is a creation request still awaiting approval; only its requester or the operator (\`agentx schedule reject ${o}\`) can drop it.`;if(c.approval?.action==="delete")return`Deletion of "${o}" is already awaiting approval.`;let a={action:"delete",requestedBy:e.agentId,requestedAt:u.toISOString()},l=await m(d=>{if(!x(d,`crons.${o}`))throw new Error(`schedule "${o}" not found`);I(d,`crons.${o}.approval`,a)});if(!l.success)return`Error: ${l.error}`;let i=c.timezone||"UTC",f=[`Schedule approval requested by ${e.agentId}`,`Delete: ${o}`,`When: ${S(c.schedule)} \u2014 cron \`${c.schedule}\` (${i})`,`Next fire: ${c.enabled?w(E(c.schedule,i,u),i):"\u2014 (paused)"}`,`Agent: ${c.agent}`,"",`Approve: agentx schedule approve ${o}`,`Reject: agentx schedule reject ${o}`].join(`
|
|
6
6
|
`),g=await k(h,t,f);return[`Deletion of "${o}" requested. It keeps its current state until the operator approves.`,g].join(`
|
|
7
7
|
`)}return`Error: unknown action "${r}". Use list, create, pause, resume or delete.`}function oe(n,e=process.env){let t=s(e.AGENTX_AGENT_ID)||s(n.callerAgentId);if(!t)return null;let r=!!(s(e.AGENTX_CHANNEL)&&s(e.AGENTX_CHAT_ID)),u=s(r?e.AGENTX_CHANNEL:n.channel),h=s(r?e.AGENTX_CHAT_ID:n.chatId),p=s(n.accountId);return{agentId:t,channel:u,chatId:h,...p?{accountId:p}:{}}}export{re as a,oe as b};
|
|
8
|
-
//# sourceMappingURL=chunk-
|
|
8
|
+
//# sourceMappingURL=chunk-ELWKTURG.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{createHash as p,randomBytes as c}from"crypto";import{existsSync as d,mkdirSync as g,readFileSync as l,renameSync as A,writeFileSync as m}from"fs";import{resolve as x,dirname as k}from"path";var a="agx_live_",w=".agentx/tokens.json",h=class{file;constructor(e=process.cwd(),t=w){this.file=x(e,t)}load(){if(!d(this.file))return[];try{return JSON.parse(l(this.file,"utf-8"))}catch{return[]}}save(e){g(k(this.file),{recursive:!0});let t=`${this.file}.${process.pid}.tmp`;m(t,JSON.stringify(e,null,2)+`
|
|
2
|
+
`,"utf-8"),A(t,this.file)}activePhoneIds(e=Date.now()){if(!d(this.file))return[];let t=JSON.parse(l(this.file,"utf-8"));if(!Array.isArray(t))throw new Error(`${this.file} is not a list of tokens`);return t.filter(s=>s?.scopes?.includes("app")&&!s.revokedAt&&!(s.expiresAt&&Date.parse(s.expiresAt)<e)).map(s=>s.id)}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(!v(o))throw new Error(`Invalid scope: ${o}`);let t=c(32).toString("hex"),s=a+t,n={id:"tok_"+c(4).toString("hex"),name:e.name.trim(),prefix:a+t.slice(0,4),hash:u(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(n),this.save(i),{token:s,record:n}}list(){return this.load()}revoke(e){let t=this.load(),s=t.find(n=>n.id===e);return s?(s.revokedAt=new Date().toISOString(),this.save(t),s):null}isActive(e){let t=this.load().find(s=>s.id===e);return!!t&&!t.revokedAt&&!(t.expiresAt&&Date.parse(t.expiresAt)<Date.now())}verify(e){if(!e||!e.startsWith(a))return null;let t=u(e),s=this.load(),n=s.find(f=>f.hash===t);if(!n||n.revokedAt||n.expiresAt&&Date.parse(n.expiresAt)<Date.now())return null;let i=Date.now(),o=n.lastUsedAt?Date.parse(n.lastUsedAt):0;if(i-o>6e4){n.lastUsedAt=new Date(i).toISOString();try{this.save(s)}catch{}}return n}};function T(r,e){return!!(r.scopes.includes(e)||e.startsWith("agent:")&&r.scopes.includes("agent:*")||e==="dashboard:read"&&r.scopes.includes("dashboard:write"))}function v(r){return r==="dashboard:read"||r==="dashboard:write"||r==="agent:*"||/^agent:[a-z0-9][a-z0-9_-]*$/.test(r)||r==="mesh:peer"||r==="app"||/^member:[a-z0-9][a-z0-9_-]{0,39}$/.test(r)||/^guest:g-[a-z0-9]+-[a-z0-9]+$/.test(r)}function u(r){return"sha256:"+p("sha256").update(r).digest("hex")}function R(r){let e=r.headers.authorization,t=Array.isArray(e)?e[0]:e;if(t&&t.toLowerCase().startsWith("bearer "))return t.slice(7).trim();if(r.url)try{let n=new URL(r.url,"http://localhost").searchParams.get("token");if(n)return n}catch{}return null}export{a,h as b,T as c,u as d,R as e};
|
|
3
|
+
//# sourceMappingURL=chunk-EMGB23H5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/daemon/token-store.ts"],"sourcesContent":["import { createHash, randomBytes } from \"crypto\"\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"fs\"\nimport { resolve, dirname } from \"path\"\n\n// --- Scoped API tokens ---\n//\n// Tokens let external services (other agentx instances, webhook senders, custom\n// apps) talk to this daemon with explicit scopes instead of sharing a single\n// all-powerful dashboard token.\n//\n// We only ever store the sha256 of each token + its printable prefix. The full\n// token is shown exactly once, at creation time, and the operator copies it.\n// Format: agx_live_<hex(32)> — prefix lets secret-scanners catch leaks.\n//\n// Scopes (string equality; \"agent:*\" grants any agent):\n// dashboard:read — /api/live, /api/agents, /api/task/history\n// dashboard:write — /api/admin/*, config mutation endpoints\n// agent:<id> — /api/public/agents/<id>/messages\n// agent:* — any agent\n// mesh:peer — cross-node mesh (forward-compatible — not enforced yet)\n// app — the phone app (/app, /api/app/*) and nothing else;\n// minted per device by `agentx app pair`\n// member:<person> — one teammate's own work page (/member, /api/member/*)\n// and nothing else; minted per machine by\n// `agentx people invite` (#385)\n// guest:<grant> — a guest mesh's key: /mesh/guest/* inside that grant\n// and nothing else; minted by `agentx mesh guests\n// invite` (#380)\n\nexport const TOKEN_PREFIX = \"agx_live_\"\nconst DEFAULT_FILE = \".agentx/tokens.json\"\n\nexport interface TokenRecord {\n id: string // short public id (shown in lists)\n name: string\n prefix: string // full printable prefix (TOKEN_PREFIX + first-4 chars of body)\n hash: string // sha256 of the full token\n scopes: string[]\n createdAt: string\n expiresAt?: string\n revokedAt?: string\n lastUsedAt?: string\n}\n\nexport class TokenStore {\n private file: string\n\n constructor(baseDir: string = process.cwd(), fileRel: string = DEFAULT_FILE) {\n this.file = resolve(baseDir, fileRel)\n }\n\n private load(): TokenRecord[] {\n if (!existsSync(this.file)) return []\n try { return JSON.parse(readFileSync(this.file, \"utf-8\")) as TokenRecord[] } catch { return [] }\n }\n\n private save(records: TokenRecord[]): void {\n mkdirSync(dirname(this.file), { recursive: true })\n // Write then rename, so a reader in another process (the dashboard, the\n // daemon's push roster) never sees a half-written file.\n const tmp = `${this.file}.${process.pid}.tmp`\n writeFileSync(tmp, JSON.stringify(records, null, 2) + \"\\n\", \"utf-8\")\n renameSync(tmp, this.file)\n }\n\n /** Ids of the paired phones that are neither revoked nor expired. Unlike\n * list(), throws when the file is there but can't be read or parsed,\n * so a bad read is never taken for \"no phones\" (the push roster would\n * then unsubscribe every one of them on the host, #711). */\n activePhoneIds(now = Date.now()): string[] {\n if (!existsSync(this.file)) return []\n const records = JSON.parse(readFileSync(this.file, \"utf-8\"))\n if (!Array.isArray(records)) throw new Error(`${this.file} is not a list of tokens`)\n return (records as TokenRecord[])\n .filter((r) => r?.scopes?.includes(\"app\") && !r.revokedAt && !(r.expiresAt && Date.parse(r.expiresAt) < now))\n .map((r) => r.id)\n }\n\n /**\n * Mint a new token. Returns the full token string AND the record.\n * The full token is the only place the secret is ever exposed — the caller\n * must surface it to the operator immediately; after this call the store only\n * knows the hash.\n */\n create(input: {\n name: string\n scopes: string[]\n expiresInDays?: number\n }): { token: string; record: TokenRecord } {\n if (!input.name?.trim()) throw new Error(\"Token name is required.\")\n if (!Array.isArray(input.scopes) || input.scopes.length === 0) {\n throw new Error(\"At least one scope is required.\")\n }\n for (const s of input.scopes) {\n if (!isValidScope(s)) throw new Error(`Invalid scope: ${s}`)\n }\n const body = randomBytes(32).toString(\"hex\")\n const token = TOKEN_PREFIX + body\n const record: TokenRecord = {\n id: \"tok_\" + randomBytes(4).toString(\"hex\"),\n name: input.name.trim(),\n prefix: TOKEN_PREFIX + body.slice(0, 4),\n hash: hashToken(token),\n scopes: [...input.scopes],\n createdAt: new Date().toISOString(),\n expiresAt: input.expiresInDays\n ? new Date(Date.now() + input.expiresInDays * 86400 * 1000).toISOString()\n : undefined,\n }\n const records = this.load()\n records.push(record)\n this.save(records)\n return { token, record }\n }\n\n list(): TokenRecord[] {\n return this.load()\n }\n\n revoke(id: string): TokenRecord | null {\n const records = this.load()\n const rec = records.find((r) => r.id === id)\n if (!rec) return null\n rec.revokedAt = new Date().toISOString()\n this.save(records)\n return rec\n }\n\n /** True when the token with this id exists and is neither revoked nor expired. */\n isActive(id: string): boolean {\n const rec = this.load().find((r) => r.id === id)\n return !!rec && !rec.revokedAt && !(rec.expiresAt && Date.parse(rec.expiresAt) < Date.now())\n }\n\n /**\n * Look up a token string. Returns the record on success, null on unknown /\n * revoked / expired. Updates lastUsedAt opportunistically (write-on-success).\n */\n verify(token: string): TokenRecord | null {\n if (!token || !token.startsWith(TOKEN_PREFIX)) return null\n const hash = hashToken(token)\n const records = this.load()\n const rec = records.find((r) => r.hash === hash)\n if (!rec) return null\n if (rec.revokedAt) return null\n if (rec.expiresAt && Date.parse(rec.expiresAt) < Date.now()) return null\n // Throttle lastUsedAt updates to at most once per minute to avoid disk churn.\n const now = Date.now()\n const last = rec.lastUsedAt ? Date.parse(rec.lastUsedAt) : 0\n if (now - last > 60_000) {\n rec.lastUsedAt = new Date(now).toISOString()\n try { this.save(records) } catch { /* best-effort */ }\n }\n return rec\n }\n}\n\n/**\n * Check whether a record has a given required scope. \"agent:<id>\" required\n * matches either itself or \"agent:*\". \"dashboard:write\" implicitly grants\n * \"dashboard:read\" for convenience.\n */\nexport function recordHasScope(record: TokenRecord, required: string): boolean {\n if (record.scopes.includes(required)) return true\n if (required.startsWith(\"agent:\") && record.scopes.includes(\"agent:*\")) return true\n if (required === \"dashboard:read\" && record.scopes.includes(\"dashboard:write\")) return true\n return false\n}\n\nfunction isValidScope(s: string): boolean {\n return (\n s === \"dashboard:read\" ||\n s === \"dashboard:write\" ||\n s === \"agent:*\" ||\n /^agent:[a-z0-9][a-z0-9_-]*$/.test(s) ||\n s === \"mesh:peer\" ||\n s === \"app\" ||\n /^member:[a-z0-9][a-z0-9_-]{0,39}$/.test(s) ||\n /^guest:g-[a-z0-9]+-[a-z0-9]+$/.test(s)\n )\n}\n\nexport function hashToken(token: string): string {\n return \"sha256:\" + createHash(\"sha256\").update(token).digest(\"hex\")\n}\n\n/**\n * Extract a bearer token from the request headers. Falls back to the\n * `?token=` query param so EventSource (which can't set headers in most\n * browsers) can still authenticate.\n */\nexport function extractToken(req: { headers: Record<string, string | string[] | undefined>; url?: string }): string | null {\n const auth = req.headers[\"authorization\"]\n const authHeader = Array.isArray(auth) ? auth[0] : auth\n if (authHeader && authHeader.toLowerCase().startsWith(\"bearer \")) {\n return authHeader.slice(7).trim()\n }\n if (req.url) {\n try {\n const u = new URL(req.url, \"http://localhost\")\n const tok = u.searchParams.get(\"token\")\n if (tok) return tok\n } catch { /* */ }\n }\n return null\n}\n"],"mappings":"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","names":["createHash","randomBytes","existsSync","mkdirSync","readFileSync","renameSync","writeFileSync","resolve","dirname","TOKEN_PREFIX","DEFAULT_FILE","TokenStore","baseDir","fileRel","records","tmp","now","r","input","s","isValidScope","body","token","record","hashToken","id","rec","hash","last","recordHasScope","required","extractToken","req","auth","authHeader","tok"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{l as U,m as F,n as He}from"./chunk-UIBUZ2N3.js";import{b as M,d as B,h as Fe}from"./chunk-BRK6M6LA.js";import{a as q,e as Ue}from"./chunk-2QNT5JDS.js";import{a as m,b as Be}from"./chunk-QIJLFPWE.js";import{z as s}from"zod";var ze,We,Ke,Xe,Ze,Ge,Ye,Ve,Je,H,z=m(()=>{"use strict";ze=s.enum(["mon","tue","wed","thu","fri","sat","sun"]),We=s.object({days:s.array(ze).default(["mon","tue","wed","thu","fri"]),start:s.string().regex(/^\d{2}:\d{2}$/),end:s.string().regex(/^\d{2}:\d{2}$/),lunch:s.object({start:s.string().regex(/^\d{2}:\d{2}$/),end:s.string().regex(/^\d{2}:\d{2}$/)}).optional()}),Ke=s.object({title:s.string(),responsibilities:s.array(s.string()).default([]),sopPath:s.string().optional(),kpis:s.array(s.string()).default([])}),Xe=s.object({role:s.string(),reportsTo:s.string().optional(),schedule:We,utilizationTarget:s.number().min(0).max(1).default(.8)}),Ze=s.object({channel:s.string(),chatId:s.string(),accountId:s.string().optional()}),Ge=s.discriminatedUnion("type",[s.object({type:s.literal("backlog"),path:s.string().default(".agentx/backlog.md")}),s.object({type:s.literal("gitlab"),projects:s.array(s.string()).default([])}),s.object({type:s.literal("wiki"),path:s.string(),glob:s.string().default("**/*.md")})]),Ye=s.object({id:s.string(),pm:s.string().optional(),client:s.string().optional()}),Ve=s.object({channel:s.string().optional(),chatId:s.string().optional(),username:s.string().optional(),senderId:s.string().optional(),client:s.string(),project:s.string().optional(),displayName:s.string().optional()}),Je=s.object({name:s.string().optional(),kind:s.enum(["client","internal","own"]).optional(),respondWithin:s.string().optional(),standing:s.array(s.string()).default([])}),H=s.object({enabled:s.boolean().default(!1),timezone:s.string().default("UTC"),mainChannel:Ze,workSource:Ge,roles:s.record(s.string(),Ke).default({}),orgChart:s.record(s.string(),Xe).default({}),projects:s.array(Ye).default([]),contactMap:s.array(Ve).default([]),clients:s.record(s.string(),Je).default({}),workTickMinutes:s.number().int().min(1).max(60).default(15),idleQueueThreshold:s.number().int().min(0).default(0),standup:s.object({enabled:s.boolean().default(!0),plansDir:s.string().default(".agentx/plans"),maxAgentsPerDay:s.number().int().min(1).max(100).default(20),dryRun:s.boolean().default(!1)}).default({})})});import{z as d}from"zod";function Sn(r,n){let t=new Set(r.labels||[]);if(r.state==="closed"){let o=n.find(i=>i.kind==="closed");if(o)return o.id}for(let o of n)if(o.kind==="scoped-label"&&o.scopedLabel&&t.has(o.scopedLabel))return o.id;for(let o of n)if(o.kind==="label"&&o.mapsToLabel&&t.has(o.mapsToLabel))return o.id;let a=n.find(o=>o.kind==="open-backlog");if(a){let o=a.scopedPrefix+"::";return[...t].some(l=>l.startsWith(o))?null:a.id}return n[0]?.id??null}function En(r,n){let t=[],a=[],o=!1,i=!1;return n.kind==="scoped-label"&&n.scopedLabel?t.push(n.scopedLabel):n.kind==="label"&&n.mapsToLabel?t.push(n.mapsToLabel):n.kind==="closed"&&(o=!0),r&&(r.kind==="scoped-label"&&r.scopedLabel?a.push(r.scopedLabel):r.kind==="label"&&r.mapsToLabel?a.push(r.mapsToLabel):r.kind==="closed"&&n.kind!=="closed"&&(i=!0)),{addLabels:t.length?t:void 0,removeLabels:a.length?a:void 0,closeIssue:o||void 0,reopen:i||void 0}}var Qe,et,tt,nt,rt,at,W,ot,K,X=m(()=>{"use strict";Qe=d.object({name:d.string(),color:d.string().regex(/^#[0-9a-f]{6}$/i).default("#6366f1"),description:d.string().optional()}),et=d.object({id:d.string().regex(/^[a-z0-9_-]+$/,"column id must be lowercase slug"),title:d.string(),kind:d.enum(["open-backlog","scoped-label","closed","label"]).default("label"),mapsToLabel:d.string().optional(),scopedLabel:d.string().optional(),scopedPrefix:d.string().default("Status"),accent:d.string().optional()}),tt=d.object({enabled:d.boolean().default(!0),staleDoingMinutes:d.number().int().min(1).default(45),respectLunchBreak:d.boolean().default(!0),respectSchedule:d.boolean().default(!0),action:d.enum(["badge","notify"]).default("badge")}),nt=d.discriminatedUnion("type",[d.object({type:d.literal("gitlab"),projects:d.array(d.string()).min(1)})]),rt=[{id:"open",title:"Open",kind:"open-backlog",scopedPrefix:"Status",accent:"#6b7280"},{id:"todo",title:"To Do",kind:"scoped-label",scopedLabel:"Status::To Do",scopedPrefix:"Status",accent:"#fb7a35"},{id:"doing",title:"Doing",kind:"scoped-label",scopedLabel:"Status::Doing",scopedPrefix:"Status",accent:"#22c55e"},{id:"onhold",title:"On Hold",kind:"scoped-label",scopedLabel:"Status::On Hold",scopedPrefix:"Status",accent:"#f59e0b"},{id:"review",title:"Review",kind:"scoped-label",scopedLabel:"Status::Review",scopedPrefix:"Status",accent:"#3b82f6"},{id:"closed",title:"Closed",kind:"closed",scopedPrefix:"Status",accent:"#6b7280"}],at=d.object({id:d.string().regex(/^[a-z0-9_-]+$/,"board id must be lowercase slug"),name:d.string(),source:nt,primaryToolLabel:d.string().optional(),labels:d.array(Qe).default([]),columns:d.array(et).min(1).default(rt),timeRangeDays:d.number().int().min(1).max(365).default(30),closedWindowDays:d.number().int().min(1).max(365).default(30),reconciliation:tt.default({})}),W=d.array(at).default([]),ot=d.object({name:d.string(),url:d.string(),dashboardUrl:d.string().optional(),token:d.string().optional(),dashboardToken:d.string().optional()}),K=d.object({enabled:d.boolean().default(!1),port:d.number().int().default(4202),bind:d.string().default("127.0.0.1"),token:d.string().optional(),daemonUrl:d.string().default("http://localhost:18800"),daemons:d.array(ot).default([]),draftAgent:d.string().optional()}).default({})});function ct(r){let n=String(r??"").trim().toLowerCase();if(!n)return{ok:!1,error:"is empty"};let t=n.split("+").map(i=>i.trim());if(t.some(i=>!i))return{ok:!1,error:`"${r}" has an empty part; write it like opt+space`};let a=dt[t[t.length-1]]??t[t.length-1],o=new Set;for(let i of t.slice(0,-1)){let l=it[i];if(!l)return{ok:!1,error:`"${i}" is not a modifier; use ctrl, opt, shift or cmd`};if(o.has(l))return{ok:!1,error:`"${r}" names ${l} twice`};o.add(l)}return ut(a)?!Z(a)&&!["ctrl","opt","cmd"].some(i=>o.has(i))?{ok:!1,error:`"${r}" needs ctrl, opt or cmd, or it would take that key away from your typing`}:{ok:!0,value:[...st.filter(i=>o.has(i)),a].join("+")}:{ok:!1,error:`"${a}" is not a key AgentX Voice can use; use a letter, a digit, f1 to f20, or space, period, comma, slash, return, tab`}}function G(r){let n=ct(r);return n.ok?void 0:n.error}function wn(r){let n={ctrl:"\u2303",opt:"\u2325",shift:"\u21E7",cmd:"\u2318"},t={space:"Space",period:".",comma:",",slash:"/",semicolon:";",quote:"'",minus:"-",equal:"=",leftbracket:"[",rightbracket:"]",backslash:"\\",grave:"`",return:"Return",tab:"Tab"},a=r.split("+"),o=a.pop()??"";return a.map(i=>n[i]??i).join("")+(t[o]??o.toUpperCase())}var it,st,lt,dt,Z,ut,E,Y=m(()=>{"use strict";it={ctrl:"ctrl",control:"ctrl",opt:"opt",option:"opt",alt:"opt",shift:"shift",cmd:"cmd",command:"cmd"},st=["ctrl","opt","shift","cmd"],lt=["space","period","comma","slash","semicolon","quote","minus","equal","leftbracket","rightbracket","backslash","grave","return","tab"],dt={".":"period",",":"comma","/":"slash",";":"semicolon","'":"quote","-":"minus","=":"equal","`":"grave",enter:"return"},Z=r=>/^f([1-9]|1[0-9]|20)$/.test(r),ut=r=>/^[a-z0-9]$/.test(r)||lt.includes(r)||Z(r);E={talk:"opt+space",stop:"cmd+opt+period",paste:"cmd+opt+v"}});function Q(r){let n=/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(r);if(!n)return null;let[t,a,o]=n.slice(1).map(b=>parseInt(b,16)/255),i=Math.max(t,a,o),l=Math.min(t,a,o),u=i-l;return u<.04?null:((i===t?(a-o)/u%6:i===a?(o-t)/u+2:(t-a)/u+4)*60+360)%360}function ft(r){let n=Q(r);if(n===null)return x.find(o=>o.id==="lagoon");let t=x[0],a=360;for(let o of x){let i=Math.abs(o.hue-n),l=Math.min(i,360-i);l<a&&(t=o,a=l)}return t}function Tn(r,n=k){let t=l=>x.find(u=>u.id===l),a=t(r?.palette);if(a)return{...a,set:!0};let o=r?.color;return{...o&&Q(o)!==null?ft(o):t(n)??t(k),set:!1}}var x,V,J,L,k,ee=m(()=>{"use strict";x=[{id:"sunrise",label:"Sunrise",hue:18,colors:["#E8505B","#F2726F","#F79A5A","#FBBF4A","#FFE3A3"]},{id:"desert",label:"Desert",hue:36,colors:["#A4492C","#C8683E","#D9905E","#E7B98A","#F6E3C4"]},{id:"forest",label:"Forest",hue:100,colors:["#2F5D34","#4C7D3A","#6FA046","#9CC25E","#D5EBA4"]},{id:"lagoon",label:"Lagoon",hue:172,colors:["#0B6E73","#0E9594","#1FBFB2","#56DCCB","#B8F4EA"]},{id:"ocean",label:"Ocean",hue:205,colors:["#15457E","#1C6BA8","#2B93CF","#5DBBE8","#BFE6FA"]},{id:"dusk",label:"Dusk",hue:268,colors:["#2E2A7A","#5B3E9E","#8C4FB0","#C8649E","#F4A7B9"]},{id:"blossom",label:"Blossom",hue:330,colors:["#A3245B","#CF3F78","#E8699A","#F49BB8","#FFD6E0"]}],V=["orb","character"],J=["off","rarely","sometimes","often"],L=x.map(r=>r.id);k="lagoon"});function te(r){let n=(r.match(/[-ۿ]/g)??[]).length,t=(r.match(/[a-zA-ZÀ-ÿ]/g)??[]).length;if(n&&n>=t)return"ar";let a=0,o=0;for(let i of r.toLowerCase().replace(/[’]/g,"'").match(/[a-zà-ÿœ']+/g)??[])mt.has(i)&&a++,gt.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?o++:pt.test(i)&&(o+=.5);return a===o?null:a>o?"en":"fr"}var mt,gt,pt,ne=m(()=>{"use strict";mt=new Set("the and is are was were i you he she we they it this that to of in for with not but yes what have has will would can your my".split(" ")),gt=new Set("le la les des du de un une et est sont je tu il elle nous vous ils elles ce cette c'est pas pour que qui avec dans sur au aux mais tr\xE8s oui non merci bonjour votre mon".split(" ")),pt=/[éèêëàâçùûîïôœ]/});function vn(r,n=O){let t=r;if(t=t.replace(/```[\s\S]*?```/g,". "),t=t.replace(/`[^`]*`/g,""),t=t.replace(/\*\*(.*?)\*\*/g,"$1"),t=t.replace(/__(.*?)__/g,"$1"),t=t.replace(/\*([^*]+)\*/g,"$1"),t=t.replace(/_([^_]+)_/g,"$1"),t=t.replace(/~~(.*?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),t=t.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),t=t.replace(/^#{1,6}\s+/gm,""),t=t.replace(/^[\s]*[-*+]\s+/gm,". "),t=t.replace(/^[\s]*\d+\.\s+/gm,". "),t=t.replace(/^[-=_]{3,}$/gm,""),t=t.replace(/^>\s*/gm,""),t=t.replace(/https?:\/\/\S+/g,"link"),t=t.replace(/\/\w+(\/\w+)+/g,a=>a.split("/").filter(Boolean).join(" slash ")),t=t.replace(/&/g," and "),t=t.replace(/@/g," at "),t=t.replace(/=>/g," returns "),t=t.replace(/->/g," to "),t=t.replace(/\|/g," or "),t=t.replace(/\be\.g\./gi,"for example"),t=t.replace(/\bi\.e\./gi,"that is"),t=t.replace(/\betc\./gi,"etcetera"),t=t.replace(/\bvs\.?\b/gi,"versus"),t=t.replace(/\n{2,}/g,". "),t=t.replace(/\n/g," "),t=t.replace(/\s+/g," "),t=t.replace(/\.\s*\./g,"."),t=t.replace(/\s+([.,!?])/g,"$1"),t=t.trim().replace(/^[.,:;]+\s*/,""),t.length>n){let a=t.slice(0,n),o=([...t.slice(0,n+1).matchAll(/[.!?؟](?=\s)/g)].at(-1)?.index??-1)+1;t=(o>=n/2?a.slice(0,o):a.replace(/\s+\S*$/,"")+"...")+" "+bt[te(a)??"en"]}return t}var O,bt,re=m(()=>{"use strict";ne();O=500,bt={en:"The rest is on screen.",fr:"La suite est \xE0 l'\xE9cran.",ar:"\u0627\u0644\u0628\u0627\u0642\u064A \u0639\u0644\u0649 \u0627\u0644\u0634\u0627\u0634\u0629."}});function On(r,n=j){let t=new Set(n.map(ae)),a=r.replace(/\[([^\][]*)\]|\(([^()]*)\)/g,(o,i,l)=>t.has(ae(i??l))?"":o);return!/[\p{L}\p{N}]/u.test(a)}var j,Ln,ae,oe=m(()=>{"use strict";j=["background noise","noise","mumbling","babbling","unintelligible","inaudible","muffled speech","pause","silence","music","outro jingle","blank audio"],Ln="I didn't catch that.",ae=r=>r.toLowerCase().replace(/[_\s]+/g," ").trim()});import{z as c}from"zod";var ie,ht,se,le=m(()=>{"use strict";ie=c.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/,"use HH:MM, 24-hour"),ht=c.object({id:c.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/,"lowercase letters, digits, - and _"),enabled:c.boolean().default(!0),chats:c.array(c.string().min(1)).default([]),senders:c.array(c.string().min(1)).default([]),agent:c.string().min(1),prompt:c.string().max(4e3).optional(),quietHours:c.object({start:ie,end:ie}).optional(),autoAck:c.boolean().default(!1)}).refine(r=>r.chats.length>0||r.senders.length>0,{message:"a rule needs at least one chat or sender"}),se=c.object({enabled:c.boolean().default(!1),secretEnv:c.string().regex(/^[A-Z_][A-Z0-9_]*$/).default("WACLI_WEBHOOK_SECRET"),batchSeconds:c.number().int().min(0).max(600).default(20),timezone:c.string().optional(),allowAutoAck:c.boolean().default(!1),describeMedia:c.boolean().default(!0),wacli:c.object({bin:c.string().default("wacli"),account:c.string().optional(),store:c.string().optional()}).default({}),rules:c.array(ht).default([])}).default({})});function yt(r){r.exec(`
|
|
1
|
+
import{b as M,d as B,h as Fe}from"./chunk-BRK6M6LA.js";import{l as U,m as F,n as He}from"./chunk-UIBUZ2N3.js";import{a as q,e as Ue}from"./chunk-2QNT5JDS.js";import{a as m,b as Be}from"./chunk-QIJLFPWE.js";import{z as s}from"zod";var ze,We,Ke,Xe,Ze,Ge,Ye,Ve,Je,H,z=m(()=>{"use strict";ze=s.enum(["mon","tue","wed","thu","fri","sat","sun"]),We=s.object({days:s.array(ze).default(["mon","tue","wed","thu","fri"]),start:s.string().regex(/^\d{2}:\d{2}$/),end:s.string().regex(/^\d{2}:\d{2}$/),lunch:s.object({start:s.string().regex(/^\d{2}:\d{2}$/),end:s.string().regex(/^\d{2}:\d{2}$/)}).optional()}),Ke=s.object({title:s.string(),responsibilities:s.array(s.string()).default([]),sopPath:s.string().optional(),kpis:s.array(s.string()).default([])}),Xe=s.object({role:s.string(),reportsTo:s.string().optional(),schedule:We,utilizationTarget:s.number().min(0).max(1).default(.8)}),Ze=s.object({channel:s.string(),chatId:s.string(),accountId:s.string().optional()}),Ge=s.discriminatedUnion("type",[s.object({type:s.literal("backlog"),path:s.string().default(".agentx/backlog.md")}),s.object({type:s.literal("gitlab"),projects:s.array(s.string()).default([])}),s.object({type:s.literal("wiki"),path:s.string(),glob:s.string().default("**/*.md")})]),Ye=s.object({id:s.string(),pm:s.string().optional(),client:s.string().optional()}),Ve=s.object({channel:s.string().optional(),chatId:s.string().optional(),username:s.string().optional(),senderId:s.string().optional(),client:s.string(),project:s.string().optional(),displayName:s.string().optional()}),Je=s.object({name:s.string().optional(),kind:s.enum(["client","internal","own"]).optional(),respondWithin:s.string().optional(),standing:s.array(s.string()).default([])}),H=s.object({enabled:s.boolean().default(!1),timezone:s.string().default("UTC"),mainChannel:Ze,workSource:Ge,roles:s.record(s.string(),Ke).default({}),orgChart:s.record(s.string(),Xe).default({}),projects:s.array(Ye).default([]),contactMap:s.array(Ve).default([]),clients:s.record(s.string(),Je).default({}),workTickMinutes:s.number().int().min(1).max(60).default(15),idleQueueThreshold:s.number().int().min(0).default(0),standup:s.object({enabled:s.boolean().default(!0),plansDir:s.string().default(".agentx/plans"),maxAgentsPerDay:s.number().int().min(1).max(100).default(20),dryRun:s.boolean().default(!1)}).default({})})});import{z as d}from"zod";function Sn(r,n){let t=new Set(r.labels||[]);if(r.state==="closed"){let o=n.find(i=>i.kind==="closed");if(o)return o.id}for(let o of n)if(o.kind==="scoped-label"&&o.scopedLabel&&t.has(o.scopedLabel))return o.id;for(let o of n)if(o.kind==="label"&&o.mapsToLabel&&t.has(o.mapsToLabel))return o.id;let a=n.find(o=>o.kind==="open-backlog");if(a){let o=a.scopedPrefix+"::";return[...t].some(l=>l.startsWith(o))?null:a.id}return n[0]?.id??null}function En(r,n){let t=[],a=[],o=!1,i=!1;return n.kind==="scoped-label"&&n.scopedLabel?t.push(n.scopedLabel):n.kind==="label"&&n.mapsToLabel?t.push(n.mapsToLabel):n.kind==="closed"&&(o=!0),r&&(r.kind==="scoped-label"&&r.scopedLabel?a.push(r.scopedLabel):r.kind==="label"&&r.mapsToLabel?a.push(r.mapsToLabel):r.kind==="closed"&&n.kind!=="closed"&&(i=!0)),{addLabels:t.length?t:void 0,removeLabels:a.length?a:void 0,closeIssue:o||void 0,reopen:i||void 0}}var Qe,et,tt,nt,rt,at,W,ot,K,X=m(()=>{"use strict";Qe=d.object({name:d.string(),color:d.string().regex(/^#[0-9a-f]{6}$/i).default("#6366f1"),description:d.string().optional()}),et=d.object({id:d.string().regex(/^[a-z0-9_-]+$/,"column id must be lowercase slug"),title:d.string(),kind:d.enum(["open-backlog","scoped-label","closed","label"]).default("label"),mapsToLabel:d.string().optional(),scopedLabel:d.string().optional(),scopedPrefix:d.string().default("Status"),accent:d.string().optional()}),tt=d.object({enabled:d.boolean().default(!0),staleDoingMinutes:d.number().int().min(1).default(45),respectLunchBreak:d.boolean().default(!0),respectSchedule:d.boolean().default(!0),action:d.enum(["badge","notify"]).default("badge")}),nt=d.discriminatedUnion("type",[d.object({type:d.literal("gitlab"),projects:d.array(d.string()).min(1)})]),rt=[{id:"open",title:"Open",kind:"open-backlog",scopedPrefix:"Status",accent:"#6b7280"},{id:"todo",title:"To Do",kind:"scoped-label",scopedLabel:"Status::To Do",scopedPrefix:"Status",accent:"#fb7a35"},{id:"doing",title:"Doing",kind:"scoped-label",scopedLabel:"Status::Doing",scopedPrefix:"Status",accent:"#22c55e"},{id:"onhold",title:"On Hold",kind:"scoped-label",scopedLabel:"Status::On Hold",scopedPrefix:"Status",accent:"#f59e0b"},{id:"review",title:"Review",kind:"scoped-label",scopedLabel:"Status::Review",scopedPrefix:"Status",accent:"#3b82f6"},{id:"closed",title:"Closed",kind:"closed",scopedPrefix:"Status",accent:"#6b7280"}],at=d.object({id:d.string().regex(/^[a-z0-9_-]+$/,"board id must be lowercase slug"),name:d.string(),source:nt,primaryToolLabel:d.string().optional(),labels:d.array(Qe).default([]),columns:d.array(et).min(1).default(rt),timeRangeDays:d.number().int().min(1).max(365).default(30),closedWindowDays:d.number().int().min(1).max(365).default(30),reconciliation:tt.default({})}),W=d.array(at).default([]),ot=d.object({name:d.string(),url:d.string(),dashboardUrl:d.string().optional(),token:d.string().optional(),dashboardToken:d.string().optional()}),K=d.object({enabled:d.boolean().default(!1),port:d.number().int().default(4202),bind:d.string().default("127.0.0.1"),token:d.string().optional(),daemonUrl:d.string().default("http://localhost:18800"),daemons:d.array(ot).default([]),draftAgent:d.string().optional()}).default({})});function ct(r){let n=String(r??"").trim().toLowerCase();if(!n)return{ok:!1,error:"is empty"};let t=n.split("+").map(i=>i.trim());if(t.some(i=>!i))return{ok:!1,error:`"${r}" has an empty part; write it like opt+space`};let a=dt[t[t.length-1]]??t[t.length-1],o=new Set;for(let i of t.slice(0,-1)){let l=it[i];if(!l)return{ok:!1,error:`"${i}" is not a modifier; use ctrl, opt, shift or cmd`};if(o.has(l))return{ok:!1,error:`"${r}" names ${l} twice`};o.add(l)}return ut(a)?!Z(a)&&!["ctrl","opt","cmd"].some(i=>o.has(i))?{ok:!1,error:`"${r}" needs ctrl, opt or cmd, or it would take that key away from your typing`}:{ok:!0,value:[...st.filter(i=>o.has(i)),a].join("+")}:{ok:!1,error:`"${a}" is not a key AgentX Voice can use; use a letter, a digit, f1 to f20, or space, period, comma, slash, return, tab`}}function G(r){let n=ct(r);return n.ok?void 0:n.error}function wn(r){let n={ctrl:"\u2303",opt:"\u2325",shift:"\u21E7",cmd:"\u2318"},t={space:"Space",period:".",comma:",",slash:"/",semicolon:";",quote:"'",minus:"-",equal:"=",leftbracket:"[",rightbracket:"]",backslash:"\\",grave:"`",return:"Return",tab:"Tab"},a=r.split("+"),o=a.pop()??"";return a.map(i=>n[i]??i).join("")+(t[o]??o.toUpperCase())}var it,st,lt,dt,Z,ut,E,Y=m(()=>{"use strict";it={ctrl:"ctrl",control:"ctrl",opt:"opt",option:"opt",alt:"opt",shift:"shift",cmd:"cmd",command:"cmd"},st=["ctrl","opt","shift","cmd"],lt=["space","period","comma","slash","semicolon","quote","minus","equal","leftbracket","rightbracket","backslash","grave","return","tab"],dt={".":"period",",":"comma","/":"slash",";":"semicolon","'":"quote","-":"minus","=":"equal","`":"grave",enter:"return"},Z=r=>/^f([1-9]|1[0-9]|20)$/.test(r),ut=r=>/^[a-z0-9]$/.test(r)||lt.includes(r)||Z(r);E={talk:"opt+space",stop:"cmd+opt+period",paste:"cmd+opt+v"}});function Q(r){let n=/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(r);if(!n)return null;let[t,a,o]=n.slice(1).map(b=>parseInt(b,16)/255),i=Math.max(t,a,o),l=Math.min(t,a,o),u=i-l;return u<.04?null:((i===t?(a-o)/u%6:i===a?(o-t)/u+2:(t-a)/u+4)*60+360)%360}function ft(r){let n=Q(r);if(n===null)return x.find(o=>o.id==="lagoon");let t=x[0],a=360;for(let o of x){let i=Math.abs(o.hue-n),l=Math.min(i,360-i);l<a&&(t=o,a=l)}return t}function Tn(r,n=k){let t=l=>x.find(u=>u.id===l),a=t(r?.palette);if(a)return{...a,set:!0};let o=r?.color;return{...o&&Q(o)!==null?ft(o):t(n)??t(k),set:!1}}var x,V,J,L,k,ee=m(()=>{"use strict";x=[{id:"sunrise",label:"Sunrise",hue:18,colors:["#E8505B","#F2726F","#F79A5A","#FBBF4A","#FFE3A3"]},{id:"desert",label:"Desert",hue:36,colors:["#A4492C","#C8683E","#D9905E","#E7B98A","#F6E3C4"]},{id:"forest",label:"Forest",hue:100,colors:["#2F5D34","#4C7D3A","#6FA046","#9CC25E","#D5EBA4"]},{id:"lagoon",label:"Lagoon",hue:172,colors:["#0B6E73","#0E9594","#1FBFB2","#56DCCB","#B8F4EA"]},{id:"ocean",label:"Ocean",hue:205,colors:["#15457E","#1C6BA8","#2B93CF","#5DBBE8","#BFE6FA"]},{id:"dusk",label:"Dusk",hue:268,colors:["#2E2A7A","#5B3E9E","#8C4FB0","#C8649E","#F4A7B9"]},{id:"blossom",label:"Blossom",hue:330,colors:["#A3245B","#CF3F78","#E8699A","#F49BB8","#FFD6E0"]}],V=["orb","character"],J=["off","rarely","sometimes","often"],L=x.map(r=>r.id);k="lagoon"});function te(r){let n=(r.match(/[-ۿ]/g)??[]).length,t=(r.match(/[a-zA-ZÀ-ÿ]/g)??[]).length;if(n&&n>=t)return"ar";let a=0,o=0;for(let i of r.toLowerCase().replace(/[’]/g,"'").match(/[a-zà-ÿœ']+/g)??[])mt.has(i)&&a++,gt.has(i)||i.startsWith("l'")||i.startsWith("d'")||i.startsWith("qu'")?o++:pt.test(i)&&(o+=.5);return a===o?null:a>o?"en":"fr"}var mt,gt,pt,ne=m(()=>{"use strict";mt=new Set("the and is are was were i you he she we they it this that to of in for with not but yes what have has will would can your my".split(" ")),gt=new Set("le la les des du de un une et est sont je tu il elle nous vous ils elles ce cette c'est pas pour que qui avec dans sur au aux mais tr\xE8s oui non merci bonjour votre mon".split(" ")),pt=/[éèêëàâçùûîïôœ]/});function vn(r,n=O){let t=r;if(t=t.replace(/```[\s\S]*?```/g,". "),t=t.replace(/`[^`]*`/g,""),t=t.replace(/\*\*(.*?)\*\*/g,"$1"),t=t.replace(/__(.*?)__/g,"$1"),t=t.replace(/\*([^*]+)\*/g,"$1"),t=t.replace(/_([^_]+)_/g,"$1"),t=t.replace(/~~(.*?)~~/g,"$1"),t=t.replace(/\[([^\]]+)\]\([^)]+\)/g,"$1"),t=t.replace(/!\[([^\]]*)\]\([^)]+\)/g,"image$1 "),t=t.replace(/^#{1,6}\s+/gm,""),t=t.replace(/^[\s]*[-*+]\s+/gm,". "),t=t.replace(/^[\s]*\d+\.\s+/gm,". "),t=t.replace(/^[-=_]{3,}$/gm,""),t=t.replace(/^>\s*/gm,""),t=t.replace(/https?:\/\/\S+/g,"link"),t=t.replace(/\/\w+(\/\w+)+/g,a=>a.split("/").filter(Boolean).join(" slash ")),t=t.replace(/&/g," and "),t=t.replace(/@/g," at "),t=t.replace(/=>/g," returns "),t=t.replace(/->/g," to "),t=t.replace(/\|/g," or "),t=t.replace(/\be\.g\./gi,"for example"),t=t.replace(/\bi\.e\./gi,"that is"),t=t.replace(/\betc\./gi,"etcetera"),t=t.replace(/\bvs\.?\b/gi,"versus"),t=t.replace(/\n{2,}/g,". "),t=t.replace(/\n/g," "),t=t.replace(/\s+/g," "),t=t.replace(/\.\s*\./g,"."),t=t.replace(/\s+([.,!?])/g,"$1"),t=t.trim().replace(/^[.,:;]+\s*/,""),t.length>n){let a=t.slice(0,n),o=([...t.slice(0,n+1).matchAll(/[.!?؟](?=\s)/g)].at(-1)?.index??-1)+1;t=(o>=n/2?a.slice(0,o):a.replace(/\s+\S*$/,"")+"...")+" "+bt[te(a)??"en"]}return t}var O,bt,re=m(()=>{"use strict";ne();O=500,bt={en:"The rest is on screen.",fr:"La suite est \xE0 l'\xE9cran.",ar:"\u0627\u0644\u0628\u0627\u0642\u064A \u0639\u0644\u0649 \u0627\u0644\u0634\u0627\u0634\u0629."}});function On(r,n=j){let t=new Set(n.map(ae)),a=r.replace(/\[([^\][]*)\]|\(([^()]*)\)/g,(o,i,l)=>t.has(ae(i??l))?"":o);return!/[\p{L}\p{N}]/u.test(a)}var j,Ln,ae,oe=m(()=>{"use strict";j=["background noise","noise","mumbling","babbling","unintelligible","inaudible","muffled speech","pause","silence","music","outro jingle","blank audio"],Ln="I didn't catch that.",ae=r=>r.toLowerCase().replace(/[_\s]+/g," ").trim()});import{z as c}from"zod";var ie,ht,se,le=m(()=>{"use strict";ie=c.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/,"use HH:MM, 24-hour"),ht=c.object({id:c.string().regex(/^[a-z0-9][a-z0-9_-]{0,63}$/,"lowercase letters, digits, - and _"),enabled:c.boolean().default(!0),chats:c.array(c.string().min(1)).default([]),senders:c.array(c.string().min(1)).default([]),agent:c.string().min(1),prompt:c.string().max(4e3).optional(),quietHours:c.object({start:ie,end:ie}).optional(),autoAck:c.boolean().default(!1)}).refine(r=>r.chats.length>0||r.senders.length>0,{message:"a rule needs at least one chat or sender"}),se=c.object({enabled:c.boolean().default(!1),secretEnv:c.string().regex(/^[A-Z_][A-Z0-9_]*$/).default("WACLI_WEBHOOK_SECRET"),batchSeconds:c.number().int().min(0).max(600).default(20),timezone:c.string().optional(),allowAutoAck:c.boolean().default(!1),describeMedia:c.boolean().default(!0),wacli:c.object({bin:c.string().default("wacli"),account:c.string().optional(),store:c.string().optional()}).default({}),rules:c.array(ht).default([])}).default({})});function yt(r){r.exec(`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS requests (
|
|
3
3
|
id TEXT PRIMARY KEY,
|
|
4
4
|
state TEXT NOT NULL,
|
|
@@ -51,4 +51,4 @@ ${f.join(`
|
|
|
51
51
|
|
|
52
52
|
`)}`:"";throw new Error(`Config validation failed (${a}):
|
|
53
53
|
${u}${b}`)}return l.data}function gn(r){let n=[];for(let[t,a]of Object.entries(r.agents)){if(!I(a.workspace)){n.push(`Agent "${t}": workspace not found at ${a.workspace}`);continue}if(a.tier==="claude-code"){let l=v(a.workspace,".claude");I(l)||n.push(`Agent "${t}": no .claude/ directory in workspace ${a.workspace}. Claude Code native features (hooks, MCP, skills) won't be available.`)}let o=a.provider||"claude",i=r.providers[o];!["claude-code","codex-cli","opencode"].includes(a.tier)&&(!i||!i.apiKey)&&n.push(`Agent "${t}": provider "${o}" has no API key configured. Set providers.${o}.apiKey in config or use a CLI-backed tier ("claude-code", "codex-cli", or "opencode").`)}for(let[t,a]of Object.entries(r.crons))r.agents[a.agent]||n.push(`Cron "${t}": references unknown agent "${a.agent}"`);if(r.channels.telegram.enabled)for(let[t,a]of Object.entries(r.channels.telegram.accounts))r.agents[a.agentBinding]||n.push(`Telegram account "${t}": references unknown agent "${a.agentBinding}"`);return n}var zt,Wt,Kt,Xt,Zt,Gt,Yt,Re,Ie,R,ve,Ce,Vt,Jt,Le,Qt,en,tn,nn,rn,an,on,sn,ln,Oe,dn,un,cn,je,Ne,$e,De,Pe,qe,Me,bn=m(()=>{z();X();Ue();Y();ee();re();oe();le();Te();zt=e.object({apiKey:e.string().optional(),defaultModel:e.string().optional(),baseUrl:e.string().optional(),thinking:e.boolean().optional()}),Wt=e.object({type:e.literal("stdio").optional(),command:e.string(),args:e.array(e.string()).default([]),env:e.record(e.string(),e.string()).optional()}),Kt=e.object({type:e.literal("http"),url:e.string().url(),headers:e.record(e.string(),e.string()).optional()}),Xt=e.union([Kt,Wt]),Zt=e.object({tokenEnv:e.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),privateAppTokenEnv:e.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),apiKeyEnv:e.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),refreshTokenEnv:e.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),clientIdEnv:e.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),clientSecretEnv:e.string().regex(/^[A-Z][A-Z0-9_]*$/).optional(),auth:e.literal("keyring").optional(),sessionDir:e.string().optional()}).strict(),Gt=e.object({kind:e.string().min(1),label:e.string().min(1),credentials:Zt.default({}),metadata:e.record(e.string(),e.union([e.string(),e.number(),e.boolean()])).default({}),enabled:e.boolean().default(!0)}),Yt=["telegram-bot","whatsapp","gitlab-user","github-user","gmail","hotmail","smtp","hubspot","salesforce","pipedrive","odoo","trello","linear","asana","jira","notion","stripe","sentry","vercel","twilio","custom"],Re=e.enum(["system","elevenlabs"]),Ie=e.union([e.string(),e.record(e.string(),e.string())]),R=e.string().superRefine((r,n)=>{let t=G(r);t&&n.addIssue({code:e.ZodIssueCode.custom,message:`shortcut ${t}`})}),ve=e.object({provider:Re.optional(),system:Ie.optional(),fallbacks:e.array(e.string().min(1)).optional(),elevenlabsVoiceId:e.string().optional(),gender:e.enum(["female","male","neutral"]).optional(),style:e.string().optional(),intro:e.string().optional(),narrate:e.enum(["off","on","all"]).optional(),rate:e.number().min(.75).max(1.5).optional(),priority:e.enum(["high","normal","low"]).optional(),hotkey:R.optional()}),Ce=e.object({kinds:e.array(e.string().min(1)).min(1),agents:e.array(e.string().min(1)).optional(),nodes:e.array(e.string().min(1)).optional(),match:e.string().min(1).optional(),delivery:e.enum(["pull","digest","wake"]).default("pull"),maxPerHour:e.number().int().min(1).max(60).default(4)}),Vt=e.object({name:e.string(),workspace:e.string(),tier:e.enum(["claude-code","codex-cli","opencode","sdk","orchestrator"]).default("claude-code"),provider:e.string().optional(),model:e.string().optional(),systemPrompt:e.string().optional(),mentions:e.array(e.string()).default([]),intents:e.array(e.string()).default([]),maxDelegationDepth:e.number().int().min(0).max(50).default(5),mcp:e.record(e.string(),Xt).optional(),codegraph:e.boolean().default(!1),contextStrategy:e.enum(["layered","planner"]).optional(),contextReferences:e.boolean().default(!1),richMessages:e.boolean().default(!0),maxConcurrent:e.number().default(1),maxExecutionMinutes:e.number().int().min(1).max(240).default(20),preSpawnTimeoutSec:e.number().int().min(10).max(3600).default(300),drainTimeoutSeconds:e.number().int().min(0).max(86400).optional(),permissionMode:e.string().default("default"),billing:e.enum(["subscription","api"]).default("subscription"),cloudSessions:e.object({enabled:e.boolean().default(!1),maxPerDay:e.number().int().min(0).default(0),openHours:e.number().min(1).max(168).default(24),launchTimeoutSeconds:e.number().int().min(10).max(600).default(120)}).default({}),toolUseRequired:e.array(e.string()).default([]),gitlabAutoReply:e.boolean().optional(),persistentProcess:e.boolean().default(!1),queueMode:e.enum(["collect","followup","drop"]).default("collect"),heartbeat:e.object({enabled:e.boolean().default(!1),intervalMinutes:e.number().default(30),prompt:e.string().default("Check inbox, pending tasks, and system health. Report anything that needs attention."),channel:e.string().default("heartbeat")}).default({}),access:e.enum(["private","public"]).default("private"),admin:e.boolean().optional(),subscriptions:e.array(Ce).default([]),integrations:e.array(Gt).default([]),voice:ve.optional(),presence:e.object({color:e.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),palette:e.enum(L).optional(),initial:e.string().max(2).optional(),label:e.string().optional(),allowActions:e.boolean().optional()}).optional()}),Jt=e.object({token:e.string(),agentBinding:e.string(),allowFrom:e.array(e.string()).optional(),pollInbound:e.boolean().default(!0)}),Le=e.object({frameIntervalSeconds:e.number().int().min(0).max(3600).default(0),maxSessionMinutes:e.number().int().min(1).max(240).default(10),maxFrameEdge:e.number().int().min(160).max(3840).default(1024),keepFrames:e.boolean().default(!1),streamFrameSeconds:e.number().int().min(2).max(60).default(5),streamMaxSeconds:e.number().int().min(10).max(600).default(60)}).default({}),Qt=e.object({telegram:e.object({enabled:e.boolean().default(!1),accounts:e.record(e.string(),Jt).default({}),policy:e.object({dm:e.enum(["pair","block"]).default("pair"),group:e.enum(["mention-required","all"]).default("mention-required"),allowFrom:e.array(e.string()).optional()}).default({})}).default({}),whatsapp:e.object({enabled:e.boolean().default(!1),sessionDir:e.string().default(".agentx/whatsapp-sessions"),defaultAgent:e.string().optional(),allowFrom:e.array(e.string()).optional(),routes:e.array(e.object({contact:e.string().optional(),group:e.string().optional(),agent:e.string()})).default([]),ingest:e.object({enabled:e.boolean().default(!1),mode:e.enum(["metadata-only","messages"]).default("metadata-only"),allowContacts:e.array(e.string()).default([]),allowGroups:e.array(e.string()).default([]),denyContacts:e.array(e.string()).default([]),denyGroups:e.array(e.string()).default([]),messageCap:e.number().int().min(1).max(500).default(50),historyDays:e.number().int().min(1).max(365).default(30),contactRefreshDays:e.number().int().min(1).max(90).default(7),throttle:e.object({minMsBetweenCalls:e.number().int().min(100).default(1500),maxCallsPerMinute:e.number().int().min(1).default(20),maxChatsPerSweep:e.number().int().min(1).default(25)}).default({}),retentionDays:e.number().int().min(0).default(0)}).default({})}).default({}),gitlab:e.object({enabled:e.boolean().default(!1),webhookPort:e.number().default(18810),webhookSecret:e.string().optional(),host:e.string().default("https://gitlab.com"),token:e.string().optional(),autoReplyLegacy:e.boolean().default(!0),routes:e.array(e.object({project:e.string(),agent:e.string()})).default([]),agentMappings:e.array(e.object({agentId:e.string(),gitlabUsernames:e.array(e.string()).default([]),keywords:e.array(e.string()).default([]),token:e.string().optional(),node:e.string().optional()})).default([]),agentUsernamePrefixes:e.array(e.string().min(1)).default([])}).default({}),github:e.object({enabled:e.boolean().default(!1),autoReplyLegacy:e.boolean().default(!0),cloudSessions:e.boolean().default(!1),token:e.string().optional(),tokenFile:e.string().optional(),appId:e.number().optional(),clientId:e.string().optional(),privateKeyFile:e.string().optional(),webhookSecret:e.string().optional(),routes:e.array(e.object({repo:e.string(),agent:e.string()})).default([]),agentMappings:e.array(e.object({agentId:e.string(),githubUsernames:e.array(e.string()).default([]),token:e.string().optional(),tokenFile:e.string().optional(),node:e.string().optional()})).default([]),issueActions:e.array(e.string().min(1)).default(["opened","reopened","assigned"]),pullRequestActions:e.array(e.string().min(1)).default(["opened","reopened","ready_for_review"]),ignoreOwnChanges:e.boolean().default(!0),debounceSeconds:e.number().min(0).max(3600).default(30)}).default({}),ntfy:e.object({enabled:e.boolean().default(!1),server:e.string().default("https://ntfy.sh"),topic:e.string().optional(),token:e.string().optional(),defaultPriority:e.number().int().min(1).max(5).default(3),defaultTitle:e.string().optional()}).default({}),push:e.object({enabled:e.boolean().default(!1),keysFile:e.string().default(".agentx/push-keys.json"),subject:e.string().regex(/^(mailto:|https:\/\/)/,"must start with mailto: or https://").optional(),relayTo:e.string().optional(),ttlSeconds:e.number().int().min(0).max(2419200).default(86400),keepRecent:e.number().int().min(0).max(1e3).default(50),allowedHosts:e.array(e.string().min(1)).default(["fcm.googleapis.com","push.services.mozilla.com","push.apple.com","notify.windows.com"])}).default({}),webrtc:e.object({enabled:e.boolean().default(!1),stunServers:e.array(e.string()).default(["stun:stun.l.google.com:19302"]),turnServers:e.array(e.object({urls:e.string(),username:e.string().optional(),credential:e.string().optional()})).default([]),allowedCallers:e.array(e.string()).default([]),ringNotify:e.array(e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()})).default([]),callUrlBase:e.string().optional(),bot:e.object({enabled:e.boolean().default(!1),defaultAgentId:e.string().optional(),whisperBackend:e.enum(["auto","mlx","openai"]).default("auto"),whisperModel:e.string().optional(),whisperLanguage:e.string().default("auto"),mlxBinary:e.string().optional(),transcriptChannel:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional(),maxCallMinutes:e.number().int().min(1).max(240).default(30)}).default({}),camera:e.object({width:e.number().int().min(160).max(3840).default(1280),height:e.number().int().min(120).max(2160).default(720),frameRate:e.number().int().min(1).max(60).default(15),maxSeconds:e.number().int().min(10).max(7200).default(600),voiceInput:e.boolean().default(!0),speakAnswers:e.boolean().default(!0),bot:Le}).default({})}).default({})}),en=e.object({enabled:e.boolean().default(!0),schedule:e.string(),timezone:e.string().default("UTC"),agent:e.string(),prompt:e.string().default(""),command:e.string().optional(),timeout:e.number().default(600),model:e.string().optional(),maxOutputTokens:e.number().int().min(50).max(8e3).optional(),autonomy:q.optional(),onError:e.union([e.enum(["log","notify","disable"]),e.array(e.enum(["log","notify","disable"]))]).default("log").transform(r=>Array.isArray(r)?r:[r]),notify:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional(),fireToken:e.string().optional(),createdBy:e.string().optional(),approval:e.object({action:e.enum(["create","delete"]),requestedBy:e.string(),requestedAt:e.string()}).optional()}).refine(r=>!!(r.command?.trim()||r.prompt?.trim()),{message:"a cron needs either a prompt (dispatch an agent) or a command (run it directly)"}).refine(r=>!(r.command?.trim()&&r.autonomy&&r.autonomy!=="act"),{message:"autonomy applies to agent routines; a command cron runs no agent (remove autonomy or the command)"}),tn=e.object({name:e.string(),triggers:e.array(e.object({pattern:e.string(),channel:e.string().optional()})),allowedContacts:e.array(e.string()).optional(),agent:e.string(),prompt:e.string(),schedule:e.string().optional(),timezone:e.string().default("UTC"),notify:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional()}),nn=e.object({url:e.string(),name:e.string(),token:e.string().optional()}),rn=e.object({name:e.string(),agent:e.string(),enabled:e.boolean().default(!0)}),an=e.object({enabled:e.boolean().default(!1),peers:e.array(nn).default([]),inboxes:e.array(rn).default([]),discovery:e.enum(["static","mdns"]).default("static"),healthCheck:e.object({interval:e.number().default(60),timeout:e.number().default(10)}).default({}),feed:e.object({enabled:e.boolean().default(!0),skipTypes:e.array(e.string().min(1)).default(["task:step"])}).default({}),delegation:e.object({asyncWhenHuman:e.boolean().default(!0),timeoutMinutes:e.number().int().min(1).max(240).default(30)}).default({})}),on=e.object({enabled:e.boolean().default(!1),baseDir:e.string().default(".agentx/graph"),draftAgent:e.string().optional(),reviewAgent:e.string().optional(),autoApproveStructure:e.enum(["strict","extend-leaves","any"]).default("extend-leaves"),autoApproveConfidence:e.number().min(0).max(1).default(1),classifierModel:e.string().default("claude-haiku-4-5-20251001"),retrievalWeights:e.object({graph:e.number().min(0).default(.6),bm25:e.number().min(0).default(.4)}).default({})}).default({}),sn=e.object({mode:e.enum(["off","shadow","active"]).default("off"),backend:e.string().optional(),model:e.string().optional(),timeoutMs:e.number().int().min(100).optional(),temperature:e.number().min(.01).default(1),explore:e.number().min(0).max(1).default(.15),holdout:e.number().min(0).max(1).optional()}).default({}),ln=e.object({enabled:e.boolean().default(!1),dbPath:e.string().default(".agentx/decisions/decisions.sqlite"),redactState:e.boolean().default(!1),keepStateRows:e.number().int().min(0).default(2e3),defaultBackend:e.string().default("local"),backends:e.object({local:e.object({provider:e.string().default("claude-code"),model:e.string().default("claude-haiku-4-5-20251001"),structureMode:e.enum(["auto","tool","text"]).default("auto"),normalizeProbabilities:e.boolean().default(!0),nRetryMalformedStructure:e.number().int().min(0).max(3).default(1),maxStateChars:e.number().int().min(500).default(24e3)}).default({}),simpleJev:e.object({baseUrl:e.string().default("http://127.0.0.1:8000/v1"),model:e.string().optional(),apiKeyEnv:e.string().optional(),timeoutMs:e.number().int().min(100).default(3e4),maxStateChars:e.number().int().min(500).default(6e3),maxChoiceOptions:e.number().int().min(2).max(255).default(50)}).default({}),jev:e.object({baseUrl:e.string().default("https://openrouter.ai/api/alpha"),path:e.string().default("/decisions"),model:e.string().default("jev-latest"),apiKeyEnv:e.string().default("OPENROUTER_API_KEY"),timeoutMs:e.number().int().min(100).default(3e4),maxStateChars:e.number().int().min(500).default(9e4),maxChoiceOptions:e.number().int().min(2).max(255).default(255)}).default({}),typesafe:e.object({baseUrl:e.string().default("https://api.typesafe.ai/v1"),path:e.string().default("/systemone"),model:e.string().default("jev-latest"),apiKeyEnv:e.string().default("TYPESAFE_API_KEY"),timeoutMs:e.number().int().min(100).default(3e4),maxStateChars:e.number().int().min(500).default(9e4),maxChoiceOptions:e.number().int().min(2).max(255).default(255)}).default({})}).default({}),seats:e.record(e.string(),sn).default({}),routing:e.object({cheapModel:e.string().optional(),cheapModels:e.object({"claude-code":e.string().optional(),"codex-cli":e.string().optional()}).optional()}).default({})}).default({}),Oe=e.object({allow:e.array(e.string()).default([]),maxPerHour:e.number().int().min(1).max(60).default(3),ringSeconds:e.number().int().min(10).max(300).default(45),maxCallMinutes:e.number().int().min(1).max(240).default(30),ringSound:e.string().regex(/^[\w -]+$/).default("Submarine"),summary:e.boolean().default(!0)}).default({}),dn=e.object({longTaskThreshold:e.number().default(30),destination:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional(),channel:e.string().optional(),on:e.object({taskComplete:e.boolean().default(!0),taskError:e.boolean().default(!0),taskQueued:e.boolean().default(!1)}).default({}),local:e.object({banner:e.boolean().default(!0),sound:e.boolean().default(!0),soundName:e.string().regex(/^[\w -]+$/).default("Glass"),volume:e.number().min(0).max(1).default(.4),icon:e.string().optional()}).default({})}).default({}),un=e.object({x:e.number(),y:e.number(),width:e.number().positive(),height:e.number().positive()}),cn=e.object({maxPixels:e.number().int().positive().default(12e5),timeoutMs:e.number().int().positive().default(5e3),intervalMs:e.number().int().positive().default(100),changeThreshold:e.number().min(0).max(1).default(.015),stableMs:e.number().int().nonnegative().default(400),regions:e.record(e.string().regex(/^[a-z][\w-]*$/),un).default({}),buffer:e.object({enabled:e.boolean().default(!1),seconds:e.number().positive().max(120).default(10),fps:e.number().positive().max(10).default(2),region:e.string().default("screen"),maxPixels:e.number().int().positive().default(3e5)}).default({})}).default({}),je=e.object({enabled:e.boolean().default(!1),channels:e.array(e.string().min(1)).default([]),from:e.array(e.string().regex(/^[a-z0-9_-]+:\S+$/i,"use channel:id, for example telegram:123456789")).default([]),staleAfterHours:e.number().positive().max(24*365).default(24),retentionDays:e.number().positive().max(3650).default(90)}).default({}),Ne=e.object({id:e.string().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/,"lower-case letters, digits, - and _"),name:e.string().min(1).max(80),say:e.string().trim().min(1).max(120).optional(),role:e.enum(["owner","member","client","guest"]).default("member"),identities:e.array(e.string().regex(/^[A-Za-z][\w-]*:\S.*$/,"write it as channel:id")).default([]),agents:e.array(e.string().min(1)).default([]),deny:e.object({tools:e.array(e.string().min(1)).default([]),skills:e.array(e.string().min(1)).default([])}).strict().default({})}),$e=e.array(Ne).default([]).superRefine((r,n)=>{let t=we(r);t&&n.addIssue({code:e.ZodIssueCode.custom,message:t})}),De=e.object({logRetentionDays:e.number().int().min(1).max(3650).default(90)}).default({}),Pe=e.object({channels:e.array(e.string().min(1)).default([])}).default({}),qe=e.object({defaultExpiryDays:e.number().positive().max(365).default(3),maxExpiryDays:e.number().positive().max(365).default(30),laterHours:e.number().positive().max(24*30).default(24),notifyAgent:e.boolean().default(!0),forwardTo:e.string().min(1).optional(),digest:e.object({enabled:e.boolean().default(!0),time:e.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/,"use HH:MM, 24-hour").default("09:00"),timezone:e.string().refine(r=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:r}),!0}catch{return!1}},"unknown timezone").optional(),destination:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional()}).default({}),popup:e.object({enabled:e.boolean().default(!1),style:e.enum(["card","dialog"]).default("card"),theme:e.enum(["system","light","dark"]).default("system"),speak:e.boolean().default(!0),voice:e.string().regex(/^[\w .()-]+$/,"a voice name, as `say -v '?'` lists them").optional(),sound:e.string().regex(/^[\w -]*$/,"a sound name, like chime or Glass").default("chime"),volume:e.number().min(0).max(1).default(.4),timeoutSeconds:e.number().int().min(10).max(3600).default(600)}).default({}),checkin:e.object({enabled:e.boolean().default(!1),times:e.array(e.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/,"use HH:MM, 24-hour")).default(["11:00","14:00","17:00"]),dailyAt:e.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/,"use HH:MM, 24-hour").default("09:00"),timezone:e.string().refine(r=>{try{return new Intl.DateTimeFormat("en-US",{timeZone:r}),!0}catch{return!1}},"unknown timezone").optional(),lists:e.array(e.string().min(1)).default(["Reminders"]),agent:e.string().min(1).optional(),dueWithinHours:e.number().positive().max(24*30).default(24),maxAsksPerPass:e.number().int().min(1).max(20).default(5),composeTimeoutSeconds:e.number().int().min(30).max(3600).default(300)}).default({})}).default({}),Me=e.object({node:e.object({id:e.string(),name:e.string(),bind:e.string().default("127.0.0.1:18800"),defaultAgent:e.string().optional()}),providers:e.record(e.string(),zt).default({}),agents:e.record(e.string(),Vt).default({}),channels:Qt.default({}),crons:e.record(e.string(),en).default({}),services:e.record(e.string(),tn).default({}),notifications:dn,calls:Oe,whatsappTriage:se,approvals:qe,shutdown:e.object({drainTimeoutSeconds:e.number().int().min(0).max(86400).optional(),restart:e.object({allowBy:e.string().optional(),window:e.string().regex(/^\d{1,2}:\d{2}$/,"window must be HH:MM").optional(),windowWaitMinutes:e.number().int().min(1).max(1440).default(180),forbidOnTimeoutRestart:e.boolean().default(!1)}).default({})}).default({}),resume:e.object({enabled:e.boolean().default(!0),maxAgeMinutes:e.number().int().positive().default(30),maxAttempts:e.number().int().min(0).default(1),reportOnlyChannels:e.array(e.string()).default([]),directChannels:e.array(e.string()).default([]),crashLoop:e.object({restarts:e.number().int().positive().default(3),windowMinutes:e.number().positive().default(10)}).default({})}).default({}),requests:je,people:$e,members:De,requestStatus:Pe,reminders:e.object({enabled:e.boolean().default(!1),lists:e.array(e.string().min(1)).default(["AgentX"]),pollSeconds:e.number().int().min(15).default(60),lookbackHours:e.number().positive().default(24),command:e.string().min(1).default("remindctl")}).default({}),app:e.object({android:e.object({packageName:e.string().regex(/^[a-zA-Z][\w]*(\.[a-zA-Z][\w]*)+$/,"must look like com.example.app").default("dev.agentx.phone"),certFingerprints:e.array(e.string().regex(/^([0-9A-Fa-f]{2}:){31}[0-9A-Fa-f]{2}$/,"must be 32 hex pairs separated by colons")).default([])}).default({}),places:e.object({enabled:e.boolean().default(!0),file:e.string().min(1).default(".agentx/places.json"),defaultRadiusMeters:e.number().int().min(50).max(5e4).default(150),minRadiusMeters:e.number().int().min(50).max(5e4).default(100),maxRadiusMeters:e.number().int().min(50).max(5e4).default(5e3),maxPlaces:e.number().int().min(1).max(100).default(50),maxRulesPerPlace:e.number().int().min(1).max(50).default(10),cooldownMinutes:e.number().int().min(0).max(1440).default(10),maxEventAgeMinutes:e.number().int().min(1).max(1440).default(30),syncMinutes:e.number().int().min(15).max(1440).default(60)}).default({})}).default({}),demo:e.object({startupTimeoutSeconds:e.number().int().positive().max(3600).optional()}).default({}),events:e.object({ringSize:e.number().int().min(1).max(1e5).default(1e3)}).default({}),screen:cn,mesh:an.default({}),meshVoices:e.record(e.string(),ve.omit({rate:!0,priority:!0,hotkey:!0}).extend({name:e.string().optional()})).default({}),voice:e.object({provider:Re.default("system"),fallback:e.enum(["system","none"]).default("system"),system:Ie.optional(),locale:e.string().default("en"),listener:e.string().optional(),pronunciations:e.array(e.object({written:e.string().trim().min(1).max(80),spoken:e.string().trim().min(1).max(120),languages:e.array(e.enum(["en","fr","ar"])).optional()}).strict()).max(200).default([]),pointer:e.boolean().default(!0),stt:e.enum(["auto","elevenlabs","local"]).default("auto"),allowUnmeasured:e.boolean().default(!1),spokenMaxChars:e.number().int().min(300).max(1500).default(O),noiseFilter:e.object({enabled:e.boolean().default(!0),markers:e.array(e.string()).default(j)}).default({}),localStt:e.enum(["mlx-whisper","parakeet"]).default("mlx-whisper"),endOfTurn:e.enum(["vad","volume"]).default("vad"),hotkeys:e.object({talk:R.default(E.talk),stop:R.default(E.stop),paste:R.default(E.paste)}).default({}),look:e.enum(V).default("orb"),startReduced:e.boolean().default(!1),stroll:e.boolean().default(!1),animations:e.enum(J).default("sometimes"),palette:e.enum(L).default(k),card:e.object({timeout:e.number().min(0).max(600).default(30),maxHeight:e.number().min(120).max(800).default(320)}).default({})}).default({}),business:H.optional(),boards:W,dashboard:K,graph:on,decisions:ln,workflows:e.object({enabled:e.boolean().default(!1),dir:e.string().default(".agentx/workflows"),n8n:e.object({baseUrl:e.string().default(""),apiKey:e.string().default("")}).default({baseUrl:"",apiKey:""}),matching:e.object({enabled:e.boolean().default(!1),mode:e.enum(["suggest","auto"]).default("suggest"),autoRunThreshold:e.number().min(0).max(1).default(.85),suggestThreshold:e.number().min(0).max(1).default(.65)}).default({}),editor:e.enum(["disabled","readonly","edit"]).default("edit")}).default({}),procedures:e.object({enabled:e.boolean().default(!0),dir:e.string().default(".agentx/procedures"),extraction:e.object({enabled:e.boolean().default(!1),onTaskCompletion:e.boolean().default(!1),minOccurrences:e.number().int().min(2).default(3),sinceDays:e.number().int().min(1).default(7),maxClusters:e.number().int().min(1).default(5),via:e.string().optional()}).default({}),injection:e.object({enabled:e.boolean().default(!0),maxProcedures:e.number().int().min(1).default(2),minScore:e.number().min(0).max(1).default(.5)}).default({})}).default({}),webhooks:e.array(e.object({id:e.string().regex(/^[a-z0-9][a-z0-9_-]*$/,"webhook id must be lowercase slug"),source:e.string().min(1),agentId:e.string(),secretEnv:e.string().optional(),description:e.string().optional(),enabled:e.boolean().default(!0),node:e.string().optional(),triggers:e.record(e.string(),e.string()).optional(),defaultWorkflow:e.string().optional()})).default([]),session:e.object({staleMinutes:e.number().int().min(1).max(1440).default(720),maxTurnsPerSession:e.number().int().min(2).max(200).default(40),tierTwoThresholdTokens:e.number().int().min(5e4).max(2e5).default(18e4),tierTwoThresholdTokensByChannel:e.record(e.number().int().min(5e4).max(2e5)).default({}),contextStrategy:e.enum(["layered","planner"]).default("layered"),maxClaudeCodeDispatchesPerHour:e.number().int().min(0).max(1e4).optional(),maxClaudeCodeDispatchesPer5h:e.number().int().min(0).max(5e4).optional(),continuityStateTurns:e.number().int().min(0).max(5).default(0),profileByChannel:e.record(e.enum(["full","lean"])).default({}),lean:e.object({mcpServers:e.array(e.string().min(1)).default(["agentx"]),settingSources:e.array(e.enum(["user","project","local"])).default(["project","local"]),contextOnDemand:e.boolean().default(!0),tools:e.array(e.string().min(1)).default([]),toolsByChannel:e.record(e.array(e.string().min(1))).default({})}).default({}),triage:e.object({models:e.object({"claude-code":e.string().min(1).optional(),"codex-cli":e.string().min(1).optional()}).default({}),actions:e.array(e.string().min(1)).default(["labeled","unlabeled","closed"])}).default({}),memoryIndexMaxChars:e.number().int().min(0).max(2e5).default(0),observationPack:e.object({enabled:e.boolean().default(!1),limitBytes:e.number().int().min(1024).max(1048576).default(10240),headBytes:e.number().int().min(0).max(65536).default(1024),tailBytes:e.number().int().min(0).max(65536).default(1024),tools:e.array(e.string().min(1)).default(["Bash","Grep","Read","WebFetch","mcp__.*"]),retentionDays:e.number().int().min(0).max(3650).default(0)}).default({})}).default({}),plugins:e.array(e.string()).default([]),processPool:e.object({maxIdleSeconds:e.number().int().min(5).max(86400).default(30),maxAgeSeconds:e.number().int().min(60).max(86400).default(2700),sweepIntervalSeconds:e.number().int().min(1).max(300).default(5)}).default({})})});export{Sn as a,En as b,X as c,ct as d,wn as e,E as f,Y as g,x as h,V as i,J as j,L as k,Tn as l,ee as m,te as n,ne as o,vn as p,re as q,Ln as r,On as s,oe as t,se as u,le as v,y as w,g as x,Pn as y,de as z,ue as A,Bn as B,Un as C,T as D,Fn as E,fe as F,pe as G,Ot as H,Zn as I,xe as J,Gn as K,Dt as L,Yn as M,Se as N,tr as O,A as P,nr as Q,ke as R,Bt as S,Ut as T,_e as U,rr as V,ar as W,or as X,Te as Y,Yt as Z,Ce as _,Le as $,Oe as aa,je as ba,Ne as ca,$e as da,De as ea,Pe as fa,qe as ga,Me as ha,C as ia,mn as ja,gn as ka,pn as la,bn as ma};
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
54
|
+
//# sourceMappingURL=chunk-FBEMUCBO.js.map
|