@kelceyp/caw-server 1.0.6 → 1.0.7
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/main.js +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -703,4 +703,4 @@ State: ${z.fields.state}
|
|
|
703
703
|
|
|
704
704
|
To confirm, call delete_story with confirm=true`}]}}let J=await $.deleteStory(K,{id:q});return{content:[{type:"text",text:`Deleted story: ${J.id} (${J.descendantCount} descendants also deleted)`}]}}catch(J){return{content:[{type:"text",text:`Error: ${J.message}`}],isError:!0}}},l66={name:"delete_story",title:"Delete Story",description:"Soft delete a story (can be restored later). If confirm is false or omitted, returns impact preview.",schema:qL1,execute:YL1};W6();var JL1=A.object({id:A.string().describe('Story ID (e.g., "As1")')}),zL1=async({core:$,projectId:K},{id:q})=>{try{let Y=await $.incrementStoryJobCount(K,{id:q});if(!Y)return{content:[{type:"text",text:`Story ${q} not found`}],isError:!0};return{content:[{type:"text",text:`Incremented activeJobCount for story ${Y.id} to: ${Y.fields.activeJobCount}`}]}}catch(Y){return{content:[{type:"text",text:`Error: ${Y.message}`}],isError:!0}}},i66={name:"increment_story_job_count",title:"Increment Story Job Count",description:"Increment a story's activeJobCount field (for manual tracking of agent activity)",schema:JL1,execute:zL1};W6();var WL1=A.object({id:A.string().describe('Story ID (e.g., "As1")')}),ZL1=async({core:$,projectId:K},{id:q})=>{try{let Y=await $.decrementStoryJobCount(K,{id:q});if(!Y)return{content:[{type:"text",text:`Story ${q} not found`}],isError:!0};return{content:[{type:"text",text:`Decremented activeJobCount for story ${Y.id} to: ${Y.fields.activeJobCount}`}]}}catch(Y){return{content:[{type:"text",text:`Error: ${Y.message}`}],isError:!0}}},d66={name:"decrement_story_job_count",title:"Decrement Story Job Count",description:"Decrement a story's activeJobCount field (for manual tracking of agent activity). Guards against going below zero.",schema:WL1,execute:ZL1};var n66=[p66,F66,c66,Q66,l66,i66,d66];W6();var HL1=A.object({id:A.string().describe('Asset ID (e.g., "Aa1")')}),OL1=async({core:$,projectId:K},{id:q})=>{try{let{buffer:Y,mimeType:J,sizeBytes:z,hash:W,originalFilename:Z}=await $.readAssetBinary(K,{id:q});return{content:[{type:"image",data:Y.toString("base64"),mimeType:J},{type:"text",text:JSON.stringify({id:q,originalFilename:Z,sizeBytes:z,hash:W},null,2)}]}}catch(Y){return{content:[{type:"text",text:Y.code==="ASSET_NOT_FOUND"||Y.code==="BLOB_NOT_FOUND"?Y.message:`Error: ${Y.message}`}],isError:!0}}},o66={name:"read_asset",title:"Read Asset",description:"Read an asset image by ID. Returns the image as base64-encoded data that Claude can view. Supported formats: PNG, JPEG, GIF, WebP. Maximum size: 10MB.",schema:HL1,execute:OL1};var a66=[o66];W6();var XL1=A.object({store:A.string().optional().describe('Store code (default: "A")'),status:A.string().optional().describe("Filter by status (pending, running, completed, error)")}),PL1=async({core:$,projectId:K},{store:q,status:Y})=>{try{let J=await $.listJobs(K,{store:q||"A",status:Y});if(J.length===0)return{content:[{type:"text",text:"No jobs found"}]};return{content:[{type:"text",text:J.map((W)=>`${W.id}: ${W.name} [${W.fields.status}]`).join(`
|
|
705
705
|
`)}]}}catch(J){return{content:[{type:"text",text:`Error: ${J.message}`}],isError:!0}}},r66={name:"list_jobs",title:"List Jobs",description:"List all jobs",schema:XL1,execute:PL1};W6();var wL1=A.object({id:A.string().describe('Job ID (e.g., "Aj1")')}),TL1=async({core:$,projectId:K},{id:q})=>{try{let Y=await $.getJob(K,{id:q}),J=Y.fields||{};return{content:[{type:"text",text:[`Job: ${Y.id}`,`Name: ${Y.name}`,`Status: ${J.status}`,`PID: ${J.pid||"N/A"}`,`Agent: ${J.agent}`,`Started: ${J.startedAt||"N/A"}`,`Completed: ${J.completedAt||"N/A"}`].join(`
|
|
706
|
-
`)}]}}catch(Y){return{content:[{type:"text",text:`Error: ${Y.message}`}],isError:!0}}},s66={name:"read_job",title:"Read Job",description:"Get job details",schema:wL1,execute:TL1};var t66=[r66,s66];var GL1=({core:$,projectId:K})=>{let q=new ua({name:"caw-server",version:"0.0.1"},{capabilities:{tools:{}}}),Y=[...G66,...A66,...D66,...b66,...U66,...n66,...a66,...t66];for(let J of Y)q.registerTool(J.name,{title:J.title,description:J.description,inputSchema:J.schema},async(z,W)=>{let Z=W?.sessionId||W?.requestInfo?.headers?.["mcp-session-id"];return J.execute({core:$,projectId:K,sessionId:Z},z)});return q},e66=Object.freeze({createMcpServer:GL1});var vL1=ma.default("caw:mcp"),t9=ma.default("caw:mcp:session"),VL1=({core:$})=>{let K=new Map;return Object.freeze({handleRequest:async(W,Z,{projectId:H})=>{let O=W.headers["mcp-session-id"];if(O){let j=K.get(O);if(!j)return t9("Session not found: %s",O),Z.status(404).json({jsonrpc:"2.0",error:{code:-32001,message:"Session not found. Server may have been restarted. If so, ask user to reconnect"},id:null});if(j.projectId!==H)return t9("Session %s belongs to project %s, not %s",O,j.projectId,H),Z.status(404).json({jsonrpc:"2.0",error:{code:-32001,message:"Session not found. Server may have been restarted. If so, ask user to reconnect"},id:null});
|
|
706
|
+
`)}]}}catch(Y){return{content:[{type:"text",text:`Error: ${Y.message}`}],isError:!0}}},s66={name:"read_job",title:"Read Job",description:"Get job details",schema:wL1,execute:TL1};var t66=[r66,s66];var GL1=({core:$,projectId:K})=>{let q=new ua({name:"caw-server",version:"0.0.1"},{capabilities:{tools:{}}}),Y=[...G66,...A66,...D66,...b66,...U66,...n66,...a66,...t66];for(let J of Y)q.registerTool(J.name,{title:J.title,description:J.description,inputSchema:J.schema},async(z,W)=>{try{let Z=W?.sessionId||W?.requestInfo?.headers?.["mcp-session-id"];return await J.execute({core:$,projectId:K,sessionId:Z},z)}catch(Z){return console.error(`Tool ${J.name} failed:`,Z),{content:[{type:"text",text:`Tool execution failed: ${Z.message}`}],isError:!0}}});return q},e66=Object.freeze({createMcpServer:GL1});var vL1=ma.default("caw:mcp"),t9=ma.default("caw:mcp:session"),VL1=({core:$})=>{let K=new Map;return Object.freeze({handleRequest:async(W,Z,{projectId:H})=>{let O=W.headers["mcp-session-id"];if(O){let j=K.get(O);if(!j)return t9("Session not found: %s",O),Z.status(404).json({jsonrpc:"2.0",error:{code:-32001,message:"Session not found. Server may have been restarted. If so, ask user to reconnect"},id:null});if(j.projectId!==H)return t9("Session %s belongs to project %s, not %s",O,j.projectId,H),Z.status(404).json({jsonrpc:"2.0",error:{code:-32001,message:"Session not found. Server may have been restarted. If so, ask user to reconnect"},id:null});t9("Routing request to existing session: %s",O),j.lastActivity=Date.now();try{return await j.transport.handleRequest(W,Z,W.body)}catch(G){console.error("MCP transport request failed:",G)}}t9("Creating new MCP session for project: %s",H);let X=null,P=new ko({sessionIdGenerator:()=>{return X=jL1(),t9("Generated session ID: %s",X),X},onsessioninitialized:(j)=>{t9("Session initialized: %s",j),Z.setHeader("Mcp-Session-Id",j),T.sessionId=j,K.set(j,T),t9("Session stored: %s",j)}});t9("Creating new server for session");let w=e66.createMcpServer({core:$,projectId:H});try{await w.connect(P)}catch(j){return console.error("MCP server connect failed:",j),P.close?.(),w.close?.(),Z.status(500).json({jsonrpc:"2.0",error:{code:-32603,message:"Internal server error"},id:null})}let T={sessionId:null,transport:P,server:w,projectId:H,createdAt:Date.now(),lastActivity:Date.now()};Z.on("finish",()=>{if(Z.statusCode!==200&&X&&K.has(X))t9("Request failed (status %d), cleaning up session: %s",Z.statusCode,X),K.delete(X),P.close?.(),w.close?.()});try{await P.handleRequest(W,Z,W.body)}catch(j){console.error("MCP transport request failed:",j)}},getSession:(W)=>{return K.get(W)},closeSession:(W)=>{let Z=K.get(W);if(!Z){t9("Cannot close session - not found: %s",W);return}t9("Closing session: %s",W),Z.transport.close?.(),Z.server.close?.(),K.delete(W)},cleanupIdle:(W)=>{let Z=Date.now(),H=0;for(let[O,X]of K.entries())if(Z-X.lastActivity>W)t9("Cleaning up idle session: %s (idle for %dms)",O,Z-X.lastActivity),X.transport.close?.(),X.server.close?.(),K.delete(O),H++;if(H>0)vL1("Cleaned up %d idle sessions",H)}})},$16=Object.freeze({create:VL1});var AL1=86400000,ML1=300000,_L1=({mcpSessionManager:$})=>{let{jobFns:K,controlFns:q}=fC.create({name:"cleanup-idle-mcp-sessions",interval:ML1,execute:async()=>{$.cleanupIdle(AL1)}});return{job:Object.freeze(K),control:q}},K16=Object.freeze({create:_L1});var rE=U16.default("caw:server"),qI1=async({port:$,databaseFilepath:K,assetsDir:q,lazilyCreateDb:Y,enableRest:J,enableSse:z,enableStatic:W,enableCrons:Z,enableMcp:H=!0,enableCli:O=!0,staticPath:X,kyselyFactory:P})=>{let w=await rl8.create({databaseFilepath:K,assetsDir:q,lazilyCreateDb:Y,kyselyFactory:P}),T=ea.default();if(T.use(ea.default.json()),T.get("/health",(f,k)=>{k.json({status:"ok"})}),J)T.use("/api",cn8),$i8.create(T,{core:w}),Yi8.create(T,{core:w}),Ji8.create(T,{core:w}),Wi8.create(T,{core:w}),Hi8.create(T,{core:w}),Xi8.create(T,{core:w}),yn8.create(T,{core:w}),mn8.create(T,{core:w}),Un8.create(T,{core:w});if(z)Fn8.create(T,{core:w});if(W&&X)tl8.create(T,{staticPath:X});if(H){rE("Initializing MCP subsystem...");let f=$16.create({core:w});w.registerCronJob(K16,{mcpSessionManager:f}),ln8.create(T,{core:w,mcpSessionManager:f}),rE("MCP subsystem initialized")}if(O){rE("Initializing CLI Adapter subsystem...");let f=(await Promise.resolve().then(() => (C16(),R16))).default,k=(await Promise.resolve().then(() => (S16(),E16))).default,N=(await Promise.resolve().then(() => (y16(),b16))).default,R=(await Promise.resolve().then(() => (B16(),m16))).default,E=N.create({mcpClientFactory:f.create(),aliasGenerator:k.create(),core:w});await E.init(),R.create(T,{cliSessionManager:E}),rE("CLI Adapter subsystem initialized")}if(Z)w.startAllCrons();let j=null,G=new Set;return Object.freeze({app:T,core:w,start:async()=>{return new Promise((f)=>{j=T.listen($,()=>{let k=j.address().port;f(k)}),j.on("connection",(k)=>{G.add(k),k.on("close",()=>{G.delete(k)})})})},stop:async()=>{if(w.stopAllCrons(),j){for(let f of G)f.destroy();return G.clear(),new Promise((f)=>{j.close(()=>{f()})})}}})},p16=Object.freeze({create:qI1});var JI1=3131,zI1=sE.join(sE.dirname(YI1(import.meta.url)),"public_html"),WI1=!0,ZI1=!0,HI1=!0,OI1=!0,XI1=!1,PI1=!0,wI1=!0,TI1=!0,D2=($,K)=>$!==void 0?$==="true":K,GI1=()=>{let $=process.env.CAW_ENV_DIR;if(!$)console.error("ERROR: CAW_ENV_DIR environment variable is required"),console.error("Set it to the path of your environment folder, e.g.:"),console.error(' export CAW_ENV_DIR="$HOME/.caw/dev"'),process.exit(1);return{databaseFilepath:sE.join($,"caw.db"),assetsDir:sE.join($,"assets")}},jI1=async($)=>{let K=await p16.create($),q=await K.start();console.log(`Server listening on port ${q}`),process.on("SIGINT",()=>K.stop("SIGINT")),process.on("SIGTERM",()=>K.stop("SIGTERM"))},vI1=()=>{let{databaseFilepath:$,assetsDir:K}=GI1(),q=process.env.CAW_PORT?Number(process.env.CAW_PORT):JI1,Y=process.env.STATIC_PATH||zI1,J=D2(process.env.LAZY_CREATE_DB,WI1),z=D2(process.env.ENABLE_REST,ZI1),W=D2(process.env.ENABLE_MCP,HI1),Z=D2(process.env.ENABLE_CLI,OI1),H=D2(process.env.ENABLE_WEBLLM_WSS,XI1),O=D2(process.env.ENABLE_SSE,PI1),X=D2(process.env.ENABLE_STATIC,wI1),P=D2(process.env.ENABLE_CRONS,TI1);return Object.freeze({port:q,staticPath:Y,databaseFilepath:$,assetsDir:K,lazilyCreateDb:J,enableRest:z,enableMcp:W,enableCli:Z,enableWebllmWss:H,enableSse:O,enableStatic:X,enableCrons:P})};await jI1(vI1()).catch(($)=>{console.error("ERROR: Failed to start server:",$),process.exit(1)});
|