agentix-cli 0.115.0 → 0.117.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.
Files changed (133) hide show
  1. package/apps/mac-voice/Sources/AgentXVoice/AnswerView.swift +24 -2
  2. package/apps/mac-voice/Sources/AgentXVoice/ListenAgain.swift +26 -0
  3. package/apps/mac-voice/Sources/AgentXVoice/main.swift +54 -0
  4. package/dist/{App-6OMMZW2M.js → App-UQP7UQYV.js} +2 -2
  5. package/dist/{ChatApp-EDDROHNA.js → ChatApp-VGSP5O6N.js} +2 -2
  6. package/dist/{agent-VPM3EEUB.js → agent-MO27U4Y7.js} +2 -2
  7. package/dist/{board-dashboard-4GQ7RTH3.js → board-dashboard-CSS7XMIZ.js} +255 -224
  8. package/dist/board-dashboard-CSS7XMIZ.js.map +1 -0
  9. package/dist/chunk-2WK5A3UV.js +482 -0
  10. package/dist/chunk-2WK5A3UV.js.map +1 -0
  11. package/dist/{chunk-S4XSVAAG.js → chunk-45GOH6F7.js} +2 -2
  12. package/dist/chunk-45YETJY4.js +2 -0
  13. package/dist/chunk-45YETJY4.js.map +1 -0
  14. package/dist/{chunk-CJJULHPJ.js → chunk-4ELAUGOP.js} +4 -4
  15. package/dist/{chunk-5FY7PWXW.js → chunk-5PPMPCHG.js} +2 -2
  16. package/dist/{chunk-BU4LE2RT.js → chunk-746KHKT4.js} +2 -2
  17. package/dist/{chunk-QLB76BGE.js → chunk-BQ2HJ7TS.js} +2 -2
  18. package/dist/{chunk-PITMPRVP.js → chunk-CKQ2YDFP.js} +2 -2
  19. package/dist/{chunk-7T7IXLLA.js → chunk-CUZTLQH2.js} +2 -2
  20. package/dist/chunk-DMHQIACQ.js +3 -0
  21. package/dist/chunk-DMHQIACQ.js.map +1 -0
  22. package/dist/chunk-EMGB23H5.js +3 -0
  23. package/dist/chunk-EMGB23H5.js.map +1 -0
  24. package/dist/chunk-FJI5GRBH.js +54 -0
  25. package/dist/chunk-FJI5GRBH.js.map +1 -0
  26. package/dist/chunk-GRMCAO3Q.js +2 -0
  27. package/dist/chunk-GRMCAO3Q.js.map +1 -0
  28. package/dist/{chunk-PX2AOZ5G.js → chunk-HVZVFCJX.js} +2 -2
  29. package/dist/{chunk-BXYKFWAI.js → chunk-HYGMWCUU.js} +2 -2
  30. package/dist/{chunk-ECBVOIIK.js → chunk-IZMXAXW3.js} +182 -182
  31. package/dist/chunk-IZMXAXW3.js.map +1 -0
  32. package/dist/{chunk-YE4HKOS5.js → chunk-J2YLOGNN.js} +2 -2
  33. package/dist/{chunk-2NYP4OQU.js → chunk-LNY6N73E.js} +4 -4
  34. package/dist/{chunk-2NYP4OQU.js.map → chunk-LNY6N73E.js.map} +1 -1
  35. package/dist/{chunk-EVXL6X2R.js → chunk-MSP25HE5.js} +58 -58
  36. package/dist/{chunk-EVXL6X2R.js.map → chunk-MSP25HE5.js.map} +1 -1
  37. package/dist/{chunk-MG5LRE5B.js → chunk-OJ7KM2UO.js} +2 -2
  38. package/dist/{chunk-4STXRZZS.js → chunk-PFK3QO6S.js} +2 -2
  39. package/dist/{chunk-K3BG77KK.js → chunk-PMQ47IPT.js} +2 -2
  40. package/dist/{chunk-KTF4YF4M.js → chunk-T2VDHVYW.js} +2 -2
  41. package/dist/{chunk-J5TZ6QGD.js → chunk-VEHTVYP6.js} +2 -2
  42. package/dist/{chunk-SDOSQ6TJ.js → chunk-VRXJW6JJ.js} +2 -2
  43. package/dist/{chunk-UQX2HY5M.js → chunk-W7WNRPNQ.js} +2 -2
  44. package/dist/cli.js +1 -1
  45. package/dist/{client-VUNPLVCG.js → client-5UMNDY7Z.js} +2 -2
  46. package/dist/{config-HE2LGTTG.js → config-O44DOHFW.js} +2 -2
  47. package/dist/config-mutator-PRLY2TCE.js +2 -0
  48. package/dist/doctor-NKPH74F7.js +2 -0
  49. package/dist/index.d.ts +55 -5
  50. package/dist/index.js +1 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/{program-53CQJEUZ.js → program-RHIJYCEJ.js} +191 -187
  53. package/dist/program-RHIJYCEJ.js.map +1 -0
  54. package/dist/{promote-4PPJJ6AW.js → promote-ZRNVPWTD.js} +2 -2
  55. package/dist/push-DID6RZYI.js +2 -0
  56. package/dist/push-bridge-VPTQNM43.js +2 -0
  57. package/dist/push-store-L5QHMSST.js +2 -0
  58. package/dist/{query-ETDKC7WC.js → query-HURONGKA.js} +2 -2
  59. package/dist/{registry-AMETOJ3S.js → registry-AYGFAKTC.js} +2 -2
  60. package/dist/{request-planner-VFWWT5XR.js → request-planner-ZZRSOBQZ.js} +2 -2
  61. package/dist/{review-candidates-2PI4CGZO.js → review-candidates-KHH47PK7.js} +2 -2
  62. package/dist/routing-GUBKKWPT.js +2 -0
  63. package/dist/schedule-tool-VH77T3N3.js +2 -0
  64. package/dist/scheduler-SZ4YYXJE.js +2 -0
  65. package/dist/{seat-TVNR245I.js → seat-CVTTTE5V.js} +2 -2
  66. package/dist/{select-KY7B4HAS.js → select-OUTM6OBC.js} +2 -2
  67. package/dist/{set-enabled-NEINY2I2.js → set-enabled-2QKQRVUN.js} +2 -2
  68. package/dist/token-store-AY6OBDVI.js +2 -0
  69. package/dist/token-store-AY6OBDVI.js.map +1 -0
  70. package/dist/{tool-5JGMWH62.js → tool-OFXHMLE5.js} +2 -2
  71. package/dist/{tool-MQQ2W5LJ.js → tool-XY7QGHLV.js} +2 -2
  72. package/dist/wiki-46GMWX34.js +2 -0
  73. package/dist/wiki-46GMWX34.js.map +1 -0
  74. package/package.json +1 -1
  75. package/dist/board-dashboard-4GQ7RTH3.js.map +0 -1
  76. package/dist/chunk-2QSG53RN.js +0 -482
  77. package/dist/chunk-2QSG53RN.js.map +0 -1
  78. package/dist/chunk-ACFQBLPX.js +0 -3
  79. package/dist/chunk-ACFQBLPX.js.map +0 -1
  80. package/dist/chunk-ECBVOIIK.js.map +0 -1
  81. package/dist/chunk-IGORU3XR.js +0 -54
  82. package/dist/chunk-IGORU3XR.js.map +0 -1
  83. package/dist/config-mutator-22AVTST2.js +0 -2
  84. package/dist/doctor-6RDRST4G.js +0 -2
  85. package/dist/program-53CQJEUZ.js.map +0 -1
  86. package/dist/push-HEDA6P3B.js +0 -2
  87. package/dist/push-HEDA6P3B.js.map +0 -1
  88. package/dist/push-store-5VJ4FNI4.js +0 -2
  89. package/dist/routing-M7MDLD7Q.js +0 -2
  90. package/dist/schedule-tool-2EQ53IOQ.js +0 -2
  91. package/dist/scheduler-YGVINPZF.js +0 -2
  92. package/dist/token-store-YBSU2DTV.js +0 -2
  93. package/dist/wiki-COAUQ6TQ.js +0 -2
  94. /package/dist/{App-6OMMZW2M.js.map → App-UQP7UQYV.js.map} +0 -0
  95. /package/dist/{ChatApp-EDDROHNA.js.map → ChatApp-VGSP5O6N.js.map} +0 -0
  96. /package/dist/{agent-VPM3EEUB.js.map → agent-MO27U4Y7.js.map} +0 -0
  97. /package/dist/{chunk-S4XSVAAG.js.map → chunk-45GOH6F7.js.map} +0 -0
  98. /package/dist/{chunk-CJJULHPJ.js.map → chunk-4ELAUGOP.js.map} +0 -0
  99. /package/dist/{chunk-5FY7PWXW.js.map → chunk-5PPMPCHG.js.map} +0 -0
  100. /package/dist/{chunk-BU4LE2RT.js.map → chunk-746KHKT4.js.map} +0 -0
  101. /package/dist/{chunk-QLB76BGE.js.map → chunk-BQ2HJ7TS.js.map} +0 -0
  102. /package/dist/{chunk-PITMPRVP.js.map → chunk-CKQ2YDFP.js.map} +0 -0
  103. /package/dist/{chunk-7T7IXLLA.js.map → chunk-CUZTLQH2.js.map} +0 -0
  104. /package/dist/{chunk-PX2AOZ5G.js.map → chunk-HVZVFCJX.js.map} +0 -0
  105. /package/dist/{chunk-BXYKFWAI.js.map → chunk-HYGMWCUU.js.map} +0 -0
  106. /package/dist/{chunk-YE4HKOS5.js.map → chunk-J2YLOGNN.js.map} +0 -0
  107. /package/dist/{chunk-MG5LRE5B.js.map → chunk-OJ7KM2UO.js.map} +0 -0
  108. /package/dist/{chunk-4STXRZZS.js.map → chunk-PFK3QO6S.js.map} +0 -0
  109. /package/dist/{chunk-K3BG77KK.js.map → chunk-PMQ47IPT.js.map} +0 -0
  110. /package/dist/{chunk-KTF4YF4M.js.map → chunk-T2VDHVYW.js.map} +0 -0
  111. /package/dist/{chunk-J5TZ6QGD.js.map → chunk-VEHTVYP6.js.map} +0 -0
  112. /package/dist/{chunk-SDOSQ6TJ.js.map → chunk-VRXJW6JJ.js.map} +0 -0
  113. /package/dist/{chunk-UQX2HY5M.js.map → chunk-W7WNRPNQ.js.map} +0 -0
  114. /package/dist/{client-VUNPLVCG.js.map → client-5UMNDY7Z.js.map} +0 -0
  115. /package/dist/{config-HE2LGTTG.js.map → config-O44DOHFW.js.map} +0 -0
  116. /package/dist/{config-mutator-22AVTST2.js.map → config-mutator-PRLY2TCE.js.map} +0 -0
  117. /package/dist/{doctor-6RDRST4G.js.map → doctor-NKPH74F7.js.map} +0 -0
  118. /package/dist/{promote-4PPJJ6AW.js.map → promote-ZRNVPWTD.js.map} +0 -0
  119. /package/dist/{push-store-5VJ4FNI4.js.map → push-DID6RZYI.js.map} +0 -0
  120. /package/dist/{query-ETDKC7WC.js.map → push-bridge-VPTQNM43.js.map} +0 -0
  121. /package/dist/{registry-AMETOJ3S.js.map → push-store-L5QHMSST.js.map} +0 -0
  122. /package/dist/{routing-M7MDLD7Q.js.map → query-HURONGKA.js.map} +0 -0
  123. /package/dist/{schedule-tool-2EQ53IOQ.js.map → registry-AYGFAKTC.js.map} +0 -0
  124. /package/dist/{request-planner-VFWWT5XR.js.map → request-planner-ZZRSOBQZ.js.map} +0 -0
  125. /package/dist/{review-candidates-2PI4CGZO.js.map → review-candidates-KHH47PK7.js.map} +0 -0
  126. /package/dist/{scheduler-YGVINPZF.js.map → routing-GUBKKWPT.js.map} +0 -0
  127. /package/dist/{seat-TVNR245I.js.map → schedule-tool-VH77T3N3.js.map} +0 -0
  128. /package/dist/{token-store-YBSU2DTV.js.map → scheduler-SZ4YYXJE.js.map} +0 -0
  129. /package/dist/{wiki-COAUQ6TQ.js.map → seat-CVTTTE5V.js.map} +0 -0
  130. /package/dist/{select-KY7B4HAS.js.map → select-OUTM6OBC.js.map} +0 -0
  131. /package/dist/{set-enabled-NEINY2I2.js.map → set-enabled-2QKQRVUN.js.map} +0 -0
  132. /package/dist/{tool-5JGMWH62.js.map → tool-OFXHMLE5.js.map} +0 -0
  133. /package/dist/{tool-MQQ2W5LJ.js.map → tool-XY7QGHLV.js.map} +0 -0
@@ -1,5 +1,5 @@
1
- import{ja as m,ma as b}from"./chunk-IGORU3XR.js";b();function w(t){let e=typeof t.node=="string"?t.node:"",n=typeof t.token=="string"?t.token:"";if(!e||!n)try{let o=m(t.config);e||(e=o.dashboard?.daemonUrl||""),n||(n=o.dashboard?.token||"")}catch{}return e||(e="http://localhost:18800"),{baseUrl:e.replace(/\/+$/,""),token:n}}async function d(t,e,n){let o={Accept:"application/json"};t.token&&(o.Authorization=`Bearer ${t.token}`);let r=await fetch(`${t.baseUrl}${e}`,{headers:o,signal:n});if(!r.ok)throw new Error(`GET ${e} \u2192 HTTP ${r.status}`);return await r.json()}function R(t,e){return d(t,"/agents",e)}async function S(t,e){return(await d(t,"/api/processes",e)).processes??[]}function P(t,e){return d(t,"/crons",e)}async function h(t,e,n,o){let r={Accept:"application/json","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}${e}`,{method:"POST",headers:r,body:JSON.stringify(n),signal:o}),a=await s.text(),i;try{i=a?JSON.parse(a):{}}catch{i={raw:a}}if(!s.ok)throw new Error(i?.error||`POST ${e} \u2192 HTTP ${s.status}`);return i}function A(t,e,n="tui"){return h(t,"/api/processes/kill",{...e,reason:n})}function C(t,e,n,o){return h(t,"/task",{agent:e,message:n,context:o??{channel:"tui",chatId:"tui:operator"}})}async function $(t,e,n,o={}){let r={Accept:"text/event-stream","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}/task`,{method:"POST",headers:r,body:JSON.stringify({agent:e,message:n,stream:!0,context:{channel:o.channel??"chat-cli",chatId:o.chatId??"chat-cli:operator"}}),signal:o.signal});if(!s.ok||!s.body){let g=await s.text().catch(()=>"");throw new Error(`POST /task (stream) \u2192 HTTP ${s.status}${g?`: ${g.slice(0,200)}`:""}`)}let a=s.body.getReader(),i=new TextDecoder,u={content:""},c="";try{for(;;){let{done:g,value:p}=await a.read();if(g)break;c+=i.decode(p,{stream:!0});let l;for(;(l=c.indexOf(`
1
+ import{ja as m,ma as b}from"./chunk-FJI5GRBH.js";b();function w(t){let e=typeof t.node=="string"?t.node:"",n=typeof t.token=="string"?t.token:"";if(!e||!n)try{let o=m(t.config);e||(e=o.dashboard?.daemonUrl||""),n||(n=o.dashboard?.token||"")}catch{}return e||(e="http://localhost:18800"),{baseUrl:e.replace(/\/+$/,""),token:n}}async function d(t,e,n){let o={Accept:"application/json"};t.token&&(o.Authorization=`Bearer ${t.token}`);let r=await fetch(`${t.baseUrl}${e}`,{headers:o,signal:n});if(!r.ok)throw new Error(`GET ${e} \u2192 HTTP ${r.status}`);return await r.json()}function R(t,e){return d(t,"/agents",e)}async function S(t,e){return(await d(t,"/api/processes",e)).processes??[]}function P(t,e){return d(t,"/crons",e)}async function h(t,e,n,o){let r={Accept:"application/json","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}${e}`,{method:"POST",headers:r,body:JSON.stringify(n),signal:o}),a=await s.text(),i;try{i=a?JSON.parse(a):{}}catch{i={raw:a}}if(!s.ok)throw new Error(i?.error||`POST ${e} \u2192 HTTP ${s.status}`);return i}function A(t,e,n="tui"){return h(t,"/api/processes/kill",{...e,reason:n})}function C(t,e,n,o){return h(t,"/task",{agent:e,message:n,context:o??{channel:"tui",chatId:"tui:operator"}})}async function $(t,e,n,o={}){let r={Accept:"text/event-stream","Content-Type":"application/json"};t.token&&(r.Authorization=`Bearer ${t.token}`);let s=await fetch(`${t.baseUrl}/task`,{method:"POST",headers:r,body:JSON.stringify({agent:e,message:n,stream:!0,context:{channel:o.channel??"chat-cli",chatId:o.chatId??"chat-cli:operator"}}),signal:o.signal});if(!s.ok||!s.body){let g=await s.text().catch(()=>"");throw new Error(`POST /task (stream) \u2192 HTTP ${s.status}${g?`: ${g.slice(0,200)}`:""}`)}let a=s.body.getReader(),i=new TextDecoder,u={content:""},c="";try{for(;;){let{done:g,value:p}=await a.read();if(g)break;c+=i.decode(p,{stream:!0});let l;for(;(l=c.indexOf(`
2
2
 
3
3
  `))>=0;){let k=c.slice(0,l);c=c.slice(l+2);let f=x(k);f&&T(f,o,u)}}}finally{try{a.releaseLock()}catch{}}return u}function T(t,e,n){let{event:o,data:r}=t;switch(o){case"text":r?.text&&(n.content+=r.text,e.onText?.(r.text));break;case"thinking":r?.text&&e.onThinking?.(r.text);break;case"tool":e.onTool?.(r);break;case"done":typeof r?.content=="string"&&(n.content=r.content),n.usage=r?.usage,n.duration=r?.duration;break;case"error":n.error=r?.error,n.errorKind=r?.errorKind;break}}function x(t){let e="message",n="";for(let r of t.split(`
4
4
  `))r.startsWith("event: ")?e=r.slice(7).trim():r.startsWith("data: ")&&(n=r.slice(6));if(!n)return null;let o;try{o=JSON.parse(n)}catch{o=n}return{event:e,data:o}}export{w as a,R as b,S as c,P as d,A as e,C as f,$ as g};
5
- //# sourceMappingURL=chunk-YE4HKOS5.js.map
5
+ //# sourceMappingURL=chunk-J2YLOGNN.js.map
@@ -1,10 +1,10 @@
1
- import{b as s}from"./chunk-JWDJMFU6.js";var d=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS push_subscriptions (
1
+ import{b as d}from"./chunk-JWDJMFU6.js";var n=class{constructor(e){this.db=e;e.exec(`CREATE TABLE IF NOT EXISTS push_subscriptions (
2
2
  endpoint TEXT PRIMARY KEY, p256dh TEXT NOT NULL, auth TEXT NOT NULL,
3
3
  device_id TEXT NOT NULL, device_name TEXT NOT NULL, public_key TEXT NOT NULL,
4
4
  created_at INTEGER NOT NULL);
5
5
  CREATE INDEX IF NOT EXISTS push_subscriptions_device ON push_subscriptions(device_id);
6
6
  CREATE TABLE IF NOT EXISTS push_log (
7
7
  id INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL, title TEXT NOT NULL,
8
- body TEXT NOT NULL, url TEXT, delivered INTEGER NOT NULL, device_id TEXT);`),this.prefs=new s(e)}prefs;chatFinishOn(e){return this.prefs.on(e,"finish")}setChatFinish(e,t,i=Date.now()){this.prefs.set(e,"finish",t,i)}subscribe(e,t=Date.now()){this.db.prepare(`INSERT OR REPLACE INTO push_subscriptions
9
- (endpoint, p256dh, auth, device_id, device_name, public_key, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(e.endpoint,e.p256dh,e.auth,e.deviceId,e.deviceName,e.publicKey,t)}unsubscribe(e,t){return(t===void 0?this.db.prepare("DELETE FROM push_subscriptions WHERE endpoint = ?").run(e):this.db.prepare("DELETE FROM push_subscriptions WHERE endpoint = ? AND device_id = ?").run(e,t)).changes>0}list(e){return(e===void 0?this.db.prepare("SELECT * FROM push_subscriptions ORDER BY created_at").all():this.db.prepare("SELECT * FROM push_subscriptions WHERE device_id = ? ORDER BY created_at").all(e)).map(i=>({endpoint:i.endpoint,p256dh:i.p256dh,auth:i.auth,deviceId:i.device_id,deviceName:i.device_name,publicKey:i.public_key,createdAt:i.created_at}))}log(e,t,i=Date.now()){this.db.prepare("INSERT INTO push_log (at, title, body, url, delivered, device_id) VALUES (?, ?, ?, ?, ?, ?)").run(i,e.title,e.body,e.url,e.delivered,e.deviceId),this.db.prepare("DELETE FROM push_log WHERE id NOT IN (SELECT id FROM push_log ORDER BY id DESC LIMIT ?)").run(Math.max(0,t))}recent(e,t){let i="id, at, title, body, url, delivered, device_id AS deviceId";return t===void 0?this.db.prepare(`SELECT ${i} FROM push_log ORDER BY id DESC LIMIT ?`).all(Math.max(0,e)):this.db.prepare(`SELECT ${i} FROM push_log WHERE device_id IS NULL OR device_id = ? ORDER BY id DESC LIMIT ?`).all(t,Math.max(0,e))}};export{d as a};
10
- //# sourceMappingURL=chunk-2NYP4OQU.js.map
8
+ body TEXT NOT NULL, url TEXT, delivered INTEGER NOT NULL, device_id TEXT);`),this.prefs=new d(e)}prefs;chatFinishOn(e){return this.prefs.on(e,"finish")}setChatFinish(e,t,i=Date.now()){this.prefs.set(e,"finish",t,i)}subscribe(e,t=Date.now()){this.db.prepare(`INSERT OR REPLACE INTO push_subscriptions
9
+ (endpoint, p256dh, auth, device_id, device_name, public_key, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`).run(e.endpoint,e.p256dh,e.auth,e.deviceId,e.deviceName,e.publicKey,t)}unsubscribe(e,t){return(t===void 0?this.db.prepare("DELETE FROM push_subscriptions WHERE endpoint = ?").run(e):this.db.prepare("DELETE FROM push_subscriptions WHERE endpoint = ? AND device_id = ?").run(e,t)).changes>0}list(e){return(e===void 0?this.db.prepare("SELECT * FROM push_subscriptions ORDER BY created_at").all():this.db.prepare("SELECT * FROM push_subscriptions WHERE device_id = ? ORDER BY created_at").all(e)).map(i=>({endpoint:i.endpoint,p256dh:i.p256dh,auth:i.auth,deviceId:i.device_id,deviceName:i.device_name,publicKey:i.public_key,createdAt:i.created_at}))}pruneOrigin(e,t){let i=new Set([...t].map(s=>`${e}:${s}`)),r=0;for(let s of this.list())s.deviceId.startsWith(`${e}:`)&&!i.has(s.deviceId)&&this.unsubscribe(s.endpoint)&&r++;return r}forgetDevice(e){return this.db.prepare("DELETE FROM push_subscriptions WHERE device_id = ?").run(e).changes}log(e,t,i=Date.now()){this.db.prepare("INSERT INTO push_log (at, title, body, url, delivered, device_id) VALUES (?, ?, ?, ?, ?, ?)").run(i,e.title,e.body,e.url,e.delivered,e.deviceId),this.db.prepare("DELETE FROM push_log WHERE id NOT IN (SELECT id FROM push_log ORDER BY id DESC LIMIT ?)").run(Math.max(0,t))}recent(e,t){let i="id, at, title, body, url, delivered, device_id AS deviceId";return t===void 0?this.db.prepare(`SELECT ${i} FROM push_log ORDER BY id DESC LIMIT ?`).all(Math.max(0,e)):this.db.prepare(`SELECT ${i} FROM push_log WHERE device_id IS NULL OR device_id = ? ORDER BY id DESC LIMIT ?`).all(t,Math.max(0,e))}};export{n as a};
10
+ //# sourceMappingURL=chunk-LNY6N73E.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/channels/push-store.ts"],"sourcesContent":["import type Database from \"better-sqlite3\"\nimport { PushPrefs } from \"./push-prefs\"\n\n// --- Web Push subscriptions and recent pushes (SQLite) ---\n//\n// Shared by two processes on the node that hosts the phone app: the\n// dashboard writes subscriptions when a phone turns notifications on\n// (/api/app/push/*), and the daemon's PushAdapter reads them to deliver,\n// prunes the ones the push service reports gone, and logs what it sent for\n// the app's Alerts tab. Both open the same .agentx/db.sqlite; WAL lets one\n// write while the other reads.\n//\n// Tables are created here with IF NOT EXISTS rather than as a numbered\n// migration, so a branch that claims the same migration number elsewhere\n// can't make a database skip them.\n\nexport interface PushSubscriptionRow {\n endpoint: string\n p256dh: string\n auth: string\n /** Token id of the paired phone (TokenRecord.id). */\n deviceId: string\n deviceName: string\n /** VAPID public key the browser subscribed with. After\n * `agentx app push-keys --force` older rows can never be delivered. */\n publicKey: string\n createdAt: number\n}\n\nexport interface PushLogRow {\n id: number\n at: number\n title: string\n body: string\n url: string | null\n /** Phones the push service accepted it for. */\n delivered: number\n /** Set when the push was addressed to one phone; null for every phone. */\n deviceId: string | null\n}\n\nexport class PushStore {\n constructor(private db: Database.Database) {\n db.exec(`CREATE TABLE IF NOT EXISTS push_subscriptions (\n endpoint TEXT PRIMARY KEY, p256dh TEXT NOT NULL, auth TEXT NOT NULL,\n device_id TEXT NOT NULL, device_name TEXT NOT NULL, public_key TEXT NOT NULL,\n created_at INTEGER NOT NULL);\n CREATE INDEX IF NOT EXISTS push_subscriptions_device ON push_subscriptions(device_id);\n CREATE TABLE IF NOT EXISTS push_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL, title TEXT NOT NULL,\n body TEXT NOT NULL, url TEXT, delivered INTEGER NOT NULL, device_id TEXT);`)\n this.prefs = new PushPrefs(db)\n }\n\n /** Per-phone switches for each kind of notification (push-prefs.ts). */\n readonly prefs: PushPrefs\n\n /** Whether this phone is told when a chat answer finishes while it looks\n * elsewhere (#265). On unless the phone turned it off. */\n chatFinishOn(deviceId: string): boolean {\n return this.prefs.on(deviceId, \"finish\")\n }\n\n setChatFinish(deviceId: string, on: boolean, now = Date.now()): void {\n this.prefs.set(deviceId, \"finish\", on, now)\n }\n\n /** Adds or refreshes a subscription. A browser that re-subscribes keeps\n * its endpoint, so the row is replaced, not duplicated. */\n subscribe(row: Omit<PushSubscriptionRow, \"createdAt\">, now = Date.now()): void {\n this.db.prepare(`INSERT OR REPLACE INTO push_subscriptions\n (endpoint, p256dh, auth, device_id, device_name, public_key, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`)\n .run(row.endpoint, row.p256dh, row.auth, row.deviceId, row.deviceName, row.publicKey, now)\n }\n\n /** Removes one subscription, only if it belongs to `deviceId` when given. */\n unsubscribe(endpoint: string, deviceId?: string): boolean {\n const r = deviceId === undefined\n ? this.db.prepare(\"DELETE FROM push_subscriptions WHERE endpoint = ?\").run(endpoint)\n : this.db.prepare(\"DELETE FROM push_subscriptions WHERE endpoint = ? AND device_id = ?\").run(endpoint, deviceId)\n return r.changes > 0\n }\n\n list(deviceId?: string): PushSubscriptionRow[] {\n const rows = (deviceId === undefined\n ? this.db.prepare(\"SELECT * FROM push_subscriptions ORDER BY created_at\").all()\n : this.db.prepare(\"SELECT * FROM push_subscriptions WHERE device_id = ? ORDER BY created_at\").all(deviceId)) as any[]\n return rows.map((r) => ({\n endpoint: r.endpoint, p256dh: r.p256dh, auth: r.auth,\n deviceId: r.device_id, deviceName: r.device_name, publicKey: r.public_key, createdAt: r.created_at,\n }))\n }\n\n /** Records a sent push and keeps only the newest `keep` rows. */\n log(entry: Omit<PushLogRow, \"id\" | \"at\">, keep: number, now = Date.now()): void {\n this.db.prepare(\"INSERT INTO push_log (at, title, body, url, delivered, device_id) VALUES (?, ?, ?, ?, ?, ?)\")\n .run(now, entry.title, entry.body, entry.url, entry.delivered, entry.deviceId)\n this.db.prepare(\"DELETE FROM push_log WHERE id NOT IN (SELECT id FROM push_log ORDER BY id DESC LIMIT ?)\").run(Math.max(0, keep))\n }\n\n /** Newest first. With `deviceId`, only pushes sent to every phone or to\n * that one, so one phone never sees another's messages. */\n recent(limit: number, deviceId?: string): PushLogRow[] {\n const cols = \"id, at, title, body, url, delivered, device_id AS deviceId\"\n return (deviceId === undefined\n ? this.db.prepare(`SELECT ${cols} FROM push_log ORDER BY id DESC LIMIT ?`).all(Math.max(0, limit))\n : this.db.prepare(`SELECT ${cols} FROM push_log WHERE device_id IS NULL OR device_id = ? ORDER BY id DESC LIMIT ?`)\n .all(deviceId, Math.max(0, limit))) as PushLogRow[]\n }\n}\n"],"mappings":"wCAyCO,IAAMA,EAAN,KAAgB,CACrB,YAAoBC,EAAuB,CAAvB,QAAAA,EAClBA,EAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iFAOqE,EAC7E,KAAK,MAAQ,IAAIC,EAAUD,CAAE,CAC/B,CAGS,MAIT,aAAaE,EAA2B,CACtC,OAAO,KAAK,MAAM,GAAGA,EAAU,QAAQ,CACzC,CAEA,cAAcA,EAAkBC,EAAaC,EAAM,KAAK,IAAI,EAAS,CACnE,KAAK,MAAM,IAAIF,EAAU,SAAUC,EAAIC,CAAG,CAC5C,CAIA,UAAUC,EAA6CD,EAAM,KAAK,IAAI,EAAS,CAC7E,KAAK,GAAG,QAAQ;AAAA,4GACwF,EACrG,IAAIC,EAAI,SAAUA,EAAI,OAAQA,EAAI,KAAMA,EAAI,SAAUA,EAAI,WAAYA,EAAI,UAAWD,CAAG,CAC7F,CAGA,YAAYE,EAAkBJ,EAA4B,CAIxD,OAHUA,IAAa,OACnB,KAAK,GAAG,QAAQ,mDAAmD,EAAE,IAAII,CAAQ,EACjF,KAAK,GAAG,QAAQ,qEAAqE,EAAE,IAAIA,EAAUJ,CAAQ,GACxG,QAAU,CACrB,CAEA,KAAKA,EAA0C,CAI7C,OAHcA,IAAa,OACvB,KAAK,GAAG,QAAQ,sDAAsD,EAAE,IAAI,EAC5E,KAAK,GAAG,QAAQ,0EAA0E,EAAE,IAAIA,CAAQ,GAChG,IAAKK,IAAO,CACtB,SAAUA,EAAE,SAAU,OAAQA,EAAE,OAAQ,KAAMA,EAAE,KAChD,SAAUA,EAAE,UAAW,WAAYA,EAAE,YAAa,UAAWA,EAAE,WAAY,UAAWA,EAAE,UAC1F,EAAE,CACJ,CAGA,IAAIC,EAAsCC,EAAcL,EAAM,KAAK,IAAI,EAAS,CAC9E,KAAK,GAAG,QAAQ,6FAA6F,EAC1G,IAAIA,EAAKI,EAAM,MAAOA,EAAM,KAAMA,EAAM,IAAKA,EAAM,UAAWA,EAAM,QAAQ,EAC/E,KAAK,GAAG,QAAQ,yFAAyF,EAAE,IAAI,KAAK,IAAI,EAAGC,CAAI,CAAC,CAClI,CAIA,OAAOC,EAAeR,EAAiC,CACrD,IAAMS,EAAO,6DACb,OAAQT,IAAa,OACjB,KAAK,GAAG,QAAQ,UAAUS,0CAA6C,EAAE,IAAI,KAAK,IAAI,EAAGD,CAAK,CAAC,EAC/F,KAAK,GAAG,QAAQ,UAAUC,mFAAsF,EAC/G,IAAIT,EAAU,KAAK,IAAI,EAAGQ,CAAK,CAAC,CACvC,CACF","names":["PushStore","db","PushPrefs","deviceId","on","now","row","endpoint","r","entry","keep","limit","cols"]}
1
+ {"version":3,"sources":["../src/channels/push-store.ts"],"sourcesContent":["import type Database from \"better-sqlite3\"\nimport { PushPrefs } from \"./push-prefs\"\n\n// --- Web Push subscriptions and recent pushes (SQLite) ---\n//\n// Shared by two processes on the node that hosts the phone app: the\n// dashboard writes subscriptions when a phone turns notifications on\n// (/api/app/push/*), and the daemon's PushAdapter reads them to deliver,\n// prunes the ones the push service reports gone, and logs what it sent for\n// the app's Alerts tab. Both open the same .agentx/db.sqlite; WAL lets one\n// write while the other reads.\n//\n// Tables are created here with IF NOT EXISTS rather than as a numbered\n// migration, so a branch that claims the same migration number elsewhere\n// can't make a database skip them.\n\nexport interface PushSubscriptionRow {\n endpoint: string\n p256dh: string\n auth: string\n /** Token id of the paired phone (TokenRecord.id). */\n deviceId: string\n deviceName: string\n /** VAPID public key the browser subscribed with. After\n * `agentx app push-keys --force` older rows can never be delivered. */\n publicKey: string\n createdAt: number\n}\n\nexport interface PushLogRow {\n id: number\n at: number\n title: string\n body: string\n url: string | null\n /** Phones the push service accepted it for. */\n delivered: number\n /** Set when the push was addressed to one phone; null for every phone. */\n deviceId: string | null\n}\n\nexport class PushStore {\n constructor(private db: Database.Database) {\n db.exec(`CREATE TABLE IF NOT EXISTS push_subscriptions (\n endpoint TEXT PRIMARY KEY, p256dh TEXT NOT NULL, auth TEXT NOT NULL,\n device_id TEXT NOT NULL, device_name TEXT NOT NULL, public_key TEXT NOT NULL,\n created_at INTEGER NOT NULL);\n CREATE INDEX IF NOT EXISTS push_subscriptions_device ON push_subscriptions(device_id);\n CREATE TABLE IF NOT EXISTS push_log (\n id INTEGER PRIMARY KEY AUTOINCREMENT, at INTEGER NOT NULL, title TEXT NOT NULL,\n body TEXT NOT NULL, url TEXT, delivered INTEGER NOT NULL, device_id TEXT);`)\n this.prefs = new PushPrefs(db)\n }\n\n /** Per-phone switches for each kind of notification (push-prefs.ts). */\n readonly prefs: PushPrefs\n\n /** Whether this phone is told when a chat answer finishes while it looks\n * elsewhere (#265). On unless the phone turned it off. */\n chatFinishOn(deviceId: string): boolean {\n return this.prefs.on(deviceId, \"finish\")\n }\n\n setChatFinish(deviceId: string, on: boolean, now = Date.now()): void {\n this.prefs.set(deviceId, \"finish\", on, now)\n }\n\n /** Adds or refreshes a subscription. A browser that re-subscribes keeps\n * its endpoint, so the row is replaced, not duplicated. */\n subscribe(row: Omit<PushSubscriptionRow, \"createdAt\">, now = Date.now()): void {\n this.db.prepare(`INSERT OR REPLACE INTO push_subscriptions\n (endpoint, p256dh, auth, device_id, device_name, public_key, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`)\n .run(row.endpoint, row.p256dh, row.auth, row.deviceId, row.deviceName, row.publicKey, now)\n }\n\n /** Removes one subscription, only if it belongs to `deviceId` when given. */\n unsubscribe(endpoint: string, deviceId?: string): boolean {\n const r = deviceId === undefined\n ? this.db.prepare(\"DELETE FROM push_subscriptions WHERE endpoint = ?\").run(endpoint)\n : this.db.prepare(\"DELETE FROM push_subscriptions WHERE endpoint = ? AND device_id = ?\").run(endpoint, deviceId)\n return r.changes > 0\n }\n\n list(deviceId?: string): PushSubscriptionRow[] {\n const rows = (deviceId === undefined\n ? this.db.prepare(\"SELECT * FROM push_subscriptions ORDER BY created_at\").all()\n : this.db.prepare(\"SELECT * FROM push_subscriptions WHERE device_id = ? ORDER BY created_at\").all(deviceId)) as any[]\n return rows.map((r) => ({\n endpoint: r.endpoint, p256dh: r.p256dh, auth: r.auth,\n deviceId: r.device_id, deviceName: r.device_name, publicKey: r.public_key, createdAt: r.created_at,\n }))\n }\n\n /** Removes the subscriptions of phones paired with relaying node\n * `origin` whose token id isn't in `active` (revoked, expired or\n * removed there). Returns how many rows went. */\n pruneOrigin(origin: string, active: Iterable<string>): number {\n const keep = new Set([...active].map((id) => `${origin}:${id}`))\n let removed = 0\n for (const s of this.list()) {\n if (s.deviceId.startsWith(`${origin}:`) && !keep.has(s.deviceId)) {\n if (this.unsubscribe(s.endpoint)) removed++\n }\n }\n return removed\n }\n\n /** Removes every subscription of one device id. Returns how many went. */\n forgetDevice(deviceId: string): number {\n return this.db.prepare(\"DELETE FROM push_subscriptions WHERE device_id = ?\").run(deviceId).changes\n }\n\n /** Records a sent push and keeps only the newest `keep` rows. */\n log(entry: Omit<PushLogRow, \"id\" | \"at\">, keep: number, now = Date.now()): void {\n this.db.prepare(\"INSERT INTO push_log (at, title, body, url, delivered, device_id) VALUES (?, ?, ?, ?, ?, ?)\")\n .run(now, entry.title, entry.body, entry.url, entry.delivered, entry.deviceId)\n this.db.prepare(\"DELETE FROM push_log WHERE id NOT IN (SELECT id FROM push_log ORDER BY id DESC LIMIT ?)\").run(Math.max(0, keep))\n }\n\n /** Newest first. With `deviceId`, only pushes sent to every phone or to\n * that one, so one phone never sees another's messages. */\n recent(limit: number, deviceId?: string): PushLogRow[] {\n const cols = \"id, at, title, body, url, delivered, device_id AS deviceId\"\n return (deviceId === undefined\n ? this.db.prepare(`SELECT ${cols} FROM push_log ORDER BY id DESC LIMIT ?`).all(Math.max(0, limit))\n : this.db.prepare(`SELECT ${cols} FROM push_log WHERE device_id IS NULL OR device_id = ? ORDER BY id DESC LIMIT ?`)\n .all(deviceId, Math.max(0, limit))) as PushLogRow[]\n }\n}\n"],"mappings":"wCAyCO,IAAMA,EAAN,KAAgB,CACrB,YAAoBC,EAAuB,CAAvB,QAAAA,EAClBA,EAAG,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iFAOqE,EAC7E,KAAK,MAAQ,IAAIC,EAAUD,CAAE,CAC/B,CAGS,MAIT,aAAaE,EAA2B,CACtC,OAAO,KAAK,MAAM,GAAGA,EAAU,QAAQ,CACzC,CAEA,cAAcA,EAAkBC,EAAaC,EAAM,KAAK,IAAI,EAAS,CACnE,KAAK,MAAM,IAAIF,EAAU,SAAUC,EAAIC,CAAG,CAC5C,CAIA,UAAUC,EAA6CD,EAAM,KAAK,IAAI,EAAS,CAC7E,KAAK,GAAG,QAAQ;AAAA,4GACwF,EACrG,IAAIC,EAAI,SAAUA,EAAI,OAAQA,EAAI,KAAMA,EAAI,SAAUA,EAAI,WAAYA,EAAI,UAAWD,CAAG,CAC7F,CAGA,YAAYE,EAAkBJ,EAA4B,CAIxD,OAHUA,IAAa,OACnB,KAAK,GAAG,QAAQ,mDAAmD,EAAE,IAAII,CAAQ,EACjF,KAAK,GAAG,QAAQ,qEAAqE,EAAE,IAAIA,EAAUJ,CAAQ,GACxG,QAAU,CACrB,CAEA,KAAKA,EAA0C,CAI7C,OAHcA,IAAa,OACvB,KAAK,GAAG,QAAQ,sDAAsD,EAAE,IAAI,EAC5E,KAAK,GAAG,QAAQ,0EAA0E,EAAE,IAAIA,CAAQ,GAChG,IAAKK,IAAO,CACtB,SAAUA,EAAE,SAAU,OAAQA,EAAE,OAAQ,KAAMA,EAAE,KAChD,SAAUA,EAAE,UAAW,WAAYA,EAAE,YAAa,UAAWA,EAAE,WAAY,UAAWA,EAAE,UAC1F,EAAE,CACJ,CAKA,YAAYC,EAAgBC,EAAkC,CAC5D,IAAMC,EAAO,IAAI,IAAI,CAAC,GAAGD,CAAM,EAAE,IAAKE,GAAO,GAAGH,KAAUG,GAAI,CAAC,EAC3DC,EAAU,EACd,QAAW,KAAK,KAAK,KAAK,EACpB,EAAE,SAAS,WAAW,GAAGJ,IAAS,GAAK,CAACE,EAAK,IAAI,EAAE,QAAQ,GACzD,KAAK,YAAY,EAAE,QAAQ,GAAGE,IAGtC,OAAOA,CACT,CAGA,aAAaV,EAA0B,CACrC,OAAO,KAAK,GAAG,QAAQ,oDAAoD,EAAE,IAAIA,CAAQ,EAAE,OAC7F,CAGA,IAAIW,EAAsCH,EAAcN,EAAM,KAAK,IAAI,EAAS,CAC9E,KAAK,GAAG,QAAQ,6FAA6F,EAC1G,IAAIA,EAAKS,EAAM,MAAOA,EAAM,KAAMA,EAAM,IAAKA,EAAM,UAAWA,EAAM,QAAQ,EAC/E,KAAK,GAAG,QAAQ,yFAAyF,EAAE,IAAI,KAAK,IAAI,EAAGH,CAAI,CAAC,CAClI,CAIA,OAAOI,EAAeZ,EAAiC,CACrD,IAAMa,EAAO,6DACb,OAAQb,IAAa,OACjB,KAAK,GAAG,QAAQ,UAAUa,0CAA6C,EAAE,IAAI,KAAK,IAAI,EAAGD,CAAK,CAAC,EAC/F,KAAK,GAAG,QAAQ,UAAUC,mFAAsF,EAC/G,IAAIb,EAAU,KAAK,IAAI,EAAGY,CAAK,CAAC,CACvC,CACF","names":["PushStore","db","PushPrefs","deviceId","on","now","row","endpoint","r","origin","active","keep","id","removed","entry","limit","cols"]}