adam-agent-server 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import{a as ks,b as Ts,d as kr,e as Tr}from"./chunk-7SPKRIMZ.js";import{c as Pr,d as _r}from"./chunk-NICRQZ7T.js";import{b as fr,c as yr}from"./chunk-B6S2AEOD.js";import{a as hr,b as br,d as vr}from"./chunk-2EP27EGS.js";import{b as Rr}from"./chunk-UOTDT2KY.js";import{a as fs,b as ys,c as wt,d as ws,e as Be,f as Ss,g as Cs,h as Ps,i as _s,j as Xs,k as Zs,l as er,m as tr,n as sr,o as rr,p as nr,q as or,r as ar,s as ir,t as cr,u as dr,v as ve,w as lr,y as _t}from"./chunk-2VKE7ONM.js";import{a as Js}from"./chunk-5JLMSNIW.js";import{a as us,c as ms,e as gs}from"./chunk-IXF3XBGX.js";import{a as mt,b as gt}from"./chunk-AXMXXUPO.js";import{a as pr,b as Ge,c as ur,d as mr,e as gr}from"./chunk-KICPHTI2.js";import{b as Ve,c as Vs,d as K,e as Gs,f as Hs,g as Ks,h as Ct,i as se,j as zs,n as Qs,o as Ys}from"./chunk-FUGJMHY4.js";import{b as Rs,c as Is}from"./chunk-5ASEAZCR.js";import{a as te,b as Tt,c as bs,e as vs}from"./chunk-742NWPTQ.js";import{b as $s,d as $e,f as be}from"./chunk-PQ7KPALO.js";import{h as ls,i as ps}from"./chunk-FDWW245P.js";import{a as St,b as Os,c as Fs}from"./chunk-2GXYBWLS.js";import{a as kt,b as hs}from"./chunk-WZOMGJSY.js";import{a as Us,c as Ws}from"./chunk-DT2LX4XI.js";import{b as le,c as We,d as qs,e as Bs}from"./chunk-WXN3PSVX.js";import{a as ut,b as D,c as H,d as M,e as os}from"./chunk-L7426WNY.js";import{a as f}from"./chunk-L7JP7DUO.js";import{a as As,b as Ue,c as Es,g as xs,j as Ds}from"./chunk-HAWA62R2.js";import{a as ds,b as wr,c as At,d as Sr,e as Cr,f as Ar}from"./chunk-EALDBELJ.js";import{b as Pt,c as He,d as Ir}from"./chunk-JXD6ZPV7.js";import{a as js,b as ne,c as Ns,d as Ls,g as Ms}from"./chunk-VF6GJGD6.js";import{b as ts,c as ss,d as rs,e as ns}from"./chunk-T25NLVMY.js";import{a as es}from"./chunk-ETQ7KC73.js";import{a as Ne,b as dt,c as Jt,d as U,e as Le,f as Me,g as Xt,h as lt}from"./chunk-FYDFMYUP.js";import"./chunk-TN6H2WM2.js";import{a as ee,b as we,c as vt,d as Rt,f as It}from"./chunk-U36NBCR3.js";import{a as as,b as is,c as Dn,e as ft,f as q,g as yt,h as ht,i as Te,j as bt,l as he}from"./chunk-XNWZZYAV.js";import{b as L,c as pt,d as ke}from"./chunk-PCSZW2PE.js";import{b as Zt,c as A,g as de}from"./chunk-SFUS33SO.js";import{a as cs,c as O,d as qe}from"./chunk-3DAK2XWP.js";import"./chunk-FCV2DPZQ.js";import{writeFileSync as _n,mkdirSync as An,unlinkSync as na}from"fs";import{join as ot}from"path";de();import{readFileSync as On,existsSync as Fn}from"fs";import{resolve as Et}from"path";function Er(o=A){let e=[],t=[],r=process.env.ADAM_ENV_FILE;r&&t.push(Et(o,r)),t.push(Et(o,".env.local")),t.push(Et(o,".env"));for(let s of t){if(!Fn(s))continue;jn(s)>0&&e.push(s)}return e}function jn(o){let t=On(o,"utf-8").split(`
2
- `),r=0;for(let s of t){let n=s.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7).trim());let a=n.indexOf("=");if(a===-1)continue;let i=n.slice(0,a).trim();if(!i)continue;let c=n.slice(a+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 h=d??m;return process.env[h]??""}),(i.startsWith("ANTHROPIC_")||process.env[i]===void 0)&&(process.env[i]=c,r++)}return r}ke();he();It();import{existsSync as xr}from"fs";import Nn from"path";import Ln from"fastify";import Mn from"@fastify/cors";import qn from"@fastify/static";import Bn from"@fastify/websocket";import Un from"@fastify/swagger";import Wn from"@fastify/swagger-ui";import{timingSafeEqual as $n}from"crypto";function Or(o,e){let t=Ln({logger:!1});if(t.register(Un,{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:"2.0.0"},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"}}}}}),t.register(Wn,{routePrefix:"/docs"}),t.register(Mn,{origin:!0}),t.register(Bn,{options:{maxPayload:1024*1024*16}}),e){let s=Buffer.from(e);t.addHook("onRequest",async(n,a)=>{let i=n.url;if(i==="/healthz"||i==="/readyz"||i.startsWith("/docs")||i.startsWith("/ui"))return;let c=n.headers["x-api-key"];if(c&&Dr(c,s))return;let l=n.query,d=l.api_key||l["x-api-key"];if(!(d&&Dr(d,s)))return a.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"})})}let r=Nn.join(ds,"web/dist");return xr(r)&&(t.register(qn,{root:r,prefix:"/ui/",wildcard:!1}),t.get("/ui",async(s,n)=>n.sendFile("index.html",r)),t.get("/ui/*",async(s,n)=>n.sendFile("index.html",r))),t.setErrorHandler((s,n,a)=>{if(s.validation){let c=s.validation.map(l=>{let d=l.instancePath||l.params?.missingProperty||"";return d?`${d}: ${l.message}`:l.message});return a.status(400).send({code:"VALIDATION_ERROR",message:c.join("; ")})}let i=s.statusCode??500;return a.status(i).send({code:"INTERNAL_ERROR",message:s.message})}),t.setNotFoundHandler((s,n)=>s.url.startsWith("/ui")&&xr(r)?n.sendFile("index.html",r):n.status(404).send({code:"NOT_FOUND",message:"Route not found"})),t}function Dr(o,e){try{let t=Buffer.from(o);return t.length!==e.length?!1:$n(t,e)}catch{return!1}}import{z as p}from"zod/v4";import{v4 as Jn}from"uuid";var Vn=o=>({...o,nullable:!0}),w={type:"object",properties:{code:{type:"string"},message:{type:"string"}}},Gn={type:"object",additionalProperties:!0,properties:{id:{type:"string"},prompt:{type:"string"},dependsOn:{type:"array",items:{type:"string"}},outputAs:{type:"string"}}},Hn={type:"object",additionalProperties:!0,properties:{type:{type:"string"},cron:{type:"string"},event:{type:"string"}}},Fr={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},description:{type:"string"},trigger:Hn,steps:{type:"array",items:Gn},agentPreference:{type:"string"},config:{type:"object",additionalProperties:!0},tags:{type:"array",items:{type:"string"}},enabled:{type:"boolean"},createdAt:{type:"number"},updatedAt:{type:"number"}}},Kn={type:"object",properties:{input:{type:"number"},output:{type:"number"}}},jr={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:Kn,numTurns:{type:"number"},totalDurationMs:{type:"number"}}},zn={type:"object",additionalProperties:!0,properties:{model:{type:"string"},effort:{type:"string"},maxTurns:{type:"number"}}},Ke={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},source:{type:"string"},traits:{type:"array",items:{type:"string"}},background:{type:"string"},preferences:zn,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"}}},xt={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"}}},Qn={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"}}},Dt={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"}}},Yn={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:Fr}}}},templateDetail:{200:{type:"object",properties:{template:Fr}},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:jr}}}},taskDetail:{200:{type:"object",properties:{task:jr}},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:Ke}}}},agentDetail:{200:{type:"object",properties:{agent:Ke}},404:w},agentCreated:{201:{type:"object",properties:{agent:Ke}}},agentUpdated:{200:{type:"object",properties:{agent:Ke}},404:w},agentDeleted:{200:{type:"object",properties:{agentId:{type:"string"},deleted:{type:"boolean"}}},400:w,404:w},agentPersona:{200:{type:"object",properties:{persona:Vn({type:"string"})}},404:w},memoryList:{200:{type:"object",properties:{memories:{type:"array",items:xt},count:{type:"number"}}},404:w},memoryQuery:{200:{type:"object",properties:{memories:{type:"array",items:xt},count:{type:"number"}}},404:w},memoryCreated:{201:{type:"object",properties:{memory:xt}},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:Qn}}}},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:Dt}}}},goalDetail:{200:{type:"object",properties:{goal:Dt}},404:w},goalCreated:{201:{type:"object",properties:{goal:Dt}},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:Yn},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 Nr=p.union([p.object({type:p.literal("session"),sessionId:p.string()}),p.object({type:p.literal("channel"),channelId:p.string(),chatId:p.string().optional()})]),Xn=p.object({prompt:p.string().min(1,"prompt is required"),roleId:p.string().optional(),deliverTo:p.array(Nr).optional(),reportTo:p.array(Nr).optional(),config:p.object({allowedTools:p.array(p.string()).optional(),disallowedTools:p.array(p.string()).optional(),maxTurns:p.number().optional(),maxBudgetUsd:p.number().optional(),mcpServers:p.record(p.string(),p.unknown()).optional(),model:p.string().optional(),effort:p.enum(["low","medium","high","max"]).optional(),settingSources:p.array(p.string()).optional(),workspacePath:p.string().optional(),timeout:p.number().optional(),approvalRequired:p.array(p.string()).optional(),approvalTimeout:p.number().optional(),fileAccess:p.object({allowedPaths:p.array(p.string()),deniedPaths:p.array(p.string())}).optional(),env:p.record(p.string(),p.string()).optional(),plugins:p.array(p.string()).optional()}).optional()}),pe=p.object({id:p.string().uuid()}),Zn=["pending","queued","running","paused","completed","failed","cancelled"],eo=p.object({status:p.enum(Zn).optional(),roleId:p.string().optional(),limit:p.coerce.number().min(1).max(100).default(100),offset:p.coerce.number().min(0).default(0)});async function Lr(o){let e=new ys;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(n,a)=>{let i=Xn.safeParse(n.body);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let{prompt:c,roleId:l,config:d,deliverTo:m,reportTo:h}=i.data,I=rs(),y={timeout:d?.timeout??I.timeout,approvalRequired:d?.approvalRequired??I.approvalRequired,approvalTimeout:d?.approvalTimeout??I.approvalTimeout,fileAccess:d?.fileAccess??I.fileAccess,allowedTools:d?.allowedTools??I.allowedTools,disallowedTools:d?.disallowedTools??I.disallowedTools,maxTurns:d?.maxTurns??I.maxTurns,maxBudgetUsd:d?.maxBudgetUsd??I.maxBudgetUsd,mcpServers:d?.mcpServers,model:d?.model||I.model||void 0,effort:d?.effort??I.effort,settingSources:d?.settingSources??I.settingSources,workspacePath:d?.workspacePath,env:d?.env??I.env,claudeCodePath:I.claudeCodePath,plugins:d?.plugins},g={id:Jn(),status:"pending",prompt:c,roleId:l,config:y,deliverTo:m,reportTo:h,createdAt:Date.now()};return ut(g),f.emit({type:"task_created",taskId:g.id}),a.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:R.taskList}},async(n,a)=>{let i=eo.safeParse(n.query);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let{status:c,roleId:l,limit:d,offset:m}=i.data;return{tasks:M(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:R.taskDetail}},async(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=D(i.data.id);return c?{task:c}:a.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=D(i.data.id);return c?c.status!=="running"&&c.status!=="queued"&&c.status!=="pending"&&c.status!=="paused"?a.status(400).send({code:"INVALID_STATE",message:`Cannot cancel task in status: ${c.status}`}):(e.cancelTask(c.id),{taskId:c.id,status:"cancelled"}):a.status(404).send({code:"NOT_FOUND",message:"Task not found"})});let t=p.object({taskIds:p.array(p.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(n,a)=>{let i=t.safeParse(n.body);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=new Set(["pending","queued","running","paused"]),l=0,d=[];for(let m of i.data.taskIds){let h=D(m);if(!h){d.push({taskId:m,reason:"not found"});continue}if(!c.has(h.status)){d.push({taskId:m,reason:`already ${h.status}`});continue}e.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(n,a)=>{let i=D(n.params.id);if(!i)return a.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:c=50,offset:l=0}=n.query;return{logs:gt(i.id,c,l)}});let r=p.object({approvalId:p.string().uuid(),reason:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=r.safeParse(n.body);return c.success?D(i.data.id)?e.resolveApproval(c.data.approvalId,"allow",c.data.reason)?{approvalId:c.data.approvalId,decision:"allow"}:a.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):a.status(404).send({code:"NOT_FOUND",message:"Task not found"}):a.status(400).send({code:"VALIDATION_ERROR",message:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=r.safeParse(n.body);return c.success?D(i.data.id)?e.resolveApproval(c.data.approvalId,"deny",c.data.reason)?{approvalId:c.data.approvalId,decision:"deny"}:a.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):a.status(404).send({code:"NOT_FOUND",message:"Task not found"}):a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(c.error)})});let s=p.object({planId:p.string(),decision:p.enum(["allow","deny"]),approvalType:p.enum(["once","permanent"]).optional(),reason:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=s.safeParse(n.body);if(!c.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(c.error)});if(!D(i.data.id))return a.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{planId:d,decision:m,approvalType:h,reason:I}=c.data;return e.resolvePlanApproval(d,m,h,I)?{planId:d,decision:m,approvalType:h}:a.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(n,a)=>{let i=pe.safeParse(n.params);return i.success?D(i.data.id)?{plans:ms(i.data.id)}:a.status(404).send({code:"NOT_FOUND",message:"Task not found"}):a.status(400).send({code:"VALIDATION_ERROR",message:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=D(i.data.id);if(!c)return a.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:l=50}=n.query;return{logs:ls(c.id,l)}})}ke();he();async function Mr(o,e){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(t,r)=>({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(t,r)=>{let s={database:!1,manager:!1,config:!1};try{L().prepare("SELECT 1").get(),s.database=!0}catch{s.database=!1}s.manager=!0,s.config=!!e.server;try{let a=Te(void 0,1,0);s.agents=a.length>0}catch{s.agents=!1}return s.embedding=hs(),s.taskHub=!0,Object.values(s).every(a=>a)?{status:"ready",checks:s}:r.status(503).send({status:"not_ready",checks:s})}),o.get("/stats",{schema:{tags:["Health"],summary:"Runtime statistics",description:"Returns execution pool status, active/pending task counts, and cost summary."}},async(t,r)=>{let n=U().execution?.maxConcurrent??5,a=M("running"),i=M("pending");return{executionPool:{active:a.length,max:n,queued:i.length}}})}import{timingSafeEqual as Br}from"crypto";import{z as Ur}from"zod/v4";var Ot=class{connections=new Map;eventBuffers=new Map;eventIndices=new Map;addConnection(e,t){this.connections.has(e)||this.connections.set(e,new Set),this.connections.get(e).add(t);let r=this.getBufferedEvents(e);for(let s of r)t.readyState===1&&t.send(JSON.stringify(s));t.on("close",()=>{this.removeConnection(e,t)})}removeConnection(e,t){let r=this.connections.get(e);r&&(r.delete(t),r.size===0&&this.connections.delete(e))}broadcast(e,t){this.addToBuffer(e,t);let r=this.connections.get(e);if(!r||r.size===0)return;let s=JSON.stringify(t);for(let n of r)n.readyState===1&&n.send(s)}addToBuffer(e,t){let r=this.eventBuffers.get(e);r||(r=[],this.eventBuffers.set(e,r)),r.push(t),r.length>100&&r.shift(),this.eventIndices.set(e,t.index)}getBufferedEvents(e){return this.eventBuffers.get(e)??[]}getNextIndex(e){let r=(this.eventIndices.get(e)??0)+1;return this.eventIndices.set(e,r),r}},qr=new Ot;var to=Ur.object({id:Ur.string().uuid()});async function Wr(o,e){o.get("/tasks/:id/stream",{websocket:!0},(t,r)=>{if(e&&!so(r,e)){t.close(4401,"Unauthorized");return}let s=to.safeParse(r.params);if(!s.success){t.close(1008,"Invalid task ID");return}let{id:n}=s.data;if(!D(n)){t.close(1008,"Task not found");return}qr.addConnection(n,t)})}function so(o,e){let t=o.headers["x-api-key"];if(t)try{let n=Buffer.from(t),a=Buffer.from(e);if(n.length===a.length&&Br(n,a))return!0}catch{}let r=o.query,s=r.api_key||r["x-api-key"];if(s)try{let n=Buffer.from(s),a=Buffer.from(e);if(n.length===a.length&&Br(n,a))return!0}catch{}return!1}import{timingSafeEqual as $r}from"crypto";var ro=O("ws"),ze=new Set;function Vr(o,e){o.get("/events",{websocket:!0},(t,r)=>{if(e&&!no(r,e)){t.close(4401,"Unauthorized");return}ze.add(t),t.on("close",()=>{ze.delete(t)}),t.on("error",s=>{ro.error({error:s},"WebSocket error"),ze.delete(t)})}),f.on("task_status_change",t=>{z(t)}),f.on("approval_request",t=>{z(t)}),f.on("stats_update",t=>{z(t)}),f.on("log_event",t=>{z(t)}),f.on("config_changed",t=>{z(t)}),f.on("plan_approval_request",t=>{(()=>{try{let s=vs(t.taskId);if(!s)return!1;let n=Rs(s.sessionId);return n?n.source.type==="channel"&&!!n.source.channelId:!1}catch{return!1}})()||z(t)}),f.on("plan_approval_decision",t=>{z(t)}),f.on("task_created",t=>{z(t)}),f.on("execution_slot_change",t=>{z(t)}),f.on("execution_task_start",t=>{z(t)}),f.on("execution_task_end",t=>{z(t)}),f.on("delivery_status_change",t=>{z(t)})}function z(o){let e=JSON.stringify(o);for(let t of ze)t.readyState===1&&t.send(e)}function no(o,e){let t=o.headers["x-api-key"];if(t)try{let n=Buffer.from(t),a=Buffer.from(e);if(n.length===a.length&&$r(n,a))return!0}catch{}let r=o.query,s=r.api_key||r["x-api-key"];if(s)try{let n=Buffer.from(s),a=Buffer.from(e);if(n.length===a.length&&$r(n,a))return!0}catch{}return!1}ke();function oo(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 Ft(){let o=L(),e=o.prepare("SELECT * FROM server_state WHERE id = 1").get();if(e)return oo(e);let t=Date.now();return o.prepare("INSERT INTO server_state (id, created_at) VALUES (1, ?)").run(t),{id:1,createdAt:t}}function Se(o){let e=L(),t=[],r=[];"sdkSessionId"in o&&(t.push("sdk_session_id = ?"),r.push(o.sdkSessionId??null)),"userTaskSessionId"in o&&(t.push("user_task_session_id = ?"),r.push(o.userTaskSessionId??null)),"workspacePath"in o&&(t.push("workspace_path = ?"),r.push(o.workspacePath??null)),"lastActiveAt"in o&&(t.push("last_active_at = ?"),r.push(o.lastActiveAt??null)),"toolsFingerprint"in o&&(t.push("tools_fingerprint = ?"),r.push(o.toolsFingerprint??null)),t.length!==0&&(Ft(),r.push(1),e.prepare(`UPDATE server_state SET ${t.join(", ")} WHERE id = ?`).run(...r))}function Qe(o){Se({sdkSessionId:o,lastActiveAt:Date.now()})}function Gr(){Se({sdkSessionId:void 0,lastActiveAt:Date.now()})}function Hr(o){Se({workspacePath:o})}he();It();import{z as u}from"zod/v4";import{v4 as Kr}from"uuid";_s();import{rmSync as ao,existsSync as jt}from"fs";var zr=u.object({model:u.string().optional(),effort:u.enum(["low","medium","high","max"]).optional(),maxTurns:u.number().optional()}),Qr=u.object({path:u.string(),inheritPlugins:u.boolean().optional(),inheritMcp:u.boolean().optional(),inheritPermissions:u.boolean().optional()}),io=u.object({name:u.string().min(1,"name is required").regex(/^[\p{L}\p{N}_-]+$/u,"name must contain only letters, numbers, underscores, or hyphens"),cagPrompt:u.string().optional(),learnedRules:u.array(u.string()).optional(),allowedTools:u.array(u.string()).optional(),disallowedTools:u.array(u.string()).optional(),evaluationCriteria:u.record(u.string(),u.number()).optional(),executionMode:u.enum(["isolated","inline"]).optional(),model:u.string().optional(),maxBudgetUsd:u.number().optional(),approvalRequired:u.array(u.string()).optional(),preferences:zr.optional(),additionalDirectories:u.array(Qr).optional(),allowedChannels:u.array(u.string()).optional(),inheritUserSettings:u.boolean().optional()}),co=u.object({name:u.string().min(1).optional(),cagPrompt:u.string().optional(),learnedRules:u.array(u.string()).optional(),status:u.enum(["active","inactive","retired"]).optional(),allowedTools:u.array(u.string()).optional(),disallowedTools:u.array(u.string()).optional(),evaluationCriteria:u.record(u.string(),u.number()).optional(),executionMode:u.enum(["isolated","inline"]).optional(),model:u.string().optional(),maxBudgetUsd:u.number().optional(),approvalRequired:u.array(u.string()).optional(),preferences:zr.optional(),additionalDirectories:u.array(Qr).optional(),allowedChannels:u.array(u.string()).nullable().optional(),inheritUserSettings:u.boolean().optional()}),Ye=u.object({id:u.string().min(1)}),lo=u.object({status:u.enum(["active","inactive","retired"]).optional(),limit:u.coerce.number().min(1).max(100).default(100),offset:u.coerce.number().min(0).default(0)}),po=u.object({path:u.string().min(1)});async function Yr(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(e,t)=>{let r=lo.safeParse(e.query);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let{status:s,limit:n,offset:a}=r.data;return{roles:Te(s,n,a).map(c=>({...c,workspacePath:ee(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(e,t)=>{let r=io.safeParse(e.body);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let{name:s,cagPrompt:n,learnedRules:a,allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:m,maxBudgetUsd:h,approvalRequired:I,preferences:y,additionalDirectories:g,allowedChannels:C,inheritUserSettings:W}=r.data;if(yt(s))return t.status(409).send({code:"CONFLICT",message:`Role with name '${s}' already exists`});let $={id:`role-${Kr().slice(0,8)}`,name:s,cagPrompt:n??"",learnedRules:a??[],memoryStreamId:`mem-${Kr().slice(0,8)}`,status:"active",preferences:y??{},allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:m,maxBudgetUsd:h,approvalRequired:I,additionalDirectories:g,allowedChannels:C,inheritUserSettings:W,createdAt:Date.now()};return ft($),we($),t.status(201).send({role:$})}),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(e,t)=>{let r=Ye.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=q(r.data.id);if(!s)return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=ee(s.name),a=Be({scope:"project",projectPath:n});return{role:s,projectPlugins:a,workspacePath:n}}),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(e,t)=>{let r=u.object({id:u.string().min(1)}).safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=q(r.data.id);if(!s)return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=e.query.limit??20,a=ks(s.id,n),i=Ts(s.id);return{scores:a,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"]},preferences:{type:"object",properties:{model:{type:"string"},effort:{type:"string",enum:["low","medium","high","max"]},maxTurns:{type:"number"}}}}}}},async(e,t)=>{let r=Ye.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=co.safeParse(e.body);if(!s.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(s.error)});if(!q(r.data.id))return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let{allowedChannels:a,...i}=s.data,c={...i,updatedAt:Date.now()};if(a!==void 0&&(c.allowedChannels=a??void 0),ht(r.data.id,c),s.data.cagPrompt!==void 0||s.data.learnedRules!==void 0){let d=q(r.data.id);if(d){let m=ee(d.name);jt(m)&&vt(m,d)}}let l=q(r.data.id);if(l&&(s.data.allowedTools!==void 0||s.data.disallowedTools!==void 0)){let d=ee(l.name);jt(d)&&Rt(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(e,t)=>{let r=Ye.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=q(r.data.id);if(!s)return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=ee(s.name);if(jt(n))try{ao(n,{recursive:!0,force:!0})}catch{}return bt(r.data.id),{roleId:r.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(e,t)=>{let r=Ye.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=po.safeParse(e.body);if(!s.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(s.error)});if(!q(r.data.id))return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let a=Ps(s.data.path);return{path:s.data.path,enabledPlugins:a.enabledPlugins,mcpServers:a.mcpServers,allowedTools:a.allowedTools,disallowedTools:a.disallowedTools}})}de();import{z as Jr}from"zod/v4";import{readdirSync as uo,existsSync as mo}from"fs";import{join as Nt,resolve as Xr,sep as en}from"path";import{homedir as go}from"os";var fo=20,yo=Jr.object({prefix:Jr.string()});function tn(o){return o.startsWith("~/")?Nt(go(),o.slice(2)):o}function Zr(o){let e=Xr(o);for(let t of Zt){let r=tn(t),s=Xr(r);if(e===s||e.startsWith(s+en))return!0}return!1}async function sn(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(e,t)=>{let r=yo.safeParse(e.query);if(!r.success)return{suggestions:[]};let{prefix:s}=r.data;if(!s.startsWith("/")&&!s.startsWith("~/"))return{suggestions:[]};if(Zr(s))return{suggestions:[]};let n=tn(s),a,i;if(s.endsWith("/"))a=n,i="";else{let g=Math.max(n.lastIndexOf("/"),n.lastIndexOf(en));if(g<0)return{suggestions:[]};a=n.slice(0,g+1),i=n.slice(g+1)}if(!mo(a))return{suggestions:[]};let c;try{c=uo(a,{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)),I=(i.startsWith(".")?d:d.filter(g=>!g.startsWith("."))).filter(g=>!Zr(Nt(a,g)));return I.sort((g,C)=>g.localeCompare(C,void 0,{sensitivity:"base"})),{suggestions:I.slice(0,fo).map(g=>Nt(a,g))}})}import{z as S}from"zod/v4";he();import{v4 as ho}from"uuid";var bo=S.object({roleId:S.string().min(1)}),vo=S.object({roleId:S.string().min(1),prompt:S.string().min(1),topK:S.number().min(1).max(50).default(10)}),Ro=S.object({limit:S.coerce.number().min(1).max(200).default(50),offset:S.coerce.number().min(0).default(0)});function Lt(o){return q(o)!==void 0}async function rn(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(r,s)=>{let n=bo.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(n.error)});let a=n.data.roleId;if(!Lt(a))return s.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let i=Ro.safeParse(r.query),{limit:c,offset:l}=i.success?i.data:{limit:50,offset:0},m=xs(a,c,l).map(({embedding:h,...I})=>I);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:R.memoryQuery}},async(r,s)=>{let n=vo.safeParse(r.body);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(n.error)});let{roleId:a,prompt:i,topK:c}=n.data;if(!Lt(a))return s.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let d=(await St(a,i,{topK:c})).map(({embedding:m,...h})=>h);return{memories:d,count:d.length}});let e=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:R.memoryCreated}},async(r,s)=>{let n=e.safeParse(r.body);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(n.error)});let{roleId:a,content:i,type:c,keywords:l,importance:d,tier:m}=n.data;if(!Lt(a))return s.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let h;try{h=await kt(i)}catch{}let I=`mem-${ho().slice(0,8)}`,y=Date.now();As({id:I,roleId:a,type:c,content:i,embedding:h,keywords:l,importance:d,sourceType:"manual",createdAt:y,lastAccessed:y,retrievedCount:0,tier:m??"episodic"});let g=Ue(I),{embedding:C,...W}=g;return s.status(201).send({memory:W})});let t=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:R.memoryUpdated}},async(r,s)=>{let{id:n}=r.params;if(!Ue(n))return s.status(404).send({code:"NOT_FOUND",message:"Memory not found"});let i=t.safeParse(r.body);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(i.error)});let c=i.data,l,d=!0;if(c.content)try{l=await kt(c.content)}catch{d=!1}let m=Es(n,{content:c.content,embedding:l,keywords:c.keywords,importance:c.importance,type:c.type});return{memoryId:n,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:R.memoryDeleted}},async(r,s)=>{let{id:n}=r.params;return Ue(n)?(Ds(n),{memoryId:n,deleted:!0}):s.status(404).send({code:"NOT_FOUND",message:"Memory not found"})})}import{query as So}from"@anthropic-ai/claude-agent-sdk";import{v4 as ue}from"uuid";Dn();de();var Io=new Set(["Read","Glob","Grep","LSP"]),ko=new Set(["Edit","Write","NotebookEdit"]);function Ce(o,e){return async(t,r,{agentID:s})=>{if(Io.has(t))return{behavior:"allow",updatedInput:r};let n=o(s??"");if(ko.has(t)){let a=as(t,r),i=A;if(a.length===0)return{behavior:"allow",updatedInput:r};let c={allowedPaths:n?.allowedPaths??[],deniedPaths:n?.deniedPaths??[]};for(let l of a){let d=is(l,i,c);if(!d.allowed)return{behavior:"deny",message:`Path denied: ${d.reason}. Try an alternative within allowed paths.`}}return{behavior:"allow",updatedInput:r}}if(n?.disallowedTools?.includes(t))return{behavior:"deny",message:`Tool ${t} is not allowed for this role.`};if(e&&n?.approvalRequired?.length){let a=t==="Bash"?r.command??"":`${t} ${JSON.stringify(r)}`;for(let i of n.approvalRequired)try{if(new RegExp(i).test(a))return await e(t,r,i,s)}catch{}}return{behavior:"allow",updatedInput:r}}}function Pe(o){return{SessionStart:[{hooks:[async e=>{if(!o.roleId)return{};let t=e.source,r=o.roleId==="role-chat-manager";if(!r&&t!=="startup"&&t!=="resume")return{};try{let{queryMemoryByTier:s}=await import("./memory-service-BKLZIRK6.js"),n=o.taskPrompt||"role context and recent interactions",a=r?["semantic","working"]:["semantic","episodic"],i=await s(o.roleId,n,a,{topK:5});if(i.length>0)return{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:`[Memory Context]
1
+ import{a as ws,b as Ss,d as wr,e as Sr}from"./chunk-7SPKRIMZ.js";import{c as Ar,d as Er}from"./chunk-KMMC7BEF.js";import{b as hr,c as br}from"./chunk-B6S2AEOD.js";import{a as vr,b as Rr,d as Ir}from"./chunk-2EP27EGS.js";import{b as kr}from"./chunk-LBLERTM4.js";import{a as hs,b as bs,c as St,d as Cs,e as Ue,f as Ps,g as _s,h as As,i as Es,j as er,k as tr,l as sr,m as rr,n as nr,o as or,p as ar,q as ir,r as cr,s as dr,t as lr,u as pr,v as ve,w as ur,y as At}from"./chunk-BQE7XAMQ.js";import{a as Zs}from"./chunk-5JLMSNIW.js";import{a as gs,c as fs,e as ys}from"./chunk-IXF3XBGX.js";import{a as gt,b as ft}from"./chunk-AXMXXUPO.js";import{a as mr,b as He,c as gr,d as fr,e as yr}from"./chunk-KICPHTI2.js";import{b as Ge,c as Hs,d as K,e as Ks,f as zs,g as Qs,h as Pt,i as se,j as Ys,n as Js,o as Xs}from"./chunk-FUGJMHY4.js";import{b as ks,c as Ts}from"./chunk-5ASEAZCR.js";import{a as te,b as wt,c as Rs,e as Is}from"./chunk-742NWPTQ.js";import{b as Gs,d as $e,f as be}from"./chunk-PQ7KPALO.js";import{h as us,i as ms}from"./chunk-FDWW245P.js";import{a as Ct,b as js,c as Ns}from"./chunk-2GXYBWLS.js";import{a as Tt,b as vs}from"./chunk-WZOMGJSY.js";import{a as Vs,c as $s}from"./chunk-DT2LX4XI.js";import{b as le,c as Ve,d as Us,e as Ws}from"./chunk-WXN3PSVX.js";import{a as mt,b as D,c as H,d as q,e as as}from"./chunk-L7426WNY.js";import{a as f}from"./chunk-L7JP7DUO.js";import{a as xs,b as We,c as Ds,g as Os,j as Fs}from"./chunk-HAWA62R2.js";import{a as ls,b as Be,c as ps,d as Cr,e as Et,f as Pr,g as _r,h as xr}from"./chunk-T7WVM27S.js";import{b as _t,c as Ke,d as Tr}from"./chunk-JXD6ZPV7.js";import{a as Ls,b as ne,c as qs,d as Ms,g as Bs}from"./chunk-VF6GJGD6.js";import{b as ss,c as rs,d as ns,e as os}from"./chunk-T25NLVMY.js";import{a as ts}from"./chunk-ETQ7KC73.js";import{a as Ne,b as lt,c as Xt,d as U,e as Le,f as qe,g as Zt,h as pt}from"./chunk-FYDFMYUP.js";import"./chunk-TN6H2WM2.js";import{a as ee,b as we,c as Rt,d as It,f as kt}from"./chunk-U36NBCR3.js";import{a as is,b as cs,c as Fn,e as yt,f as M,g as ht,h as bt,i as Te,j as vt,l as he}from"./chunk-XNWZZYAV.js";import{b as L,c as ut,d as ke}from"./chunk-PCSZW2PE.js";import{b as es,c as A,g as de}from"./chunk-SFUS33SO.js";import{a as ds,c as O,d as Me}from"./chunk-3DAK2XWP.js";import"./chunk-FCV2DPZQ.js";import{writeFileSync as En,mkdirSync as xn,unlinkSync as aa}from"fs";import{join as at}from"path";de();import{readFileSync as jn,existsSync as Nn}from"fs";import{resolve as xt}from"path";function Dr(o=A){let e=[],t=[],r=process.env.ADAM_ENV_FILE;r&&t.push(xt(o,r)),t.push(xt(o,".env.local")),t.push(xt(o,".env"));for(let s of t){if(!Nn(s))continue;Ln(s)>0&&e.push(s)}return e}function Ln(o){let t=jn(o,"utf-8").split(`
2
+ `),r=0;for(let s of t){let n=s.trim();if(!n||n.startsWith("#"))continue;n.startsWith("export ")&&(n=n.slice(7).trim());let a=n.indexOf("=");if(a===-1)continue;let i=n.slice(0,a).trim();if(!i)continue;let c=n.slice(a+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 h=d??m;return process.env[h]??""}),(i.startsWith("ANTHROPIC_")||process.env[i]===void 0)&&(process.env[i]=c,r++)}return r}ke();he();kt();import{existsSync as Or}from"fs";import qn from"path";import Mn from"fastify";import Bn from"@fastify/cors";import Un from"@fastify/static";import Wn from"@fastify/websocket";import Vn from"@fastify/swagger";import $n from"@fastify/swagger-ui";import{timingSafeEqual as Gn}from"crypto";function jr(o,e){let t=Mn({logger:!1});if(t.register(Vn,{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:Be()},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"}}}}}),t.register($n,{routePrefix:"/docs"}),t.register(Bn,{origin:!0}),t.register(Wn,{options:{maxPayload:1024*1024*16}}),e){let s=Buffer.from(e);t.addHook("onRequest",async(n,a)=>{let i=n.url;if(i==="/healthz"||i==="/readyz"||i.startsWith("/docs")||i.startsWith("/ui"))return;let c=n.headers["x-api-key"];if(c&&Fr(c,s))return;let l=n.query,d=l.api_key||l["x-api-key"];if(!(d&&Fr(d,s)))return a.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"})})}let r=qn.join(ls,"web/dist");return Or(r)&&(t.register(Un,{root:r,prefix:"/ui/",wildcard:!1}),t.get("/ui",async(s,n)=>n.sendFile("index.html",r)),t.get("/ui/*",async(s,n)=>n.sendFile("index.html",r))),t.setErrorHandler((s,n,a)=>{if(s.validation){let c=s.validation.map(l=>{let d=l.instancePath||l.params?.missingProperty||"";return d?`${d}: ${l.message}`:l.message});return a.status(400).send({code:"VALIDATION_ERROR",message:c.join("; ")})}let i=s.statusCode??500;return a.status(i).send({code:"INTERNAL_ERROR",message:s.message})}),t.setNotFoundHandler((s,n)=>s.url.startsWith("/ui")&&Or(r)?n.sendFile("index.html",r):n.status(404).send({code:"NOT_FOUND",message:"Route not found"})),t}function Fr(o,e){try{let t=Buffer.from(o);return t.length!==e.length?!1:Gn(t,e)}catch{return!1}}import{z as p}from"zod/v4";import{v4 as Zn}from"uuid";var Hn=o=>({...o,nullable:!0}),w={type:"object",properties:{code:{type:"string"},message:{type:"string"}}},Kn={type:"object",additionalProperties:!0,properties:{id:{type:"string"},prompt:{type:"string"},dependsOn:{type:"array",items:{type:"string"}},outputAs:{type:"string"}}},zn={type:"object",additionalProperties:!0,properties:{type:{type:"string"},cron:{type:"string"},event:{type:"string"}}},Nr={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},description:{type:"string"},trigger:zn,steps:{type:"array",items:Kn},agentPreference:{type:"string"},config:{type:"object",additionalProperties:!0},tags:{type:"array",items:{type:"string"}},enabled:{type:"boolean"},createdAt:{type:"number"},updatedAt:{type:"number"}}},Qn={type:"object",properties:{input:{type:"number"},output:{type:"number"}}},Lr={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:Qn,numTurns:{type:"number"},totalDurationMs:{type:"number"}}},Yn={type:"object",additionalProperties:!0,properties:{model:{type:"string"},effort:{type:"string"},maxTurns:{type:"number"}}},ze={type:"object",additionalProperties:!0,properties:{id:{type:"string"},name:{type:"string"},source:{type:"string"},traits:{type:"array",items:{type:"string"}},background:{type:"string"},preferences:Yn,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"}}},Dt={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"}}},Jn={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"}}},Ot={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"}}},Xn={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:Nr}}}},templateDetail:{200:{type:"object",properties:{template:Nr}},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:Lr}}}},taskDetail:{200:{type:"object",properties:{task:Lr}},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:ze}}}},agentDetail:{200:{type:"object",properties:{agent:ze}},404:w},agentCreated:{201:{type:"object",properties:{agent:ze}}},agentUpdated:{200:{type:"object",properties:{agent:ze}},404:w},agentDeleted:{200:{type:"object",properties:{agentId:{type:"string"},deleted:{type:"boolean"}}},400:w,404:w},agentPersona:{200:{type:"object",properties:{persona:Hn({type:"string"})}},404:w},memoryList:{200:{type:"object",properties:{memories:{type:"array",items:Dt},count:{type:"number"}}},404:w},memoryQuery:{200:{type:"object",properties:{memories:{type:"array",items:Dt},count:{type:"number"}}},404:w},memoryCreated:{201:{type:"object",properties:{memory:Dt}},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:Jn}}}},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:Ot}}}},goalDetail:{200:{type:"object",properties:{goal:Ot}},404:w},goalCreated:{201:{type:"object",properties:{goal:Ot}},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:Xn},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 qr=p.union([p.object({type:p.literal("session"),sessionId:p.string()}),p.object({type:p.literal("channel"),channelId:p.string(),chatId:p.string().optional()})]),eo=p.object({prompt:p.string().min(1,"prompt is required"),roleId:p.string().optional(),deliverTo:p.array(qr).optional(),reportTo:p.array(qr).optional(),config:p.object({allowedTools:p.array(p.string()).optional(),disallowedTools:p.array(p.string()).optional(),maxTurns:p.number().optional(),maxBudgetUsd:p.number().optional(),mcpServers:p.record(p.string(),p.unknown()).optional(),model:p.string().optional(),effort:p.enum(["low","medium","high","max"]).optional(),settingSources:p.array(p.string()).optional(),workspacePath:p.string().optional(),timeout:p.number().optional(),approvalRequired:p.array(p.string()).optional(),approvalTimeout:p.number().optional(),fileAccess:p.object({allowedPaths:p.array(p.string()),deniedPaths:p.array(p.string())}).optional(),env:p.record(p.string(),p.string()).optional(),plugins:p.array(p.string()).optional()}).optional()}),pe=p.object({id:p.string().uuid()}),to=["pending","queued","running","paused","completed","failed","cancelled"],so=p.object({status:p.enum(to).optional(),roleId:p.string().optional(),limit:p.coerce.number().min(1).max(100).default(100),offset:p.coerce.number().min(0).default(0)});async function Mr(o){let e=new bs;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(n,a)=>{let i=eo.safeParse(n.body);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let{prompt:c,roleId:l,config:d,deliverTo:m,reportTo:h}=i.data,I=ns(),y={timeout:d?.timeout??I.timeout,approvalRequired:d?.approvalRequired??I.approvalRequired,approvalTimeout:d?.approvalTimeout??I.approvalTimeout,fileAccess:d?.fileAccess??I.fileAccess,allowedTools:d?.allowedTools??I.allowedTools,disallowedTools:d?.disallowedTools??I.disallowedTools,maxTurns:d?.maxTurns??I.maxTurns,maxBudgetUsd:d?.maxBudgetUsd??I.maxBudgetUsd,mcpServers:d?.mcpServers,model:d?.model||I.model||void 0,effort:d?.effort??I.effort,settingSources:d?.settingSources??I.settingSources,workspacePath:d?.workspacePath,env:d?.env??I.env,claudeCodePath:I.claudeCodePath,plugins:d?.plugins},g={id:Zn(),status:"pending",prompt:c,roleId:l,config:y,deliverTo:m,reportTo:h,createdAt:Date.now()};return mt(g),f.emit({type:"task_created",taskId:g.id}),a.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:R.taskList}},async(n,a)=>{let i=so.safeParse(n.query);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let{status:c,roleId:l,limit:d,offset:m}=i.data;return{tasks:q(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:R.taskDetail}},async(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=D(i.data.id);return c?{task:c}:a.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=D(i.data.id);return c?c.status!=="running"&&c.status!=="queued"&&c.status!=="pending"&&c.status!=="paused"?a.status(400).send({code:"INVALID_STATE",message:`Cannot cancel task in status: ${c.status}`}):(e.cancelTask(c.id),{taskId:c.id,status:"cancelled"}):a.status(404).send({code:"NOT_FOUND",message:"Task not found"})});let t=p.object({taskIds:p.array(p.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(n,a)=>{let i=t.safeParse(n.body);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=new Set(["pending","queued","running","paused"]),l=0,d=[];for(let m of i.data.taskIds){let h=D(m);if(!h){d.push({taskId:m,reason:"not found"});continue}if(!c.has(h.status)){d.push({taskId:m,reason:`already ${h.status}`});continue}e.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(n,a)=>{let i=D(n.params.id);if(!i)return a.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:c=50,offset:l=0}=n.query;return{logs:ft(i.id,c,l)}});let r=p.object({approvalId:p.string().uuid(),reason:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=r.safeParse(n.body);return c.success?D(i.data.id)?e.resolveApproval(c.data.approvalId,"allow",c.data.reason)?{approvalId:c.data.approvalId,decision:"allow"}:a.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):a.status(404).send({code:"NOT_FOUND",message:"Task not found"}):a.status(400).send({code:"VALIDATION_ERROR",message:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=r.safeParse(n.body);return c.success?D(i.data.id)?e.resolveApproval(c.data.approvalId,"deny",c.data.reason)?{approvalId:c.data.approvalId,decision:"deny"}:a.status(404).send({code:"NOT_FOUND",message:"Approval not found or already resolved"}):a.status(404).send({code:"NOT_FOUND",message:"Task not found"}):a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(c.error)})});let s=p.object({planId:p.string(),decision:p.enum(["allow","deny"]),approvalType:p.enum(["once","permanent"]).optional(),reason:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=s.safeParse(n.body);if(!c.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(c.error)});if(!D(i.data.id))return a.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{planId:d,decision:m,approvalType:h,reason:I}=c.data;return e.resolvePlanApproval(d,m,h,I)?{planId:d,decision:m,approvalType:h}:a.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(n,a)=>{let i=pe.safeParse(n.params);return i.success?D(i.data.id)?{plans:fs(i.data.id)}:a.status(404).send({code:"NOT_FOUND",message:"Task not found"}):a.status(400).send({code:"VALIDATION_ERROR",message:p.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(n,a)=>{let i=pe.safeParse(n.params);if(!i.success)return a.status(400).send({code:"VALIDATION_ERROR",message:p.prettifyError(i.error)});let c=D(i.data.id);if(!c)return a.status(404).send({code:"NOT_FOUND",message:"Task not found"});let{limit:l=50}=n.query;return{logs:us(c.id,l)}})}ke();he();async function Br(o,e){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(t,r)=>({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(t,r)=>{let s={database:!1,manager:!1,config:!1};try{L().prepare("SELECT 1").get(),s.database=!0}catch{s.database=!1}s.manager=!0,s.config=!!e.server;try{let a=Te(void 0,1,0);s.agents=a.length>0}catch{s.agents=!1}return s.embedding=vs(),s.taskHub=!0,Object.values(s).every(a=>a)?{status:"ready",checks:s}:r.status(503).send({status:"not_ready",checks:s})}),o.get("/stats",{schema:{tags:["Health"],summary:"Runtime statistics",description:"Returns execution pool status, active/pending task counts, and cost summary."}},async(t,r)=>{let n=U().execution?.maxConcurrent??5,a=q("running"),i=q("pending");return{executionPool:{active:a.length,max:n,queued:i.length}}}),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(t,r)=>({name:ps(),version:Be()}))}import{timingSafeEqual as Wr}from"crypto";import{z as Vr}from"zod/v4";var Ft=class{connections=new Map;eventBuffers=new Map;eventIndices=new Map;addConnection(e,t){this.connections.has(e)||this.connections.set(e,new Set),this.connections.get(e).add(t);let r=this.getBufferedEvents(e);for(let s of r)t.readyState===1&&t.send(JSON.stringify(s));t.on("close",()=>{this.removeConnection(e,t)})}removeConnection(e,t){let r=this.connections.get(e);r&&(r.delete(t),r.size===0&&this.connections.delete(e))}broadcast(e,t){this.addToBuffer(e,t);let r=this.connections.get(e);if(!r||r.size===0)return;let s=JSON.stringify(t);for(let n of r)n.readyState===1&&n.send(s)}addToBuffer(e,t){let r=this.eventBuffers.get(e);r||(r=[],this.eventBuffers.set(e,r)),r.push(t),r.length>100&&r.shift(),this.eventIndices.set(e,t.index)}getBufferedEvents(e){return this.eventBuffers.get(e)??[]}getNextIndex(e){let r=(this.eventIndices.get(e)??0)+1;return this.eventIndices.set(e,r),r}},Ur=new Ft;var ro=Vr.object({id:Vr.string().uuid()});async function $r(o,e){o.get("/tasks/:id/stream",{websocket:!0},(t,r)=>{if(e&&!no(r,e)){t.close(4401,"Unauthorized");return}let s=ro.safeParse(r.params);if(!s.success){t.close(1008,"Invalid task ID");return}let{id:n}=s.data;if(!D(n)){t.close(1008,"Task not found");return}Ur.addConnection(n,t)})}function no(o,e){let t=o.headers["x-api-key"];if(t)try{let n=Buffer.from(t),a=Buffer.from(e);if(n.length===a.length&&Wr(n,a))return!0}catch{}let r=o.query,s=r.api_key||r["x-api-key"];if(s)try{let n=Buffer.from(s),a=Buffer.from(e);if(n.length===a.length&&Wr(n,a))return!0}catch{}return!1}import{timingSafeEqual as Gr}from"crypto";var oo=O("ws"),Qe=new Set;function Hr(o,e){o.get("/events",{websocket:!0},(t,r)=>{if(e&&!ao(r,e)){t.close(4401,"Unauthorized");return}Qe.add(t),t.on("close",()=>{Qe.delete(t)}),t.on("error",s=>{oo.error({error:s},"WebSocket error"),Qe.delete(t)})}),f.on("task_status_change",t=>{z(t)}),f.on("approval_request",t=>{z(t)}),f.on("stats_update",t=>{z(t)}),f.on("log_event",t=>{z(t)}),f.on("config_changed",t=>{z(t)}),f.on("plan_approval_request",t=>{(()=>{try{let s=Is(t.taskId);if(!s)return!1;let n=ks(s.sessionId);return n?n.source.type==="channel"&&!!n.source.channelId:!1}catch{return!1}})()||z(t)}),f.on("plan_approval_decision",t=>{z(t)}),f.on("task_created",t=>{z(t)}),f.on("execution_slot_change",t=>{z(t)}),f.on("execution_task_start",t=>{z(t)}),f.on("execution_task_end",t=>{z(t)}),f.on("delivery_status_change",t=>{z(t)})}function z(o){let e=JSON.stringify(o);for(let t of Qe)t.readyState===1&&t.send(e)}function ao(o,e){let t=o.headers["x-api-key"];if(t)try{let n=Buffer.from(t),a=Buffer.from(e);if(n.length===a.length&&Gr(n,a))return!0}catch{}let r=o.query,s=r.api_key||r["x-api-key"];if(s)try{let n=Buffer.from(s),a=Buffer.from(e);if(n.length===a.length&&Gr(n,a))return!0}catch{}return!1}ke();function io(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 jt(){let o=L(),e=o.prepare("SELECT * FROM server_state WHERE id = 1").get();if(e)return io(e);let t=Date.now();return o.prepare("INSERT INTO server_state (id, created_at) VALUES (1, ?)").run(t),{id:1,createdAt:t}}function Se(o){let e=L(),t=[],r=[];"sdkSessionId"in o&&(t.push("sdk_session_id = ?"),r.push(o.sdkSessionId??null)),"userTaskSessionId"in o&&(t.push("user_task_session_id = ?"),r.push(o.userTaskSessionId??null)),"workspacePath"in o&&(t.push("workspace_path = ?"),r.push(o.workspacePath??null)),"lastActiveAt"in o&&(t.push("last_active_at = ?"),r.push(o.lastActiveAt??null)),"toolsFingerprint"in o&&(t.push("tools_fingerprint = ?"),r.push(o.toolsFingerprint??null)),t.length!==0&&(jt(),r.push(1),e.prepare(`UPDATE server_state SET ${t.join(", ")} WHERE id = ?`).run(...r))}function Ye(o){Se({sdkSessionId:o,lastActiveAt:Date.now()})}function Kr(){Se({sdkSessionId:void 0,lastActiveAt:Date.now()})}function zr(o){Se({workspacePath:o})}he();kt();import{z as u}from"zod/v4";import{v4 as Qr}from"uuid";Es();import{rmSync as co,existsSync as Nt}from"fs";var Yr=u.object({model:u.string().optional(),effort:u.enum(["low","medium","high","max"]).optional(),maxTurns:u.number().optional()}),Jr=u.object({path:u.string(),inheritPlugins:u.boolean().optional(),inheritMcp:u.boolean().optional(),inheritPermissions:u.boolean().optional()}),lo=u.object({name:u.string().min(1,"name is required").regex(/^[\p{L}\p{N}_-]+$/u,"name must contain only letters, numbers, underscores, or hyphens"),cagPrompt:u.string().optional(),learnedRules:u.array(u.string()).optional(),allowedTools:u.array(u.string()).optional(),disallowedTools:u.array(u.string()).optional(),evaluationCriteria:u.record(u.string(),u.number()).optional(),executionMode:u.enum(["isolated","inline"]).optional(),model:u.string().optional(),maxBudgetUsd:u.number().optional(),approvalRequired:u.array(u.string()).optional(),preferences:Yr.optional(),additionalDirectories:u.array(Jr).optional(),allowedChannels:u.array(u.string()).optional(),inheritUserSettings:u.boolean().optional()}),po=u.object({name:u.string().min(1).optional(),cagPrompt:u.string().optional(),learnedRules:u.array(u.string()).optional(),status:u.enum(["active","inactive","retired"]).optional(),allowedTools:u.array(u.string()).optional(),disallowedTools:u.array(u.string()).optional(),evaluationCriteria:u.record(u.string(),u.number()).optional(),executionMode:u.enum(["isolated","inline"]).optional(),model:u.string().optional(),maxBudgetUsd:u.number().optional(),approvalRequired:u.array(u.string()).optional(),preferences:Yr.optional(),additionalDirectories:u.array(Jr).optional(),allowedChannels:u.array(u.string()).nullable().optional(),inheritUserSettings:u.boolean().optional()}),Je=u.object({id:u.string().min(1)}),uo=u.object({status:u.enum(["active","inactive","retired"]).optional(),limit:u.coerce.number().min(1).max(100).default(100),offset:u.coerce.number().min(0).default(0)}),mo=u.object({path:u.string().min(1)});async function Xr(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(e,t)=>{let r=uo.safeParse(e.query);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let{status:s,limit:n,offset:a}=r.data;return{roles:Te(s,n,a).map(c=>({...c,workspacePath:ee(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(e,t)=>{let r=lo.safeParse(e.body);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let{name:s,cagPrompt:n,learnedRules:a,allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:m,maxBudgetUsd:h,approvalRequired:I,preferences:y,additionalDirectories:g,allowedChannels:C,inheritUserSettings:W}=r.data;if(ht(s))return t.status(409).send({code:"CONFLICT",message:`Role with name '${s}' already exists`});let V={id:`role-${Qr().slice(0,8)}`,name:s,cagPrompt:n??"",learnedRules:a??[],memoryStreamId:`mem-${Qr().slice(0,8)}`,status:"active",preferences:y??{},allowedTools:i,disallowedTools:c,evaluationCriteria:l,executionMode:d,model:m,maxBudgetUsd:h,approvalRequired:I,additionalDirectories:g,allowedChannels:C,inheritUserSettings:W,createdAt:Date.now()};return yt(V),we(V),t.status(201).send({role:V})}),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(e,t)=>{let r=Je.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=M(r.data.id);if(!s)return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=ee(s.name),a=Ue({scope:"project",projectPath:n});return{role:s,projectPlugins:a,workspacePath:n}}),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(e,t)=>{let r=u.object({id:u.string().min(1)}).safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=M(r.data.id);if(!s)return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=e.query.limit??20,a=ws(s.id,n),i=Ss(s.id);return{scores:a,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"]},preferences:{type:"object",properties:{model:{type:"string"},effort:{type:"string",enum:["low","medium","high","max"]},maxTurns:{type:"number"}}}}}}},async(e,t)=>{let r=Je.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=po.safeParse(e.body);if(!s.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(s.error)});if(!M(r.data.id))return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let{allowedChannels:a,...i}=s.data,c={...i,updatedAt:Date.now()};if(a!==void 0&&(c.allowedChannels=a??void 0),bt(r.data.id,c),s.data.cagPrompt!==void 0||s.data.learnedRules!==void 0){let d=M(r.data.id);if(d){let m=ee(d.name);Nt(m)&&Rt(m,d)}}let l=M(r.data.id);if(l&&(s.data.allowedTools!==void 0||s.data.disallowedTools!==void 0)){let d=ee(l.name);Nt(d)&&It(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(e,t)=>{let r=Je.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=M(r.data.id);if(!s)return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let n=ee(s.name);if(Nt(n))try{co(n,{recursive:!0,force:!0})}catch{}return vt(r.data.id),{roleId:r.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(e,t)=>{let r=Je.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(r.error)});let s=mo.safeParse(e.body);if(!s.success)return t.status(400).send({code:"VALIDATION_ERROR",message:u.prettifyError(s.error)});if(!M(r.data.id))return t.status(404).send({code:"NOT_FOUND",message:"Role not found"});let a=As(s.data.path);return{path:s.data.path,enabledPlugins:a.enabledPlugins,mcpServers:a.mcpServers,allowedTools:a.allowedTools,disallowedTools:a.disallowedTools}})}de();import{z as Zr}from"zod/v4";import{readdirSync as go,existsSync as fo}from"fs";import{join as Lt,resolve as en,sep as sn}from"path";import{homedir as yo}from"os";var ho=20,bo=Zr.object({prefix:Zr.string()});function rn(o){return o.startsWith("~/")?Lt(yo(),o.slice(2)):o}function tn(o){let e=en(o);for(let t of es){let r=rn(t),s=en(r);if(e===s||e.startsWith(s+sn))return!0}return!1}async function nn(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(e,t)=>{let r=bo.safeParse(e.query);if(!r.success)return{suggestions:[]};let{prefix:s}=r.data;if(!s.startsWith("/")&&!s.startsWith("~/"))return{suggestions:[]};if(tn(s))return{suggestions:[]};let n=rn(s),a,i;if(s.endsWith("/"))a=n,i="";else{let g=Math.max(n.lastIndexOf("/"),n.lastIndexOf(sn));if(g<0)return{suggestions:[]};a=n.slice(0,g+1),i=n.slice(g+1)}if(!fo(a))return{suggestions:[]};let c;try{c=go(a,{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)),I=(i.startsWith(".")?d:d.filter(g=>!g.startsWith("."))).filter(g=>!tn(Lt(a,g)));return I.sort((g,C)=>g.localeCompare(C,void 0,{sensitivity:"base"})),{suggestions:I.slice(0,ho).map(g=>Lt(a,g))}})}import{z as S}from"zod/v4";he();import{v4 as vo}from"uuid";var Ro=S.object({roleId:S.string().min(1)}),Io=S.object({roleId:S.string().min(1),prompt:S.string().min(1),topK:S.number().min(1).max(50).default(10)}),ko=S.object({limit:S.coerce.number().min(1).max(200).default(50),offset:S.coerce.number().min(0).default(0)});function qt(o){return M(o)!==void 0}async function on(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(r,s)=>{let n=Ro.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(n.error)});let a=n.data.roleId;if(!qt(a))return s.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let i=ko.safeParse(r.query),{limit:c,offset:l}=i.success?i.data:{limit:50,offset:0},m=Os(a,c,l).map(({embedding:h,...I})=>I);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:R.memoryQuery}},async(r,s)=>{let n=Io.safeParse(r.body);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(n.error)});let{roleId:a,prompt:i,topK:c}=n.data;if(!qt(a))return s.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let d=(await Ct(a,i,{topK:c})).map(({embedding:m,...h})=>h);return{memories:d,count:d.length}});let e=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:R.memoryCreated}},async(r,s)=>{let n=e.safeParse(r.body);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(n.error)});let{roleId:a,content:i,type:c,keywords:l,importance:d,tier:m}=n.data;if(!qt(a))return s.status(404).send({code:"NOT_FOUND",message:"Role or agent not found"});let h;try{h=await Tt(i)}catch{}let I=`mem-${vo().slice(0,8)}`,y=Date.now();xs({id:I,roleId:a,type:c,content:i,embedding:h,keywords:l,importance:d,sourceType:"manual",createdAt:y,lastAccessed:y,retrievedCount:0,tier:m??"episodic"});let g=We(I),{embedding:C,...W}=g;return s.status(201).send({memory:W})});let t=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:R.memoryUpdated}},async(r,s)=>{let{id:n}=r.params;if(!We(n))return s.status(404).send({code:"NOT_FOUND",message:"Memory not found"});let i=t.safeParse(r.body);if(!i.success)return s.status(400).send({code:"VALIDATION_ERROR",message:S.prettifyError(i.error)});let c=i.data,l,d=!0;if(c.content)try{l=await Tt(c.content)}catch{d=!1}let m=Ds(n,{content:c.content,embedding:l,keywords:c.keywords,importance:c.importance,type:c.type});return{memoryId:n,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:R.memoryDeleted}},async(r,s)=>{let{id:n}=r.params;return We(n)?(Fs(n),{memoryId:n,deleted:!0}):s.status(404).send({code:"NOT_FOUND",message:"Memory not found"})})}import{query as Po}from"@anthropic-ai/claude-agent-sdk";import{v4 as ue}from"uuid";Fn();de();var To=new Set(["Read","Glob","Grep","LSP"]),wo=new Set(["Edit","Write","NotebookEdit"]);function Ce(o,e){return async(t,r,{agentID:s})=>{if(To.has(t))return{behavior:"allow",updatedInput:r};let n=o(s??"");if(wo.has(t)){let a=is(t,r),i=A;if(a.length===0)return{behavior:"allow",updatedInput:r};let c={allowedPaths:n?.allowedPaths??[],deniedPaths:n?.deniedPaths??[]};for(let l of a){let d=cs(l,i,c);if(!d.allowed)return{behavior:"deny",message:`Path denied: ${d.reason}. Try an alternative within allowed paths.`}}return{behavior:"allow",updatedInput:r}}if(n?.disallowedTools?.includes(t))return{behavior:"deny",message:`Tool ${t} is not allowed for this role.`};if(e&&n?.approvalRequired?.length){let a=t==="Bash"?r.command??"":`${t} ${JSON.stringify(r)}`;for(let i of n.approvalRequired)try{if(new RegExp(i).test(a))return await e(t,r,i,s)}catch{}}return{behavior:"allow",updatedInput:r}}}function Pe(o){return{SessionStart:[{hooks:[async e=>{if(!o.roleId)return{};let t=e.source,r=o.roleId==="role-chat-manager";if(!r&&t!=="startup"&&t!=="resume")return{};try{let{queryMemoryByTier:s}=await import("./memory-service-BKLZIRK6.js"),n=o.taskPrompt||"role context and recent interactions",a=r?["semantic","working"]:["semantic","episodic"],i=await s(o.roleId,n,a,{topK:5});if(i.length>0)return{hookSpecificOutput:{hookEventName:"SessionStart",additionalContext:`[Memory Context]
3
3
  ${i.map(d=>`- [${d.tier??"episodic"}] ${d.content}`).join(`
4
4
  `)}
5
5
 
6
- `}}}catch{}return{}}]}],SubagentStart:[{hooks:[async e=>{let t=o.roleId??e.agent_id;if(!t)return{};try{let r=o.taskPrompt||"role context",s=await Os(r,t,5);if(s)return{hookSpecificOutput:{hookEventName:"SubagentStart",additionalContext:s}}}catch{}return{}}]}],SubagentStop:[{hooks:[async e=>{let t=e.agent_id;if(!t||!o.currentTaskId)return{};try{let{createMemory:r}=await import("./memories-EFQ4SFZG.js"),{getDb:s}=await import("./db-PNZ3UJOE.js"),n=e.transcript;if(!n||n.length<=100)return{};if(s().prepare("SELECT 1 FROM memories WHERE source_task_id = ? AND type = 'thought' LIMIT 1").get(o.currentTaskId))return{};let i=`[Task ${o.currentTaskId} reasoning] ${n.slice(0,800)}`;r({id:`session-${Date.now()}`,roleId:o.roleId??t,type:"thought",content:i,keywords:[],importance:3,sourceType:"task_complete",sourceTaskId:o.currentTaskId,createdAt:Date.now(),lastAccessed:Date.now(),retrievedCount:0,tier:"episodic"})}catch{}return{}}]}],PostToolUse:[{hooks:[async e=>{if(!o.currentTaskId)return{};let t=e.tool_name,r=e.tool_input,s=e.tool_response,n=typeof s=="string"?s:JSON.stringify(s??"");try{mt({id:`step-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,taskId:o.currentTaskId,index:0,type:"tool_call",content:`${t}: ${JSON.stringify(r??{})} \u2192 ${n.slice(0,200)}`,toolName:t,toolInput:r,toolOutput:n,timestamp:Date.now()})}catch{}return{}}]}],PreCompact:[{hooks:[async e=>{let t=e.compact_summary;if(!t)return{};try{let{createMemory:r}=await import("./memories-EFQ4SFZG.js");r({id:`compact-${Date.now()}`,roleId:o.roleId??"role-chat-manager",type:"thought",content:t.slice(0,2e3),keywords:["compaction","context","decisions"],importance:4,sourceType:"pre_compact",createdAt:Date.now(),lastAccessed:Date.now(),retrievedCount:0,tier:"working"})}catch{}return{}}]}]}}function Mt(o){return`# ChatManager \u2014 User Interface Agent
6
+ `}}}catch{}return{}}]}],SubagentStart:[{hooks:[async e=>{let t=o.roleId??e.agent_id;if(!t)return{};try{let r=o.taskPrompt||"role context",s=await js(r,t,5);if(s)return{hookSpecificOutput:{hookEventName:"SubagentStart",additionalContext:s}}}catch{}return{}}]}],SubagentStop:[{hooks:[async e=>{let t=e.agent_id;if(!t||!o.currentTaskId)return{};try{let{createMemory:r}=await import("./memories-EFQ4SFZG.js"),{getDb:s}=await import("./db-PNZ3UJOE.js"),n=e.transcript;if(!n||n.length<=100)return{};if(s().prepare("SELECT 1 FROM memories WHERE source_task_id = ? AND type = 'thought' LIMIT 1").get(o.currentTaskId))return{};let i=`[Task ${o.currentTaskId} reasoning] ${n.slice(0,800)}`;r({id:`session-${Date.now()}`,roleId:o.roleId??t,type:"thought",content:i,keywords:[],importance:3,sourceType:"task_complete",sourceTaskId:o.currentTaskId,createdAt:Date.now(),lastAccessed:Date.now(),retrievedCount:0,tier:"episodic"})}catch{}return{}}]}],PostToolUse:[{hooks:[async e=>{if(!o.currentTaskId)return{};let t=e.tool_name,r=e.tool_input,s=e.tool_response,n=typeof s=="string"?s:JSON.stringify(s??"");try{gt({id:`step-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,taskId:o.currentTaskId,index:0,type:"tool_call",content:`${t}: ${JSON.stringify(r??{})} \u2192 ${n.slice(0,200)}`,toolName:t,toolInput:r,toolOutput:n,timestamp:Date.now()})}catch{}return{}}]}],PreCompact:[{hooks:[async e=>{let t=e.compact_summary;if(!t)return{};try{let{createMemory:r}=await import("./memories-EFQ4SFZG.js");r({id:`compact-${Date.now()}`,roleId:o.roleId??"role-chat-manager",type:"thought",content:t.slice(0,2e3),keywords:["compaction","context","decisions"],importance:4,sourceType:"pre_compact",createdAt:Date.now(),lastAccessed:Date.now(),retrievedCount:0,tier:"working"})}catch{}return{}}]}]}}function Mt(o){return`# ChatManager \u2014 User Interface Agent
7
7
 
8
8
  You are the primary interface between the user and the goal-driven autonomous system.
9
9
  You have access to a persistent conversation session and the adam-tools MCP server.
@@ -74,18 +74,18 @@ conflict, treat the [Session context] as authoritative (it reflects the latest D
74
74
  ## Conversation Coherence
75
75
  When task completion notifications arrive, incorporate the results naturally into your conversation.
76
76
  For example, if the user asked "run a report" and Task xyz completed, summarize the result for the user.
77
- `}function To(o){return o.map(e=>`${e.role==="user"?"User":"Assistant"}: ${e.content}`).join(`
78
- `)}function wo(o){return o.map(e=>`Memory [${e.tier??"episodic"}]: ${e.content} (importance: ${e.importance})`).join(`
79
- `)}async function nn(o,e){let t=ns(),r=bs(o,t.maxSessionTurns),s=To(r),n="";try{let i=await Fs(void 0,e,["semantic","working"],{topK:5});i.length>0&&(n=wo(i))}catch{}let a=[];return s&&a.push(`[Session context \u2014 last ${t.maxSessionTurns} turns]
77
+ `}function So(o){return o.map(e=>`${e.role==="user"?"User":"Assistant"}: ${e.content}`).join(`
78
+ `)}function Co(o){return o.map(e=>`Memory [${e.tier??"episodic"}]: ${e.content} (importance: ${e.importance})`).join(`
79
+ `)}async function an(o,e){let t=os(),r=Rs(o,t.maxSessionTurns),s=So(r),n="";try{let i=await Ns(void 0,e,["semantic","working"],{topK:5});i.length>0&&(n=Co(i))}catch{}let a=[];return s&&a.push(`[Session context \u2014 last ${t.maxSessionTurns} turns]
80
80
  ${s}`),n&&a.push(`[Relevant memories \u2014 from Memory system]
81
81
  ${n}`),a.push(`[Current message]
82
82
  User: ${e}`),a.join(`
83
83
 
84
- `)}de();var F=O("chat-manager"),Co=A,_e=class{sessionId;adamToolsInstance=null;running=!1;processing=!1;messageQueue=[];lastActivityAt=Date.now();consecutiveStaleCount=0;subscribed=!1;activeChatSessionId;activeChatSource;taskOriginMap=new Map;constructor(e){this.sessionId=e}async start(){this.running||(this.running=!0,this.subscribeToEvents(),F.info("ChatManager started"))}stop(){this.running=!1,F.info("ChatManager stopped")}async handleMessage(e,t,r){return new Promise((s,n)=>{let a=t;this.messageQueue.push({content:e,chatSessionId:a,resolve:i=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,s(i)},reject:i=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,n(i)}}),this.activeChatSessionId=t,this.activeChatSource=r,this.processQueue()})}async processQueue(){if(this.processing||!this.running)return;let e=this.messageQueue.shift();if(e){this.processing=!0;try{let t=await this.runQuery(e.content,e.chatSessionId);e.resolve(t)}catch(t){let r=t instanceof Error?t.message:String(t);if(r.includes("Prompt is too long")||r.includes("prompt is too long")){F.warn("Prompt too long \u2014 resetting session and retrying"),this.sessionId=void 0,Qe(void 0);try{let s=await this.runQuery(e.content,e.chatSessionId);e.resolve(s)}catch(s){e.reject(s instanceof Error?s:new Error(String(s)))}}else e.reject(t instanceof Error?t:new Error(r))}finally{this.processing=!1,this.processQueue()}}}async runQuery(e,t){let r=Mt({currentTime:Date.now()}),s=e;if(t)try{let d=await nn(t,e);d&&d!==e&&(s=d)}catch(d){F.debug({error:d},"Session context enrichment failed, using raw message")}this.adamToolsInstance||(this.adamToolsInstance=_t());let n=Pe({currentTaskId:void 0,roleId:"role-chat-manager"}),a=Ce(d=>({disallowedTools:["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"]}));F.debug({hasApiKey:!!process.env.ANTHROPIC_API_KEY,hasResume:!!this.sessionId},"ChatManager SDK query starting");let i=["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"],c=So({prompt:s,options:{cwd:Co,additionalDirectories:[process.cwd()],systemPrompt:r,resume:this.sessionId,maxTurns:50,maxBudgetUsd:5,disallowedTools:i,settingSources:["project"],mcpServers:{"adam-tools":this.adamToolsInstance},hooks:n,canUseTool:a,env:{...process.env,...Me(),DISABLE_TELEMETRY:"1",DISABLE_ERROR_REPORTING:"1",CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1",DISABLE_AUTOUPDATER:"1",ANTHROPIC_SMALL_FAST_MODEL:U().anthropic?.smallFastModel||process.env.ANTHROPIC_MODEL||""},stderr:d=>{d.trim()&&F.debug({stderr:d.trim().slice(0,500)},"ChatManager SDK stderr")}}}),l="";for await(let d of c){let m=d;F.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,Qe(this.sessionId)),m.type==="result"&&typeof m.result=="string"&&(l=m.result)}return l}subscribeToEvents(){this.subscribed||(this.subscribed=!0,f.on("task_created",e=>{this.activeChatSessionId&&this.activeChatSource&&(H(e.taskId,{sourceSessionId:this.activeChatSessionId}),this.taskOriginMap.set(e.taskId,{chatSessionId:this.activeChatSessionId,source:this.activeChatSource,createdAt:Date.now()}),F.debug({taskId:e.taskId,chatSessionId:this.activeChatSessionId},"Tracked task origin for result delivery"));let t=D(e.taskId);if(t?.parentId){let r=this.taskOriginMap.get(t.parentId),s=r?void 0:D(t.parentId),n=r?.chatSessionId??s?.sourceSessionId;n&&(H(e.taskId,{sourceSessionId:n}),r&&this.taskOriginMap.set(e.taskId,{...r}))}}),f.on("task_complete_event",e=>{this.handleTaskCompletion(e.taskId,e.result,e.error)}),f.on("task_status_change",e=>{let t=this.taskOriginMap.get(e.taskId);t&&e.newStatus==="running"&&this.handleTaskStatusReport(e.taskId,e.newStatus,t)}),f.on("plan_approval_request",e=>{let t=this.taskOriginMap.get(e.taskId);t&&this.handleTaskStatusReport(e.taskId,"approval_requested",t)}),setInterval(()=>{let e=Date.now()-864e5;for(let[t,r]of this.taskOriginMap)r.createdAt<e&&this.taskOriginMap.delete(t)},3600*1e3))}async handleTaskStatusReport(e,t,r){let s=D(e),a=(s?.roleId?await this.getRoleName(s.roleId):void 0)??e.slice(0,8),i=s?.prompt?.slice(0,200)??"",c;switch(t){case"running":c=`[System] Task "${a}" 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 "${a}" 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 ${a} \u5DF2\u542F\u52A8`,approval_requested:`\u4EFB\u52A1 ${a} \u9700\u8981\u6388\u6743`},d=!1,m=setTimeout(()=>{if(d)return;d=!0;let h=l[t]??`\u4EFB\u52A1 ${a}: ${t}`;this.deliverReport(r,e,h)},3e4);this.messageQueue.push({content:c,resolve:h=>{if(d)return;d=!0,clearTimeout(m);let I=h?.trim()||(l[t]??`\u4EFB\u52A1 ${a}: ${t}`);this.deliverReport(r,e,I)},reject:()=>{if(d)return;d=!0,clearTimeout(m);let h=l[t]??`\u4EFB\u52A1 ${a}: ${t}`;this.deliverReport(r,e,h)}}),this.processQueue()}deliverReport(e,t,r){let s={id:ue(),sessionId:e.chatSessionId,role:"assistant",content:r,source:e.source,taskId:t,createdAt:Date.now()};te(s),f.emit({type:"chat_message",sessionId:e.chatSessionId,message:s}),se(e.chatSessionId),e.source.type==="channel"&&e.source.channelId&&e.source.chatId&&this.deliverToChannel(e.source.channelId,e.source.chatId,r,"report")}async handleTaskCompletion(e,t,r){let s=D(e),n=this.taskOriginMap.get(e);if(!n&&s?.sourceSessionId){let y=K(s.sourceSessionId);y&&(n={chatSessionId:y.id,source:y.source,createdAt:s.createdAt})}let a=r?`\u4EFB\u52A1\u5931\u8D25: ${r}`:t??"",i=async(y,g)=>{try{let C=K(y);if(!C)return;te({id:ue(),sessionId:y,role:"assistant",content:g,source:C.source,taskId:e,createdAt:Date.now()}),se(y),f.emit({type:"chat_message",sessionId:y,message:{id:ue(),sessionId:y,role:"assistant",content:g,source:C.source,createdAt:Date.now()}})}catch(C){F.error({error:C,taskId:e,targetSession:y},"Failed to deliver to session")}},c=s?.roleId?await this.getRoleName(s.roleId):void 0,l=c?`${c}`:e.slice(0,8),d=r?`[System] Task "${l}" failed. Error: ${r.slice(0,300)}. Compose a brief failure report for the user (2-3 sentences). Do NOT call any tools.`:`[System] Task "${l}" completed successfully. Result summary: ${(t??"").slice(0,500)}. 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})`},h=!1,I=setTimeout(()=>{if(h)return;h=!0;let y=r?m.error:m.success;if(n&&this.deliverReport(n,e,y),s?.reportTo&&s.reportTo.length>0)for(let g of s.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,y,"report"):g.type==="session"&&g.sessionId&&i(g.sessionId,y)},3e4);if(this.messageQueue.push({content:d,resolve:y=>{if(h)return;h=!0,clearTimeout(I);let g=y?.trim()||(r?m.error:m.success);if(n&&this.deliverReport(n,e,g),s?.reportTo&&s.reportTo.length>0)for(let C of s.reportTo)C.type==="channel"&&C.channelId&&C.chatId?this.deliverToChannel(C.channelId,C.chatId,g,"report"):C.type==="session"&&C.sessionId&&i(C.sessionId,g);n&&this.taskOriginMap.delete(e)},reject:()=>{if(h)return;h=!0,clearTimeout(I);let y=r?m.error:m.success;if(n&&this.deliverReport(n,e,y),s?.reportTo&&s.reportTo.length>0)for(let g of s.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,y,"report"):g.type==="session"&&g.sessionId&&i(g.sessionId,y);n&&this.taskOriginMap.delete(e)}}),this.processQueue(),n||F.debug({taskId:e},"Task completed but no chat session origin tracked (may be API-created or template-triggered)"),s?.deliverTo&&s.deliverTo.length>0)for(let y of s.deliverTo)y.type==="channel"&&y.channelId&&y.chatId?this.deliverToChannel(y.channelId,y.chatId,a,"deliver"):y.type==="session"&&y.sessionId&&await i(y.sessionId,a);else if(n?.source.type==="channel"&&n.source.channelId&&n.source.chatId){let g=a.length>2e3?a.slice(0,2e3)+`
84
+ `)}de();var F=O("chat-manager"),_o=A,_e=class{sessionId;adamToolsInstance=null;running=!1;processing=!1;messageQueue=[];lastActivityAt=Date.now();consecutiveStaleCount=0;subscribed=!1;activeChatSessionId;activeChatSource;taskOriginMap=new Map;constructor(e){this.sessionId=e}async start(){this.running||(this.running=!0,this.subscribeToEvents(),F.info("ChatManager started"))}stop(){this.running=!1,F.info("ChatManager stopped")}async handleMessage(e,t,r){return new Promise((s,n)=>{let a=t,i=r;this.messageQueue.push({content:e,chatSessionId:a,source:i,resolve:c=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,s(c)},reject:c=>{this.activeChatSessionId=void 0,this.activeChatSource=void 0,n(c)}}),this.processQueue()})}async processQueue(){if(this.processing||!this.running)return;let e=this.messageQueue.shift();if(e){this.activeChatSessionId=e.chatSessionId,this.activeChatSource=e.source,this.processing=!0;try{let t=await this.runQuery(e.content,e.chatSessionId);e.resolve(t)}catch(t){let r=t instanceof Error?t.message:String(t);if(r.includes("Prompt is too long")||r.includes("prompt is too long")){F.warn("Prompt too long \u2014 resetting session and retrying"),this.sessionId=void 0,Ye(void 0);try{let s=await this.runQuery(e.content,e.chatSessionId);e.resolve(s)}catch(s){e.reject(s instanceof Error?s:new Error(String(s)))}}else e.reject(t instanceof Error?t:new Error(r))}finally{this.processing=!1,this.processQueue()}}}async runQuery(e,t){let r=Mt({currentTime:Date.now()}),s=e;if(t)try{let d=await an(t,e);d&&d!==e&&(s=d)}catch(d){F.debug({error:d},"Session context enrichment failed, using raw message")}this.adamToolsInstance||(this.adamToolsInstance=At());let n=Pe({currentTaskId:void 0,roleId:"role-chat-manager"}),a=Ce(d=>({disallowedTools:["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"]}));F.debug({hasApiKey:!!process.env.ANTHROPIC_API_KEY,hasResume:!!this.sessionId},"ChatManager SDK query starting");let i=["WebSearch","WebFetch","Bash","Edit","Write","NotebookEdit"],c=Po({prompt:s,options:{cwd:_o,additionalDirectories:[process.cwd()],systemPrompt:r,resume:this.sessionId,maxTurns:50,maxBudgetUsd:5,disallowedTools:i,settingSources:["project"],mcpServers:{"adam-tools":this.adamToolsInstance},hooks:n,canUseTool:a,env:{...process.env,...qe(),DISABLE_TELEMETRY:"1",DISABLE_ERROR_REPORTING:"1",CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1",DISABLE_AUTOUPDATER:"1",ANTHROPIC_SMALL_FAST_MODEL:U().anthropic?.smallFastModel||process.env.ANTHROPIC_MODEL||""},stderr:d=>{d.trim()&&F.debug({stderr:d.trim().slice(0,500)},"ChatManager SDK stderr")}}}),l="";for await(let d of c){let m=d;F.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,Ye(this.sessionId)),m.type==="result"&&typeof m.result=="string"&&(l=m.result)}return l}subscribeToEvents(){this.subscribed||(this.subscribed=!0,f.on("task_created",e=>{this.activeChatSessionId&&this.activeChatSource&&(H(e.taskId,{sourceSessionId:this.activeChatSessionId}),this.taskOriginMap.set(e.taskId,{chatSessionId:this.activeChatSessionId,source:this.activeChatSource,createdAt:Date.now()}),F.debug({taskId:e.taskId,chatSessionId:this.activeChatSessionId},"Tracked task origin for result delivery"));let t=D(e.taskId);if(t?.parentId){let r=this.taskOriginMap.get(t.parentId),s=r?void 0:D(t.parentId),n=r?.chatSessionId??s?.sourceSessionId;n&&(H(e.taskId,{sourceSessionId:n}),r&&this.taskOriginMap.set(e.taskId,{...r}))}}),f.on("task_complete_event",e=>{this.handleTaskCompletion(e.taskId,e.result,e.error)}),f.on("task_status_change",e=>{let t=this.taskOriginMap.get(e.taskId);t&&e.newStatus==="running"&&this.handleTaskStatusReport(e.taskId,e.newStatus,t)}),f.on("plan_approval_request",e=>{let t=this.taskOriginMap.get(e.taskId);t&&this.handleTaskStatusReport(e.taskId,"approval_requested",t)}),setInterval(()=>{let e=Date.now()-864e5;for(let[t,r]of this.taskOriginMap)r.createdAt<e&&this.taskOriginMap.delete(t)},3600*1e3))}async handleTaskStatusReport(e,t,r){let s=D(e),a=(s?.roleId?await this.getRoleName(s.roleId):void 0)??e.slice(0,8),i=s?.prompt?.slice(0,200)??"",c;switch(t){case"running":c=`[System] Task "${a}" 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 "${a}" 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 ${a} \u5DF2\u542F\u52A8`,approval_requested:`\u4EFB\u52A1 ${a} \u9700\u8981\u6388\u6743`},d=!1,m=setTimeout(()=>{if(d)return;d=!0;let h=l[t]??`\u4EFB\u52A1 ${a}: ${t}`;this.deliverReport(r,e,h)},3e4);this.messageQueue.push({content:c,resolve:h=>{if(d)return;d=!0,clearTimeout(m);let I=h?.trim()||(l[t]??`\u4EFB\u52A1 ${a}: ${t}`);this.deliverReport(r,e,I)},reject:()=>{if(d)return;d=!0,clearTimeout(m);let h=l[t]??`\u4EFB\u52A1 ${a}: ${t}`;this.deliverReport(r,e,h)}}),this.processQueue()}deliverReport(e,t,r,s){let n={id:ue(),sessionId:e.chatSessionId,role:"assistant",content:r,source:e.source,taskId:t,createdAt:Date.now()};te(n),f.emit({type:"chat_message",sessionId:e.chatSessionId,message:n}),se(e.chatSessionId),e.source.type==="channel"&&e.source.channelId&&e.source.chatId&&this.deliverToChannel(e.source.channelId,e.source.chatId,r,"report",s)}async handleTaskCompletion(e,t,r){let s=D(e),n=this.taskOriginMap.get(e);if(!n&&s?.sourceSessionId){let y=K(s.sourceSessionId);y&&(n={chatSessionId:y.id,source:y.source,createdAt:s.createdAt})}let a=r?`\u4EFB\u52A1\u5931\u8D25: ${r}`:t??"",i=async(y,g)=>{try{let C=K(y);if(!C)return;te({id:ue(),sessionId:y,role:"assistant",content:g,source:C.source,taskId:e,createdAt:Date.now()}),se(y),f.emit({type:"chat_message",sessionId:y,message:{id:ue(),sessionId:y,role:"assistant",content:g,source:C.source,createdAt:Date.now()}})}catch(C){F.error({error:C,taskId:e,targetSession:y},"Failed to deliver to session")}},c=s?.roleId?await this.getRoleName(s.roleId):void 0,l=c?`${c}`:e.slice(0,8),d=r?`[System] Task "${l}" failed. Error: ${r.slice(0,300)}. Compose a brief failure report for the user (2-3 sentences). Do NOT call any tools.`:`[System] Task "${l}" completed successfully. Result summary: ${(t??"").slice(0,500)}. 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})`},h=!1,I=setTimeout(()=>{if(h)return;h=!0;let y=r?m.error:m.success;if(n&&this.deliverReport(n,e,y,e),s?.reportTo&&s.reportTo.length>0)for(let g of s.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,y,"report",e):g.type==="session"&&g.sessionId&&i(g.sessionId,y)},3e4);if(this.messageQueue.push({content:d,resolve:y=>{if(h)return;h=!0,clearTimeout(I);let g=y?.trim()||(r?m.error:m.success);if(n&&this.deliverReport(n,e,g,e),s?.reportTo&&s.reportTo.length>0)for(let C of s.reportTo)C.type==="channel"&&C.channelId&&C.chatId?this.deliverToChannel(C.channelId,C.chatId,g,"report",e):C.type==="session"&&C.sessionId&&i(C.sessionId,g);n&&this.taskOriginMap.delete(e)},reject:()=>{if(h)return;h=!0,clearTimeout(I);let y=r?m.error:m.success;if(n&&this.deliverReport(n,e,y,e),s?.reportTo&&s.reportTo.length>0)for(let g of s.reportTo)g.type==="channel"&&g.channelId&&g.chatId?this.deliverToChannel(g.channelId,g.chatId,y,"report",e):g.type==="session"&&g.sessionId&&i(g.sessionId,y);n&&this.taskOriginMap.delete(e)}}),this.processQueue(),n||F.debug({taskId:e},"Task completed but no chat session origin tracked (may be API-created or template-triggered)"),s?.deliverTo&&s.deliverTo.length>0)for(let y of s.deliverTo)y.type==="channel"&&y.channelId&&y.chatId?this.deliverToChannel(y.channelId,y.chatId,a,"deliver",e):y.type==="session"&&y.sessionId&&await i(y.sessionId,a);else if(n?.source.type==="channel"&&n.source.channelId&&n.source.chatId){let g=a.length>2e3?a.slice(0,2e3)+`
85
85
 
86
- ... \u67E5\u770B\u5B8C\u6574\u7ED3\u679C\u8BF7\u8BBF\u95EE Web UI`:a;this.deliverToChannel(n.source.channelId,n.source.chatId,g,"deliver")}if(s?.parentId){let y=le(s.parentId);if(y){let g=os(s.parentId);if(g.every(W=>W.status==="completed"||W.status==="failed")){let W=g.some(ae=>ae.status==="failed"),oe=W?"failed":"completed";We(s.parentId,{status:oe,updatedAt:Date.now()}),F.info({goalId:s.parentId,goalName:y.name,finalStatus:oe},"Goal completed");let $=`${W?"\u274C":"\u2705"} \u76EE\u6807\u5B8C\u6210: ${y.name}
86
+ ... \u67E5\u770B\u5B8C\u6574\u7ED3\u679C\u8BF7\u8BBF\u95EE Web UI`:a;this.deliverToChannel(n.source.channelId,n.source.chatId,g,"deliver",e)}if(s?.parentId){let y=le(s.parentId);if(y){let g=as(s.parentId);if(g.every(W=>W.status==="completed"||W.status==="failed")){let W=g.some(ae=>ae.status==="failed"),oe=W?"failed":"completed";Ve(s.parentId,{status:oe,updatedAt:Date.now()}),F.info({goalId:s.parentId,goalName:y.name,finalStatus:oe},"Goal completed");let V=`${W?"\u274C":"\u2705"} \u76EE\u6807\u5B8C\u6210: ${y.name}
87
87
 
88
- ${g.length} \u4E2A\u5B50\u4EFB\u52A1\u5168\u90E8\u5B8C\u6210`;await this.routeGoalNotification(y,$,s.parentId)}}}}async getRoleName(e){try{let{getRole:t}=await import("./roles-SG2YAR64.js");return t(e)?.name}catch{return}}async deliverToChannel(e,t,r,s="reply"){if(!e||!t){F.warn({channelId:e,chatId:t},"Cannot deliver to channel: missing channelId or chatId");return}try{await Rr().send({channelId:e,chatId:t,content:r,messageType:s}),F.info({channelId:e,chatId:t.slice(0,12),messageType:s},"Delivered notification to channel")}catch(n){F.error({error:n,channelId:e,chatId:t.slice(0,12)},"Failed to deliver to channel")}}async routeGoalNotification(e,t,r){let s=e.deliverTo??[],n=e.sourceSessionId;if(!(s.length===0&&!n)){for(let a of s)if(a.type==="session")try{let i=K(a.sessionId);i&&(te({id:ue(),sessionId:a.sessionId,role:"assistant",content:t,source:i.source,createdAt:Date.now()}),se(a.sessionId),f.emit({type:"chat_message",sessionId:a.sessionId,message:{id:ue(),sessionId:a.sessionId,role:"assistant",content:t,source:i.source,createdAt:Date.now()}}))}catch(i){F.error({error:i,goalId:r,targetSession:a.sessionId},"Failed to deliver Goal notification to session")}else a.type==="channel"&&await this.deliverToChannel(a.channelId,a.chatId??"",t);if(n&&!s.some(a=>a.type==="session"&&a.sessionId===n))try{let a=K(n);a&&(te({id:ue(),sessionId:n,role:"assistant",content:t,source:a.source,createdAt:Date.now()}),se(n),f.emit({type:"chat_message",sessionId:n,message:{id:ue(),sessionId:n,role:"assistant",content:t,source:a.source,createdAt:Date.now()}}))}catch(a){F.error({error:a,goalId:r,sessionId:n},"Failed to deliver Goal notification to source session")}}}getLastActivityAt(){return this.lastActivityAt}getConsecutiveStaleCount(){return this.consecutiveStaleCount}isHealthy(){return this.running}async restartSession(){F.warn("Restarting ChatManager session (Watchdog triggered)"),this.consecutiveStaleCount++,this.sessionId=void 0,Qe(void 0)}};import{query as Eo}from"@anthropic-ai/claude-agent-sdk";import{v4 as xo}from"uuid";function qt(o){let e=o.roleName?`## Role Context
88
+ ${g.length} \u4E2A\u5B50\u4EFB\u52A1\u5168\u90E8\u5B8C\u6210`;await this.routeGoalNotification(y,V,s.parentId)}}}}async getRoleName(e){try{let{getRole:t}=await import("./roles-SG2YAR64.js");return t(e)?.name}catch{return}}async deliverToChannel(e,t,r,s="reply",n){if(!e||!t){F.warn({channelId:e,chatId:t},"Cannot deliver to channel: missing channelId or chatId");return}try{await kr().send({taskId:n,channelId:e,chatId:t,content:r,messageType:s}),F.info({channelId:e,chatId:t.slice(0,12),messageType:s,taskId:n?.slice(0,8)},"Delivered notification to channel")}catch(a){F.error({error:a,channelId:e,chatId:t.slice(0,12)},"Failed to deliver to channel")}}async routeGoalNotification(e,t,r){let s=e.deliverTo??[],n=e.sourceSessionId;if(!(s.length===0&&!n)){for(let a of s)if(a.type==="session")try{let i=K(a.sessionId);i&&(te({id:ue(),sessionId:a.sessionId,role:"assistant",content:t,source:i.source,createdAt:Date.now()}),se(a.sessionId),f.emit({type:"chat_message",sessionId:a.sessionId,message:{id:ue(),sessionId:a.sessionId,role:"assistant",content:t,source:i.source,createdAt:Date.now()}}))}catch(i){F.error({error:i,goalId:r,targetSession:a.sessionId},"Failed to deliver Goal notification to session")}else a.type==="channel"&&await this.deliverToChannel(a.channelId,a.chatId??"",t);if(n&&!s.some(a=>a.type==="session"&&a.sessionId===n))try{let a=K(n);a&&(te({id:ue(),sessionId:n,role:"assistant",content:t,source:a.source,createdAt:Date.now()}),se(n),f.emit({type:"chat_message",sessionId:n,message:{id:ue(),sessionId:n,role:"assistant",content:t,source:a.source,createdAt:Date.now()}}))}catch(a){F.error({error:a,goalId:r,sessionId:n},"Failed to deliver Goal notification to source session")}}}getLastActivityAt(){return this.lastActivityAt}getConsecutiveStaleCount(){return this.consecutiveStaleCount}isHealthy(){return this.running}async restartSession(){F.warn("Restarting ChatManager session (Watchdog triggered)"),this.consecutiveStaleCount++,this.sessionId=void 0,Ye(void 0)}};import{query as Do}from"@anthropic-ai/claude-agent-sdk";import{v4 as Oo}from"uuid";function Bt(o){let e=o.roleName?`## Role Context
89
89
  - Role: ${o.roleName}
90
90
  ${o.roleCagPrompt?`- CAG Prompt: ${o.roleCagPrompt.slice(0,200)}`:""}`:"",t=o.allowedTools&&o.allowedTools.length>0?`## Available Tools
91
91
  You have access to: ${o.allowedTools.join(", ")}. Use them as needed to complete the task.`:"";return`# Execution Agent \u2014 Task Focus
@@ -111,20 +111,20 @@ ${t}
111
111
  - Report completion with a clear result summary
112
112
  - If WebSearch or WebFetch fails (network error, invalid params), report the failure honestly \u2014 do not fabricate data
113
113
  - If a tool is unavailable, state it clearly in the result rather than guessing
114
- `}he();It();de();ke();import{randomUUID as Po}from"crypto";function an(o,e,t){let s=L().prepare(`
114
+ `}he();kt();de();ke();import{randomUUID as Ao}from"crypto";function dn(o,e,t){let s=L().prepare(`
115
115
  INSERT INTO task_plugins (id, task_id, plugin_path, plugin_name, role_id, used_at)
116
116
  VALUES (?, ?, ?, ?, ?, ?)
117
- `),n=Date.now();for(let a of e){let i=a.split("/").pop()??a;s.run(Po(),o,a,i,t??null,n)}}function cn(o){return L().prepare(`
117
+ `),n=Date.now();for(let a of e){let i=a.split("/").pop()??a;s.run(Ao(),o,a,i,t??null,n)}}function ln(o){return L().prepare(`
118
118
  SELECT plugin_name as pluginName, COUNT(*) as usageCount
119
119
  FROM task_plugins
120
120
  WHERE role_id = ?
121
121
  GROUP BY plugin_path
122
122
  ORDER BY usageCount DESC
123
- `).all(o)}function dn(o=50){return L().prepare(`
123
+ `).all(o)}function pn(o=50){return L().prepare(`
124
124
  SELECT plugin_path as pluginPath, plugin_name as pluginName, COUNT(*) as usageCount, MAX(used_at) as lastUsed
125
125
  FROM task_plugins
126
126
  GROUP BY plugin_path
127
127
  ORDER BY usageCount DESC
128
128
  LIMIT ?
129
- `).all(o)}he();import{createSdkMcpServer as _o,tool as ln}from"@anthropic-ai/claude-agent-sdk";import{z as pn}from"zod";async function Ao(o){let{listChannels:e}=await import("./channels-VEUBY2NZ.js"),t=e(),{listSessions:r}=await import("./session-manager-45LFTPBA.js"),s=[...r("active"),...r("archived")],n=t.find(c=>c.name.toLowerCase().includes(o.toLowerCase()));if(!n)return null;let i=s.find(c=>c.source.type==="channel"&&c.source.channelId===n.id&&c.source.chatId)?.source.chatId??n.config?.userId??"";return{channelId:n.id,chatId:i}}function Ae(o){return{content:[{type:"text",text:JSON.stringify(o)}]}}function un(o){let e=o?q(o):void 0,t=[...nr(o),ln("list_channels","List all available channels. Use this to discover what channels can be used with send_to_channel.",{},async()=>{let{listChannels:r}=await import("./channels-VEUBY2NZ.js"),s=r();return Ae({channels:s.map(n=>({id:n.id,name:n.name,enabled:n.enabled,type:n.config?.type??"unknown"}))})}),ln("send_to_channel","Send a message to a connected channel by name. This role can only send to channels in its allowedChannels list (if configured).",{channelName:pn.string().describe("The channel name, e.g., 'WeChat on iPad'"),message:pn.string().describe("The message content to send")},async r=>{if(e?.allowedChannels!==void 0){if(e.allowedChannels.length===0)return Ae({error:"This role is not allowed to send to any channels"});if(!e.allowedChannels.some(l=>l.toLowerCase()===r.channelName.toLowerCase()))return Ae({error:`Channel "${r.channelName}" is not in the allowed channels list for this role`})}let s=await Ao(r.channelName);if(!s)return Ae({error:`Channel "${r.channelName}" not found or has no chatId available`});let{getOutboundGateway:n}=await import("./outbound-gateway-FIPC4BZO.js"),i=await n().send({channelId:s.channelId,chatId:s.chatId,content:r.message,messageType:"reply"});return Ae({success:i.success,channelName:r.channelName})})];return _o({name:"execution-tools",version:"1.0.0",tools:t})}var Q=O("execution"),Ee=class{async execute(e,t){let r=Date.now(),s,n,a;H(e.id,{status:"running",startedAt:Date.now()}),f.emit({type:"task_status_change",taskId:e.id,oldStatus:e.status,newStatus:"running"}),Q.info({taskId:e.id,roleId:e.roleId},"ExecutionManager: starting task");try{let i=e.roleId?q(e.roleId):void 0,c=A;i&&(we(i),c=ee(i.name));let l={taskId:e.id,prompt:e.prompt,roleName:i?.name,roleCagPrompt:i?.cagPrompt,allowedTools:i?.allowedTools},d=qt(l),m=Pe({currentTaskId:e.id,roleId:e.roleId,taskPrompt:e.prompt}),h=e.config.approvalTimeout??300,y=i?.preferences?.permissions,C=Ce(x=>({allowedPaths:y?.allowedPaths,deniedPaths:y?.deniedPaths,disallowedTools:i?.disallowedTools,approvalRequired:i?.approvalRequired??e.config.approvalRequired}),async(x,N,G,Fe)=>{let J=xo(),it=fs(Fe??e.roleId,e.prompt,"medium");if(it)return Q.info({operationId:J,ruleId:it.id,taskId:e.id},"Auto-approved by permanent rule"),{behavior:"allow",updatedInput:N};let je={steps:[{index:0,description:`${x}: ${JSON.stringify(N).slice(0,300)}`,toolsNeeded:[x],expectedOutput:"",riskLevel:"medium"}],requiredPermissions:{},overallRisk:"medium"};return us({id:J,taskId:e.id,roleId:Fe??e.roleId,plan:je,status:"pending",createdAt:Date.now()}),f.emit({type:"plan_approval_request",taskId:e.id,planId:J,plan:je}),Q.info({taskId:e.id,operationId:J,toolName:x,matchedPattern:G},"Privilege escalation: awaiting user decision"),new Promise(ct=>{let En=setTimeout(()=>{Yt(),gs(J,"denied"),Q.warn({taskId:e.id,operationId:J},"Privilege escalation timed out, auto-denied"),ct({behavior:"deny",message:`Operation timed out after ${h}s. Auto-denied. Try a safer alternative that does not require approval.`})},h*1e3),Qt=ye=>{if(ye.planId===J)if(Yt(),ye.decision==="allow")Q.info({taskId:e.id,operationId:J,approvalType:ye.approvalType},"Operation authorized by user"),ct({behavior:"allow",updatedInput:N});else{let xn=ye.reason?`Operation denied by user: ${ye.reason}. Try a safer alternative.`:"Operation denied by user. Try a safer alternative approach.";Q.info({taskId:e.id,operationId:J,reason:ye.reason??"no reason given"},"Operation denied by user"),ct({behavior:"deny",message:xn})}},Yt=()=>{clearTimeout(En),f.off("plan_approval_decision",Qt)};f.on("plan_approval_decision",Qt)})}),W={...process.env,...Me(),DISABLE_TELEMETRY:"1",DISABLE_ERROR_REPORTING:"1",CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1",DISABLE_AUTOUPDATER:"1"},oe=e.config.maxBudgetUsd??5,$=e.config.maxTurns??100,ae=un(e.roleId??""),Ie=i?.mcpServers??{},_=e.config.mcpServers??{},ie={...Ie,..._,"execution-tools":ae},me=i?.additionalDirectories??[],ge=i?lr(i):[],fe=[e.config.workspacePath??process.cwd(),...me.map(x=>x.path)].filter((x,N,G)=>G.indexOf(x)===N),at=Eo({prompt:e.prompt,options:{cwd:c,additionalDirectories:fe,systemPrompt:d,maxTurns:$,maxBudgetUsd:oe,allowedTools:i?.allowedTools,model:i?.model,mcpServers:ie,settingSources:i?.inheritUserSettings?["project","user"]:["project"],hooks:m,canUseTool:C,env:W,plugins:ge.map(x=>({type:"local",path:x})),stderr:x=>{x.trim()&&Q.debug({stderr:x.trim().slice(0,500)},"ExecutionManager SDK stderr")}}}),ce="",v=0,V=()=>{Q.warn({taskId:e.id},"ExecutionManager: abort signal received")};t&&t.addEventListener("abort",V);try{for await(let x of at){let N=x;if(Q.debug({eventType:N.type,taskId:e.id},"ExecutionManager SDK event"),N.type==="result"&&typeof N.result=="string"&&(ce=N.result),N.type==="result"&&v++,N.token_usage){let G=N.token_usage;G.input_tokens!==void 0&&G.output_tokens!==void 0&&(s={input:G.input_tokens,output:G.output_tokens}),G.cost_usd!==void 0&&(n=G.cost_usd)}}}finally{t&&t.removeEventListener("abort",V)}a=v;let re=Date.now()-r;return H(e.id,{status:"completed",result:ce,completedAt:Date.now(),costUsd:n,tokenUsage:s,numTurns:a,totalDurationMs:re}),f.emit({type:"task_status_change",taskId:e.id,oldStatus:"running",newStatus:"completed"}),f.emit({type:"task_complete_event",taskId:e.id,result:ce}),ge.length>0&&an(e.id,ge,e.roleId),Q.info({taskId:e.id,durationMs:re,costUsd:n},"ExecutionManager: task completed"),{taskId:e.id,status:"completed",result:ce,costUsd:n,tokenUsage:s,numTurns:a,durationMs:re}}catch(i){let c=i instanceof Error?i.message:String(i),l=Date.now()-r;return(c.includes("Prompt is too long")||c.includes("prompt is too long"))&&Q.warn({taskId:e.id,error:c},"Task prompt exceeds model context window \u2014 task failed"),H(e.id,{status:"failed",error:c,completedAt:Date.now(),totalDurationMs:l}),f.emit({type:"task_status_change",taskId:e.id,oldStatus:"running",newStatus:"failed"}),f.emit({type:"task_complete_event",taskId:e.id,error:c}),Q.error({taskId:e.id,error:i},"ExecutionManager: task failed"),{taskId:e.id,status:"failed",error:c,durationMs:l}}}};var Y=O("execution-pool"),xe=class{slots;running=!1;pollTimeoutId=null;executor;constructor(e,t){this.slots=Array.from({length:e},(r,s)=>({index:s,taskId:null,abortController:null})),this.executor=t??new Ee}async start(){if(this.running)return;this.running=!0,f.on("task_created",r=>{this.onTaskCreated(r.taskId)}),f.on("task_status_change",r=>{r.newStatus==="pending"&&this.pickupPendingTasks()});let t=U().execution?.pollIntervalMs??3e4;this.pollTimeoutId=setTimeout(this.poll,t),Y.info({maxConcurrent:this.slots.length},"ExecutionPool started")}stop(){this.running=!1,this.pollTimeoutId&&(clearTimeout(this.pollTimeoutId),this.pollTimeoutId=null);for(let e of this.slots)e.abortController&&(e.abortController.abort(),e.taskId=null,e.abortController=null);Y.info("ExecutionPool stopped")}poll=()=>{if(!this.running)return;this.pickupPendingTasks();let t=U().execution?.pollIntervalMs??3e4;this.pollTimeoutId=setTimeout(this.poll,t)};async onTaskCreated(e){this.running&&await this.pickupPendingTasks()}async pickupPendingTasks(){if(!this.running)return;let e=this.slots.find(i=>i.taskId===null);if(!e){Y.debug("No free slots available");return}let t=M("pending");if(t.length===0)return;let s=[...t].sort((i,c)=>i.createdAt-c.createdAt)[0];e.taskId=s.id,e.abortController=new AbortController;let n=e.index,a=s.id;Y.info({slotIndex:n,taskId:a},"ExecutionPool: claimed slot for task"),this.emitSlotChange(),this.executeTask(s,n).catch(i=>{Y.error({taskId:a,error:i},"ExecutionPool: executeTask failed unexpectedly")})}async executeTask(e,t){let r=this.slots[t];if(!r)return;let s="completed";try{f.emit({type:"execution_task_start",taskId:e.id,slotIndex:t});let n=await this.executor.execute(e,r.abortController?.signal);s=n.status,Y.info({taskId:e.id,status:n.status,slotIndex:t},"ExecutionPool: task finished")}finally{r.taskId=null,r.abortController=null,f.emit({type:"execution_task_end",taskId:e.id,slotIndex:t,status:s}),this.emitSlotChange(),this.runPostCompletion(e.id,e.roleId).catch(n=>{Y.error({taskId:e.id,error:n},"Post-completion processing failed (non-fatal)")}),this.running&&this.pickupPendingTasks()}}emitSlotChange(){let e=this.slots.filter(r=>r.taskId!==null).length,t=M("pending");f.emit({type:"execution_slot_change",active:e,max:this.slots.length,queued:t.length})}async runPostCompletion(e,t){if(t){try{let{processTaskCompletion:r}=await import("./memory-extractor-GOISDQTO.js"),s=await r(e,t);s>0&&Y.debug({taskId:e,roleId:t,memoriesStored:s},"Post-completion: memories extracted")}catch(r){Y.error({taskId:e,roleId:t,error:r},"Post-completion: memory extraction failed")}try{let{processTaskReview:r}=await import("./learner-VMD5NQCD.js");await r(e)}catch(r){Y.error({taskId:e,roleId:t,error:r},"Post-completion: task review failed")}try{let{evaluateTaskCompletion:r}=await import("./monitor-K7CGTLA6.js");r(e,t)}catch(r){Y.error({taskId:e,roleId:t,error:r},"Post-completion: monitor evaluation failed")}}}getStatus(){let e=this.slots.filter(r=>r.taskId!==null).length,t=M("pending");return{active:e,max:this.slots.length,queued:t.length}}isHealthy(){return this.running}releaseSlot(e){let t=this.slots.find(r=>r.taskId===e);t&&(Y.warn({taskId:e,slotIndex:t.index},"ExecutionPool: force-releasing slot"),t.abortController&&t.abortController.abort(),t.taskId=null,t.abortController=null,this.emitSlotChange(),this.running&&this.pickupPendingTasks())}};import{v4 as Bt}from"uuid";var Ut=O("message-handler");async function Do(o,e){if(!(await import("./config-Y4QWELO3.js").then(s=>s.getChatConfig())).autoTitle)return;let r=["Generate a very short title (max 50 characters) for a chat session that started with this message:",`"${e.slice(0,200)}"`,"Respond with only the title, no quotes or explanation."].join(`
130
- `);try{let n=(await Js(r,"You are a concise title generator. Reply with only the title, max 50 characters.")).trim().slice(0,50);n.length>0&&Is(o,{title:n})}catch{}}var Wt=null;function mn(o){Wt=o}async function Je(o,e,t,r){let s;r&&(s=K(r)),s||(s=Vs(e)),s||(s=Ve(e,t));let n=Bt(),a={id:n,sessionId:s.id,role:"user",content:o,source:e,createdAt:Date.now()};if(te(a),f.emit({type:"chat_message",sessionId:s.id,message:a}),s.messageCount===0&&Do(s.id,o),se(s.id),Ct(s.id),Wt){let i=s.id,c=s.source;(async()=>{try{let l=await Wt.handleMessage(o,i,e),d={id:Bt(),sessionId:i,role:"assistant",content:l,source:e,createdAt:Date.now()};te(d),f.emit({type:"chat_message",sessionId:i,message:d}),se(i),Ct(i),c.type==="channel"&&c.channelId&&c.chatId&&(Ut.info({sessionId:i,sourceType:c.type,hasChannelId:!!c.channelId,hasResponse:!!l},"Chat response ready, checking channel delivery"),Oo(c.channelId,c.chatId,l))}catch(l){(await import("./logger-BEG4WFIM.js")).getLogger("message-handler").error({error:l,sessionId:i},"ChatManager response failed");let m={id:Bt(),sessionId:i,role:"assistant",content:`\u26A0\uFE0F \u5904\u7406\u5931\u8D25: ${l instanceof Error?l.message:String(l)}`,source:e,createdAt:Date.now()};te(m),f.emit({type:"chat_message",sessionId:i,message:m}),se(i)}})()}return{sessionId:s.id,messageId:n}}async function Oo(o,e,t){Ut.info({channelId:o,chatId:e.slice(0,12)},"Delivering chat response to channel");try{let{getOutboundGateway:r}=await import("./outbound-gateway-FIPC4BZO.js");await r().send({channelId:o,chatId:e,content:t,messageType:"reply"})}catch(r){Ut.error({error:r,channelId:o,chatId:e.slice(0,12)},"Channel delivery failed (non-fatal)")}}import{z as b}from"zod/v4";import{v4 as Fo}from"uuid";var gn=b.union([b.object({type:b.literal("session"),sessionId:b.string()}),b.object({type:b.literal("channel"),channelId:b.string(),chatId:b.string().optional()})]),jo=b.object({id:b.string(),prompt:b.string(),dependsOn:b.array(b.string()).optional(),outputAs:b.string().optional()}),No=b.object({type:b.enum(["cron","manual","event","once"]),cron:b.string().optional(),event:b.string().optional(),runAt:b.string().optional()}),$t=b.object({name:b.string().min(1),description:b.string().optional(),trigger:No,steps:b.array(jo).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(gn).optional(),reportTo:b.array(gn).optional()}),nd=$t.transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Lo=$t.partial().transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Xe=b.object({id:b.string().min(1)});async function fn(o,e){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"}}}},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(t,r)=>{let s=$t.safeParse(t.body);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)});let n={id:Fo(),...s.data,createdAt:Date.now()};return js(n),n.enabled&&n.trigger.type==="cron"&&n.trigger.cron?await e.scheduleJob(n.id):n.enabled&&n.trigger.type==="once"&&n.trigger.runAt&&e.scheduleOnceJob(n.id),r.status(201).send({templateId:n.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 t=>{let s=t.query.enabled==="true";return{templates:Ls(s)}}),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(t,r)=>{let s=Xe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)});let n=ne(s.data.id);return n?{template:n}:r.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(t,r)=>{let s=Xe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)});let n=Lo.safeParse(t.body);if(!n.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(n.error)});if(!ne(s.data.id))return r.status(404).send({code:"NOT_FOUND",message:"Template not found"});Ns(s.data.id,n.data),await e.unscheduleJob(s.data.id);let i=ne(s.data.id);return i?.enabled&&i.trigger.type==="cron"&&i.trigger.cron?await e.scheduleJob(i.id):i?.enabled&&i.trigger.type==="once"&&i.trigger.runAt&&e.scheduleOnceJob(i.id),{templateId:s.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(t,r)=>{let s=Xe.safeParse(t.params);return s.success?ne(s.data.id)?(await e.unscheduleJob(s.data.id),Ms(s.data.id),{templateId:s.data.id,deleted:!0}):r.status(404).send({code:"NOT_FOUND",message:"Template not found"}):r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.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(t,r)=>{let s=Xe.safeParse(t.params);return s.success?ne(s.data.id)?{executionId:await e.runNow(s.data.id),status:"started"}:r.status(404).send({code:"NOT_FOUND",message:"Template not found"}):r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)})})}import{z as E}from"zod/v4";_s();var Vt=E.object({id:E.string().min(1)}),Mo=E.object({scope:E.enum(["user","project"]).optional(),cwd:E.string().optional()}),qo=E.object({scope:E.enum(["user","project"]).optional(),cwd:E.string().optional()});async function yn(o){o.get("/plugins",{schema:{tags:["Plugins"],summary:"List all installed plugins",querystring:{type:"object",properties:{scope:{type:"string",enum:["user","project","local"]}}}}},async t=>{let r=t.query,s=Be({scope:r.scope}),n=wt();return{plugins:s.map(a=>({...a,globalEnabled:n[a.id]??a.enabled}))}}),o.get("/plugins/:id",{schema:{tags:["Plugins"],summary:"Get plugin by ID",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(t,r)=>{let s=Vt.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)});let n=Ss(s.data.id);if(!n)return r.status(404).send({code:"NOT_FOUND",message:"Plugin not found"});let a=ws(n.installPath),i=wt();return{plugin:{...n,globalEnabled:i[n.id]??n.enabled,manifest:a}}}),o.post("/plugins/:id/enable",{schema:{tags:["Plugins"],summary:"Enable a plugin globally",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(t,r)=>{let s=Vt.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return cr(s.data.id),{pluginId:s.data.id,enabled:!0}}catch(n){return r.status(500).send({code:"CLI_ERROR",message:n instanceof Error?n.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(t,r)=>{let s=Vt.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return dr(s.data.id),{pluginId:s.data.id,enabled:!1}}catch(n){return r.status(500).send({code:"CLI_ERROR",message:n instanceof Error?n.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 t=>{let r=t.query;return{stats:dn(r.limit??50)}});let e=E.object({roleId:E.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(t,r)=>{let s=e.safeParse(t.params);return s.success?{roleId:s.data.roleId,stats:cn(s.data.roleId)}:r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)})}),o.get("/plugins/marketplace",{schema:{tags:["Marketplace"],summary:"List available marketplace plugins"}},async(t,r)=>{if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found. Install Claude Code to use marketplace features."});try{let s=or();return{available:s.available,installed:s.installed}}catch(s){return r.status(500).send({code:"CLI_ERROR",message:s instanceof Error?s.message:"CLI command failed"})}}),o.get("/plugins/marketplaces",{schema:{tags:["Marketplace"],summary:"List known marketplace sources"}},async()=>({sources:Cs()})),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(t,r)=>{let n=E.object({name:E.string().min(1)}).safeParse(t.params);if(!n.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(n.error)});let a=Mo.safeParse(t.body??{});if(!a.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(a.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return ar(n.data.name,a.data.scope??"user",a.data.cwd),{success:!0,pluginId:n.data.name}}catch(i){return r.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(t,r)=>{let n=E.object({name:E.string().min(1)}).safeParse(t.params);if(!n.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(n.error)});let a=qo.safeParse(t.body??{});if(!a.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(a.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return ir(n.data.name,a.data.scope,a.data.cwd),{success:!0,pluginId:n.data.name}}catch(i){return r.status(500).send({code:"CLI_ERROR",message:i instanceof Error?i.message:"Uninstall failed"})}})}import{z as Gt}from"zod/v4";var Bo=Gt.object({name:Gt.string().min(1)}),Uo="x-api-key";async function hn(o,e,t){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(r,s)=>{if(t&&r.headers[Uo]!==t)return s.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"});let n=Bo.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:Gt.prettifyError(n.error)});let{name:a}=n.data,i=ne(a);if(!i){let{listTaskTemplates:c}=await import("./task-templates-7LSQ6OST.js");i=c(!1).find(d=>d.name===a||d.id===a)}if(!i)return s.status(404).send({code:"NOT_FOUND",message:`Template '${a}' not found`});if(!i.enabled)return s.status(409).send({code:"DISABLED",message:`Template '${a}' is disabled`});try{let c=await e.runNow(i.id);return s.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 s.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:r}=await import("./task-templates-7LSQ6OST.js");return{webhooks:r(!0).map(n=>({name:n.id,displayName:n.name,description:n.description,tags:n.tags,trigger:`POST /webhooks/${n.id}`})),auth:t?"X-API-Key header required":"No auth configured"}})}import{z as k}from"zod/v4";var Wo=k.object({status:k.string().optional(),limit:k.coerce.number().min(1).max(100).default(20),offset:k.coerce.number().min(0).default(0)}),Ze=k.union([k.object({type:k.literal("session"),sessionId:k.string()}),k.object({type:k.literal("channel"),channelId:k.string(),chatId:k.string().optional()})]),$o=k.object({input:k.string().min(1,"goal input is required"),deliverTo:k.array(Ze).optional(),reportTo:k.array(Ze).optional()}),bn=k.object({id:k.string().min(1)}),Vo=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(Ze).optional(),reportTo:k.array(Ze).optional()});async function vn(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(e,t)=>{let r=Wo.safeParse(e.query);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)});let{status:s,limit:n,offset:a}=r.data;return{goals:qs(s,n,a)}}),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(e,t)=>{let r=le(e.params.id);return r?{goal:r}:t.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(e,t)=>{let r=$o.safeParse(e.body);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)});let s=await Xs(r.data.input);if(!s.validationResult.isValid)return t.status(400).send({code:"INVALID_GOAL",errors:s.validationResult.errors,warnings:s.validationResult.warnings});let n=Zs(s.goalState,r.data.deliverTo,r.data.reportTo);return er(n.id,n.metricType),t.status(201).send({goal:n})}),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(e,t)=>{let r=bn.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)});let s=Vo.safeParse(e.body);return s.success?le(r.data.id)?(We(r.data.id,{...s.data,updatedAt:Date.now()}),{goal:le(r.data.id)}):t.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(s.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(e,t)=>{let r=bn.safeParse(e.params);return r.success?le(r.data.id)?(Bs(r.data.id),{goalId:r.data.id,deleted:!0}):t.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)})})}import{z as De}from"zod/v4";var Go=De.object({role:De.string().optional(),taskType:De.string().optional(),limit:De.coerce.number().min(1).max(100).default(50)});async function Rn(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(e,t)=>{let r=Go.safeParse(e.query);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:De.prettifyError(r.error)});let{role:s,taskType:n,limit:a}=r.data,i;return s&&n?i=rr.getStrategies(s,n):s?i=sr(s):i=tr(a),{strategies:i.slice(0,a)}})}async function In(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,t)=>{let r=U(),s=[...Ne,...dt],n={},a=new Set(["anthropic.apiKey","server.apiKey"]);for(let i of s){let c=lt(r,i),l=Ne.includes(i);a.has(i)&&typeof c=="string"&&c.length>0&&(c=c.slice(0,5)+"****"),n[i]={value:c??null,mutable:l}}return{config:n,mutable:[...Ne],restartRequired:[...dt]}}),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,t)=>{let r=e.body;if(!r||typeof r!="object")return t.status(400).send({success:!1,updated:[],errors:["Request body must be a JSON object with config key-value pairs"],message:"Validation error"});let s=Xt(r,Pt);if(s.updated.includes("logging.level")){let n=r["logging.level"];typeof n=="string"&&qe(n)}if(s.updated.length>0){let n=U(),a=s.updated.map(i=>({path:i,value:lt(n,i)}));f.emit({type:"config_changed",changes:a})}return{success:s.errors.length===0,updated:s.updated,errors:s.errors,message:s.errors.length===0?`Updated ${s.updated.length} configuration value(s)`:`Updated ${s.updated.length} value(s); ${s.errors.length} rejected (restart required)`}}),o.get("/config/env-diff",async()=>{let e=He();return{diffs:Sr(e),envFileExists:At()!==null}}),o.post("/config/sync-to-env",async()=>{let e=He();return{success:!0,changed:Cr(e)}}),o.post("/config/load-from-env",async()=>{let e=At();if(!e)return{success:!1,error:".env file not found"};let t=0;for(let[r,s]of Object.entries(e)){let n=Object.entries(wr).find(([,a])=>a===r)?.[0];n&&(Pt(n,s),t++)}return Le(He),{success:!0,updated:t}})}async function kn(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(e,t)=>{let{limit:r=20,offset:s=0,roleId:n}=e.query;return n?yr(n,r,s):fr(r,s)})}import{z as T}from"zod/v4";var Ho=["active","archived"],Ko=T.object({source:T.object({type:T.enum(["tui","web","api","channel"]),channelId:T.string().optional(),chatId:T.string().optional()}),roleId:T.string().optional()}),Oe=T.object({id:T.string().uuid()}),zo=T.object({status:T.enum(Ho).optional(),limit:T.coerce.number().min(1).max(100).default(100),offset:T.coerce.number().min(0).default(0)}),Qo=T.object({limit:T.coerce.number().min(1).max(200).default(50),offset:T.coerce.number().min(0).default(0)});async function Tn(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(t,r)=>{let s=Ko.safeParse(t.body);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let{source:n,roleId:a}=s.data,i=Ve(n,a);return r.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(t,r)=>{let s=zo.safeParse(t.query);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let{status:n}=s.data;return{sessions:zs(n)}}),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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);if(!n)return r.status(404).send({code:"NOT_FOUND",message:"Session not found"});let a=Tt(n.id);return{session:n,messages:a}}),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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);return n?(Gs(n.id),{sessionId:n.id,status:"archived"}):r.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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=Hs(s.data.id);return n?{session:n}:r.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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);return n?(Ks(n.id),r.status(204).send()):r.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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);if(!n)return r.status(404).send({code:"NOT_FOUND",message:"Session not found"});let a=Qo.safeParse(t.query),{limit:i=50,offset:c=0}=a.success?a.data:{};return{messages:Tt(n.id,i,c)}});let e=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(t,r)=>{let s=e.safeParse(t.body);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let{content:n,source:a,roleId:i,sessionId:c}=s.data,l=await Je(n,a,i,c);return r.status(201).send(l)})}var Yo=O("ws"),et=new Set,tt=[],Jo=50;function Xo(o){tt.push(o),tt.length>Jo&&tt.shift()}function Re(o){Xo(o);let e=JSON.stringify(o);for(let t of et)t.readyState===1&&t.send(e)}function wn(o){o.get("/chat/stream",{websocket:!0},(e,t)=>{et.add(e);for(let r of tt)e.readyState===1&&e.send(JSON.stringify(r));e.on("close",()=>{et.delete(e)}),e.on("error",r=>{Yo.error({error:r},"Chat WebSocket error"),et.delete(e)})}),f.on("session_created",e=>Re(e)),f.on("session_archived",e=>Re(e)),f.on("session_restored",e=>Re(e)),f.on("session_deleted",e=>Re(e)),f.on("chat_message",e=>Re(e)),f.on("task_complete_event",e=>Re(e))}var B=O("channels"),st=class{adapters=new Map;rateLimits=new Map;healthInterval;rateLimitPerMinute;constructor(e){this.rateLimitPerMinute=e?.rateLimitPerMinute??60}async addChannel(e,t){this.adapters.set(e.id,t),t.onMessage(r=>{this.handleInbound(e.id,r)}),e.enabled&&await this.connectChannel(e.id)}async removeChannel(e){let t=this.adapters.get(e);if(t){try{await t.disconnect()}catch(r){B.error({channelId:e,error:r},"Error disconnecting channel")}this.adapters.delete(e),this.rateLimits.delete(e)}}async connectChannel(e){let t=this.adapters.get(e);if(!t)throw new Error(`No adapter registered for channel ${e}`);try{be(e,"connecting"),await t.connect(),be(e,"connected"),B.info({channelId:e,platform:t.platform},"Channel connected")}catch(r){throw be(e,"error"),B.error({channelId:e,error:r},"Failed to connect channel"),r}}async disconnectChannel(e){let t=this.adapters.get(e);if(t)try{await t.disconnect(),be(e,"disconnected"),B.info({channelId:e},"Channel disconnected")}catch(r){B.error({channelId:e,error:r},"Error disconnecting channel")}}getChannelStatus(e){let t=this.adapters.get(e);return t?t.getStatus():"disconnected"}getChannelStatuses(){let e=new Map;for(let[t,r]of this.adapters)e.set(t,r.getStatus());return e}hasAdapter(e){return this.adapters.has(e)}async sendMessage(e,t,r){let s=this.adapters.get(e);if(!s)return B.warn({channelId:e},"No adapter for outbound message"),null;if(!this.checkRateLimit(e))return B.warn({channelId:e},"Rate limit exceeded, dropping outbound message"),null;try{return await s.sendMessage(t,r)}catch(n){return B.error({channelId:e,chatId:t,error:n},"Failed to send outbound message"),null}}checkRateLimit(e){let t=Date.now(),r=this.rateLimits.get(e);return!r||t-r.windowStart>=6e4?(this.rateLimits.set(e,{count:1,windowStart:t}),!0):r.count>=this.rateLimitPerMinute?!1:(r.count++,!0)}async handleInbound(e,t){if(t.source==="system"){B.debug({channelId:e},"Skipping system message (anti-loop)");return}try{let{isRecentlySent:s}=await import("./outbound-gateway-FIPC4BZO.js"),n=t.channelMessageId??t.raw?.MsgId??"";if(n&&s(String(n))){B.debug({channelId:e,messageId:n},"Skipping delivery-sent message (anti-loop)");return}}catch{}if(!this.checkRateLimit(e)){B.warn({channelId:e,senderId:t.senderId},"Rate limit exceeded for inbound message");return}try{let{handleInboundForApproval:s}=await import("./approval-handler-D3J6NCMM.js");if(await s(e,t.chatId,t.content)){B.debug({channelId:e,chatId:t.chatId},"Inbound message consumed as approval reply");return}}catch{}let r=$s(e);if(r?.allowedChatIds&&!r.allowedChatIds.includes(t.chatId)){B.debug({channelId:e,chatId:t.chatId},"Chat not in allowlist, ignoring");return}try{let s=await Je(t.content,{type:"channel",channelId:e,chatId:t.chatId},r?.linkedRoleId);B.info({channelId:e,chatId:t.chatId,sessionId:s.sessionId},"Inbound message routed to session")}catch(s){B.error({channelId:e,chatId:t.chatId,error:s},"Failed to route inbound message")}}startHealthMonitor(e=3e4){this.stopHealthMonitor(),this.healthInterval=setInterval(()=>{this.checkHealth()},e)}stopHealthMonitor(){this.healthInterval&&(clearInterval(this.healthInterval),this.healthInterval=void 0)}checkHealth(){for(let[e,t]of this.adapters){let r=t.getStatus();try{be(e,r)}catch{}}}async startAll(){let e=$e(!0);for(let t of e){let r=this.adapters.get(t.id);if(r&&r.getStatus()!=="connected")try{await this.connectChannel(t.id)}catch{}}this.startHealthMonitor()}async stopAll(){this.stopHealthMonitor();for(let e of this.adapters.keys())await this.disconnectChannel(e);this.adapters.clear(),this.rateLimits.clear()}_getAdapterCount(){return this.adapters.size}_getRateLimitEntry(e){return this.rateLimits.get(e)}};ke();var X=O("watchdog"),rt=null;function Sn(o,e,t,r){if(!o.enabled){X.info("Watchdog disabled");return}let s=o.intervalMinutes*6e4;X.info({intervalMinutes:o.intervalMinutes},"Watchdog started"),rt=setInterval(()=>{Zo(o,e,t,r)},s)}function Cn(){rt&&(clearInterval(rt),rt=null,X.info("Watchdog stopped"))}function Zo(o,e,t,r){let{rules:s}=o;if(s.managerHealthCheck.enabled){let n=s.managerHealthCheck.staleDurationMinutes*6e4,a=e.getLastActivityAt();if(Date.now()-a>n){let i=`ChatManager session stale (no activity for ${s.managerHealthCheck.staleDurationMinutes} min)`;if(X.warn(i),s.managerHealthCheck.action==="restart"){let c=e.getConsecutiveStaleCount()>0;e.restartSession(),c&&(X.fatal("ChatManager unrecoverable after session restart \u2014 exiting for supervisor restart"),process.exit(1))}else s.managerHealthCheck.action==="notify"&&r(i)}}if(!t.isHealthy()){let n="ExecutionPool is not healthy (stopped unexpectedly)";X.warn(n),r(n)}if(s.staleTasks.enabled){let n=s.staleTasks.maxPendingMinutes*6e4,i=M("pending").filter(c=>Date.now()-c.createdAt>n);if(i.length>0){let c=`${i.length} stale task(s) pending > ${s.staleTasks.maxPendingMinutes} min`;X.warn({count:i.length},c),s.staleTasks.action==="notify"&&r(c)}}if(s.staleRunningTasks?.enabled){let n=s.staleRunningTasks.maxRunningMinutes*6e4,i=M("running").filter(c=>{if(!c.startedAt||Date.now()-c.startedAt<n)return!1;try{let h=L().prepare("SELECT MAX(timestamp) as latest FROM step_logs WHERE task_id = ?").get(c.id)?.latest??c.startedAt;return Date.now()-h>n}catch{return!0}});if(i.length>0){let c=`${i.length} task(s) running with no activity for > ${s.staleRunningTasks.maxRunningMinutes} min \u2014 marking as failed`;X.warn({count:i.length,taskIds:i.map(l=>l.id)},c);for(let l of i)H(l.id,{status:"failed",error:`Watchdog timeout: no activity for > ${s.staleRunningTasks.maxRunningMinutes} min`,completedAt:Date.now()}),f.emit({type:"task_status_change",taskId:l.id,oldStatus:"running",newStatus:"failed"}),t.releaseSlot(l.id);r(c)}}if(s.dbMaintenance.enabled)try{let a=L().pragma("wal_checkpoint(PASSIVE)");X.debug({walSize:a},"WAL checkpoint")}catch(n){X.error({error:n},"DB health check failed")}}import{z as j}from"zod";import{v4 as ea}from"uuid";var ta=j.object({eventType:j.enum(["task_complete","task_error","plan_approval_request","*"]),matchCriteria:j.object({templateId:j.string().optional(),roleId:j.string().optional(),promptPattern:j.string().optional(),taskStatus:j.string().optional()}).optional().default({}),target:j.object({type:j.enum(["channel","webhook"]),channelId:j.string().optional(),chatId:j.string().optional(),webhookUrl:j.string().optional()}),formatTemplate:j.string().optional(),maxPerMinute:j.number().int().min(1).max(60).optional().default(5),skipOriginChannel:j.boolean().optional().default(!0),enabled:j.boolean().optional().default(!0)});async function Ht(o){o.get("/delivery-rules",async(e,t)=>ur()),o.post("/delivery-rules",async(e,t)=>{let r=ta.safeParse(e.body);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:j.prettifyError(r.error)});let s=r.data,n={id:ea(),eventType:s.eventType,matchCriteria:s.matchCriteria,target:s.target,formatTemplate:s.formatTemplate,maxPerMinute:s.maxPerMinute,skipOriginChannel:s.skipOriginChannel,enabled:s.enabled,createdAt:Date.now()};return pr(n),t.status(201).send(n)}),o.put("/delivery-rules/:id",async(e,t)=>{if(!Ge(e.params.id))return t.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let s=e.body;return mr(e.params.id,s),{id:e.params.id,updated:!0}}),o.delete("/delivery-rules/:id",async(e,t)=>Ge(e.params.id)?(gr(e.params.id),{id:e.params.id,deleted:!0}):t.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"})),o.get("/delivery-rules/:id/log",async(e,t)=>ps(e.params.id)),o.post("/delivery-rules/:id/test",async(e,t)=>{let r=Ge(e.params.id);if(!r)return t.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let{getDeliveryEngine:s}=await import("./engine-V5MOGOLN.js"),n=s();if(!n)return t.status(503).send({code:"ENGINE_NOT_READY",message:"DeliveryEngine not initialized"});let a=`[TEST] Delivery rule test at ${new Date().toISOString()}`,{createDeliveryLog:i}=await import("./delivery-log-VYTYUFCK.js"),{v4:c}=await import("uuid"),{TTL_MS:l}=await import("./delivery-log-VYTYUFCK.js"),d={id:c(),ruleId:r.id,status:"pending",target:r.target,content:a,attempts:0,createdAt:Date.now(),expiresAt:Date.now()+l};i(d);try{return await n.attemptDeliveryPublic(d,r),{id:d.id,ruleId:r.id,status:"sent",content:a}}catch(m){let h=m instanceof Error?m.message:String(m);return t.status(500).send({code:"DELIVERY_FAILED",message:h,logId:d.id})}})}de();de();import{existsSync as nt,copyFileSync as sa,mkdirSync as Kt,cpSync as ra}from"fs";import{join as Z}from"path";function zt(){Kt(A,{recursive:!0}),Kt(Z(A,"logs"),{recursive:!0}),Kt(Z(A,".claude"),{recursive:!0})}function Pn(o=process.cwd()){zt();let e=[],t=[{from:Z(o,"data","adam.db"),to:Z(A,"adam.db"),label:"database"},{from:Z(o,"adam.config.yaml"),to:Z(A,"adam.config.yaml"),label:"config"},{from:Z(o,".env"),to:Z(A,".env"),label:".env"}];for(let{from:n,to:a,label:i}of t)nt(n)&&!nt(a)&&(sa(n,a),e.push(i));let r=Z(o,".claude","plugins"),s=Z(A,".claude","plugins");return nt(r)&&!nt(s)&&(ra(r,s,{recursive:!0}),e.push("plugins")),e}var P=O("adam");function oa(o){let e={...o};if(e.defaults&&typeof e.defaults=="object"){let t={...e.defaults};if(t.env&&typeof t.env=="object"){let r={...t.env};for(let s of Object.keys(r))r[s]&&(r[s]=r[s].slice(0,4)+"****");t.env=r}e.defaults=t}if(e.server&&typeof e.server=="object"){let t={...e.server};t.apiKey&&typeof t.apiKey=="string"&&(t.apiKey=t.apiKey.slice(0,4)+"****"),e.server=t}return e}async function aa(){zt();let o=Pn();o.length>0&&console.log(`[adam] Migrated to ~/.adam/: ${o.join(", ")}`);let e=Er();P.info("Starting Adam Agent Server"),e.length>0&&P.info({files:e},"Loaded env files");let t=ts();Jt(t),U().anthropic?.apiKey||process.env.ANTHROPIC_API_KEY||P.warn("ANTHROPIC_API_KEY not set \u2014 configure via Settings UI or ~/.adam/.env"),process.env.ANTHROPIC_BASE_URL&&P.info({url:process.env.ANTHROPIC_BASE_URL},"Using custom API base URL");let s=t.defaults?.claudeCodePath;try{if(!s){let{createRequire:G}=await import("module"),{dirname:Fe,join:J}=await import("path"),je=G(import.meta.url).resolve("@anthropic-ai/claude-agent-sdk");s=J(Fe(je),"cli.js")}let{execSync:v}=await import("child_process"),{chmodSync:V,accessSync:re,constants:x}=await import("fs");try{re(s,x.X_OK)}catch{P.info({path:s},"CLI not executable, fixing permissions"),V(s,493)}let N=v(`"${s}" --version`,{timeout:5e3,encoding:"utf-8"}).trim();P.info({path:s,version:N},"Claude Code CLI detected")}catch(v){let V=v;V.code==="ENOENT"?P.warn({path:s},"Claude Code CLI not found. Task execution will fail. Install: npm i -g @anthropic-ai/claude-code"):P.warn({path:s,error:(V.stderr?.trim()||String(v)).slice(0,200)},"Claude Code CLI check failed")}let a=L().prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all();P.info({tables:a.map(v=>v.name).join(", ")},"Database initialized");let i=ss(),c=Ir(i);c>0&&P.info({count:c},"Seeded config DB from .env");let{getAllConfig:l}=await import("./config-WHXCZCI4.js");Le(l);let d=U();d.logging?.level&&qe(d.logging.level),P.info({config:oa(d)},"Config loaded (DB + defaults)");let m=Ft(),{getToolsFingerprint:h}=await import("./adam-tools-Q4BRKX3U.js"),I=h(),y=m.sdkSessionId;if(y&&m.toolsFingerprint!==I&&(P.info({old:m.toolsFingerprint?.slice(0,40),new:I.slice(0,40)},"MCP tools changed \u2014 invalidating old SDK session"),Gr(),y=void 0),Se({toolsFingerprint:I}),y){let v=process.cwd();m.workspacePath&&m.workspacePath!==v&&(P.warn({serverCwd:v,saved:m.workspacePath},"Workspace mismatch"),P.warn("SDK session may not resume correctly due to cwd mismatch")),P.info({sessionId:y.slice(0,8)},"Recovering manager SDK session")}else P.info("No previous manager SDK session found, starting fresh");m.userTaskSessionId&&P.info({sessionId:m.userTaskSessionId.slice(0,8)},"Recovering user task session"),Hr(process.cwd());let{initializeDefaultRoles:g}=await import("./role-presets-FN2RWUCP.js"),C=g();P.info({count:C.length},"Roles initialized");let oe=U().execution??{maxConcurrent:3,maxBudgetPerTaskUsd:5,pollIntervalMs:3e4},$=new _e(y),ae=new xe(oe.maxConcurrent);mn($),await $.start(),await ae.start();let Ie=M("running");if(Ie.length>0){P.warn({count:Ie.length},"Found orphaned running tasks from previous session \u2014 marking as failed");for(let v of Ie)H(v.id,{status:"failed",error:"Server restarted while task was running",completedAt:Date.now()})}let _=Or(t,t.server.apiKey);await _.register(v=>Lr(v)),await _.register(v=>Mr(v,t)),await _.register(v=>Wr(v,t.server.apiKey)),await _.register(Yr),await _.register(rn),await _.register(vn),await _.register(Rn);let ie=new Us;Ws(ie),await ie.start(),Ar(),await _.register(v=>fn(v,ie)),await _.register(yn),await _.register(v=>hn(v,ie,process.env.ADAM_WEBHOOK_API_KEY)),await _.register(In),await _.register(kn),await _.register(Tn);let me=new st;br(me),await _.register(vr),await _.register(wn),await _.register(v=>Vr(v,t.server.apiKey)),await _.register(sn),await _.register(Ht),Qs(),Pr(),kr(),me.startHealthMonitor();try{let v=$e();for(let V of v)if(V.platform==="wechat"){let re=V.config;if(re.botToken){let x=new hr(V.id,re);me.addChannel(V,x)}}}catch(v){P.error({error:v},"Failed to register WeChat adapters at startup")}let{host:ge,port:fe}=t.server;await _.listen({host:ge,port:fe}),P.info({host:ge,port:fe},"Server listening");let at=t.watchdog??es.watchdog;Sn(at,$,ae,v=>{P.warn({alert:v},"Watchdog alert")}),cs(v=>{f.emit({type:"log_event",timestamp:v.time??Date.now(),level:v.level??"info",component:v.component??"adam",msg:v.msg??""})}),An(A,{recursive:!0}),An(ot(A,"logs"),{recursive:!0}),_n(ot(A,"adam.port"),String(fe)),t.server.apiKey&&_n(ot(A,"adam.key"),t.server.apiKey,{mode:384}),process.send?.({type:"ready",port:fe});let ce=async()=>{P.info("Shutting down"),Cn(),Tr(),Ys(),_r(),await me.stopAll(),$.stop(),ae.stop(),await ie.stop(),await _.close(),pt();try{na(ot(A,"adam.key"))}catch{}process.exit(0)};process.on("SIGINT",()=>{ce()}),process.on("SIGTERM",()=>{ce()})}aa().catch(o=>{P.fatal(o,"Fatal error"),process.exit(1)});
129
+ `).all(o)}he();import{createSdkMcpServer as Eo,tool as un}from"@anthropic-ai/claude-agent-sdk";import{z as mn}from"zod";async function xo(o){let{listChannels:e}=await import("./channels-VEUBY2NZ.js"),t=e(),{listSessions:r}=await import("./session-manager-45LFTPBA.js"),s=[...r("active"),...r("archived")],n=t.find(c=>c.name.toLowerCase().includes(o.toLowerCase()));if(!n)return null;let i=s.find(c=>c.source.type==="channel"&&c.source.channelId===n.id&&c.source.chatId)?.source.chatId??n.config?.userId??"";return{channelId:n.id,chatId:i}}function Ae(o){return{content:[{type:"text",text:JSON.stringify(o)}]}}function gn(o){let e=o?M(o):void 0,t=[...ar(o),un("list_channels","List all available channels. Use this to discover what channels can be used with send_to_channel.",{},async()=>{let{listChannels:r}=await import("./channels-VEUBY2NZ.js"),s=r();return Ae({channels:s.map(n=>({id:n.id,name:n.name,enabled:n.enabled,type:n.config?.type??"unknown"}))})}),un("send_to_channel","Send a message to a connected channel by name. This role can only send to channels in its allowedChannels list (if configured).",{channelName:mn.string().describe("The channel name, e.g., 'WeChat on iPad'"),message:mn.string().describe("The message content to send")},async r=>{if(e?.allowedChannels!==void 0){if(e.allowedChannels.length===0)return Ae({error:"This role is not allowed to send to any channels"});if(!e.allowedChannels.some(l=>l.toLowerCase()===r.channelName.toLowerCase()))return Ae({error:`Channel "${r.channelName}" is not in the allowed channels list for this role`})}let s=await xo(r.channelName);if(!s)return Ae({error:`Channel "${r.channelName}" not found or has no chatId available`});let{getOutboundGateway:n}=await import("./outbound-gateway-UCB57NPJ.js"),i=await n().send({channelId:s.channelId,chatId:s.chatId,content:r.message,messageType:"reply"});return Ae({success:i.success,channelName:r.channelName})})];return Eo({name:"execution-tools",version:"1.0.0",tools:t})}var Q=O("execution"),Ee=class{async execute(e,t){let r=Date.now(),s,n,a;H(e.id,{status:"running",startedAt:Date.now()}),f.emit({type:"task_status_change",taskId:e.id,oldStatus:e.status,newStatus:"running"}),Q.info({taskId:e.id,roleId:e.roleId},"ExecutionManager: starting task");try{let i=e.roleId?M(e.roleId):void 0,c=A;i&&(we(i),c=ee(i.name));let l={taskId:e.id,prompt:e.prompt,roleName:i?.name,roleCagPrompt:i?.cagPrompt,allowedTools:i?.allowedTools},d=Bt(l),m=Pe({currentTaskId:e.id,roleId:e.roleId,taskPrompt:e.prompt}),h=e.config.approvalTimeout??300,y=i?.preferences?.permissions,C=Ce(x=>({allowedPaths:y?.allowedPaths,deniedPaths:y?.deniedPaths,disallowedTools:i?.disallowedTools,approvalRequired:i?.approvalRequired??e.config.approvalRequired}),async(x,N,G,Fe)=>{let J=Oo(),ct=hs(Fe??e.roleId,e.prompt,"medium");if(ct)return Q.info({operationId:J,ruleId:ct.id,taskId:e.id},"Auto-approved by permanent rule"),{behavior:"allow",updatedInput:N};let je={steps:[{index:0,description:`${x}: ${JSON.stringify(N).slice(0,300)}`,toolsNeeded:[x],expectedOutput:"",riskLevel:"medium"}],requiredPermissions:{},overallRisk:"medium"};return gs({id:J,taskId:e.id,roleId:Fe??e.roleId,plan:je,status:"pending",createdAt:Date.now()}),f.emit({type:"plan_approval_request",taskId:e.id,planId:J,plan:je}),Q.info({taskId:e.id,operationId:J,toolName:x,matchedPattern:G},"Privilege escalation: awaiting user decision"),new Promise(dt=>{let Dn=setTimeout(()=>{Jt(),ys(J,"denied"),Q.warn({taskId:e.id,operationId:J},"Privilege escalation timed out, auto-denied"),dt({behavior:"deny",message:`Operation timed out after ${h}s. Auto-denied. Try a safer alternative that does not require approval.`})},h*1e3),Yt=ye=>{if(ye.planId===J)if(Jt(),ye.decision==="allow")Q.info({taskId:e.id,operationId:J,approvalType:ye.approvalType},"Operation authorized by user"),dt({behavior:"allow",updatedInput:N});else{let On=ye.reason?`Operation denied by user: ${ye.reason}. Try a safer alternative.`:"Operation denied by user. Try a safer alternative approach.";Q.info({taskId:e.id,operationId:J,reason:ye.reason??"no reason given"},"Operation denied by user"),dt({behavior:"deny",message:On})}},Jt=()=>{clearTimeout(Dn),f.off("plan_approval_decision",Yt)};f.on("plan_approval_decision",Yt)})}),W={...process.env,...qe(),DISABLE_TELEMETRY:"1",DISABLE_ERROR_REPORTING:"1",CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC:"1",DISABLE_AUTOUPDATER:"1"},oe=e.config.maxBudgetUsd??5,V=e.config.maxTurns??100,ae=gn(e.roleId??""),Ie=i?.mcpServers??{},_=e.config.mcpServers??{},ie={...Ie,..._,"execution-tools":ae},me=i?.additionalDirectories??[],ge=i?ur(i):[],fe=[e.config.workspacePath??process.cwd(),...me.map(x=>x.path)].filter((x,N,G)=>G.indexOf(x)===N),it=Do({prompt:e.prompt,options:{cwd:c,additionalDirectories:fe,systemPrompt:d,maxTurns:V,maxBudgetUsd:oe,allowedTools:i?.allowedTools,model:i?.model,mcpServers:ie,settingSources:i?.inheritUserSettings?["project","user"]:["project"],hooks:m,canUseTool:C,env:W,plugins:ge.map(x=>({type:"local",path:x})),stderr:x=>{x.trim()&&Q.debug({stderr:x.trim().slice(0,500)},"ExecutionManager SDK stderr")}}}),ce="",v=0,$=()=>{Q.warn({taskId:e.id},"ExecutionManager: abort signal received")};t&&t.addEventListener("abort",$);try{for await(let x of it){let N=x;if(Q.debug({eventType:N.type,taskId:e.id},"ExecutionManager SDK event"),N.type==="result"&&typeof N.result=="string"&&(ce=N.result),N.type==="result"&&v++,N.token_usage){let G=N.token_usage;G.input_tokens!==void 0&&G.output_tokens!==void 0&&(s={input:G.input_tokens,output:G.output_tokens}),G.cost_usd!==void 0&&(n=G.cost_usd)}}}finally{t&&t.removeEventListener("abort",$)}a=v;let re=Date.now()-r;return H(e.id,{status:"completed",result:ce,completedAt:Date.now(),costUsd:n,tokenUsage:s,numTurns:a,totalDurationMs:re}),f.emit({type:"task_status_change",taskId:e.id,oldStatus:"running",newStatus:"completed"}),f.emit({type:"task_complete_event",taskId:e.id,result:ce}),ge.length>0&&dn(e.id,ge,e.roleId),Q.info({taskId:e.id,durationMs:re,costUsd:n},"ExecutionManager: task completed"),{taskId:e.id,status:"completed",result:ce,costUsd:n,tokenUsage:s,numTurns:a,durationMs:re}}catch(i){let c=i instanceof Error?i.message:String(i),l=Date.now()-r;return(c.includes("Prompt is too long")||c.includes("prompt is too long"))&&Q.warn({taskId:e.id,error:c},"Task prompt exceeds model context window \u2014 task failed"),H(e.id,{status:"failed",error:c,completedAt:Date.now(),totalDurationMs:l}),f.emit({type:"task_status_change",taskId:e.id,oldStatus:"running",newStatus:"failed"}),f.emit({type:"task_complete_event",taskId:e.id,error:c}),Q.error({taskId:e.id,error:i},"ExecutionManager: task failed"),{taskId:e.id,status:"failed",error:c,durationMs:l}}}};var Y=O("execution-pool"),xe=class{slots;running=!1;pollTimeoutId=null;executor;constructor(e,t){this.slots=Array.from({length:e},(r,s)=>({index:s,taskId:null,abortController:null})),this.executor=t??new Ee}async start(){if(this.running)return;this.running=!0,f.on("task_created",r=>{this.onTaskCreated(r.taskId)}),f.on("task_status_change",r=>{r.newStatus==="pending"&&this.pickupPendingTasks()});let t=U().execution?.pollIntervalMs??3e4;this.pollTimeoutId=setTimeout(this.poll,t),Y.info({maxConcurrent:this.slots.length},"ExecutionPool started")}stop(){this.running=!1,this.pollTimeoutId&&(clearTimeout(this.pollTimeoutId),this.pollTimeoutId=null);for(let e of this.slots)e.abortController&&(e.abortController.abort(),e.taskId=null,e.abortController=null);Y.info("ExecutionPool stopped")}poll=()=>{if(!this.running)return;this.pickupPendingTasks();let t=U().execution?.pollIntervalMs??3e4;this.pollTimeoutId=setTimeout(this.poll,t)};async onTaskCreated(e){this.running&&await this.pickupPendingTasks()}async pickupPendingTasks(){if(!this.running)return;let e=this.slots.find(i=>i.taskId===null);if(!e){Y.debug("No free slots available");return}let t=q("pending");if(t.length===0)return;let s=[...t].sort((i,c)=>i.createdAt-c.createdAt)[0];e.taskId=s.id,e.abortController=new AbortController;let n=e.index,a=s.id;Y.info({slotIndex:n,taskId:a},"ExecutionPool: claimed slot for task"),this.emitSlotChange(),this.executeTask(s,n).catch(i=>{Y.error({taskId:a,error:i},"ExecutionPool: executeTask failed unexpectedly")})}async executeTask(e,t){let r=this.slots[t];if(!r)return;let s="completed";try{f.emit({type:"execution_task_start",taskId:e.id,slotIndex:t});let n=await this.executor.execute(e,r.abortController?.signal);s=n.status,Y.info({taskId:e.id,status:n.status,slotIndex:t},"ExecutionPool: task finished")}finally{r.taskId=null,r.abortController=null,f.emit({type:"execution_task_end",taskId:e.id,slotIndex:t,status:s}),this.emitSlotChange(),this.runPostCompletion(e.id,e.roleId).catch(n=>{Y.error({taskId:e.id,error:n},"Post-completion processing failed (non-fatal)")}),this.running&&this.pickupPendingTasks()}}emitSlotChange(){let e=this.slots.filter(r=>r.taskId!==null).length,t=q("pending");f.emit({type:"execution_slot_change",active:e,max:this.slots.length,queued:t.length})}async runPostCompletion(e,t){if(t){try{let{processTaskCompletion:r}=await import("./memory-extractor-GOISDQTO.js"),s=await r(e,t);s>0&&Y.debug({taskId:e,roleId:t,memoriesStored:s},"Post-completion: memories extracted")}catch(r){Y.error({taskId:e,roleId:t,error:r},"Post-completion: memory extraction failed")}try{let{processTaskReview:r}=await import("./learner-VMD5NQCD.js");await r(e)}catch(r){Y.error({taskId:e,roleId:t,error:r},"Post-completion: task review failed")}try{let{evaluateTaskCompletion:r}=await import("./monitor-K7CGTLA6.js");r(e,t)}catch(r){Y.error({taskId:e,roleId:t,error:r},"Post-completion: monitor evaluation failed")}}}getStatus(){let e=this.slots.filter(r=>r.taskId!==null).length,t=q("pending");return{active:e,max:this.slots.length,queued:t.length}}isHealthy(){return this.running}releaseSlot(e){let t=this.slots.find(r=>r.taskId===e);t&&(Y.warn({taskId:e,slotIndex:t.index},"ExecutionPool: force-releasing slot"),t.abortController&&t.abortController.abort(),t.taskId=null,t.abortController=null,this.emitSlotChange(),this.running&&this.pickupPendingTasks())}};import{v4 as Ut}from"uuid";var Wt=O("message-handler");async function Fo(o,e){if(!(await import("./config-Y4QWELO3.js").then(s=>s.getChatConfig())).autoTitle)return;let r=["Generate a very short title (max 50 characters) for a chat session that started with this message:",`"${e.slice(0,200)}"`,"Respond with only the title, no quotes or explanation."].join(`
130
+ `);try{let n=(await Zs(r,"You are a concise title generator. Reply with only the title, max 50 characters.")).trim().slice(0,50);n.length>0&&Ts(o,{title:n})}catch{}}var Vt=null;function fn(o){Vt=o}async function Xe(o,e,t,r){let s;r&&(s=K(r)),s||(s=Hs(e)),s||(s=Ge(e,t));let n=Ut(),a={id:n,sessionId:s.id,role:"user",content:o,source:e,createdAt:Date.now()};if(te(a),f.emit({type:"chat_message",sessionId:s.id,message:a}),s.messageCount===0&&Fo(s.id,o),se(s.id),Pt(s.id),Vt){let i=s.id,c=s.source;(async()=>{try{let l=await Vt.handleMessage(o,i,e),d={id:Ut(),sessionId:i,role:"assistant",content:l,source:e,createdAt:Date.now()};te(d),f.emit({type:"chat_message",sessionId:i,message:d}),se(i),Pt(i),c.type==="channel"&&c.channelId&&c.chatId&&(Wt.info({sessionId:i,sourceType:c.type,hasChannelId:!!c.channelId,hasResponse:!!l},"Chat response ready, checking channel delivery"),jo(c.channelId,c.chatId,l))}catch(l){(await import("./logger-BEG4WFIM.js")).getLogger("message-handler").error({error:l,sessionId:i},"ChatManager response failed");let m={id:Ut(),sessionId:i,role:"assistant",content:`\u26A0\uFE0F \u5904\u7406\u5931\u8D25: ${l instanceof Error?l.message:String(l)}`,source:e,createdAt:Date.now()};te(m),f.emit({type:"chat_message",sessionId:i,message:m}),se(i)}})()}return{sessionId:s.id,messageId:n}}async function jo(o,e,t){Wt.info({channelId:o,chatId:e.slice(0,12)},"Delivering chat response to channel");try{let{getOutboundGateway:r}=await import("./outbound-gateway-UCB57NPJ.js");await r().send({channelId:o,chatId:e,content:t,messageType:"reply"})}catch(r){Wt.error({error:r,channelId:o,chatId:e.slice(0,12)},"Channel delivery failed (non-fatal)")}}import{z as b}from"zod/v4";import{v4 as No}from"uuid";var yn=b.union([b.object({type:b.literal("session"),sessionId:b.string()}),b.object({type:b.literal("channel"),channelId:b.string(),chatId:b.string().optional()})]),Lo=b.object({id:b.string(),prompt:b.string(),dependsOn:b.array(b.string()).optional(),outputAs:b.string().optional()}),qo=b.object({type:b.enum(["cron","manual","event","once"]),cron:b.string().optional(),event:b.string().optional(),runAt:b.string().optional()}),$t=b.object({name:b.string().min(1),description:b.string().optional(),trigger:qo,steps:b.array(Lo).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(yn).optional(),reportTo:b.array(yn).optional()}),cd=$t.transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Mo=$t.partial().transform(o=>({...o,deliverTo:o.deliverTo,reportTo:o.reportTo})),Ze=b.object({id:b.string().min(1)});async function hn(o,e){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"}}}},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(t,r)=>{let s=$t.safeParse(t.body);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)});let n={id:No(),...s.data,createdAt:Date.now()};return Ls(n),n.enabled&&n.trigger.type==="cron"&&n.trigger.cron?await e.scheduleJob(n.id):n.enabled&&n.trigger.type==="once"&&n.trigger.runAt&&e.scheduleOnceJob(n.id),r.status(201).send({templateId:n.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 t=>{let s=t.query.enabled==="true";return{templates:Ms(s)}}),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(t,r)=>{let s=Ze.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)});let n=ne(s.data.id);return n?{template:n}:r.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(t,r)=>{let s=Ze.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)});let n=Mo.safeParse(t.body);if(!n.success)return r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(n.error)});if(!ne(s.data.id))return r.status(404).send({code:"NOT_FOUND",message:"Template not found"});qs(s.data.id,n.data),await e.unscheduleJob(s.data.id);let i=ne(s.data.id);return i?.enabled&&i.trigger.type==="cron"&&i.trigger.cron?await e.scheduleJob(i.id):i?.enabled&&i.trigger.type==="once"&&i.trigger.runAt&&e.scheduleOnceJob(i.id),{templateId:s.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(t,r)=>{let s=Ze.safeParse(t.params);return s.success?ne(s.data.id)?(await e.unscheduleJob(s.data.id),Bs(s.data.id),{templateId:s.data.id,deleted:!0}):r.status(404).send({code:"NOT_FOUND",message:"Template not found"}):r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.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(t,r)=>{let s=Ze.safeParse(t.params);return s.success?ne(s.data.id)?{executionId:await e.runNow(s.data.id),status:"started"}:r.status(404).send({code:"NOT_FOUND",message:"Template not found"}):r.status(400).send({code:"VALIDATION_ERROR",message:b.prettifyError(s.error)})})}import{z as E}from"zod/v4";Es();var Gt=E.object({id:E.string().min(1)}),Bo=E.object({scope:E.enum(["user","project"]).optional(),cwd:E.string().optional()}),Uo=E.object({scope:E.enum(["user","project"]).optional(),cwd:E.string().optional()});async function bn(o){o.get("/plugins",{schema:{tags:["Plugins"],summary:"List all installed plugins",querystring:{type:"object",properties:{scope:{type:"string",enum:["user","project","local"]}}}}},async t=>{let r=t.query,s=Ue({scope:r.scope}),n=St();return{plugins:s.map(a=>({...a,globalEnabled:n[a.id]??a.enabled}))}}),o.get("/plugins/:id",{schema:{tags:["Plugins"],summary:"Get plugin by ID",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(t,r)=>{let s=Gt.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)});let n=Ps(s.data.id);if(!n)return r.status(404).send({code:"NOT_FOUND",message:"Plugin not found"});let a=Cs(n.installPath),i=St();return{plugin:{...n,globalEnabled:i[n.id]??n.enabled,manifest:a}}}),o.post("/plugins/:id/enable",{schema:{tags:["Plugins"],summary:"Enable a plugin globally",params:{type:"object",required:["id"],properties:{id:{type:"string"}}}}},async(t,r)=>{let s=Gt.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return lr(s.data.id),{pluginId:s.data.id,enabled:!0}}catch(n){return r.status(500).send({code:"CLI_ERROR",message:n instanceof Error?n.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(t,r)=>{let s=Gt.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude CLI not found. Plugin enable/disable requires the Claude Agent SDK CLI."});try{return pr(s.data.id),{pluginId:s.data.id,enabled:!1}}catch(n){return r.status(500).send({code:"CLI_ERROR",message:n instanceof Error?n.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 t=>{let r=t.query;return{stats:pn(r.limit??50)}});let e=E.object({roleId:E.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(t,r)=>{let s=e.safeParse(t.params);return s.success?{roleId:s.data.roleId,stats:ln(s.data.roleId)}:r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(s.error)})}),o.get("/plugins/marketplace",{schema:{tags:["Marketplace"],summary:"List available marketplace plugins"}},async(t,r)=>{if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found. Install Claude Code to use marketplace features."});try{let s=ir();return{available:s.available,installed:s.installed}}catch(s){return r.status(500).send({code:"CLI_ERROR",message:s instanceof Error?s.message:"CLI command failed"})}}),o.get("/plugins/marketplaces",{schema:{tags:["Marketplace"],summary:"List known marketplace sources"}},async()=>({sources:_s()})),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(t,r)=>{let n=E.object({name:E.string().min(1)}).safeParse(t.params);if(!n.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(n.error)});let a=Bo.safeParse(t.body??{});if(!a.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(a.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return cr(n.data.name,a.data.scope??"user",a.data.cwd),{success:!0,pluginId:n.data.name}}catch(i){return r.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(t,r)=>{let n=E.object({name:E.string().min(1)}).safeParse(t.params);if(!n.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(n.error)});let a=Uo.safeParse(t.body??{});if(!a.success)return r.status(400).send({code:"VALIDATION_ERROR",message:E.prettifyError(a.error)});if(!ve())return r.status(503).send({code:"CLI_NOT_AVAILABLE",message:"Claude Code CLI not found"});try{return dr(n.data.name,a.data.scope,a.data.cwd),{success:!0,pluginId:n.data.name}}catch(i){return r.status(500).send({code:"CLI_ERROR",message:i instanceof Error?i.message:"Uninstall failed"})}})}import{z as Ht}from"zod/v4";var Wo=Ht.object({name:Ht.string().min(1)}),Vo="x-api-key";async function vn(o,e,t){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(r,s)=>{if(t&&r.headers[Vo]!==t)return s.status(401).send({code:"UNAUTHORIZED",message:"Invalid or missing API key"});let n=Wo.safeParse(r.params);if(!n.success)return s.status(400).send({code:"VALIDATION_ERROR",message:Ht.prettifyError(n.error)});let{name:a}=n.data,i=ne(a);if(!i){let{listTaskTemplates:c}=await import("./task-templates-7LSQ6OST.js");i=c(!1).find(d=>d.name===a||d.id===a)}if(!i)return s.status(404).send({code:"NOT_FOUND",message:`Template '${a}' not found`});if(!i.enabled)return s.status(409).send({code:"DISABLED",message:`Template '${a}' is disabled`});try{let c=await e.runNow(i.id);return s.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 s.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:r}=await import("./task-templates-7LSQ6OST.js");return{webhooks:r(!0).map(n=>({name:n.id,displayName:n.name,description:n.description,tags:n.tags,trigger:`POST /webhooks/${n.id}`})),auth:t?"X-API-Key header required":"No auth configured"}})}import{z as k}from"zod/v4";var $o=k.object({status:k.string().optional(),limit:k.coerce.number().min(1).max(100).default(20),offset:k.coerce.number().min(0).default(0)}),et=k.union([k.object({type:k.literal("session"),sessionId:k.string()}),k.object({type:k.literal("channel"),channelId:k.string(),chatId:k.string().optional()})]),Go=k.object({input:k.string().min(1,"goal input is required"),deliverTo:k.array(et).optional(),reportTo:k.array(et).optional()}),Rn=k.object({id:k.string().min(1)}),Ho=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(et).optional(),reportTo:k.array(et).optional()});async function In(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(e,t)=>{let r=$o.safeParse(e.query);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)});let{status:s,limit:n,offset:a}=r.data;return{goals:Us(s,n,a)}}),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(e,t)=>{let r=le(e.params.id);return r?{goal:r}:t.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(e,t)=>{let r=Go.safeParse(e.body);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)});let s=await er(r.data.input);if(!s.validationResult.isValid)return t.status(400).send({code:"INVALID_GOAL",errors:s.validationResult.errors,warnings:s.validationResult.warnings});let n=tr(s.goalState,r.data.deliverTo,r.data.reportTo);return sr(n.id,n.metricType),t.status(201).send({goal:n})}),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(e,t)=>{let r=Rn.safeParse(e.params);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)});let s=Ho.safeParse(e.body);return s.success?le(r.data.id)?(Ve(r.data.id,{...s.data,updatedAt:Date.now()}),{goal:le(r.data.id)}):t.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(s.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(e,t)=>{let r=Rn.safeParse(e.params);return r.success?le(r.data.id)?(Ws(r.data.id),{goalId:r.data.id,deleted:!0}):t.status(404).send({code:"NOT_FOUND",message:"Goal not found"}):t.status(400).send({code:"VALIDATION_ERROR",message:k.prettifyError(r.error)})})}import{z as De}from"zod/v4";var Ko=De.object({role:De.string().optional(),taskType:De.string().optional(),limit:De.coerce.number().min(1).max(100).default(50)});async function kn(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(e,t)=>{let r=Ko.safeParse(e.query);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:De.prettifyError(r.error)});let{role:s,taskType:n,limit:a}=r.data,i;return s&&n?i=or.getStrategies(s,n):s?i=nr(s):i=rr(a),{strategies:i.slice(0,a)}})}async function Tn(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,t)=>{let r=U(),s=[...Ne,...lt],n={},a=new Set(["anthropic.apiKey","server.apiKey"]);for(let i of s){let c=pt(r,i),l=Ne.includes(i);a.has(i)&&typeof c=="string"&&c.length>0&&(c=c.slice(0,5)+"****"),n[i]={value:c??null,mutable:l}}return{config:n,mutable:[...Ne],restartRequired:[...lt]}}),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,t)=>{let r=e.body;if(!r||typeof r!="object")return t.status(400).send({success:!1,updated:[],errors:["Request body must be a JSON object with config key-value pairs"],message:"Validation error"});let s=Zt(r,_t);if(s.updated.includes("logging.level")){let n=r["logging.level"];typeof n=="string"&&Me(n)}if(s.updated.length>0){let n=U(),a=s.updated.map(i=>({path:i,value:pt(n,i)}));f.emit({type:"config_changed",changes:a})}return{success:s.errors.length===0,updated:s.updated,errors:s.errors,message:s.errors.length===0?`Updated ${s.updated.length} configuration value(s)`:`Updated ${s.updated.length} value(s); ${s.errors.length} rejected (restart required)`}}),o.get("/config/env-diff",async()=>{let e=Ke();return{diffs:Pr(e),envFileExists:Et()!==null}}),o.post("/config/sync-to-env",async()=>{let e=Ke();return{success:!0,changed:_r(e)}}),o.post("/config/load-from-env",async()=>{let e=Et();if(!e)return{success:!1,error:".env file not found"};let t=0;for(let[r,s]of Object.entries(e)){let n=Object.entries(Cr).find(([,a])=>a===r)?.[0];n&&(_t(n,s),t++)}return Le(Ke),{success:!0,updated:t}})}async function wn(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(e,t)=>{let{limit:r=20,offset:s=0,roleId:n}=e.query;return n?br(n,r,s):hr(r,s)})}import{z as T}from"zod/v4";var zo=["active","archived"],Qo=T.object({source:T.object({type:T.enum(["tui","web","api","channel"]),channelId:T.string().optional(),chatId:T.string().optional()}),roleId:T.string().optional()}),Oe=T.object({id:T.string().uuid()}),Yo=T.object({status:T.enum(zo).optional(),limit:T.coerce.number().min(1).max(100).default(100),offset:T.coerce.number().min(0).default(0)}),Jo=T.object({limit:T.coerce.number().min(1).max(200).default(50),offset:T.coerce.number().min(0).default(0)});async function Sn(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(t,r)=>{let s=Qo.safeParse(t.body);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let{source:n,roleId:a}=s.data,i=Ge(n,a);return r.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(t,r)=>{let s=Yo.safeParse(t.query);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let{status:n}=s.data;return{sessions:Ys(n)}}),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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);if(!n)return r.status(404).send({code:"NOT_FOUND",message:"Session not found"});let a=wt(n.id);return{session:n,messages:a}}),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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);return n?(Ks(n.id),{sessionId:n.id,status:"archived"}):r.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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=zs(s.data.id);return n?{session:n}:r.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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);return n?(Qs(n.id),r.status(204).send()):r.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(t,r)=>{let s=Oe.safeParse(t.params);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let n=K(s.data.id);if(!n)return r.status(404).send({code:"NOT_FOUND",message:"Session not found"});let a=Jo.safeParse(t.query),{limit:i=50,offset:c=0}=a.success?a.data:{};return{messages:wt(n.id,i,c)}});let e=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(t,r)=>{let s=e.safeParse(t.body);if(!s.success)return r.status(400).send({code:"VALIDATION_ERROR",message:T.prettifyError(s.error)});let{content:n,source:a,roleId:i,sessionId:c}=s.data,l=await Xe(n,a,i,c);return r.status(201).send(l)})}var Xo=O("ws"),tt=new Set,st=[],Zo=50;function ea(o){st.push(o),st.length>Zo&&st.shift()}function Re(o){ea(o);let e=JSON.stringify(o);for(let t of tt)t.readyState===1&&t.send(e)}function Cn(o){o.get("/chat/stream",{websocket:!0},(e,t)=>{tt.add(e);for(let r of st)e.readyState===1&&e.send(JSON.stringify(r));e.on("close",()=>{tt.delete(e)}),e.on("error",r=>{Xo.error({error:r},"Chat WebSocket error"),tt.delete(e)})}),f.on("session_created",e=>Re(e)),f.on("session_archived",e=>Re(e)),f.on("session_restored",e=>Re(e)),f.on("session_deleted",e=>Re(e)),f.on("chat_message",e=>Re(e)),f.on("task_complete_event",e=>Re(e))}var B=O("channels"),rt=class{adapters=new Map;rateLimits=new Map;healthInterval;rateLimitPerMinute;constructor(e){this.rateLimitPerMinute=e?.rateLimitPerMinute??60}async addChannel(e,t){this.adapters.set(e.id,t),t.onMessage(r=>{this.handleInbound(e.id,r)}),e.enabled&&await this.connectChannel(e.id)}async removeChannel(e){let t=this.adapters.get(e);if(t){try{await t.disconnect()}catch(r){B.error({channelId:e,error:r},"Error disconnecting channel")}this.adapters.delete(e),this.rateLimits.delete(e)}}async connectChannel(e){let t=this.adapters.get(e);if(!t)throw new Error(`No adapter registered for channel ${e}`);try{be(e,"connecting"),await t.connect(),be(e,"connected"),B.info({channelId:e,platform:t.platform},"Channel connected")}catch(r){throw be(e,"error"),B.error({channelId:e,error:r},"Failed to connect channel"),r}}async disconnectChannel(e){let t=this.adapters.get(e);if(t)try{await t.disconnect(),be(e,"disconnected"),B.info({channelId:e},"Channel disconnected")}catch(r){B.error({channelId:e,error:r},"Error disconnecting channel")}}getChannelStatus(e){let t=this.adapters.get(e);return t?t.getStatus():"disconnected"}getChannelStatuses(){let e=new Map;for(let[t,r]of this.adapters)e.set(t,r.getStatus());return e}hasAdapter(e){return this.adapters.has(e)}async sendMessage(e,t,r){let s=this.adapters.get(e);if(!s)return B.warn({channelId:e},"No adapter for outbound message"),null;if(!this.checkRateLimit(e))return B.warn({channelId:e},"Rate limit exceeded, dropping outbound message"),null;try{return await s.sendMessage(t,r)}catch(n){return B.error({channelId:e,chatId:t,error:n},"Failed to send outbound message"),null}}checkRateLimit(e){let t=Date.now(),r=this.rateLimits.get(e);return!r||t-r.windowStart>=6e4?(this.rateLimits.set(e,{count:1,windowStart:t}),!0):r.count>=this.rateLimitPerMinute?!1:(r.count++,!0)}async handleInbound(e,t){if(t.source==="system"){B.debug({channelId:e},"Skipping system message (anti-loop)");return}try{let{isRecentlySent:s}=await import("./outbound-gateway-UCB57NPJ.js"),n=t.channelMessageId??t.raw?.MsgId??"";if(n&&s(String(n))){B.debug({channelId:e,messageId:n},"Skipping delivery-sent message (anti-loop)");return}}catch{}if(!this.checkRateLimit(e)){B.warn({channelId:e,senderId:t.senderId},"Rate limit exceeded for inbound message");return}try{let{handleInboundForApproval:s}=await import("./approval-handler-SSKO2IGC.js");if(await s(e,t.chatId,t.content)){B.debug({channelId:e,chatId:t.chatId},"Inbound message consumed as approval reply");return}}catch{}let r=Gs(e);if(r?.allowedChatIds&&!r.allowedChatIds.includes(t.chatId)){B.debug({channelId:e,chatId:t.chatId},"Chat not in allowlist, ignoring");return}try{let s=await Xe(t.content,{type:"channel",channelId:e,chatId:t.chatId},r?.linkedRoleId);B.info({channelId:e,chatId:t.chatId,sessionId:s.sessionId},"Inbound message routed to session")}catch(s){B.error({channelId:e,chatId:t.chatId,error:s},"Failed to route inbound message")}}startHealthMonitor(e=3e4){this.stopHealthMonitor(),this.healthInterval=setInterval(()=>{this.checkHealth()},e)}stopHealthMonitor(){this.healthInterval&&(clearInterval(this.healthInterval),this.healthInterval=void 0)}checkHealth(){for(let[e,t]of this.adapters){let r=t.getStatus();try{be(e,r)}catch{}}}async startAll(){let e=$e(!0);for(let t of e){let r=this.adapters.get(t.id);if(r&&r.getStatus()!=="connected")try{await this.connectChannel(t.id)}catch{}}this.startHealthMonitor()}async stopAll(){this.stopHealthMonitor();for(let e of this.adapters.keys())await this.disconnectChannel(e);this.adapters.clear(),this.rateLimits.clear()}_getAdapterCount(){return this.adapters.size}_getRateLimitEntry(e){return this.rateLimits.get(e)}};ke();var X=O("watchdog"),nt=null;function Pn(o,e,t,r){if(!o.enabled){X.info("Watchdog disabled");return}let s=o.intervalMinutes*6e4;X.info({intervalMinutes:o.intervalMinutes},"Watchdog started"),nt=setInterval(()=>{ta(o,e,t,r)},s)}function _n(){nt&&(clearInterval(nt),nt=null,X.info("Watchdog stopped"))}function ta(o,e,t,r){let{rules:s}=o;if(s.managerHealthCheck.enabled){let n=s.managerHealthCheck.staleDurationMinutes*6e4,a=e.getLastActivityAt();if(Date.now()-a>n){let i=`ChatManager session stale (no activity for ${s.managerHealthCheck.staleDurationMinutes} min)`;if(X.warn(i),s.managerHealthCheck.action==="restart"){let c=e.getConsecutiveStaleCount()>0;e.restartSession(),c&&(X.fatal("ChatManager unrecoverable after session restart \u2014 exiting for supervisor restart"),process.exit(1))}else s.managerHealthCheck.action==="notify"&&r(i)}}if(!t.isHealthy()){let n="ExecutionPool is not healthy (stopped unexpectedly)";X.warn(n),r(n)}if(s.staleTasks.enabled){let n=s.staleTasks.maxPendingMinutes*6e4,i=q("pending").filter(c=>Date.now()-c.createdAt>n);if(i.length>0){let c=`${i.length} stale task(s) pending > ${s.staleTasks.maxPendingMinutes} min`;X.warn({count:i.length},c),s.staleTasks.action==="notify"&&r(c)}}if(s.staleRunningTasks?.enabled){let n=s.staleRunningTasks.maxRunningMinutes*6e4,i=q("running").filter(c=>{if(!c.startedAt||Date.now()-c.startedAt<n)return!1;try{let h=L().prepare("SELECT MAX(timestamp) as latest FROM step_logs WHERE task_id = ?").get(c.id)?.latest??c.startedAt;return Date.now()-h>n}catch{return!0}});if(i.length>0){let c=`${i.length} task(s) running with no activity for > ${s.staleRunningTasks.maxRunningMinutes} min \u2014 marking as failed`;X.warn({count:i.length,taskIds:i.map(l=>l.id)},c);for(let l of i)H(l.id,{status:"failed",error:`Watchdog timeout: no activity for > ${s.staleRunningTasks.maxRunningMinutes} min`,completedAt:Date.now()}),f.emit({type:"task_status_change",taskId:l.id,oldStatus:"running",newStatus:"failed"}),t.releaseSlot(l.id);r(c)}}if(s.dbMaintenance.enabled)try{let a=L().pragma("wal_checkpoint(PASSIVE)");X.debug({walSize:a},"WAL checkpoint")}catch(n){X.error({error:n},"DB health check failed")}}import{z as j}from"zod";import{v4 as sa}from"uuid";var ra=j.object({eventType:j.enum(["task_complete","task_error","plan_approval_request","*"]),matchCriteria:j.object({templateId:j.string().optional(),roleId:j.string().optional(),promptPattern:j.string().optional(),taskStatus:j.string().optional()}).optional().default({}),target:j.object({type:j.enum(["channel","webhook"]),channelId:j.string().optional(),chatId:j.string().optional(),webhookUrl:j.string().optional()}),formatTemplate:j.string().optional(),maxPerMinute:j.number().int().min(1).max(60).optional().default(5),skipOriginChannel:j.boolean().optional().default(!0),enabled:j.boolean().optional().default(!0)});async function Kt(o){o.get("/delivery-rules",async(e,t)=>gr()),o.post("/delivery-rules",async(e,t)=>{let r=ra.safeParse(e.body);if(!r.success)return t.status(400).send({code:"VALIDATION_ERROR",message:j.prettifyError(r.error)});let s=r.data,n={id:sa(),eventType:s.eventType,matchCriteria:s.matchCriteria,target:s.target,formatTemplate:s.formatTemplate,maxPerMinute:s.maxPerMinute,skipOriginChannel:s.skipOriginChannel,enabled:s.enabled,createdAt:Date.now()};return mr(n),t.status(201).send(n)}),o.put("/delivery-rules/:id",async(e,t)=>{if(!He(e.params.id))return t.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let s=e.body;return fr(e.params.id,s),{id:e.params.id,updated:!0}}),o.delete("/delivery-rules/:id",async(e,t)=>He(e.params.id)?(yr(e.params.id),{id:e.params.id,deleted:!0}):t.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"})),o.get("/delivery-rules/:id/log",async(e,t)=>ms(e.params.id)),o.post("/delivery-rules/:id/test",async(e,t)=>{let r=He(e.params.id);if(!r)return t.status(404).send({code:"NOT_FOUND",message:"Delivery rule not found"});let{getDeliveryEngine:s}=await import("./engine-6SFURLSL.js"),n=s();if(!n)return t.status(503).send({code:"ENGINE_NOT_READY",message:"DeliveryEngine not initialized"});let a=`[TEST] Delivery rule test at ${new Date().toISOString()}`,{createDeliveryLog:i}=await import("./delivery-log-VYTYUFCK.js"),{v4:c}=await import("uuid"),{TTL_MS:l}=await import("./delivery-log-VYTYUFCK.js"),d={id:c(),ruleId:r.id,status:"pending",target:r.target,content:a,attempts:0,createdAt:Date.now(),expiresAt:Date.now()+l};i(d);try{return await n.attemptDeliveryPublic(d,r),{id:d.id,ruleId:r.id,status:"sent",content:a}}catch(m){let h=m instanceof Error?m.message:String(m);return t.status(500).send({code:"DELIVERY_FAILED",message:h,logId:d.id})}})}de();de();import{existsSync as ot,copyFileSync as na,mkdirSync as zt,cpSync as oa}from"fs";import{join as Z}from"path";function Qt(){zt(A,{recursive:!0}),zt(Z(A,"logs"),{recursive:!0}),zt(Z(A,".claude"),{recursive:!0})}function An(o=process.cwd()){Qt();let e=[],t=[{from:Z(o,"data","adam.db"),to:Z(A,"adam.db"),label:"database"},{from:Z(o,"adam.config.yaml"),to:Z(A,"adam.config.yaml"),label:"config"},{from:Z(o,".env"),to:Z(A,".env"),label:".env"}];for(let{from:n,to:a,label:i}of t)ot(n)&&!ot(a)&&(na(n,a),e.push(i));let r=Z(o,".claude","plugins"),s=Z(A,".claude","plugins");return ot(r)&&!ot(s)&&(oa(r,s,{recursive:!0}),e.push("plugins")),e}var P=O("adam");function ia(o){let e={...o};if(e.defaults&&typeof e.defaults=="object"){let t={...e.defaults};if(t.env&&typeof t.env=="object"){let r={...t.env};for(let s of Object.keys(r))r[s]&&(r[s]=r[s].slice(0,4)+"****");t.env=r}e.defaults=t}if(e.server&&typeof e.server=="object"){let t={...e.server};t.apiKey&&typeof t.apiKey=="string"&&(t.apiKey=t.apiKey.slice(0,4)+"****"),e.server=t}return e}async function ca(){Qt();let o=An();o.length>0&&console.log(`[adam] Migrated to ~/.adam/: ${o.join(", ")}`);let e=Dr();P.info("Starting Adam Agent Server"),e.length>0&&P.info({files:e},"Loaded env files");let t=ss();Xt(t),U().anthropic?.apiKey||process.env.ANTHROPIC_API_KEY||P.warn("ANTHROPIC_API_KEY not set \u2014 configure via Settings UI or ~/.adam/.env"),process.env.ANTHROPIC_BASE_URL&&P.info({url:process.env.ANTHROPIC_BASE_URL},"Using custom API base URL");let s=t.defaults?.claudeCodePath;try{if(!s){let{createRequire:G}=await import("module"),{dirname:Fe,join:J}=await import("path"),je=G(import.meta.url).resolve("@anthropic-ai/claude-agent-sdk");s=J(Fe(je),"cli.js")}let{execSync:v}=await import("child_process"),{chmodSync:$,accessSync:re,constants:x}=await import("fs");try{re(s,x.X_OK)}catch{P.info({path:s},"CLI not executable, fixing permissions"),$(s,493)}let N=v(`"${s}" --version`,{timeout:5e3,encoding:"utf-8"}).trim();P.info({path:s,version:N},"Claude Code CLI detected")}catch(v){let $=v;$.code==="ENOENT"?P.warn({path:s},"Claude Code CLI not found. Task execution will fail. Install: npm i -g @anthropic-ai/claude-code"):P.warn({path:s,error:($.stderr?.trim()||String(v)).slice(0,200)},"Claude Code CLI check failed")}let a=L().prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all();P.info({tables:a.map(v=>v.name).join(", ")},"Database initialized");let i=rs(),c=Tr(i);c>0&&P.info({count:c},"Seeded config DB from .env");let{getAllConfig:l}=await import("./config-WHXCZCI4.js");Le(l);let d=U();d.logging?.level&&Me(d.logging.level),P.info({config:ia(d)},"Config loaded (DB + defaults)");let m=jt(),{getToolsFingerprint:h}=await import("./adam-tools-RTCTINZI.js"),I=h(),y=m.sdkSessionId;if(y&&m.toolsFingerprint!==I&&(P.info({old:m.toolsFingerprint?.slice(0,40),new:I.slice(0,40)},"MCP tools changed \u2014 invalidating old SDK session"),Kr(),y=void 0),Se({toolsFingerprint:I}),y){let v=process.cwd();m.workspacePath&&m.workspacePath!==v&&(P.warn({serverCwd:v,saved:m.workspacePath},"Workspace mismatch"),P.warn("SDK session may not resume correctly due to cwd mismatch")),P.info({sessionId:y.slice(0,8)},"Recovering manager SDK session")}else P.info("No previous manager SDK session found, starting fresh");m.userTaskSessionId&&P.info({sessionId:m.userTaskSessionId.slice(0,8)},"Recovering user task session"),zr(process.cwd());let{initializeDefaultRoles:g}=await import("./role-presets-FN2RWUCP.js"),C=g();P.info({count:C.length},"Roles initialized");let oe=U().execution??{maxConcurrent:3,maxBudgetPerTaskUsd:5,pollIntervalMs:3e4},V=new _e(y),ae=new xe(oe.maxConcurrent);fn(V),await V.start(),await ae.start();let Ie=q("running");if(Ie.length>0){P.warn({count:Ie.length},"Found orphaned running tasks from previous session \u2014 marking as failed");for(let v of Ie)H(v.id,{status:"failed",error:"Server restarted while task was running",completedAt:Date.now()})}let _=jr(t,t.server.apiKey);await _.register(v=>Mr(v)),await _.register(v=>Br(v,t)),await _.register(v=>$r(v,t.server.apiKey)),await _.register(Xr),await _.register(on),await _.register(In),await _.register(kn);let ie=new Vs;$s(ie),await ie.start(),xr(),await _.register(v=>hn(v,ie)),await _.register(bn),await _.register(v=>vn(v,ie,process.env.ADAM_WEBHOOK_API_KEY)),await _.register(Tn),await _.register(wn),await _.register(Sn);let me=new rt;Rr(me),await _.register(Ir),await _.register(Cn),await _.register(v=>Hr(v,t.server.apiKey)),await _.register(nn),await _.register(Kt),Js(),Ar(),wr(),me.startHealthMonitor();try{let v=$e();for(let $ of v)if($.platform==="wechat"){let re=$.config;if(re.botToken){let x=new vr($.id,re);me.addChannel($,x)}}}catch(v){P.error({error:v},"Failed to register WeChat adapters at startup")}let{host:ge,port:fe}=t.server;await _.listen({host:ge,port:fe}),P.info({host:ge,port:fe},"Server listening");let it=t.watchdog??ts.watchdog;Pn(it,V,ae,v=>{P.warn({alert:v},"Watchdog alert")}),ds(v=>{f.emit({type:"log_event",timestamp:v.time??Date.now(),level:v.level??"info",component:v.component??"adam",msg:v.msg??""})}),xn(A,{recursive:!0}),xn(at(A,"logs"),{recursive:!0}),En(at(A,"adam.port"),String(fe)),t.server.apiKey&&En(at(A,"adam.key"),t.server.apiKey,{mode:384}),process.send?.({type:"ready",port:fe});let ce=async()=>{P.info("Shutting down"),_n(),Sr(),Xs(),Er(),await me.stopAll(),V.stop(),ae.stop(),await ie.stop(),await _.close(),ut();try{aa(at(A,"adam.key"))}catch{}process.exit(0)};process.on("SIGINT",()=>{ce()}),process.on("SIGTERM",()=>{ce()})}ca().catch(o=>{P.fatal(o,"Fatal error"),process.exit(1)});