agentix-cli 0.16.0 → 0.18.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 (173) hide show
  1. package/dist/agent-RDVGL2TW.js +2 -0
  2. package/dist/audit-Z47AQFFD.js +3 -0
  3. package/dist/audit-Z47AQFFD.js.map +1 -0
  4. package/dist/board-dashboard-KX2CNOSY.js +7282 -0
  5. package/dist/board-dashboard-KX2CNOSY.js.map +1 -0
  6. package/dist/chunk-34NG7UDX.js +11 -0
  7. package/dist/chunk-34NG7UDX.js.map +1 -0
  8. package/dist/{chunk-6MKAXEE5.js → chunk-4ITQP3XL.js} +2 -2
  9. package/dist/{chunk-6MKAXEE5.js.map → chunk-4ITQP3XL.js.map} +1 -1
  10. package/dist/chunk-53NRX2NA.js +2 -0
  11. package/dist/chunk-53NRX2NA.js.map +1 -0
  12. package/dist/chunk-6PPIFDOQ.js +1742 -0
  13. package/dist/chunk-6PPIFDOQ.js.map +1 -0
  14. package/dist/chunk-AFRHKA7B.js +2 -0
  15. package/dist/chunk-AFRHKA7B.js.map +1 -0
  16. package/dist/chunk-ASSJ4Z6Z.js +164 -0
  17. package/dist/chunk-ASSJ4Z6Z.js.map +1 -0
  18. package/dist/chunk-BLUXL6HR.js +854 -0
  19. package/dist/chunk-BLUXL6HR.js.map +1 -0
  20. package/dist/chunk-BTAEYL3P.js +72 -0
  21. package/dist/chunk-BTAEYL3P.js.map +1 -0
  22. package/dist/chunk-CDNWCYF7.js +2 -0
  23. package/dist/chunk-CDNWCYF7.js.map +1 -0
  24. package/dist/chunk-DJEZ2HVU.js +5 -0
  25. package/dist/chunk-DJEZ2HVU.js.map +1 -0
  26. package/dist/{chunk-FLOGK2U7.js → chunk-DSCMCVTV.js} +3 -3
  27. package/dist/chunk-DSCMCVTV.js.map +1 -0
  28. package/dist/chunk-EW27SCCC.js +2 -0
  29. package/dist/chunk-EW27SCCC.js.map +1 -0
  30. package/dist/chunk-HPDHNIA3.js +2 -0
  31. package/dist/chunk-IM376SD6.js +13 -0
  32. package/dist/chunk-IM376SD6.js.map +1 -0
  33. package/dist/chunk-J4WKMKTP.js +5 -0
  34. package/dist/{chunk-YI2T5QYB.js.map → chunk-J4WKMKTP.js.map} +1 -1
  35. package/dist/chunk-JGXE2YNV.js +46 -0
  36. package/dist/chunk-JGXE2YNV.js.map +1 -0
  37. package/dist/chunk-JXEPJ3YD.js +118 -0
  38. package/dist/chunk-JXEPJ3YD.js.map +1 -0
  39. package/dist/chunk-LY7JGDV7.js +6 -0
  40. package/dist/chunk-LY7JGDV7.js.map +1 -0
  41. package/dist/chunk-N67JZAXU.js +2 -0
  42. package/dist/chunk-N67JZAXU.js.map +1 -0
  43. package/dist/chunk-SR3X25TN.js +3 -0
  44. package/dist/chunk-SR3X25TN.js.map +1 -0
  45. package/dist/{chunk-7MBTMCKY.js → chunk-TRQSP67X.js} +2 -2
  46. package/dist/chunk-U364GNQX.js +719 -0
  47. package/dist/chunk-U364GNQX.js.map +1 -0
  48. package/dist/chunk-VJUTQAPJ.js +2 -0
  49. package/dist/chunk-VJUTQAPJ.js.map +1 -0
  50. package/dist/{chunk-HI24KAEY.js → chunk-WJXU5F4Z.js} +3 -4
  51. package/dist/{chunk-HI24KAEY.js.map → chunk-WJXU5F4Z.js.map} +1 -1
  52. package/dist/{chunk-QZP65I2H.js → chunk-ZE2YFX4K.js} +2 -2
  53. package/dist/cli.js +1 -320
  54. package/dist/cli.js.map +1 -1
  55. package/dist/{compaction-JBZZ7I7Y.js → compaction-S5H6DTOR.js} +6 -6
  56. package/dist/compaction-S5H6DTOR.js.map +1 -0
  57. package/dist/config-UOHEG4BW.js +2 -0
  58. package/dist/config-mutator-KSEBWKJH.js +2 -0
  59. package/dist/context-planner-2RGHJHSO.js +17 -0
  60. package/dist/context-planner-2RGHJHSO.js.map +1 -0
  61. package/dist/debug-TGAP7E7W.js +2 -0
  62. package/dist/discover-OATU7SHI.js +4 -0
  63. package/dist/discover-OATU7SHI.js.map +1 -0
  64. package/dist/editor-chat-FUBQLMAQ.js +137 -0
  65. package/dist/editor-chat-FUBQLMAQ.js.map +1 -0
  66. package/dist/heal-YP7QI7D3.js +2 -0
  67. package/dist/inbox-O5UB3YQN.js +315 -0
  68. package/dist/inbox-O5UB3YQN.js.map +1 -0
  69. package/dist/index.d.ts +3390 -1814
  70. package/dist/index.js +23 -53
  71. package/dist/index.js.map +1 -1
  72. package/dist/ingest-whatsapp-C3O5UPBX.js +6 -0
  73. package/dist/ingest-whatsapp-C3O5UPBX.js.map +1 -0
  74. package/dist/loader-BGWA7IRY.js +2 -0
  75. package/dist/loader-LBHKSXBK.js +2 -0
  76. package/dist/memory-extract-KKPKAOPH.js +2 -0
  77. package/dist/processes-7W27G3J3.js +256 -0
  78. package/dist/processes-7W27G3J3.js.map +1 -0
  79. package/dist/program-2MDELQLX.js +2 -0
  80. package/dist/providers-WCQSKTNP.js +2 -0
  81. package/dist/query-FZAL7AQD.js +2 -0
  82. package/dist/recipes-LZ56TA3X.js +2 -0
  83. package/dist/registry-ONJSILH4.js +2 -0
  84. package/dist/scheduler-XRM2RJIV.js +2 -0
  85. package/dist/slack-D27BE37Q.js +3 -0
  86. package/dist/slack-D27BE37Q.js.map +1 -0
  87. package/dist/store-4UCO56K2.js +2 -0
  88. package/dist/store-4UCO56K2.js.map +1 -0
  89. package/dist/{subagent-2SJHSSJS.js → subagent-EPOT3QDM.js} +2 -2
  90. package/dist/task-store-3NUWLYRY.js +2 -0
  91. package/dist/task-store-3NUWLYRY.js.map +1 -0
  92. package/dist/telegram-UWV67KWG.js +3 -0
  93. package/dist/telegram-UWV67KWG.js.map +1 -0
  94. package/dist/timers-QB4KYNAE.js +2 -0
  95. package/dist/timers-QB4KYNAE.js.map +1 -0
  96. package/dist/types-ECMEC5BZ.js +2 -0
  97. package/dist/types-ECMEC5BZ.js.map +1 -0
  98. package/dist/types-TTB6DJUE.js +2 -0
  99. package/dist/types-TTB6DJUE.js.map +1 -0
  100. package/dist/usage-dashboard-FQGPPABD.js +803 -0
  101. package/dist/usage-dashboard-FQGPPABD.js.map +1 -0
  102. package/dist/web/workflow-editor.global.js +1450 -0
  103. package/dist/web/workflow-editor.global.js.map +1 -0
  104. package/dist/whatsapp-KJ2NRKKQ.js +3 -0
  105. package/dist/whatsapp-KJ2NRKKQ.js.map +1 -0
  106. package/dist/{whatsapp-state-6D6FHHD2.js → whatsapp-state-3ZVQ6MQD.js} +2 -2
  107. package/dist/{wiki-UDPYFJBL.js → wiki-OUYKM7MB.js} +2 -2
  108. package/dist/wiki-OUYKM7MB.js.map +1 -0
  109. package/dist/workspace-setup-6GDBEORT.js +2 -0
  110. package/dist/workspace-setup-6GDBEORT.js.map +1 -0
  111. package/package.json +19 -2
  112. package/dist/agent-BCDPSPKU.js +0 -2
  113. package/dist/board-dashboard-LA7WW56M.js +0 -5668
  114. package/dist/board-dashboard-LA7WW56M.js.map +0 -1
  115. package/dist/chunk-6U2XOQHU.js +0 -7
  116. package/dist/chunk-6U2XOQHU.js.map +0 -1
  117. package/dist/chunk-7FJQGD6U.js +0 -6
  118. package/dist/chunk-7FJQGD6U.js.map +0 -1
  119. package/dist/chunk-ABDP7TDL.js +0 -71
  120. package/dist/chunk-ABDP7TDL.js.map +0 -1
  121. package/dist/chunk-CXY2RYNI.js +0 -11
  122. package/dist/chunk-CXY2RYNI.js.map +0 -1
  123. package/dist/chunk-FIOB3MEX.js +0 -2
  124. package/dist/chunk-FLOGK2U7.js.map +0 -1
  125. package/dist/chunk-HVC6FJNP.js +0 -108
  126. package/dist/chunk-HVC6FJNP.js.map +0 -1
  127. package/dist/chunk-K7BE4E35.js +0 -138
  128. package/dist/chunk-K7BE4E35.js.map +0 -1
  129. package/dist/chunk-KXJSLLSQ.js +0 -199
  130. package/dist/chunk-KXJSLLSQ.js.map +0 -1
  131. package/dist/chunk-KXZMYLHQ.js +0 -46
  132. package/dist/chunk-KXZMYLHQ.js.map +0 -1
  133. package/dist/chunk-M7HKBG3V.js +0 -2
  134. package/dist/chunk-M7HKBG3V.js.map +0 -1
  135. package/dist/chunk-MCJUAE6V.js +0 -6
  136. package/dist/chunk-MCJUAE6V.js.map +0 -1
  137. package/dist/chunk-RB7265LO.js +0 -12
  138. package/dist/chunk-RB7265LO.js.map +0 -1
  139. package/dist/chunk-YI2T5QYB.js +0 -5
  140. package/dist/compaction-JBZZ7I7Y.js.map +0 -1
  141. package/dist/config-LN6JEHMF.js +0 -2
  142. package/dist/config-mutator-24TH7PHM.js +0 -2
  143. package/dist/debug-3MEUO2P2.js +0 -2
  144. package/dist/heal-WKY5I4KB.js +0 -2
  145. package/dist/loader-PTCXLJEX.js +0 -2
  146. package/dist/memory-extract-AD7KMRPC.js +0 -2
  147. package/dist/providers-VUIWO3ZK.js +0 -2
  148. package/dist/query-PKGYE5HR.js +0 -2
  149. package/dist/registry-ASC2QS5K.js +0 -2
  150. package/dist/scheduler-A3TQOCKT.js +0 -2
  151. package/dist/types-OIFU3KSQ.js +0 -2
  152. package/dist/usage-dashboard-QX3CF6KK.js +0 -404
  153. package/dist/usage-dashboard-QX3CF6KK.js.map +0 -1
  154. package/dist/workspace-setup-ZWTT42XT.js +0 -2
  155. /package/dist/{agent-BCDPSPKU.js.map → agent-RDVGL2TW.js.map} +0 -0
  156. /package/dist/{chunk-FIOB3MEX.js.map → chunk-HPDHNIA3.js.map} +0 -0
  157. /package/dist/{chunk-7MBTMCKY.js.map → chunk-TRQSP67X.js.map} +0 -0
  158. /package/dist/{chunk-QZP65I2H.js.map → chunk-ZE2YFX4K.js.map} +0 -0
  159. /package/dist/{config-LN6JEHMF.js.map → config-UOHEG4BW.js.map} +0 -0
  160. /package/dist/{config-mutator-24TH7PHM.js.map → config-mutator-KSEBWKJH.js.map} +0 -0
  161. /package/dist/{debug-3MEUO2P2.js.map → debug-TGAP7E7W.js.map} +0 -0
  162. /package/dist/{heal-WKY5I4KB.js.map → heal-YP7QI7D3.js.map} +0 -0
  163. /package/dist/{loader-PTCXLJEX.js.map → loader-BGWA7IRY.js.map} +0 -0
  164. /package/dist/{memory-extract-AD7KMRPC.js.map → loader-LBHKSXBK.js.map} +0 -0
  165. /package/dist/{providers-VUIWO3ZK.js.map → memory-extract-KKPKAOPH.js.map} +0 -0
  166. /package/dist/{query-PKGYE5HR.js.map → program-2MDELQLX.js.map} +0 -0
  167. /package/dist/{registry-ASC2QS5K.js.map → providers-WCQSKTNP.js.map} +0 -0
  168. /package/dist/{scheduler-A3TQOCKT.js.map → query-FZAL7AQD.js.map} +0 -0
  169. /package/dist/{types-OIFU3KSQ.js.map → recipes-LZ56TA3X.js.map} +0 -0
  170. /package/dist/{wiki-UDPYFJBL.js.map → registry-ONJSILH4.js.map} +0 -0
  171. /package/dist/{workspace-setup-ZWTT42XT.js.map → scheduler-XRM2RJIV.js.map} +0 -0
  172. /package/dist/{subagent-2SJHSSJS.js.map → subagent-EPOT3QDM.js.map} +0 -0
  173. /package/dist/{whatsapp-state-6D6FHHD2.js.map → whatsapp-state-3ZVQ6MQD.js.map} +0 -0
@@ -1,7 +0,0 @@
1
- import{readFileSync as p,writeFileSync as k,existsSync as u,readdirSync as _,statSync as j}from"fs";import{resolve as f,join as v}from"path";var h=/^(\s*)-\s*\[( |x|X)\]\s*(.*)$/,g=/@([a-z0-9_-]+)/i,w=/\[time:\s*([0-9hm\s]+)\]/i;function U(d){let e=d.match(/(\d+)\s*h/i),s=d.match(/(\d+)\s*m/i);return(e?parseInt(e[1],10)*3600:0)+(s?parseInt(s[1],10)*60:0)}var b=class{constructor(e){this.path=e}type="backlog";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};read(){let e=f(process.cwd(),this.path);return u(e)?p(e,"utf-8").split(`
2
- `):[]}write(e){let s=f(process.cwd(),this.path);k(s,e.join(`
3
- `))}async listOpen(e){let s=this.read(),n=[];for(let t=0;t<s.length;t++){let i=s[t].match(h);if(!i||i[2].toLowerCase()==="x")continue;let r=i[3],l=r.match(g);if(l&&l[1].toLowerCase()!==e.toLowerCase())continue;let a=r.match(w),c=r.replace(g,"").replace(w,"").trim();n.push({id:`backlog:${t}`,title:c||`Task at line ${t+1}`,assignee:l?l[1]:void 0,estimatedSeconds:a?U(a[1]):void 0,priority:t})}return n}async claim(e,s){}async report(e,s){if(!e.startsWith("backlog:"))throw new Error(`not a backlog id: ${e}`);let n=parseInt(e.slice(8),10),t=this.read(),i=t[n];if(!i)throw new Error(`backlog line ${n} missing`);if(!i.match(h))throw new Error(`backlog line ${n} not a checkbox`);if(s.status==="done"){t[n]=i.replace(/- \[ \]/,"- [x]");let r=s.timeSeconds?` <!-- done by agent, ${Math.round(s.timeSeconds/60)}m -->`:" <!-- done by agent -->";t.splice(n+1,0,r)}else s.status==="blocked"?t.splice(n+1,0,` <!-- BLOCKED: ${s.blocker||s.note||"?"} -->`):s.note&&t.splice(n+1,0,` <!-- ${s.note.replace(/-->/g,"\u2014 >")} -->`);this.write(t)}},y=class{constructor(e,s){this.root=e;this.glob=s}type="wiki";capabilities={listAll:!1,create:!1,transition:!1,labels:!1,search:!1};walk(e,s){if(u(e))for(let n of _(e)){let t=v(e,n);j(t).isDirectory()?this.walk(t,s):n.endsWith(".md")&&s.push(t)}}async listOpen(e){let s=[];this.walk(f(process.cwd(),this.root),s);let n=[];for(let t of s){let i=p(t,"utf-8").split(`
4
- `);for(let o=0;o<i.length;o++){let r=i[o].match(h);if(!r||r[2].toLowerCase()==="x")continue;let l=r[3].match(g);!l||l[1].toLowerCase()!==e.toLowerCase()||n.push({id:`wiki:${t}:${o}`,title:r[3].replace(g,"").trim(),assignee:l[1],priority:o})}}return n}async claim(){}async report(e,s){let n=e.split(":"),t=parseInt(n[n.length-1],10),i=n.slice(1,-1).join(":");if(!u(i))return;let o=p(i,"utf-8").split(`
5
- `);s.status==="done"&&o[t]&&(o[t]=o[t].replace(/- \[ \]/,"- [x]"),k(i,o.join(`
6
- `)))}},$=class{constructor(e,s,n,t,i){this.host=e;this.token=s;this.projects=n;this.agentUsernames=t;this.log=i}type="gitlab";capabilities={listAll:!0,create:!0,transition:!0,labels:!0,search:!0};usernameToAgent(e){for(let[s,n]of Object.entries(this.agentUsernames))if(n.some(t=>t.toLowerCase()===e.toLowerCase()))return s}mapIssue(e,s){let n=e.references?.full?.split("#")[0]||s,t=[],i;Array.isArray(e.labels)&&(e.labels.length&&typeof e.labels[0]=="object"?(i=e.labels.map(a=>({name:a.name,color:a.color,text_color:a.text_color})),t=i.map(a=>a.name)):t=e.labels);let r=(Array.isArray(e.assignees)&&e.assignees.length?e.assignees:e.assignee?[e.assignee]:[]).map(a=>({username:a.username,name:a.name,avatarUrl:a.avatar_url})),l=r[0]?.username;return{id:`gitlab:${n}:issue:${e.iid}`,title:e.title,description:e.description||void 0,assignee:l?this.usernameToAgent(l)||l:void 0,assignees:r,url:e.web_url,priority:e.weight??99,estimatedSeconds:e.time_stats?.time_estimate||void 0,labels:t,labelDetails:i,updatedAt:e.updated_at,state:e.state==="closed"?"closed":"opened",milestone:e.milestone?.title||void 0}}async api(e,s={}){let n=await fetch(`${this.host}/api/v4${e}`,{...s,headers:{"PRIVATE-TOKEN":this.token,"Content-Type":"application/json",...s.headers||{}}});if(!n.ok)throw new Error(`GitLab ${n.status}: ${await n.text().catch(()=>"")}`);return n.json()}async listOpen(e){let s=this.agentUsernames[e]||[];if(!s.length)return[];let n=[],t=this.projects.length?this.projects:["__ALL__"];for(let i of s)for(let o of t)try{let r=`assignee_username=${encodeURIComponent(i)}&state=opened&scope=all&per_page=20`,l=o==="__ALL__"?`/issues?${r}`:`/projects/${encodeURIComponent(o)}/issues?${r}`,a=await this.api(l);for(let c of a){let m=this.mapIssue(c,o);m.assignee=e,n.push(m)}}catch(r){this.log(`[business] GitLab listOpen failed for ${i} on ${o}: ${r.message}`)}return n}async claim(e,s){let{project:n,iid:t,type:i}=this.parseId(s),o=`/projects/${encodeURIComponent(n)}/${i==="issue"?"issues":"merge_requests"}/${t}?add_labels=Doing&remove_labels=To Do`;try{await this.api(o,{method:"PUT"})}catch(r){this.log(`[business] claim label update failed: ${r.message}`)}}async report(e,s){let{project:n,iid:t,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";if(s.timeSeconds&&s.timeSeconds>0){let r=Math.max(1,Math.round(s.timeSeconds/60)),l=r>=60?`${Math.floor(r/60)}h${r%60?` ${r%60}m`:""}`:`${r}m`;try{await this.api(`/projects/${encodeURIComponent(n)}/${o}/${t}/add_spent_time?duration=${encodeURIComponent(l)}`,{method:"POST"})}catch(a){this.log(`[business] add_spent_time failed: ${a.message}`)}}if(s.status==="done")try{await this.api(`/projects/${encodeURIComponent(n)}/${o}/${t}?add_labels=Done&remove_labels=Doing`,{method:"PUT"})}catch(r){this.log(`[business] done label update failed: ${r.message}`)}else if(s.status==="blocked")try{await this.api(`/projects/${encodeURIComponent(n)}/${o}/${t}?add_labels=Blocked`,{method:"PUT"})}catch(r){this.log(`[business] blocked label update failed: ${r.message}`)}if(s.note)try{await this.api(`/projects/${encodeURIComponent(n)}/${o}/${t}/notes`,{method:"POST",body:JSON.stringify({body:s.note})})}catch(r){this.log(`[business] report note failed: ${r.message}`)}}async listAll(e={}){let s=e.sinceDays??30,n=new Date(Date.now()-s*24*36e5).toISOString(),t=new URLSearchParams,i=e.state??"opened";t.set("state",i),t.set("updated_after",n),t.set("scope","all"),t.set("per_page","100"),t.set("with_labels_details","true"),t.set("order_by","updated_at"),t.set("sort","desc"),e.labels?.length&&t.set("labels",e.labels.join(",")),e.milestone&&t.set("milestone",e.milestone),e.search&&t.set("search",e.search);let o=this.projects.length?this.projects:["__ALL__"],r=[];for(let a of o)try{let c=a==="__ALL__"?`/issues?${t.toString()}`:`/projects/${encodeURIComponent(a)}/issues?${t.toString()}`,m=await this.api(c);for(let I of m)r.push(this.mapIssue(I,a))}catch(c){this.log(`[business] GitLab listAll failed on ${a}: ${c.message}`)}let l=r;if(e.notLabels?.length){let a=new Set(e.notLabels);l=l.filter(c=>!(c.labels||[]).some(m=>a.has(m)))}if(e.withoutScopedPrefix){let a=e.withoutScopedPrefix+"::";l=l.filter(c=>!(c.labels||[]).some(m=>m.startsWith(a)))}return l}async setState(e,s){let{project:n,iid:t,type:i}=this.parseId(e),o=i==="issue"?"issues":"merge_requests";await this.api(`/projects/${encodeURIComponent(n)}/${o}/${t}?state_event=${s}`,{method:"PUT"})}async getItem(e){let{project:s,iid:n}=this.parseId(e);try{let t=await this.api(`/projects/${encodeURIComponent(s)}/issues/${n}?with_labels_details=true`);return{...this.mapIssue(t,s),descriptionHtml:t.description_html||void 0,createdAt:t.created_at,author:t.author?{username:t.author.username,name:t.author.name,avatarUrl:t.author.avatar_url}:void 0,allLabels:Array.isArray(t.labels)?typeof t.labels[0]=="object"?t.labels.map(o=>o.name):t.labels:[]}}catch(t){return this.log(`[board] GitLab getItem failed for ${e}: ${t.message}`),null}}async updateItem(e,s){let{project:n,iid:t}=this.parseId(e),i;s.assigneeUsernames&&(i=(await Promise.all(s.assigneeUsernames.map(async c=>{try{let m=await this.api(`/users?username=${encodeURIComponent(c)}`);return Array.isArray(m)&&m[0]?.id?m[0].id:null}catch{return null}}))).filter(c=>typeof c=="number"));let o;if(s.milestoneTitle!==void 0)if(s.milestoneTitle===null||s.milestoneTitle==="")o=0;else try{let a=await this.api(`/projects/${encodeURIComponent(n)}/milestones?title=${encodeURIComponent(s.milestoneTitle)}`);Array.isArray(a)&&a[0]?.id&&(o=a[0].id)}catch(a){this.log(`[board] milestone lookup failed for "${s.milestoneTitle}": ${a.message}`)}let r={};s.title!==void 0&&(r.title=s.title),s.description!==void 0&&(r.description=s.description),s.labels!==void 0&&(r.labels=s.labels.join(",")),s.addLabels?.length&&(r.add_labels=s.addLabels.join(",")),s.removeLabels?.length&&(r.remove_labels=s.removeLabels.join(",")),i!==void 0&&(r.assignee_ids=i),o!==void 0&&(r.milestone_id=o);let l=await this.api(`/projects/${encodeURIComponent(n)}/issues/${t}`,{method:"PUT",body:JSON.stringify(r)});return this.mapIssue(l,n)}async listMembers(){let e=new Map;for(let s of this.projects)try{let n=await this.api(`/projects/${encodeURIComponent(s)}/members/all?per_page=100`);for(let t of n)t.username&&!e.has(t.username)&&e.set(t.username,{username:t.username,name:t.name,avatarUrl:t.avatar_url})}catch(n){this.log(`[board] listMembers failed for ${s}: ${n.message}`)}return[...e.values()].sort((s,n)=>s.username.localeCompare(n.username))}async listMilestones(){let e=new Map;for(let n of this.projects)try{let t=await this.api(`/projects/${encodeURIComponent(n)}/milestones?per_page=100`);for(let i of t)i.title&&!e.has(i.title)&&e.set(i.title,{id:i.id,title:i.title,state:i.state,dueDate:i.due_date})}catch(t){this.log(`[board] listMilestones failed for ${n}: ${t.message}`)}let s=[...e.values()];return s.sort((n,t)=>n.state!==t.state?n.state==="active"?-1:1:n.title.localeCompare(t.title)),s}async create(e){let s=e.projectHint||this.projects[0];if(!s)throw new Error("GitLabWorkSource.create requires projectHint or configured projects");let n,t=e.assigneeUsernames?.length?e.assigneeUsernames:e.assignee?(this.agentUsernames[e.assignee]||[]).slice(0,1):[];t.length&&(n=(await Promise.all(t.map(async a=>{try{let c=await this.api(`/users?username=${encodeURIComponent(a)}`);return Array.isArray(c)&&c[0]?.id?c[0].id:null}catch(c){return this.log(`[board] user lookup failed for ${a}: ${c.message}`),null}}))).filter(a=>typeof a=="number"));let i;if(e.milestoneTitle)try{let l=await this.api(`/projects/${encodeURIComponent(s)}/milestones?title=${encodeURIComponent(e.milestoneTitle)}`);Array.isArray(l)&&l[0]?.id&&(i=l[0].id)}catch(l){this.log(`[board] milestone lookup failed for "${e.milestoneTitle}": ${l.message}`)}let o={title:e.title,description:e.description,labels:(e.labels||[]).join(",")};n?.length&&(o.assignee_ids=n),i!==void 0&&(o.milestone_id=i);let r=await this.api(`/projects/${encodeURIComponent(s)}/issues`,{method:"POST",body:JSON.stringify(o)});return this.mapIssue(r,s)}async transition(e,s,n){await this.transitionMany(e,s?[s]:[],n?[n]:[])}async transitionMany(e,s,n){let{project:t,iid:i,type:o}=this.parseId(e),r=o==="issue"?"issues":"merge_requests",l=new URLSearchParams;s.length&&l.set("add_labels",s.join(",")),n.length&&l.set("remove_labels",n.join(",")),l.toString()&&await this.api(`/projects/${encodeURIComponent(t)}/${r}/${i}?${l.toString()}`,{method:"PUT"})}parseId(e){let n=e.replace(/^gitlab:/,"").split(":"),t=n.pop(),i=n.pop()==="mr"?"mr":"issue";return{project:n.join(":"),type:i,iid:t}}};function W(d,e,s){let n=d.workSource;switch(n.type){case"backlog":return new b(n.path);case"wiki":return new y(n.path,n.glob);case"gitlab":{let t=e.channels.gitlab;if(!t?.token)throw new Error("business.workSource.type=gitlab requires channels.gitlab.token");let i={};for(let r of t.agentMappings)r.gitlabUsernames.length&&(i[r.agentId]=r.gitlabUsernames);let o=n.projects.length?n.projects:t.routes.map(r=>r.project);return new $(t.host,t.token,o,i,s)}}}export{$ as a,W as b};
7
- //# sourceMappingURL=chunk-6U2XOQHU.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/business/work-pool.ts"],"sourcesContent":["import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from \"fs\"\nimport { resolve, join } from \"path\"\nimport type { BusinessConfig, BusinessWorkSource } from \"./config\"\nimport type { DaemonConfig } from \"@/daemon/config\"\n\n// --- Work pool: pluggable source of tasks for the business layer ---\n\nexport interface WorkItem {\n id: string // stable id for claim/report (e.g. \"backlog:line-12\", \"gitlab:proj:issue:42\")\n title: string\n description?: string\n assignee?: string // agentId\n estimatedSeconds?: number\n url?: string\n priority?: number // lower = higher priority\n /** Board stage derived from labels (kanban column id). */\n stage?: \"triage\" | \"todo\" | \"doing\" | \"onhold\" | \"review\" | \"done\"\n /** Raw labels from the source (GitLab). Empty array if source doesn't support labels. */\n labels?: string[]\n /** Label name+color when the source returns colored labels (GitLab with_labels_details). */\n labelDetails?: Array<{ name: string; color: string; text_color?: string }>\n /** ISO timestamp of last update on the source. */\n updatedAt?: string\n /** Open/closed state from the source. */\n state?: \"opened\" | \"closed\"\n /** Optional milestone title (GitLab: issue.milestone.title). */\n milestone?: string\n /** GitLab assignees (0..n). `assignee` above is the agentId alias for assignees[0]. */\n assignees?: Array<{ username: string; name?: string; avatarUrl?: string }>\n}\n\n/** Member of a source (GitLab project members) — used for assignee pickers. */\nexport interface WorkMember {\n username: string\n name?: string\n avatarUrl?: string\n}\n\n/** Milestone on a source — used for milestone pickers. */\nexport interface WorkMilestone {\n id: number | string\n title: string\n state?: \"active\" | \"closed\"\n dueDate?: string\n}\n\n/** Full issue detail — a superset of WorkItem for the detail view. */\nexport interface WorkDetail extends WorkItem {\n /** Raw body, may be markdown. */\n descriptionHtml?: string\n /** ISO timestamp of creation. */\n createdAt?: string\n /** Author (issue reporter). */\n author?: { username: string; name?: string; avatarUrl?: string }\n /** Full labels list (all of them). */\n allLabels?: string[]\n}\n\nexport interface WorkReport {\n status: \"in-progress\" | \"done\" | \"blocked\"\n note?: string\n timeSeconds?: number\n blocker?: string\n}\n\n/** What a WorkSource can do beyond the minimal listOpen/claim/report triple. */\nexport interface WorkSourceCapabilities {\n /** Enumerate items beyond assignee filter — required for a board view. */\n listAll: boolean\n /** Create new items (e.g. POST GitLab issue). */\n create: boolean\n /** Arbitrary column transitions (label add/remove pair). */\n transition: boolean\n /** Surfaces labels[] on returned items. */\n labels: boolean\n /** Server-side text search. */\n search: boolean\n}\n\nexport interface WorkCreateInput {\n title: string\n description?: string\n /** agentId */\n assignee?: string\n /** Raw GitLab usernames — bypass agentId resolution for UI-driven creates. */\n assigneeUsernames?: string[]\n labels?: string[]\n /** Milestone title (resolved to id). */\n milestoneTitle?: string\n /** For sources that span multiple projects (gitlab): \"group/project\". */\n projectHint?: string\n}\n\nexport interface ListAllOpts {\n sinceDays?: number\n labels?: string[]\n /** Exclude items carrying any of these labels (client-side filter). */\n notLabels?: string[]\n /** Exclude items whose labels carry this scoped prefix (e.g. \"Status\"). */\n withoutScopedPrefix?: string\n search?: string\n assignee?: string\n /** GitLab issue state. Defaults to \"opened\" (boards hide closed issues). */\n state?: \"opened\" | \"closed\" | \"all\"\n /** Milestone filter (GitLab \"milestone\" query param). */\n milestone?: string\n}\n\nexport interface WorkSource {\n type: string\n capabilities: WorkSourceCapabilities\n listOpen(agentId: string): Promise<WorkItem[]>\n claim(agentId: string, itemId: string): Promise<void>\n report(itemId: string, update: WorkReport): Promise<void>\n /** Optional — gated by capabilities.listAll. */\n listAll?(opts: ListAllOpts): Promise<WorkItem[]>\n /** Optional — gated by capabilities.create. */\n create?(input: WorkCreateInput): Promise<WorkItem>\n /**\n * Optional — gated by capabilities.transition. Add `toLabel` and remove\n * `fromLabel` (if provided) from the item. Used by the kanban board on drag.\n */\n transition?(itemId: string, toLabel: string, fromLabel?: string): Promise<void>\n}\n\n// ---------- BacklogWorkSource: GFM checklist file ----------\n// Format in .agentx/backlog.md (or configured path):\n//\n// - [ ] @alice Implement login form [time: 2h]\n// - [x] @alice Write unit tests (done)\n// - [ ] @bob Design pricing page [time: 1h30m]\n//\n// Line number is the stable id.\n\nconst CHECK_RE = /^(\\s*)-\\s*\\[( |x|X)\\]\\s*(.*)$/\nconst MENTION_RE = /@([a-z0-9_-]+)/i\nconst TIME_RE = /\\[time:\\s*([0-9hm\\s]+)\\]/i\n\nfunction parseDuration(s: string): number {\n // \"2h30m\" -> 9000 s. \"1h\" -> 3600. \"45m\" -> 2700.\n const hMatch = s.match(/(\\d+)\\s*h/i)\n const mMatch = s.match(/(\\d+)\\s*m/i)\n return (hMatch ? parseInt(hMatch[1], 10) * 3600 : 0) + (mMatch ? parseInt(mMatch[1], 10) * 60 : 0)\n}\n\nexport class BacklogWorkSource implements WorkSource {\n type = \"backlog\"\n capabilities: WorkSourceCapabilities = {\n listAll: false, create: false, transition: false, labels: false, search: false,\n }\n constructor(private path: string) {}\n\n private read(): string[] {\n const full = resolve(process.cwd(), this.path)\n if (!existsSync(full)) return []\n return readFileSync(full, \"utf-8\").split(\"\\n\")\n }\n\n private write(lines: string[]): void {\n const full = resolve(process.cwd(), this.path)\n writeFileSync(full, lines.join(\"\\n\"))\n }\n\n async listOpen(agentId: string): Promise<WorkItem[]> {\n const lines = this.read()\n const items: WorkItem[] = []\n for (let i = 0; i < lines.length; i++) {\n const m = lines[i].match(CHECK_RE)\n if (!m) continue\n const checked = m[2].toLowerCase() === \"x\"\n if (checked) continue\n const body = m[3]\n const mention = body.match(MENTION_RE)\n if (mention && mention[1].toLowerCase() !== agentId.toLowerCase()) continue\n const timeMatch = body.match(TIME_RE)\n const title = body.replace(MENTION_RE, \"\").replace(TIME_RE, \"\").trim()\n items.push({\n id: `backlog:${i}`,\n title: title || `Task at line ${i + 1}`,\n assignee: mention ? mention[1] : undefined,\n estimatedSeconds: timeMatch ? parseDuration(timeMatch[1]) : undefined,\n priority: i,\n })\n }\n return items\n }\n\n async claim(_agentId: string, _itemId: string): Promise<void> {\n // No-op: backlog file has no \"claimed\" state distinct from \"assigned\".\n }\n\n async report(itemId: string, update: WorkReport): Promise<void> {\n if (!itemId.startsWith(\"backlog:\")) throw new Error(`not a backlog id: ${itemId}`)\n const lineNo = parseInt(itemId.slice(\"backlog:\".length), 10)\n const lines = this.read()\n const line = lines[lineNo]\n if (!line) throw new Error(`backlog line ${lineNo} missing`)\n const m = line.match(CHECK_RE)\n if (!m) throw new Error(`backlog line ${lineNo} not a checkbox`)\n\n if (update.status === \"done\") {\n lines[lineNo] = line.replace(/- \\[ \\]/, \"- [x]\")\n const note = update.timeSeconds\n ? ` <!-- done by agent, ${Math.round(update.timeSeconds / 60)}m -->`\n : \" <!-- done by agent -->\"\n lines.splice(lineNo + 1, 0, note)\n } else if (update.status === \"blocked\") {\n lines.splice(lineNo + 1, 0, ` <!-- BLOCKED: ${update.blocker || update.note || \"?\"} -->`)\n } else if (update.note) {\n lines.splice(lineNo + 1, 0, ` <!-- ${update.note.replace(/-->/g, \"— >\")} -->`)\n }\n this.write(lines)\n }\n}\n\n// ---------- WikiWorkSource: scan markdown files for @mention checkboxes ----------\n\nexport class WikiWorkSource implements WorkSource {\n type = \"wiki\"\n capabilities: WorkSourceCapabilities = {\n listAll: false, create: false, transition: false, labels: false, search: false,\n }\n constructor(private root: string, private glob: string) {}\n\n private walk(dir: string, out: string[]): void {\n if (!existsSync(dir)) return\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry)\n const st = statSync(full)\n if (st.isDirectory()) {\n this.walk(full, out)\n } else if (entry.endsWith(\".md\")) {\n out.push(full)\n }\n }\n }\n\n async listOpen(agentId: string): Promise<WorkItem[]> {\n const files: string[] = []\n this.walk(resolve(process.cwd(), this.root), files)\n const items: WorkItem[] = []\n for (const file of files) {\n const lines = readFileSync(file, \"utf-8\").split(\"\\n\")\n for (let i = 0; i < lines.length; i++) {\n const m = lines[i].match(CHECK_RE)\n if (!m || m[2].toLowerCase() === \"x\") continue\n const mention = m[3].match(MENTION_RE)\n if (!mention || mention[1].toLowerCase() !== agentId.toLowerCase()) continue\n items.push({\n id: `wiki:${file}:${i}`,\n title: m[3].replace(MENTION_RE, \"\").trim(),\n assignee: mention[1],\n priority: i,\n })\n }\n }\n return items\n }\n\n async claim(): Promise<void> { /* no-op */ }\n\n async report(itemId: string, update: WorkReport): Promise<void> {\n // wiki:<file>:<line>\n const parts = itemId.split(\":\")\n const lineNo = parseInt(parts[parts.length - 1], 10)\n const file = parts.slice(1, -1).join(\":\")\n if (!existsSync(file)) return\n const lines = readFileSync(file, \"utf-8\").split(\"\\n\")\n if (update.status === \"done\" && lines[lineNo]) {\n lines[lineNo] = lines[lineNo].replace(/- \\[ \\]/, \"- [x]\")\n writeFileSync(file, lines.join(\"\\n\"))\n }\n }\n}\n\n// ---------- GitLabWorkSource: assignee-filtered issues via GitLab API ----------\n\nexport class GitLabWorkSource implements WorkSource {\n type = \"gitlab\"\n capabilities: WorkSourceCapabilities = {\n listAll: true, create: true, transition: true, labels: true, search: true,\n }\n\n constructor(\n private host: string,\n private token: string,\n private projects: string[],\n /** Map from agentId -> GitLab username(s) */\n private agentUsernames: Record<string, string[]>,\n private log: (...args: unknown[]) => void,\n ) {}\n\n /** Reverse lookup: GitLab username -> agentId. Used when resolving board items\n * back to an agent (for the reconciler and card display). */\n private usernameToAgent(username: string): string | undefined {\n for (const [agentId, names] of Object.entries(this.agentUsernames)) {\n if (names.some((n) => n.toLowerCase() === username.toLowerCase())) return agentId\n }\n return undefined\n }\n\n private mapIssue(issue: any, project: string): WorkItem {\n const ns = issue.references?.full?.split(\"#\")[0] || project\n // `labels` may be a string[] or, with with_labels_details=true, an object[].\n let labels: string[] = []\n let labelDetails: Array<{ name: string; color: string; text_color?: string }> | undefined\n if (Array.isArray(issue.labels)) {\n if (issue.labels.length && typeof issue.labels[0] === \"object\") {\n labelDetails = issue.labels.map((l: any) => ({\n name: l.name, color: l.color, text_color: l.text_color,\n }))\n labels = labelDetails!.map((l) => l.name)\n } else {\n labels = issue.labels\n }\n }\n const rawAssignees: any[] = Array.isArray(issue.assignees) && issue.assignees.length\n ? issue.assignees\n : (issue.assignee ? [issue.assignee] : [])\n const assignees = rawAssignees.map((a) => ({\n username: a.username, name: a.name, avatarUrl: a.avatar_url,\n }))\n const firstUsername = assignees[0]?.username\n return {\n id: `gitlab:${ns}:issue:${issue.iid}`,\n title: issue.title,\n description: issue.description || undefined,\n // Prefer configured agentId mapping; fall back to the raw GitLab username\n // so cards still render an assignee even without agentMappings configured.\n assignee: firstUsername ? (this.usernameToAgent(firstUsername) || firstUsername) : undefined,\n assignees,\n url: issue.web_url,\n priority: issue.weight ?? 99,\n estimatedSeconds: issue.time_stats?.time_estimate || undefined,\n labels,\n labelDetails,\n updatedAt: issue.updated_at,\n state: issue.state === \"closed\" ? \"closed\" : \"opened\",\n milestone: issue.milestone?.title || undefined,\n }\n }\n\n private async api(path: string, init: RequestInit = {}): Promise<any> {\n const res = await fetch(`${this.host}/api/v4${path}`, {\n ...init,\n headers: {\n \"PRIVATE-TOKEN\": this.token,\n \"Content-Type\": \"application/json\",\n ...(init.headers || {}),\n },\n })\n if (!res.ok) throw new Error(`GitLab ${res.status}: ${await res.text().catch(() => \"\")}`)\n return res.json()\n }\n\n async listOpen(agentId: string): Promise<WorkItem[]> {\n const usernames = this.agentUsernames[agentId] || []\n if (!usernames.length) return []\n\n const items: WorkItem[] = []\n const projectList = this.projects.length\n ? this.projects\n : [\"__ALL__\"] // falls back to a global issues query\n\n for (const username of usernames) {\n for (const project of projectList) {\n try {\n const q = `assignee_username=${encodeURIComponent(username)}&state=opened&scope=all&per_page=20`\n const path = project === \"__ALL__\"\n ? `/issues?${q}`\n : `/projects/${encodeURIComponent(project)}/issues?${q}`\n const issues = await this.api(path)\n for (const issue of issues) {\n const item = this.mapIssue(issue, project)\n // Force assignee to the agent we queried for (listOpen is per-agent).\n item.assignee = agentId\n items.push(item)\n }\n } catch (e: any) {\n this.log(`[business] GitLab listOpen failed for ${username} on ${project}: ${e.message}`)\n }\n }\n }\n return items\n }\n\n async claim(agentId: string, itemId: string): Promise<void> {\n // itemId: \"gitlab:<project>:issue:<iid>\"\n const { project, iid, type } = this.parseId(itemId)\n // Transition labels: add \"Doing\", remove \"To Do\"\n const path = `/projects/${encodeURIComponent(project)}/${type === \"issue\" ? \"issues\" : \"merge_requests\"}/${iid}?add_labels=Doing&remove_labels=To Do`\n try {\n await this.api(path, { method: \"PUT\" })\n } catch (e: any) {\n this.log(`[business] claim label update failed: ${e.message}`)\n }\n }\n\n async report(itemId: string, update: WorkReport): Promise<void> {\n const { project, iid, type } = this.parseId(itemId)\n const seg = type === \"issue\" ? \"issues\" : \"merge_requests\"\n\n // Time tracking\n if (update.timeSeconds && update.timeSeconds > 0) {\n const mins = Math.max(1, Math.round(update.timeSeconds / 60))\n const dur = mins >= 60 ? `${Math.floor(mins / 60)}h${mins % 60 ? ` ${mins % 60}m` : \"\"}` : `${mins}m`\n try {\n await this.api(\n `/projects/${encodeURIComponent(project)}/${seg}/${iid}/add_spent_time?duration=${encodeURIComponent(dur)}`,\n { method: \"POST\" },\n )\n } catch (e: any) {\n this.log(`[business] add_spent_time failed: ${e.message}`)\n }\n }\n\n // Status → labels\n if (update.status === \"done\") {\n try {\n await this.api(\n `/projects/${encodeURIComponent(project)}/${seg}/${iid}?add_labels=Done&remove_labels=Doing`,\n { method: \"PUT\" },\n )\n } catch (e: any) {\n this.log(`[business] done label update failed: ${e.message}`)\n }\n } else if (update.status === \"blocked\") {\n try {\n await this.api(\n `/projects/${encodeURIComponent(project)}/${seg}/${iid}?add_labels=Blocked`,\n { method: \"PUT\" },\n )\n } catch (e: any) {\n this.log(`[business] blocked label update failed: ${e.message}`)\n }\n }\n\n // Note/comment\n if (update.note) {\n try {\n await this.api(\n `/projects/${encodeURIComponent(project)}/${seg}/${iid}/notes`,\n { method: \"POST\", body: JSON.stringify({ body: update.note }) },\n )\n } catch (e: any) {\n this.log(`[business] report note failed: ${e.message}`)\n }\n }\n }\n\n async listAll(opts: ListAllOpts = {}): Promise<WorkItem[]> {\n const sinceDays = opts.sinceDays ?? 30\n const updatedAfter = new Date(Date.now() - sinceDays * 24 * 3600_000).toISOString()\n\n const params = new URLSearchParams()\n const state = opts.state ?? \"opened\"\n params.set(\"state\", state)\n // `updated_after` makes sense for the Closed column (bounded window) and for\n // keeping the open list recent; for \"opened\" we pass it too but GitLab treats\n // the window loosely (any issue updated since counts, regardless of open-age).\n params.set(\"updated_after\", updatedAfter)\n params.set(\"scope\", \"all\")\n params.set(\"per_page\", \"100\")\n params.set(\"with_labels_details\", \"true\")\n params.set(\"order_by\", \"updated_at\")\n params.set(\"sort\", \"desc\")\n if (opts.labels?.length) params.set(\"labels\", opts.labels.join(\",\"))\n if (opts.milestone) params.set(\"milestone\", opts.milestone)\n if (opts.search) params.set(\"search\", opts.search)\n\n const projectList = this.projects.length ? this.projects : [\"__ALL__\"]\n const items: WorkItem[] = []\n for (const project of projectList) {\n try {\n const path = project === \"__ALL__\"\n ? `/issues?${params.toString()}`\n : `/projects/${encodeURIComponent(project)}/issues?${params.toString()}`\n const issues = await this.api(path)\n for (const issue of issues) items.push(this.mapIssue(issue, project))\n } catch (e: any) {\n this.log(`[business] GitLab listAll failed on ${project}: ${e.message}`)\n }\n }\n\n // Client-side negative-label filter (GitLab API supports `not[labels]` only\n // via the `not[]` nested query form, which isn't convenient via URLSearchParams).\n let result = items\n if (opts.notLabels?.length) {\n const deny = new Set(opts.notLabels)\n result = result.filter((i) => !(i.labels || []).some((l) => deny.has(l)))\n }\n if (opts.withoutScopedPrefix) {\n const prefix = opts.withoutScopedPrefix + \"::\"\n result = result.filter((i) => !(i.labels || []).some((l) => l.startsWith(prefix)))\n }\n return result\n }\n\n /** Close or reopen an issue via state_event. */\n async setState(itemId: string, to: \"close\" | \"reopen\"): Promise<void> {\n const { project, iid, type } = this.parseId(itemId)\n const seg = type === \"issue\" ? \"issues\" : \"merge_requests\"\n await this.api(\n `/projects/${encodeURIComponent(project)}/${seg}/${iid}?state_event=${to}`,\n { method: \"PUT\" },\n )\n }\n\n /** Fetch a single issue's full detail. */\n async getItem(itemId: string): Promise<WorkDetail | null> {\n const { project, iid } = this.parseId(itemId)\n try {\n const issue = await this.api(\n `/projects/${encodeURIComponent(project)}/issues/${iid}?with_labels_details=true`,\n )\n const base = this.mapIssue(issue, project)\n return {\n ...base,\n descriptionHtml: issue.description_html || undefined,\n createdAt: issue.created_at,\n author: issue.author ? {\n username: issue.author.username, name: issue.author.name, avatarUrl: issue.author.avatar_url,\n } : undefined,\n allLabels: Array.isArray(issue.labels)\n ? (typeof issue.labels[0] === \"object\" ? issue.labels.map((l: any) => l.name) : issue.labels)\n : [],\n }\n } catch (e: any) {\n this.log(`[board] GitLab getItem failed for ${itemId}: ${e.message}`)\n return null\n }\n }\n\n /** Update fields on an issue. Accepts string usernames for assignees. */\n async updateItem(\n itemId: string,\n patch: {\n title?: string\n description?: string\n labels?: string[]\n addLabels?: string[]\n removeLabels?: string[]\n assigneeUsernames?: string[]\n milestoneTitle?: string | null\n },\n ): Promise<WorkItem> {\n const { project, iid } = this.parseId(itemId)\n\n // Resolve assignee usernames → user ids (parallel).\n let assigneeIds: number[] | undefined\n if (patch.assigneeUsernames) {\n const results = await Promise.all(patch.assigneeUsernames.map(async (u) => {\n try {\n const users = await this.api(`/users?username=${encodeURIComponent(u)}`)\n return Array.isArray(users) && users[0]?.id ? users[0].id : null\n } catch { return null }\n }))\n assigneeIds = results.filter((x): x is number => typeof x === \"number\")\n }\n\n // Resolve milestone title → id (null clears the milestone).\n let milestoneId: number | 0 | undefined\n if (patch.milestoneTitle !== undefined) {\n if (patch.milestoneTitle === null || patch.milestoneTitle === \"\") {\n milestoneId = 0\n } else {\n try {\n const ms = await this.api(\n `/projects/${encodeURIComponent(project)}/milestones?title=${encodeURIComponent(patch.milestoneTitle)}`,\n )\n if (Array.isArray(ms) && ms[0]?.id) milestoneId = ms[0].id\n } catch (e: any) {\n this.log(`[board] milestone lookup failed for \"${patch.milestoneTitle}\": ${e.message}`)\n }\n }\n }\n\n const body: Record<string, unknown> = {}\n if (patch.title !== undefined) body.title = patch.title\n if (patch.description !== undefined) body.description = patch.description\n if (patch.labels !== undefined) body.labels = patch.labels.join(\",\")\n if (patch.addLabels?.length) body.add_labels = patch.addLabels.join(\",\")\n if (patch.removeLabels?.length) body.remove_labels = patch.removeLabels.join(\",\")\n if (assigneeIds !== undefined) body.assignee_ids = assigneeIds\n if (milestoneId !== undefined) body.milestone_id = milestoneId\n\n const issue = await this.api(`/projects/${encodeURIComponent(project)}/issues/${iid}`, {\n method: \"PUT\",\n body: JSON.stringify(body),\n })\n return this.mapIssue(issue, project)\n }\n\n /** List project members (direct + inherited). Deduped by username across projects. */\n async listMembers(): Promise<WorkMember[]> {\n const byUsername = new Map<string, WorkMember>()\n for (const project of this.projects) {\n try {\n const members = await this.api(\n `/projects/${encodeURIComponent(project)}/members/all?per_page=100`,\n )\n for (const m of members) {\n if (m.username && !byUsername.has(m.username)) {\n byUsername.set(m.username, {\n username: m.username, name: m.name, avatarUrl: m.avatar_url,\n })\n }\n }\n } catch (e: any) {\n this.log(`[board] listMembers failed for ${project}: ${e.message}`)\n }\n }\n return [...byUsername.values()].sort((a, b) => a.username.localeCompare(b.username))\n }\n\n /** List milestones (active first, then closed). Deduped by title across projects. */\n async listMilestones(): Promise<WorkMilestone[]> {\n const byTitle = new Map<string, WorkMilestone>()\n for (const project of this.projects) {\n try {\n const ms = await this.api(\n `/projects/${encodeURIComponent(project)}/milestones?per_page=100`,\n )\n for (const m of ms) {\n if (m.title && !byTitle.has(m.title)) {\n byTitle.set(m.title, {\n id: m.id, title: m.title, state: m.state, dueDate: m.due_date,\n })\n }\n }\n } catch (e: any) {\n this.log(`[board] listMilestones failed for ${project}: ${e.message}`)\n }\n }\n const all = [...byTitle.values()]\n all.sort((a, b) => {\n if (a.state !== b.state) return a.state === \"active\" ? -1 : 1\n return a.title.localeCompare(b.title)\n })\n return all\n }\n\n async create(input: WorkCreateInput): Promise<WorkItem> {\n const project = input.projectHint || this.projects[0]\n if (!project) throw new Error(\"GitLabWorkSource.create requires projectHint or configured projects\")\n\n // Resolve assignee usernames → user ids. Prefer explicit `assigneeUsernames`,\n // fall back to agentId → configured mapping for legacy callers.\n let assignee_ids: number[] | undefined\n const usernames = input.assigneeUsernames?.length\n ? input.assigneeUsernames\n : (input.assignee ? (this.agentUsernames[input.assignee] || []).slice(0, 1) : [])\n if (usernames.length) {\n const results = await Promise.all(usernames.map(async (u) => {\n try {\n const users = await this.api(`/users?username=${encodeURIComponent(u)}`)\n return Array.isArray(users) && users[0]?.id ? users[0].id : null\n } catch (e: any) {\n this.log(`[board] user lookup failed for ${u}: ${e.message}`)\n return null\n }\n }))\n assignee_ids = results.filter((x): x is number => typeof x === \"number\")\n }\n\n // Resolve milestone title → id.\n let milestone_id: number | undefined\n if (input.milestoneTitle) {\n try {\n const ms = await this.api(\n `/projects/${encodeURIComponent(project)}/milestones?title=${encodeURIComponent(input.milestoneTitle)}`,\n )\n if (Array.isArray(ms) && ms[0]?.id) milestone_id = ms[0].id\n } catch (e: any) {\n this.log(`[board] milestone lookup failed for \"${input.milestoneTitle}\": ${e.message}`)\n }\n }\n\n const body: Record<string, unknown> = {\n title: input.title,\n description: input.description,\n labels: (input.labels || []).join(\",\"),\n }\n if (assignee_ids?.length) body.assignee_ids = assignee_ids\n if (milestone_id !== undefined) body.milestone_id = milestone_id\n\n const issue = await this.api(`/projects/${encodeURIComponent(project)}/issues`, {\n method: \"POST\",\n body: JSON.stringify(body),\n })\n return this.mapIssue(issue, project)\n }\n\n async transition(itemId: string, toLabel: string, fromLabel?: string): Promise<void> {\n // Legacy single add/remove — boards use transitionMany.\n await this.transitionMany(itemId, toLabel ? [toLabel] : [], fromLabel ? [fromLabel] : [])\n }\n\n /** Multi-label transition; used by board drag-drop (scoped labels produce pairs). */\n async transitionMany(itemId: string, add: string[], remove: string[]): Promise<void> {\n const { project, iid, type } = this.parseId(itemId)\n const seg = type === \"issue\" ? \"issues\" : \"merge_requests\"\n const params = new URLSearchParams()\n if (add.length) params.set(\"add_labels\", add.join(\",\"))\n if (remove.length) params.set(\"remove_labels\", remove.join(\",\"))\n if (!params.toString()) return\n await this.api(\n `/projects/${encodeURIComponent(project)}/${seg}/${iid}?${params.toString()}`,\n { method: \"PUT\" },\n )\n }\n\n private parseId(itemId: string): { project: string; type: \"issue\" | \"mr\"; iid: string } {\n // \"gitlab:<project>:issue:<iid>\" (project may contain a slash → it's joined)\n const body = itemId.replace(/^gitlab:/, \"\")\n const parts = body.split(\":\")\n const iid = parts.pop() as string\n const type = parts.pop() === \"mr\" ? \"mr\" : \"issue\"\n const project = parts.join(\":\")\n return { project, type, iid }\n }\n}\n\n// ---------- Factory ----------\n\nexport function createWorkSource(\n business: BusinessConfig,\n daemon: DaemonConfig,\n log: (...args: unknown[]) => void,\n): WorkSource {\n const ws: BusinessWorkSource = business.workSource\n switch (ws.type) {\n case \"backlog\":\n return new BacklogWorkSource(ws.path)\n\n case \"wiki\":\n return new WikiWorkSource(ws.path, ws.glob)\n\n case \"gitlab\": {\n const gl = daemon.channels.gitlab\n if (!gl?.token) {\n throw new Error(\"business.workSource.type=gitlab requires channels.gitlab.token\")\n }\n const agentUsernames: Record<string, string[]> = {}\n for (const mapping of gl.agentMappings) {\n if (mapping.gitlabUsernames.length) {\n agentUsernames[mapping.agentId] = mapping.gitlabUsernames\n }\n }\n const projects = ws.projects.length\n ? ws.projects\n : gl.routes.map((r) => r.project)\n return new GitLabWorkSource(gl.host, gl.token, projects, agentUsernames, log)\n }\n }\n}\n"],"mappings":"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","names":["readFileSync","writeFileSync","existsSync","readdirSync","statSync","resolve","join","CHECK_RE","MENTION_RE","TIME_RE","parseDuration","s","hMatch","mMatch","BacklogWorkSource","path","full","lines","agentId","items","i","m","body","mention","timeMatch","title","_agentId","_itemId","itemId","update","lineNo","line","note","WikiWorkSource","root","glob","dir","out","entry","files","file","parts","GitLabWorkSource","host","token","projects","agentUsernames","log","username","names","n","issue","project","ns","labels","labelDetails","l","assignees","firstUsername","init","res","usernames","projectList","q","issues","item","e","iid","type","seg","mins","dur","opts","sinceDays","updatedAfter","params","state","result","deny","prefix","to","patch","assigneeIds","u","users","x","milestoneId","ms","byUsername","members","a","b","byTitle","all","input","assignee_ids","milestone_id","toLabel","fromLabel","add","remove","createWorkSource","business","daemon","ws","gl","mapping"]}
@@ -1,6 +0,0 @@
1
- import{b as g,c as w}from"./chunk-FIOB3MEX.js";import{z as n}from"zod";var v,C,L,z,T,$,m,h=g(()=>{"use strict";v=n.enum(["mon","tue","wed","thu","fri","sat","sun"]),C=n.object({days:n.array(v).default(["mon","tue","wed","thu","fri"]),start:n.string().regex(/^\d{2}:\d{2}$/),end:n.string().regex(/^\d{2}:\d{2}$/),lunch:n.object({start:n.string().regex(/^\d{2}:\d{2}$/),end:n.string().regex(/^\d{2}:\d{2}$/)}).optional()}),L=n.object({title:n.string(),responsibilities:n.array(n.string()).default([]),sopPath:n.string().optional(),kpis:n.array(n.string()).default([])}),z=n.object({role:n.string(),reportsTo:n.string().optional(),schedule:C,utilizationTarget:n.number().min(0).max(1).default(.8)}),T=n.object({channel:n.string(),chatId:n.string(),accountId:n.string().optional()}),$=n.discriminatedUnion("type",[n.object({type:n.literal("backlog"),path:n.string().default(".agentx/backlog.md")}),n.object({type:n.literal("gitlab"),projects:n.array(n.string()).default([])}),n.object({type:n.literal("wiki"),path:n.string(),glob:n.string().default("**/*.md")})]),m=n.object({enabled:n.boolean().default(!1),timezone:n.string().default("UTC"),mainChannel:T,workSource:$,roles:n.record(n.string(),L).default({}),orgChart:n.record(n.string(),z).default({}),workTickMinutes:n.number().int().min(1).max(60).default(15),idleQueueThreshold:n.number().int().min(0).default(0)})});import{z as t}from"zod";function te(o,r){let s=new Set(o.labels||[]);if(o.state==="closed"){let a=r.find(l=>l.kind==="closed");if(a)return a.id}for(let a of r)if(a.kind==="scoped-label"&&a.scopedLabel&&s.has(a.scopedLabel))return a.id;for(let a of r)if(a.kind==="label"&&a.mapsToLabel&&s.has(a.mapsToLabel))return a.id;let i=r.find(a=>a.kind==="open-backlog");if(i){let a=i.scopedPrefix+"::";return[...s].some(d=>d.startsWith(a))?null:i.id}return r[0]?.id??null}function ne(o,r){let s=[],i=[],a=!1,l=!1;return r.kind==="scoped-label"&&r.scopedLabel?s.push(r.scopedLabel):r.kind==="label"&&r.mapsToLabel?s.push(r.mapsToLabel):r.kind==="closed"&&(a=!0),o&&(o.kind==="scoped-label"&&o.scopedLabel?i.push(o.scopedLabel):o.kind==="label"&&o.mapsToLabel?i.push(o.mapsToLabel):o.kind==="closed"&&r.kind!=="closed"&&(l=!0)),{addLabels:s.length?s:void 0,removeLabels:i.length?i:void 0,closeIssue:a||void 0,reopen:l||void 0}}var B,D,A,I,P,E,y,O,k,x=g(()=>{"use strict";B=t.object({name:t.string(),color:t.string().regex(/^#[0-9a-f]{6}$/i).default("#6366f1"),description:t.string().optional()}),D=t.object({id:t.string().regex(/^[a-z0-9_-]+$/,"column id must be lowercase slug"),title:t.string(),kind:t.enum(["open-backlog","scoped-label","closed","label"]).default("label"),mapsToLabel:t.string().optional(),scopedLabel:t.string().optional(),scopedPrefix:t.string().default("Status"),accent:t.string().optional()}),A=t.object({enabled:t.boolean().default(!0),staleDoingMinutes:t.number().int().min(1).default(45),respectLunchBreak:t.boolean().default(!0),respectSchedule:t.boolean().default(!0),action:t.enum(["badge","notify"]).default("badge")}),I=t.discriminatedUnion("type",[t.object({type:t.literal("gitlab"),projects:t.array(t.string()).min(1)})]),P=[{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"}],E=t.object({id:t.string().regex(/^[a-z0-9_-]+$/,"board id must be lowercase slug"),name:t.string(),source:I,primaryToolLabel:t.string().optional(),labels:t.array(B).default([]),columns:t.array(D).min(1).default(P),timeRangeDays:t.number().int().min(1).max(365).default(30),closedWindowDays:t.number().int().min(1).max(365).default(30),reconciliation:A.default({})}),y=t.array(E).default([]),O=t.object({name:t.string(),url:t.string(),dashboardUrl:t.string().optional(),token:t.string().optional(),dashboardToken:t.string().optional()}),k=t.object({enabled:t.boolean().default(!1),port:t.number().int().default(4202),bind:t.string().default("127.0.0.1"),token:t.string().optional(),daemonUrl:t.string().default("http://localhost:18800"),daemons:t.array(O).default([]),draftAgent:t.string().optional()}).default({})});var G={};w(G,{daemonConfigSchema:()=>j,expandEnvVars:()=>p,loadDaemonConfig:()=>Q,validateWorkspaces:()=>V});import{z as e}from"zod";import{readFileSync as S,existsSync as u}from"fs";import{resolve as f}from"path";function R(o){let r=f(o,".env");if(!u(r))return;let s=S(r,"utf-8");for(let i of s.split(`
2
- `)){let a=i.trim();if(!a||a.startsWith("#"))continue;let l=a.indexOf("=");if(l===-1)continue;let d=a.slice(0,l).trim(),c=a.slice(l+1).trim();process.env[d]||(process.env[d]=c)}}function p(o){if(typeof o=="string")return o.replace(/\$\{(\w+)\}/g,(r,s)=>process.env[s]||"");if(Array.isArray(o))return o.map(p);if(o!==null&&typeof o=="object"){let r={};for(let[s,i]of Object.entries(o))r[s]=p(i);return r}return o}function Q(o){let r=o?[o]:[f(process.cwd(),"agentx.json"),f(process.cwd(),".agentx/config.json")];R(process.cwd());let s,i;for(let c of r)if(u(c)){s=S(c,"utf-8"),i=c;break}if(!s||!i)throw new Error(`No config found. Create agentx.json or .agentx/config.json
3
- Searched: ${r.join(", ")}`);let a;try{a=JSON.parse(s)}catch(c){throw new Error(`Invalid JSON in ${i}: ${c.message}`)}let l=p(a),d=j.safeParse(l);if(!d.success){let c=d.error.issues.map(b=>` ${b.path.join(".")}: ${b.message}`).join(`
4
- `);throw new Error(`Config validation failed (${i}):
5
- ${c}`)}return d.data}function V(o){let r=[];for(let[s,i]of Object.entries(o.agents)){if(!u(i.workspace)){r.push(`Agent "${s}": workspace not found at ${i.workspace}`);continue}if(i.tier==="claude-code"){let d=f(i.workspace,".claude");u(d)||r.push(`Agent "${s}": no .claude/ directory in workspace ${i.workspace}. Claude Code native features (hooks, MCP, skills) won't be available.`)}let a=i.provider||"claude",l=o.providers[a];i.tier!=="claude-code"&&(!l||!l.apiKey)&&r.push(`Agent "${s}": provider "${a}" has no API key configured. Set providers.${a}.apiKey in config or use tier "claude-code" for subscription.`)}for(let[s,i]of Object.entries(o.crons))o.agents[i.agent]||r.push(`Cron "${s}": references unknown agent "${i.agent}"`);if(o.channels.telegram.enabled)for(let[s,i]of Object.entries(o.channels.telegram.accounts))o.agents[i.agentBinding]||r.push(`Telegram account "${s}": references unknown agent "${i.agentBinding}"`);return r}var M,U,W,F,J,N,_,q,K,H,j,X=g(()=>{h();x();M=e.object({apiKey:e.string().optional(),defaultModel:e.string().optional(),baseUrl:e.string().optional()}),U=e.object({name:e.string(),workspace:e.string(),tier:e.enum(["claude-code","sdk","orchestrator"]).default("claude-code"),provider:e.string().optional(),model:e.string().optional(),systemPrompt:e.string().optional(),mentions:e.array(e.string()).default([]),maxConcurrent:e.number().default(1),maxExecutionMinutes:e.number().int().min(1).max(240).default(20),permissionMode:e.string().default("default"),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")}),W=e.object({token:e.string(),agentBinding:e.string(),allowFrom:e.array(e.string()).optional()}),F=e.object({telegram:e.object({enabled:e.boolean().default(!1),accounts:e.record(e.string(),W).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([])}).default({}),discord:e.object({enabled:e.boolean().default(!1),token:e.string().optional(),agentBinding:e.string().optional()}).default({}),slack:e.object({enabled:e.boolean().default(!1),botToken:e.string().optional(),appToken:e.string().optional(),agentBinding:e.string().optional()}).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(),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([])}).default({})}),J=e.object({enabled:e.boolean().default(!0),schedule:e.string(),timezone:e.string().default("UTC"),agent:e.string(),prompt:e.string(),timeout:e.number().default(600),model:e.string().optional(),maxOutputTokens:e.number().int().min(50).max(8e3).optional(),onError:e.union([e.enum(["log","notify","disable"]),e.array(e.enum(["log","notify","disable"]))]).default("log").transform(o=>Array.isArray(o)?o:[o]),notify:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional()}),N=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()}),_=e.object({url:e.string(),name:e.string(),token:e.string().optional()}),q=e.object({enabled:e.boolean().default(!1),peers:e.array(_).default([]),discovery:e.enum(["static","mdns"]).default("static"),healthCheck:e.object({interval:e.number().default(60),timeout:e.number().default(10)}).default({})}),K=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),retrievalWeights:e.object({graph:e.number().min(0).default(.6),bm25:e.number().min(0).default(.4)}).default({})}).default({}),H=e.object({longTaskThreshold:e.number().default(30),destination:e.object({channel:e.string(),chatId:e.string(),accountId:e.string().optional()}).optional(),on:e.object({taskComplete:e.boolean().default(!0),taskError:e.boolean().default(!0),taskQueued:e.boolean().default(!1)}).default({})}).default({}),j=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(),M).default({}),agents:e.record(e.string(),U).default({}),channels:F.default({}),crons:e.record(e.string(),J).default({}),services:e.record(e.string(),N).default({}),notifications:H,mesh:q.default({}),business:m.optional(),boards:y,dashboard:k,graph:K,webhooks:e.array(e.object({id:e.string().regex(/^[a-z0-9][a-z0-9_-]*$/,"webhook id must be lowercase slug"),source:e.enum(["gitlab","github","sentry","stripe","discord","slack","custom"]),agentId:e.string(),secretEnv:e.string().optional(),description:e.string().optional(),enabled:e.boolean().default(!0)})).default([]),session:e.object({staleMinutes:e.number().int().min(1).max(1440).default(120)}).default({})})});export{te as a,ne as b,x as c,j as d,p as e,Q as f,V as g,G as h,X as i};
6
- //# sourceMappingURL=chunk-7FJQGD6U.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/business/config.ts","../src/boards/config.ts","../src/daemon/config.ts"],"sourcesContent":["import { z } from \"zod\"\n\n// --- Business layer configuration schema ---\n// Optional top-level `business` key in agentx.json.\n// When enabled, AgentX simulates a team with roles, schedules, and a work pool.\n\nconst dayEnum = z.enum([\"mon\", \"tue\", \"wed\", \"thu\", \"fri\", \"sat\", \"sun\"])\n\nconst scheduleSchema = z.object({\n days: z.array(dayEnum).default([\"mon\", \"tue\", \"wed\", \"thu\", \"fri\"]),\n start: z.string().regex(/^\\d{2}:\\d{2}$/), // \"09:00\"\n end: z.string().regex(/^\\d{2}:\\d{2}$/), // \"17:00\"\n lunch: z.object({\n start: z.string().regex(/^\\d{2}:\\d{2}$/),\n end: z.string().regex(/^\\d{2}:\\d{2}$/),\n }).optional(),\n})\n\nconst roleSchema = z.object({\n title: z.string(),\n responsibilities: z.array(z.string()).default([]),\n sopPath: z.string().optional(),\n kpis: z.array(z.string()).default([]),\n})\n\nconst orgEntrySchema = z.object({\n role: z.string(),\n reportsTo: z.string().optional(),\n schedule: scheduleSchema,\n utilizationTarget: z.number().min(0).max(1).default(0.8),\n})\n\nconst channelRefSchema = z.object({\n channel: z.string(),\n chatId: z.string(),\n accountId: z.string().optional(),\n})\n\nconst workSourceSchema = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"backlog\"),\n path: z.string().default(\".agentx/backlog.md\"),\n }),\n z.object({\n type: z.literal(\"gitlab\"),\n projects: z.array(z.string()).default([]), // empty = all configured gitlab projects\n }),\n z.object({\n type: z.literal(\"wiki\"),\n path: z.string(),\n glob: z.string().default(\"**/*.md\"),\n }),\n])\n\nexport const businessConfigSchema = z.object({\n enabled: z.boolean().default(false),\n timezone: z.string().default(\"UTC\"),\n mainChannel: channelRefSchema,\n workSource: workSourceSchema,\n roles: z.record(z.string(), roleSchema).default({}),\n orgChart: z.record(z.string(), orgEntrySchema).default({}),\n /** Work-tick cadence in minutes during business hours. Default 15. */\n workTickMinutes: z.number().int().min(1).max(60).default(15),\n /** Max queue depth for an idle agent before skipping the work tick (avoids piling up). */\n idleQueueThreshold: z.number().int().min(0).default(0),\n})\n\nexport type BusinessConfig = z.infer<typeof businessConfigSchema>\nexport type BusinessRole = z.infer<typeof roleSchema>\nexport type BusinessOrgEntry = z.infer<typeof orgEntrySchema>\nexport type BusinessSchedule = z.infer<typeof scheduleSchema>\nexport type BusinessWorkSource = z.infer<typeof workSourceSchema>\nexport type BusinessChannelRef = z.infer<typeof channelRefSchema>\n","import { z } from \"zod\"\n\n// --- Kanban board configuration ---\n//\n// Top-level optional keys in agentx.json, independent of the business layer:\n//\n// boards: array of kanban boards, each backed by a WorkSource\n// dashboard: HTTP server controlling whether the board UI serves\n//\n// Both default to empty / disabled so existing installs see no change.\n\nexport const boardLabelSchema = z.object({\n /** Label name — used verbatim as the GitLab label string. */\n name: z.string(),\n color: z.string().regex(/^#[0-9a-f]{6}$/i).default(\"#6366f1\"),\n description: z.string().optional(),\n})\n\n/**\n * A board column. `kind` controls what issues land here and how drag-to-this-column\n * mutates the issue:\n *\n * - \"open-backlog\": opened issues that have NO scoped label matching `scopedPrefix`\n * (default \"Status\"). Dragging INTO this column removes any existing scoped label.\n * - \"scoped-label\": opened issues carrying `scopedLabel` (e.g. \"Status::Doing\").\n * Scoped labels are mutually exclusive by prefix, so adding the new one lets\n * GitLab auto-remove the old one (Premium), but we still explicitly strip the\n * previous column's label for compatibility.\n * - \"closed\": all closed issues. Dragging here closes the issue; dragging away\n * reopens it.\n * - \"label\" (default, legacy): opened issues with `mapsToLabel`; flat add/remove.\n */\nexport const boardColumnSchema = z.object({\n id: z.string().regex(/^[a-z0-9_-]+$/, \"column id must be lowercase slug\"),\n title: z.string(),\n kind: z.enum([\"open-backlog\", \"scoped-label\", \"closed\", \"label\"]).default(\"label\"),\n /** For kind=\"label\": label written on entry, removed on exit. */\n mapsToLabel: z.string().optional(),\n /** For kind=\"scoped-label\": the full scoped label (e.g. \"Status::Doing\"). */\n scopedLabel: z.string().optional(),\n /** For kind=\"open-backlog\": scoped prefix that marks \"claimed\" cards to exclude. */\n scopedPrefix: z.string().default(\"Status\"),\n /** CSS color or hex — shown as the column's top accent bar. */\n accent: z.string().optional(),\n})\nexport type BoardColumnId = string\n\nexport const boardReconcileSchema = z.object({\n enabled: z.boolean().default(true),\n staleDoingMinutes: z.number().int().min(1).default(45),\n respectLunchBreak: z.boolean().default(true),\n respectSchedule: z.boolean().default(true),\n /** Badge only for P1/P3; auto-notify + auto-demote deferred. */\n action: z.enum([\"badge\", \"notify\"]).default(\"badge\"),\n})\n\nexport const boardSourceSchema = z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"gitlab\"),\n /** GitLab project paths (e.g. \"mtgl/mtgl-system-v2\"). At least one required. */\n projects: z.array(z.string()).min(1),\n }),\n // future: backlog, wiki\n])\n\n/**\n * GitLab-style default board — six columns:\n * Open (backlog) → To Do → Doing → On Hold → Review → Closed\n *\n * Drives the `Status::*` scoped label taxonomy. Moving a card adds/removes the\n * column's scoped label; moving INTO Closed closes the issue; moving OUT of\n * Closed reopens it; moving INTO Open strips any Status::* label.\n */\nexport const DEFAULT_COLUMNS: Array<z.infer<typeof boardColumnSchema>> = [\n { id: \"open\", title: \"Open\", kind: \"open-backlog\", scopedPrefix: \"Status\", accent: \"#6b7280\" },\n { id: \"todo\", title: \"To Do\", kind: \"scoped-label\", scopedLabel: \"Status::To Do\", scopedPrefix: \"Status\", accent: \"#fb7a35\" },\n { id: \"doing\", title: \"Doing\", kind: \"scoped-label\", scopedLabel: \"Status::Doing\", scopedPrefix: \"Status\", accent: \"#22c55e\" },\n { id: \"onhold\", title: \"On Hold\", kind: \"scoped-label\", scopedLabel: \"Status::On Hold\", scopedPrefix: \"Status\", accent: \"#f59e0b\" },\n { id: \"review\", title: \"Review\", kind: \"scoped-label\", scopedLabel: \"Status::Review\", scopedPrefix: \"Status\", accent: \"#3b82f6\" },\n { id: \"closed\", title: \"Closed\", kind: \"closed\", scopedPrefix: \"Status\", accent: \"#6b7280\" },\n]\n\nexport const boardSchema = z.object({\n id: z.string().regex(/^[a-z0-9_-]+$/, \"board id must be lowercase slug\"),\n name: z.string(),\n source: boardSourceSchema,\n /** If set, ANDed into every listAll query and shown as a baseline chip in the UI. */\n primaryToolLabel: z.string().optional(),\n labels: z.array(boardLabelSchema).default([]),\n columns: z.array(boardColumnSchema).min(1).default(DEFAULT_COLUMNS),\n timeRangeDays: z.number().int().min(1).max(365).default(30),\n /** Maximum closed-issue window (days) shown in the Closed column. */\n closedWindowDays: z.number().int().min(1).max(365).default(30),\n reconciliation: boardReconcileSchema.default({}),\n})\n\nexport const boardsConfigSchema = z.array(boardSchema).default([])\n\nexport const dashboardDaemonSchema = z.object({\n name: z.string(),\n /** Daemon HTTP URL (the one serving /agents, /health, /task). */\n url: z.string(),\n /** Optional board-dashboard URL if we want to proxy admin writes to this\n * peer. Defaults to `url` with port :18800/:19900 rewritten to :4202,\n * matching our convention that the dashboard runs alongside the daemon. */\n dashboardUrl: z.string().optional(),\n /** Bearer for the daemon's HTTP API (live snapshot, task stream). */\n token: z.string().optional(),\n /** Bearer for the peer's dashboard when proxying admin calls. Defaults to\n * `token` when unset. */\n dashboardToken: z.string().optional(),\n})\n\nexport const dashboardConfigSchema = z.object({\n enabled: z.boolean().default(false),\n port: z.number().int().default(4202),\n bind: z.string().default(\"127.0.0.1\"),\n /** Opt-in bearer token for writes. If unset, writes are unauthenticated. */\n token: z.string().optional(),\n /** Primary daemon the dashboard talks to for live view + A2A. */\n daemonUrl: z.string().default(\"http://localhost:18800\"),\n /** Additional daemons to poll (beyond peers discovered via primary's /mesh). */\n daemons: z.array(dashboardDaemonSchema).default([]),\n /** Default agent used for AI-assisted drafting in the create-issue flow. */\n draftAgent: z.string().optional(),\n}).default({})\n\nexport type BoardConfig = z.infer<typeof boardSchema>\nexport type BoardLabel = z.infer<typeof boardLabelSchema>\nexport type BoardColumn = z.infer<typeof boardColumnSchema>\nexport type BoardSource = z.infer<typeof boardSourceSchema>\nexport type BoardReconcile = z.infer<typeof boardReconcileSchema>\nexport type DashboardConfig = z.infer<typeof dashboardConfigSchema>\n\n/**\n * Decide which column an item lives in. Walks columns in order; the first\n * matching column wins. Items with `state: \"closed\"` always land in the\n * first `kind: \"closed\"` column; otherwise the first `scoped-label` whose\n * `scopedLabel` is present wins; otherwise the first `label` column whose\n * `mapsToLabel` is present; otherwise the first `open-backlog` column.\n *\n * Returns `null` when the item carries a scoped label matching an\n * `open-backlog` column's `scopedPrefix` but no `scoped-label` column claims\n * it — those are off-board workflow states (e.g. `Status::Done` when no\n * Done column exists) and must not leak into the backlog.\n */\nexport function deriveStage(\n item: { state?: \"opened\" | \"closed\"; labels?: string[] },\n columns: BoardColumn[],\n): BoardColumnId | null {\n const set = new Set(item.labels || [])\n if (item.state === \"closed\") {\n const closed = columns.find((c) => c.kind === \"closed\")\n if (closed) return closed.id\n }\n for (const c of columns) {\n if (c.kind === \"scoped-label\" && c.scopedLabel && set.has(c.scopedLabel)) return c.id\n }\n for (const c of columns) {\n if (c.kind === \"label\" && c.mapsToLabel && set.has(c.mapsToLabel)) return c.id\n }\n const backlog = columns.find((c) => c.kind === \"open-backlog\")\n if (backlog) {\n // If the item has any scoped-prefix label, it's not an open-backlog candidate.\n const prefix = backlog.scopedPrefix + \"::\"\n const hasScoped = [...set].some((l) => l.startsWith(prefix))\n return hasScoped ? null : backlog.id\n }\n return columns[0]?.id ?? null\n}\n\n/**\n * Describes how to mutate an issue to move it between two columns.\n * `closeIssue` / `reopen` take precedence over label mutations on the same action.\n */\nexport interface ColumnTransition {\n addLabels?: string[]\n removeLabels?: string[]\n closeIssue?: boolean\n reopen?: boolean\n}\n\nexport function transitionDiff(\n fromColumn: BoardColumn | undefined,\n toColumn: BoardColumn,\n): ColumnTransition {\n const add: string[] = []\n const remove: string[] = []\n let closeIssue = false\n let reopen = false\n\n // Handle target column.\n if (toColumn.kind === \"scoped-label\" && toColumn.scopedLabel) {\n add.push(toColumn.scopedLabel)\n } else if (toColumn.kind === \"label\" && toColumn.mapsToLabel) {\n add.push(toColumn.mapsToLabel)\n } else if (toColumn.kind === \"closed\") {\n closeIssue = true\n }\n\n // Handle source column — strip its label; if it was \"closed\", reopen.\n if (fromColumn) {\n if (fromColumn.kind === \"scoped-label\" && fromColumn.scopedLabel) {\n remove.push(fromColumn.scopedLabel)\n } else if (fromColumn.kind === \"label\" && fromColumn.mapsToLabel) {\n remove.push(fromColumn.mapsToLabel)\n } else if (fromColumn.kind === \"closed\" && toColumn.kind !== \"closed\") {\n reopen = true\n }\n }\n\n return {\n addLabels: add.length ? add : undefined,\n removeLabels: remove.length ? remove : undefined,\n closeIssue: closeIssue || undefined,\n reopen: reopen || undefined,\n }\n}\n","import { z } from \"zod\"\nimport { readFileSync, existsSync } from \"fs\"\nimport { resolve } from \"path\"\nimport { businessConfigSchema } from \"@/business/config\"\nimport { boardsConfigSchema, dashboardConfigSchema } from \"@/boards/config\"\n\n/**\n * Load .env file into process.env (simple, no dependency).\n */\nfunction loadDotEnv(dir: string): void {\n const envPath = resolve(dir, \".env\")\n if (!existsSync(envPath)) return\n\n const content = readFileSync(envPath, \"utf-8\")\n for (const line of content.split(\"\\n\")) {\n const trimmed = line.trim()\n if (!trimmed || trimmed.startsWith(\"#\")) continue\n const eqIdx = trimmed.indexOf(\"=\")\n if (eqIdx === -1) continue\n const key = trimmed.slice(0, eqIdx).trim()\n const value = trimmed.slice(eqIdx + 1).trim()\n if (!process.env[key]) {\n process.env[key] = value\n }\n }\n}\n\n// --- Daemon configuration schema & loader ---\n\nconst providerConfigSchema = z.object({\n apiKey: z.string().optional(),\n defaultModel: z.string().optional(),\n baseUrl: z.string().optional(),\n})\n\nconst agentConfigSchema = z.object({\n name: z.string(),\n workspace: z.string(),\n tier: z.enum([\"claude-code\", \"sdk\", \"orchestrator\"]).default(\"claude-code\"),\n provider: z.string().optional(),\n model: z.string().optional(),\n systemPrompt: z.string().optional(),\n mentions: z.array(z.string()).default([]),\n maxConcurrent: z.number().default(1),\n /** Hard wall-clock cap on a single Claude Code invocation. Exceeding the\n * cap sends SIGTERM (exit 143). Default 20 min — bump for devops/coder\n * agents that do long investigations or multi-file refactors. */\n maxExecutionMinutes: z.number().int().min(1).max(240).default(20),\n permissionMode: z.string().default(\"default\"),\n queueMode: z.enum([\"collect\", \"followup\", \"drop\"]).default(\"collect\"),\n heartbeat: z.object({\n enabled: z.boolean().default(false),\n intervalMinutes: z.number().default(30),\n prompt: z.string().default(\"Check inbox, pending tasks, and system health. Report anything that needs attention.\"),\n channel: z.string().default(\"heartbeat\"),\n }).default({}),\n /** Reachability via the external public API.\n * - \"private\" (default): this agent is daemon-internal + channel-bound only.\n * - \"public\": external apps can POST /api/public/agents/<id>/messages\n * with a scoped token (agent:<id> or agent:*). */\n access: z.enum([\"private\", \"public\"]).default(\"private\"),\n})\n\nconst telegramAccountSchema = z.object({\n token: z.string(),\n agentBinding: z.string(),\n /** Per-account sender allowlist. When set, OVERRIDES the global\n * `policy.allowFrom`. Entries accept:\n * - numeric user id (\"1816212449\") — matches sender (from.id)\n * - numeric chat id (\"-1003861455814\") — matches chat (chat.id)\n * - \"@username\" — matches sender username\n * A message is dispatched iff at least one entry matches. */\n allowFrom: z.array(z.string()).optional(),\n})\n\nconst channelsConfigSchema = z.object({\n telegram: z.object({\n enabled: z.boolean().default(false),\n accounts: z.record(z.string(), telegramAccountSchema).default({}),\n policy: z.object({\n dm: z.enum([\"pair\", \"block\"]).default(\"pair\"),\n group: z.enum([\"mention-required\", \"all\"]).default(\"mention-required\"),\n /** Global sender allowlist applied to every account that doesn't set\n * its own `allowFrom`. When neither is configured, every incoming\n * message is dropped — closed by default. Same entry forms as the\n * per-account list (user id, chat id, @username). */\n allowFrom: z.array(z.string()).optional(),\n }).default({}),\n }).default({}),\n whatsapp: z.object({\n enabled: z.boolean().default(false),\n sessionDir: z.string().default(\".agentx/whatsapp-sessions\"),\n defaultAgent: z.string().optional(),\n allowFrom: z.array(z.string()).optional(),\n routes: z.array(z.object({\n contact: z.string().optional(),\n group: z.string().optional(),\n agent: z.string(),\n })).default([]),\n }).default({}),\n discord: z.object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n agentBinding: z.string().optional(),\n }).default({}),\n slack: z.object({\n enabled: z.boolean().default(false),\n /** xoxb-... — bot user OAuth token from the Slack app's \"OAuth & Permissions\" tab. */\n botToken: z.string().optional(),\n /** xapp-... — app-level token with connections:write scope (for Socket Mode). */\n appToken: z.string().optional(),\n agentBinding: z.string().optional(),\n }).default({}),\n gitlab: z.object({\n enabled: z.boolean().default(false),\n webhookPort: z.number().default(18810),\n webhookSecret: z.string().optional(),\n host: z.string().default(\"https://gitlab.com\"),\n token: z.string().optional(),\n routes: z.array(z.object({\n project: z.string(),\n agent: z.string(),\n })).default([]),\n agentMappings: z.array(z.object({\n agentId: z.string(),\n gitlabUsernames: z.array(z.string()).default([]),\n keywords: z.array(z.string()).default([]),\n token: z.string().optional(),\n /** If set, the agent lives on a remote mesh peer (node id). Forces the\n * username→agent map to resolve to this mapping even when a local\n * agent's token resolves to the same GitLab user — prevents collisions\n * like two agents both claiming @devops-noqta. */\n node: z.string().optional(),\n })).default([]),\n }).default({}),\n})\n\nconst cronJobSchema = z.object({\n enabled: z.boolean().default(true),\n schedule: z.string(),\n timezone: z.string().default(\"UTC\"),\n agent: z.string(),\n prompt: z.string(),\n timeout: z.number().default(600),\n model: z.string().optional(),\n /** Soft cap on output length. Claude Code CLI has no hard flag for this,\n * but appending an instruction to the prompt is reliably honored. Use\n * 1500 for briefs, 500 for status pings, 300 for pure classifiers. */\n maxOutputTokens: z.number().int().min(50).max(8000).optional(),\n onError: z.union([\n z.enum([\"log\", \"notify\", \"disable\"]),\n z.array(z.enum([\"log\", \"notify\", \"disable\"])),\n ]).default(\"log\").transform(v => Array.isArray(v) ? v : [v]),\n notify: z.object({\n channel: z.string(),\n chatId: z.string(),\n accountId: z.string().optional(),\n }).optional(),\n})\n\nconst serviceSchema = z.object({\n name: z.string(),\n triggers: z.array(z.object({\n pattern: z.string(),\n channel: z.string().optional(),\n })),\n allowedContacts: z.array(z.string()).optional(),\n agent: z.string(),\n prompt: z.string(),\n schedule: z.string().optional(),\n timezone: z.string().default(\"UTC\"),\n notify: z.object({\n channel: z.string(),\n chatId: z.string(),\n accountId: z.string().optional(),\n }).optional(),\n})\n\nconst meshPeerSchema = z.object({\n url: z.string(),\n name: z.string(),\n token: z.string().optional(),\n})\n\nconst meshConfigSchema = z.object({\n enabled: z.boolean().default(false),\n peers: z.array(meshPeerSchema).default([]),\n discovery: z.enum([\"static\", \"mdns\"]).default(\"static\"),\n healthCheck: z.object({\n interval: z.number().default(60),\n timeout: z.number().default(10),\n }).default({}),\n})\n\n/** Intent Knowledge Graph — fixed-axis, LLM-proposed taxonomy used by the\n * Intent layer in context.ts and (eventually) wiki retrieval. Off by default\n * so existing installs see no change. */\nconst graphConfigSchema = z.object({\n enabled: z.boolean().default(false),\n /** Where the schema/nodes/classifications live. Relative to cwd. */\n baseDir: z.string().default(\".agentx/graph\"),\n /** Which agent makes LLM classification proposals. Falls back to\n * `dashboard.draftAgent` at call sites if unset. */\n draftAgent: z.string().optional(),\n /** Agent used by `agentx graph review` to triage pending classifications.\n * Should be an agent with the wiki skill so it can call `wiki query` for\n * context before deciding approve/reject. Falls back to draftAgent. */\n reviewAgent: z.string().optional(),\n /** Structural auto-approval policy. Evaluated against each classification\n * independently of `autoApproveConfidence`; either triggers approval.\n * - \"strict\" : never approve via structure — every classification\n * waits for human review\n * - \"extend-leaves\" : auto-approve when the proposed path (a) reuses only\n * existing nodes, or (b) adds exactly one NEW node at\n * the deepest level. Structural changes (new mid-path\n * node, new root) still queue for review. Default.\n * - \"any\" : auto-approve every classification regardless of\n * structural change\n */\n autoApproveStructure: z.enum([\"strict\", \"extend-leaves\", \"any\"]).default(\"extend-leaves\"),\n /** Minimum classifier confidence (0..1) to auto-approve. OR'd with the\n * structural policy — either hitting the threshold lets the classification\n * bypass the pending queue. 1.0 (default) disables this knob, so approval\n * is driven by `autoApproveStructure` alone. Lower it to e.g. 0.7 if you\n * also want high-confidence structural changes auto-approved. */\n autoApproveConfidence: z.number().min(0).max(1).default(1.0),\n /** Weights for the wiki hybrid retrieval score. Path-ancestry match vs\n * BM25 over article text. Sum need not be 1. */\n retrievalWeights: z.object({\n graph: z.number().min(0).default(0.6),\n bm25: z.number().min(0).default(0.4),\n }).default({}),\n}).default({})\n\nconst notificationsSchema = z.object({\n /** Send notification when task takes longer than this (seconds). 0 = disabled. */\n longTaskThreshold: z.number().default(30),\n /** Where to send notifications */\n destination: z.object({\n channel: z.string(),\n chatId: z.string(),\n accountId: z.string().optional(),\n }).optional(),\n /** Notify on these events */\n on: z.object({\n taskComplete: z.boolean().default(true),\n taskError: z.boolean().default(true),\n taskQueued: z.boolean().default(false),\n }).default({}),\n}).default({})\n\nexport const daemonConfigSchema = z.object({\n node: z.object({\n id: z.string(),\n name: z.string(),\n bind: z.string().default(\"127.0.0.1:18800\"),\n /** Default agent for voice/API calls that don't specify one (e.g. Siri) */\n defaultAgent: z.string().optional(),\n }),\n providers: z.record(z.string(), providerConfigSchema).default({}),\n agents: z.record(z.string(), agentConfigSchema).default({}),\n channels: channelsConfigSchema.default({}),\n crons: z.record(z.string(), cronJobSchema).default({}),\n services: z.record(z.string(), serviceSchema).default({}),\n notifications: notificationsSchema,\n mesh: meshConfigSchema.default({}),\n business: businessConfigSchema.optional(),\n boards: boardsConfigSchema,\n dashboard: dashboardConfigSchema,\n graph: graphConfigSchema,\n /** Registered inbound webhooks — an inventory the dashboard manages. Each\n * entry binds an (agent, source) pair to an optional signing secret. The\n * actual inbound URL is always POST /webhook/<agentId>/<source>. */\n webhooks: z.array(z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9_-]*$/, \"webhook id must be lowercase slug\"),\n source: z.enum([\"gitlab\", \"github\", \"sentry\", \"stripe\", \"discord\", \"slack\", \"custom\"]),\n agentId: z.string(),\n secretEnv: z.string().optional(),\n description: z.string().optional(),\n enabled: z.boolean().default(true),\n })).default([]),\n /** Session cache-reuse policy. `staleMinutes` controls how long a Claude\n * session can idle before we rebuild the prompt from scratch (paying the\n * full cache-create tax again). Longer is cheaper at Opus rates but means\n * an agent may resume with mildly outdated context. */\n session: z.object({\n staleMinutes: z.number().int().min(1).max(1440).default(120),\n }).default({}),\n})\n\nexport type DaemonConfig = z.infer<typeof daemonConfigSchema>\nexport type AgentDef = z.infer<typeof agentConfigSchema>\nexport type CronJobDef = z.infer<typeof cronJobSchema>\nexport type MeshPeer = z.infer<typeof meshPeerSchema>\n\n/**\n * Expand environment variables in strings: ${VAR_NAME} -> process.env.VAR_NAME\n */\nexport function expandEnvVars(obj: unknown): unknown {\n if (typeof obj === \"string\") {\n return obj.replace(/\\$\\{(\\w+)\\}/g, (_match, name) => process.env[name] || \"\")\n }\n if (Array.isArray(obj)) {\n return obj.map(expandEnvVars)\n }\n if (obj !== null && typeof obj === \"object\") {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n result[key] = expandEnvVars(value)\n }\n return result\n }\n return obj\n}\n\n/**\n * Load daemon config from agentx.json, with env var expansion and validation.\n */\nexport function loadDaemonConfig(configPath?: string): DaemonConfig {\n const paths = configPath\n ? [configPath]\n : [\n resolve(process.cwd(), \"agentx.json\"),\n resolve(process.cwd(), \".agentx/config.json\"),\n ]\n\n // Load .env from same directory as config search\n loadDotEnv(process.cwd())\n\n let raw: string | undefined\n let foundPath: string | undefined\n\n for (const p of paths) {\n if (existsSync(p)) {\n raw = readFileSync(p, \"utf-8\")\n foundPath = p\n break\n }\n }\n\n if (!raw || !foundPath) {\n throw new Error(\n `No config found. Create agentx.json or .agentx/config.json\\n` +\n `Searched: ${paths.join(\", \")}`\n )\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (e: any) {\n throw new Error(`Invalid JSON in ${foundPath}: ${e.message}`)\n }\n\n // Expand environment variables\n const expanded = expandEnvVars(parsed)\n\n // Validate\n const result = daemonConfigSchema.safeParse(expanded)\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\")\n throw new Error(`Config validation failed (${foundPath}):\\n${issues}`)\n }\n\n return result.data\n}\n\n/**\n * Validate agent workspace directories exist and have .claude/ setup.\n */\nexport function validateWorkspaces(config: DaemonConfig): string[] {\n const warnings: string[] = []\n\n for (const [id, agent] of Object.entries(config.agents)) {\n if (!existsSync(agent.workspace)) {\n warnings.push(`Agent \"${id}\": workspace not found at ${agent.workspace}`)\n continue\n }\n\n if (agent.tier === \"claude-code\") {\n const claudeDir = resolve(agent.workspace, \".claude\")\n if (!existsSync(claudeDir)) {\n warnings.push(\n `Agent \"${id}\": no .claude/ directory in workspace ${agent.workspace}. ` +\n `Claude Code native features (hooks, MCP, skills) won't be available.`\n )\n }\n }\n\n // Check provider availability\n const providerName = agent.provider || \"claude\"\n const providerConfig = config.providers[providerName]\n if (agent.tier !== \"claude-code\" && (!providerConfig || !providerConfig.apiKey)) {\n warnings.push(\n `Agent \"${id}\": provider \"${providerName}\" has no API key configured. ` +\n `Set providers.${providerName}.apiKey in config or use tier \"claude-code\" for subscription.`\n )\n }\n }\n\n // Validate cron agent bindings\n for (const [id, cron] of Object.entries(config.crons)) {\n if (!config.agents[cron.agent]) {\n warnings.push(`Cron \"${id}\": references unknown agent \"${cron.agent}\"`)\n }\n }\n\n // Validate channel agent bindings\n if (config.channels.telegram.enabled) {\n for (const [name, account] of Object.entries(config.channels.telegram.accounts)) {\n if (!config.agents[account.agentBinding]) {\n warnings.push(\n `Telegram account \"${name}\": references unknown agent \"${account.agentBinding}\"`\n )\n }\n }\n }\n\n return warnings\n}\n"],"mappings":"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","names":["z","dayEnum","scheduleSchema","roleSchema","orgEntrySchema","channelRefSchema","workSourceSchema","businessConfigSchema","init_config","__esmMin","z","deriveStage","item","columns","set","closed","c","backlog","prefix","l","transitionDiff","fromColumn","toColumn","add","remove","closeIssue","reopen","boardLabelSchema","boardColumnSchema","boardReconcileSchema","boardSourceSchema","DEFAULT_COLUMNS","boardSchema","boardsConfigSchema","dashboardDaemonSchema","dashboardConfigSchema","init_config","__esmMin","config_exports","__export","daemonConfigSchema","expandEnvVars","loadDaemonConfig","validateWorkspaces","z","readFileSync","existsSync","resolve","loadDotEnv","dir","envPath","content","line","trimmed","eqIdx","key","value","obj","_match","name","result","configPath","paths","raw","foundPath","p","parsed","e","expanded","issues","i","config","warnings","id","agent","claudeDir","providerName","providerConfig","cron","account","providerConfigSchema","agentConfigSchema","telegramAccountSchema","channelsConfigSchema","cronJobSchema","serviceSchema","meshPeerSchema","meshConfigSchema","graphConfigSchema","notificationsSchema","init_config","__esmMin","v","businessConfigSchema","boardsConfigSchema","dashboardConfigSchema"]}
@@ -1,71 +0,0 @@
1
- import{a as se,b as re,d as ie}from"./chunk-HI24KAEY.js";import{a as te}from"./chunk-CXY2RYNI.js";import{a as ne}from"./chunk-5F3J55LG.js";import{b as ee}from"./chunk-LEIYC3BF.js";import{b as z,c as V}from"./chunk-WZEYII2S.js";import{a as Z}from"./chunk-7MBTMCKY.js";import{c as N,d as E}from"./chunk-QOYAX2FT.js";import{execa as _e}from"execa";import{execFile as Pe}from"child_process";function D(o){let e=(o||"").trim();if(!e)return{message:"Unknown error from the model.",kind:"unknown",retryable:!1};if(/timed out after/i.test(e))return{message:e.slice(0,300),kind:"timeout",retryable:!0,raw:e};let n=e.match(/\{.*\}\s*$/s)||e.match(/\{[\s\S]*\}/),t;if(n)try{t=JSON.parse(n[0])}catch{}let s=t?.error||t,r=typeof s?.type=="string"?s.type:void 0,i=typeof s?.message=="string"?s.message:void 0,c=e.match(/API Error:\s*(\d{3})/i),a=c?parseInt(c[1],10):void 0;return i&&/out of (extra )?usage|out of credit|credit(s)? exhausted|insufficient credit/i.test(i)?{kind:"out_of_credits",retryable:!1,message:"The agent is out of Anthropic credits.",fix:"Top up at https://console.anthropic.com/settings/billing (or claude.ai/settings/usage for Max subscribers), then retry.",raw:e}:i&&/context|prompt is too long|too many tokens|maximum context length/i.test(i)?{kind:"context_too_large",retryable:!1,message:"The conversation has grown past what the model can hold.",fix:"Clear session history or switch the agent to a bigger context model.",raw:e}:r==="authentication_error"||i&&/authentication|invalid.*api.*key|no api key|not authenticated/i.test(i)?{kind:"auth",retryable:!1,message:"Authentication failed talking to Anthropic.",fix:"Check ANTHROPIC_API_KEY in .env (or the Claude Code login for claude-code tier agents).",raw:e}:r==="permission_error"||a===403?{kind:"permission",retryable:!1,message:i||"The API key doesn't have permission for this request.",raw:e}:r==="rate_limit_error"||a===429?{kind:"rate_limit",retryable:!0,message:"Anthropic's API rate-limited this request.",fix:"AgentX will retry automatically. If it recurs, lower the agent's concurrency or spread scheduled jobs.",raw:e}:r==="overloaded_error"||a===529||a===503?{kind:"overloaded",retryable:!0,message:"Anthropic's API is temporarily overloaded.",fix:"AgentX will retry in a moment.",raw:e}:r==="invalid_request_error"||a===400?{kind:"invalid_request",retryable:!1,message:i||"The model rejected the request as invalid.",raw:e}:a&&a>=500?{kind:"upstream_api",retryable:!0,message:i||`Anthropic API error (HTTP ${a}).`,fix:"Transient \u2014 retry. Check https://status.anthropic.com if it persists.",raw:e}:{kind:"unknown",retryable:!1,message:e.replace(/\s+/g," ").slice(0,220),raw:e}}function _(o){return o.fix?`${o.message} \u2014 ${o.fix}`:o.message}function Q(o,e,n){let t=[];if(e.context&&!n){let s=e.context,r=["","[Environment]"],i=s.channel==="gitlab"||s.channel?.startsWith("webhook:"),c=s.channel==="telegram";if(s.channel&&r.push(`Channel: ${s.channel}`),s.group&&r.push(`Group: ${s.group}`),s.sender&&r.push(`Message from: ${s.sender}`),s.myHandle&&r.push(`Your handle on this channel: ${s.myHandle}`),i&&(r.push(""),r.push("[IMPORTANT: You are responding to a GitLab comment/event]"),r.push("- Keep it short \u2014 3-5 lines for the main message. Humans scan, not read"),r.push("- Lead with the result or action, not a narration of what you plan to do"),r.push("- Use <details><summary>Details</summary>\\n\\ncontent\\n</details> for verbose output (logs, full commands, step-by-step)"),r.push("- Do NOT mention Telegram handles \u2014 they don't work on GitLab"),r.push("- Do NOT try to delegate to other agents \u2014 reply directly"),r.push("- Reference issues with #IID and MRs with !IID")),c&&s.peers?.length){r.push(""),r.push("[Team \u2014 other agents you can mention to delegate or collaborate]");for(let a of s.peers){let d=a.handle?` (mention: ${a.handle})`:"",l=a.role?` \u2014 ${a.role}`:"";r.push(`\u2022 ${a.name}${d}${l}`)}r.push(""),r.push("To involve another agent, mention their handle in your response and they will automatically see it and reply.")}t.push(r.join(`
2
- `))}return e.context?.replyToText&&(t.push(""),t.push(`[Replying to]: ${e.context.replyToText}`)),e.context?.mediaPath&&(t.push(""),t.push(`[Attached file: ${e.context.mediaPath}]`),t.push(`[File type: ${e.context.mediaType||"unknown"}]`),e.context.mediaType?.startsWith("image/")?t.push("Please read/view this image file and describe or respond to it."):e.context.mediaType?.startsWith("audio/")?t.push("Please transcribe this audio file and respond to its content."):e.context.mediaType?.startsWith("video/")?t.push("A video file is attached. Describe what you can determine about it."):t.push("Please read this file and respond based on its content.")),n&&(t.push(""),t.push(n)),t.push(""),t.push(e.message),t.join(`
3
- `)}function oe(o,e,n,t,s,r){let i=["-p",e,"--output-format",n?"stream-json":"json"];n&&i.push("--verbose"),t&&i.push("--resume",t);let c=s||o.model;return c&&i.push("--model",c),o.permissionMode==="bypassPermissions"&&i.push("--dangerously-skip-permissions"),r&&r.trim().length>0&&i.push("--append-system-prompt",r),i}function Re(o){try{let e=JSON.parse(o);if(e&&e.is_error&&typeof e.result=="string")return e.result;if(e&&e.error&&typeof e.error=="string")return e.error}catch{}return null}function Oe(o){try{let e=JSON.parse(o),n=e.usage?{inputTokens:e.usage.input_tokens||0,outputTokens:e.usage.output_tokens||0,cacheReadTokens:e.usage.cache_read_input_tokens||0,cacheCreateTokens:e.usage.cache_creation_input_tokens||0}:void 0,t=typeof e.model=="string"&&e.model||typeof e.message?.model=="string"&&e.message.model||void 0;return{text:e.result||e.content||"",sessionId:e.session_id,usage:n,billedModel:t}}catch{return{text:o}}}async function je(o,e,n,t){let s=Date.now(),r=Q(o,e,n),i=oe(o,r,!1,t,e.model,e.systemPromptAppend);try{let c=Math.max(6e4,(o.maxExecutionMinutes??20)*6e4),{stdout:a,stderr:d,exitCode:l}=await new Promise((h,x)=>{Pe("claude",i,{cwd:o.workspace,timeout:c,maxBuffer:10485760,env:{...process.env,HOME:process.env.HOME||"/home/"+(process.env.USER||"user")}},(v,T,R)=>{h({stdout:T||"",stderr:R||"",exitCode:v?v.code??1:0})}).stdin?.end()});if(!a&&l!==0){let h;return l===143?h=`Claude Code timed out after ${Math.round(c/6e4)}m (SIGTERM). Bump agent.maxExecutionMinutes for "${o.name||"this agent"}" if tasks need longer.`:h=d?.trim()||`Claude Code exited with code ${l}`,{content:"",error:_(D(h)),duration:Date.now()-s}}let g=Re(a);if(g)return{content:"",error:_(D(g)),duration:Date.now()-s};let p=Oe(a);return{content:p.text,duration:Date.now()-s,claudeSessionId:p.sessionId,usage:p.usage,billedModel:p.billedModel}}catch(c){return console.error(`[runtime] execFile threw: ${c.message}`),{content:"",error:c.message||"Claude Code failed",duration:Date.now()-s}}}async function Ne(o,e,n,t,s,r){let i=Date.now(),c=Q(o,e,t),a=oe(o,c,!0,s,e.model,e.systemPromptAppend),d="",l,g,p,h;try{let x=Math.max(6e4,(o.maxExecutionMinutes??20)*6e4),b=_e("claude",a,{cwd:o.workspace,timeout:x,reject:!1,env:process.env,buffer:!1,stdin:"ignore"});if(b.stdout){let T="";b.stdout.on("data",R=>{T+=R.toString();let O=T.split(`
4
- `);T=O.pop()||"";for(let A of O)if(A.trim())try{let f=JSON.parse(A);if(r)try{r(f)}catch{}if(f.type==="assistant"&&f.message?.content){for(let S of f.message.content)if(S.type==="text"&&S.text){let C=S.text.slice(d.length);C&&(d=S.text,n(C,d))}}if(f.type==="content_block_delta"&&f.delta?.text&&(d+=f.delta.text,n(f.delta.text,d)),f.type==="result"&&f.result){if(f.is_error&&typeof f.result=="string")h=f.result;else{let S=(typeof f.result=="string",f.result);if(typeof S=="string"&&S.length>d.length){let C=S.slice(d.length);d=S,C&&n(C,d)}}f.usage&&(g={inputTokens:f.usage.input_tokens||0,outputTokens:f.usage.output_tokens||0,cacheReadTokens:f.usage.cache_read_input_tokens||0,cacheCreateTokens:f.usage.cache_creation_input_tokens||0}),typeof f.model=="string"&&(l=f.model),typeof f.session_id=="string"&&(p=f.session_id)}f.type==="system"&&f.subtype==="init"&&(typeof f.model=="string"&&(l=f.model),typeof f.session_id=="string"&&(p=f.session_id))}catch{A.trim()&&!A.startsWith("{")&&(d+=A+`
5
- `,n(A+`
6
- `,d))}})}let v=await b;if(!d&&v.stdout&&(d=typeof v.stdout=="string"?v.stdout:""),v.exitCode!==0&&!d){let T=typeof v.stderr=="string"?v.stderr:"";return{content:"",error:_(D(T||`Claude Code exited with code ${v.exitCode}`)),duration:Date.now()-i}}return h?{content:"",error:_(D(h)),duration:Date.now()-i,usage:g,billedModel:l,claudeSessionId:p}:{content:d,duration:Date.now()-i,usage:g,billedModel:l,claudeSessionId:p}}catch(x){return{content:d||"",error:_(D(x.message)),duration:Date.now()-i,usage:g,billedModel:l,claudeSessionId:p}}}async function Ee(o,e,n,t){let s=Date.now();try{let r=await import("@anthropic-ai/claude-agent-sdk"),{query:i}=r,c=Q(o,e,t),a="",d=i({prompt:c,options:{model:e.model||o.model,cwd:o.workspace,permissionMode:"bypassPermissions"}});for await(let l of d)l.type==="result"&&l.subtype==="success"&&(a=l.result||"");return{content:a,duration:Date.now()-s}}catch(r){return{content:"",error:`SDK error: ${r.message}`,duration:Date.now()-s}}}async function Fe(o,e,n,t){let s=Date.now();try{let{generate:r}=await import("./agent-BCDPSPKU.js"),i=o.provider||"claude-code",c=t?`${t}
7
-
8
- ${e.message}`:e.message,a=await r({task:c,cwd:o.workspace,provider:i,model:e.model||o.model,apiKey:n,overwrite:!0,interactive:!1,context7:!1});return{content:a.content||"Done.",tokensUsed:a.tokensUsed,duration:Date.now()-s}}catch(r){return{content:"",error:`Orchestrator error: ${r.message}`,duration:Date.now()-s}}}async function ae(o,e,n,t,s,r,i){switch(o.tier){case"claude-code":return t?Ne(o,e,t,s,r,i):je(o,e,s,r);case"sdk":{let c=o.provider||"claude",a=n[c]?.apiKey;return a?Ee(o,e,a,s):{content:"",error:`No API key for provider "${c}". Configure providers.${c}.apiKey`}}case"orchestrator":{let c=o.provider||"claude-code",a=n[c]?.apiKey;return Fe(o,e,a,s)}default:return{content:"",error:`Unknown tier: ${o.tier}`}}}import{readFileSync as ce,writeFileSync as He,mkdirSync as Le,existsSync as de,readdirSync as Ue}from"fs";import{resolve as K}from"path";var We=12e3,ue=30,qe=120,Be="[Compacted conversation summary";function Qe(o){let e=o.slice(11,16),n=e.slice(0,2),t=parseInt(e.slice(3,5),10);if(Number.isNaN(t))return e;let s=Math.floor(t/15)*15;return`${n}:${s.toString().padStart(2,"0")}`}var F=class{sessionsDir;cache=new Map;staleMinutes;constructor(e=process.cwd(),n={}){this.sessionsDir=K(e,".agentx/sessions"),de(this.sessionsDir)||Le(this.sessionsDir,{recursive:!0}),this.staleMinutes=Math.max(1,n.staleMinutes??qe)}sessionKey(e,n,t){let s=new Date().toISOString().slice(0,10);return`${e}:${n}:${t}:${s}`}sessionFile(e){let n=e.replace(/[^a-zA-Z0-9_:-]/g,"_");return K(this.sessionsDir,`${n}.json`)}getSession(e,n,t){let s=this.sessionKey(e,n,t);if(this.cache.has(s))return this.cache.get(s);let r=this.sessionFile(s);if(de(r))try{let a=JSON.parse(ce(r,"utf-8"));return this.cache.set(s,a),a}catch{}let i=new Date().toISOString().slice(0,10),c={id:s,agentId:e,channel:n,chatId:t,day:i,messages:[],createdAt:new Date().toISOString(),updatedAt:new Date().toISOString()};return this.cache.set(s,c),this.save(c),c}addUserMessage(e,n,t,s,r){let i=this.getSession(e,n,t);i.messages.push({role:"user",name:s,content:r,timestamp:new Date().toISOString()}),this.trim(i),i.updatedAt=new Date().toISOString(),this.save(i)}addAgentMessage(e,n,t,s){let r=this.getSession(e,n,t);r.messages.push({role:"agent",name:e,content:s,timestamp:new Date().toISOString()}),this.trim(r),r.updatedAt=new Date().toISOString(),this.save(r)}getClaudeSessionId(e,n,t){return this.getSession(e,n,t).claudeSessionId}setClaudeSessionId(e,n,t,s){let r=this.getSession(e,n,t);r.claudeSessionId=s,r.updatedAt=new Date().toISOString(),this.save(r)}buildHistoryContext(e,n,t){let s=this.getSession(e,n,t);if(s.messages.length===0)return"";let r=[`[Conversation history for today (${s.day})]`],i="";for(let c of s.messages){let a=Qe(c.timestamp);a!==i&&(r.push(`\u2014 ${a} \u2014`),i=a);let d=c.name||(c.role==="user"?"User":"Agent");r.push(`${d}: ${c.content}`)}return r.push("[End of history \u2014 respond to the latest message above]"),r.push(""),r.join(`
9
- `)}isSessionStale(e,n,t){let s=this.getSession(e,n,t);return s.claudeSessionId?Date.now()-new Date(s.updatedAt).getTime()>this.staleMinutes*60*1e3:!1}getCrossSessionSummary(e,n,t){let s=new Date().toISOString().slice(0,10),r=this.sessionKey(e,n,t);try{let i=Ue(this.sessionsDir).filter(a=>a.startsWith(e.replace(/[^a-zA-Z0-9_:-]/g,"_"))&&a.includes(s)&&a.endsWith(".json")),c=[];for(let a of i)try{let d=JSON.parse(ce(K(this.sessionsDir,a),"utf-8"));if(d.id===r||d.messages.length===0)continue;let l=d.messages.slice(-4),p=!d.chatId.startsWith("-")&&/^\d+$/.test(d.chatId)?"DM":d.chatId,h=l.map(x=>` [${x.timestamp.slice(11,16)}] ${x.name||x.role}: ${x.content.slice(0,200)}`);c.push(`From ${p} (${d.channel}):
10
- ${h.join(`
11
- `)}`)}catch{}return c.length===0?"":["[Cross-chat context \u2014 recent activity from your other conversations today]",...c,"[End cross-chat context \u2014 the user in THIS chat may be referring to actions from above]",""].join(`
12
- `)}catch{return""}}async compactIfNeeded(e,n,t,s){let r=this.getSession(e,n,t),{needsCompaction:i,compactSession:c,applyCompaction:a}=await import("./compaction-JBZZ7I7Y.js");if(!i(r.messages))return{compacted:!1};let d=await c(r.messages,e,s);return d.compactedCount===0?{compacted:!1}:(r.messages=a(r.messages,d),r.updatedAt=new Date().toISOString(),delete r.claudeSessionId,this.save(r),{compacted:!0,qualityScore:d.qualityScore,lostEntities:d.lostEntities,drift:d.drift})}hasCompaction(e,n,t){let s=this.getSession(e,n,t);return s.messages.length>0&&s.messages[0].content.startsWith(Be)}clearClaudeSessionId(e,n,t){let s=this.getSession(e,n,t);delete s.claudeSessionId,s.updatedAt=new Date().toISOString(),this.save(s)}trim(e){e.messages.length>ue&&(e.messages=e.messages.slice(-ue));let n=e.messages.reduce((t,s)=>t+s.content.length,0);for(;n>We&&e.messages.length>2;){let t=e.messages.shift();n-=t.content.length}}save(e){try{let n=this.sessionFile(e.id);He(n,JSON.stringify(e,null,2))}catch{}}};var H=class{windows=new Map;maxPerMinute;maxPerHour;constructor(e=10,n=100){this.maxPerMinute=e,this.maxPerHour=n}check(e){let n=Date.now(),t=this.windows.get(e)||[],s=n-36e5,r=t.filter(a=>a>s),i=n-6e4,c=r.filter(a=>a>i);if(c.length>=this.maxPerMinute){let a=c[0],d=Math.max(50,a+6e4-n);return{allowed:!1,reason:`Rate limit: ${c.length}/${this.maxPerMinute} per minute`,waitMs:d}}if(r.length>=this.maxPerHour){let a=r[0],d=Math.max(1e3,a+36e5-n);return{allowed:!1,reason:`Rate limit: ${r.length}/${this.maxPerHour} per hour`,waitMs:d}}return r.push(n),this.windows.set(e,r),{allowed:!0}}async acquire(e,n={}){let t=n.maxWaitMs??3e5,s=Date.now()+t,r=!0;for(;;){let i=this.check(e);if(i.allowed)return{ok:!0};if(Date.now()>=s)return{ok:!1,reason:`${i.reason} (waited ${Math.round(t/1e3)}s, giving up)`};r&&(r=!1,n.onWait?.(i.reason,i.waitMs));let c=s-Date.now(),a=Math.min(i.waitMs??1e3,c,5e3);await new Promise(d=>setTimeout(d,a))}}usage(e){let n=Date.now(),t=this.windows.get(e)||[];return{lastMinute:t.filter(s=>s>n-6e4).length,lastHour:t.filter(s=>s>n-36e5).length}}};var Ke={totalBudget:6e3,layerBudgets:{channel:200,scope:200,landscape:800,identity:200,bootstrap:500,intent:200,artifacts:500,memory:600,history:1200,"cross-chat":800,wiki:1e3}},le=4;function ge(o,e=Ke){let n=Je(o,e);n.sort((i,c)=>i.priority-c.priority);let t=[],s=0,r=e.totalBudget*le;for(let i of n){if(!i.content)continue;let c=i.maxTokens*le,a=i.content.length>c?i.content.slice(0,c)+"...":i.content;if(s+a.length>r){let d=r-s;d>100&&t.push(a.slice(0,d)+"...");break}t.push(a),s+=a.length}return t.join(`
13
-
14
- `)}function Je(o,e){let n=(i,c)=>e.layerBudgets?.[i]??c,t=[];if(t.push(Ge(o,n("channel",200))),t.push(Xe(o,n("scope",200))),o.landscape&&t.push({name:"landscape",priority:3,maxTokens:n("landscape",350),content:o.landscape,tags:["landscape","world-model"]}),o.systemPrompt&&t.push({name:"identity",priority:4,maxTokens:n("identity",200),content:o.systemPrompt.split(`
15
- `)[0],tags:["identity",o.agentId]}),o.bootstrapContext&&t.push({name:"bootstrap",priority:4.5,maxTokens:n("bootstrap",500),content:o.bootstrapContext,tags:["bootstrap","identity","personality"]}),o.intent&&o.intent.path.length>0){let i=[`[Intent path: ${o.intent.pathLabel}${o.intent.status==="pending"?" (pending approval)":""}]`],c=o.intent.path[o.intent.path.length-1],a=o.intent.axes?.[c];if(a&&Object.keys(a).length){let d=Object.entries(a).map(([l,g])=>` ${l}: ${g}`).join(`
16
- `);i.push(d)}o.intent.leaf?.input&&i.push(` input: ${o.intent.leaf.input}`),t.push({name:"intent",priority:5,maxTokens:n("intent",200),content:i.join(`
17
- `),tags:["intent",...o.intent.path]})}else{let i=Ye(o.message);i.length&&t.push({name:"intent",priority:5,maxTokens:n("intent",200),content:`[Intent: ${i.join(", ")}]`,tags:i})}let s=[];o.replyToText&&s.push(`[Replying to]: ${o.replyToText.slice(0,300)}`),o.mediaPath&&(s.push(`[Attached file: ${o.mediaPath}]`),s.push(`[File type: ${o.mediaType||"unknown"}]`),o.mediaType?.startsWith("image/")?s.push("Please view this image and respond to it."):o.mediaType?.startsWith("audio/")&&s.push("Please transcribe this audio and respond.")),o.issueMR&&s.push(`[${o.issueMR.type} #${o.issueMR.iid}: ${o.issueMR.title}]`),s.length&&t.push({name:"artifacts",priority:6,maxTokens:n("artifacts",500),content:s.join(`
18
- `),tags:["artifacts",...o.mediaType?["media"]:[]]}),o.skillInjection&&t.push({name:"skills",priority:6.2,maxTokens:n("skills",2e3),content:o.skillInjection,tags:["skills","auto-inject"]}),o.patternContext&&t.push({name:"patterns",priority:6.3,maxTokens:n("patterns",400),content:o.patternContext,tags:["patterns","behavioral","self-improving"]}),o.memoryContext&&t.push({name:"memory",priority:6.5,maxTokens:n("memory",600),content:o.memoryContext,tags:["memory","persistent"]});let r=o.groupHistory||o.sessionHistory;if(r&&t.push({name:"history",priority:7,maxTokens:n("history",1200),content:r,tags:["history","conversation"]}),o.crossChatContext&&t.push({name:"cross-chat",priority:7,maxTokens:n("cross-chat",800),content:o.crossChatContext,tags:["history","cross-chat"]}),o.handoverNote){let i=[`[Handover] You are taking over this conversation from ${o.handoverNote.fromAgent}.`];o.handoverNote.summary&&i.push(`Operator summary: ${o.handoverNote.summary}`),i.push(`Handover time: ${o.handoverNote.at}`),t.push({name:"handover",priority:7.5,maxTokens:n("handover",400),content:i.join(`
19
- `),tags:["handover",o.handoverNote.fromAgent]})}return o.wikiContext&&t.push({name:"wiki",priority:8,maxTokens:n("wiki",1e3),content:o.wikiContext,tags:["wiki","knowledge"]}),t}function Ge(o,e){let n=[`Channel: ${o.channel}`],t=[],s=[o.channel];switch(o.channel){case"telegram":o.agentHandle&&n.push(`Your handle: ${o.agentHandle}`),n.push(`From: ${o.sender}`),o.senderId&&n.push(`Telegram user ID: ${o.senderId}`),o.senderUsername&&n.push(`Username: @${o.senderUsername}`),t.push("Format responses using Telegram-compatible markdown"),t.push("Be brief \u2014 2-4 sentences max for the main point. Humans scan, not read"),t.push("Lead with the action or answer, skip preamble");break;case"whatsapp":n.push(`From: ${o.sender}`),t.push("Be brief \u2014 2-3 sentences max. WhatsApp is mobile-first"),t.push("No rich formatting \u2014 plain text only"),t.push("Lead with the action or answer, skip preamble");break;case"gitlab":n.push(`From: ${o.sender}`),t.push("Reply as a short, actionable GitLab comment \u2014 3-5 lines for the main message"),t.push("Do NOT mention Telegram handles \u2014 they don't work on GitLab"),t.push("Do NOT delegate to other agents"),t.push("Reference issues with #IID and merge requests with !IID"),t.push("Put verbose details (logs, full commands, step-by-step) inside collapsible sections: <details><summary>Title</summary>\\n\\ncontent\\n</details>"),t.push("Never narrate what you are about to do \u2014 just do it and report the result"),s.push("code-review");break;case"discord":n.push(`From: ${o.sender}`),t.push("Use Discord markdown for formatting"),t.push("Be brief \u2014 2-4 sentences for the main point");break;default:o.channel.startsWith("webhook:")&&(t.push("This is an automated event \u2014 respond with actionable steps"),s.push("webhook","automated"))}return t.length&&(n.push(""),n.push("[Rules]"),n.push(...t.map(r=>`- ${r}`))),{name:"channel",priority:1,maxTokens:e,content:n.join(`
20
- `),tags:s,rules:t}}function Xe(o,e){let n=[],t=[];if(o.channelScope==="group"&&o.groupName?(n.push(`Group: ${o.groupName}`),t.push("group",o.groupName)):o.channelScope==="project"&&o.projectPath?(n.push(`Project: ${o.projectPath}`),t.push("project",o.projectPath)):o.channelScope==="personal"&&(n.push("Direct message"),t.push("dm")),o.channelMeta){let s=o.channelMeta;if(s.agents?.length&&(n.push(`[Verified bots in this chat: ${s.agents.map(r=>r.handle||r.name||r.id).join(", ")}]`),n.push("Only mention these agents as group members \u2014 do NOT assume others are present.")),s.project&&n.push(`Project: ${s.project}`),s.issue&&n.push(`${s.issue.type} #${s.issue.iid}${s.issue.title?`: ${s.issue.title}`:""}`),s.facts?.length)for(let r of s.facts)n.push(`\u2022 ${r}`)}return{name:"scope",priority:2,maxTokens:e,content:n.join(`
21
- `),tags:t}}function Ye(o){let e=[],n=o.toLowerCase();return/deploy|push|release|ship/.test(n)&&e.push("deployment"),/review|check|look at|approve/.test(n)&&e.push("review"),/fix|bug|broken|error|issue/.test(n)&&e.push("bugfix"),/create|add|build|implement/.test(n)&&e.push("feature"),/test|spec|coverage/.test(n)&&e.push("testing"),/refactor|clean|improve/.test(n)&&e.push("refactor"),/docs|document|readme/.test(n)&&e.push("docs"),/security|vuln|auth|token/.test(n)&&e.push("security"),/perf|slow|optim|fast/.test(n)&&e.push("performance"),/status|update|progress|standup/.test(n)&&e.push("status"),/help|how|what|explain/.test(n)&&e.push("question"),/gitlab|merge|mr|issue|pipeline/.test(n)&&e.push("gitlab"),/seo|analytics|content|marketing/.test(n)&&e.push("marketing"),/infra|server|docker|k8s|devops/.test(n)&&e.push("devops"),e}import{readFileSync as Ze,writeFileSync as he,appendFileSync as ze,mkdirSync as Ve,existsSync as pe}from"fs";import{resolve as J}from"path";var me=200,et=7,L=class{memoryDir;constructor(e=process.cwd()){this.memoryDir=J(e,".agentx/memory"),pe(this.memoryDir)||Ve(this.memoryDir,{recursive:!0})}filePath(e){return J(this.memoryDir,`${e}.jsonl`)}addMemory(e,n){let t={...n,id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,createdAt:new Date().toISOString()};ze(this.filePath(e),JSON.stringify(t)+`
22
- `)}getAll(e){let n=this.filePath(e);if(!pe(n))return[];try{return Ze(n,"utf-8").split(`
23
- `).filter(s=>s.trim()).map(s=>{try{return JSON.parse(s)}catch{return null}}).filter(s=>s!==null)}catch{return[]}}findRelevant(e,n,t=8){let s=this.getAll(n);if(s.length===0)return[];let r=s.map(h=>`${h.keywords.join(" ")} ${h.content}`),i=J(this.memoryDir,`${n}_bm25_cache.json`),c=E(r,i),a=N(e,c),d=new Map(a.map(h=>[h.docIndex,h.score])),g=s.map((h,x)=>{let b=d.get(x)??0;return h.category==="secret"&&(b+=2),h.category==="commitment"&&(b+=1),{memory:h,score:b}}).filter(h=>h.score>0);if(g.length===0)return s.slice(-t);let p=g.sort((h,x)=>x.score-h.score).slice(0,t).map(h=>h.memory);if(p.length>0)try{this.recordAccess(n,p.map(h=>h.id))}catch{}return p}buildContext(e){if(e.length===0)return"";let n=["[Agent Memory \u2014 persistent facts from past conversations]"],t=n[0].length;for(let s of e){let i=!s.source.chatId.startsWith("-")&&/^\d+$/.test(s.source.chatId)?"DM":s.source.chatId,c=`- [${s.category}] ${s.content} (${i}, ${s.source.date})`;if(t+c.length>2400)break;n.push(c),t+=c.length}return n.push("[End Memory]"),n.join(`
24
- `)}recordAccess(e,n){if(n.length===0)return;let t=this.getAll(e),s=new Set(n),r=!1;for(let i of t)if(s.has(i.id)){i.accessCount=(i.accessCount||0)+1,i.lastAccessed=new Date().toISOString();let c=i.intervalDays||1;i.intervalDays=Math.min(c*2,30),i.nextReview=new Date(Date.now()+i.intervalDays*864e5).toISOString(),r=!0}r&&he(this.filePath(e),t.map(i=>JSON.stringify(i)).join(`
25
- `)+`
26
- `)}getDueForReview(e,n=5){let t=this.getAll(e),s=Date.now();return t.filter(r=>r.category==="task-state"?!1:r.nextReview?new Date(r.nextReview).getTime()<=s:!0).sort((r,i)=>!r.nextReview&&i.nextReview?-1:r.nextReview&&!i.nextReview?1:r.nextReview&&i.nextReview?new Date(r.nextReview).getTime()-new Date(i.nextReview).getTime():(r.accessCount||0)-(i.accessCount||0)).slice(0,n)}buildRecallContext(e){let n=this.getDueForReview(e,5);if(n.length===0)return"";let t=["[Memory Recall \u2014 facts due for review, verify they are still accurate]"];for(let s of n){let r=Math.round((Date.now()-new Date(s.createdAt).getTime())/864e5);t.push(`- [${s.category}] ${s.content} (${r}d old, accessed ${s.accessCount||0}x)`)}return t.push("[If any fact is outdated, note the correction. Otherwise, acknowledge recall.]"),t.join(`
27
- `)}hasSimilar(e,n){let t=this.getAll(e),r=n.toLowerCase().split(/\s+/).filter(i=>i.length>3);return t.some(i=>{let c=i.content.toLowerCase();return r.filter(d=>c.includes(d)).length>=r.length*.7})}prune(e){let n=this.getAll(e);if(n.length===0)return;let t=Date.now(),s=et*24*60*60*1e3;n=n.filter(i=>i.category==="task-state"&&i.expiresAt?new Date(i.expiresAt).getTime()>t:i.category==="task-state"&&!i.expiresAt?t-new Date(i.createdAt).getTime()<s:!0),n.length>me&&(n=n.slice(-me));let r=this.filePath(e);he(r,n.map(i=>JSON.stringify(i)).join(`
28
- `)+`
29
- `)}};var U=class{queues=new Map;defaultMode;constructor(e="collect"){this.defaultMode=e}key(e,n,t){return`${e}:${n}:${t}`}getOrCreate(e,n,t){let s=this.key(e,n,t);return this.queues.has(s)||this.queues.set(s,{mode:this.defaultMode,pending:[],running:!1}),this.queues.get(s)}setMode(e,n,t,s){this.getOrCreate(e,n,t).mode=s}onFlush(e,n,t,s){this.getOrCreate(e,n,t).onFlush=s}isBusy(e,n,t){return this.getOrCreate(e,n,t).running}markRunning(e,n,t){let s=this.getOrCreate(e,n,t);return s.running?!1:(s.running=!0,!0)}enqueue(e,n,t,s){let r=this.getOrCreate(e,n,t);if(!r.running)return null;switch(r.mode){case"drop":return"drop";case"collect":case"followup":return r.pending.push(s),r.mode}}async markDone(e,n,t){let s=this.getOrCreate(e,n,t);if(s.running=!1,s.pending.length===0)return[];let r=[...s.pending];switch(s.pending=[],s.mode){case"collect":{let i={text:r.map(c=>`[${c.sender}, ${new Date(c.timestamp).toISOString().slice(11,16)}]: ${c.text}`).join(`
30
- `),sender:r[r.length-1].sender,timestamp:Date.now(),channel:r[0].channel,chatId:r[0].chatId,originalContext:r[r.length-1].originalContext};return s.onFlush&&await s.onFlush([i]),[i]}case"followup":return s.onFlush&&await s.onFlush(r),r;case"drop":return[];default:return r}}pendingCount(e,n,t){return this.getOrCreate(e,n,t).pending.length}clear(e,n,t){let s=this.key(e,n,t);this.queues.delete(s)}stats(){return Array.from(this.queues.entries()).map(([e,n])=>({key:e,mode:n.mode,pending:n.pending.length,running:n.running}))}};import{readFileSync as tt,writeFileSync as fe,appendFileSync as nt,mkdirSync as st,existsSync as ye}from"fs";import{resolve as G}from"path";var xe=50,rt="claude-haiku-4-20250514",it=`You are a behavioral pattern extractor. Given a conversation between a user and an AI agent, extract behavioral patterns \u2014 lessons about HOW to approach tasks, not facts about the world.
31
-
32
- Extract patterns like:
33
- - "When asked about X, the approach that works is Y"
34
- - "User prefers Z style of communication"
35
- - "For deployment tasks, always check A before doing B"
36
- - "This codebase uses pattern X, so generate code following X"
37
-
38
- SKIP:
39
- - Factual information (names, dates, URLs)
40
- - Routine task completions
41
- - Greetings or small talk
42
-
43
- Output a JSON array:
44
- [{"pattern":"the behavioral lesson","context":"when this applies","confidence":0.5}]
45
-
46
- If nothing worth extracting, output: []`,W=class{patternsDir;constructor(e=process.cwd()){this.patternsDir=G(e,".agentx/patterns"),ye(this.patternsDir)||st(this.patternsDir,{recursive:!0})}filePath(e){return G(this.patternsDir,`${e}.jsonl`)}getAll(e){let n=this.filePath(e);if(!ye(n))return[];try{return tt(n,"utf-8").split(`
47
- `).filter(t=>t.trim()).map(t=>{try{return JSON.parse(t)}catch{return null}}).filter(t=>t!==null)}catch{return[]}}addPattern(e,n){let t={...n,id:`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,accessCount:0,createdAt:new Date().toISOString()};nt(this.filePath(e),JSON.stringify(t)+`
48
- `)}findRelevant(e,n,t=5){let s=this.getAll(n);if(s.length===0)return[];let r=s.map(l=>`${l.context} ${l.pattern}`),i=G(this.patternsDir,`${n}_bm25_cache.json`),c=E(r,i),d=N(e,c).slice(0,t).map(l=>s[l.docIndex]).filter(l=>l.confidence>=.3);return d.length>0&&this.recordAccess(n,d.map(l=>l.id)),d}buildContext(e){if(e.length===0)return"";let n=["[Learned Patterns \u2014 behavioral lessons from past interactions]"];for(let t of e)n.push(`- ${t.pattern} (context: ${t.context}, confidence: ${Math.round(t.confidence*100)}%)`);return n.push("[Apply these patterns when relevant to the current task]"),n.join(`
49
- `)}hasSimilar(e,n){let t=this.getAll(e),s=n.toLowerCase().split(/\s+/).filter(r=>r.length>3);return t.some(r=>{let i=r.pattern.toLowerCase();return s.filter(a=>i.includes(a)).length>=s.length*.6})}recordAccess(e,n){let t=this.getAll(e),s=new Set(n),r=!1;for(let i of t)s.has(i.id)&&(i.accessCount++,i.lastUsed=new Date().toISOString(),i.confidence=Math.min(1,i.confidence+.05),r=!0);r&&fe(this.filePath(e),t.map(i=>JSON.stringify(i)).join(`
50
- `)+`
51
- `)}prune(e){let n=this.getAll(e);n.length<=xe||(n.sort((t,s)=>s.confidence*s.accessCount-t.confidence*t.accessCount),n=n.slice(0,xe),fe(this.filePath(e),n.map(t=>JSON.stringify(t)).join(`
52
- `)+`
53
- `))}};async function we(o,e,n,t,s){if(e.length<30&&n.length<100)return;let{createProvider:r}=await import("./providers-VUIWO3ZK.js"),a=(await r("claude").generate([{role:"system",content:it},{role:"user",content:`User: ${e.slice(0,500)}
54
-
55
- Agent: ${n.slice(0,1e3)}`}],{model:rt,maxTokens:512})).content.trim().match(/\[[\s\S]*\]/);if(!a)return;let d=JSON.parse(a[0]);if(!(!Array.isArray(d)||d.length===0)){for(let l of d)s.hasSimilar(o,l.pattern)||s.addPattern(o,{agentId:o,pattern:l.pattern,context:l.context,confidence:l.confidence||.5,source:t});Math.random()<.05&&s.prune(o)}}import{existsSync as $,mkdirSync as ot,readdirSync as I,readFileSync as X,rmSync as at,writeFileSync as ct}from"fs";import{resolve as w}from"path";var ve;function Xt(o){ve=o}function Yt(){return ve}var be=64*1024,dt=5*60*1e3,P=".agentx/task-history",ut=30;function Y(o,e=800){return o.length<=e?o:o.slice(0,e)+` \u2026[+${o.length-e} chars]`}function lt(o,e){let n=0;try{n=o.listArticles(e).length}catch{return""}if(n===0)return"";let t=w(o.baseDir,"_index.md");if(!$(t))return"";let s=process.argv[1]||"dist/cli.js",r=o.baseDir.replace(new RegExp(`/agents/${e}(/[^/]+)?$`),"");return["[Institutional Wiki \u2014 cross-agent source of truth]",`A curated wiki with ${n} article${n===1?"":"s"} grouped by type: person, project, place, concept, event, decision, pattern.`,"","The wiki is the canonical source for: who people are (team, clients, agents), past events (incidents, deploys), decisions and their reasoning, documented procedures, patterns.","","BEFORE you grep the workspace, search memory, or answer from your own prior context \u2014 if the question is about who / what happened / what we decided / how we do X, call:",` node ${s} wiki query "the user's question" --dir ${r} --agent ${e}`,"","It walks the catalog + wikilink graph and returns a cited answer. Your workspace memory is local to you; the wiki is shared and authoritative. Prefer the wiki for institutional questions; prefer your workspace for code-level questions.","[End Institutional Wiki]"].join(`
56
- `)}function gt(){let o="";return e=>{if(!e||typeof e!="object")return"";let n=e.type;if(n==="system"&&e.subtype==="init"){let t=e.model?` model=${e.model}`:"",s=e.session_id?` session=${e.session_id.slice(0,8)}`:"";return`\xB7 init${t}${s}
57
- `}if(n==="assistant"&&e.message?.content){let t="";for(let s of e.message.content)if(s.type==="text"&&typeof s.text=="string")s.text.length>o.length&&(t+=s.text.slice(o.length),o=s.text);else if(s.type==="thinking"&&typeof s.thinking=="string")t+=`
58
- \u{1F4AD} ${Y(s.thinking,600)}
59
- `;else if(s.type==="tool_use"){let r=s.name||"tool",i=s.input?Y(JSON.stringify(s.input),400):"";t+=`
60
- \u2192 ${r}(${i})
61
- `}return t}if(n==="user"&&e.message?.content){let t="";for(let s of e.message.content)if(s.type==="tool_result"){let r=Array.isArray(s.content)?s.content.map(c=>typeof c?.text=="string"?c.text:"").join(""):typeof s.content=="string"?s.content:"",i=s.is_error?"\u2190 [error] ":"\u2190 ";t+=`${i}${Y(r,800)}
62
- `}return t}return n==="result"?`\xB7 done${e.duration_ms?` (${Math.round(e.duration_ms/1e3)}s)`:""}
63
- `:""}}var Se=class{agents=new Map;config;providers={};sessions;wikiHub;memoryStore;patternStore;rateLimiter;tokenTracker;landscape;messageQueue;classifier;graphStore;handoverStore=new ne;activeSouls=new Map;taskOutputs=new Map;lastSummaries=new Map;sparklineCache=new Map;log;constructor(e,n=console.error.bind(console,"[agents]")){if(this.log=n,this.config=e,this.providers=e.providers,this.sessions=new F(process.cwd(),{staleMinutes:e.session.staleMinutes}),this.wikiHub=new ee(void 0,void 0,"unified"),this.memoryStore=new L,this.patternStore=new W,this.rateLimiter=new H,this.tokenTracker=new te,this.messageQueue=new U,e.graph?.enabled){this.graphStore=new z({baseDir:w(process.cwd(),e.graph.baseDir),log:(...s)=>n("[graph]",...s)});let t=e.graph.draftAgent||e.dashboard?.draftAgent;this.classifier=new V({store:this.graphStore,daemonUrl:e.dashboard.daemonUrl,token:e.dashboard.token,draftAgent:t,autoApproveStructure:e.graph.autoApproveStructure,autoApproveConfidence:e.graph.autoApproveConfidence,log:(...s)=>n("[classifier]",...s)})}for(let[t,s]of Object.entries(e.agents))this.agents.set(t,{id:t,def:s,activeTasks:0,totalTasks:0,errors:0,runningTasks:[]})}setLandscape(e){this.landscape=e}buildHandoverNote(e,n,t){let s=this.handoverStore.get(n,t);if(!s||s.toAgent!==e)return;let r=this.handoverStore.consumeSummary(n,t);if(!(!r&&s.summaryConsumedAt))return{fromAgent:s.fromAgent,summary:r||s.summary,at:s.createdAt}}getAgent(e){return this.agents.get(e)?.def}findByMention(e,n={}){let t=e.toLowerCase(),s,r=0;for(let[i,c]of this.agents)for(let a of c.def.mentions){if(n.atMentionsOnly&&!a.startsWith("@"))continue;let d=a.toLowerCase();t.includes(d)&&d.length>r&&(s=i,r=d.length)}return s}findAllMentioned(e){let n=e.toLowerCase(),t=[];for(let[s,r]of this.agents)for(let i of r.def.mentions)if(n.includes(i.toLowerCase())){t.push(s);break}return t}getWikiHub(){return this.wikiHub}buildPeerList(e,n){let t=[];for(let[s,r]of this.agents)s!==e&&t.push({name:r.def.name,handle:this.getChannelHandle(s,n),role:r.def.systemPrompt?.split(`
64
- `)[0]?.slice(0,80)});return t}getChannelHandle(e,n){let t=this.agents.get(e)?.def;if(t)return n==="telegram"?t.mentions.find(s=>s.startsWith("@")):t.mentions[0]}async execute(e,n){let t=this.agents.get(e.agentId);if(!t)return{content:"",error:`Unknown agent: ${e.agentId}`};let s=e.context?.channel||"api",r=e.context?.chatId||e.context?.group||e.context?.sender||"default";if(t.activeTasks>=t.def.maxConcurrent){let u=t.def.queueMode||"collect",m=this.messageQueue.enqueue(e.agentId,s,r,{text:e.message,sender:e.context?.sender||"User",timestamp:Date.now(),channel:s,chatId:r,originalContext:e.context});if(m==="drop")return this.log(`[${e.agentId}] busy, message dropped (mode: drop)`),{content:"",error:`Agent "${e.agentId}" is busy \u2014 message dropped`};if(m){let y=this.messageQueue.pendingCount(e.agentId,s,r);return this.log(`[${e.agentId}] busy, message queued (mode: ${m}, pending: ${y})`),{content:"",error:`__queued__:${m}:${y}`}}}let i=await this.rateLimiter.acquire(e.agentId,{maxWaitMs:5*6e4,onWait:(u,m)=>{this.log(`[${e.agentId}] ${u} \u2014 queued, resumes in ~${Math.max(1,Math.round(m/1e3))}s`)}});if(!i.ok)return this.log(`[${e.agentId}] ${i.reason}`),{content:"",error:i.reason};t.activeTasks++,t.totalTasks++,t.lastActive=new Date;let c={id:`${Date.now()}-${Math.random().toString(36).slice(2,8)}`,messagePreview:(e.message||"").slice(0,200),channel:e.context?.channel||"api",chatId:e.context?.chatId||e.context?.group,sender:e.context?.sender,startedAt:new Date};t.runningTasks.push(c);let a={agentId:e.agentId,buffer:"",subscribers:new Set,done:!1};this.taskOutputs.set(c.id,a);let d=u=>{if(u){a.buffer+=u,a.buffer.length>be&&(a.buffer=a.buffer.slice(a.buffer.length-be));for(let m of a.subscribers)try{m(u)}catch{}}},l;if(n){let u=gt();l=m=>{let y=u(m);y&&d(y)}}this.messageQueue.markRunning(e.agentId,s,r),this.log(`[${e.agentId}] executing task (${t.activeTasks}/${t.def.maxConcurrent})`);let g=e.context?.channel||"api",p=e.context?.chatId||e.context?.group||e.context?.sender||"default",h=e.context?.sender||"User";this.sessions.addUserMessage(e.agentId,g,p,h,e.message);let x;if(this.classifier&&g!=="a2a")try{x=await this.classifier.classify({text:e.message,channel:g,sender:e.context?.sender,agentId:e.agentId})||void 0}catch(u){this.log(`[classifier] classify failed for ${e.agentId}: ${u?.message||u}`)}let b=this.wikiHub.getAgentWiki(e.agentId),v=lt(b,e.agentId),T=this.memoryStore.findRelevant(e.message,e.agentId,8),R=this.memoryStore.buildContext(T),O=this.patternStore.findRelevant(e.message,e.agentId,5),A=this.patternStore.buildContext(O),f="";try{let{loadLocalSkills:u,getAutoInjectSkills:m}=await import("./loader-PTCXLJEX.js"),y=await u(t.def.workspace);f=m(y,e.message)}catch{}let S=t.def.tier==="claude-code"?this.sessions.getClaudeSessionId(e.agentId,g,p):void 0;S&&this.sessions.isSessionStale(e.agentId,g,p)&&(this.log(`[${e.agentId}] session stale for ${g}:${p}, starting fresh`),this.sessions.clearClaudeSessionId(e.agentId,g,p),S=void 0);try{let u=await this.sessions.compactIfNeeded(e.agentId,g,p,this.memoryStore);if(u.compacted){let m=u.qualityScore??"?",y=u.lostEntities?.length??0;if(this.log(`[${e.agentId}] session compacted for ${g}:${p} (quality: ${m}%, ${y} entities lost)`),u.lostEntities?.length&&this.log(`[${e.agentId}] lost entities: ${u.lostEntities.slice(0,5).join(", ")}`),u.drift){let k=u.drift;this.log(`[${e.agentId}] DRIFT DETECTED: score=${k.overallScore} (lexicon=${k.lexiconDecay}, tools=${k.toolShift}, semantic=${k.semanticDrift})`),k.lostWords.length&&this.log(`[${e.agentId}] lost domain words: ${k.lostWords.slice(0,5).join(", ")}`)}S=void 0}}catch(u){this.log(`[${e.agentId}] compaction failed (non-fatal): ${u.message}`)}let C=S?void 0:this.sessions.buildHistoryContext(e.agentId,g,p),Te=this.sessions.getCrossSessionSummary(e.agentId,g,p),q=`${e.agentId}:${g}:${p}`,j=ie(e.message);j&&(j==="default"?(this.activeSouls.delete(q),this.log(`[${e.agentId}] Soul reset to default`)):(this.activeSouls.set(q,j),this.log(`[${e.agentId}] Soul switched to: ${j}`)));let ke=this.activeSouls.get(q),Ie=se(t.def.workspace,ke),$e=re(Ie),Ae=[t.def.systemPrompt||"",$e||""].filter(u=>u.trim().length>0).join(`
65
-
66
- `)||void 0,Ce={channel:g,channelScope:e.context?.group?"group":g==="gitlab"?"project":"personal",groupName:e.context?.group,agentId:e.agentId,agentName:t.def.name,agentHandle:this.getChannelHandle(e.agentId,g),systemPrompt:t.def.systemPrompt,sender:h,senderId:e.context?.senderId,senderUsername:e.context?.senderUsername,landscape:this.landscape?.getForAgent(e.agentId),channelMeta:e.context?.channelMeta,mediaPath:e.context?.mediaPath,mediaType:e.context?.mediaType,replyToText:e.context?.replyToText,patternContext:A||void 0,skillInjection:f||void 0,groupHistory:(e.context?.group,void 0),sessionHistory:C,memoryContext:R||void 0,crossChatContext:Te||void 0,wikiContext:v,handoverNote:this.buildHandoverNote(e.agentId,g,p),intent:x?{path:x.path,pathLabel:x.pathLabel,pathId:x.pathId,axes:x.axes,leaf:x.leaf,status:x.status}:void 0,message:e.message},Me=ge(Ce),De={...e,systemPromptAppend:Ae},M;try{let u=await ae(t.def,De,this.providers,n,Me,S,l);if(M=u,!n&&(u.content||u.error)){let m=u.error?`[error] ${u.error}`:u.content;a.buffer=m;for(let y of a.subscribers)try{y(m)}catch{}}if(u.error)t.errors++,this.log(`[${e.agentId}] error: ${u.error}`);else{if(this.sessions.addAgentMessage(e.agentId,g,p,u.content),u.claudeSessionId&&this.sessions.setClaudeSessionId(e.agentId,g,p,u.claudeSessionId),u.content.length>50){try{let B=`${e.agentId}-${Date.now().toString(36)}`;this.wikiHub.getSharedStore().addEntry({id:B,date:new Date().toISOString().slice(0,10),agentId:e.agentId,source:g,sourceContext:e.context?.group||e.context?.sender,content:`User: ${e.message}
67
-
68
- Agent: ${u.content}`})}catch{}Z(e.agentId,e.message,u.content,{channel:g,chatId:p,sender:h},this.memoryStore).catch(()=>{}),we(e.agentId,e.message,u.content,{channel:g,date:new Date().toISOString().slice(0,10)},this.patternStore).catch(()=>{})}let m=u.billedModel||e.model||t.def.model,y=e.context?.channel,k=y&&(e.context?.chatId||e.context?.group||e.context?.sender)?`${y}:${e.context?.chatId||e.context?.group||e.context?.sender}`:void 0;this.tokenTracker.record(e.agentId,u.duration||0,u.usage,e.message.length,u.content.length,!1,m,y,k),this.log(`[${e.agentId}] completed in ${u.duration}ms`+(u.tokensUsed?` (${u.tokensUsed} tokens)`:""))}return u}catch(u){return t.errors++,this.log(`[${e.agentId}] unexpected error: ${u.message}`),M={content:"",error:u.message},M}finally{t.activeTasks--;let u=t.runningTasks.findIndex(m=>m.id===c.id);u!==-1&&t.runningTasks.splice(u,1),a.done=!0,a.endedAt=new Date;for(let m of a.subscribers)try{m(`
69
- [task finished]
70
- `)}catch{}a.subscribers.clear(),setTimeout(()=>this.taskOutputs.delete(c.id),dt).unref?.();try{let m=a.endedAt,y={id:c.id,agentId:e.agentId,channel:c.channel,chatId:c.chatId,sender:c.sender,message:e.message||"",startedAt:c.startedAt.toISOString(),endedAt:m.toISOString(),durationMs:m.getTime()-c.startedAt.getTime(),ok:!M?.error,error:M?.error,responseText:M?.content||"",transcript:a.buffer};this.persistTaskRecord(y);let k=(y.responseText||y.error||"").trim();if(k){let B=k.split(/\r?\n/)[0].slice(0,140);this.lastSummaries.set(e.agentId,{text:B,at:m,ok:y.ok})}}catch(m){this.log(`[${e.agentId}] task history persist failed: ${m?.message}`)}this.messageQueue.markDone(e.agentId,s,r).then(m=>{if(m.length!==0){this.log(`[${e.agentId}] flushing ${m.length} queued message(s)`);for(let y of m)this.execute({message:y.text,agentId:e.agentId,context:y.originalContext||{channel:y.channel,sender:y.sender,chatId:y.chatId}}).catch(k=>{this.log(`[${e.agentId}] queued message failed: ${k.message}`)})}}).catch(m=>{this.log(`[${e.agentId}] queue flush failed: ${m.message}`)})}}list(){return Array.from(this.agents.values()).map(e=>{let n=this.lastSummaries.get(e.id);return{id:e.id,name:e.def.name,tier:e.def.tier,model:e.def.model,workspace:e.def.workspace,active:e.activeTasks,total:e.totalTasks,errors:e.errors,lastActive:e.lastActive,runningTasks:e.runningTasks,lastSummary:n?{text:n.text,at:n.at.toISOString(),ok:n.ok}:void 0,hourlyTasks:this.getHourlySparkline(e.id,24)}})}persistTaskRecord(e){let n=e.endedAt.slice(0,10),t=w(process.cwd(),P,this.safe(e.agentId),n);$(t)||ot(t,{recursive:!0});let s=w(t,`${this.safe(e.id)}.json`);ct(s,JSON.stringify(e,null,2),"utf-8")}getHourlySparkline(e,n=24){let t=Date.now(),s=this.sparklineCache.get(e);if(s&&t-s.at<6e4&&s.hourly.length===n)return s.hourly;let r=new Array(n).fill(0),i=t-n*36e5,c=w(process.cwd(),P,this.safe(e));if(!$(c))return this.sparklineCache.set(e,{hourly:r,at:t}),r;let a=new Date(t).toISOString().slice(0,10),d=new Date(t-864e5).toISOString().slice(0,10);new Date(t).setUTCHours(0,0,0,0);for(let g of[d,a]){let p=w(c,g);if($(p))try{for(let h of I(p)){if(!h.endsWith(".json"))continue;let x=h.split("-")[0],b=parseInt(x,10);if(!Number.isFinite(b)||b<i||b>t)continue;let v=Math.floor((t-b)/36e5),T=n-1-v;T>=0&&T<n&&r[T]++}}catch{}}return this.sparklineCache.set(e,{hourly:r,at:t}),r}hydrateLastSummariesFromDisk(){let e=w(process.cwd(),P);if(!$(e))return 0;let n=0;for(let t of I(e)){let s=w(e,t),r;try{r=I(s).filter(i=>/^\d{4}-\d{2}-\d{2}$/.test(i)).sort().reverse()}catch{continue}e:for(let i of r){let c=w(s,i),a;try{a=I(c).filter(d=>d.endsWith(".json")).sort().reverse()}catch{continue}for(let d of a)try{let l=JSON.parse(X(w(c,d),"utf-8")),g=(l.responseText||l.error||"").trim();if(!g)continue;let p=g.split(/\r?\n/)[0].slice(0,140);this.lastSummaries.set(l.agentId,{text:p,at:new Date(l.endedAt),ok:l.ok}),n++;break e}catch{}}}return n}pruneTaskHistory(e=ut){let n=w(process.cwd(),P);if(!$(n))return 0;let t=Date.now()-e*24*60*60*1e3,s=0;for(let r of I(n)){let i=w(n,r),c;try{c=I(i)}catch{continue}for(let a of c){let d=Date.parse(a+"T00:00:00Z");if(!(Number.isNaN(d)||d>=t))try{at(w(i,a),{recursive:!0,force:!0}),s++}catch{}}}return s}listTaskHistory(e,n=50){let t=w(process.cwd(),P,this.safe(e));if(!$(t))return[];let s=I(t).filter(i=>/^\d{4}-\d{2}-\d{2}$/.test(i)).sort().reverse(),r=[];for(let i of s){if(r.length>=n)break;let c=w(t,i),a;try{a=I(c).filter(d=>d.endsWith(".json"))}catch{continue}a.sort().reverse();for(let d of a){if(r.length>=n)break;try{let l=JSON.parse(X(w(c,d),"utf-8")),{transcript:g,responseText:p,...h}=l;r.push(h)}catch{}}}return r}getTaskRecord(e,n){let t=w(process.cwd(),P,this.safe(e));if(!$(t))return null;let s=this.safe(n),r=I(t).filter(i=>/^\d{4}-\d{2}-\d{2}$/.test(i)).sort().reverse();for(let i of r){let c=w(t,i,`${s}.json`);if($(c))try{return JSON.parse(X(c,"utf-8"))}catch{return null}}return null}safe(e){return e.replace(/[^a-zA-Z0-9_.:-]/g,"_")}subscribeToTaskOutput(e,n){let t=this.taskOutputs.get(e);return t?t.done?{initial:t.buffer,done:!0,unsubscribe:()=>{}}:(t.subscribers.add(n),{initial:t.buffer,done:!1,unsubscribe:()=>{t.subscribers.delete(n)}}):null}getUsage(e=7){return this.tokenTracker.summary(e)}getTodayUsage(){return this.tokenTracker.today()}getTokenTracker(){return this.tokenTracker}};export{je as a,Ee as b,Fe as c,ae as d,Xt as e,Yt as f,Se as g};
71
- //# sourceMappingURL=chunk-ABDP7TDL.js.map