adam-agent-server 1.3.0 → 1.5.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 (138) hide show
  1. package/README.md +22 -9
  2. package/dist/App-JGH6G5US.js +13 -0
  3. package/dist/adam-tools-W5AOIGEQ.js +1 -0
  4. package/dist/{approval-handler-RIJO3OBO.js → approval-handler-ORD4MUVM.js} +1 -1
  5. package/dist/audit-manager-YCJT2WP5.js +1 -0
  6. package/dist/bree-engine-R5YLSDCL.js +1 -0
  7. package/dist/{channels-LUJ7GTSP.js → channels-HYSB2EEK.js} +1 -1
  8. package/dist/channels-JCMPPQED.js +1 -0
  9. package/dist/{chunk-CLHSPXZ6.js → chunk-23VZKIB6.js} +1 -1
  10. package/dist/{chunk-AZBNUSM2.js → chunk-2DLVAKH7.js} +1 -1
  11. package/dist/chunk-2YAP4YJV.js +57 -0
  12. package/dist/{chunk-YPOTHL7X.js → chunk-5S6BMWD2.js} +1 -1
  13. package/dist/chunk-5XUR3M23.js +12 -0
  14. package/dist/chunk-6775OYXA.js +47 -0
  15. package/dist/chunk-6FXNB7NE.js +1 -0
  16. package/dist/{chunk-WKS7QVIX.js → chunk-7L2WQM7N.js} +1 -1
  17. package/dist/{chunk-NDP6LWXX.js → chunk-BR2JY5X2.js} +1 -1
  18. package/dist/{chunk-IZGTTLTG.js → chunk-C6BOQJJF.js} +1 -1
  19. package/dist/{chunk-4NW2DNDZ.js → chunk-DZEVMYPB.js} +1 -1
  20. package/dist/chunk-GBTG5B5R.js +8 -0
  21. package/dist/chunk-GY52JA5I.js +10 -0
  22. package/dist/{chunk-HFN7Y3IM.js → chunk-H54ZXA26.js} +1 -1
  23. package/dist/{chunk-DBUEHITK.js → chunk-H7VDC6FY.js} +2 -2
  24. package/dist/{chunk-ZQYKT5UY.js → chunk-HDP7A4XY.js} +1 -1
  25. package/dist/{chunk-4LSIHSCO.js → chunk-HTPUEIFT.js} +1 -1
  26. package/dist/{chunk-JZNBFZ7W.js → chunk-ISZJV72D.js} +1 -1
  27. package/dist/{chunk-4MJF77RD.js → chunk-JAS3TUZX.js} +4 -3
  28. package/dist/chunk-MTWLLE26.js +49 -0
  29. package/dist/{chunk-NUTUI5KM.js → chunk-QVKI7H7W.js} +1 -1
  30. package/dist/{chunk-7IXLL673.js → chunk-QWCRZDZS.js} +1 -1
  31. package/dist/{chunk-P6KWAGAY.js → chunk-R4GIIQ7G.js} +1 -1
  32. package/dist/chunk-RAW263MQ.js +99 -0
  33. package/dist/{chunk-IKUBP3SY.js → chunk-S3BAIZ4Q.js} +2 -2
  34. package/dist/chunk-VRJ7R766.js +1 -0
  35. package/dist/{chunk-WTRM5VO7.js → chunk-XL46AGRZ.js} +2 -2
  36. package/dist/{chunk-AKPLOO2V.js → chunk-Y3AMO6WC.js} +1 -1
  37. package/dist/{chunk-TCHBOWQ5.js → chunk-YVS565QY.js} +1 -1
  38. package/dist/{chunk-TKDT7EQO.js → chunk-Z4D3L2HR.js} +1 -1
  39. package/dist/cli.js +2 -2
  40. package/dist/{config-HR4MBTIS.js → config-EMNKHR3W.js} +1 -1
  41. package/dist/{db-6KUGCGVR.js → db-YUYXVV3A.js} +1 -1
  42. package/dist/{delivery-log-7DJJTPXL.js → delivery-log-VKONLSVD.js} +1 -1
  43. package/dist/engine-BM5BMPIC.js +1 -0
  44. package/dist/{evolution-audit-I2ITWAEC.js → evolution-audit-LZSQPDHH.js} +1 -1
  45. package/dist/index.js +18 -12
  46. package/dist/{learner-CBPQZ3HL.js → learner-IJN6B7KV.js} +1 -1
  47. package/dist/{memories-HBBW44MG.js → memories-ZII5QSTJ.js} +1 -1
  48. package/dist/{memory-extractor-XO2HJ22Y.js → memory-extractor-DIYJFBCI.js} +2 -2
  49. package/dist/memory-service-QMYJPBAE.js +1 -0
  50. package/dist/outbound-gateway-6K6P2BEH.js +1 -0
  51. package/dist/role-presets-K2BDRZBS.js +1 -0
  52. package/dist/roles-L34L5MK3.js +1 -0
  53. package/dist/{session-manager-JICVE4CO.js → session-manager-GRJ3FV3L.js} +1 -1
  54. package/dist/{task-templates-NC7XIZIC.js → task-templates-23YOAF3E.js} +1 -1
  55. package/dist/workflow-executor-JTUWX5DC.js +1 -0
  56. package/package.json +2 -2
  57. package/web/dist/assets/AlertDialog-r3y6IhpW.js +51 -0
  58. package/web/dist/assets/Button-BjXgrQ95.js +1 -0
  59. package/web/dist/assets/Card-C153tGfJ.js +1 -0
  60. package/web/dist/assets/ChannelDetail-C2uAZv1u.js +1 -0
  61. package/web/dist/assets/Channels-C62Qrg-n.js +12 -0
  62. package/web/dist/assets/Chat-kH2owmB_.js +1 -0
  63. package/web/dist/assets/Dashboard-BhD8SpFb.js +1 -0
  64. package/web/dist/assets/EmptyState-CXwJFCDQ.js +1 -0
  65. package/web/dist/assets/EnvVarEditor-GSapLD96.js +1 -0
  66. package/web/dist/assets/Evolution-BO5hysLD.js +6 -0
  67. package/web/dist/assets/GoalDetail-cxa8OvEi.js +1 -0
  68. package/web/dist/assets/Goals-Dz3qqp_l.js +1 -0
  69. package/web/dist/assets/Logs-Ckp3-hYV.js +1 -0
  70. package/web/dist/assets/Memories-DEuSRoP3.js +1 -0
  71. package/web/dist/assets/NotFound-Bvn39vSk.js +1 -0
  72. package/web/dist/assets/PageHeader-BMvN0xiB.js +1 -0
  73. package/web/dist/assets/Plugins-CRym22JF.js +1 -0
  74. package/web/dist/assets/RoleDetail-BWMjP9aZ.js +33 -0
  75. package/web/dist/assets/Roles-DD7NBDku.js +1 -0
  76. package/web/dist/assets/SectionHeader-CiCj3Is0.js +1 -0
  77. package/web/dist/assets/Settings-BlU19KuR.js +1 -0
  78. package/web/dist/assets/Strategies-CJ_q94-v.js +1 -0
  79. package/web/dist/assets/Switch-CoUUy5jr.js +1 -0
  80. package/web/dist/assets/Table-CaFJieh_.js +1 -0
  81. package/web/dist/assets/TaskDetail-DVrjU-E6.js +2 -0
  82. package/web/dist/assets/Work-BMl61RRi.js +1 -0
  83. package/web/dist/assets/dist-Bdqp1ixJ.js +1 -0
  84. package/web/dist/assets/index-DcXMQByM.css +2 -0
  85. package/web/dist/assets/index-pF--tN9F.js +2 -0
  86. package/web/dist/assets/ui-B_uMx2Fy.js +1 -0
  87. package/web/dist/assets/useIsMobileLayout-Bwrm84kJ.js +1 -0
  88. package/web/dist/assets/vendor-icons-BlMaTTx3.js +1 -0
  89. package/web/dist/assets/{vendor-react-DLRtONKt.js → vendor-react-7e01TWy7.js} +2 -2
  90. package/web/dist/assets/vendor-state-Bj70wnRm.js +1 -0
  91. package/web/dist/index.html +8 -6
  92. package/dist/App-3OBJDI2C.js +0 -9
  93. package/dist/adam-tools-4LZYFB6J.js +0 -1
  94. package/dist/audit-manager-6FFPXID3.js +0 -1
  95. package/dist/bree-engine-2NOTIBAZ.js +0 -1
  96. package/dist/channels-TSZLEU3L.js +0 -1
  97. package/dist/chunk-6NUHSHS5.js +0 -4
  98. package/dist/chunk-72VLUJ2S.js +0 -1
  99. package/dist/chunk-7CJGPCSJ.js +0 -49
  100. package/dist/chunk-NLD7WK3R.js +0 -6
  101. package/dist/chunk-OTH4M5L3.js +0 -8
  102. package/dist/chunk-PVYEGQEG.js +0 -83
  103. package/dist/chunk-XTHP5JMO.js +0 -10
  104. package/dist/chunk-ZKMDHQJY.js +0 -104
  105. package/dist/engine-HJUE6I4I.js +0 -1
  106. package/dist/memory-service-HIFTKEW2.js +0 -1
  107. package/dist/outbound-gateway-GGFMU5JW.js +0 -1
  108. package/dist/role-presets-W452Y3RV.js +0 -1
  109. package/dist/roles-NYGWZMQI.js +0 -1
  110. package/dist/workflow-executor-QN4KP7B4.js +0 -1
  111. package/web/dist/assets/Card-4mOZntHG.js +0 -1
  112. package/web/dist/assets/ChannelDetail-DX4QnE8j.js +0 -1
  113. package/web/dist/assets/Channels-EXkNOQpB.js +0 -12
  114. package/web/dist/assets/Chat-Da-mCR0c.js +0 -1
  115. package/web/dist/assets/Dashboard-Bq6sEDdP.js +0 -1
  116. package/web/dist/assets/EmptyState-BlgMMAr-.js +0 -1
  117. package/web/dist/assets/EnvVarEditor-CNxXpVbD.js +0 -1
  118. package/web/dist/assets/Evolution-DPdmbooj.js +0 -6
  119. package/web/dist/assets/GoalDetail-BamCfVzS.js +0 -1
  120. package/web/dist/assets/Goals-CHPEg0RK.js +0 -1
  121. package/web/dist/assets/Logs-BHkBvH0T.js +0 -1
  122. package/web/dist/assets/Memories-BY2pJhVd.js +0 -1
  123. package/web/dist/assets/NotFound-CSjhzSGa.js +0 -1
  124. package/web/dist/assets/Plugins-C5xLM0BU.js +0 -1
  125. package/web/dist/assets/RoleDetail-Dnp-W14x.js +0 -33
  126. package/web/dist/assets/Roles-BVOVoHvc.js +0 -1
  127. package/web/dist/assets/Settings-eBHvn6s_.js +0 -1
  128. package/web/dist/assets/Strategies-BbFbLKBJ.js +0 -1
  129. package/web/dist/assets/Switch-Q-inggPs.js +0 -1
  130. package/web/dist/assets/Table-BxbnOSbq.js +0 -1
  131. package/web/dist/assets/TaskDetail-BEjZ1gco.js +0 -2
  132. package/web/dist/assets/Work-CF2iLs8i.js +0 -1
  133. package/web/dist/assets/dist-HyCSN_hp.js +0 -1
  134. package/web/dist/assets/index-CaHdOfAc.js +0 -52
  135. package/web/dist/assets/index-D0SvKqKc.css +0 -2
  136. package/web/dist/assets/vendor-icons-CkI4-NxL.js +0 -1
  137. package/web/dist/assets/vendor-state-B_-GdGNJ.js +0 -1
  138. /package/web/dist/assets/{format-DvtQjPZn.js → format-CHfBBLog.js} +0 -0
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import{a as Fe,b as rr,c as ar,d as nr,e as or,f as ir,g as cr,h as dr,i as lr,j as pr,k as ur,l as mr,m as de,o as ht}from"./chunk-PVYEGQEG.js";import{a as sr}from"./chunk-5V36ACKZ.js";import{a as vs,b as Rs,c as bt,d as vt,e as Rr,f as Ir,g as kr,h as Tr,i as wr,j as Sr,k as Cr,m as Ar,n as Pr,p as _r,q as Rt}from"./chunk-ZKMDHQJY.js";import{c as mt,d as Is,e as Oe,f as ks,g as Ts,h as ws,j as Ss}from"./chunk-6NUHSHS5.js";import{c as us}from"./chunk-HFN7Y3IM.js";import{b as rt}from"./chunk-AKPLOO2V.js";import{c as Er,d as Fr}from"./chunk-DBUEHITK.js";import{a as gr,b as qe,c as fr,d as yr,e as hr}from"./chunk-NDP6LWXX.js";import"./chunk-TCHBOWQ5.js";import{a as Ls,b as Ms,c as Bs,e as Us}from"./chunk-72VLUJ2S.js";import{a as Ks,c as zs}from"./chunk-7CJGPCSJ.js";import{b as re,c as De,d as js,e as Ns}from"./chunk-NLD7WK3R.js";import{a as je,b as ft,c as Hs}from"./chunk-XTHP5JMO.js";import{f as Vs,g as Gs,h as $s}from"./chunk-YHVFZB6Q.js";import{a as st,b as E,c as X,d as V,e as fe,f as ts}from"./chunk-JZNBFZ7W.js";import{b as Ws}from"./chunk-WTRM5VO7.js";import{b as qs,d as he,f as ce}from"./chunk-CLHSPXZ6.js";import{b as Ne,c as Qs,d as B,e as Ys,f as Xs,g as Zs,h as yt,i as z,j as Js,n as er,o as tr}from"./chunk-TKDT7EQO.js";import{b as hs,c as bs}from"./chunk-AZBNUSM2.js";import{a as K,b as ut,c as fs,e as ys}from"./chunk-ZQYKT5UY.js";import{b as br,c as vr}from"./chunk-YPOTHL7X.js";import{a as is}from"./chunk-4NW2DNDZ.js";import{a as it,b as as,c as ns,d as La,e as se,f as ct,g as dt,h as lt,j as os}from"./chunk-7IXLL673.js";import{h as ls,i as ps}from"./chunk-NUTUI5KM.js";import{a as y}from"./chunk-L7JP7DUO.js";import{a as gt,c as Es}from"./chunk-P6KWAGAY.js";import{a as pt,b as ms}from"./chunk-2CMR5AG7.js";import{a as Cs,b as xe,c as As,g as Ps,j as _s}from"./chunk-IZGTTLTG.js";import{a as cs,b as Ee,c as ds,d as Or}from"./chunk-4LSIHSCO.js";import{b as gs}from"./chunk-T33BLZV2.js";import{a as Fs,b as Z,c as Os,d as xs,g as Ds}from"./chunk-IKUBP3SY.js";import{b as Xt,c as Zt,d as Jt,e as es}from"./chunk-7K4AQBDD.js";import{a as $t}from"./chunk-UQJZU3R5.js";import{a as et,b as Ht,c as Kt,d as zt,e as Qt}from"./chunk-7IFLU3CY.js";import{a as Te,b as Ze,c as Ut,d as F,e as we,i as Wt,j as Vt,k as Je}from"./chunk-GSMC3VUM.js";import{d as at,e as L,f as nt,g as Pe,h as ye,i as ot,k as _e}from"./chunk-OTH4M5L3.js";import{b as ie,c as Ae,d as ss,g as rs}from"./chunk-WKS7QVIX.js";import{b as W,c as tt,d as Ce}from"./chunk-4MJF77RD.js";import{c as Gt,d as O,h as ge}from"./chunk-WBAPIPST.js";import{a as Yt,c as q,d as Se,h as Y}from"./chunk-INNDBLZE.js";import"./chunk-FCV2DPZQ.js";import{writeFileSync as Ea,mkdirSync as Fa,unlinkSync as no}from"fs";import{join as Ye}from"path";ge();import{readFileSync as Ma,existsSync as Ba}from"fs";import{resolve as It}from"path";function xr(o=O){let r=[],e=[],s=process.env.ADAM_ENV_FILE;s&&e.push(It(o,s)),e.push(It(o,".env.local")),e.push(It(o,".env"));for(let t of e){if(!Ba(t))continue;Ua(t)>0&&r.push(t)}return r}function Ua(o){let e=Ma(o,"utf-8").split(`
2
- `),s=0;for(let t of e){let a=t.trim();if(!a||a.startsWith("#"))continue;a.startsWith("export ")&&(a=a.slice(7).trim());let n=a.indexOf("=");if(n===-1)continue;let i=a.slice(0,n).trim();if(!i)continue;let c=a.slice(n+1).trim();(c.startsWith('"')&&c.endsWith('"')||c.startsWith("'")&&c.endsWith("'"))&&(c=c.slice(1,-1)),c=c.replace(/\$\{(\w+)\}|\$(\w+)/g,(l,d,m)=>{let b=d??m;return process.env[b]??""}),(i.startsWith("ANTHROPIC_")||process.env[i]===void 0)&&(process.env[i]=c,s++)}return s}Ce();_e();os();import{existsSync as Dr}from"fs";import jr from"path";import Wa from"fastify";import Va from"@fastify/cors";import Ga from"@fastify/static";import $a from"@fastify/websocket";import Ha from"@fastify/swagger";import Ka from"@fastify/swagger-ui";import{timingSafeEqual as za}from"crypto";function qr(o,r){let e=Wa({logger:!1});if(e.register(Ha,{openapi:{info:{title:"Adam API",description:"Agent orchestration server built on Claude Agent SDK. Multi-agent system with parallel task execution, intelligent agent routing, self-evolving personas, and REST/WebSocket API.",version:Ee()},servers:[{url:"http://localhost:7100"}],tags:[{name:"Tasks",description:"Task lifecycle management"},{name:"Roles",description:"Role CRUD and workspace management"},{name:"Skills",description:"Skill CRUD and permissions"},{name:"Memories",description:"Agent memory search and retrieval"},{name:"Goals",description:"Goal-driven task management"},{name:"Strategies",description:"Thompson Sampling strategy engine"},{name:"Templates",description:"Task template CRUD and triggers"},{name:"Webhooks",description:"External system integration"},{name:"Config",description:"Runtime configuration management"},{name:"Evolution",description:"Agent evolution audit log"},{name:"Health",description:"Server health checks"}],components:{securitySchemes:{apiKey:{type:"apiKey",in:"header",name:"x-api-key",description:"API key for webhook endpoints"}}}}}),e.register(Ka,{routePrefix:"/docs"}),e.register(Va,{origin:!0}),e.register($a,{options:{maxPayload:1024*1024*16}}),r){let t=Buffer.from(r);e.addHook("onRequest",async(a,n)=>{let i=a.url;if(i==="/healthz"||i==="/readyz"||i.startsWith("/docs")||i.startsWith("/ui"))return;let c=a.headers["x-api-key"];if(c&&Nr(c,t))return;let l=a.query,d=l.api_key||l["x-api-key"];if(!(d&&Nr(d,t)))return n.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"})})}let s=jr.join(cs,"web/dist");return Dr(s)&&(e.register(Ga,{root:s,prefix:"/ui/",wildcard:!0}),e.get("/ui",async(t,a)=>a.sendFile("index.html",s))),e.setErrorHandler((t,a,n)=>{if(t.validation){let c=t.validation.map(l=>{let d=l.instancePath||l.params?.missingProperty||"";return d?`${d}: ${l.message}`:l.message});return n.status(400).send({code:"VALIDATION_ERROR",message:c.join("; ")})}let i=t.statusCode??500;return n.status(i).send({code:"INTERNAL_ERROR",message:t.message})}),e.setNotFoundHandler((t,a)=>{let n=t.url.split("?")[0];return t.url.startsWith("/ui")&&Dr(s)&&!jr.extname(n)?a.sendFile("index.html",s):a.status(404).send({code:"NOT_FOUND",message:"Route not found"})}),e}function Nr(o,r){try{let e=Buffer.from(o);return e.length!==r.length?!1:za(e,r)}catch{return!1}}import{z as u}from"zod/v4";import{v4 as sn}from"uuid";var Qa=o=>({...o,nullable:!0}),w={type:"object",properties:{code:{type:"string"},message:{type:"string"}}},Ya={type:"object",additionalProperties:!0,properties:{id:{type:"string"},prompt:{type:"string"},dependsOn:{type:"array",items:{type:"string"}},outputAs:{type:"string"}}},Xa={type:"object",additionalProperties:!0,properties:{type:{type:"string"},cron:{type:"string"},event:{type:"string"}}},Lr={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},description:{type:"string"},trigger:Xa,steps:{type:"array",items:Ya},agentPreference:{type:"string"},config:{type:"object",additionalProperties:!0},tags:{type:"array",items:{type:"string"}},enabled:{type:"boolean"},createdAt:{type:"number"},updatedAt:{type:"number"}}},Za={type:"object",properties:{input:{type:"number"},output:{type:"number"}}},Mr={type:"object",additionalProperties:!0,properties:{id:{type:"string"},parentId:{type:"string"},status:{type:"string"},prompt:{type:"string"},originalPrompt:{type:"string"},config:{type:"object",additionalProperties:!0},result:{type:"string"},error:{type:"string"},sdkSessionId:{type:"string"},roleId:{type:"string"},templateId:{type:"string"},createdAt:{type:"number"},startedAt:{type:"number"},completedAt:{type:"number"},costUsd:{type:"number"},tokenUsage:Za,numTurns:{type:"number"},totalDurationMs:{type:"number"}}},Ja={type:"object",additionalProperties:!0,properties:{model:{type:"string"},effort:{type:"string"},maxTurns:{type:"number"}}},Le={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},source:{type:"string"},traits:{type:"array",items:{type:"string"}},background:{type:"string"},preferences:Ja,learnedRules:{type:"array",items:{type:"string"}},memoryStreamId:{type:"string"},status:{type:"string"},createdAt:{type:"number"},lastActiveAt:{type:"number"},taskCount:{type:"number"},performanceScore:{type:"number"},role:{type:"string"},toolProfile:{type:"array",items:{type:"string"}},evaluationCriteria:{type:"object",additionalProperties:{type:"number"}},strategyPoolId:{type:"string"}}},kt={type:"object",additionalProperties:!0,properties:{id:{type:"string"},roleId:{type:"string"},type:{type:"string"},content:{type:"string"},keywords:{type:"array",items:{type:"string"}},importance:{type:"number"},sourceType:{type:"string"},sourceTaskId:{type:"string"},evidence:{type:"array",items:{type:"string"}},createdAt:{type:"number"},lastAccessed:{type:"number"},retrievedCount:{type:"number"},score:{type:"number"}}},en={type:"object",additionalProperties:!0,properties:{id:{type:"string"},role:{type:"string"},taskType:{type:"string"},name:{type:"string"},promptTemplate:{type:"string"},alpha:{type:"number"},beta:{type:"number"},totalTrials:{type:"number"},avgReward:{type:"number"},toolProfile:{type:"array",items:{type:"string"}},createdAt:{type:"number"},updatedAt:{type:"number"}}},Tt={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},description:{type:"string"},role:{type:"string"},metricType:{type:"string"},targetValue:{type:"number"},currentValue:{type:"number"},deadline:{type:"number"},budgetUsd:{type:"number"},status:{type:"string"},createdAt:{type:"number"},updatedAt:{type:"number"}}},tn={type:"object",additionalProperties:!0,properties:{name:{type:"string"},displayName:{type:"string"},description:{type:"string"},tags:{type:"array",items:{type:"string"}},trigger:{type:"string"}}},I={templateCreated:{201:{type:"object",properties:{templateId:{type:"string"}}}},templateList:{200:{type:"object",properties:{templates:{type:"array",items:Lr}}}},templateDetail:{200:{type:"object",properties:{template:Lr}},404:w},templateUpdated:{200:{type:"object",properties:{templateId:{type:"string"}}},404:w},templateDeleted:{200:{type:"object",properties:{templateId:{type:"string"},deleted:{type:"boolean"}}},404:w},templateRun:{200:{type:"object",properties:{executionId:{type:"string"},status:{type:"string"}}},404:w},taskCreated:{201:{type:"object",properties:{taskId:{type:"string"}}},400:w},taskList:{200:{type:"object",properties:{tasks:{type:"array",items:Mr}}}},taskDetail:{200:{type:"object",properties:{task:Mr}},404:w},taskAction:{200:{type:"object",additionalProperties:!0,properties:{taskId:{type:"string"}}},400:w,404:w},approvalAction:{200:{type:"object",properties:{approvalId:{type:"string"},decision:{type:"string"}}},404:w},agentList:{200:{type:"object",properties:{roles:{type:"array",items:Le}}}},agentDetail:{200:{type:"object",properties:{agent:Le}},404:w},agentCreated:{201:{type:"object",properties:{agent:Le}}},agentUpdated:{200:{type:"object",properties:{agent:Le}},404:w},agentDeleted:{200:{type:"object",properties:{agentId:{type:"string"},deleted:{type:"boolean"}}},400:w,404:w},agentPersona:{200:{type:"object",properties:{persona:Qa({type:"string"})}},404:w},memoryList:{200:{type:"object",properties:{memories:{type:"array",items:kt},count:{type:"number"}}},404:w},memoryQuery:{200:{type:"object",properties:{memories:{type:"array",items:kt},count:{type:"number"}}},404:w},memoryCreated:{201:{type:"object",properties:{memory:kt}},400:w,404:w},memoryUpdated:{200:{type:"object",properties:{memoryId:{type:"string"},updated:{type:"boolean"},embeddingUpdated:{type:"boolean"}}},400:w,404:w},memoryDeleted:{200:{type:"object",properties:{memoryId:{type:"string"},deleted:{type:"boolean"}}},404:w},strategyList:{200:{type:"object",properties:{strategies:{type:"array",items:en}}}},strategyProbabilities:{200:{type:"object",additionalProperties:!0,properties:{role:{type:"string"},taskType:{type:"string"},stats:{type:"object",additionalProperties:!0},probabilities:{type:"object",additionalProperties:{type:"number"}}}}},goalList:{200:{type:"object",properties:{goals:{type:"array",items:Tt}}}},goalDetail:{200:{type:"object",properties:{goal:Tt}},404:w},goalCreated:{201:{type:"object",properties:{goal:Tt}},400:{...w,additionalProperties:!0,properties:{...w.properties,errors:{type:"array",items:{type:"string"}},warnings:{type:"array",items:{type:"string"}}}}},webhookTriggered:{202:{type:"object",properties:{code:{type:"string"},message:{type:"string"},executionId:{type:"string"},templateId:{type:"string"}}},401:w,404:w,409:w,500:w},webhookList:{200:{type:"object",properties:{webhooks:{type:"array",items:tn},auth:{type:"string"}}}},configGet:{200:{type:"object",additionalProperties:!0,properties:{config:{type:"object",additionalProperties:{type:"object",additionalProperties:!0,properties:{value:{},mutable:{type:"boolean"}}}},mutable:{type:"array",items:{type:"string"}},restartRequired:{type:"array",items:{type:"string"}}}}},configPatch:{200:{type:"object",additionalProperties:!0,properties:{success:{type:"boolean"},updated:{type:"array",items:{type:"string"}},errors:{type:"array",items:{type:"string"}},message:{type:"string"}}}},healthz:{200:{type:"object",properties:{status:{type:"string"}}}},readyz:{200:{type:"object",properties:{status:{type:"string"},checks:{type:"object",additionalProperties:{type:"boolean"}}}},503:{type:"object",properties:{status:{type:"string"},checks:{type:"object",additionalProperties:{type:"boolean"}}}}}};var Br=u.union([u.object({type:u.literal("session"),sessionId:u.string()}),u.object({type:u.literal("channel"),channelId:u.string(),chatId:u.string().optional()})]),rn=u.object({prompt:u.string().min(1,"prompt is required"),roleId:u.string().optional(),deliverTo:u.array(Br).optional(),reportTo:u.array(Br).optional(),config:u.object({allowedTools:u.array(u.string()).optional(),disallowedTools:u.array(u.string()).optional(),maxTurns:u.number().optional(),maxBudgetUsd:u.number().optional(),mcpServers:u.record(u.string(),u.unknown()).optional(),model:u.string().optional(),effort:u.enum(["low","medium","high","max"]).optional(),settingSources:u.array(u.string()).optional(),workspacePath:u.string().optional(),timeout:u.number().optional(),approvalRequired:u.array(u.string()).optional(),approvalTimeout:u.number().optional(),env:u.record(u.string(),u.string()).optional(),plugins:u.array(u.string()).optional()}).optional()}),ae=u.object({id:u.string().uuid()}),an=["pending","queued","running","paused","completed","failed","cancelled"],nn=u.object({status:u.enum(an).optional(),roleId:u.string().optional(),limit:u.coerce.number().min(1).max(100).default(100),offset:u.coerce.number().min(0).default(0)});async function Ur(o){let r=new Fe;o.post("/tasks",{schema:{tags:["Tasks"],summary:"Create a task",description:"Create a new task with a prompt and optional agent/config overrides. The task enters 'pending' status and is picked up by the scheduler.",body:{type:"object",required:["prompt"],properties:{prompt:{type:"string",minLength:1,description:"Task prompt"},roleId:{type:"string",description:"Role to assign"},config:{type:"object",description:"Optional task configuration overrides",properties:{model:{type:"string"},maxTurns:{type:"integer"},maxBudgetUsd:{type:"number"},timeout:{type:"integer"},effort:{type:"string",enum:["low","medium","high","max"]}}}}},response:I.taskCreated}},async(a,n)=>{let i=rn.safeParse(a.body);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let{prompt:c,roleId:l,config:d,deliverTo:m,reportTo:b}=i.data,v=Jt(),f={timeout:d?.timeout??v.timeout,approvalRequired:d?.approvalRequired??v.approvalRequired,approvalTimeout:d?.approvalTimeout??v.approvalTimeout,allowedTools:d?.allowedTools??v.allowedTools,disallowedTools:d?.disallowedTools??v.disallowedTools,maxTurns:d?.maxTurns??v.maxTurns,maxBudgetUsd:d?.maxBudgetUsd??v.maxBudgetUsd,mcpServers:d?.mcpServers,model:d?.model||v.model||void 0,effort:d?.effort??v.effort,settingSources:d?.settingSources??v.settingSources,workspacePath:d?.workspacePath,env:d?.env??v.env,claudeCodePath:v.claudeCodePath,plugins:d?.plugins},g={id:sn(),status:"pending",prompt:c,roleId:l,config:f,deliverTo:m,reportTo:b,createdAt:Date.now()};return st(g),y.emit({type:"task_created",taskId:g.id}),n.status(201).send({taskId:g.id})}),o.get("/tasks",{schema:{tags:["Tasks"],summary:"List tasks",description:"List tasks with optional status filter and pagination.",querystring:{type:"object",properties:{status:{type:"string",enum:["pending","queued","running","paused","completed","failed","cancelled"]},limit:{type:"integer",minimum:1,maximum:100,default:100},offset:{type:"integer",minimum:0,default:0}}},response:I.taskList}},async(a,n)=>{let i=nn.safeParse(a.query);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let{status:c,roleId:l,limit:d,offset:m}=i.data;return{tasks:V(c,d,m,l)}}),o.get("/tasks/:id",{schema:{tags:["Tasks"],summary:"Get task by ID",description:"Retrieve a single task by its UUID.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},response:I.taskDetail}},async(a,n)=>{let i=ae.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=E(i.data.id);return c?{task:c}:n.status(404).send({code:"NOT_FOUND",message:"Task not found"})}),o.post("/tasks/:id/cancel",{schema:{tags:["Tasks"],summary:"Cancel a task",description:"Cancel a running, queued, pending, or paused task. Returns 400 if the task is in a terminal state.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},response:I.taskAction}},async(a,n)=>{let i=ae.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=E(i.data.id);return c?c.status!=="running"&&c.status!=="queued"&&c.status!=="pending"&&c.status!=="paused"?n.status(400).send({code:"INVALID_STATE",message:`Cannot cancel task in status: ${c.status}`}):(r.cancelTask(c.id),{taskId:c.id,status:"cancelled"}):n.status(404).send({code:"NOT_FOUND",message:"Task not found"})});let e=u.object({taskIds:u.array(u.string()).min(1).max(500)});o.post("/tasks/batch-cancel",{schema:{tags:["Tasks"],summary:"Batch cancel tasks",description:"Cancel multiple tasks at once. Skips tasks that are already in terminal state. Returns count of cancelled tasks.",body:{type:"object",required:["taskIds"],properties:{taskIds:{type:"array",items:{type:"string"},minItems:1,maxItems:500}}}}},async(a,n)=>{let i=e.safeParse(a.body);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=new Set(["pending","queued","running","paused"]),l=0,d=[];for(let m of i.data.taskIds){let b=E(m);if(!b){d.push({taskId:m,reason:"not found"});continue}if(!c.has(b.status)){d.push({taskId:m,reason:`already ${b.status}`});continue}r.cancelTask(m),l++}return{cancelled:l,total:i.data.taskIds.length,errors:d.length>0?d:void 0}}),o.get("/tasks/:id/logs",{schema:{tags:["Tasks"],summary:"Get task step logs",description:"Returns execution step logs for a task (reasoning, tool calls, results).",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(a,n)=>{let i=E(a.params.id);if(!i)return n.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:c=50,offset:l=0}=a.query;return{logs:rt(i.id,c,l)}});let s=u.object({approvalId:u.string().uuid(),reason:u.string().optional()});o.post("/tasks/:id/approve",{schema:{tags:["Tasks"],summary:"Approve a pending approval",description:"Approve a tool-use approval request for a paused task. The skill agent resumes execution with the approved tool call.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",required:["approvalId"],properties:{approvalId:{type:"string",format:"uuid"},reason:{type:"string"}}},response:I.approvalAction}},async(a,n)=>{let i=ae.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=s.safeParse(a.body);return c.success?E(i.data.id)?r.resolveApproval(c.data.approvalId,"allow",c.data.reason)?{approvalId:c.data.approvalId,decision:"allow"}:n.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):n.status(404).send({code:"NOT_FOUND",message:"Task not found"}):n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(c.error)})}),o.post("/tasks/:id/reject",{schema:{tags:["Tasks"],summary:"Reject a pending approval",description:"Reject a tool-use approval request for a paused task. The skill agent skips the denied tool call.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",required:["approvalId"],properties:{approvalId:{type:"string",format:"uuid"},reason:{type:"string"}}},response:I.approvalAction}},async(a,n)=>{let i=ae.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=s.safeParse(a.body);return c.success?E(i.data.id)?r.resolveApproval(c.data.approvalId,"deny",c.data.reason)?{approvalId:c.data.approvalId,decision:"deny"}:n.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):n.status(404).send({code:"NOT_FOUND",message:"Task not found"}):n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(c.error)})});let t=u.object({planId:u.string(),decision:u.enum(["allow","deny"]),approvalType:u.enum(["once","permanent"]).optional(),reason:u.string().optional()});o.post("/tasks/:id/approve-plan",{schema:{tags:["Tasks"],summary:"Approve or deny an execution plan",description:"Respond to a plan approval request. Allow once (single task), allow permanent (create rule for similar tasks), or deny.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",required:["planId","decision"],properties:{planId:{type:"string"},decision:{type:"string",enum:["allow","deny"]},approvalType:{type:"string",enum:["once","permanent"]},reason:{type:"string"}}}}},async(a,n)=>{let i=ae.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=t.safeParse(a.body);if(!c.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(c.error)});if(!E(i.data.id))return n.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{planId:d,decision:m,approvalType:b,reason:v}=c.data;return r.resolvePlanApproval(d,m,b,v)?{planId:d,decision:m,approvalType:b}:n.status(404).send({code:"NOT_FOUND",message:"Plan approval not found or already resolved"})}),o.get("/tasks/:id/plan",{schema:{tags:["Tasks"],summary:"Get execution plans for a task",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(a,n)=>{let i=ae.safeParse(a.params);return i.success?E(i.data.id)?{plans:us(i.data.id)}:n.status(404).send({code:"NOT_FOUND",message:"Task not found"}):n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)})}),o.get("/tasks/:id/delivery-log",{schema:{tags:["Tasks"],summary:"Get delivery log for a task",description:"Returns delivery log entries for a task, including channel and webhook delivery attempts.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50}}}}},async(a,n)=>{let i=ae.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(i.error)});let c=E(i.data.id);if(!c)return n.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:l=50}=a.query;return{logs:ls(c.id,l)}})}Ce();_e();async function Wr(o,r){o.get("/healthz",{schema:{tags:["Health"],summary:"Health check",description:"Basic liveness probe. Returns 200 if the server process is running.",response:I.healthz}},async(e,s)=>({status:"ok"})),o.get("/readyz",{schema:{tags:["Health"],summary:"Readiness check",description:"Readiness probe that checks database, roles, config, embedding model, and task hub. Returns 503 if any check fails.",response:I.readyz}},async(e,s)=>{let t={database:!1,manager:!1,config:!1};try{W().prepare("SELECT 1").get(),t.database=!0}catch{t.database=!1}t.manager=!0,t.config=!!r.server;try{let n=ye(void 0,1,0);t.agents=n.length>0}catch{t.agents=!1}return t.embedding=ms(),t.taskHub=!0,Object.values(t).every(n=>n)?{status:"ready",checks:t}:s.status(503).send({status:"not_ready",checks:t})}),o.get("/stats",{schema:{tags:["Health"],summary:"Runtime statistics",description:"Returns execution pool status, active/pending task counts, and cost summary."}},async(e,s)=>{let a=F().execution?.maxConcurrent??5,n=V("running"),i=V("pending"),c=ts(gs());return{executionPool:{active:n.length,max:a,queued:i.length},totalCostToday:c}}),o.get("/version",{schema:{tags:["Health"],summary:"Server version",description:"Returns the server version from package.json.",response:{200:{type:"object",properties:{name:{type:"string"},version:{type:"string"}}}}}},async(e,s)=>({name:ds(),version:Ee()}))}import{timingSafeEqual as Gr}from"crypto";import{z as $r}from"zod/v4";var wt=class{connections=new Map;eventBuffers=new Map;eventIndices=new Map;addConnection(r,e){this.connections.has(r)||this.connections.set(r,new Set),this.connections.get(r).add(e);let s=this.getBufferedEvents(r);for(let t of s)e.readyState===1&&e.send(JSON.stringify(t));e.on("close",()=>{this.removeConnection(r,e)})}removeConnection(r,e){let s=this.connections.get(r);s&&(s.delete(e),s.size===0&&this.connections.delete(r))}broadcast(r,e){this.addToBuffer(r,e);let s=this.connections.get(r);if(!s||s.size===0)return;let t=JSON.stringify(e);for(let a of s)a.readyState===1&&a.send(t)}addToBuffer(r,e){let s=this.eventBuffers.get(r);s||(s=[],this.eventBuffers.set(r,s)),s.push(e),s.length>100&&s.shift(),this.eventIndices.set(r,e.index)}getBufferedEvents(r){return this.eventBuffers.get(r)??[]}getNextIndex(r){let s=(this.eventIndices.get(r)??0)+1;return this.eventIndices.set(r,s),s}},Vr=new wt;var on=$r.object({id:$r.string().uuid()});async function Hr(o,r){o.get("/tasks/:id/stream",{websocket:!0},(e,s)=>{if(r&&!cn(s,r)){e.close(4401,"Unauthorized");return}let t=on.safeParse(s.params);if(!t.success){e.close(1008,"Invalid task ID");return}let{id:a}=t.data;if(!E(a)){e.close(1008,"Task not found");return}Vr.addConnection(a,e)})}function cn(o,r){let e=o.headers["x-api-key"];if(e)try{let a=Buffer.from(e),n=Buffer.from(r);if(a.length===n.length&&Gr(a,n))return!0}catch{}let s=o.query,t=s.api_key||s["x-api-key"];if(t)try{let a=Buffer.from(t),n=Buffer.from(r);if(a.length===n.length&&Gr(a,n))return!0}catch{}return!1}import{timingSafeEqual as Kr}from"crypto";Y();var dn=q("ws"),Me=new Set;function zr(o,r){o.get("/events",{websocket:!0},(e,s)=>{if(r&&!ln(s,r)){e.close(4401,"Unauthorized");return}Me.add(e),e.on("close",()=>{Me.delete(e)}),e.on("error",t=>{dn.error({error:t},"WebSocket error"),Me.delete(e)})}),y.on("task_status_change",e=>{M(e)}),y.on("approval_request",e=>{M(e)}),y.on("stats_update",e=>{M(e)}),y.on("log_event",e=>{M(e)}),y.on("config_changed",e=>{M(e)}),y.on("plan_approval_request",e=>{(()=>{try{let t=ys(e.taskId);if(!t)return!1;let a=hs(t.sessionId);return a?a.source.type==="channel"&&!!a.source.channelId:!1}catch{return!1}})()||M(e)}),y.on("plan_approval_decision",e=>{M(e)}),y.on("task_created",e=>{M(e)}),y.on("execution_slot_change",e=>{M(e)}),y.on("execution_task_start",e=>{M(e)}),y.on("execution_task_end",e=>{M(e)}),y.on("delivery_status_change",e=>{M(e)}),y.on("workflow_status_change",e=>{M(e)})}function M(o){let r=JSON.stringify(o);for(let e of Me)e.readyState===1&&e.send(r)}function ln(o,r){let e=o.headers["x-api-key"];if(e)try{let a=Buffer.from(e),n=Buffer.from(r);if(a.length===n.length&&Kr(a,n))return!0}catch{}let s=o.query,t=s.api_key||s["x-api-key"];if(t)try{let a=Buffer.from(t),n=Buffer.from(r);if(a.length===n.length&&Kr(a,n))return!0}catch{}return!1}Ce();function pn(o){return{id:o.id,sdkSessionId:o.sdk_session_id??void 0,userTaskSessionId:o.user_task_session_id??void 0,workspacePath:o.workspace_path??void 0,toolsFingerprint:o.tools_fingerprint??void 0,createdAt:o.created_at,lastActiveAt:o.last_active_at??void 0}}function St(){let o=W(),r=o.prepare("SELECT * FROM server_state WHERE id = 1").get();if(r)return pn(r);let e=Date.now();return o.prepare("INSERT INTO server_state (id, created_at) VALUES (1, ?)").run(e),{id:1,createdAt:e}}function be(o){let r=W(),e=[],s=[];"sdkSessionId"in o&&(e.push("sdk_session_id = ?"),s.push(o.sdkSessionId??null)),"userTaskSessionId"in o&&(e.push("user_task_session_id = ?"),s.push(o.userTaskSessionId??null)),"workspacePath"in o&&(e.push("workspace_path = ?"),s.push(o.workspacePath??null)),"lastActiveAt"in o&&(e.push("last_active_at = ?"),s.push(o.lastActiveAt??null)),"toolsFingerprint"in o&&(e.push("tools_fingerprint = ?"),s.push(o.toolsFingerprint??null)),e.length!==0&&(St(),s.push(1),r.prepare(`UPDATE server_state SET ${e.join(", ")} WHERE id = ?`).run(...s))}function Be(o){be({sdkSessionId:o,lastActiveAt:Date.now()})}function Qr(){be({sdkSessionId:void 0,lastActiveAt:Date.now()})}function Yr(o){be({workspacePath:o})}_e();os();import{z as p}from"zod/v4";import{v4 as Xr}from"uuid";Ss();La();import{rmSync as un,existsSync as Ct}from"fs";var Zr=p.object({model:p.string().optional(),effort:p.enum(["low","medium","high","max"]).optional(),maxTurns:p.number().optional()}),Jr=p.object({path:p.string(),mode:p.enum(["ro","rw"]).default("rw"),inheritPlugins:p.boolean().optional(),inheritMcp:p.boolean().optional(),inheritPermissions:p.boolean().optional()}),mn=p.string().max(256).regex(/^[A-Za-z_][A-Za-z0-9_]*$/,"Env var key must match POSIX format: [A-Za-z_][A-Za-z0-9_]*").check(p.refine(o=>!o.startsWith("ANTHROPIC_"),"ANTHROPIC_* keys are managed globally in Settings")),ea=p.record(mn,p.string().max(4096)).optional().check(p.refine(o=>!o||Object.keys(o).length<=100,"Maximum 100 environment variables per role")),gn=p.object({name:p.string().min(1,"name is required").regex(/^[\p{L}\p{N}_-]+$/u,"name must contain only letters, numbers, underscores, or hyphens"),cagPrompt:p.string().optional(),learnedRules:p.array(p.string()).optional(),allowedTools:p.array(p.string()).optional(),disallowedTools:p.array(p.string()).optional(),evaluationCriteria:p.record(p.string(),p.number()).optional(),executionMode:p.enum(["isolated","inline"]).optional(),model:p.string().optional(),maxBudgetUsd:p.number().optional(),approvalRequired:p.array(p.string()).optional(),preferences:Zr.optional(),additionalDirectories:p.array(Jr).optional(),allowedChannels:p.array(p.string()).optional(),inheritUserSettings:p.boolean().optional(),envVars:ea}),fn=p.object({name:p.string().min(1).optional(),cagPrompt:p.string().optional(),learnedRules:p.array(p.string()).optional(),status:p.enum(["active","inactive","retired"]).optional(),allowedTools:p.array(p.string()).optional(),disallowedTools:p.array(p.string()).optional(),evaluationCriteria:p.record(p.string(),p.number()).optional(),executionMode:p.enum(["isolated","inline"]).optional(),model:p.string().optional(),maxBudgetUsd:p.number().optional(),approvalRequired:p.array(p.string()).optional(),preferences:Zr.optional(),additionalDirectories:p.array(Jr).optional(),permissionMode:p.enum(["default","acceptEdits","dontAsk","bypassPermissions","plan","auto"]).optional(),allowedBashPatterns:p.array(p.string()).optional(),deniedBashPatterns:p.array(p.string()).optional(),allowedChannels:p.array(p.string()).nullable().optional(),inheritUserSettings:p.boolean().optional(),envVars:ea}),Ue=p.object({id:p.string().min(1)}),yn=p.object({status:p.enum(["active","inactive","retired"]).optional(),limit:p.coerce.number().min(1).max(100).default(100),offset:p.coerce.number().min(0).default(0)}),hn=p.object({path:p.string().min(1)});async function ta(o){o.get("/roles",{schema:{tags:["Roles"],summary:"List all roles",description:"List all roles with optional status filter and pagination.",querystring:{type:"object",properties:{status:{type:"string",enum:["active","inactive","retired"]},limit:{type:"integer",minimum:1,maximum:100,default:100},offset:{type:"integer",minimum:0,default:0}}}}},async(r,e)=>{let s=yn.safeParse(r.query);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let{status:t,limit:a,offset:n}=s.data;return{roles:ye(t,a,n).map(c=>({...c,workspacePath:se(c.name)}))}}),o.post("/roles",{schema:{tags:["Roles"],summary:"Create a role",description:"Create a new role with a name, CAG prompt, and optional preferences.",body:{type:"object",required:["name"],properties:{name:{type:"string",minLength:1},cagPrompt:{type:"string"},preferences:{type:"object",properties:{model:{type:"string"},effort:{type:"string",enum:["low","medium","high","max"]},maxTurns:{type:"number"}}}}}}},async(r,e)=>{let s=gn.safeParse(r.body);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let{name:t,cagPrompt:a,learnedRules:n,allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:m,maxBudgetUsd:b,approvalRequired:v,preferences:f,additionalDirectories:g,allowedChannels:A,inheritUserSettings:G,envVars:oe}=s.data;if(nt(t))return e.status(409).send({code:"CONFLICT",message:`Role with name '${t}' already exists`});let H={id:`role-${Xr().slice(0,8)}`,name:t,cagPrompt:a??"",learnedRules:n??[],memoryStreamId:`mem-${Xr().slice(0,8)}`,status:"active",preferences:f??{},allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:m,maxBudgetUsd:b,approvalRequired:v,additionalDirectories:g,allowedChannels:A,inheritUserSettings:G,envVars:oe,createdAt:Date.now()};return at(H),ct(H),e.status(201).send({role:H})}),o.get("/roles/:id",{schema:{tags:["Roles"],summary:"Get role by ID",description:"Retrieve a single role with its project-scope plugins.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=Ue.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=L(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let a=se(t.name),n=Oe({scope:"project",projectPath:a});return{role:t,projectPlugins:n,workspacePath:a}}),o.get("/roles/:id/scores",{schema:{tags:["Roles"],summary:"Get role quality scores",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:100,default:20}}}}},async(r,e)=>{let s=p.object({id:p.string().min(1)}).safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=L(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let a=r.query.limit??20,n=vs(t.id,a),i=Rs(t.id);return{scores:n,latestEma:i??null}}),o.patch("/roles/:id",{schema:{tags:["Roles"],summary:"Update a role",description:"Partially update a role's CAG prompt, learned rules, status, or preferences.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{name:{type:"string",minLength:1},cagPrompt:{type:"string"},learnedRules:{type:"array",items:{type:"string"}},status:{type:"string",enum:["active","inactive","retired"]},permissionMode:{type:"string",enum:["default","acceptEdits","dontAsk","bypassPermissions","plan","auto"]},allowedBashPatterns:{type:"array",items:{type:"string"}},deniedBashPatterns:{type:"array",items:{type:"string"}},preferences:{type:"object",properties:{model:{type:"string"},effort:{type:"string",enum:["low","medium","high","max"]},maxTurns:{type:"number"}}}}}}},async(r,e)=>{let s=Ue.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=fn.safeParse(r.body);if(!t.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(t.error)});if(!L(s.data.id))return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let{allowedChannels:n,...i}=t.data,c={...i,updatedAt:Date.now()};if(n!==void 0&&(c.allowedChannels=n??void 0),Pe(s.data.id,c),t.data.cagPrompt!==void 0||t.data.learnedRules!==void 0){let d=L(s.data.id);if(d){let m=se(d.name);Ct(m)&&dt(m,d)}}let l=L(s.data.id);if(l&&(t.data.allowedTools!==void 0||t.data.disallowedTools!==void 0)){let d=se(l.name);Ct(d)&&lt(l.id,l.allowedTools,d)}return{role:l}}),o.delete("/roles/:id",{schema:{tags:["Roles"],summary:"Delete a role",description:"Delete a role and its workspace.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=Ue.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=L(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});if(t.id===is)return e.status(403).send({code:"FORBIDDEN",message:"System role 'chat-manager' cannot be deleted"});let a=se(t.name);if(Ct(a))try{un(a,{recursive:!0,force:!0})}catch{}return ot(s.data.id),{roleId:s.data.id,deleted:!0}}),o.post("/roles/:id/scan-directory",{schema:{tags:["Roles"],summary:"Scan directory for plugin/permission configuration",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",required:["path"],properties:{path:{type:"string",minLength:1}}}}},async(r,e)=>{let s=Ue.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=hn.safeParse(r.body);if(!t.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(t.error)});if(!L(s.data.id))return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=ws(t.data.path);return{path:t.data.path,enabledPlugins:n.enabledPlugins,mcpServers:n.mcpServers,allowedTools:n.allowedTools,disallowedTools:n.disallowedTools}}),o.get("/roles/:id/env-diff",{schema:{tags:["Roles"],summary:"Get role env diff",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=L(r.params.id);return s?{diffs:as(s.name,s.envVars),envFileExists:it(s.name)!==null}:e.status(404).send({code:"NOT_FOUND",message:"Role not found"})}),o.post("/roles/:id/sync-to-env",{schema:{tags:["Roles"],summary:"Sync role env to .env file",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=L(r.params.id);return s?{success:!0,changed:ns(s.name,s.envVars)}:e.status(404).send({code:"NOT_FOUND",message:"Role not found"})}),o.post("/roles/:id/load-from-env",{schema:{tags:["Roles"],summary:"Load role env from .env file",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=L(r.params.id);if(!s)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let t=it(s.name);if(!t)return e.status(400).send({code:"NOT_FOUND",message:".env file not found in role workspace"});let a={};for(let[n,i]of Object.entries(t))n.startsWith("ANTHROPIC_")||(a[n]=i);return Pe(s.id,{envVars:Object.keys(a).length>0?a:void 0,updatedAt:Date.now()}),{success:!0,updated:Object.keys(a).length}})}ge();import{z as sa}from"zod/v4";import{readdirSync as bn,existsSync as vn}from"fs";import{join as At,resolve as ra,sep as na}from"path";import{homedir as Rn}from"os";var In=20,kn=sa.object({prefix:sa.string()});function oa(o){return o.startsWith("~/")?At(Rn(),o.slice(2)):o}function aa(o){let r=ra(o);for(let e of Gt){let s=oa(e),t=ra(s);if(r===t||r.startsWith(t+na))return!0}return!1}async function ia(o){o.get("/fs/suggest-dirs",{schema:{tags:["FS"],summary:"Suggest directory completions",description:"Return directory suggestions matching a given path prefix.",querystring:{type:"object",required:["prefix"],properties:{prefix:{type:"string"}}}}},async(r,e)=>{let s=kn.safeParse(r.query);if(!s.success)return{suggestions:[]};let{prefix:t}=s.data;if(!t.startsWith("/")&&!t.startsWith("~/"))return{suggestions:[]};if(aa(t))return{suggestions:[]};let a=oa(t),n,i;if(t.endsWith("/"))n=a,i="";else{let g=Math.max(a.lastIndexOf("/"),a.lastIndexOf(na));if(g<0)return{suggestions:[]};n=a.slice(0,g+1),i=a.slice(g+1)}if(!vn(n))return{suggestions:[]};let c;try{c=bn(n,{withFileTypes:!0}).filter(g=>g.isDirectory()).map(g=>g.name)}catch{return{suggestions:[]}}let l=i.toLowerCase(),d=c.filter(g=>g.toLowerCase().startsWith(l)),v=(i.startsWith(".")?d:d.filter(g=>!g.startsWith("."))).filter(g=>!aa(At(n,g)));return v.sort((g,A)=>g.localeCompare(A,void 0,{sensitivity:"base"})),{suggestions:v.slice(0,In).map(g=>At(n,g))}})}import{z as S}from"zod/v4";_e();import{v4 as Tn}from"uuid";var wn=S.object({roleId:S.string().min(1)}),Sn=S.object({roleId:S.string().min(1),prompt:S.string().min(1),topK:S.number().min(1).max(50).default(10)}),Cn=S.object({limit:S.coerce.number().min(1).max(200).default(50),offset:S.coerce.number().min(0).default(0)});function Pt(o){return L(o)!==void 0}async function ca(o){o.get("/memories/:roleId",{schema:{tags:["Memories"],summary:"List role memories",description:"List all memories for a specific role with pagination. Embeddings are stripped from the response.",params:{type:"object",required:["roleId"],properties:{roleId:{type:"string"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}},response:I.memoryList}},async(s,t)=>{let a=wn.safeParse(s.params);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(a.error)});let n=a.data.roleId;if(!Pt(n))return t.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let i=Cn.safeParse(s.query),{limit:c,offset:l}=i.success?i.data:{limit:50,offset:0},m=Ps(n,c,l).map(({embedding:b,...v})=>v);return{memories:m,count:m.length}}),o.post("/memories/query",{schema:{tags:["Memories"],summary:"Query role memories",description:"Query a role's memories using hybrid search (FTS5 + vector similarity) with Smallville-style scoring (recency, importance, relevance).",body:{type:"object",required:["roleId","prompt"],properties:{roleId:{type:"string",minLength:1,description:"The role whose memories to query"},prompt:{type:"string",minLength:1,description:"The search query"},topK:{type:"integer",minimum:1,maximum:50,default:10,description:"Number of results to return"}}},response:I.memoryQuery}},async(s,t)=>{let a=Sn.safeParse(s.body);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(a.error)});let{roleId:n,prompt:i,topK:c}=a.data;if(!Pt(n))return t.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let d=(await gt(n,i,{topK:c})).map(({embedding:m,...b})=>b);return{memories:d,count:d.length}});let r=S.object({roleId:S.string().min(1),content:S.string().min(1),type:S.enum(["event","thought","reflection"]).default("thought"),keywords:S.array(S.string()).default([]),importance:S.number().min(1).max(5).default(3),tier:S.enum(["working","episodic","semantic"]).default("episodic")});o.post("/memories",{schema:{tags:["Memories"],summary:"Create memory",description:"Create a new memory for a role. Embedding is auto-generated from content.",body:{type:"object",required:["roleId","content"],properties:{roleId:{type:"string",minLength:1},content:{type:"string",minLength:1},type:{type:"string",enum:["event","thought","reflection"],default:"thought"},keywords:{type:"array",items:{type:"string"},default:[]},importance:{type:"integer",minimum:1,maximum:5,default:3},tier:{type:"string",enum:["working","episodic","semantic"],default:"episodic"}}},response:I.memoryCreated}},async(s,t)=>{let a=r.safeParse(s.body);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(a.error)});let{roleId:n,content:i,type:c,keywords:l,importance:d,tier:m}=a.data;if(!Pt(n))return t.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let b;try{b=await pt(i)}catch{}let v=`mem-${Tn().slice(0,8)}`,f=Date.now();Cs({id:v,roleId:n,type:c,content:i,embedding:b,keywords:l,importance:d,sourceType:"manual",createdAt:f,lastAccessed:f,retrievedCount:0,tier:m??"episodic"});let g=xe(v),{embedding:A,...G}=g;return t.status(201).send({memory:G})});let e=S.object({content:S.string().min(1).optional(),type:S.enum(["event","thought","reflection"]).optional(),keywords:S.array(S.string()).optional(),importance:S.number().min(1).max(5).optional()});o.patch("/memories/:id",{schema:{tags:["Memories"],summary:"Update memory",description:"Update a memory's content, type, keywords, or importance. Embedding is regenerated if content changes.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{content:{type:"string",minLength:1},type:{type:"string",enum:["event","thought","reflection"]},keywords:{type:"array",items:{type:"string"}},importance:{type:"integer",minimum:1,maximum:5}}},response:I.memoryUpdated}},async(s,t)=>{let{id:a}=s.params;if(!xe(a))return t.status(404).send({code:"NOT_FOUND",message:"Memory not found"});let i=e.safeParse(s.body);if(!i.success)return t.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(i.error)});let c=i.data,l,d=!0;if(c.content)try{l=await pt(c.content)}catch{d=!1}let m=As(a,{content:c.content,embedding:l,keywords:c.keywords,importance:c.importance,type:c.type});return{memoryId:a,updated:m,embeddingUpdated:d}}),o.delete("/memories/:id",{schema:{tags:["Memories"],summary:"Delete memory",description:"Delete a memory by ID.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:I.memoryDeleted}},async(s,t)=>{let{id:a}=s.params;return xe(a)?(_s(a),{memoryId:a,deleted:!0}):t.status(404).send({code:"NOT_FOUND",message:"Memory not found"})})}import{query as En}from"@anthropic-ai/claude-agent-sdk";import{v4 as ne}from"uuid";function An(){try{return F().defaults.maxBudgetUsd}catch{return 5}}function _t(o){return`# ChatManager \u2014 User Interface Agent
1
+ import{a as De,b as pr,c as lr,d as ur,e as mr,f as gr,g as yr,h as fr,i as hr,j as pe,l as ht}from"./chunk-2YAP4YJV.js";import{a as Ds,b as js,c as bt,d as vt,e as Cr,f as Ar,g as Pr,h as _r,i as Er,k as Or,l as Fr,n as xr,o as Rt}from"./chunk-RAW263MQ.js";import{d as kr,e as Tr}from"./chunk-5XUR3M23.js";import{c as As}from"./chunk-H54ZXA26.js";import{c as Dr,d as jr}from"./chunk-H7VDC6FY.js";import{a as br,b as Le,c as vr,d as Rr,e as Ir}from"./chunk-BR2JY5X2.js";import"./chunk-YVS565QY.js";import{a as $s,b as Ks,c as zs,e as Qs}from"./chunk-6FXNB7NE.js";import{a as tr,c as sr}from"./chunk-MTWLLE26.js";import{a as Ne,b as yt,c as er}from"./chunk-GY52JA5I.js";import{a as hs,g as bs,h as vs,j as ae,k as xe,l as Rs,m as Is,p as Ts,q as Ss}from"./chunk-6775OYXA.js";import{a as ks}from"./chunk-5V36ACKZ.js";import{f as Xs,g as Zs,h as Js}from"./chunk-YHVFZB6Q.js";import{a as lt,b as us,c as Fe,d as ms,e as gs,f as ys,h as fs}from"./chunk-VRJ7R766.js";import{b as st}from"./chunk-Y3AMO6WC.js";import{b as E,c as J,d as V,e as ye,f as ts}from"./chunk-ISZJV72D.js";import{b as Ys}from"./chunk-XL46AGRZ.js";import{b as Hs,d as he,f as de}from"./chunk-23VZKIB6.js";import{b as qe,c as rr,d as B,e as ar,f as nr,g as or,h as ft,i as z,j as ir,n as cr,o as dr}from"./chunk-Z4D3L2HR.js";import{b as Fs,c as xs}from"./chunk-2DLVAKH7.js";import{a as K,b as mt,c as Es,e as Os}from"./chunk-HDP7A4XY.js";import{b as Sr,c as wr}from"./chunk-5S6BMWD2.js";import{a as ds}from"./chunk-DZEVMYPB.js";import{a as it,b as os,c as is,d as Ka,e as re,f as ct,g as dt,h as pt,j as cs}from"./chunk-QWCRZDZS.js";import{a as h}from"./chunk-L7JP7DUO.js";import{h as ws,i as Cs}from"./chunk-QVKI7H7W.js";import{a as gt,c as Bs}from"./chunk-R4GIIQ7G.js";import{a as ut,b as Ps}from"./chunk-2CMR5AG7.js";import{a as Ns,b as je,c as qs,g as Ls,j as Ms}from"./chunk-C6BOQJJF.js";import{a as ps,b as Oe,c as ls,d as Nr}from"./chunk-HTPUEIFT.js";import{b as _s}from"./chunk-T33BLZV2.js";import{a as Us,b as ee,c as Ws,d as Vs,g as Gs}from"./chunk-S3BAIZ4Q.js";import{b as Zt,c as Jt,e as es}from"./chunk-7K4AQBDD.js";import{a as $t}from"./chunk-UQJZU3R5.js";import{a as et,b as Kt,c as zt,d as Qt,e as Yt}from"./chunk-7IFLU3CY.js";import{a as Se,b as Ze,c as Wt,d as O,e as we,i as Vt,j as Gt,k as Je}from"./chunk-GSMC3VUM.js";import{f as as,g as rt,i as ns,k as at,l as L,m as nt,n as _e,o as fe,p as ot,r as Ee}from"./chunk-GBTG5B5R.js";import{b as ce,c as Pe,d as ss,g as rs}from"./chunk-7L2WQM7N.js";import{b as W,c as tt,d as Ae}from"./chunk-JAS3TUZX.js";import{c as Ht,d as F,h as ge}from"./chunk-WBAPIPST.js";import{a as Xt,c as q,d as Ce,h as Z}from"./chunk-INNDBLZE.js";import"./chunk-FCV2DPZQ.js";import{writeFileSync as Ma,mkdirSync as Ba,unlinkSync as vo}from"fs";import{join as Xe}from"path";ge();import{readFileSync as za,existsSync as Qa}from"fs";import{resolve as It}from"path";function qr(o=F){let r=[],e=[],s=process.env.ADAM_ENV_FILE;s&&e.push(It(o,s)),e.push(It(o,".env.local")),e.push(It(o,".env"));for(let t of e){if(!Qa(t))continue;Ya(t)>0&&r.push(t)}return r}function Ya(o){let e=za(o,"utf-8").split(`
2
+ `),s=0;for(let t of e){let a=t.trim();if(!a||a.startsWith("#"))continue;a.startsWith("export ")&&(a=a.slice(7).trim());let n=a.indexOf("=");if(n===-1)continue;let i=a.slice(0,n).trim();if(!i)continue;let c=a.slice(n+1).trim();(c.startsWith('"')&&c.endsWith('"')||c.startsWith("'")&&c.endsWith("'"))&&(c=c.slice(1,-1)),c=c.replace(/\$\{(\w+)\}|\$(\w+)/g,(l,d,u)=>{let f=d??u;return process.env[f]??""}),(i.startsWith("ANTHROPIC_")||process.env[i]===void 0)&&(process.env[i]=c,s++)}return s}Ae();Ee();cs();import{existsSync as Lr}from"fs";import Mr from"path";import Xa from"fastify";import Za from"@fastify/cors";import Ja from"@fastify/static";import en from"@fastify/websocket";import tn from"@fastify/swagger";import sn from"@fastify/swagger-ui";import{timingSafeEqual as rn}from"crypto";function Ur(o,r){let e=Xa({logger:!1});if(e.register(tn,{openapi:{info:{title:"Adam API",description:"Agent orchestration server built on Claude Agent SDK. Multi-agent system with parallel task execution, intelligent agent routing, self-evolving personas, and REST/WebSocket API.",version:Oe()},servers:[{url:"http://localhost:7100"}],tags:[{name:"Tasks",description:"Task lifecycle management"},{name:"Roles",description:"Role CRUD and workspace management"},{name:"Skills",description:"Skill CRUD and permissions"},{name:"Memories",description:"Agent memory search and retrieval"},{name:"Goals",description:"Goal-driven task management"},{name:"Strategies",description:"Thompson Sampling strategy engine"},{name:"Templates",description:"Task template CRUD and triggers"},{name:"Webhooks",description:"External system integration"},{name:"Config",description:"Runtime configuration management"},{name:"Evolution",description:"Agent evolution audit log"},{name:"Health",description:"Server health checks"}],components:{securitySchemes:{apiKey:{type:"apiKey",in:"header",name:"x-api-key",description:"API key for webhook endpoints"}}}}}),e.register(sn,{routePrefix:"/docs"}),e.register(Za,{origin:!0}),e.register(en,{options:{maxPayload:1024*1024*16}}),r){let t=Buffer.from(r);e.addHook("onRequest",async(a,n)=>{let i=a.url;if(i==="/healthz"||i==="/readyz"||i.startsWith("/docs")||i.startsWith("/ui"))return;let c=a.headers["x-api-key"];if(c&&Br(c,t))return;let l=a.query,d=l.api_key||l["x-api-key"];if(!(d&&Br(d,t)))return n.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"})})}let s=Mr.join(ps,"web/dist");return Lr(s)&&(e.register(Ja,{root:s,prefix:"/ui/",wildcard:!0}),e.get("/ui",async(t,a)=>a.sendFile("index.html",s))),e.setErrorHandler((t,a,n)=>{if(t.validation){let c=t.validation.map(l=>{let d=l.instancePath||l.params?.missingProperty||"";return d?`${d}: ${l.message}`:l.message});return n.status(400).send({code:"VALIDATION_ERROR",message:c.join("; ")})}let i=t.statusCode??500;return n.status(i).send({code:"INTERNAL_ERROR",message:t.message})}),e.setNotFoundHandler((t,a)=>{let n=t.url.split("?")[0];return t.url.startsWith("/ui")&&Lr(s)&&!Mr.extname(n)?a.sendFile("index.html",s):a.status(404).send({code:"NOT_FOUND",message:"Route not found"})}),e}function Br(o,r){try{let e=Buffer.from(o);return e.length!==r.length?!1:rn(e,r)}catch{return!1}}import{z as m}from"zod/v4";var an=o=>({...o,nullable:!0}),S={type:"object",properties:{code:{type:"string"},message:{type:"string"}}},nn={type:"object",additionalProperties:!0,properties:{id:{type:"string"},prompt:{type:"string"},dependsOn:{type:"array",items:{type:"string"}},outputAs:{type:"string"}}},on={type:"object",additionalProperties:!0,properties:{type:{type:"string"},cron:{type:"string"},event:{type:"string"}}},Wr={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},description:{type:"string"},trigger:on,steps:{type:"array",items:nn},agentPreference:{type:"string"},config:{type:"object",additionalProperties:!0},tags:{type:"array",items:{type:"string"}},enabled:{type:"boolean"},createdAt:{type:"number"},updatedAt:{type:"number"}}},cn={type:"object",properties:{input:{type:"number"},output:{type:"number"}}},Gr={type:"object",additionalProperties:!0,properties:{path:{type:"string"},access:{type:"string",enum:["ro","rw"]}}},St={type:"object",additionalProperties:!0,properties:{id:{type:"string"},targets:{type:"array",items:{type:"string"}}}},dn={type:"object",additionalProperties:!0,properties:{tools:{type:"array",items:{type:"string"}},paths:{type:"array",items:Gr},osCapabilities:{type:"array",items:St},network:{type:"boolean"},plugins:{type:"array",items:{type:"string"}}}},pn={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},status:{type:"string"},allowedTools:{type:"array",items:{type:"string"}},disallowedTools:{type:"array",items:{type:"string"}},approvalRequired:{type:"array",items:{type:"string"}},osCapabilities:{type:"array",items:St},additionalDirectories:{type:"array",items:{type:"object",additionalProperties:!0}},cagPrompt:{type:"string"},learnedRules:{type:"array",items:{type:"string"}},performanceScore:{type:"number"},model:{type:"string"},executionMode:{type:"string"}}},ln={type:"object",additionalProperties:!0,properties:{model:{type:"string"},maxTurns:{type:"integer"},maxBudgetUsd:{type:"number"},timeout:{type:"integer"},effort:{type:"string"},requirements:dn,executionProfile:pn}},Hr={type:"object",additionalProperties:!0,properties:{tools:{type:"array",items:{type:"string"}},paths:{type:"array",items:Gr},osCapabilities:{type:"array",items:St},plugins:{type:"array",items:{type:"string"}},network:{type:"boolean"}}},un={type:"object",additionalProperties:!0,properties:{roleId:{type:"string"},name:{type:"string"},fitScore:{type:"number"},missing:Hr}},mn={type:"object",additionalProperties:!0,properties:{code:{type:"string",enum:["ROLE_NOT_FOUND","ROLE_TOOL_MISMATCH","ROLE_PATH_SCOPE_MISMATCH","ROLE_OS_CAPABILITY_MISMATCH","ROLE_PLUGIN_MISMATCH","ROLE_NETWORK_MISMATCH","ROLE_SELECTION_AMBIGUOUS","REQUIREMENTS_MISSING","VALIDATION_ERROR"]},message:{type:"string"},missing:Hr,candidates:{type:"array",items:un}}},Vr={type:"object",additionalProperties:!0,properties:{id:{type:"string"},parentId:{type:"string"},status:{type:"string"},prompt:{type:"string"},originalPrompt:{type:"string"},config:ln,result:{type:"string"},error:{type:"string"},sdkSessionId:{type:"string"},roleId:{type:"string"},templateId:{type:"string"},createdAt:{type:"number"},startedAt:{type:"number"},completedAt:{type:"number"},costUsd:{type:"number"},tokenUsage:cn,numTurns:{type:"number"},totalDurationMs:{type:"number"}}},gn={type:"object",additionalProperties:!0,properties:{model:{type:"string"},effort:{type:"string"},maxTurns:{type:"number"}}},Me={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},source:{type:"string"},traits:{type:"array",items:{type:"string"}},background:{type:"string"},preferences:gn,learnedRules:{type:"array",items:{type:"string"}},memoryStreamId:{type:"string"},status:{type:"string"},createdAt:{type:"number"},lastActiveAt:{type:"number"},taskCount:{type:"number"},performanceScore:{type:"number"},role:{type:"string"},toolProfile:{type:"array",items:{type:"string"}},evaluationCriteria:{type:"object",additionalProperties:{type:"number"}},strategyPoolId:{type:"string"}}},kt={type:"object",additionalProperties:!0,properties:{id:{type:"string"},roleId:{type:"string"},type:{type:"string"},content:{type:"string"},keywords:{type:"array",items:{type:"string"}},importance:{type:"number"},sourceType:{type:"string"},sourceTaskId:{type:"string"},evidence:{type:"array",items:{type:"string"}},createdAt:{type:"number"},lastAccessed:{type:"number"},retrievedCount:{type:"number"},score:{type:"number"}}},yn={type:"object",additionalProperties:!0,properties:{id:{type:"string"},role:{type:"string"},taskType:{type:"string"},name:{type:"string"},promptTemplate:{type:"string"},alpha:{type:"number"},beta:{type:"number"},totalTrials:{type:"number"},avgReward:{type:"number"},toolProfile:{type:"array",items:{type:"string"}},createdAt:{type:"number"},updatedAt:{type:"number"}}},Tt={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},description:{type:"string"},role:{type:"string"},metricType:{type:"string"},targetValue:{type:"number"},currentValue:{type:"number"},deadline:{type:"number"},budgetUsd:{type:"number"},status:{type:"string"},createdAt:{type:"number"},updatedAt:{type:"number"}}},fn={type:"object",additionalProperties:!0,properties:{name:{type:"string"},displayName:{type:"string"},description:{type:"string"},tags:{type:"array",items:{type:"string"}},trigger:{type:"string"}}},R={templateCreated:{201:{type:"object",properties:{templateId:{type:"string"}}}},templateList:{200:{type:"object",properties:{templates:{type:"array",items:Wr}}}},templateDetail:{200:{type:"object",properties:{template:Wr}},404:S},templateUpdated:{200:{type:"object",properties:{templateId:{type:"string"}}},404:S},templateDeleted:{200:{type:"object",properties:{templateId:{type:"string"},deleted:{type:"boolean"}}},404:S},templateRun:{200:{type:"object",properties:{executionId:{type:"string"},status:{type:"string"}}},404:S},taskCreated:{201:{type:"object",additionalProperties:!0,properties:{taskId:{type:"string"},roleId:{type:"string"},fitScore:{type:"number"}}},400:mn},taskList:{200:{type:"object",properties:{tasks:{type:"array",items:Vr}}}},taskDetail:{200:{type:"object",properties:{task:Vr}},404:S},taskAction:{200:{type:"object",additionalProperties:!0,properties:{taskId:{type:"string"}}},400:S,404:S},approvalAction:{200:{type:"object",properties:{approvalId:{type:"string"},decision:{type:"string"}}},404:S},agentList:{200:{type:"object",properties:{roles:{type:"array",items:Me}}}},agentDetail:{200:{type:"object",properties:{agent:Me}},404:S},agentCreated:{201:{type:"object",properties:{agent:Me}}},agentUpdated:{200:{type:"object",properties:{agent:Me}},404:S},agentDeleted:{200:{type:"object",properties:{agentId:{type:"string"},deleted:{type:"boolean"}}},400:S,404:S},agentPersona:{200:{type:"object",properties:{persona:an({type:"string"})}},404:S},memoryList:{200:{type:"object",properties:{memories:{type:"array",items:kt},count:{type:"number"}}},404:S},memoryQuery:{200:{type:"object",properties:{memories:{type:"array",items:kt},count:{type:"number"}}},404:S},memoryCreated:{201:{type:"object",properties:{memory:kt}},400:S,404:S},memoryUpdated:{200:{type:"object",properties:{memoryId:{type:"string"},updated:{type:"boolean"},embeddingUpdated:{type:"boolean"}}},400:S,404:S},memoryDeleted:{200:{type:"object",properties:{memoryId:{type:"string"},deleted:{type:"boolean"}}},404:S},strategyList:{200:{type:"object",properties:{strategies:{type:"array",items:yn}}}},strategyProbabilities:{200:{type:"object",additionalProperties:!0,properties:{role:{type:"string"},taskType:{type:"string"},stats:{type:"object",additionalProperties:!0},probabilities:{type:"object",additionalProperties:{type:"number"}}}}},goalList:{200:{type:"object",properties:{goals:{type:"array",items:Tt}}}},goalDetail:{200:{type:"object",properties:{goal:Tt}},404:S},goalCreated:{201:{type:"object",properties:{goal:Tt}},400:{...S,additionalProperties:!0,properties:{...S.properties,errors:{type:"array",items:{type:"string"}},warnings:{type:"array",items:{type:"string"}}}}},webhookTriggered:{202:{type:"object",properties:{code:{type:"string"},message:{type:"string"},executionId:{type:"string"},templateId:{type:"string"}}},401:S,404:S,409:S,500:S},webhookList:{200:{type:"object",properties:{webhooks:{type:"array",items:fn},auth:{type:"string"}}}},configGet:{200:{type:"object",additionalProperties:!0,properties:{config:{type:"object",additionalProperties:{type:"object",additionalProperties:!0,properties:{value:{},mutable:{type:"boolean"}}}},mutable:{type:"array",items:{type:"string"}},restartRequired:{type:"array",items:{type:"string"}},sandbox:{type:"object",additionalProperties:!0,properties:{platform:{type:"string"},available:{type:"boolean"}}},osCapabilities:{type:"object",additionalProperties:!0,properties:{registry:{type:"array",items:{type:"object",additionalProperties:!0,properties:{id:{type:"string"},label:{type:"string"},description:{type:"string"},platform:{type:"string"},status:{type:"string"},availability:{type:"string"},editable:{type:"boolean"},supportsTargets:{type:"boolean"},disabledReason:{type:"string"},effectiveDisabledReason:{type:"string"}}}}}}}}},configPatch:{200:{type:"object",additionalProperties:!0,properties:{success:{type:"boolean"},updated:{type:"array",items:{type:"string"}},errors:{type:"array",items:{type:"string"}},message:{type:"string"}}}},healthz:{200:{type:"object",properties:{status:{type:"string"}}}},readyz:{200:{type:"object",properties:{status:{type:"string"},checks:{type:"object",additionalProperties:{type:"boolean"}}}},503:{type:"object",properties:{status:{type:"string"},checks:{type:"object",additionalProperties:{type:"boolean"}}}}}};var $r=m.union([m.object({type:m.literal("session"),sessionId:m.string()}),m.object({type:m.literal("channel"),channelId:m.string(),chatId:m.string().optional()})]),hn=m.object({prompt:m.string().min(1,"prompt is required"),roleId:m.string().optional(),requirements:hs.optional(),autoSelectRole:m.boolean().optional(),deliverTo:m.array($r).optional(),reportTo:m.array($r).optional(),config:m.object({allowedTools:m.array(m.string()).optional(),disallowedTools:m.array(m.string()).optional(),maxTurns:m.number().optional(),maxBudgetUsd:m.number().optional(),mcpServers:m.record(m.string(),m.unknown()).optional(),model:m.string().optional(),effort:m.enum(["low","medium","high","max"]).optional(),settingSources:m.array(m.string()).optional(),workspacePath:m.string().optional(),timeout:m.number().optional(),approvalRequired:m.array(m.string()).optional(),approvalTimeout:m.number().optional(),env:m.record(m.string(),m.string()).optional(),plugins:m.array(m.string()).optional()}).optional()}),ne=m.object({id:m.string().uuid()}),bn=["pending","queued","running","paused","completed","failed","cancelled"],vn=m.object({status:m.enum(bn).optional(),roleId:m.string().optional(),limit:m.coerce.number().min(1).max(100).default(100),offset:m.coerce.number().min(0).default(0)});async function Kr(o){let r=new De;o.post("/tasks",{schema:{tags:["Tasks"],summary:"Create a task",description:"Create a new task with a prompt and optional agent/config overrides. The task enters 'pending' status and is picked up by the scheduler.",body:{type:"object",required:["prompt"],properties:{prompt:{type:"string",minLength:1,description:"Task prompt"},roleId:{type:"string",description:"Role to assign"},config:{type:"object",description:"Optional task configuration overrides",properties:{model:{type:"string"},maxTurns:{type:"integer"},maxBudgetUsd:{type:"number"},timeout:{type:"integer"},effort:{type:"string",enum:["low","medium","high","max"]}}}}},response:R.taskCreated}},async(a,n)=>{let i=hn.safeParse(a.body);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let{prompt:c,roleId:l,requirements:d,autoSelectRole:u,config:f,deliverTo:T,reportTo:y}=i.data,g=await Ss({prompt:c,roleId:l,requirements:d,autoSelectRole:u,deliverTo:T,reportTo:y,config:f});return g.ok?n.status(201).send({taskId:g.taskId,roleId:g.roleId,fitScore:g.fitScore}):n.status(400).send({code:g.code,message:g.reason,missing:g.missing,candidates:g.candidates})}),o.get("/tasks",{schema:{tags:["Tasks"],summary:"List tasks",description:"List tasks with optional status filter and pagination.",querystring:{type:"object",properties:{status:{type:"string",enum:["pending","queued","running","paused","completed","failed","cancelled"]},limit:{type:"integer",minimum:1,maximum:100,default:100},offset:{type:"integer",minimum:0,default:0}}},response:R.taskList}},async(a,n)=>{let i=vn.safeParse(a.query);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let{status:c,roleId:l,limit:d,offset:u}=i.data;return{tasks:V(c,d,u,l)}}),o.get("/tasks/:id",{schema:{tags:["Tasks"],summary:"Get task by ID",description:"Retrieve a single task by its UUID.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},response:R.taskDetail}},async(a,n)=>{let i=ne.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=E(i.data.id);return c?{task:c}:n.status(404).send({code:"NOT_FOUND",message:"Task not found"})}),o.post("/tasks/:id/cancel",{schema:{tags:["Tasks"],summary:"Cancel a task",description:"Cancel a running, queued, pending, or paused task. Returns 400 if the task is in a terminal state.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},response:R.taskAction}},async(a,n)=>{let i=ne.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=E(i.data.id);return c?c.status!=="running"&&c.status!=="queued"&&c.status!=="pending"&&c.status!=="paused"?n.status(400).send({code:"INVALID_STATE",message:`Cannot cancel task in status: ${c.status}`}):(r.cancelTask(c.id),{taskId:c.id,status:"cancelled"}):n.status(404).send({code:"NOT_FOUND",message:"Task not found"})});let e=m.object({taskIds:m.array(m.string()).min(1).max(500)});o.post("/tasks/batch-cancel",{schema:{tags:["Tasks"],summary:"Batch cancel tasks",description:"Cancel multiple tasks at once. Skips tasks that are already in terminal state. Returns count of cancelled tasks.",body:{type:"object",required:["taskIds"],properties:{taskIds:{type:"array",items:{type:"string"},minItems:1,maxItems:500}}}}},async(a,n)=>{let i=e.safeParse(a.body);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=new Set(["pending","queued","running","paused"]),l=0,d=[];for(let u of i.data.taskIds){let f=E(u);if(!f){d.push({taskId:u,reason:"not found"});continue}if(!c.has(f.status)){d.push({taskId:u,reason:`already ${f.status}`});continue}r.cancelTask(u),l++}return{cancelled:l,total:i.data.taskIds.length,errors:d.length>0?d:void 0}}),o.get("/tasks/:id/logs",{schema:{tags:["Tasks"],summary:"Get task step logs",description:"Returns execution step logs for a task (reasoning, tool calls, results).",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(a,n)=>{let i=E(a.params.id);if(!i)return n.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:c=50,offset:l=0}=a.query;return{logs:st(i.id,c,l)}});let s=m.object({approvalId:m.string().uuid(),reason:m.string().optional()});o.post("/tasks/:id/approve",{schema:{tags:["Tasks"],summary:"Approve a pending approval",description:"Approve a tool-use approval request for a paused task. The skill agent resumes execution with the approved tool call.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",required:["approvalId"],properties:{approvalId:{type:"string",format:"uuid"},reason:{type:"string"}}},response:R.approvalAction}},async(a,n)=>{let i=ne.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=s.safeParse(a.body);return c.success?E(i.data.id)?r.resolveApproval(c.data.approvalId,"allow",c.data.reason)?{approvalId:c.data.approvalId,decision:"allow"}:n.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):n.status(404).send({code:"NOT_FOUND",message:"Task not found"}):n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(c.error)})}),o.post("/tasks/:id/reject",{schema:{tags:["Tasks"],summary:"Reject a pending approval",description:"Reject a tool-use approval request for a paused task. The skill agent skips the denied tool call.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",required:["approvalId"],properties:{approvalId:{type:"string",format:"uuid"},reason:{type:"string"}}},response:R.approvalAction}},async(a,n)=>{let i=ne.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=s.safeParse(a.body);return c.success?E(i.data.id)?r.resolveApproval(c.data.approvalId,"deny",c.data.reason)?{approvalId:c.data.approvalId,decision:"deny"}:n.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):n.status(404).send({code:"NOT_FOUND",message:"Task not found"}):n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(c.error)})});let t=m.object({planId:m.string(),decision:m.enum(["allow","deny"]),approvalType:m.enum(["once","permanent"]).optional(),reason:m.string().optional()});o.post("/tasks/:id/approve-plan",{schema:{tags:["Tasks"],summary:"Approve or deny an execution plan",description:"Respond to a plan approval request. Allow once (single task), allow permanent (create rule for similar tasks), or deny.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},body:{type:"object",required:["planId","decision"],properties:{planId:{type:"string"},decision:{type:"string",enum:["allow","deny"]},approvalType:{type:"string",enum:["once","permanent"]},reason:{type:"string"}}}}},async(a,n)=>{let i=ne.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=t.safeParse(a.body);if(!c.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(c.error)});if(!E(i.data.id))return n.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{planId:d,decision:u,approvalType:f,reason:T}=c.data;return r.resolvePlanApproval(d,u,f,T)?{planId:d,decision:u,approvalType:f}:n.status(404).send({code:"NOT_FOUND",message:"Plan approval not found or already resolved"})}),o.get("/tasks/:id/plan",{schema:{tags:["Tasks"],summary:"Get execution plans for a task",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(a,n)=>{let i=ne.safeParse(a.params);return i.success?E(i.data.id)?{plans:As(i.data.id)}:n.status(404).send({code:"NOT_FOUND",message:"Task not found"}):n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)})}),o.get("/tasks/:id/delivery-log",{schema:{tags:["Tasks"],summary:"Get delivery log for a task",description:"Returns delivery log entries for a task, including channel and webhook delivery attempts.",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50}}}}},async(a,n)=>{let i=ne.safeParse(a.params);if(!i.success)return n.status(400).send({code:"VALIDATION_ERROR",message:m.prettifyError(i.error)});let c=E(i.data.id);if(!c)return n.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:l=50}=a.query;return{logs:ws(c.id,l)}})}Ae();Ee();async function zr(o,r){o.get("/healthz",{schema:{tags:["Health"],summary:"Health check",description:"Basic liveness probe. Returns 200 if the server process is running.",response:R.healthz}},async(e,s)=>({status:"ok"})),o.get("/readyz",{schema:{tags:["Health"],summary:"Readiness check",description:"Readiness probe that checks database, roles, config, embedding model, and task hub. Returns 503 if any check fails.",response:R.readyz}},async(e,s)=>{let t={database:!1,manager:!1,config:!1};try{W().prepare("SELECT 1").get(),t.database=!0}catch{t.database=!1}t.manager=!0,t.config=!!r.server;try{let n=fe(void 0,1,0);t.agents=n.length>0}catch{t.agents=!1}return t.embedding=Ps(),t.taskHub=!0,Object.values(t).every(n=>n)?{status:"ready",checks:t}:s.status(503).send({status:"not_ready",checks:t})}),o.get("/stats",{schema:{tags:["Health"],summary:"Runtime statistics",description:"Returns execution pool status, active/pending task counts, and cost summary."}},async(e,s)=>{let a=O().execution?.maxConcurrent??5,n=V("running"),i=V("pending"),c=ts(_s());return{executionPool:{active:n.length,max:a,queued:i.length},totalCostToday:c}}),o.get("/version",{schema:{tags:["Health"],summary:"Server version",description:"Returns the server version from package.json.",response:{200:{type:"object",properties:{name:{type:"string"},version:{type:"string"}}}}}},async(e,s)=>({name:ls(),version:Oe()}))}import{timingSafeEqual as Yr}from"crypto";import{z as Xr}from"zod/v4";var wt=class{connections=new Map;eventBuffers=new Map;eventIndices=new Map;addConnection(r,e){this.connections.has(r)||this.connections.set(r,new Set),this.connections.get(r).add(e);let s=this.getBufferedEvents(r);for(let t of s)e.readyState===1&&e.send(JSON.stringify(t));e.on("close",()=>{this.removeConnection(r,e)})}removeConnection(r,e){let s=this.connections.get(r);s&&(s.delete(e),s.size===0&&this.connections.delete(r))}broadcast(r,e){this.addToBuffer(r,e);let s=this.connections.get(r);if(!s||s.size===0)return;let t=JSON.stringify(e);for(let a of s)a.readyState===1&&a.send(t)}addToBuffer(r,e){let s=this.eventBuffers.get(r);s||(s=[],this.eventBuffers.set(r,s)),s.push(e),s.length>100&&s.shift(),this.eventIndices.set(r,e.index)}getBufferedEvents(r){return this.eventBuffers.get(r)??[]}getNextIndex(r){let s=(this.eventIndices.get(r)??0)+1;return this.eventIndices.set(r,s),s}},Qr=new wt;var Rn=Xr.object({id:Xr.string().uuid()});async function Zr(o,r){o.get("/tasks/:id/stream",{websocket:!0},(e,s)=>{if(r&&!In(s,r)){e.close(4401,"Unauthorized");return}let t=Rn.safeParse(s.params);if(!t.success){e.close(1008,"Invalid task ID");return}let{id:a}=t.data;if(!E(a)){e.close(1008,"Task not found");return}Qr.addConnection(a,e)})}function In(o,r){let e=o.headers["x-api-key"];if(e)try{let a=Buffer.from(e),n=Buffer.from(r);if(a.length===n.length&&Yr(a,n))return!0}catch{}let s=o.query,t=s.api_key||s["x-api-key"];if(t)try{let a=Buffer.from(t),n=Buffer.from(r);if(a.length===n.length&&Yr(a,n))return!0}catch{}return!1}import{timingSafeEqual as Jr}from"crypto";Z();var kn=q("ws"),Be=new Set;function ea(o,r){o.get("/events",{websocket:!0},(e,s)=>{if(r&&!Tn(s,r)){e.close(4401,"Unauthorized");return}Be.add(e),e.on("close",()=>{Be.delete(e)}),e.on("error",t=>{kn.error({error:t},"WebSocket error"),Be.delete(e)})}),h.on("task_status_change",e=>{M(e)}),h.on("approval_request",e=>{M(e)}),h.on("stats_update",e=>{M(e)}),h.on("log_event",e=>{M(e)}),h.on("config_changed",e=>{M(e)}),h.on("plan_approval_request",e=>{(()=>{try{let t=Os(e.taskId);if(!t)return!1;let a=Fs(t.sessionId);return a?a.source.type==="channel"&&!!a.source.channelId:!1}catch{return!1}})()||M(e)}),h.on("plan_approval_decision",e=>{M(e)}),h.on("task_created",e=>{M(e)}),h.on("execution_slot_change",e=>{M(e)}),h.on("execution_task_start",e=>{M(e)}),h.on("execution_task_end",e=>{M(e)}),h.on("delivery_status_change",e=>{M(e)}),h.on("workflow_status_change",e=>{M(e)})}function M(o){let r=JSON.stringify(o);for(let e of Be)e.readyState===1&&e.send(r)}function Tn(o,r){let e=o.headers["x-api-key"];if(e)try{let a=Buffer.from(e),n=Buffer.from(r);if(a.length===n.length&&Jr(a,n))return!0}catch{}let s=o.query,t=s.api_key||s["x-api-key"];if(t)try{let a=Buffer.from(t),n=Buffer.from(r);if(a.length===n.length&&Jr(a,n))return!0}catch{}return!1}Ae();function Sn(o){return{id:o.id,sdkSessionId:o.sdk_session_id??void 0,userTaskSessionId:o.user_task_session_id??void 0,workspacePath:o.workspace_path??void 0,toolsFingerprint:o.tools_fingerprint??void 0,createdAt:o.created_at,lastActiveAt:o.last_active_at??void 0}}function Ct(){let o=W(),r=o.prepare("SELECT * FROM server_state WHERE id = 1").get();if(r)return Sn(r);let e=Date.now();return o.prepare("INSERT INTO server_state (id, created_at) VALUES (1, ?)").run(e),{id:1,createdAt:e}}function be(o){let r=W(),e=[],s=[];"sdkSessionId"in o&&(e.push("sdk_session_id = ?"),s.push(o.sdkSessionId??null)),"userTaskSessionId"in o&&(e.push("user_task_session_id = ?"),s.push(o.userTaskSessionId??null)),"workspacePath"in o&&(e.push("workspace_path = ?"),s.push(o.workspacePath??null)),"lastActiveAt"in o&&(e.push("last_active_at = ?"),s.push(o.lastActiveAt??null)),"toolsFingerprint"in o&&(e.push("tools_fingerprint = ?"),s.push(o.toolsFingerprint??null)),e.length!==0&&(Ct(),s.push(1),r.prepare(`UPDATE server_state SET ${e.join(", ")} WHERE id = ?`).run(...s))}function Ue(o){be({sdkSessionId:o,lastActiveAt:Date.now()})}function ta(){be({sdkSessionId:void 0,lastActiveAt:Date.now()})}function sa(o){be({workspacePath:o})}ns();Ee();cs();import{z as p}from"zod/v4";import{v4 as ra}from"uuid";fs();Ka();import{rmSync as wn,existsSync as At}from"fs";var aa=p.object({model:p.string().optional(),effort:p.enum(["low","medium","high","max"]).optional(),maxTurns:p.number().optional()}),na=p.object({path:p.string(),mode:p.enum(["ro","rw"]).default("rw"),inheritPlugins:p.boolean().optional(),inheritMcp:p.boolean().optional(),inheritPermissions:p.boolean().optional()}),Cn=p.string().max(256).regex(/^[A-Za-z_][A-Za-z0-9_]*$/,"Env var key must match POSIX format: [A-Za-z_][A-Za-z0-9_]*").check(p.refine(o=>!o.startsWith("ANTHROPIC_"),"ANTHROPIC_* keys are managed globally in Settings")),oa=p.record(Cn,p.string().max(4096)).optional().check(p.refine(o=>!o||Object.keys(o).length<=100,"Maximum 100 environment variables per role")),ia=p.object({id:p.string().min(1),targets:p.array(p.string().min(1)).optional()}),An=p.object({name:p.string().min(1,"name is required").regex(/^[\p{L}\p{N}_-]+$/u,"name must contain only letters, numbers, underscores, or hyphens"),cagPrompt:p.string().optional(),learnedRules:p.array(p.string()).optional(),allowedTools:p.array(p.string()).optional(),disallowedTools:p.array(p.string()).optional(),evaluationCriteria:p.record(p.string(),p.number()).optional(),executionMode:p.enum(["isolated","inline"]).optional(),model:p.string().optional(),maxBudgetUsd:p.number().optional(),approvalRequired:p.array(p.string()).optional(),preferences:aa.optional(),additionalDirectories:p.array(na).optional(),allowedChannels:p.array(p.string()).optional(),inheritUserSettings:p.boolean().optional(),envVars:oa,osCapabilities:p.array(ia).optional()}),Pn=p.object({name:p.string().min(1).optional(),cagPrompt:p.string().optional(),learnedRules:p.array(p.string()).optional(),status:p.enum(["active","inactive","retired"]).optional(),allowedTools:p.array(p.string()).optional(),disallowedTools:p.array(p.string()).optional(),evaluationCriteria:p.record(p.string(),p.number()).optional(),executionMode:p.enum(["isolated","inline"]).optional(),model:p.string().optional(),maxBudgetUsd:p.number().optional(),approvalRequired:p.array(p.string()).optional(),preferences:aa.optional(),additionalDirectories:p.array(na).optional(),permissionMode:p.enum(["default","acceptEdits","dontAsk","bypassPermissions","plan","auto"]).optional(),allowedBashPatterns:p.array(p.string()).optional(),deniedBashPatterns:p.array(p.string()).optional(),allowedChannels:p.array(p.string()).nullable().optional(),inheritUserSettings:p.boolean().optional(),envVars:oa,osCapabilities:p.array(ia).optional()}),We=p.object({id:p.string().min(1)}),_n=p.object({status:p.enum(["active","inactive","retired"]).optional(),limit:p.coerce.number().min(1).max(1e3).optional(),offset:p.coerce.number().min(0).default(0)}),En=p.object({path:p.string().min(1)});async function ca(o){o.get("/roles",{schema:{tags:["Roles"],summary:"List all roles",description:"List all roles with optional status filter and pagination.",querystring:{type:"object",properties:{status:{type:"string",enum:["active","inactive","retired"]},limit:{type:"integer",minimum:1,maximum:1e3},offset:{type:"integer",minimum:0,default:0}}}}},async(r,e)=>{let s=_n.safeParse(r.query);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let{status:t,limit:a,offset:n}=s.data;return{roles:fe(t,a,n).map(c=>({...c,workspacePath:re(c.name)}))}}),o.post("/roles",{schema:{tags:["Roles"],summary:"Create a role",description:"Create a new role with a name, CAG prompt, and optional preferences.",body:{type:"object",required:["name"],properties:{name:{type:"string",minLength:1},cagPrompt:{type:"string"},preferences:{type:"object",properties:{model:{type:"string"},effort:{type:"string",enum:["low","medium","high","max"]},maxTurns:{type:"number"}}}}}}},async(r,e)=>{let s=An.safeParse(r.body);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let{name:t,cagPrompt:a,learnedRules:n,allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:u,maxBudgetUsd:f,approvalRequired:T,preferences:y,additionalDirectories:g,allowedChannels:P,inheritUserSettings:G,envVars:ie,osCapabilities:Y}=s.data;if(nt(t))return e.status(409).send({code:"CONFLICT",message:`Role with name '${t}' already exists`});let X;try{X=rt(Y)}catch($){return e.status(400).send({code:"VALIDATION_ERROR",message:$ instanceof Error?$.message:String($)})}let C={id:`role-${ra().slice(0,8)}`,name:t,cagPrompt:a??"",learnedRules:n??[],memoryStreamId:`mem-${ra().slice(0,8)}`,status:"active",preferences:y??{},allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:u,maxBudgetUsd:f,approvalRequired:T,additionalDirectories:g,allowedChannels:P,inheritUserSettings:G,envVars:ie,osCapabilities:X,createdAt:Date.now()};return at(C),ct(C),e.status(201).send({role:C})}),o.get("/roles/:id",{schema:{tags:["Roles"],summary:"Get role by ID",description:"Retrieve a single role with its project-scope plugins.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=We.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=L(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let a=re(t.name),n=Fe({scope:"project",projectPath:a});return{role:t,projectPlugins:n,workspacePath:a}}),o.get("/roles/:id/scores",{schema:{tags:["Roles"],summary:"Get role quality scores",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:100,default:20}}}}},async(r,e)=>{let s=p.object({id:p.string().min(1)}).safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=L(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let a=r.query.limit??20,n=Ds(t.id,a),i=js(t.id);return{scores:n,latestEma:i??null}}),o.patch("/roles/:id",{schema:{tags:["Roles"],summary:"Update a role",description:"Partially update a role's CAG prompt, learned rules, status, or preferences.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{name:{type:"string",minLength:1},cagPrompt:{type:"string"},learnedRules:{type:"array",items:{type:"string"}},status:{type:"string",enum:["active","inactive","retired"]},permissionMode:{type:"string",enum:["default","acceptEdits","dontAsk","bypassPermissions","plan","auto"]},allowedBashPatterns:{type:"array",items:{type:"string"}},deniedBashPatterns:{type:"array",items:{type:"string"}},preferences:{type:"object",properties:{model:{type:"string"},effort:{type:"string",enum:["low","medium","high","max"]},maxTurns:{type:"number"}}}}}}},async(r,e)=>{let s=We.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=Pn.safeParse(r.body);if(!t.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(t.error)});if(!L(s.data.id))return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let{allowedChannels:n,osCapabilities:i,...c}=t.data,l={...c,updatedAt:Date.now()};if(n!==void 0&&(l.allowedChannels=n??void 0),i!==void 0)try{l.osCapabilities=rt(i)}catch(u){return e.status(400).send({code:"VALIDATION_ERROR",message:u instanceof Error?u.message:String(u)})}if(_e(s.data.id,l),t.data.cagPrompt!==void 0||t.data.learnedRules!==void 0){let u=L(s.data.id);if(u){let f=re(u.name);At(f)&&dt(f,u)}}let d=L(s.data.id);if(d&&(t.data.allowedTools!==void 0||t.data.disallowedTools!==void 0)){let u=re(d.name);At(u)&&pt(d.id,d.allowedTools,u)}return{role:d}}),o.delete("/roles/:id",{schema:{tags:["Roles"],summary:"Delete a role",description:"Delete a role and its workspace.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=We.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=L(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});if(t.id===ds)return e.status(403).send({code:"FORBIDDEN",message:"System role 'chat-manager' cannot be deleted"});let a=re(t.name);if(At(a))try{wn(a,{recursive:!0,force:!0})}catch{}return ot(s.data.id),{roleId:s.data.id,deleted:!0}}),o.post("/roles/:id/scan-directory",{schema:{tags:["Roles"],summary:"Scan directory for plugin/permission configuration",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",required:["path"],properties:{path:{type:"string",minLength:1}}}}},async(r,e)=>{let s=We.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(s.error)});let t=En.safeParse(r.body);if(!t.success)return e.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(t.error)});if(!L(s.data.id))return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=ys(t.data.path);return{path:t.data.path,enabledPlugins:n.enabledPlugins,mcpServers:n.mcpServers,allowedTools:n.allowedTools,disallowedTools:n.disallowedTools}}),o.get("/roles/:id/env-diff",{schema:{tags:["Roles"],summary:"Get role env diff",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=L(r.params.id);return s?{diffs:os(s.name,s.envVars),envFileExists:it(s.name)!==null}:e.status(404).send({code:"NOT_FOUND",message:"Role not found"})}),o.post("/roles/:id/sync-to-env",{schema:{tags:["Roles"],summary:"Sync role env to .env file",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=L(r.params.id);return s?{success:!0,changed:is(s.name,s.envVars)}:e.status(404).send({code:"NOT_FOUND",message:"Role not found"})}),o.post("/roles/:id/load-from-env",{schema:{tags:["Roles"],summary:"Load role env from .env file",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=L(r.params.id);if(!s)return e.status(404).send({code:"NOT_FOUND",message:"Role not found"});let t=it(s.name);if(!t)return e.status(400).send({code:"NOT_FOUND",message:".env file not found in role workspace"});let a={};for(let[n,i]of Object.entries(t))n.startsWith("ANTHROPIC_")||(a[n]=i);return _e(s.id,{envVars:Object.keys(a).length>0?a:void 0,updatedAt:Date.now()}),{success:!0,updated:Object.keys(a).length}})}ge();import{z as da}from"zod/v4";import{readdirSync as On,existsSync as Fn}from"fs";import{join as Pt,resolve as pa,sep as ua}from"path";import{homedir as xn}from"os";var Dn=20,jn=da.object({prefix:da.string()});function ma(o){return o.startsWith("~/")?Pt(xn(),o.slice(2)):o}function la(o){let r=pa(o);for(let e of Ht){let s=ma(e),t=pa(s);if(r===t||r.startsWith(t+ua))return!0}return!1}async function ga(o){o.get("/fs/suggest-dirs",{schema:{tags:["FS"],summary:"Suggest directory completions",description:"Return directory suggestions matching a given path prefix.",querystring:{type:"object",required:["prefix"],properties:{prefix:{type:"string"}}}}},async(r,e)=>{let s=jn.safeParse(r.query);if(!s.success)return{suggestions:[]};let{prefix:t}=s.data;if(!t.startsWith("/")&&!t.startsWith("~/"))return{suggestions:[]};if(la(t))return{suggestions:[]};let a=ma(t),n,i;if(t.endsWith("/"))n=a,i="";else{let g=Math.max(a.lastIndexOf("/"),a.lastIndexOf(ua));if(g<0)return{suggestions:[]};n=a.slice(0,g+1),i=a.slice(g+1)}if(!Fn(n))return{suggestions:[]};let c;try{c=On(n,{withFileTypes:!0}).filter(g=>g.isDirectory()).map(g=>g.name)}catch{return{suggestions:[]}}let l=i.toLowerCase(),d=c.filter(g=>g.toLowerCase().startsWith(l)),T=(i.startsWith(".")?d:d.filter(g=>!g.startsWith("."))).filter(g=>!la(Pt(n,g)));return T.sort((g,P)=>g.localeCompare(P,void 0,{sensitivity:"base"})),{suggestions:T.slice(0,Dn).map(g=>Pt(n,g))}})}import{z as w}from"zod/v4";Ee();import{v4 as Nn}from"uuid";var qn=w.object({roleId:w.string().min(1)}),Ln=w.object({roleId:w.string().min(1),prompt:w.string().min(1),topK:w.number().min(1).max(50).default(10)}),Mn=w.object({limit:w.coerce.number().min(1).max(200).default(50),offset:w.coerce.number().min(0).default(0)});function _t(o){return L(o)!==void 0}async function ya(o){o.get("/memories/:roleId",{schema:{tags:["Memories"],summary:"List role memories",description:"List all memories for a specific role with pagination. Embeddings are stripped from the response.",params:{type:"object",required:["roleId"],properties:{roleId:{type:"string"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}},response:R.memoryList}},async(s,t)=>{let a=qn.safeParse(s.params);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:w.prettifyError(a.error)});let n=a.data.roleId;if(!_t(n))return t.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let i=Mn.safeParse(s.query),{limit:c,offset:l}=i.success?i.data:{limit:50,offset:0},u=Ls(n,c,l).map(({embedding:f,...T})=>T);return{memories:u,count:u.length}}),o.post("/memories/query",{schema:{tags:["Memories"],summary:"Query role memories",description:"Query a role's memories using hybrid search (FTS5 + vector similarity) with Smallville-style scoring (recency, importance, relevance).",body:{type:"object",required:["roleId","prompt"],properties:{roleId:{type:"string",minLength:1,description:"The role whose memories to query"},prompt:{type:"string",minLength:1,description:"The search query"},topK:{type:"integer",minimum:1,maximum:50,default:10,description:"Number of results to return"}}},response:R.memoryQuery}},async(s,t)=>{let a=Ln.safeParse(s.body);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:w.prettifyError(a.error)});let{roleId:n,prompt:i,topK:c}=a.data;if(!_t(n))return t.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let d=(await gt(n,i,{topK:c})).map(({embedding:u,...f})=>f);return{memories:d,count:d.length}});let r=w.object({roleId:w.string().min(1),content:w.string().min(1),type:w.enum(["event","thought","reflection"]).default("thought"),keywords:w.array(w.string()).default([]),importance:w.number().min(1).max(5).default(3),tier:w.enum(["working","episodic","semantic"]).default("episodic")});o.post("/memories",{schema:{tags:["Memories"],summary:"Create memory",description:"Create a new memory for a role. Embedding is auto-generated from content.",body:{type:"object",required:["roleId","content"],properties:{roleId:{type:"string",minLength:1},content:{type:"string",minLength:1},type:{type:"string",enum:["event","thought","reflection"],default:"thought"},keywords:{type:"array",items:{type:"string"},default:[]},importance:{type:"integer",minimum:1,maximum:5,default:3},tier:{type:"string",enum:["working","episodic","semantic"],default:"episodic"}}},response:R.memoryCreated}},async(s,t)=>{let a=r.safeParse(s.body);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:w.prettifyError(a.error)});let{roleId:n,content:i,type:c,keywords:l,importance:d,tier:u}=a.data;if(!_t(n))return t.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let f;try{f=await ut(i)}catch{}let T=`mem-${Nn().slice(0,8)}`,y=Date.now();Ns({id:T,roleId:n,type:c,content:i,embedding:f,keywords:l,importance:d,sourceType:"manual",createdAt:y,lastAccessed:y,retrievedCount:0,tier:u??"episodic"});let g=je(T),{embedding:P,...G}=g;return t.status(201).send({memory:G})});let e=w.object({content:w.string().min(1).optional(),type:w.enum(["event","thought","reflection"]).optional(),keywords:w.array(w.string()).optional(),importance:w.number().min(1).max(5).optional()});o.patch("/memories/:id",{schema:{tags:["Memories"],summary:"Update memory",description:"Update a memory's content, type, keywords, or importance. Embedding is regenerated if content changes.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{content:{type:"string",minLength:1},type:{type:"string",enum:["event","thought","reflection"]},keywords:{type:"array",items:{type:"string"}},importance:{type:"integer",minimum:1,maximum:5}}},response:R.memoryUpdated}},async(s,t)=>{let{id:a}=s.params;if(!je(a))return t.status(404).send({code:"NOT_FOUND",message:"Memory not found"});let i=e.safeParse(s.body);if(!i.success)return t.status(400).send({code:"VALIDATION_ERROR",message:w.prettifyError(i.error)});let c=i.data,l,d=!0;if(c.content)try{l=await ut(c.content)}catch{d=!1}let u=qs(a,{content:c.content,embedding:l,keywords:c.keywords,importance:c.importance,type:c.type});return{memoryId:a,updated:u,embeddingUpdated:d}}),o.delete("/memories/:id",{schema:{tags:["Memories"],summary:"Delete memory",description:"Delete a memory by ID.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:R.memoryDeleted}},async(s,t)=>{let{id:a}=s.params;return je(a)?(Ms(a),{memoryId:a,deleted:!0}):t.status(404).send({code:"NOT_FOUND",message:"Memory not found"})})}import{query as Vn}from"@anthropic-ai/claude-agent-sdk";import{v4 as oe}from"uuid";function Bn(){try{return O().defaults.maxBudgetUsd}catch{return 5}}function Et(o){return`# ChatManager \u2014 User Interface Agent
3
3
 
4
4
  You are the primary interface between the user and the goal-driven autonomous system.
5
5
  You have access to a persistent conversation session and the adam-tools MCP server.
@@ -29,7 +29,7 @@ When the user asks what you can do or asks for help, call **get_capabilities** t
29
29
 
30
30
  ## Current Context
31
31
  - Time: ${new Date(o.currentTime).toISOString()}
32
- - Platform budget per task: $${An()} (change via update_config with key "defaults.maxBudgetUsd")
32
+ - Platform budget per task: $${Bn()} (change via update_config with key "defaults.maxBudgetUsd")
33
33
  - All config is stored in the database. adam.config.yaml is deprecated and NOT loaded at runtime.
34
34
  - Role budget: if a Role has maxBudgetUsd set (> 0), the effective budget is min(role budget, platform budget). If 0 or unset, the platform budget applies.
35
35
 
@@ -45,6 +45,13 @@ conflict, treat the [Session context] as authoritative (it reflects the latest D
45
45
  - Saying "\u5DF2\u8BBE\u7F6E", "\u5DF2\u521B\u5EFA", "\u5DF2\u53D1\u9001", "done", "completed" without a preceding successful tool call is FORBIDDEN.
46
46
  - This rule has NO exceptions. Even if you are confident about what to do, call the tool first, confirm after.
47
47
 
48
+ ## Role dispatch (HARD FLOW \u2014 no exceptions)
49
+ - **Step 1**: Translate the user's request into a structured TaskRequirements object: which tools, which file paths (absolute, with ro/rw), which OS capabilities the task needs.
50
+ - **Step 2**: If you cannot produce clear requirements (user's ask is ambiguous, no paths given but the task needs to write files, etc.), **ASK THE USER**. Do NOT dispatch.
51
+ - **Step 3**: Call list_roles(requirements) \u2014 you get a ranked candidate list with fitScore, matched/missing capabilities, and warnings.
52
+ - **Step 4**: Call dispatch_task(requirements, roleId) with the top-ranked role's id. If admission fails (e.g., ROLE_PATH_SCOPE_MISMATCH), tell the user what's missing and which roles would fit \u2014 do not silently retry.
53
+ - When admission returns warnings (e.g., APPROVAL_WILL_TRIGGER), proactively tell the user "this task will trigger N approval prompts because role X requires approval for tool Y" so they know what to expect.
54
+
48
55
  ## Decision Principles
49
56
  - Answer simple questions directly from state (no task needed)
50
57
  - For ANY work request that needs external data (weather, news, web content, file operations, code execution): ALWAYS use dispatch_task. Do NOT tell the user "I can't do this" \u2014 dispatch_task delegates to workers that CAN do it.
@@ -53,10 +60,9 @@ conflict, treat the [Session context] as authoritative (it reflects the latest D
53
60
  - Task lifecycle messages include: task started, approval needed, task completed, task failed. Respond naturally to each (e.g., "\u5929\u6C14\u67E5\u8BE2\u4EFB\u52A1\u5DF2\u542F\u52A8" / "\u4EFB\u52A1\u9700\u8981\u4F60\u7684\u6388\u6743" / "\u67E5\u8BE2\u5B8C\u6210\uFF0C\u7ED3\u679C\u5982\u4E0B").
54
61
  - Task completion delivery is automatic: reportTo targets receive your composed status message; deliverTo targets receive the full result. Do NOT call send_to_channel for task lifecycle events.
55
62
  - NEVER say "I don't have the ability to..." \u2014 use dispatch_task instead. The workers have WebSearch, WebFetch, Bash, and all standard tools.
56
- - **Role selection**: Before dispatching, call list_roles to discover available roles and their full capabilities (allowedTools, plugins with skills/agents). Match the task to the role whose plugin skills best fit the work. Pass the matching role's id as roleId to dispatch_task. Never dispatch without a roleId unless no role matches the task.
57
63
 
58
64
  ## Decision Patterns
59
- - Simple task request \u2192 list_roles \u2192 pick best role \u2192 dispatch_task with roleId
65
+ - Simple task request \u2192 list_roles(requirements) \u2192 pick top-ranked role \u2192 dispatch_task(requirements, roleId)
60
66
  - Multi-role workflow ("A does X, then B does Y") \u2192 list_roles \u2192 dispatch_workflow with per-step roleId. Each step is a complete task; use {{stepId.result}} to pass data between steps. Steps without dependencies run in parallel automatically.
61
67
  - Complex multi-step request \u2192 create_goal \u2192 decompose_goal
62
68
  - Recurring/scheduled request ("every day", "weekly", "\u6BCF\u5C0F\u65F6") \u2192 create_template with cron
@@ -74,16 +80,16 @@ conflict, treat the [Session context] as authoritative (it reflects the latest D
74
80
  ## Conversation Coherence
75
81
  When task completion notifications arrive, incorporate the results naturally into your conversation.
76
82
  For example, if the user asked "run a report" and Task xyz completed, summarize the result for the user.
77
- `}function Pn(o){return o.map(r=>`${r.role==="user"?"User":"Assistant"}: ${r.content}`).join(`
78
- `)}function _n(o){return o.map(r=>`Memory [${r.tier??"episodic"}]: ${r.content} (importance: ${r.importance})`).join(`
79
- `)}async function da(o,r){let e=es(),s=fs(o,e.maxSessionTurns),t=Pn(s),a="";try{let i=await Es(void 0,r,["semantic","working"],{topK:5});i.length>0&&(a=_n(i))}catch{}let n=[];return t&&n.push(`[Session context \u2014 last ${e.maxSessionTurns} turns]
83
+ `}function Un(o){return o.map(r=>`${r.role==="user"?"User":"Assistant"}: ${r.content}`).join(`
84
+ `)}function Wn(o){return o.map(r=>`Memory [${r.tier??"episodic"}]: ${r.content} (importance: ${r.importance})`).join(`
85
+ `)}async function fa(o,r){let e=es(),s=Es(o,e.maxSessionTurns),t=Un(s),a="";try{let i=await Bs(void 0,r,["semantic","working"],{topK:5});i.length>0&&(a=Wn(i))}catch{}let n=[];return t&&n.push(`[Session context \u2014 last ${e.maxSessionTurns} turns]
80
86
  ${t}`),a&&n.push(`[Relevant memories \u2014 from Memory system]
81
87
  ${a}`),n.push(`[Current message]
82
88
  User: ${r}`),n.join(`
83
89
 
84
- `)}ge();Y();var x=q("chat-manager"),Fn=O,ve=class{sessionId;adamToolsInstance=null;running=!1;processing=!1;messageQueue=[];lastActivityAt=Date.now();consecutiveStaleCount=0;subscribed=!1;activeChatSessionId;activeChatSource;taskOriginMap=new Map;constructor(r){this.sessionId=r}async start(){this.running||(this.running=!0,this.subscribeToEvents(),x.info("ChatManager started"))}stop(){this.running=!1,x.info("ChatManager stopped")}async handleMessage(r,e,s){return new Promise((t,a)=>{let n=e,i=s;this.messageQueue.push({content:r,chatSessionId:n,source:i,resolve:c=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,t(c)},reject:c=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,a(c)}}),this.processQueue()})}async processQueue(){if(this.processing||!this.running)return;let r=this.messageQueue.shift();if(r){this.activeChatSessionId=r.chatSessionId,this.activeChatSource=r.source,this.processing=!0;try{let e=await this.runQuery(r.content,r.chatSessionId);r.resolve(e)}catch(e){let s=e instanceof Error?e.message:String(e);if(s.includes("Prompt is too long")||s.includes("prompt is too long")){x.warn("Prompt too long \u2014 resetting session and retrying"),this.sessionId=void 0,Be(void 0);try{let t=await this.runQuery(r.content,r.chatSessionId);r.resolve(t)}catch(t){r.reject(t instanceof Error?t:new Error(String(t)))}}else r.reject(e instanceof Error?e:new Error(s))}finally{this.processing=!1,this.processQueue()}}}async runQuery(r,e){let s=_t({currentTime:Date.now()}),t=r;if(e)try{let d=await da(e,r);d&&d!==r&&(t=d)}catch(d){x.debug({error:d},"Session context enrichment failed, using raw message")}this.adamToolsInstance||(this.adamToolsInstance=ht());let a=vt({currentTaskId:void 0,roleId:"role-chat-manager"}),n=bt(d=>({disallowedTools:["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"]}));x.debug({hasApiKey:!!process.env.ANTHROPIC_API_KEY,hasResume:!!this.sessionId},"ChatManager SDK query starting");let i=["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"],c=En({prompt:t,options:{cwd:Fn,additionalDirectories:[process.cwd()],systemPrompt:s,resume:this.sessionId,maxTurns:50,maxBudgetUsd:F().defaults.maxBudgetUsd,disallowedTools:i,settingSources:["project"],mcpServers:{"adam-tools":this.adamToolsInstance},hooks:a,canUseTool:n,env:{...Wt(),ANTHROPIC_SMALL_FAST_MODEL:F().anthropic?.smallFastModel||process.env.ANTHROPIC_MODEL||""},stderr:d=>{d.trim()&&x.debug({stderr:d.trim().slice(0,500)},"ChatManager SDK stderr")}}}),l="";for await(let d of c){let m=d;x.debug({eventType:m.type,subtype:m.subtype},"ChatManager SDK event"),this.lastActivityAt=Date.now(),this.consecutiveStaleCount=0,m.session_id&&typeof m.session_id=="string"&&(this.sessionId=m.session_id,Be(this.sessionId)),m.type==="result"&&typeof m.result=="string"&&(l=m.result)}return l}subscribeToEvents(){this.subscribed||(this.subscribed=!0,y.on("task_created",r=>{this.activeChatSessionId&&this.activeChatSource&&(X(r.taskId,{sourceSessionId:this.activeChatSessionId}),this.taskOriginMap.set(r.taskId,{chatSessionId:this.activeChatSessionId,source:this.activeChatSource,createdAt:Date.now()}),x.debug({taskId:r.taskId,chatSessionId:this.activeChatSessionId},"Tracked task origin for result delivery"));let e=E(r.taskId);if(e?.parentId){let s=this.taskOriginMap.get(e.parentId),t=s?void 0:E(e.parentId),a=s?.chatSessionId??t?.sourceSessionId;a&&(X(r.taskId,{sourceSessionId:a}),s&&this.taskOriginMap.set(r.taskId,{...s}))}}),y.on("task_complete_event",r=>{this.handleTaskCompletion(r.taskId,r.result,r.error)}),y.on("task_status_change",r=>{let e=this.taskOriginMap.get(r.taskId);e&&r.newStatus==="running"&&this.handleTaskStatusReport(r.taskId,r.newStatus,e)}),y.on("plan_approval_request",r=>{let e=this.taskOriginMap.get(r.taskId);e&&this.handleTaskStatusReport(r.taskId,"approval_requested",e)}),setInterval(()=>{let r=Date.now()-864e5;for(let[e,s]of this.taskOriginMap)s.createdAt<r&&this.taskOriginMap.delete(e)},3600*1e3))}async handleTaskStatusReport(r,e,s){let t=E(r),n=(t?.roleId?await this.getRoleName(t.roleId):void 0)??r.slice(0,8),i=t?.prompt?.slice(0,1e3)??"",c;switch(e){case"running":c=`[System] Task "${n}" has started execution. Task prompt: "${i}". Compose a brief, natural status message for the user (1-2 sentences in the user's language). Do NOT call any tools \u2014 just output the message text.`;break;case"approval_requested":c=`[System] Task "${n}" needs user approval (privilege escalation). The approval request has been sent separately. Compose a brief notice for the user (1 sentence). Do NOT call any tools.`;break;default:return}let l={running:`\u4EFB\u52A1 ${n} \u5DF2\u542F\u52A8`,approval_requested:`\u4EFB\u52A1 ${n} \u9700\u8981\u6388\u6743`},d=!1,m=setTimeout(()=>{if(d)return;d=!0;let b=l[e]??`\u4EFB\u52A1 ${n}: ${e}`;this.deliverReport(s,r,b)},3e4);this.messageQueue.push({content:c,resolve:b=>{if(d)return;d=!0,clearTimeout(m);let v=b?.trim()||(l[e]??`\u4EFB\u52A1 ${n}: ${e}`);this.deliverReport(s,r,v)},reject:()=>{if(d)return;d=!0,clearTimeout(m);let b=l[e]??`\u4EFB\u52A1 ${n}: ${e}`;this.deliverReport(s,r,b)}}),this.processQueue()}deliverReport(r,e,s,t){let a={id:ne(),sessionId:r.chatSessionId,role:"assistant",content:s,source:r.source,taskId:e,createdAt:Date.now()};K(a),y.emit({type:"chat_message",sessionId:r.chatSessionId,message:a}),z(r.chatSessionId),r.source.type==="channel"&&r.source.channelId&&r.source.chatId&&this.deliverToChannel(r.source.channelId,r.source.chatId,s,"report",t)}async handleTaskCompletion(r,e,s){let t=E(r),a=this.taskOriginMap.get(r);if(!a&&t?.sourceSessionId){let f=B(t.sourceSessionId);f&&(a={chatSessionId:f.id,source:f.source,createdAt:t.createdAt})}let n=s?`\u4EFB\u52A1\u5931\u8D25: ${s}`:e??"",i=async(f,g)=>{try{let A=B(f);if(!A)return;K({id:ne(),sessionId:f,role:"assistant",content:g,source:A.source,taskId:r,createdAt:Date.now()}),z(f),y.emit({type:"chat_message",sessionId:f,message:{id:ne(),sessionId:f,role:"assistant",content:g,source:A.source,createdAt:Date.now()}})}catch(A){x.error({error:A,taskId:r,targetSession:f},"Failed to deliver to session")}},c=t?.roleId?await this.getRoleName(t.roleId):void 0,l=c?`${c}`:r.slice(0,8),d=s?`[System] Task "${l}" failed. Error: ${s.slice(0,1500)}. Compose a brief failure report for the user (2-3 sentences). Do NOT call any tools.`:`[System] Task "${l}" completed successfully. Result summary: ${(e??"").slice(0,4e3)}. Compose a brief completion report for the user (2-3 sentences, highlight key outcomes). Do NOT call any tools.`,m={success:`\u4EFB\u52A1\u5B8C\u6210 (${l})`,error:`\u4EFB\u52A1\u5931\u8D25 (${l})`},b=!1,v=setTimeout(()=>{if(b)return;b=!0;let f=s?m.error:m.success;if(a&&this.deliverReport(a,r,f,r),t?.reportTo&&t.reportTo.length>0)for(let g of t.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,f,"report",r):g.type==="session"&&g.sessionId&&i(g.sessionId,f)},3e4);if(this.messageQueue.push({content:d,resolve:f=>{if(b)return;b=!0,clearTimeout(v);let g=f?.trim()||(s?m.error:m.success);if(a&&this.deliverReport(a,r,g,r),t?.reportTo&&t.reportTo.length>0)for(let A of t.reportTo)A.type==="channel"&&A.channelId&&A.chatId?this.deliverToChannel(A.channelId,A.chatId,g,"report",r):A.type==="session"&&A.sessionId&&i(A.sessionId,g);a&&this.taskOriginMap.delete(r)},reject:()=>{if(b)return;b=!0,clearTimeout(v);let f=s?m.error:m.success;if(a&&this.deliverReport(a,r,f,r),t?.reportTo&&t.reportTo.length>0)for(let g of t.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,f,"report",r):g.type==="session"&&g.sessionId&&i(g.sessionId,f);a&&this.taskOriginMap.delete(r)}}),this.processQueue(),a||x.debug({taskId:r},"Task completed but no chat session origin tracked (may be API-created or template-triggered)"),t?.deliverTo&&t.deliverTo.length>0)for(let f of t.deliverTo)f.type==="channel"&&f.channelId&&f.chatId?this.deliverToChannel(f.channelId,f.chatId,n,"deliver",r):f.type==="session"&&f.sessionId&&await i(f.sessionId,n);else if(a?.source.type==="channel"&&a.source.channelId&&a.source.chatId){let g=n.length>4e3?n.slice(0,4e3)+`
90
+ `)}ge();Z();var x=q("chat-manager"),Gn=F,ve=class{sessionId;adamToolsInstance=null;running=!1;processing=!1;messageQueue=[];lastActivityAt=Date.now();consecutiveStaleCount=0;subscribed=!1;activeChatSessionId;activeChatSource;taskOriginMap=new Map;constructor(r){this.sessionId=r}async start(){this.running||(this.running=!0,this.subscribeToEvents(),x.info("ChatManager started"))}stop(){this.running=!1,x.info("ChatManager stopped")}async handleMessage(r,e,s){return new Promise((t,a)=>{let n=e,i=s;this.messageQueue.push({content:r,chatSessionId:n,source:i,resolve:c=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,t(c)},reject:c=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,a(c)}}),this.processQueue()})}async processQueue(){if(this.processing||!this.running)return;let r=this.messageQueue.shift();if(r){this.activeChatSessionId=r.chatSessionId,this.activeChatSource=r.source,this.processing=!0;try{let e=await this.runQuery(r.content,r.chatSessionId);r.resolve(e)}catch(e){let s=e instanceof Error?e.message:String(e);if(s.includes("Prompt is too long")||s.includes("prompt is too long")){x.warn("Prompt too long \u2014 resetting session and retrying"),this.sessionId=void 0,Ue(void 0);try{let t=await this.runQuery(r.content,r.chatSessionId);r.resolve(t)}catch(t){r.reject(t instanceof Error?t:new Error(String(t)))}}else r.reject(e instanceof Error?e:new Error(s))}finally{this.processing=!1,this.processQueue()}}}async runQuery(r,e){let s=Et({currentTime:Date.now()}),t=r;if(e)try{let d=await fa(e,r);d&&d!==r&&(t=d)}catch(d){x.debug({error:d},"Session context enrichment failed, using raw message")}this.adamToolsInstance||(this.adamToolsInstance=ht());let a=vt({currentTaskId:void 0,roleId:"role-chat-manager"}),n=bt(d=>({disallowedTools:["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"]}));x.debug({hasApiKey:!!process.env.ANTHROPIC_API_KEY,hasResume:!!this.sessionId},"ChatManager SDK query starting");let i=["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"],c=Vn({prompt:t,options:{cwd:Gn,additionalDirectories:[process.cwd()],systemPrompt:s,resume:this.sessionId,maxTurns:50,maxBudgetUsd:O().defaults.maxBudgetUsd,disallowedTools:i,settingSources:["project"],mcpServers:{"adam-tools":this.adamToolsInstance},hooks:a,canUseTool:n,env:{...Vt(),ANTHROPIC_SMALL_FAST_MODEL:O().anthropic?.smallFastModel||process.env.ANTHROPIC_MODEL||""},stderr:d=>{d.trim()&&x.debug({stderr:d.trim().slice(0,500)},"ChatManager SDK stderr")}}}),l="";for await(let d of c){let u=d;x.debug({eventType:u.type,subtype:u.subtype},"ChatManager SDK event"),this.lastActivityAt=Date.now(),this.consecutiveStaleCount=0,u.session_id&&typeof u.session_id=="string"&&(this.sessionId=u.session_id,Ue(this.sessionId)),u.type==="result"&&typeof u.result=="string"&&(l=u.result)}return l}subscribeToEvents(){this.subscribed||(this.subscribed=!0,h.on("task_created",r=>{this.activeChatSessionId&&this.activeChatSource&&(J(r.taskId,{sourceSessionId:this.activeChatSessionId}),this.taskOriginMap.set(r.taskId,{chatSessionId:this.activeChatSessionId,source:this.activeChatSource,createdAt:Date.now()}),x.debug({taskId:r.taskId,chatSessionId:this.activeChatSessionId},"Tracked task origin for result delivery"));let e=E(r.taskId);if(e?.parentId){let s=this.taskOriginMap.get(e.parentId),t=s?void 0:E(e.parentId),a=s?.chatSessionId??t?.sourceSessionId;a&&(J(r.taskId,{sourceSessionId:a}),s&&this.taskOriginMap.set(r.taskId,{...s}))}}),h.on("task_complete_event",r=>{this.handleTaskCompletion(r.taskId,r.result,r.error)}),h.on("task_status_change",r=>{let e=this.taskOriginMap.get(r.taskId);e&&r.newStatus==="running"&&this.handleTaskStatusReport(r.taskId,r.newStatus,e)}),h.on("plan_approval_request",r=>{let e=this.taskOriginMap.get(r.taskId);e&&this.handleTaskStatusReport(r.taskId,"approval_requested",e)}),setInterval(()=>{let r=Date.now()-864e5;for(let[e,s]of this.taskOriginMap)s.createdAt<r&&this.taskOriginMap.delete(e)},3600*1e3))}async handleTaskStatusReport(r,e,s){let t=E(r),n=(t?.roleId?await this.getRoleName(t.roleId):void 0)??r.slice(0,8),i=t?.prompt?.slice(0,1e3)??"",c;switch(e){case"running":c=`[System] Task "${n}" has started execution. Task prompt: "${i}". Compose a brief, natural status message for the user (1-2 sentences in the user's language). Do NOT call any tools \u2014 just output the message text.`;break;case"approval_requested":c=`[System] Task "${n}" needs user approval (privilege escalation). The approval request has been sent separately. Compose a brief notice for the user (1 sentence). Do NOT call any tools.`;break;default:return}let l={running:`\u4EFB\u52A1 ${n} \u5DF2\u542F\u52A8`,approval_requested:`\u4EFB\u52A1 ${n} \u9700\u8981\u6388\u6743`},d=!1,u=setTimeout(()=>{if(d)return;d=!0;let f=l[e]??`\u4EFB\u52A1 ${n}: ${e}`;this.deliverReport(s,r,f)},3e4);this.messageQueue.push({content:c,resolve:f=>{if(d)return;d=!0,clearTimeout(u);let T=f?.trim()||(l[e]??`\u4EFB\u52A1 ${n}: ${e}`);this.deliverReport(s,r,T)},reject:()=>{if(d)return;d=!0,clearTimeout(u);let f=l[e]??`\u4EFB\u52A1 ${n}: ${e}`;this.deliverReport(s,r,f)}}),this.processQueue()}deliverReport(r,e,s,t){let a={id:oe(),sessionId:r.chatSessionId,role:"assistant",content:s,source:r.source,taskId:e,createdAt:Date.now()};K(a),h.emit({type:"chat_message",sessionId:r.chatSessionId,message:a}),z(r.chatSessionId),r.source.type==="channel"&&r.source.channelId&&r.source.chatId&&this.deliverToChannel(r.source.channelId,r.source.chatId,s,"report",t)}async handleTaskCompletion(r,e,s){let t=E(r),a=this.taskOriginMap.get(r);if(!a&&t?.sourceSessionId){let y=B(t.sourceSessionId);y&&(a={chatSessionId:y.id,source:y.source,createdAt:t.createdAt})}let n=s?`\u4EFB\u52A1\u5931\u8D25: ${s}`:e??"",i=async(y,g)=>{try{let P=B(y);if(!P)return;K({id:oe(),sessionId:y,role:"assistant",content:g,source:P.source,taskId:r,createdAt:Date.now()}),z(y),h.emit({type:"chat_message",sessionId:y,message:{id:oe(),sessionId:y,role:"assistant",content:g,source:P.source,createdAt:Date.now()}})}catch(P){x.error({error:P,taskId:r,targetSession:y},"Failed to deliver to session")}},c=t?.roleId?await this.getRoleName(t.roleId):void 0,l=c?`${c}`:r.slice(0,8),d=s?`[System] Task "${l}" failed. Error: ${s.slice(0,1500)}. Compose a brief failure report for the user (2-3 sentences). Do NOT call any tools.`:`[System] Task "${l}" completed successfully. Result summary: ${(e??"").slice(0,4e3)}. Compose a brief completion report for the user (2-3 sentences, highlight key outcomes). Do NOT call any tools.`,u={success:`\u4EFB\u52A1\u5B8C\u6210 (${l})`,error:`\u4EFB\u52A1\u5931\u8D25 (${l})`},f=!1,T=setTimeout(()=>{if(f)return;f=!0;let y=s?u.error:u.success;if(a&&this.deliverReport(a,r,y,r),t?.reportTo&&t.reportTo.length>0)for(let g of t.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,y,"report",r):g.type==="session"&&g.sessionId&&i(g.sessionId,y)},3e4);if(this.messageQueue.push({content:d,resolve:y=>{if(f)return;f=!0,clearTimeout(T);let g=y?.trim()||(s?u.error:u.success);if(a&&this.deliverReport(a,r,g,r),t?.reportTo&&t.reportTo.length>0)for(let P of t.reportTo)P.type==="channel"&&P.channelId&&P.chatId?this.deliverToChannel(P.channelId,P.chatId,g,"report",r):P.type==="session"&&P.sessionId&&i(P.sessionId,g);a&&this.taskOriginMap.delete(r)},reject:()=>{if(f)return;f=!0,clearTimeout(T);let y=s?u.error:u.success;if(a&&this.deliverReport(a,r,y,r),t?.reportTo&&t.reportTo.length>0)for(let g of t.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,y,"report",r):g.type==="session"&&g.sessionId&&i(g.sessionId,y);a&&this.taskOriginMap.delete(r)}}),this.processQueue(),a||x.debug({taskId:r},"Task completed but no chat session origin tracked (may be API-created or template-triggered)"),t?.deliverTo&&t.deliverTo.length>0)for(let y of t.deliverTo)y.type==="channel"&&y.channelId&&y.chatId?this.deliverToChannel(y.channelId,y.chatId,n,"deliver",r):y.type==="session"&&y.sessionId&&await i(y.sessionId,n);else if(a?.source.type==="channel"&&a.source.channelId&&a.source.chatId){let g=n.length>4e3?n.slice(0,4e3)+`
85
91
 
86
- ... \u67E5\u770B\u5B8C\u6574\u7ED3\u679C\u8BF7\u8BBF\u95EE Web UI`:n;this.deliverToChannel(a.source.channelId,a.source.chatId,g,"deliver",r)}if(t?.parentId){let f=re(t.parentId);if(f){let g=fe(t.parentId);if(g.every(G=>G.status==="completed"||G.status==="failed")){let G=g.some(H=>H.status==="failed"),oe=G?"failed":"completed";De(t.parentId,{status:oe,updatedAt:Date.now()}),x.info({goalId:t.parentId,goalName:f.name,finalStatus:oe},"Goal completed");let ee=`${G?"\u274C":"\u2705"} \u76EE\u6807\u5B8C\u6210: ${f.name}
92
+ ... \u67E5\u770B\u5B8C\u6574\u7ED3\u679C\u8BF7\u8BBF\u95EE Web UI`:n;this.deliverToChannel(a.source.channelId,a.source.chatId,g,"deliver",r)}if(t?.parentId){let y=ae(t.parentId);if(y){let g=ye(t.parentId);if(g.every(G=>G.status==="completed"||G.status==="failed")){let G=g.some(X=>X.status==="failed"),ie=G?"failed":"completed";xe(t.parentId,{status:ie,updatedAt:Date.now()}),x.info({goalId:t.parentId,goalName:y.name,finalStatus:ie},"Goal completed");let Y=`${G?"\u274C":"\u2705"} \u76EE\u6807\u5B8C\u6210: ${y.name}
87
93
 
88
- ${g.length} \u4E2A\u5B50\u4EFB\u52A1\u5168\u90E8\u5B8C\u6210`;await this.routeGoalNotification(f,ee,t.parentId)}}}}async getRoleName(r){try{let{getRole:e}=await import("./roles-NYGWZMQI.js");return e(r)?.name}catch{return}}async deliverToChannel(r,e,s,t="reply",a){if(!r||!e){x.warn({channelId:r,chatId:e},"Cannot deliver to channel: missing channelId or chatId");return}try{let i=await Ws().send({taskId:a,channelId:r,chatId:e,content:s,messageType:t});i.success?x.info({channelId:r,chatId:e.slice(0,12),messageType:t,taskId:a?.slice(0,8),messageId:i.messageId},"Delivered notification to channel"):x.warn({channelId:r,chatId:e.slice(0,12),messageType:t,taskId:a?.slice(0,8),error:i.error},"Channel delivery failed")}catch(n){x.error({error:n,channelId:r,chatId:e.slice(0,12)},"Failed to deliver to channel")}}async routeGoalNotification(r,e,s){let t=r.deliverTo??[],a=r.sourceSessionId;if(!(t.length===0&&!a)){for(let n of t)if(n.type==="session")try{let i=B(n.sessionId);i&&(K({id:ne(),sessionId:n.sessionId,role:"assistant",content:e,source:i.source,createdAt:Date.now()}),z(n.sessionId),y.emit({type:"chat_message",sessionId:n.sessionId,message:{id:ne(),sessionId:n.sessionId,role:"assistant",content:e,source:i.source,createdAt:Date.now()}}))}catch(i){x.error({error:i,goalId:s,targetSession:n.sessionId},"Failed to deliver Goal notification to session")}else n.type==="channel"&&await this.deliverToChannel(n.channelId,n.chatId??"",e);if(a&&!t.some(n=>n.type==="session"&&n.sessionId===a))try{let n=B(a);n&&(K({id:ne(),sessionId:a,role:"assistant",content:e,source:n.source,createdAt:Date.now()}),z(a),y.emit({type:"chat_message",sessionId:a,message:{id:ne(),sessionId:a,role:"assistant",content:e,source:n.source,createdAt:Date.now()}}))}catch(n){x.error({error:n,goalId:s,sessionId:a},"Failed to deliver Goal notification to source session")}}}getLastActivityAt(){return this.lastActivityAt}getConsecutiveStaleCount(){return this.consecutiveStaleCount}isHealthy(){return this.running}async restartSession(){x.warn("Restarting ChatManager session (Watchdog triggered)"),this.consecutiveStaleCount++,this.sessionId=void 0,Be(void 0)}};import{v4 as Et}from"uuid";Y();var Ft=q("message-handler");async function On(o,r){if(!(await import("./config-XMQS2NPT.js").then(t=>t.getChatConfig())).autoTitle)return;let s=["Generate a very short title (max 50 characters) for a chat session that started with this message:",`"${r.slice(0,200)}"`,"Respond with only the title, no quotes or explanation."].join(`
89
- `);try{let a=(await sr(s,"You are a concise title generator. Reply with only the title, max 50 characters.")).trim().slice(0,50);a.length>0&&bs(o,{title:a})}catch{}}var Ot=null;function pa(o){Ot=o}async function We(o,r,e,s){let t;s&&(t=B(s)),t||(t=Qs(r)),t||(t=Ne(r,e));let a=Et(),n={id:a,sessionId:t.id,role:"user",content:o,source:r,createdAt:Date.now()};if(K(n),y.emit({type:"chat_message",sessionId:t.id,message:n}),t.messageCount===0&&On(t.id,o),z(t.id),yt(t.id),Ot){let i=t.id,c=t.source;(async()=>{try{let l=await Ot.handleMessage(o,i,r),d={id:Et(),sessionId:i,role:"assistant",content:l,source:r,createdAt:Date.now()};K(d),y.emit({type:"chat_message",sessionId:i,message:d}),z(i),yt(i),c.type==="channel"&&c.channelId&&c.chatId&&(Ft.info({sessionId:i,sourceType:c.type,hasChannelId:!!c.channelId,hasResponse:!!l},"Chat response ready, checking channel delivery"),xn(c.channelId,c.chatId,l))}catch(l){(await import("./logger-QCJUU7GV.js")).getLogger("message-handler").error({error:l,sessionId:i},"ChatManager response failed");let m={id:Et(),sessionId:i,role:"assistant",content:`\u26A0\uFE0F \u5904\u7406\u5931\u8D25: ${l instanceof Error?l.message:String(l)}`,source:r,createdAt:Date.now()};K(m),y.emit({type:"chat_message",sessionId:i,message:m}),z(i)}})()}return{sessionId:t.id,messageId:a}}async function xn(o,r,e){Ft.info({channelId:o,chatId:r.slice(0,12)},"Delivering chat response to channel");try{let{getOutboundGateway:s}=await import("./outbound-gateway-GGFMU5JW.js");await s().send({channelId:o,chatId:r,content:e,messageType:"reply"})}catch(s){Ft.error({error:s,channelId:o,chatId:r.slice(0,12)},"Channel delivery failed (non-fatal)")}}import{z as h}from"zod/v4";import{v4 as Dn}from"uuid";var ua=h.union([h.object({type:h.literal("session"),sessionId:h.string()}),h.object({type:h.literal("channel"),channelId:h.string(),chatId:h.string().optional()})]),jn=h.object({id:h.string(),prompt:h.string(),dependsOn:h.array(h.string()).optional(),outputAs:h.string().optional(),roleId:h.string().optional(),config:h.object({timeout:h.number().optional(),maxTurns:h.number().optional()}).optional()}),Nn=h.object({type:h.enum(["cron","manual","event","once"]),cron:h.string().optional(),event:h.string().optional(),runAt:h.string().optional()}),xt=h.object({name:h.string().min(1),description:h.string().optional(),trigger:Nn,steps:h.array(jn).min(1),rolePreference:h.string().optional(),config:h.record(h.string(),h.unknown()).optional(),enabled:h.boolean().default(!0),goalIds:h.array(h.string()).optional(),deliverTo:h.array(ua).optional(),reportTo:h.array(ua).optional()}),xc=xt.transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),qn=xt.partial().transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Ve=h.object({id:h.string().min(1)});async function ma(o,r){o.post("/task-templates",{schema:{tags:["Templates"],summary:"Create a task template",description:"Create a new task template with trigger (cron/manual/event) and execution steps. Cron-triggered templates are automatically scheduled.",body:{type:"object",required:["name","trigger","steps"],properties:{name:{type:"string",minLength:1},description:{type:"string"},trigger:{type:"object",required:["type"],properties:{type:{type:"string",enum:["cron","manual","event","once"]},cron:{type:"string",description:"Cron expression (required when type is cron)"},event:{type:"string",description:"Event name (required when type is event)"},runAt:{type:"string",description:"ISO 8601 timestamp (required when type is once)"}}},steps:{type:"array",minItems:1,items:{type:"object",required:["id","prompt"],properties:{id:{type:"string"},prompt:{type:"string"},dependsOn:{type:"array",items:{type:"string"}},outputAs:{type:"string"},roleId:{type:"string",description:"Role ID for this step (overrides template rolePreference)"},config:{type:"object",properties:{timeout:{type:"number",description:"Step-level timeout override (seconds)"},maxTurns:{type:"number",description:"Step-level maxTurns override"}}}}}},rolePreference:{type:"string"},config:{type:"object",additionalProperties:!0},enabled:{type:"boolean",default:!0},goalIds:{type:"array",items:{type:"string"}},deliverTo:{type:"array",items:{type:"object"}},reportTo:{type:"array",items:{type:"object"}}}},response:I.templateCreated}},async(e,s)=>{let t=xt.safeParse(e.body);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:h.prettifyError(t.error)});let a={id:Dn(),...t.data,createdAt:Date.now()};return Fs(a),a.enabled&&a.trigger.type==="cron"&&a.trigger.cron?await r.scheduleJob(a.id):a.enabled&&a.trigger.type==="once"&&a.trigger.runAt&&r.scheduleOnceJob(a.id),s.status(201).send({templateId:a.id})}),o.get("/task-templates",{schema:{tags:["Templates"],summary:"List task templates",description:"List all task templates, optionally filtering to enabled-only.",querystring:{type:"object",properties:{enabled:{type:"string",enum:["true","false"],description:"Filter to enabled templates only when 'true'"}}},response:I.templateList}},async e=>{let t=e.query.enabled==="true";return{templates:xs(t)}}),o.get("/task-templates/:id",{schema:{tags:["Templates"],summary:"Get task template by ID",description:"Retrieve a single task template by its ID.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:I.templateDetail}},async(e,s)=>{let t=Ve.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:h.prettifyError(t.error)});let a=Z(t.data.id);return a?{template:a}:s.status(404).send({code:"NOT_FOUND",message:"Template not found"})}),o.patch("/task-templates/:id",{schema:{tags:["Templates"],summary:"Update a task template",description:"Partially update a task template. Cron schedules are automatically rescheduled if the trigger changes.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{name:{type:"string",minLength:1},description:{type:"string"},trigger:{type:"object",properties:{type:{type:"string",enum:["cron","manual","event","once"]},cron:{type:"string"},event:{type:"string"},runAt:{type:"string"}}},steps:{type:"array",items:{type:"object"}},rolePreference:{type:"string"},config:{type:"object",additionalProperties:!0},enabled:{type:"boolean"},goalIds:{type:"array",items:{type:"string"}},deliverTo:{type:"array",items:{type:"object"}},reportTo:{type:"array",items:{type:"object"}}}},response:I.templateUpdated}},async(e,s)=>{let t=Ve.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:h.prettifyError(t.error)});let a=qn.safeParse(e.body);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:h.prettifyError(a.error)});if(!Z(t.data.id))return s.status(404).send({code:"NOT_FOUND",message:"Template not found"});Os(t.data.id,a.data),await r.unscheduleJob(t.data.id);let i=Z(t.data.id);return i?.enabled&&i.trigger.type==="cron"&&i.trigger.cron?await r.scheduleJob(i.id):i?.enabled&&i.trigger.type==="once"&&i.trigger.runAt&&r.scheduleOnceJob(i.id),{templateId:t.data.id}}),o.delete("/task-templates/:id",{schema:{tags:["Templates"],summary:"Delete a task template",description:"Delete a task template by ID. Cron jobs are automatically unscheduled.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:I.templateDeleted}},async(e,s)=>{let t=Ve.safeParse(e.params);return t.success?Z(t.data.id)?(await r.unscheduleJob(t.data.id),Ds(t.data.id),{templateId:t.data.id,deleted:!0}):s.status(404).send({code:"NOT_FOUND",message:"Template not found"}):s.status(400).send({code:"VALIDATION_ERROR",message:h.prettifyError(t.error)})}),o.post("/task-templates/:id/run",{schema:{tags:["Templates"],summary:"Run a task template",description:"Manually trigger execution of a task template regardless of its trigger type.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:I.templateRun}},async(e,s)=>{let t=Ve.safeParse(e.params);return t.success?Z(t.data.id)?{executionId:await r.runNow(t.data.id),status:"started"}:s.status(404).send({code:"NOT_FOUND",message:"Template not found"}):s.status(400).send({code:"VALIDATION_ERROR",message:h.prettifyError(t.error)})})}import{z as _}from"zod/v4";Ss();var Dt=_.object({id:_.string().min(1)}),Ln=_.object({scope:_.enum(["user","project"]).optional(),cwd:_.string().optional()}),Mn=_.object({scope:_.enum(["user","project"]).optional(),cwd:_.string().optional()});async function ga(o){o.get("/plugins",{schema:{tags:["Plugins"],summary:"List all installed plugins",querystring:{type:"object",properties:{scope:{type:"string",enum:["user","project","local"]}}}}},async e=>{let s=e.query,t=Oe({scope:s.scope}),a=mt();return{plugins:t.map(n=>({...n,globalEnabled:a[n.id]??n.enabled}))}}),o.get("/plugins/:id",{schema:{tags:["Plugins"],summary:"Get plugin by ID",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(e,s)=>{let t=Dt.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)});let a=ks(t.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Plugin not found"});let n=Is(a.installPath),i=mt();return{plugin:{...a,globalEnabled:i[a.id]??a.enabled,manifest:n}}}),o.post("/plugins/:id/enable",{schema:{tags:["Plugins"],summary:"Enable a plugin globally",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(e,s)=>{let t=Dt.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)});if(!de())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return ur(t.data.id),{pluginId:t.data.id,enabled:!0}}catch(a){return s.status(500).send({code:"CLI_ERROR",message:a instanceof Error?a.message:"Enable failed"})}}),o.post("/plugins/:id/disable",{schema:{tags:["Plugins"],summary:"Disable a plugin globally",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(e,s)=>{let t=Dt.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)});if(!de())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return mr(t.data.id),{pluginId:t.data.id,enabled:!1}}catch(a){return s.status(500).send({code:"CLI_ERROR",message:a instanceof Error?a.message:"Disable failed"})}}),o.get("/plugins/stats",{schema:{tags:["Plugins"],summary:"Get plugin usage statistics",querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50}}}}},async e=>{let s=e.query;return{stats:Tr(s.limit??50)}});let r=_.object({roleId:_.string().min(1)});o.get("/plugins/stats/role/:roleId",{schema:{tags:["Plugins"],summary:"Get plugin usage by role",params:{type:"object",required:["roleId"],properties:{roleId:{type:"string"}}}}},async(e,s)=>{let t=r.safeParse(e.params);return t.success?{roleId:t.data.roleId,stats:kr(t.data.roleId)}:s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)})}),o.get("/plugins/marketplace",{schema:{tags:["Marketplace"],summary:"List available marketplace plugins"}},async(e,s)=>{if(!de())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found. Install Claude Code to use marketplace features."});try{let t=dr();return{available:t.available,installed:t.installed}}catch(t){return s.status(500).send({code:"CLI_ERROR",message:t instanceof Error?t.message:"CLI command failed"})}}),o.get("/plugins/marketplaces",{schema:{tags:["Marketplace"],summary:"List known marketplace sources"}},async()=>({sources:Ts()})),o.post("/plugins/install/:name",{schema:{tags:["Marketplace"],summary:"Install a plugin",params:{type:"object",required:["name"],properties:{name:{type:"string"}}},body:{type:"object",properties:{scope:{type:"string",enum:["user","project"]},cwd:{type:"string"}}}}},async(e,s)=>{let a=_.object({name:_.string().min(1)}).safeParse(e.params);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(a.error)});let n=Ln.safeParse(e.body??{});if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(n.error)});if(!de())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return lr(a.data.name,n.data.scope??"user",n.data.cwd),{success:!0,pluginId:a.data.name}}catch(i){return s.status(500).send({code:"CLI_ERROR",message:i instanceof Error?i.message:"Install failed"})}}),o.post("/plugins/uninstall/:name",{schema:{tags:["Marketplace"],summary:"Uninstall a plugin",params:{type:"object",required:["name"],properties:{name:{type:"string"}}},body:{type:"object",properties:{scope:{type:"string",enum:["user","project"]},cwd:{type:"string"}}}}},async(e,s)=>{let a=_.object({name:_.string().min(1)}).safeParse(e.params);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(a.error)});let n=Mn.safeParse(e.body??{});if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(n.error)});if(!de())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return pr(a.data.name,n.data.scope,n.data.cwd),{success:!0,pluginId:a.data.name}}catch(i){return s.status(500).send({code:"CLI_ERROR",message:i instanceof Error?i.message:"Uninstall failed"})}})}import{z as jt}from"zod/v4";var Bn=jt.object({name:jt.string().min(1)}),Un="x-api-key";async function fa(o,r,e){o.post("/webhooks/:name",{schema:{tags:["Webhooks"],summary:"Trigger a webhook",description:"Trigger a task template execution by name or ID. Requires X-API-Key header if API key is configured.",security:[{apiKey:[]}],params:{type:"object",required:["name"],properties:{name:{type:"string",description:"Template name or ID"}}},response:I.webhookTriggered}},async(s,t)=>{if(e&&s.headers[Un]!==e)return t.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"});let a=Bn.safeParse(s.params);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:jt.prettifyError(a.error)});let{name:n}=a.data,i=Z(n);if(!i){let{listTaskTemplates:c}=await import("./task-templates-NC7XIZIC.js");i=c(!1).find(d=>d.name===n||d.id===n)}if(!i)return t.status(404).send({code:"NOT_FOUND",message:`Template '${n}' not found`});if(!i.enabled)return t.status(409).send({code:"DISABLED",message:`Template '${n}' is disabled`});try{let c=await r.runNow(i.id);return t.status(202).send({code:"ACCEPTED",message:`Template '${i.name}' triggered`,executionId:c,templateId:i.id})}catch(c){let l=c instanceof Error?c.message:String(c);return t.status(500).send({code:"EXECUTION_ERROR",message:l})}}),o.get("/webhooks",{schema:{tags:["Webhooks"],summary:"List available webhooks",description:"List all enabled task templates that can be triggered via webhook, along with auth requirements.",response:I.webhookList}},async()=>{let{listTaskTemplates:s}=await import("./task-templates-NC7XIZIC.js");return{webhooks:s(!0).map(a=>({name:a.id,displayName:a.name,description:a.description,tags:a.tags,trigger:`POST /webhooks/${a.id}`})),auth:e?"X-API-Key header required":"No auth configured"}})}import{z as k}from"zod/v4";var Wn=k.object({status:k.string().optional(),limit:k.coerce.number().min(1).max(100).default(20),offset:k.coerce.number().min(0).default(0)}),Ge=k.union([k.object({type:k.literal("session"),sessionId:k.string()}),k.object({type:k.literal("channel"),channelId:k.string(),chatId:k.string().optional()})]),Vn=k.object({input:k.string().min(1,"goal input is required"),deliverTo:k.array(Ge).optional(),reportTo:k.array(Ge).optional()}),ya=k.object({id:k.string().min(1)}),Gn=k.object({name:k.string().min(1).optional(),description:k.string().optional(),status:k.enum(["active","paused","completed","failed"]).optional(),currentValue:k.number().optional(),budgetUsd:k.number().min(0).optional(),deliverTo:k.array(Ge).optional(),reportTo:k.array(Ge).optional()});async function ha(o){o.get("/goals",{schema:{tags:["Goals"],summary:"List goals",description:"List goals with optional status filter and pagination.",querystring:{type:"object",properties:{status:{type:"string",description:"Filter by goal status"},limit:{type:"integer",minimum:1,maximum:100,default:20},offset:{type:"integer",minimum:0,default:0}}},response:I.goalList}},async(r,e)=>{let s=Wn.safeParse(r.query);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(s.error)});let{status:t,limit:a,offset:n}=s.data;return{goals:js(t,a,n)}}),o.get("/goals/:id",{schema:{tags:["Goals"],summary:"Get goal by ID",description:"Retrieve a single goal by its ID, including metric tree and progress.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:I.goalDetail}},async(r,e)=>{let s=re(r.params.id);return s?{goal:s}:e.status(404).send({code:"NOT_FOUND",message:"Goal not found"})}),o.post("/goals",{schema:{tags:["Goals"],summary:"Create a goal",description:"Create a new goal from a natural language input. The input is parsed, validated, and a metric tree is built.",body:{type:"object",required:["input"],properties:{input:{type:"string",minLength:1,description:"Natural language goal description"},deliverTo:{type:"array",items:{type:"object"},description:"Delivery targets (result output)"},reportTo:{type:"array",items:{type:"object"},description:"Report targets (status notifications)"}}},response:I.goalCreated}},async(r,e)=>{let s=Vn.safeParse(r.body);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(s.error)});let t=await rr(s.data.input);if(!t.validationResult.isValid)return e.status(400).send({code:"INVALID_GOAL",errors:t.validationResult.errors,warnings:t.validationResult.warnings});let a=ar(t.goalState,s.data.deliverTo,s.data.reportTo);return nr(a.id,a.metricType),e.status(201).send({goal:a})}),o.patch("/goals/:id",{schema:{tags:["Goals"],summary:"Update a goal",description:"Partially update a goal's name, description, status, currentValue, or budgetUsd.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{name:{type:"string",minLength:1},description:{type:"string"},status:{type:"string"},currentValue:{type:"number"},budgetUsd:{type:"number",minimum:0},deliverTo:{type:"array",items:{type:"object"},description:"Delivery targets (result output)"},reportTo:{type:"array",items:{type:"object"},description:"Report targets (status notifications)"}}},response:I.goalDetail}},async(r,e)=>{let s=ya.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(s.error)});let t=Gn.safeParse(r.body);return t.success?re(s.data.id)?(De(s.data.id,{...t.data,updatedAt:Date.now()}),{goal:re(s.data.id)}):e.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):e.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)})}),o.delete("/goals/:id",{schema:{tags:["Goals"],summary:"Delete a goal",description:"Delete a goal by ID.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=ya.safeParse(r.params);return s.success?re(s.data.id)?(Ns(s.data.id),{goalId:s.data.id,deleted:!0}):e.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):e.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(s.error)})})}import{z as Re}from"zod/v4";var $n=Re.object({role:Re.string().optional(),taskType:Re.string().optional(),limit:Re.coerce.number().min(1).max(100).default(50)});async function ba(o){o.get("/strategies",{schema:{tags:["Strategies"],summary:"List strategies",description:"List agent strategies with optional role/taskType filter. Returns evolutionary strategy entries used for agent routing.",querystring:{type:"object",properties:{role:{type:"string",description:"Filter by role ID"},taskType:{type:"string",description:"Filter by task type"},limit:{type:"integer",minimum:1,maximum:100,default:50}}},response:I.strategyList}},async(r,e)=>{let s=$n.safeParse(r.query);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:Re.prettifyError(s.error)});let{role:t,taskType:a,limit:n}=s.data,i;return t&&a?i=cr.getStrategies(t,a):t?i=ir(t):i=or(n),{strategies:i.slice(0,n)}})}rs();Y();import{z as Q}from"zod/v4";async function va(o){o.get("/config",{schema:{tags:["Config"],summary:"Get current configuration",description:"Returns the current server configuration with runtime-mutable vs restart-required indication for each setting.",response:I.configGet}},async(e,s)=>{let t=F(),a=Rr(),n=[...Te,...Ze],i={},c=new Set(["anthropic.apiKey","server.apiKey"]);for(let l of n){let d=Je(t,l),m=Te.includes(l);c.has(l)&&typeof d=="string"&&d.length>0&&(d=d.slice(0,5)+"****"),i[l]={value:d??null,mutable:m}}return{config:i,mutable:[...Te],restartRequired:[...Ze],sandbox:{platform:a.platform,available:await Ir()}}}),o.patch("/config",{schema:{tags:["Config"],summary:"Update runtime-mutable configuration",description:"Updates configuration values that can be changed at runtime. Restart-required settings are rejected but valid mutable changes are still applied (partial success).",response:I.configPatch}},async(e,s)=>{let t=e.body;if(!t||typeof t!="object")return s.status(400).send({success:!1,updated:[],errors:["Request body must be a JSON object with config key-value pairs"],message:"Validation error"});let a=Vt(t,ie);if(a.updated.includes("logging.level")){let n=t["logging.level"];typeof n=="string"&&Se(n)}if(a.updated.length>0){let n=F(),i=a.updated.map(c=>({path:c,value:Je(n,c)}));y.emit({type:"config_changed",changes:i})}return{success:a.errors.length===0,updated:a.updated,errors:a.errors,message:a.errors.length===0?`Updated ${a.updated.length} configuration value(s)`:`Updated ${a.updated.length} value(s); ${a.errors.length} rejected (restart required)`}}),o.get("/config/env-diff",async()=>{let e=Ae();return{diffs:zt(e),envFileExists:Ht()!==null}}),o.post("/config/sync-to-env",async()=>{let e=Ae();return{success:!0,changed:Qt(e)}}),o.post("/config/load-from-env",async()=>{let e=Kt();if(!e)return{success:!1,error:".env file not found"};let s=0;for(let[a,n]of Object.entries(e)){let i=Object.entries(et).find(([,c])=>c===a)?.[0];i&&(ie(i,n),s++)}let t={};for(let[a,n]of Object.entries(e))a in et||a.startsWith("ANTHROPIC_")||a.startsWith("ADAM_")||(t[a]=n);return Object.keys(t).length>0&&(ie("defaults.env",t),F().defaults.env=t,s+=Object.keys(t).length),we(Ae),{success:!0,updated:s}});let r=Q.string().max(256).regex(/^[A-Za-z_][A-Za-z0-9_]*$/,"Env var key must match POSIX format: [A-Za-z_][A-Za-z0-9_]*").check(Q.refine(e=>!e.startsWith("ANTHROPIC_"),"ANTHROPIC_* keys are managed in the Anthropic config section"));o.get("/config/env",{schema:{tags:["Config"],summary:"Get custom environment variables",description:"Returns global custom env vars (defaults.env). Sensitive values are masked."}},async()=>({env:F().defaults?.env??{}})),o.put("/config/env",{schema:{tags:["Config"],summary:"Replace all custom environment variables",description:"Full replacement of defaults.env. ANTHROPIC_* keys are rejected."}},async(e,s)=>{let a=Q.record(r,Q.string().max(4096)).check(Q.refine(i=>Object.keys(i).length<=100,"Maximum 100 environment variables")).safeParse(e.body);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:Q.prettifyError(a.error)});let n=a.data;return ie("defaults.env",n),F().defaults.env=n,y.emit({type:"config_changed",changes:[{path:"defaults.env",value:n}]}),{success:!0,count:Object.keys(n).length}}),o.patch("/config/env",{schema:{tags:["Config"],summary:"Partially update custom environment variables",description:"Add/update keys (string value) or delete keys (null value). ANTHROPIC_* keys are rejected."}},async(e,s)=>{let a=Q.record(r,Q.string().max(4096).nullable()).safeParse(e.body);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:Q.prettifyError(a.error)});let n={...F().defaults?.env??{}};for(let[i,c]of Object.entries(a.data))c===null?delete n[i]:n[i]=c;return Object.keys(n).length>100?s.status(400).send({code:"VALIDATION_ERROR",message:"Maximum 100 environment variables"}):(ie("defaults.env",n),F().defaults.env=n,y.emit({type:"config_changed",changes:[{path:"defaults.env",value:n}]}),{success:!0,count:Object.keys(n).length})})}async function Ra(o){o.get("/audit/posture",async(r,e)=>{let s=await _r();return e.send(s)})}async function Ia(o){o.get("/evolution-audit",{schema:{tags:["Evolution"],summary:"List evolution audit records",description:"Returns evolution audit log entries with optional role filter.",querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:100,default:20},offset:{type:"integer",minimum:0,default:0},roleId:{type:"string"}}}}},async(r,e)=>{let{limit:s=20,offset:t=0,roleId:a}=r.query;return a?vr(a,s,t):br(s,t)})}import{z as T}from"zod/v4";var Hn=["active","archived"],Kn=T.object({source:T.object({type:T.enum(["tui","web","api","channel"]),channelId:T.string().optional(),chatId:T.string().optional()}),roleId:T.string().optional()}),Ie=T.object({id:T.string().uuid()}),zn=T.object({status:T.enum(Hn).optional(),limit:T.coerce.number().min(1).max(100).default(100),offset:T.coerce.number().min(0).default(0)}),Qn=T.object({limit:T.coerce.number().min(1).max(200).default(50),offset:T.coerce.number().min(0).default(0)});async function ka(o){o.post("/chat/sessions",{schema:{tags:["Chat"],summary:"Create a chat session",body:{type:"object",required:["source"],properties:{source:{type:"object",required:["type"],properties:{type:{type:"string",enum:["tui","web","api","channel"]},channelId:{type:"string"},chatId:{type:"string"}}},roleId:{type:"string"}}}}},async(e,s)=>{let t=Kn.safeParse(e.body);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let{source:a,roleId:n}=t.data,i=Ne(a,n);return s.status(201).send({session:i})}),o.get("/chat/sessions",{schema:{tags:["Chat"],summary:"List chat sessions",querystring:{type:"object",properties:{status:{type:"string",enum:["active","archived"]},limit:{type:"integer",minimum:1,maximum:100,default:100},offset:{type:"integer",minimum:0,default:0}}}}},async(e,s)=>{let t=zn.safeParse(e.query);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let{status:a}=t.data;return{sessions:Js(a)}}),o.get("/chat/sessions/:id",{schema:{tags:["Chat"],summary:"Get chat session with messages",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let a=B(t.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Session not found"});let n=ut(a.id);return{session:a,messages:n}}),o.post("/chat/sessions/:id/archive",{schema:{tags:["Chat"],summary:"Archive a chat session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let a=B(t.data.id);return a?(Ys(a.id),{sessionId:a.id,status:"archived"}):s.status(404).send({code:"NOT_FOUND",message:"Session not found"})}),o.post("/chat/sessions/:id/restore",{schema:{tags:["Chat"],summary:"Restore an archived session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let a=Xs(t.data.id);return a?{session:a}:s.status(404).send({code:"NOT_FOUND",message:"Session not found"})}),o.delete("/chat/sessions/:id",{schema:{tags:["Chat"],summary:"Delete a chat session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let a=B(t.data.id);return a?(Zs(a.id),s.status(204).send()):s.status(404).send({code:"NOT_FOUND",message:"Session not found"})}),o.get("/chat/sessions/:id/messages",{schema:{tags:["Chat"],summary:"Get messages for a session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let a=B(t.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Session not found"});let n=Qn.safeParse(e.query),{limit:i=50,offset:c=0}=n.success?n.data:{};return{messages:ut(a.id,i,c)}});let r=T.object({content:T.string().min(1,"content is required"),source:T.object({type:T.enum(["tui","web","api","channel"]),channelId:T.string().optional(),chatId:T.string().optional()}),roleId:T.string().optional(),sessionId:T.string().uuid().optional()});o.post("/chat/messages",{schema:{tags:["Chat"],summary:"Send a chat message",description:"Send a message. Creates a session if no active session exists for the source. Returns sessionId, messageId, and response.",body:{type:"object",required:["content","source"],properties:{content:{type:"string",minLength:1},source:{type:"object",required:["type"],properties:{type:{type:"string",enum:["tui","web","api","channel"]},channelId:{type:"string"},chatId:{type:"string"}}},roleId:{type:"string"},sessionId:{type:"string"}}}}},async(e,s)=>{let t=r.safeParse(e.body);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(t.error)});let{content:a,source:n,roleId:i,sessionId:c}=t.data,l=await We(a,n,i,c);return s.status(201).send(l)})}Y();var Yn=q("ws"),$e=new Set,He=[],Xn=50;function Zn(o){He.push(o),He.length>Xn&&He.shift()}function le(o){Zn(o);let r=JSON.stringify(o);for(let e of $e)e.readyState===1&&e.send(r)}function Ta(o){o.get("/chat/stream",{websocket:!0},(r,e)=>{$e.add(r);for(let s of He)r.readyState===1&&r.send(JSON.stringify(s));r.on("close",()=>{$e.delete(r)}),r.on("error",s=>{Yn.error({error:s},"Chat WebSocket error"),$e.delete(r)})}),y.on("session_created",r=>le(r)),y.on("session_archived",r=>le(r)),y.on("session_restored",r=>le(r)),y.on("session_deleted",r=>le(r)),y.on("chat_message",r=>le(r)),y.on("task_complete_event",r=>le(r))}Y();var j=q("channels"),Ke=class{adapters=new Map;rateLimits=new Map;healthInterval;rateLimitPerMinute;constructor(r){this.rateLimitPerMinute=r?.rateLimitPerMinute??60}async addChannel(r,e){this.adapters.set(r.id,e),e.onMessage(s=>{this.handleInbound(r.id,s)}),r.enabled&&await this.connectChannel(r.id)}async removeChannel(r){let e=this.adapters.get(r);if(e){try{await e.disconnect()}catch(s){j.error({channelId:r,error:s},"Error disconnecting channel")}this.adapters.delete(r),this.rateLimits.delete(r)}}async connectChannel(r){let e=this.adapters.get(r);if(!e)throw new Error(`No adapter registered for channel ${r}`);try{ce(r,"connecting"),await e.connect(),ce(r,"connected"),j.info({channelId:r,platform:e.platform},"Channel connected")}catch(s){throw ce(r,"error"),j.error({channelId:r,error:s},"Failed to connect channel"),s}}async disconnectChannel(r){let e=this.adapters.get(r);if(e)try{await e.disconnect(),ce(r,"disconnected"),j.info({channelId:r},"Channel disconnected")}catch(s){j.error({channelId:r,error:s},"Error disconnecting channel")}}getChannelStatus(r){let e=this.adapters.get(r);return e?e.getStatus():"disconnected"}getChannelStatuses(){let r=new Map;for(let[e,s]of this.adapters)r.set(e,s.getStatus());return r}hasAdapter(r){return this.adapters.has(r)}async sendMessage(r,e,s){let t=this.adapters.get(r);if(!t)return j.warn({channelId:r},"No adapter for outbound message"),null;if(!this.checkRateLimit(r))return j.warn({channelId:r},"Rate limit exceeded, dropping outbound message"),null;try{return await t.sendMessage(e,s)}catch(a){return j.error({channelId:r,chatId:e,error:a},"Failed to send outbound message"),null}}checkRateLimit(r){let e=Date.now(),s=this.rateLimits.get(r);return!s||e-s.windowStart>=6e4?(this.rateLimits.set(r,{count:1,windowStart:e}),!0):s.count>=this.rateLimitPerMinute?!1:(s.count++,!0)}async handleInbound(r,e){if(e.source==="system"){j.debug({channelId:r},"Skipping system message (anti-loop)");return}try{let{isRecentlySent:t}=await import("./outbound-gateway-GGFMU5JW.js"),a=e.channelMessageId??e.raw?.MsgId??"";if(a&&t(String(a))){j.debug({channelId:r,messageId:a},"Skipping delivery-sent message (anti-loop)");return}}catch{}if(!this.checkRateLimit(r)){j.warn({channelId:r,senderId:e.senderId},"Rate limit exceeded for inbound message");return}try{let{handleInboundForApproval:t}=await import("./approval-handler-RIJO3OBO.js");if(await t(r,e.chatId,e.content)){j.debug({channelId:r,chatId:e.chatId},"Inbound message consumed as approval reply");return}}catch{}let s=qs(r);if(s?.allowedChatIds&&!s.allowedChatIds.includes(e.chatId)){j.debug({channelId:r,chatId:e.chatId},"Chat not in allowlist, ignoring");return}try{let t=await We(e.content,{type:"channel",channelId:r,chatId:e.chatId},s?.linkedRoleId);j.info({channelId:r,chatId:e.chatId,sessionId:t.sessionId},"Inbound message routed to session")}catch(t){j.error({channelId:r,chatId:e.chatId,error:t},"Failed to route inbound message")}}startHealthMonitor(r=3e4){this.stopHealthMonitor(),this.healthInterval=setInterval(()=>{this.checkHealth()},r)}stopHealthMonitor(){this.healthInterval&&(clearInterval(this.healthInterval),this.healthInterval=void 0)}checkHealth(){for(let[r,e]of this.adapters){let s=e.getStatus();try{ce(r,s)}catch{}}}async startAll(){let r=he(!0);for(let e of r){let s=this.adapters.get(e.id);if(s&&s.getStatus()!=="connected")try{await this.connectChannel(e.id)}catch{}}this.startHealthMonitor()}async stopAll(){this.stopHealthMonitor();for(let r of this.adapters.keys())await this.disconnectChannel(r);this.adapters.clear(),this.rateLimits.clear()}_getAdapterCount(){return this.adapters.size}_getRateLimitEntry(r){return this.rateLimits.get(r)}};Ce();Y();var U=q("watchdog"),ze=null;function wa(o,r,e,s){if(!o.enabled){U.info("Watchdog disabled");return}let t=o.intervalMinutes*6e4;U.info({intervalMinutes:o.intervalMinutes},"Watchdog started"),ze=setInterval(()=>{Jn(o,r,e,s)},t)}function Sa(){ze&&(clearInterval(ze),ze=null,U.info("Watchdog stopped"))}function Jn(o,r,e,s){let{rules:t}=o;if(t.managerHealthCheck.enabled){let a=t.managerHealthCheck.staleDurationMinutes*6e4,n=r.getLastActivityAt();if(Date.now()-n>a){let i=`ChatManager session stale (no activity for ${t.managerHealthCheck.staleDurationMinutes} min)`;if(U.warn(i),t.managerHealthCheck.action==="restart"){let c=r.getConsecutiveStaleCount()>0;r.restartSession(),c&&(U.fatal("ChatManager unrecoverable after session restart \u2014 exiting for supervisor restart"),process.exit(1))}else t.managerHealthCheck.action==="notify"&&s(i)}}if(!e.isHealthy()){let a="ExecutionPool is not healthy (stopped unexpectedly)";U.warn(a),s(a)}if(t.staleTasks.enabled){let a=t.staleTasks.maxPendingMinutes*6e4,i=V("pending").filter(c=>Date.now()-c.createdAt>a);if(i.length>0){let c=`${i.length} stale task(s) pending > ${t.staleTasks.maxPendingMinutes} min`;U.warn({count:i.length},c),t.staleTasks.action==="notify"&&s(c)}}if(t.staleRunningTasks?.enabled){let a=t.staleRunningTasks.maxRunningMinutes*6e4,i=V("running").filter(c=>{if(!c.startedAt||Date.now()-c.startedAt<a)return!1;try{let b=W().prepare("SELECT MAX(timestamp) as latest FROM step_logs WHERE task_id = ?").get(c.id)?.latest??c.startedAt;return Date.now()-b>a}catch{return!0}});if(i.length>0){let c=`${i.length} task(s) running with no activity for > ${t.staleRunningTasks.maxRunningMinutes} min \u2014 marking as failed`;U.warn({count:i.length,taskIds:i.map(l=>l.id)},c);for(let l of i)X(l.id,{status:"failed",error:`Watchdog timeout: no activity for > ${t.staleRunningTasks.maxRunningMinutes} min`,completedAt:Date.now()}),y.emit({type:"task_status_change",taskId:l.id,oldStatus:"running",newStatus:"failed"}),e.releaseSlot(l.id);s(c)}}if(t.dbMaintenance.enabled)try{let n=W().pragma("wal_checkpoint(PASSIVE)");U.debug({walSize:n},"WAL checkpoint")}catch(a){U.error({error:a},"DB health check failed")}if(t.artifactCleanup?.enabled)try{let a=t.artifactCleanup.ttlDays*24*60*60*1e3,n=t.artifactCleanup.orphanGcMinAgeHours*60*60*1e3,i=Date.now()-a,c=Cr(i),l=0;for(let d of c){let m=new Set(wr(d).map(v=>v.id));l+=$s(d,m,n);let b=Sr(d);for(let v of b)v.blobPath&&(Vs(v.blobPath),l++);Gs(d)}c.length>0&&U.info({executions:c.length,files:l},"Workflow artifacts cleaned")}catch(a){U.error({error:a},"Workflow artifact cleanup failed")}}import{z as D}from"zod";import{v4 as eo}from"uuid";var to=D.object({eventType:D.enum(["task_complete","task_error","plan_approval_request","*"]),matchCriteria:D.object({templateId:D.string().optional(),roleId:D.string().optional(),promptPattern:D.string().optional(),taskStatus:D.string().optional()}).optional().default({}),target:D.object({type:D.enum(["channel","webhook"]),channelId:D.string().optional(),chatId:D.string().optional(),webhookUrl:D.string().optional()}),formatTemplate:D.string().optional(),maxPerMinute:D.number().int().min(1).max(60).optional().default(5),skipOriginChannel:D.boolean().optional().default(!0),enabled:D.boolean().optional().default(!0)});async function Nt(o){o.get("/delivery-rules",async(r,e)=>fr()),o.post("/delivery-rules",async(r,e)=>{let s=to.safeParse(r.body);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:D.prettifyError(s.error)});let t=s.data,a={id:eo(),eventType:t.eventType,matchCriteria:t.matchCriteria,target:t.target,formatTemplate:t.formatTemplate,maxPerMinute:t.maxPerMinute,skipOriginChannel:t.skipOriginChannel,enabled:t.enabled,createdAt:Date.now()};return gr(a),e.status(201).send(a)}),o.put("/delivery-rules/:id",async(r,e)=>{if(!qe(r.params.id))return e.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let t=r.body;return yr(r.params.id,t),{id:r.params.id,updated:!0}}),o.delete("/delivery-rules/:id",async(r,e)=>qe(r.params.id)?(hr(r.params.id),{id:r.params.id,deleted:!0}):e.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"})),o.get("/delivery-rules/:id/log",async(r,e)=>ps(r.params.id)),o.post("/delivery-rules/:id/test",async(r,e)=>{let s=qe(r.params.id);if(!s)return e.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let{getDeliveryEngine:t}=await import("./engine-HJUE6I4I.js"),a=t();if(!a)return e.status(503).send({code:"ENGINE_NOT_READY",message:"DeliveryEngine not initialized"});let n=`[TEST] Delivery rule test at ${new Date().toISOString()}`,{createDeliveryLog:i}=await import("./delivery-log-7DJJTPXL.js"),{v4:c}=await import("uuid"),{TTL_MS:l}=await import("./delivery-log-7DJJTPXL.js"),d={id:c(),ruleId:s.id,status:"pending",target:s.target,content:n,attempts:0,createdAt:Date.now(),expiresAt:Date.now()+l};i(d);try{return await a.attemptDeliveryPublic(d,s),{id:d.id,ruleId:s.id,status:"sent",content:n}}catch(m){let b=m instanceof Error?m.message:String(m);return e.status(500).send({code:"DELIVERY_FAILED",message:b,logId:d.id})}})}import{z as J}from"zod/v4";var Ca=new Fe,Aa=J.object({id:J.string().min(1)}),so=J.object({id:J.string().min(1),stepId:J.string().min(1)});async function Pa(o){o.get("/workflow-executions",{schema:{tags:["Workflows"],summary:"List workflow executions",description:"List recent workflow executions, optionally filtered by templateId.",querystring:{type:"object",properties:{templateId:{type:"string",description:"Filter by template ID"},limit:{type:"number",default:50},offset:{type:"number",default:0}}}}},async r=>{let e=r.query;return{executions:Hs(e.templateId,e.limit??50,e.offset??0)}}),o.get("/workflow-executions/:id",{schema:{tags:["Workflows"],summary:"Get workflow execution",description:"Get details of a specific workflow execution including step statuses.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=Aa.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:J.prettifyError(s.error)});let t=je(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Workflow execution not found"});let a=fe(s.data.id);return{execution:t,stepTasks:a}}),o.post("/workflow-executions/:id/cancel",{schema:{tags:["Workflows"],summary:"Cancel a workflow execution",description:"Cancel all running/pending step tasks in a workflow execution.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=Aa.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:J.prettifyError(s.error)});let t=je(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Workflow execution not found"});if(t.status!=="running")return e.status(400).send({code:"INVALID_STATE",message:`Cannot cancel workflow in status: ${t.status}`});let a=fe(s.data.id),n=new Set(["pending","running","queued","paused"]),i=0,c={...t.stepStatuses};for(let l of a)n.has(l.status)&&(Ca.cancelTask(l.id),l.stepId&&(c[l.stepId]={taskId:l.id,status:"cancelled",roleId:l.roleId,error:"Workflow cancelled"}),i++);return ft(s.data.id,{status:"cancelled",stepStatuses:c,completedAt:Date.now()}),y.emit({type:"workflow_status_change",executionId:s.data.id,templateId:t.templateId,status:"cancelled"}),{executionId:s.data.id,cancelled:i,total:a.length}}),o.post("/workflow-executions/:id/steps/:stepId/skip",{schema:{tags:["Workflows"],summary:"Skip a workflow step",description:"Mark a pending step as skipped without cancelling the whole workflow. Dependents of the skipped step will also be skipped.",params:{type:"object",required:["id","stepId"],properties:{id:{type:"string"},stepId:{type:"string"}}}}},async(r,e)=>{let s=so.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:J.prettifyError(s.error)});let t=je(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Workflow execution not found"});let a=t.stepStatuses[s.data.stepId];if(!a)return e.status(404).send({code:"NOT_FOUND",message:"Step not found in workflow"});if(a.taskId){let i=E(a.taskId);i&&["pending","running","queued","paused"].includes(i.status)&&Ca.cancelTask(a.taskId)}let n={...t.stepStatuses};return n[s.data.stepId]={...a,status:"skipped",error:"Manually skipped"},ft(s.data.id,{stepStatuses:n}),{executionId:s.data.id,stepId:s.data.stepId,status:"skipped"}})}Y();ge();ge();import{existsSync as Qe,copyFileSync as ro,mkdirSync as qt,cpSync as ao}from"fs";import{join as $}from"path";function Lt(){qt(O,{recursive:!0}),qt($(O,"logs"),{recursive:!0}),qt($(O,".claude"),{recursive:!0})}function _a(o=process.cwd()){Lt();let r=[],e=[{from:$(o,"data","adam.db"),to:$(O,"adam.db"),label:"database"},{from:$(o,"adam.config.yaml"),to:$(O,"adam.config.yaml"),label:"config"},{from:$(o,".env"),to:$(O,".env"),label:".env"}];for(let{from:a,to:n,label:i}of e)Qe(a)&&!Qe(n)&&(ro(a,n),r.push(i));let s=$(o,".claude","plugins"),t=$(O,".claude","plugins");return Qe(s)&&!Qe(t)&&(ao(s,t,{recursive:!0}),r.push("plugins")),r}rs();var C=q("adam");function oo(o){let r={...o};if(r.defaults&&typeof r.defaults=="object"){let e={...r.defaults};if(e.env&&typeof e.env=="object"){let s={...e.env};for(let t of Object.keys(s))s[t]&&(s[t]=s[t].slice(0,4)+"****");e.env=s}r.defaults=e}if(r.server&&typeof r.server=="object"){let e={...r.server};e.apiKey&&typeof e.apiKey=="string"&&(e.apiKey=e.apiKey.slice(0,4)+"****"),r.server=e}return r}async function io(){Lt();let o=_a();o.length>0&&console.log(`[adam] Migrated to ~/.adam/: ${o.join(", ")}`);let r=xr();C.info("Starting Adam Agent Server"),r.length>0&&C.info({files:r},"Loaded env files");let e=Xt();Ut(e),F().anthropic?.apiKey||process.env.ANTHROPIC_API_KEY||C.warn("ANTHROPIC_API_KEY not set \u2014 configure via Settings UI or ~/.adam/.env"),process.env.ANTHROPIC_BASE_URL&&C.info({url:process.env.ANTHROPIC_BASE_URL},"Using custom API base URL");let t=e.defaults?.claudeCodePath;try{if(!t){let{createRequire:Da}=await import("module"),{dirname:ja,join:Na}=await import("path"),qa=Da(import.meta.url).resolve("@anthropic-ai/claude-agent-sdk");t=Na(ja(qa),"cli.js")}let{execSync:R}=await import("child_process"),{chmodSync:N,accessSync:te,constants:me}=await import("fs");try{te(t,me.X_OK)}catch{C.info({path:t},"CLI not executable, fixing permissions"),N(t,493)}let xa=R(`"${t}" --version`,{timeout:5e3,encoding:"utf-8"}).trim();C.info({path:t,version:xa},"Claude Code CLI detected")}catch(R){let N=R;N.code==="ENOENT"?C.warn({path:t},"Claude Code CLI not found. Task execution will fail. Install: npm i -g @anthropic-ai/claude-code"):C.warn({path:t,error:(N.stderr?.trim()||String(R)).slice(0,200)},"Claude Code CLI check failed")}let n=W().prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all();C.info({tables:n.map(R=>R.name).join(", ")},"Database initialized");let i=Zt(),c=ss(i);c>0&&C.info({count:c},"Seeded config DB from .env");let{getAllConfig:l}=await import("./config-HR4MBTIS.js");we(l);let d=F();d.logging?.level&&Se(d.logging.level),C.info({config:oo(d)},"Config loaded (DB + defaults)");let m=St(),{getToolsFingerprint:b}=await import("./adam-tools-4LZYFB6J.js"),v=b(),f=m.sdkSessionId;if(f&&m.toolsFingerprint!==v&&(C.info({old:m.toolsFingerprint?.slice(0,40),new:v.slice(0,40)},"MCP tools changed \u2014 invalidating old SDK session"),Qr(),f=void 0),be({toolsFingerprint:v}),f){let R=process.cwd();m.workspacePath&&m.workspacePath!==R&&(C.warn({serverCwd:R,saved:m.workspacePath},"Workspace mismatch"),C.warn("SDK session may not resume correctly due to cwd mismatch")),C.info({sessionId:f.slice(0,8)},"Recovering manager SDK session")}else C.info("No previous manager SDK session found, starting fresh");m.userTaskSessionId&&C.info({sessionId:m.userTaskSessionId.slice(0,8)},"Recovering user task session"),Yr(process.cwd());let{initializeDefaultRoles:g}=await import("./role-presets-W452Y3RV.js"),A=g();C.info({count:A.length},"Roles initialized");let oe=F().execution??{maxConcurrent:3,pollIntervalMs:3e4},ee=new ve(f),H=new Rt(oe.maxConcurrent);pa(ee),await ee.start(),await H.start();let Xe=V("running");if(Xe.length>0){C.warn({count:Xe.length},"Found orphaned running tasks from previous session \u2014 marking as failed");for(let R of Xe)X(R.id,{status:"failed",error:"Server restarted while task was running",completedAt:Date.now()})}let P=qr(e,e.server.apiKey);await P.register(R=>Ur(R)),await P.register(R=>Wr(R,e)),await P.register(R=>Hr(R,e.server.apiKey)),await P.register(ta),await P.register(ca),await P.register(ha),await P.register(ba);let pe=new Ks;zs(pe),await pe.start(),Or(),await P.register(R=>ma(R,pe)),await P.register(ga),await P.register(R=>fa(R,pe,process.env.ADAM_WEBHOOK_API_KEY)),await P.register(va),await P.register(Ra),await P.register(Ia),await P.register(ka);let ue=new Ke;Bs(ue),await P.register(Us),await P.register(Ta),await P.register(R=>zr(R,e.server.apiKey)),await P.register(ia),await P.register(Nt),await P.register(Pa),er(),Er(),await Ar(),ue.startHealthMonitor();try{let R=he();for(let N of R)if(N.platform==="wechat"){let te=N.config;if(te.botToken){let me=new Ls(N.id,te);ue.addChannel(N,me)}}}catch(R){C.error({error:R},"Failed to register WeChat adapters at startup")}try{let R=he();for(let N of R)if(N.platform==="discord"){let te=N.config;if(te.botToken){let me=new Ms(N.id,{botToken:te.botToken});ue.addChannel(N,me)}}}catch(R){C.error({error:R},"Failed to register Discord adapters at startup")}let{host:Mt,port:ke}=e.server;await P.listen({host:Mt,port:ke}),C.info({host:Mt,port:ke},"Server listening");let Oa=e.watchdog??$t.watchdog;wa(Oa,ee,H,R=>{C.warn({alert:R},"Watchdog alert")}),Yt(R=>{y.emit({type:"log_event",timestamp:R.time??Date.now(),level:R.level??"info",component:R.component??"adam",msg:R.msg??""})}),Fa(O,{recursive:!0}),Fa(Ye(O,"logs"),{recursive:!0}),Ea(Ye(O,"adam.port"),String(ke)),e.server.apiKey&&Ea(Ye(O,"adam.key"),e.server.apiKey,{mode:384}),process.send?.({type:"ready",port:ke});let Bt=async()=>{C.info("Shutting down"),Sa(),Pr(),tr(),Fr(),await ue.stopAll(),ee.stop(),H.stop(),await pe.stop(),await P.close(),tt();try{no(Ye(O,"adam.key"))}catch{}process.exit(0)};process.on("SIGINT",()=>{Bt()}),process.on("SIGTERM",()=>{Bt()})}io().catch(o=>{C.fatal(o,"Fatal error"),process.exit(1)});
94
+ ${g.length} \u4E2A\u5B50\u4EFB\u52A1\u5168\u90E8\u5B8C\u6210`;await this.routeGoalNotification(y,Y,t.parentId)}}}}async getRoleName(r){try{let{getRole:e}=await import("./roles-L34L5MK3.js");return e(r)?.name}catch{return}}async deliverToChannel(r,e,s,t="reply",a){if(!r||!e){x.warn({channelId:r,chatId:e},"Cannot deliver to channel: missing channelId or chatId");return}try{let i=await Ys().send({taskId:a,channelId:r,chatId:e,content:s,messageType:t});i.success?x.info({channelId:r,chatId:e.slice(0,12),messageType:t,taskId:a?.slice(0,8),messageId:i.messageId},"Delivered notification to channel"):x.warn({channelId:r,chatId:e.slice(0,12),messageType:t,taskId:a?.slice(0,8),error:i.error},"Channel delivery failed")}catch(n){x.error({error:n,channelId:r,chatId:e.slice(0,12)},"Failed to deliver to channel")}}async routeGoalNotification(r,e,s){let t=r.deliverTo??[],a=r.sourceSessionId;if(!(t.length===0&&!a)){for(let n of t)if(n.type==="session")try{let i=B(n.sessionId);i&&(K({id:oe(),sessionId:n.sessionId,role:"assistant",content:e,source:i.source,createdAt:Date.now()}),z(n.sessionId),h.emit({type:"chat_message",sessionId:n.sessionId,message:{id:oe(),sessionId:n.sessionId,role:"assistant",content:e,source:i.source,createdAt:Date.now()}}))}catch(i){x.error({error:i,goalId:s,targetSession:n.sessionId},"Failed to deliver Goal notification to session")}else n.type==="channel"&&await this.deliverToChannel(n.channelId,n.chatId??"",e);if(a&&!t.some(n=>n.type==="session"&&n.sessionId===a))try{let n=B(a);n&&(K({id:oe(),sessionId:a,role:"assistant",content:e,source:n.source,createdAt:Date.now()}),z(a),h.emit({type:"chat_message",sessionId:a,message:{id:oe(),sessionId:a,role:"assistant",content:e,source:n.source,createdAt:Date.now()}}))}catch(n){x.error({error:n,goalId:s,sessionId:a},"Failed to deliver Goal notification to source session")}}}getLastActivityAt(){return this.lastActivityAt}getConsecutiveStaleCount(){return this.consecutiveStaleCount}isHealthy(){return this.running}async restartSession(){x.warn("Restarting ChatManager session (Watchdog triggered)"),this.consecutiveStaleCount++,this.sessionId=void 0,Ue(void 0)}};import{v4 as Ot}from"uuid";Z();var Ft=q("message-handler"),ba=new Set;function va(o){ba.add(o),o.finally(()=>{ba.delete(o)})}async function Hn(o,r){if(!(await import("./config-XMQS2NPT.js").then(t=>t.getChatConfig())).autoTitle)return;let s=["Generate a very short title (max 50 characters) for a chat session that started with this message:",`"${r.slice(0,200)}"`,"Respond with only the title, no quotes or explanation."].join(`
95
+ `);try{let a=(await ks(s,"You are a concise title generator. Reply with only the title, max 50 characters.")).trim().slice(0,50);a.length>0&&xs(o,{title:a})}catch{}}var xt=null;function Ra(o){xt=o}async function Ve(o,r,e,s){let t;s&&(t=B(s)),t||(t=rr(r)),t||(t=qe(r,e));let a=Ot(),n={id:a,sessionId:t.id,role:"user",content:o,source:r,createdAt:Date.now()};if(K(n),h.emit({type:"chat_message",sessionId:t.id,message:n}),t.messageCount===0&&va(Hn(t.id,o)),z(t.id),ft(t.id),xt){let i=t.id,c=t.source,l=(async()=>{try{let d=await xt.handleMessage(o,i,r),u={id:Ot(),sessionId:i,role:"assistant",content:d,source:r,createdAt:Date.now()};K(u),h.emit({type:"chat_message",sessionId:i,message:u}),z(i),ft(i),c.type==="channel"&&c.channelId&&c.chatId&&(Ft.info({sessionId:i,sourceType:c.type,hasChannelId:!!c.channelId,hasResponse:!!d},"Chat response ready, checking channel delivery"),await $n(c.channelId,c.chatId,d))}catch(d){(await import("./logger-QCJUU7GV.js")).getLogger("message-handler").error({error:d,sessionId:i},"ChatManager response failed");let f={id:Ot(),sessionId:i,role:"assistant",content:`\u26A0\uFE0F \u5904\u7406\u5931\u8D25: ${d instanceof Error?d.message:String(d)}`,source:r,createdAt:Date.now()};K(f),h.emit({type:"chat_message",sessionId:i,message:f}),z(i)}})();va(l)}return{sessionId:t.id,messageId:a}}async function $n(o,r,e){Ft.info({channelId:o,chatId:r.slice(0,12)},"Delivering chat response to channel");try{let{getOutboundGateway:s}=await import("./outbound-gateway-6K6P2BEH.js");await s().send({channelId:o,chatId:r,content:e,messageType:"reply"})}catch(s){Ft.error({error:s,channelId:o,chatId:r.slice(0,12)},"Channel delivery failed (non-fatal)")}}import{z as b}from"zod/v4";import{v4 as Kn}from"uuid";var Ia=b.union([b.object({type:b.literal("session"),sessionId:b.string()}),b.object({type:b.literal("channel"),channelId:b.string(),chatId:b.string().optional()})]),zn=b.object({id:b.string(),prompt:b.string(),dependsOn:b.array(b.string()).optional(),outputAs:b.string().optional(),roleId:b.string().optional(),config:b.object({timeout:b.number().optional(),maxTurns:b.number().optional()}).optional()}),Qn=b.object({type:b.enum(["cron","manual","event","once"]),cron:b.string().optional(),event:b.string().optional(),runAt:b.string().optional()}),Dt=b.object({name:b.string().min(1),description:b.string().optional(),trigger:Qn,steps:b.array(zn).min(1),rolePreference:b.string().optional(),config:b.record(b.string(),b.unknown()).optional(),enabled:b.boolean().default(!0),goalIds:b.array(b.string()).optional(),deliverTo:b.array(Ia).optional(),reportTo:b.array(Ia).optional()}),Kc=Dt.transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Yn=Dt.partial().transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Ge=b.object({id:b.string().min(1)});async function ka(o,r){o.post("/task-templates",{schema:{tags:["Templates"],summary:"Create a task template",description:"Create a new task template with trigger (cron/manual/event) and execution steps. Cron-triggered templates are automatically scheduled.",body:{type:"object",required:["name","trigger","steps"],properties:{name:{type:"string",minLength:1},description:{type:"string"},trigger:{type:"object",required:["type"],properties:{type:{type:"string",enum:["cron","manual","event","once"]},cron:{type:"string",description:"Cron expression (required when type is cron)"},event:{type:"string",description:"Event name (required when type is event)"},runAt:{type:"string",description:"ISO 8601 timestamp (required when type is once)"}}},steps:{type:"array",minItems:1,items:{type:"object",required:["id","prompt"],properties:{id:{type:"string"},prompt:{type:"string"},dependsOn:{type:"array",items:{type:"string"}},outputAs:{type:"string"},roleId:{type:"string",description:"Role ID for this step (overrides template rolePreference)"},config:{type:"object",properties:{timeout:{type:"number",description:"Step-level timeout override (seconds)"},maxTurns:{type:"number",description:"Step-level maxTurns override"}}}}}},rolePreference:{type:"string"},config:{type:"object",additionalProperties:!0},enabled:{type:"boolean",default:!0},goalIds:{type:"array",items:{type:"string"}},deliverTo:{type:"array",items:{type:"object"}},reportTo:{type:"array",items:{type:"object"}}}},response:R.templateCreated}},async(e,s)=>{let t=Dt.safeParse(e.body);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(t.error)});let a={id:Kn(),...t.data,createdAt:Date.now()};return Us(a),a.enabled&&a.trigger.type==="cron"&&a.trigger.cron?await r.scheduleJob(a.id):a.enabled&&a.trigger.type==="once"&&a.trigger.runAt&&r.scheduleOnceJob(a.id),s.status(201).send({templateId:a.id})}),o.get("/task-templates",{schema:{tags:["Templates"],summary:"List task templates",description:"List all task templates, optionally filtering to enabled-only.",querystring:{type:"object",properties:{enabled:{type:"string",enum:["true","false"],description:"Filter to enabled templates only when 'true'"}}},response:R.templateList}},async e=>{let t=e.query.enabled==="true";return{templates:Vs(t)}}),o.get("/task-templates/:id",{schema:{tags:["Templates"],summary:"Get task template by ID",description:"Retrieve a single task template by its ID.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:R.templateDetail}},async(e,s)=>{let t=Ge.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(t.error)});let a=ee(t.data.id);return a?{template:a}:s.status(404).send({code:"NOT_FOUND",message:"Template not found"})}),o.patch("/task-templates/:id",{schema:{tags:["Templates"],summary:"Update a task template",description:"Partially update a task template. Cron schedules are automatically rescheduled if the trigger changes.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{name:{type:"string",minLength:1},description:{type:"string"},trigger:{type:"object",properties:{type:{type:"string",enum:["cron","manual","event","once"]},cron:{type:"string"},event:{type:"string"},runAt:{type:"string"}}},steps:{type:"array",items:{type:"object"}},rolePreference:{type:"string"},config:{type:"object",additionalProperties:!0},enabled:{type:"boolean"},goalIds:{type:"array",items:{type:"string"}},deliverTo:{type:"array",items:{type:"object"}},reportTo:{type:"array",items:{type:"object"}}}},response:R.templateUpdated}},async(e,s)=>{let t=Ge.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(t.error)});let a=Yn.safeParse(e.body);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(a.error)});if(!ee(t.data.id))return s.status(404).send({code:"NOT_FOUND",message:"Template not found"});Ws(t.data.id,a.data),await r.unscheduleJob(t.data.id);let i=ee(t.data.id);return i?.enabled&&i.trigger.type==="cron"&&i.trigger.cron?await r.scheduleJob(i.id):i?.enabled&&i.trigger.type==="once"&&i.trigger.runAt&&r.scheduleOnceJob(i.id),{templateId:t.data.id}}),o.delete("/task-templates/:id",{schema:{tags:["Templates"],summary:"Delete a task template",description:"Delete a task template by ID. Cron jobs are automatically unscheduled.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:R.templateDeleted}},async(e,s)=>{let t=Ge.safeParse(e.params);return t.success?ee(t.data.id)?(await r.unscheduleJob(t.data.id),Gs(t.data.id),{templateId:t.data.id,deleted:!0}):s.status(404).send({code:"NOT_FOUND",message:"Template not found"}):s.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(t.error)})}),o.post("/task-templates/:id/run",{schema:{tags:["Templates"],summary:"Run a task template",description:"Manually trigger execution of a task template regardless of its trigger type.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:R.templateRun}},async(e,s)=>{let t=Ge.safeParse(e.params);return t.success?ee(t.data.id)?{executionId:await r.runNow(t.data.id),status:"started"}:s.status(404).send({code:"NOT_FOUND",message:"Template not found"}):s.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(t.error)})})}import{z as _}from"zod/v4";fs();var jt=_.object({id:_.string().min(1)}),Xn=_.object({scope:_.enum(["user","project"]).optional(),cwd:_.string().optional()}),Zn=_.object({scope:_.enum(["user","project"]).optional(),cwd:_.string().optional()});async function Ta(o){o.get("/plugins",{schema:{tags:["Plugins"],summary:"List all installed plugins",querystring:{type:"object",properties:{scope:{type:"string",enum:["user","project","local"]}}}}},async e=>{let s=e.query,t=Fe({scope:s.scope}),a=lt();return{plugins:t.map(n=>({...n,globalEnabled:a[n.id]??n.enabled}))}}),o.get("/plugins/:id",{schema:{tags:["Plugins"],summary:"Get plugin by ID",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(e,s)=>{let t=jt.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)});let a=ms(t.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Plugin not found"});let n=us(a.installPath),i=lt();return{plugin:{...a,globalEnabled:i[a.id]??a.enabled,manifest:n}}}),o.post("/plugins/:id/enable",{schema:{tags:["Plugins"],summary:"Enable a plugin globally",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(e,s)=>{let t=jt.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)});if(!pe())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return fr(t.data.id),{pluginId:t.data.id,enabled:!0}}catch(a){return s.status(500).send({code:"CLI_ERROR",message:a instanceof Error?a.message:"Enable failed"})}}),o.post("/plugins/:id/disable",{schema:{tags:["Plugins"],summary:"Disable a plugin globally",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(e,s)=>{let t=jt.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)});if(!pe())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return hr(t.data.id),{pluginId:t.data.id,enabled:!1}}catch(a){return s.status(500).send({code:"CLI_ERROR",message:a instanceof Error?a.message:"Disable failed"})}}),o.get("/plugins/stats",{schema:{tags:["Plugins"],summary:"Get plugin usage statistics",querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50}}}}},async e=>{let s=e.query;return{stats:Ar(s.limit??50)}});let r=_.object({roleId:_.string().min(1)});o.get("/plugins/stats/role/:roleId",{schema:{tags:["Plugins"],summary:"Get plugin usage by role",params:{type:"object",required:["roleId"],properties:{roleId:{type:"string"}}}}},async(e,s)=>{let t=r.safeParse(e.params);return t.success?{roleId:t.data.roleId,stats:Cr(t.data.roleId)}:s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(t.error)})}),o.get("/plugins/marketplace",{schema:{tags:["Marketplace"],summary:"List available marketplace plugins"}},async(e,s)=>{if(!pe())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found. Install Claude Code to use marketplace features."});try{let t=mr();return{available:t.available,installed:t.installed}}catch(t){return s.status(500).send({code:"CLI_ERROR",message:t instanceof Error?t.message:"CLI command failed"})}}),o.get("/plugins/marketplaces",{schema:{tags:["Marketplace"],summary:"List known marketplace sources"}},async()=>({sources:gs()})),o.post("/plugins/install/:name",{schema:{tags:["Marketplace"],summary:"Install a plugin",params:{type:"object",required:["name"],properties:{name:{type:"string"}}},body:{type:"object",properties:{scope:{type:"string",enum:["user","project"]},cwd:{type:"string"}}}}},async(e,s)=>{let a=_.object({name:_.string().min(1)}).safeParse(e.params);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(a.error)});let n=Xn.safeParse(e.body??{});if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(n.error)});if(!pe())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return gr(a.data.name,n.data.scope??"user",n.data.cwd),{success:!0,pluginId:a.data.name}}catch(i){return s.status(500).send({code:"CLI_ERROR",message:i instanceof Error?i.message:"Install failed"})}}),o.post("/plugins/uninstall/:name",{schema:{tags:["Marketplace"],summary:"Uninstall a plugin",params:{type:"object",required:["name"],properties:{name:{type:"string"}}},body:{type:"object",properties:{scope:{type:"string",enum:["user","project"]},cwd:{type:"string"}}}}},async(e,s)=>{let a=_.object({name:_.string().min(1)}).safeParse(e.params);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(a.error)});let n=Zn.safeParse(e.body??{});if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:_.prettifyError(n.error)});if(!pe())return s.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return yr(a.data.name,n.data.scope,n.data.cwd),{success:!0,pluginId:a.data.name}}catch(i){return s.status(500).send({code:"CLI_ERROR",message:i instanceof Error?i.message:"Uninstall failed"})}})}import{z as Nt}from"zod/v4";var Jn=Nt.object({name:Nt.string().min(1)}),eo="x-api-key";async function Sa(o,r,e){o.post("/webhooks/:name",{schema:{tags:["Webhooks"],summary:"Trigger a webhook",description:"Trigger a task template execution by name or ID. Requires X-API-Key header if API key is configured.",security:[{apiKey:[]}],params:{type:"object",required:["name"],properties:{name:{type:"string",description:"Template name or ID"}}},response:R.webhookTriggered}},async(s,t)=>{if(e&&s.headers[eo]!==e)return t.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"});let a=Jn.safeParse(s.params);if(!a.success)return t.status(400).send({code:"VALIDATION_ERROR",message:Nt.prettifyError(a.error)});let{name:n}=a.data,i=ee(n);if(!i){let{listTaskTemplates:c}=await import("./task-templates-23YOAF3E.js");i=c(!1).find(d=>d.name===n||d.id===n)}if(!i)return t.status(404).send({code:"NOT_FOUND",message:`Template '${n}' not found`});if(!i.enabled)return t.status(409).send({code:"DISABLED",message:`Template '${n}' is disabled`});try{let c=await r.runNow(i.id);return t.status(202).send({code:"ACCEPTED",message:`Template '${i.name}' triggered`,executionId:c,templateId:i.id})}catch(c){let l=c instanceof Error?c.message:String(c);return t.status(500).send({code:"EXECUTION_ERROR",message:l})}}),o.get("/webhooks",{schema:{tags:["Webhooks"],summary:"List available webhooks",description:"List all enabled task templates that can be triggered via webhook, along with auth requirements.",response:R.webhookList}},async()=>{let{listTaskTemplates:s}=await import("./task-templates-23YOAF3E.js");return{webhooks:s(!0).map(a=>({name:a.id,displayName:a.name,description:a.description,tags:a.tags,trigger:`POST /webhooks/${a.id}`})),auth:e?"X-API-Key header required":"No auth configured"}})}import{z as I}from"zod/v4";var to=I.object({status:I.string().optional(),limit:I.coerce.number().min(1).max(100).default(20),offset:I.coerce.number().min(0).default(0)}),He=I.union([I.object({type:I.literal("session"),sessionId:I.string()}),I.object({type:I.literal("channel"),channelId:I.string(),chatId:I.string().optional()})]),so=I.object({input:I.string().min(1,"goal input is required"),deliverTo:I.array(He).optional(),reportTo:I.array(He).optional()}),wa=I.object({id:I.string().min(1)}),ro=I.object({name:I.string().min(1).optional(),description:I.string().optional(),status:I.enum(["active","paused","completed","failed"]).optional(),currentValue:I.number().optional(),budgetUsd:I.number().min(0).optional(),deliverTo:I.array(He).optional(),reportTo:I.array(He).optional()});async function Ca(o){o.get("/goals",{schema:{tags:["Goals"],summary:"List goals",description:"List goals with optional status filter and pagination.",querystring:{type:"object",properties:{status:{type:"string",description:"Filter by goal status"},limit:{type:"integer",minimum:1,maximum:100,default:20},offset:{type:"integer",minimum:0,default:0}}},response:R.goalList}},async(r,e)=>{let s=to.safeParse(r.query);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:I.prettifyError(s.error)});let{status:t,limit:a,offset:n}=s.data;return{goals:Rs(t,a,n)}}),o.get("/goals/:id",{schema:{tags:["Goals"],summary:"Get goal by ID",description:"Retrieve a single goal by its ID, including metric tree and progress.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},response:R.goalDetail}},async(r,e)=>{let s=ae(r.params.id);return s?{goal:s}:e.status(404).send({code:"NOT_FOUND",message:"Goal not found"})}),o.post("/goals",{schema:{tags:["Goals"],summary:"Create a goal",description:"Create a new goal from a natural language input. The input is parsed, validated, and a metric tree is built.",body:{type:"object",required:["input"],properties:{input:{type:"string",minLength:1,description:"Natural language goal description"},deliverTo:{type:"array",items:{type:"object"},description:"Delivery targets (result output)"},reportTo:{type:"array",items:{type:"object"},description:"Report targets (status notifications)"}}},response:R.goalCreated}},async(r,e)=>{let s=so.safeParse(r.body);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:I.prettifyError(s.error)});let t=await pr(s.data.input);if(!t.validationResult.isValid)return e.status(400).send({code:"INVALID_GOAL",errors:t.validationResult.errors,warnings:t.validationResult.warnings});let a=lr(t.goalState,s.data.deliverTo,s.data.reportTo);return ur(a.id,a.metricType),e.status(201).send({goal:a})}),o.patch("/goals/:id",{schema:{tags:["Goals"],summary:"Update a goal",description:"Partially update a goal's name, description, status, currentValue, or budgetUsd.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}},body:{type:"object",properties:{name:{type:"string",minLength:1},description:{type:"string"},status:{type:"string"},currentValue:{type:"number"},budgetUsd:{type:"number",minimum:0},deliverTo:{type:"array",items:{type:"object"},description:"Delivery targets (result output)"},reportTo:{type:"array",items:{type:"object"},description:"Report targets (status notifications)"}}},response:R.goalDetail}},async(r,e)=>{let s=wa.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:I.prettifyError(s.error)});let t=ro.safeParse(r.body);return t.success?ae(s.data.id)?(xe(s.data.id,{...t.data,updatedAt:Date.now()}),{goal:ae(s.data.id)}):e.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):e.status(400).send({code:"VALIDATION_ERROR",message:I.prettifyError(t.error)})}),o.delete("/goals/:id",{schema:{tags:["Goals"],summary:"Delete a goal",description:"Delete a goal by ID.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=wa.safeParse(r.params);return s.success?ae(s.data.id)?(Is(s.data.id),{goalId:s.data.id,deleted:!0}):e.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):e.status(400).send({code:"VALIDATION_ERROR",message:I.prettifyError(s.error)})})}import{z as Re}from"zod/v4";var ao=Re.object({role:Re.string().optional(),taskType:Re.string().optional(),limit:Re.coerce.number().min(1).max(100).default(50)});async function Aa(o){o.get("/strategies",{schema:{tags:["Strategies"],summary:"List strategies",description:"List agent strategies with optional role/taskType filter. Returns evolutionary strategy entries used for agent routing.",querystring:{type:"object",properties:{role:{type:"string",description:"Filter by role ID"},taskType:{type:"string",description:"Filter by task type"},limit:{type:"integer",minimum:1,maximum:100,default:50}}},response:R.strategyList}},async(r,e)=>{let s=ao.safeParse(r.query);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:Re.prettifyError(s.error)});let{role:t,taskType:a,limit:n}=s.data,i;return t&&a?i=Ts.getStrategies(t,a):t?i=vs(t):i=bs(n),{strategies:i.slice(0,n)}})}rs();Z();ns();import{z as Q}from"zod/v4";async function Pa(o){o.get("/config",{schema:{tags:["Config"],summary:"Get current configuration",description:"Returns the current server configuration with runtime-mutable vs restart-required indication for each setting.",response:R.configGet}},async(e,s)=>{let t=O(),a=kr(),n=await Tr(),i=[...Se,...Ze],c={},l=new Set(["anthropic.apiKey","server.apiKey"]);for(let d of i){let u=Je(t,d),f=Se.includes(d);l.has(d)&&typeof u=="string"&&u.length>0&&(u=u.slice(0,5)+"****"),c[d]={value:u??null,mutable:f}}return{config:c,mutable:[...Se],restartRequired:[...Ze],sandbox:{platform:a.platform,available:n},osCapabilities:{registry:as(a.platform,n)}}}),o.patch("/config",{schema:{tags:["Config"],summary:"Update runtime-mutable configuration",description:"Updates configuration values that can be changed at runtime. Restart-required settings are rejected but valid mutable changes are still applied (partial success).",response:R.configPatch}},async(e,s)=>{let t=e.body;if(!t||typeof t!="object")return s.status(400).send({success:!1,updated:[],errors:["Request body must be a JSON object with config key-value pairs"],message:"Validation error"});let a=Gt(t,ce);if(a.updated.includes("logging.level")){let n=t["logging.level"];typeof n=="string"&&Ce(n)}if(a.updated.length>0){let n=O(),i=a.updated.map(c=>({path:c,value:Je(n,c)}));h.emit({type:"config_changed",changes:i})}return{success:a.errors.length===0,updated:a.updated,errors:a.errors,message:a.errors.length===0?`Updated ${a.updated.length} configuration value(s)`:`Updated ${a.updated.length} value(s); ${a.errors.length} rejected (restart required)`}}),o.get("/config/env-diff",async()=>{let e=Pe();return{diffs:Qt(e),envFileExists:Kt()!==null}}),o.post("/config/sync-to-env",async()=>{let e=Pe();return{success:!0,changed:Yt(e)}}),o.post("/config/load-from-env",async()=>{let e=zt();if(!e)return{success:!1,error:".env file not found"};let s=0;for(let[a,n]of Object.entries(e)){let i=Object.entries(et).find(([,c])=>c===a)?.[0];i&&(ce(i,n),s++)}let t={};for(let[a,n]of Object.entries(e))a in et||a.startsWith("ANTHROPIC_")||a.startsWith("ADAM_")||(t[a]=n);return Object.keys(t).length>0&&(ce("defaults.env",t),O().defaults.env=t,s+=Object.keys(t).length),we(Pe),{success:!0,updated:s}});let r=Q.string().max(256).regex(/^[A-Za-z_][A-Za-z0-9_]*$/,"Env var key must match POSIX format: [A-Za-z_][A-Za-z0-9_]*").check(Q.refine(e=>!e.startsWith("ANTHROPIC_"),"ANTHROPIC_* keys are managed in the Anthropic config section"));o.get("/config/env",{schema:{tags:["Config"],summary:"Get custom environment variables",description:"Returns global custom env vars (defaults.env). Sensitive values are masked."}},async()=>({env:O().defaults?.env??{}})),o.put("/config/env",{schema:{tags:["Config"],summary:"Replace all custom environment variables",description:"Full replacement of defaults.env. ANTHROPIC_* keys are rejected."}},async(e,s)=>{let a=Q.record(r,Q.string().max(4096)).check(Q.refine(i=>Object.keys(i).length<=100,"Maximum 100 environment variables")).safeParse(e.body);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:Q.prettifyError(a.error)});let n=a.data;return ce("defaults.env",n),O().defaults.env=n,h.emit({type:"config_changed",changes:[{path:"defaults.env",value:n}]}),{success:!0,count:Object.keys(n).length}}),o.patch("/config/env",{schema:{tags:["Config"],summary:"Partially update custom environment variables",description:"Add/update keys (string value) or delete keys (null value). ANTHROPIC_* keys are rejected."}},async(e,s)=>{let a=Q.record(r,Q.string().max(4096).nullable()).safeParse(e.body);if(!a.success)return s.status(400).send({code:"VALIDATION_ERROR",message:Q.prettifyError(a.error)});let n={...O().defaults?.env??{}};for(let[i,c]of Object.entries(a.data))c===null?delete n[i]:n[i]=c;return Object.keys(n).length>100?s.status(400).send({code:"VALIDATION_ERROR",message:"Maximum 100 environment variables"}):(ce("defaults.env",n),O().defaults.env=n,h.emit({type:"config_changed",changes:[{path:"defaults.env",value:n}]}),{success:!0,count:Object.keys(n).length})})}async function _a(o){o.get("/audit/posture",async(r,e)=>{let s=await xr();return e.send(s)})}async function Ea(o){o.get("/evolution-audit",{schema:{tags:["Evolution"],summary:"List evolution audit records",description:"Returns evolution audit log entries with optional role filter.",querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:100,default:20},offset:{type:"integer",minimum:0,default:0},roleId:{type:"string"}}}}},async(r,e)=>{let{limit:s=20,offset:t=0,roleId:a}=r.query;return a?wr(a,s,t):Sr(s,t)})}import{z as k}from"zod/v4";var no=["active","archived"],oo=k.object({source:k.object({type:k.enum(["tui","web","api","channel"]),channelId:k.string().optional(),chatId:k.string().optional()}),roleId:k.string().optional()}),Ie=k.object({id:k.string().uuid()}),io=k.object({status:k.enum(no).optional(),limit:k.coerce.number().min(1).max(100).default(100),offset:k.coerce.number().min(0).default(0)}),co=k.object({limit:k.coerce.number().min(1).max(200).default(50),offset:k.coerce.number().min(0).default(0)});async function Oa(o){o.post("/chat/sessions",{schema:{tags:["Chat"],summary:"Create a chat session",body:{type:"object",required:["source"],properties:{source:{type:"object",required:["type"],properties:{type:{type:"string",enum:["tui","web","api","channel"]},channelId:{type:"string"},chatId:{type:"string"}}},roleId:{type:"string"}}}}},async(e,s)=>{let t=oo.safeParse(e.body);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let{source:a,roleId:n}=t.data,i=qe(a,n);return s.status(201).send({session:i})}),o.get("/chat/sessions",{schema:{tags:["Chat"],summary:"List chat sessions",querystring:{type:"object",properties:{status:{type:"string",enum:["active","archived"]},limit:{type:"integer",minimum:1,maximum:100,default:100},offset:{type:"integer",minimum:0,default:0}}}}},async(e,s)=>{let t=io.safeParse(e.query);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let{status:a}=t.data;return{sessions:ir(a)}}),o.get("/chat/sessions/:id",{schema:{tags:["Chat"],summary:"Get chat session with messages",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let a=B(t.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Session not found"});let n=mt(a.id);return{session:a,messages:n}}),o.post("/chat/sessions/:id/archive",{schema:{tags:["Chat"],summary:"Archive a chat session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let a=B(t.data.id);return a?(ar(a.id),{sessionId:a.id,status:"archived"}):s.status(404).send({code:"NOT_FOUND",message:"Session not found"})}),o.post("/chat/sessions/:id/restore",{schema:{tags:["Chat"],summary:"Restore an archived session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let a=nr(t.data.id);return a?{session:a}:s.status(404).send({code:"NOT_FOUND",message:"Session not found"})}),o.delete("/chat/sessions/:id",{schema:{tags:["Chat"],summary:"Delete a chat session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let a=B(t.data.id);return a?(or(a.id),s.status(204).send()):s.status(404).send({code:"NOT_FOUND",message:"Session not found"})}),o.get("/chat/sessions/:id/messages",{schema:{tags:["Chat"],summary:"Get messages for a session",params:{type:"object",required:["id"],properties:{id:{type:"string",format:"uuid"}}},querystring:{type:"object",properties:{limit:{type:"integer",minimum:1,maximum:200,default:50},offset:{type:"integer",minimum:0,default:0}}}}},async(e,s)=>{let t=Ie.safeParse(e.params);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let a=B(t.data.id);if(!a)return s.status(404).send({code:"NOT_FOUND",message:"Session not found"});let n=co.safeParse(e.query),{limit:i=50,offset:c=0}=n.success?n.data:{};return{messages:mt(a.id,i,c)}});let r=k.object({content:k.string().min(1,"content is required"),source:k.object({type:k.enum(["tui","web","api","channel"]),channelId:k.string().optional(),chatId:k.string().optional()}),roleId:k.string().optional(),sessionId:k.string().uuid().optional()});o.post("/chat/messages",{schema:{tags:["Chat"],summary:"Send a chat message",description:"Send a message. Creates a session if no active session exists for the source. Returns sessionId, messageId, and response.",body:{type:"object",required:["content","source"],properties:{content:{type:"string",minLength:1},source:{type:"object",required:["type"],properties:{type:{type:"string",enum:["tui","web","api","channel"]},channelId:{type:"string"},chatId:{type:"string"}}},roleId:{type:"string"},sessionId:{type:"string"}}}}},async(e,s)=>{let t=r.safeParse(e.body);if(!t.success)return s.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(t.error)});let{content:a,source:n,roleId:i,sessionId:c}=t.data,l=await Ve(a,n,i,c);return s.status(201).send(l)})}Z();var po=q("ws"),$e=new Set,Ke=[],lo=50;function uo(o){Ke.push(o),Ke.length>lo&&Ke.shift()}function le(o){uo(o);let r=JSON.stringify(o);for(let e of $e)e.readyState===1&&e.send(r)}function Fa(o){o.get("/chat/stream",{websocket:!0},(r,e)=>{$e.add(r);for(let s of Ke)r.readyState===1&&r.send(JSON.stringify(s));r.on("close",()=>{$e.delete(r)}),r.on("error",s=>{po.error({error:s},"Chat WebSocket error"),$e.delete(r)})}),h.on("session_created",r=>le(r)),h.on("session_archived",r=>le(r)),h.on("session_restored",r=>le(r)),h.on("session_deleted",r=>le(r)),h.on("chat_message",r=>le(r)),h.on("task_complete_event",r=>le(r))}Z();var j=q("channels"),ze=class{adapters=new Map;rateLimits=new Map;healthInterval;rateLimitPerMinute;constructor(r){this.rateLimitPerMinute=r?.rateLimitPerMinute??60}async addChannel(r,e){this.adapters.set(r.id,e),e.onMessage(s=>{this.handleInbound(r.id,s)}),r.enabled&&await this.connectChannel(r.id)}async removeChannel(r){let e=this.adapters.get(r);if(e){try{await e.disconnect()}catch(s){j.error({channelId:r,error:s},"Error disconnecting channel")}this.adapters.delete(r),this.rateLimits.delete(r)}}async connectChannel(r){let e=this.adapters.get(r);if(!e)throw new Error(`No adapter registered for channel ${r}`);try{de(r,"connecting"),await e.connect(),de(r,"connected"),j.info({channelId:r,platform:e.platform},"Channel connected")}catch(s){throw de(r,"error"),j.error({channelId:r,error:s},"Failed to connect channel"),s}}async disconnectChannel(r){let e=this.adapters.get(r);if(e)try{await e.disconnect(),de(r,"disconnected"),j.info({channelId:r},"Channel disconnected")}catch(s){j.error({channelId:r,error:s},"Error disconnecting channel")}}getChannelStatus(r){let e=this.adapters.get(r);return e?e.getStatus():"disconnected"}getChannelStatuses(){let r=new Map;for(let[e,s]of this.adapters)r.set(e,s.getStatus());return r}hasAdapter(r){return this.adapters.has(r)}async sendMessage(r,e,s){let t=this.adapters.get(r);if(!t)return j.warn({channelId:r},"No adapter for outbound message"),null;if(!this.checkRateLimit(r))return j.warn({channelId:r},"Rate limit exceeded, dropping outbound message"),null;try{return await t.sendMessage(e,s)}catch(a){return j.error({channelId:r,chatId:e,error:a},"Failed to send outbound message"),null}}checkRateLimit(r){let e=Date.now(),s=this.rateLimits.get(r);return!s||e-s.windowStart>=6e4?(this.rateLimits.set(r,{count:1,windowStart:e}),!0):s.count>=this.rateLimitPerMinute?!1:(s.count++,!0)}async handleInbound(r,e){if(e.source==="system"){j.debug({channelId:r},"Skipping system message (anti-loop)");return}try{let{isRecentlySent:t}=await import("./outbound-gateway-6K6P2BEH.js"),a=e.channelMessageId??e.raw?.MsgId??"";if(a&&t(String(a))){j.debug({channelId:r,messageId:a},"Skipping delivery-sent message (anti-loop)");return}}catch{}if(!this.checkRateLimit(r)){j.warn({channelId:r,senderId:e.senderId},"Rate limit exceeded for inbound message");return}try{let{handleInboundForApproval:t}=await import("./approval-handler-ORD4MUVM.js");if(await t(r,e.chatId,e.content)){j.debug({channelId:r,chatId:e.chatId},"Inbound message consumed as approval reply");return}}catch{}let s=Hs(r);if(s?.allowedChatIds&&!s.allowedChatIds.includes(e.chatId)){j.debug({channelId:r,chatId:e.chatId},"Chat not in allowlist, ignoring");return}try{let t=await Ve(e.content,{type:"channel",channelId:r,chatId:e.chatId},s?.linkedRoleId);j.info({channelId:r,chatId:e.chatId,sessionId:t.sessionId},"Inbound message routed to session")}catch(t){j.error({channelId:r,chatId:e.chatId,error:t},"Failed to route inbound message")}}startHealthMonitor(r=3e4){this.stopHealthMonitor(),this.healthInterval=setInterval(()=>{this.checkHealth()},r)}stopHealthMonitor(){this.healthInterval&&(clearInterval(this.healthInterval),this.healthInterval=void 0)}checkHealth(){for(let[r,e]of this.adapters){let s=e.getStatus();try{de(r,s)}catch{}}}async startAll(){let r=he(!0);for(let e of r){let s=this.adapters.get(e.id);if(s&&s.getStatus()!=="connected")try{await this.connectChannel(e.id)}catch{}}this.startHealthMonitor()}async stopAll(){this.stopHealthMonitor();for(let r of this.adapters.keys())await this.disconnectChannel(r);this.adapters.clear(),this.rateLimits.clear()}_getAdapterCount(){return this.adapters.size}_getRateLimitEntry(r){return this.rateLimits.get(r)}};Ae();Z();var U=q("watchdog"),Qe=null;function xa(o,r,e,s){if(!o.enabled){U.info("Watchdog disabled");return}let t=o.intervalMinutes*6e4;U.info({intervalMinutes:o.intervalMinutes},"Watchdog started"),Qe=setInterval(()=>{mo(o,r,e,s)},t)}function Da(){Qe&&(clearInterval(Qe),Qe=null,U.info("Watchdog stopped"))}function mo(o,r,e,s){let{rules:t}=o;if(t.managerHealthCheck.enabled){let a=t.managerHealthCheck.staleDurationMinutes*6e4,n=r.getLastActivityAt();if(Date.now()-n>a){let i=`ChatManager session stale (no activity for ${t.managerHealthCheck.staleDurationMinutes} min)`;if(U.warn(i),t.managerHealthCheck.action==="restart"){let c=r.getConsecutiveStaleCount()>0;r.restartSession(),c&&(U.fatal("ChatManager unrecoverable after session restart \u2014 exiting for supervisor restart"),process.exit(1))}else t.managerHealthCheck.action==="notify"&&s(i)}}if(!e.isHealthy()){let a="ExecutionPool is not healthy (stopped unexpectedly)";U.warn(a),s(a)}if(t.staleTasks.enabled){let a=t.staleTasks.maxPendingMinutes*6e4,i=V("pending").filter(c=>Date.now()-c.createdAt>a);if(i.length>0){let c=`${i.length} stale task(s) pending > ${t.staleTasks.maxPendingMinutes} min`;U.warn({count:i.length},c),t.staleTasks.action==="notify"&&s(c)}}if(t.staleRunningTasks?.enabled){let a=t.staleRunningTasks.maxRunningMinutes*6e4,i=V("running").filter(c=>{if(!c.startedAt||Date.now()-c.startedAt<a)return!1;try{let f=W().prepare("SELECT MAX(timestamp) as latest FROM step_logs WHERE task_id = ?").get(c.id)?.latest??c.startedAt;return Date.now()-f>a}catch{return!0}});if(i.length>0){let c=`${i.length} task(s) running with no activity for > ${t.staleRunningTasks.maxRunningMinutes} min \u2014 marking as failed`;U.warn({count:i.length,taskIds:i.map(l=>l.id)},c);for(let l of i)J(l.id,{status:"failed",error:`Watchdog timeout: no activity for > ${t.staleRunningTasks.maxRunningMinutes} min`,completedAt:Date.now()}),h.emit({type:"task_status_change",taskId:l.id,oldStatus:"running",newStatus:"failed"}),e.releaseSlot(l.id);s(c)}}if(t.dbMaintenance.enabled)try{let n=W().pragma("wal_checkpoint(PASSIVE)");U.debug({walSize:n},"WAL checkpoint")}catch(a){U.error({error:a},"DB health check failed")}if(t.artifactCleanup?.enabled)try{let a=t.artifactCleanup.ttlDays*24*60*60*1e3,n=t.artifactCleanup.orphanGcMinAgeHours*60*60*1e3,i=Date.now()-a,c=Er(i),l=0;for(let d of c){let u=new Set(Pr(d).map(T=>T.id));l+=Js(d,u,n);let f=_r(d);for(let T of f)T.blobPath&&(Xs(T.blobPath),l++);Zs(d)}c.length>0&&U.info({executions:c.length,files:l},"Workflow artifacts cleaned")}catch(a){U.error({error:a},"Workflow artifact cleanup failed")}}import{z as D}from"zod";import{v4 as go}from"uuid";var yo=D.object({eventType:D.enum(["task_complete","task_error","plan_approval_request","*"]),matchCriteria:D.object({templateId:D.string().optional(),roleId:D.string().optional(),promptPattern:D.string().optional(),taskStatus:D.string().optional()}).optional().default({}),target:D.object({type:D.enum(["channel","webhook"]),channelId:D.string().optional(),chatId:D.string().optional(),webhookUrl:D.string().optional()}),formatTemplate:D.string().optional(),maxPerMinute:D.number().int().min(1).max(60).optional().default(5),skipOriginChannel:D.boolean().optional().default(!0),enabled:D.boolean().optional().default(!0)});async function qt(o){o.get("/delivery-rules",async(r,e)=>vr()),o.post("/delivery-rules",async(r,e)=>{let s=yo.safeParse(r.body);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:D.prettifyError(s.error)});let t=s.data,a={id:go(),eventType:t.eventType,matchCriteria:t.matchCriteria,target:t.target,formatTemplate:t.formatTemplate,maxPerMinute:t.maxPerMinute,skipOriginChannel:t.skipOriginChannel,enabled:t.enabled,createdAt:Date.now()};return br(a),e.status(201).send(a)}),o.put("/delivery-rules/:id",async(r,e)=>{if(!Le(r.params.id))return e.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let t=r.body;return Rr(r.params.id,t),{id:r.params.id,updated:!0}}),o.delete("/delivery-rules/:id",async(r,e)=>Le(r.params.id)?(Ir(r.params.id),{id:r.params.id,deleted:!0}):e.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"})),o.get("/delivery-rules/:id/log",async(r,e)=>Cs(r.params.id)),o.post("/delivery-rules/:id/test",async(r,e)=>{let s=Le(r.params.id);if(!s)return e.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let{getDeliveryEngine:t}=await import("./engine-BM5BMPIC.js"),a=t();if(!a)return e.status(503).send({code:"ENGINE_NOT_READY",message:"DeliveryEngine not initialized"});let n=`[TEST] Delivery rule test at ${new Date().toISOString()}`,{createDeliveryLog:i}=await import("./delivery-log-VKONLSVD.js"),{v4:c}=await import("uuid"),{TTL_MS:l}=await import("./delivery-log-VKONLSVD.js"),d={id:c(),ruleId:s.id,status:"pending",target:s.target,content:n,attempts:0,createdAt:Date.now(),expiresAt:Date.now()+l};i(d);try{return await a.attemptDeliveryPublic(d,s),{id:d.id,ruleId:s.id,status:"sent",content:n}}catch(u){let f=u instanceof Error?u.message:String(u);return e.status(500).send({code:"DELIVERY_FAILED",message:f,logId:d.id})}})}import{z as te}from"zod/v4";var ja=new De,Na=te.object({id:te.string().min(1)}),fo=te.object({id:te.string().min(1),stepId:te.string().min(1)});async function qa(o){o.get("/workflow-executions",{schema:{tags:["Workflows"],summary:"List workflow executions",description:"List recent workflow executions, optionally filtered by templateId.",querystring:{type:"object",properties:{templateId:{type:"string",description:"Filter by template ID"},limit:{type:"number",default:50},offset:{type:"number",default:0}}}}},async r=>{let e=r.query;return{executions:er(e.templateId,e.limit??50,e.offset??0)}}),o.get("/workflow-executions/:id",{schema:{tags:["Workflows"],summary:"Get workflow execution",description:"Get details of a specific workflow execution including step statuses.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=Na.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:te.prettifyError(s.error)});let t=Ne(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Workflow execution not found"});let a=ye(s.data.id);return{execution:t,stepTasks:a}}),o.post("/workflow-executions/:id/cancel",{schema:{tags:["Workflows"],summary:"Cancel a workflow execution",description:"Cancel all running/pending step tasks in a workflow execution.",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(r,e)=>{let s=Na.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:te.prettifyError(s.error)});let t=Ne(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Workflow execution not found"});if(t.status!=="running")return e.status(400).send({code:"INVALID_STATE",message:`Cannot cancel workflow in status: ${t.status}`});let a=ye(s.data.id),n=new Set(["pending","running","queued","paused"]),i=0,c={...t.stepStatuses};for(let l of a)n.has(l.status)&&(ja.cancelTask(l.id),l.stepId&&(c[l.stepId]={taskId:l.id,status:"cancelled",roleId:l.roleId,error:"Workflow cancelled"}),i++);return yt(s.data.id,{status:"cancelled",stepStatuses:c,completedAt:Date.now()}),h.emit({type:"workflow_status_change",executionId:s.data.id,templateId:t.templateId,status:"cancelled"}),{executionId:s.data.id,cancelled:i,total:a.length}}),o.post("/workflow-executions/:id/steps/:stepId/skip",{schema:{tags:["Workflows"],summary:"Skip a workflow step",description:"Mark a pending step as skipped without cancelling the whole workflow. Dependents of the skipped step will also be skipped.",params:{type:"object",required:["id","stepId"],properties:{id:{type:"string"},stepId:{type:"string"}}}}},async(r,e)=>{let s=fo.safeParse(r.params);if(!s.success)return e.status(400).send({code:"VALIDATION_ERROR",message:te.prettifyError(s.error)});let t=Ne(s.data.id);if(!t)return e.status(404).send({code:"NOT_FOUND",message:"Workflow execution not found"});let a=t.stepStatuses[s.data.stepId];if(!a)return e.status(404).send({code:"NOT_FOUND",message:"Step not found in workflow"});if(a.taskId){let i=E(a.taskId);i&&["pending","running","queued","paused"].includes(i.status)&&ja.cancelTask(a.taskId)}let n={...t.stepStatuses};return n[s.data.stepId]={...a,status:"skipped",error:"Manually skipped"},yt(s.data.id,{stepStatuses:n}),{executionId:s.data.id,stepId:s.data.stepId,status:"skipped"}})}Z();ge();ge();import{existsSync as Ye,copyFileSync as ho,mkdirSync as Lt,cpSync as bo}from"fs";import{join as H}from"path";function Mt(){Lt(F,{recursive:!0}),Lt(H(F,"logs"),{recursive:!0}),Lt(H(F,".claude"),{recursive:!0})}function La(o=process.cwd()){Mt();let r=[],e=[{from:H(o,"data","adam.db"),to:H(F,"adam.db"),label:"database"},{from:H(o,"adam.config.yaml"),to:H(F,"adam.config.yaml"),label:"config"},{from:H(o,".env"),to:H(F,".env"),label:".env"}];for(let{from:a,to:n,label:i}of e)Ye(a)&&!Ye(n)&&(ho(a,n),r.push(i));let s=H(o,".claude","plugins"),t=H(F,".claude","plugins");return Ye(s)&&!Ye(t)&&(bo(s,t,{recursive:!0}),r.push("plugins")),r}rs();var A=q("adam");function Ro(o){let r={...o};if(r.defaults&&typeof r.defaults=="object"){let e={...r.defaults};if(e.env&&typeof e.env=="object"){let s={...e.env};for(let t of Object.keys(s))s[t]&&(s[t]=s[t].slice(0,4)+"****");e.env=s}r.defaults=e}if(r.server&&typeof r.server=="object"){let e={...r.server};e.apiKey&&typeof e.apiKey=="string"&&(e.apiKey=e.apiKey.slice(0,4)+"****"),r.server=e}return r}async function Io(){Mt();let o=La();o.length>0&&console.log(`[adam] Migrated to ~/.adam/: ${o.join(", ")}`);let r=qr();A.info("Starting Adam Agent Server"),r.length>0&&A.info({files:r},"Loaded env files");let e=Zt();Wt(e),O().anthropic?.apiKey||process.env.ANTHROPIC_API_KEY||A.warn("ANTHROPIC_API_KEY not set \u2014 configure via Settings UI or ~/.adam/.env"),process.env.ANTHROPIC_BASE_URL&&A.info({url:process.env.ANTHROPIC_BASE_URL},"Using custom API base URL");let t=e.defaults?.claudeCodePath;try{if(!t){let{createRequire:Va}=await import("module"),{dirname:Ga,join:Ha}=await import("path"),$a=Va(import.meta.url).resolve("@anthropic-ai/claude-agent-sdk");t=Ha(Ga($a),"cli.js")}let{execSync:v}=await import("child_process"),{chmodSync:N,accessSync:se,constants:me}=await import("fs");try{se(t,me.X_OK)}catch{A.info({path:t},"CLI not executable, fixing permissions"),N(t,493)}let Wa=v(`"${t}" --version`,{timeout:5e3,encoding:"utf-8"}).trim();A.info({path:t,version:Wa},"Claude Code CLI detected")}catch(v){let N=v;N.code==="ENOENT"?A.warn({path:t},"Claude Code CLI not found. Task execution will fail. Install: npm i -g @anthropic-ai/claude-code"):A.warn({path:t,error:(N.stderr?.trim()||String(v)).slice(0,200)},"Claude Code CLI check failed")}let n=W().prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all();A.info({tables:n.map(v=>v.name).join(", ")},"Database initialized");let i=Jt(),c=ss(i);c>0&&A.info({count:c},"Seeded config DB from .env");let{getAllConfig:l}=await import("./config-EMNKHR3W.js");we(l);let d=O();d.logging?.level&&Ce(d.logging.level),A.info({config:Ro(d)},"Config loaded (DB + defaults)");let u=Ct(),{getToolsFingerprint:f}=await import("./adam-tools-W5AOIGEQ.js"),T=f(),y=u.sdkSessionId;if(y&&u.toolsFingerprint!==T&&(A.info({old:u.toolsFingerprint?.slice(0,40),new:T.slice(0,40)},"MCP tools changed \u2014 invalidating old SDK session"),ta(),y=void 0),be({toolsFingerprint:T}),y){let v=process.cwd();u.workspacePath&&u.workspacePath!==v&&(A.warn({serverCwd:v,saved:u.workspacePath},"Workspace mismatch"),A.warn("SDK session may not resume correctly due to cwd mismatch")),A.info({sessionId:y.slice(0,8)},"Recovering manager SDK session")}else A.info("No previous manager SDK session found, starting fresh");u.userTaskSessionId&&A.info({sessionId:u.userTaskSessionId.slice(0,8)},"Recovering user task session"),sa(process.cwd());let{initializeDefaultRoles:g}=await import("./role-presets-K2BDRZBS.js"),P=g();A.info({count:P.length},"Roles initialized");let ie=O().execution??{maxConcurrent:3,pollIntervalMs:3e4},Y=new ve(y),X=new Rt(ie.maxConcurrent);Ra(Y),await Y.start(),await X.start();let ke=V("running");if(ke.length>0){A.warn({count:ke.length},"Found orphaned running tasks from previous session \u2014 marking as failed");for(let v of ke)J(v.id,{status:"failed",error:"Server restarted while task was running",completedAt:Date.now()})}let C=Ur(e,e.server.apiKey);await C.register(v=>Kr(v)),await C.register(v=>zr(v,e)),await C.register(v=>Zr(v,e.server.apiKey)),await C.register(ca),await C.register(ya),await C.register(Ca),await C.register(Aa);let $=new tr;sr($),await $.start(),Nr(),await C.register(v=>ka(v,$)),await C.register(Ta),await C.register(v=>Sa(v,$,process.env.ADAM_WEBHOOK_API_KEY)),await C.register(Pa),await C.register(_a),await C.register(Ea),await C.register(Oa);let ue=new ze;zs(ue),await C.register(Qs),await C.register(Fa),await C.register(v=>ea(v,e.server.apiKey)),await C.register(ga),await C.register(qt),await C.register(qa),cr(),Dr(),await Or(),ue.startHealthMonitor();try{let v=he();for(let N of v)if(N.platform==="wechat"){let se=N.config;if(se.botToken){let me=new $s(N.id,se);ue.addChannel(N,me)}}}catch(v){A.error({error:v},"Failed to register WeChat adapters at startup")}try{let v=he();for(let N of v)if(N.platform==="discord"){let se=N.config;if(se.botToken){let me=new Ks(N.id,{botToken:se.botToken});ue.addChannel(N,me)}}}catch(v){A.error({error:v},"Failed to register Discord adapters at startup")}let{host:Bt,port:Te}=e.server;await C.listen({host:Bt,port:Te}),A.info({host:Bt,port:Te},"Server listening");let Ua=e.watchdog??$t.watchdog;xa(Ua,Y,X,v=>{A.warn({alert:v},"Watchdog alert")}),Xt(v=>{h.emit({type:"log_event",timestamp:v.time??Date.now(),level:v.level??"info",component:v.component??"adam",msg:v.msg??""})}),Ba(F,{recursive:!0}),Ba(Xe(F,"logs"),{recursive:!0}),Ma(Xe(F,"adam.port"),String(Te)),e.server.apiKey&&Ma(Xe(F,"adam.key"),e.server.apiKey,{mode:384}),process.send?.({type:"ready",port:Te});let Ut=async()=>{A.info("Shutting down"),Da(),Fr(),dr(),jr(),await ue.stopAll(),Y.stop(),X.stop(),await $.stop(),await C.close(),tt();try{vo(Xe(F,"adam.key"))}catch{}process.exit(0)};process.on("SIGINT",()=>{Ut()}),process.on("SIGTERM",()=>{Ut()})}Io().catch(o=>{A.fatal(o,"Fatal error"),process.exit(1)});