@vpxa/aikit 0.1.307 → 0.1.308
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/package.json +1 -1
- package/packages/cli/dist/index.js +1 -1
- package/packages/server/dist/bin.js +1 -1
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{server-B_KbLM43.js → server-BSvqfFcK.js} +170 -161
- package/packages/server/dist/{server-utMi-Qu3.js → server-D6sJEw0I.js} +170 -161
- package/packages/server/dist/{server-http-B-TDT3t-.js → server-http-B1ixOw2x.js} +1 -1
- package/packages/server/dist/{server-http-BbuuthEP.js → server-http-BurquBLf.js} +1 -1
- package/packages/server/dist/server-stdio-CBmXDMpq.js +1 -0
- package/packages/server/dist/server-stdio-z3_zG1HF.js +2 -0
- package/packages/server/dist/{version-check-DSWaugPC.js → version-check-CdBHTxtt.js} +1 -1
- package/packages/server/dist/{version-check-6qDKknz4.js → version-check-CggUKvv8.js} +1 -1
- package/scaffold/dist/adapters/hooks.mjs +1 -1
- package/scaffold/dist/definitions/agents.mjs +1 -1
- package/scaffold/dist/definitions/bodies.mjs +6 -6
- package/scaffold/dist/definitions/flows.mjs +6 -6
- package/scaffold/dist/definitions/prompts.mjs +12 -12
- package/scaffold/dist/definitions/protocols.mjs +11 -11
- package/scaffold/dist/definitions/skills/docs.mjs +174 -174
- package/packages/server/dist/server-stdio-BUb39kqq.js +0 -2
- package/packages/server/dist/server-stdio-Ch7yAxNk.js +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as e,i as t,o as n,s as r}from"./bin.js";import{n as i,t as a}from"./startup-maintenance-L9NUOBVy.js";import{createLogger as o,serializeError as s,setDetailedErrorLoggingEnabled as c}from"../../core/dist/index.js";import{randomUUID as l}from"node:crypto";const u=`__pending__:`;function d(e){return e.startsWith(u)}function f(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function p(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var m=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=f(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){p(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){p(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!d(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!d(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!d(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){p(e,503,-32003,`Session capacity reached`);return}let t=this.now(),n=await this.options.createServer(),r={id:`${u}${l()}`,transport:void 0,createdAt:t,lastAccessAt:t,server:n,requestChain:Promise.resolve()},i=this.options.createTransport({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{this.runtimes.delete(r.id),r.id=e,this.runtimes.set(e,r),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return r.transport=i,i.onclose=()=>{let e=r.transport.sessionId??r.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(r.id,r),await n.connect(i),r}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function h(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var g=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=h(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};const _=o(`server`);async function v(o,u){let[{default:d},{loadConfig:f,resolveIndexMode:p},{registerDashboardRoutes:h,resolveDashboardDir:v},{registerSettingsRoutes:y,resolveSettingsDir:b},{createSettingsRouter:x},{authMiddleware:S,getOrCreateToken:C}]=await Promise.all([import(`express`),import(`./config-Bx85fwRX.js`),import(`./dashboard-static-dPnij4uF.js`),import(`./settings-static-MepJZjer.js`),import(`./routes-CfG5gdSR.js`),import(`./auth-bEP-6uqy.js`)]),w=f();c(w.logging?.errorDetails===!0),w.configError&&_.warn(`Config load failure`,{error:w.configError}),_.info(`Config loaded`,{sourceCount:w.sources.length,storePath:w.store.path});let T=d();T.use(d.json({limit:`1mb`}));let E=Number(u),D=`http://localhost:${E}`,O=process.env.AIKIT_CORS_ORIGIN??D,k=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,A=n(`AIKIT_HTTP_MAX_SESSIONS`,8),j=n(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),M=n(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),N=t({limit:100,windowMs:6e4}),P=!1;T.use((e,t,n)=>{let i=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,a=r({requestOrigin:i,configuredOrigin:O,allowAnyOrigin:k,fallbackOrigin:D});if(a.warn&&!P&&(P=!0,_.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:i,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),i&&!a.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(a.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,a.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let F=C();T.use(S(F)),T.use(`/mcp`,(t,n,r)=>{let i=e(t)??t.ip??t.socket.remoteAddress??`anonymous`;if(N.allow(i)){r();return}let a=Math.max(1,Math.ceil(N.getRetryAfterMs(i)/1e3));n.setHeader(`Retry-After`,String(a)),n.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I;T.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(I=t,_.debug(`Captured workspace root from proxy header`,{wsRoot:t}))}n()}),h(T,v(),_);let L=new Date().toISOString();T.use(`/settings/api`,x({log:_,mcpInfo:()=>({transport:`http`,port:E,pid:process.pid,startedAt:L})})),y(T,b(),_),T.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(t,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e});let a={POST:6e4,GET:1e4,DELETE:1e4}[t.method]??3e4;if(!await Promise.race([r.then(()=>!0),new Promise(e=>{let n=setTimeout(()=>{_.warn(`mcpLock timed out waiting for previous request, resetting lock chain`,{method:t.method,timeoutMs:a}),e(!1)},a);n.unref&&n.unref()})])&&(q=Promise.resolve(),i=()=>{},W)){let e=W;W=null,G=null,e.close().catch(()=>{})}try{let r=e(t);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(t,n,t.body),t.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(_.error(`MCP handler error`,s(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(t,n)=>{let r=e(t);if(U&&(!W||r!==G)){await U.handleRequest(t,n,t.body);return}await J(t,n)};T.post(`/mcp`,Y),T.get(`/mcp`,Y),T.delete(`/mcp`,Y);let X=T.listen(E,`127.0.0.1`,()=>{_.info(`MCP server listening`,{url:`http://127.0.0.1:${E}/mcp`,port:E}),setTimeout(async()=>{try{typeof I==`string`&&I.length>0&&(w.sources[0]={path:I,excludePatterns:w.sources[0]?.excludePatterns??[]},w.allRoots=[I],_.debug(`Workspace root applied from proxy header`,{wsRoot:I}));let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:r},{checkForUpdates:c,autoUpgradeScaffold:l}]=await Promise.all([import(`./server-B_KbLM43.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-DSWaugPC.js`)]);c(),l(),setInterval(c,1440*60*1e3).unref();let u=!1,d=p(w),f=e(w,d);K=async()=>{f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})])},V=f.server,H=r,R=!0,_.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),f.startInit(),f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);B=new g(f.aikit.stateStore,{staleTimeoutMinutes:j,gcIntervalMinutes:M,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!f.aikit?.curated||!f.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(f.aikit.curated,f.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&_.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new m({createServer:()=>{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);return t(f.aikit,w)},createTransport:e=>new r(e),maxSessions:A,sessionTimeoutMinutes:j,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),_.info(`HTTP session runtime ready`,{maxSessions:A,sessionTimeoutMinutes:j,gcIntervalMinutes:M})}catch(e){_.error(`Failed to start session manager`,s(e)),R=!1,u=!0,V=null,H=null,K=null}}),d===`auto`?f.ready.then(async()=>{try{let e=w.sources.map(e=>e.path).join(`, `);_.info(`Running initial index`,{sourcePaths:e}),await f.runInitialIndex(),_.info(`Initial index complete`)}catch(e){_.error(`Initial index failed; will retry on aikit_reindex`,i(o,e))}}):d===`smart`?u||f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,w,f.aikit.store),n=f.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),_.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){_.error(`Failed to start smart index scheduler`,i(o,e))}}):_.info(`Initial full indexing skipped in HTTP mode`,{indexMode:d}),f.ready.catch(e=>{_.error(`AI Kit initialization failed`,i(o,e)),R=!1,u=!0,V=null,H=null,K=null}),a(f.ready,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null,o)}catch(e){_.error(`Failed to load server modules`,i(o,e)),R=!1,K=null}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,_.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}export{v as startHttpMode};
|
|
2
|
+
import{a as e,i as t,o as n,s as r}from"./bin.js";import{n as i,t as a}from"./startup-maintenance-L9NUOBVy.js";import{createLogger as o,serializeError as s,setDetailedErrorLoggingEnabled as c}from"../../core/dist/index.js";import{randomUUID as l}from"node:crypto";const u=`__pending__:`;function d(e){return e.startsWith(u)}function f(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function p(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var m=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=f(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){p(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){p(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!d(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!d(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!d(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){p(e,503,-32003,`Session capacity reached`);return}let t=this.now(),n=await this.options.createServer(),r={id:`${u}${l()}`,transport:void 0,createdAt:t,lastAccessAt:t,server:n,requestChain:Promise.resolve()},i=this.options.createTransport({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{this.runtimes.delete(r.id),r.id=e,this.runtimes.set(e,r),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return r.transport=i,i.onclose=()=>{let e=r.transport.sessionId??r.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(r.id,r),await n.connect(i),r}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function h(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var g=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=h(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};const _=o(`server`);async function v(o,u){let[{default:d},{loadConfig:f,resolveIndexMode:p},{registerDashboardRoutes:h,resolveDashboardDir:v},{registerSettingsRoutes:y,resolveSettingsDir:b},{createSettingsRouter:x},{authMiddleware:S,getOrCreateToken:C}]=await Promise.all([import(`express`),import(`./config-Bx85fwRX.js`),import(`./dashboard-static-dPnij4uF.js`),import(`./settings-static-MepJZjer.js`),import(`./routes-CfG5gdSR.js`),import(`./auth-bEP-6uqy.js`)]),w=f();c(w.logging?.errorDetails===!0),w.configError&&_.warn(`Config load failure`,{error:w.configError}),_.info(`Config loaded`,{sourceCount:w.sources.length,storePath:w.store.path});let T=d();T.use(d.json({limit:`1mb`}));let E=Number(u),D=`http://localhost:${E}`,O=process.env.AIKIT_CORS_ORIGIN??D,k=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,A=n(`AIKIT_HTTP_MAX_SESSIONS`,8),j=n(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),M=n(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),N=t({limit:100,windowMs:6e4}),P=!1;T.use((e,t,n)=>{let i=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,a=r({requestOrigin:i,configuredOrigin:O,allowAnyOrigin:k,fallbackOrigin:D});if(a.warn&&!P&&(P=!0,_.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:i,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),i&&!a.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(a.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,a.allowOrigin),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),t.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),e.method===`OPTIONS`){t.status(204).end();return}n()});let F=C();T.use(S(F)),T.use(`/mcp`,(t,n,r)=>{let i=e(t)??t.ip??t.socket.remoteAddress??`anonymous`;if(N.allow(i)){r();return}let a=Math.max(1,Math.ceil(N.getRetryAfterMs(i)/1e3));n.setHeader(`Retry-After`,String(a)),n.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I;T.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(I=t,_.debug(`Captured workspace root from proxy header`,{wsRoot:t}))}n()}),h(T,v(),_);let L=new Date().toISOString();T.use(`/settings/api`,x({log:_,mcpInfo:()=>({transport:`http`,port:E,pid:process.pid,startedAt:L})})),y(T,b(),_),T.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(t,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e});let a={POST:6e4,GET:1e4,DELETE:1e4}[t.method]??3e4;if(!await Promise.race([r.then(()=>!0),new Promise(e=>{let n=setTimeout(()=>{_.warn(`mcpLock timed out waiting for previous request, resetting lock chain`,{method:t.method,timeoutMs:a}),e(!1)},a);n.unref&&n.unref()})])&&(q=Promise.resolve(),i=()=>{},W)){let e=W;W=null,G=null,e.close().catch(()=>{})}try{let r=e(t);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(t,n,t.body),t.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(_.error(`MCP handler error`,s(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(t,n)=>{let r=e(t);if(U&&(!W||r!==G)){await U.handleRequest(t,n,t.body);return}await J(t,n)};T.post(`/mcp`,Y),T.get(`/mcp`,Y),T.delete(`/mcp`,Y);let X=T.listen(E,`127.0.0.1`,()=>{_.info(`MCP server listening`,{url:`http://127.0.0.1:${E}/mcp`,port:E}),setTimeout(async()=>{try{typeof I==`string`&&I.length>0&&(w.sources[0]={path:I,excludePatterns:w.sources[0]?.excludePatterns??[]},w.allRoots=[I],_.debug(`Workspace root applied from proxy header`,{wsRoot:I}));let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:r},{checkForUpdates:c,autoUpgradeScaffold:l}]=await Promise.all([import(`./server-BSvqfFcK.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CdBHTxtt.js`)]);c(),l(),setInterval(c,1440*60*1e3).unref();let u=!1,d=p(w),f=e(w,d);K=async()=>{f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})])},V=f.server,H=r,R=!0,_.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),f.startInit(),f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);B=new g(f.aikit.stateStore,{staleTimeoutMinutes:j,gcIntervalMinutes:M,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!f.aikit?.curated||!f.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-DWaEE6XW.js`).then(e=>e.t),t=await e(f.aikit.curated,f.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&_.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new m({createServer:()=>{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);return t(f.aikit,w)},createTransport:e=>new r(e),maxSessions:A,sessionTimeoutMinutes:j,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),_.info(`HTTP session runtime ready`,{maxSessions:A,sessionTimeoutMinutes:j,gcIntervalMinutes:M})}catch(e){_.error(`Failed to start session manager`,s(e)),R=!1,u=!0,V=null,H=null,K=null}}),d===`auto`?f.ready.then(async()=>{try{let e=w.sources.map(e=>e.path).join(`, `);_.info(`Running initial index`,{sourcePaths:e}),await f.runInitialIndex(),_.info(`Initial index complete`)}catch(e){_.error(`Initial index failed; will retry on aikit_reindex`,i(o,e))}}):d===`smart`?u||f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,w,f.aikit.store),n=f.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),_.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){_.error(`Failed to start smart index scheduler`,i(o,e))}}):_.info(`Initial full indexing skipped in HTTP mode`,{indexMode:d}),f.ready.catch(e=>{_.error(`AI Kit initialization failed`,i(o,e)),R=!1,u=!0,V=null,H=null,K=null}),a(f.ready,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null,o)}catch(e){_.error(`Failed to load server modules`,i(o,e)),R=!1,K=null}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,_.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}export{v as startHttpMode};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,n as t,r as n,t as r}from"./server-utils-De-aZNQa.js";import{n as i,t as a}from"./startup-maintenance-D0Uhpi3k.js";import{createLogger as o,serializeError as s,setDetailedErrorLoggingEnabled as c}from"../../core/dist/index.js";import{randomUUID as l}from"node:crypto";const u=`__pending__:`;function d(e){return e.startsWith(u)}function f(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function p(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var m=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=f(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){p(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){p(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!d(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!d(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!d(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){p(e,503,-32003,`Session capacity reached`);return}let t=this.now(),n=await this.options.createServer(),r={id:`${u}${l()}`,transport:void 0,createdAt:t,lastAccessAt:t,server:n,requestChain:Promise.resolve()},i=this.options.createTransport({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{this.runtimes.delete(r.id),r.id=e,this.runtimes.set(e,r),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return r.transport=i,i.onclose=()=>{let e=r.transport.sessionId??r.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(r.id,r),await n.connect(i),r}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function h(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var g=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=h(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};const _=o(`server`);async function v(o,u){let[{default:d},{loadConfig:f,resolveIndexMode:p},{registerDashboardRoutes:h,resolveDashboardDir:v},{registerSettingsRoutes:y,resolveSettingsDir:b},{createSettingsRouter:x},{authMiddleware:S,getOrCreateToken:C}]=await Promise.all([import(`express`),import(`./config-B-wvmMyo.js`),import(`./dashboard-static-Dw7Nsq4f.js`),import(`./settings-static-BpQgaMRs.js`),import(`./routes-C7bDyCOW.js`),import(`./auth-7LFAZQBu.js`).then(e=>e.t)]),w=f();c(w.logging?.errorDetails===!0),w.configError&&_.warn(`Config load failure`,{error:w.configError}),_.info(`Config loaded`,{sourceCount:w.sources.length,storePath:w.store.path});let T=d();T.use(d.json({limit:`1mb`}));let E=Number(u),D=`http://localhost:${E}`,O=process.env.AIKIT_CORS_ORIGIN??D,k=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,A=n(`AIKIT_HTTP_MAX_SESSIONS`,8),j=n(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),M=n(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),N=r({limit:100,windowMs:6e4}),P=!1;T.use((t,n,r)=>{let i=Array.isArray(t.headers.origin)?t.headers.origin[0]:t.headers.origin,a=e({requestOrigin:i,configuredOrigin:O,allowAnyOrigin:k,fallbackOrigin:D});if(a.warn&&!P&&(P=!0,_.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:i,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),i&&!a.allowOrigin){n.status(403).json({error:`Origin not allowed`});return}if(a.allowOrigin&&n.setHeader(`Access-Control-Allow-Origin`,a.allowOrigin),n.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),n.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),n.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),t.method===`OPTIONS`){n.status(204).end();return}r()});let F=C();T.use(S(F)),T.use(`/mcp`,(e,n,r)=>{let i=t(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(N.allow(i)){r();return}let a=Math.max(1,Math.ceil(N.getRetryAfterMs(i)/1e3));n.setHeader(`Retry-After`,String(a)),n.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I;T.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(I=t,_.debug(`Captured workspace root from proxy header`,{wsRoot:t}))}n()}),h(T,v(),_);let L=new Date().toISOString();T.use(`/settings/api`,x({log:_,mcpInfo:()=>({transport:`http`,port:E,pid:process.pid,startedAt:L})})),y(T,b(),_),T.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(e,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e});let a={POST:6e4,GET:1e4,DELETE:1e4}[e.method]??3e4;if(!await Promise.race([r.then(()=>!0),new Promise(t=>{let n=setTimeout(()=>{_.warn(`mcpLock timed out waiting for previous request, resetting lock chain`,{method:e.method,timeoutMs:a}),t(!1)},a);n.unref&&n.unref()})])&&(q=Promise.resolve(),i=()=>{},W)){let e=W;W=null,G=null,e.close().catch(()=>{})}try{let r=t(e);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(_.error(`MCP handler error`,s(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(e,n)=>{let r=t(e);if(U&&(!W||r!==G)){await U.handleRequest(e,n,e.body);return}await J(e,n)};T.post(`/mcp`,Y),T.get(`/mcp`,Y),T.delete(`/mcp`,Y);let X=T.listen(E,`127.0.0.1`,()=>{_.info(`MCP server listening`,{url:`http://127.0.0.1:${E}/mcp`,port:E}),setTimeout(async()=>{try{typeof I==`string`&&I.length>0&&(w.sources[0]={path:I,excludePatterns:w.sources[0]?.excludePatterns??[]},w.allRoots=[I],_.debug(`Workspace root applied from proxy header`,{wsRoot:I}));let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:r},{checkForUpdates:c,autoUpgradeScaffold:l}]=await Promise.all([import(`./server-utMi-Qu3.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-6qDKknz4.js`)]);c(),l(),setInterval(c,1440*60*1e3).unref();let u=!1,d=p(w),f=e(w,d);K=async()=>{f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})])},V=f.server,H=r,R=!0,_.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),f.startInit(),f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);B=new g(f.aikit.stateStore,{staleTimeoutMinutes:j,gcIntervalMinutes:M,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!f.aikit?.curated||!f.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(f.aikit.curated,f.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&_.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new m({createServer:()=>{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);return t(f.aikit,w)},createTransport:e=>new r(e),maxSessions:A,sessionTimeoutMinutes:j,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),_.info(`HTTP session runtime ready`,{maxSessions:A,sessionTimeoutMinutes:j,gcIntervalMinutes:M})}catch(e){_.error(`Failed to start session manager`,s(e)),R=!1,u=!0,V=null,H=null,K=null}}),d===`auto`?f.ready.then(async()=>{try{let e=w.sources.map(e=>e.path).join(`, `);_.info(`Running initial index`,{sourcePaths:e}),await f.runInitialIndex(),_.info(`Initial index complete`)}catch(e){_.error(`Initial index failed; will retry on aikit_reindex`,i(o,e))}}):d===`smart`?u||f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,w,f.aikit.store),n=f.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),_.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){_.error(`Failed to start smart index scheduler`,i(o,e))}}):_.info(`Initial full indexing skipped in HTTP mode`,{indexMode:d}),f.ready.catch(e=>{_.error(`AI Kit initialization failed`,i(o,e)),R=!1,u=!0,V=null,H=null,K=null}),a(f.ready,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null,o)}catch(e){_.error(`Failed to load server modules`,i(o,e)),R=!1,K=null}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,_.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}export{v as startHttpMode};
|
|
1
|
+
import{a as e,n as t,r as n,t as r}from"./server-utils-De-aZNQa.js";import{n as i,t as a}from"./startup-maintenance-D0Uhpi3k.js";import{createLogger as o,serializeError as s,setDetailedErrorLoggingEnabled as c}from"../../core/dist/index.js";import{randomUUID as l}from"node:crypto";const u=`__pending__:`;function d(e){return e.startsWith(u)}function f(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function p(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var m=class{options;runtimes=new Map;maxSessions;sessionTimeoutMs;now;constructor(e){this.options=e,this.maxSessions=e.maxSessions??8,this.sessionTimeoutMs=(e.sessionTimeoutMinutes??30)*60*1e3,this.now=e.now??(()=>Date.now())}hasSession(e){return this.runtimes.has(e)}getSessionCount(){return this.runtimes.size}async handleRequest(e,t,n=e.body){let r=f(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){p(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){p(t,400,-32e3,`Session required`);return}if(i=await this.createRuntime(t),!i)return}await this.withRuntimeLock(i,async()=>{await i.transport.handleRequest(e,t,n),i.lastAccessAt=this.now();let r=i.transport.sessionId??i.id;e.method!==`DELETE`&&!d(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!d(r)&&await this.closeSession(r,{closeTransport:!1})})}async closeExpiredSessions(){let e=[...this.runtimes.values()].filter(e=>this.now()-e.lastAccessAt>=this.sessionTimeoutMs).map(e=>e.id);for(let t of e)await this.closeSession(t);return e.length}async closeSession(e,t={}){let n=this.runtimes.get(e);return n?(this.runtimes.delete(e),t.notifySessionEnd!==!1&&!d(e)&&this.options.onSessionEnd?.(e),t.closeTransport!==!1&&await n.transport.close().catch(()=>void 0),await n.server.close().catch(()=>void 0),!0):!1}async closeAll(){let e=[...this.runtimes.keys()];for(let t of e)await this.closeSession(t)}async createRuntime(e){if(await this.closeExpiredSessions(),this.runtimes.size>=this.maxSessions){p(e,503,-32003,`Session capacity reached`);return}let t=this.now(),n=await this.options.createServer(),r={id:`${u}${l()}`,transport:void 0,createdAt:t,lastAccessAt:t,server:n,requestChain:Promise.resolve()},i=this.options.createTransport({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{this.runtimes.delete(r.id),r.id=e,this.runtimes.set(e,r),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return r.transport=i,i.onclose=()=>{let e=r.transport.sessionId??r.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(r.id,r),await n.connect(i),r}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function h(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var g=class{stateStore;options;gcTimer=null;constructor(e,t={}){this.stateStore=e,this.options=t}onSessionStart(e,t){this.stateStore.sessionCreate(e,t)}onSessionActivity(e){this.stateStore.sessionTouch(e)}onSessionEnd(e){this.stateStore.sessionDelete(e),Promise.resolve(this.options.onSessionEndMaintenance?.(e)).catch(()=>{})}startGC(){if(this.gcTimer)return;let e=(this.options.gcIntervalMinutes??5)*60*1e3;this.gcTimer=setInterval(()=>{this.runGC()},e),this.gcTimer.unref()}runGC(){let e=this.getStaleSessionIds();for(let t of e)this.options.onBeforeSessionDelete?.(t),Promise.resolve(this.options.onSessionEndMaintenance?.(t)).catch(()=>{}),this.stateStore.sessionDelete(t);return e.length}stop(){this.gcTimer&&=(clearInterval(this.gcTimer),null)}getActiveSessions(){return this.stateStore.sessionList().length}listSessions(){return this.stateStore.sessionList()}getStaleSessionIds(e=Date.now()){let t=(this.options.staleTimeoutMinutes??30)*60*1e3;return this.stateStore.sessionList().filter(n=>{let r=h(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};const _=o(`server`);async function v(o,u){let[{default:d},{loadConfig:f,resolveIndexMode:p},{registerDashboardRoutes:h,resolveDashboardDir:v},{registerSettingsRoutes:y,resolveSettingsDir:b},{createSettingsRouter:x},{authMiddleware:S,getOrCreateToken:C}]=await Promise.all([import(`express`),import(`./config-B-wvmMyo.js`),import(`./dashboard-static-Dw7Nsq4f.js`),import(`./settings-static-BpQgaMRs.js`),import(`./routes-C7bDyCOW.js`),import(`./auth-7LFAZQBu.js`).then(e=>e.t)]),w=f();c(w.logging?.errorDetails===!0),w.configError&&_.warn(`Config load failure`,{error:w.configError}),_.info(`Config loaded`,{sourceCount:w.sources.length,storePath:w.store.path});let T=d();T.use(d.json({limit:`1mb`}));let E=Number(u),D=`http://localhost:${E}`,O=process.env.AIKIT_CORS_ORIGIN??D,k=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,A=n(`AIKIT_HTTP_MAX_SESSIONS`,8),j=n(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),M=n(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),N=r({limit:100,windowMs:6e4}),P=!1;T.use((t,n,r)=>{let i=Array.isArray(t.headers.origin)?t.headers.origin[0]:t.headers.origin,a=e({requestOrigin:i,configuredOrigin:O,allowAnyOrigin:k,fallbackOrigin:D});if(a.warn&&!P&&(P=!0,_.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:i,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),i&&!a.allowOrigin){n.status(403).json({error:`Origin not allowed`});return}if(a.allowOrigin&&n.setHeader(`Access-Control-Allow-Origin`,a.allowOrigin),n.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),n.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID`),n.setHeader(`Access-Control-Expose-Headers`,`Mcp-Session-Id`),t.method===`OPTIONS`){n.status(204).end();return}r()});let F=C();T.use(S(F)),T.use(`/mcp`,(e,n,r)=>{let i=t(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(N.allow(i)){r();return}let a=Math.max(1,Math.ceil(N.getRetryAfterMs(i)/1e3));n.setHeader(`Retry-After`,String(a)),n.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I;T.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(I=t,_.debug(`Captured workspace root from proxy header`,{wsRoot:t}))}n()}),h(T,v(),_);let L=new Date().toISOString();T.use(`/settings/api`,x({log:_,mcpInfo:()=>({transport:`http`,port:E,pid:process.pid,startedAt:L})})),y(T,b(),_),T.get(`/health`,(e,t)=>{t.json({status:`ok`})});let R=!1,z=null,B=null,V=null,H=null,U=null,W=null,G=null,K=null,q=Promise.resolve(),J=async(e,n)=>{if(!R||!V||!H){n.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let r=q,i;q=new Promise(e=>{i=e});let a={POST:6e4,GET:1e4,DELETE:1e4}[e.method]??3e4;if(!await Promise.race([r.then(()=>!0),new Promise(t=>{let n=setTimeout(()=>{_.warn(`mcpLock timed out waiting for previous request, resetting lock chain`,{method:e.method,timeoutMs:a}),t(!1)},a);n.unref&&n.unref()})])&&(q=Promise.resolve(),i=()=>{},W)){let e=W;W=null,G=null,e.close().catch(()=>{})}try{let r=t(e);if(!W){if(r){n.status(404).json({jsonrpc:`2.0`,error:{code:-32001,message:`Session not found`},id:null});return}let e=new H({sessionIdGenerator:()=>l(),onsessioninitialized:async e=>{G=e,B?.onSessionStart(e,{transport:`http`})},onsessionclosed:async e=>{e&&B?.onSessionEnd(e),G=null}});e.onclose=()=>{W===e&&(W=null),G===e.sessionId&&(G=null)},W=e,await V.connect(e)}let i=W;await i.handleRequest(e,n,e.body),e.method!==`DELETE`&&(!r&&i.sessionId?(G=i.sessionId,B?.onSessionStart(i.sessionId,{transport:`http`}),B?.onSessionActivity(i.sessionId)):r&&B?.onSessionActivity(r))}catch(e){if(_.error(`MCP handler error`,s(e)),!n.headersSent){let t=e instanceof Error?e.message:String(e),r=t.includes(`Not Acceptable`);n.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?t:`Internal server error`},id:null})}}finally{i()}},Y=async(e,n)=>{let r=t(e);if(U&&(!W||r!==G)){await U.handleRequest(e,n,e.body);return}await J(e,n)};T.post(`/mcp`,Y),T.get(`/mcp`,Y),T.delete(`/mcp`,Y);let X=T.listen(E,`127.0.0.1`,()=>{_.info(`MCP server listening`,{url:`http://127.0.0.1:${E}/mcp`,port:E}),setTimeout(async()=>{try{typeof I==`string`&&I.length>0&&(w.sources[0]={path:I,excludePatterns:w.sources[0]?.excludePatterns??[]},w.allRoots=[I],_.debug(`Workspace root applied from proxy header`,{wsRoot:I}));let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:n},{StreamableHTTPServerTransport:r},{checkForUpdates:c,autoUpgradeScaffold:l}]=await Promise.all([import(`./server-D6sJEw0I.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-CggUKvv8.js`)]);c(),l(),setInterval(c,1440*60*1e3).unref();let u=!1,d=p(w),f=e(w,d);K=async()=>{f.aikit&&await Promise.all([f.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),f.aikit.graphStore.close().catch(()=>{}),f.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),f.aikit.store.close().catch(()=>{})])},V=f.server,H=r,R=!0,_.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:n.length,resourceCount:2}),f.startInit(),f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);B=new g(f.aikit.stateStore,{staleTimeoutMinutes:j,gcIntervalMinutes:M,onBeforeSessionDelete:e=>{if(G===e&&W){let e=W;W=null,G=null,e.close().catch(()=>void 0)}U?.closeSession(e,{notifySessionEnd:!1})},onSessionEndMaintenance:async()=>{if(!f.aikit?.curated||!f.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(f.aikit.curated,f.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&_.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new m({createServer:()=>{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);return t(f.aikit,w)},createTransport:e=>new r(e),maxSessions:A,sessionTimeoutMinutes:j,onSessionStart:e=>B?.onSessionStart(e,{transport:`http`}),onSessionActivity:e=>B?.onSessionActivity(e),onSessionEnd:e=>B?.onSessionEnd(e)}),B.startGC(),G&&(B.onSessionStart(G,{transport:`http`}),B.onSessionActivity(G)),_.info(`HTTP session runtime ready`,{maxSessions:A,sessionTimeoutMinutes:j,gcIntervalMinutes:M})}catch(e){_.error(`Failed to start session manager`,s(e)),R=!1,u=!0,V=null,H=null,K=null}}),d===`auto`?f.ready.then(async()=>{try{let e=w.sources.map(e=>e.path).join(`, `);_.info(`Running initial index`,{sourcePaths:e}),await f.runInitialIndex(),_.info(`Initial index complete`)}catch(e){_.error(`Initial index failed; will retry on aikit_reindex`,i(o,e))}}):d===`smart`?u||f.ready.then(async()=>{try{if(!f.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.aikit.indexer,w,f.aikit.store),n=f.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),_.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){_.error(`Failed to start smart index scheduler`,i(o,e))}}):_.info(`Initial full indexing skipped in HTTP mode`,{indexMode:d}),f.ready.catch(e=>{_.error(`AI Kit initialization failed`,i(o,e)),R=!1,u=!0,V=null,H=null,K=null}),a(f.ready,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null,o)}catch(e){_.error(`Failed to load server modules`,i(o,e)),R=!1,K=null}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,_.info(`Shutdown signal received`,{signal:e}),z?.stop(),B?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await U?.closeAll().catch(()=>void 0),G&&B?.onSessionEnd(G),W&&(await W.close().catch(()=>void 0),W=null,G=null),X.close(),V&&await V.close(),await K?.().catch(()=>void 0),process.exit(0))};process.on(`SIGINT`,()=>Q(`SIGINT`)),process.on(`SIGTERM`,()=>Q(`SIGTERM`))}export{v as startHttpMode};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./workspace-bootstrap-BPWA6BVf.js";import{n as t,t as n}from"./startup-maintenance-D0Uhpi3k.js";import{createLogger as r,serializeError as i,setDetailedErrorLoggingEnabled as a}from"../../core/dist/index.js";const o=r(`server`);async function s(r){let[{loadConfig:s,reconfigureForWorkspace:c,resolveIndexMode:l},{createLazyServer:u},{checkForUpdates:d,autoUpgradeScaffold:f},{RootsListChangedNotificationSchema:p}]=await Promise.all([import(`./config-B-wvmMyo.js`),import(`./server-D6sJEw0I.js`),import(`./version-check-CggUKvv8.js`),import(`@modelcontextprotocol/sdk/types.js`)]),m=s();a(m.logging?.errorDetails===!0),m.configError&&o.warn(`Config load failure`,{error:m.configError}),o.info(`Config loaded`,{sourceCount:m.sources.length,storePath:m.store.path}),f(),setInterval(d,1440*60*1e3).unref();let h=l(m),g=u(m,h),{server:_,startInit:v,ready:y,runInitialIndex:b}=g,{StdioServerTransport:x}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),S=new x;await _.connect(S),o.debug(`MCP server started`,{transport:`stdio`}),await e({config:m,indexMode:h,log:o,rootsChangedNotificationSchema:p,reconfigureForWorkspace:c,runInitialIndex:b,server:_,startInit:v,version:r});let C=null,w=null,T=!1,E=async e=>{T||(T=!0,o.info(`Shutdown signal received`,{signal:e}),C&&=(clearTimeout(C),null),w?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await S.close().catch(()=>void 0),await _.close().catch(()=>void 0),g.aikit&&await Promise.all([g.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),g.aikit.graphStore.close().catch(()=>{}),g.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),g.aikit.store.close().catch(()=>{})]),process.exit(0))},D=()=>{C&&clearTimeout(C),C=setTimeout(async()=>{o.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=g.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch(e){o.warn(`Resource release failed during shutdown`,i(e))}},18e5),C.unref&&C.unref()};D(),process.stdin.on(`data`,()=>D()),process.stdin.on(`end`,()=>void E(`stdin-end`)),process.stdin.on(`close`,()=>void E(`stdin-close`)),process.stdin.on(`error`,()=>void E(`stdin-error`)),process.on(`SIGINT`,()=>void E(`SIGINT`)),process.on(`SIGTERM`,()=>void E(`SIGTERM`)),y.catch(e=>{o.error(`Initialization failed — server will continue with limited tools`,t(r,e))}),h===`smart`?y.then(async()=>{try{if(!g.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(g.aikit.indexer,m,g.aikit.store);w=t;let n=g.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),g.setSmartScheduler(t),o.debug(`Smart index scheduler started (stdio mode)`)}catch(e){o.error(`Failed to start smart index scheduler`,t(r,e))}}).catch(e=>o.error(`AI Kit init failed for smart scheduler`,t(r,e))):o.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:h}),n(y,()=>g.aikit?{curated:g.aikit.curated,stateStore:g.aikit.stateStore}:null,r)}export{s as startStdioMode};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{r as e}from"./bin.js";import{n as t,t as n}from"./startup-maintenance-L9NUOBVy.js";import{createLogger as r,serializeError as i,setDetailedErrorLoggingEnabled as a}from"../../core/dist/index.js";const o=r(`server`);async function s(r){let[{loadConfig:s,reconfigureForWorkspace:c,resolveIndexMode:l},{createLazyServer:u},{checkForUpdates:d,autoUpgradeScaffold:f},{RootsListChangedNotificationSchema:p}]=await Promise.all([import(`./config-Bx85fwRX.js`),import(`./server-BSvqfFcK.js`),import(`./version-check-CdBHTxtt.js`),import(`@modelcontextprotocol/sdk/types.js`)]),m=s();a(m.logging?.errorDetails===!0),m.configError&&o.warn(`Config load failure`,{error:m.configError}),o.info(`Config loaded`,{sourceCount:m.sources.length,storePath:m.store.path}),f(),setInterval(d,1440*60*1e3).unref();let h=l(m),g=u(m,h),{server:_,startInit:v,ready:y,runInitialIndex:b}=g,{StdioServerTransport:x}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),S=new x;await _.connect(S),o.debug(`MCP server started`,{transport:`stdio`}),await e({config:m,indexMode:h,log:o,rootsChangedNotificationSchema:p,reconfigureForWorkspace:c,runInitialIndex:b,server:_,startInit:v,version:r});let C=null,w=null,T=!1,E=async e=>{T||(T=!0,o.info(`Shutdown signal received`,{signal:e}),C&&=(clearTimeout(C),null),w?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await S.close().catch(()=>void 0),await _.close().catch(()=>void 0),g.aikit&&await Promise.all([g.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),g.aikit.graphStore.close().catch(()=>{}),g.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),g.aikit.store.close().catch(()=>{})]),process.exit(0))},D=()=>{C&&clearTimeout(C),C=setTimeout(async()=>{o.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=g.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch(e){o.warn(`Resource release failed during shutdown`,i(e))}},18e5),C.unref&&C.unref()};D(),process.stdin.on(`data`,()=>D()),process.stdin.on(`end`,()=>void E(`stdin-end`)),process.stdin.on(`close`,()=>void E(`stdin-close`)),process.stdin.on(`error`,()=>void E(`stdin-error`)),process.on(`SIGINT`,()=>void E(`SIGINT`)),process.on(`SIGTERM`,()=>void E(`SIGTERM`)),y.catch(e=>{o.error(`Initialization failed — server will continue with limited tools`,t(r,e))}),h===`smart`?y.then(async()=>{try{if(!g.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(g.aikit.indexer,m,g.aikit.store);w=t;let n=g.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),g.setSmartScheduler(t),o.debug(`Smart index scheduler started (stdio mode)`)}catch(e){o.error(`Failed to start smart index scheduler`,t(r,e))}}).catch(e=>o.error(`AI Kit init failed for smart scheduler`,t(r,e))):o.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:h}),n(y,()=>g.aikit?{curated:g.aikit.curated,stateStore:g.aikit.stateStore}:null,r)}export{s as startStdioMode};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{fileURLToPath as e}from"node:url";import{createLogger as t}from"../../core/dist/index.js";import{existsSync as n,mkdirSync as r,readFileSync as i,renameSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,resolve as u}from"node:path";import{homedir as d}from"node:os";import{execFile as f,execSync as p}from"node:child_process";const m=`@vpxa/aikit`,h=`https://registry.npmjs.org/${m}/latest`,g=t(`server`),_=l(d(),`.aikit`),v=l(_,`current-version.json`),y=l(_,`versions`),b=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/;function x(e){if(!b.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}function S(){let t=u(c(e(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(i(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function C(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function w(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}async function T(e){x(e);let t=`v${e}`,i=l(y,`${t}-staging`),c=l(y,t);try{n(i)&&o(i,{recursive:!0,force:!0}),r(i,{recursive:!0}),p(`tar -xzf "${p(`npm pack ${m}@${e}`,{cwd:i,encoding:`utf-8`,timeout:6e4,windowsHide:!0}).trim()}"`,{cwd:i,encoding:`utf-8`,timeout:3e4,windowsHide:!0});let u=l(i,`package`);p(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:u,encoding:`utf-8`,timeout:12e4,windowsHide:!0});let d=l(u,`packages`,`server`,`dist`,`bin.js`);if(!n(d))throw Error(`Server entry not found at ${d}`);if(!n(l(u,`node_modules`)))throw Error(`node_modules not found — npm install may have failed`);let f=`${v}.tmp`;s(f,JSON.stringify({version:e,installedAt:new Date().toISOString()},null,2)),a(f,v),n(c)&&o(c,{recursive:!0,force:!0}),a(u,c),g.info(`Installed version ${t}`,{targetDir:c})}finally{n(i)&&o(i,{recursive:!0,force:!0})}}async function E(){try{let e=i(v,`utf-8`),{version:t}=JSON.parse(e),r=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!r.ok)return;let o=(await r.json()).version;if(!o||o===t||!w(o,t))return;if(n(l(y,`v${o}`))){let e=`${v}.tmp`;s(e,JSON.stringify({version:o,installedAt:new Date().toISOString()},null,2)),a(e,v),g.info(`Re-activated existing version v${o} — no download needed`);return}g.info(`New version available: ${o}. Installing...`),await T(o),g.info(`Updated to v${o}. Restart to use.`)}catch(e){g.error(`Background update check failed: ${e instanceof Error?e.message:String(e)}`)}}function D(){if(n(v)){E();return}let e=S();fetch(h,{signal:AbortSignal.timeout(1e4)})
|
|
2
|
+
import{fileURLToPath as e}from"node:url";import{createLogger as t}from"../../core/dist/index.js";import{existsSync as n,mkdirSync as r,readFileSync as i,renameSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,resolve as u}from"node:path";import{homedir as d}from"node:os";import{execFile as f,execSync as p}from"node:child_process";const m=`@vpxa/aikit`,h=`https://registry.npmjs.org/${m}/latest`,g=t(`server`),_=l(d(),`.aikit`),v=l(_,`current-version.json`),y=l(_,`versions`),b=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/;function x(e){if(!b.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}function S(){let t=u(c(e(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(i(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function C(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function w(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}async function T(e){x(e);let t=`v${e}`,i=l(y,`${t}-staging`),c=l(y,t);try{n(i)&&o(i,{recursive:!0,force:!0}),r(i,{recursive:!0}),p(`tar -xzf "${p(`npm pack ${m}@${e}`,{cwd:i,encoding:`utf-8`,timeout:6e4,windowsHide:!0}).trim()}"`,{cwd:i,encoding:`utf-8`,timeout:3e4,windowsHide:!0});let u=l(i,`package`);p(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:u,encoding:`utf-8`,timeout:12e4,windowsHide:!0});let d=l(u,`packages`,`server`,`dist`,`bin.js`);if(!n(d))throw Error(`Server entry not found at ${d}`);if(!n(l(u,`node_modules`)))throw Error(`node_modules not found — npm install may have failed`);let f=`${v}.tmp`;s(f,JSON.stringify({version:e,installedAt:new Date().toISOString()},null,2)),a(f,v),n(c)&&o(c,{recursive:!0,force:!0}),a(u,c),g.info(`Installed version ${t}`,{targetDir:c})}finally{n(i)&&o(i,{recursive:!0,force:!0})}}async function E(){try{let e=i(v,`utf-8`),{version:t}=JSON.parse(e),r=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!r.ok)return;let o=(await r.json()).version;if(!o||o===t||!w(o,t))return;if(n(l(y,`v${o}`))){let e=`${v}.tmp`;s(e,JSON.stringify({version:o,installedAt:new Date().toISOString()},null,2)),a(e,v),g.info(`Re-activated existing version v${o} — no download needed`);return}g.info(`New version available: ${o}. Installing...`),await T(o),g.info(`Updated to v${o}. Restart to use.`)}catch(e){g.error(`Background update check failed: ${e instanceof Error?e.message:String(e)}`)}}let D=null;function O(){return D||(D=k().finally(()=>{D=null}),D)}async function k(){if(n(v)){await E();return}let e=S();try{let t=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!t.ok)return;let n=(await t.json()).version;if(!n)return;if(C(e,n)<0){g.info(`Newer version available — installing`,{currentVersion:e,latestVersion:n});try{await T(n),g.info(`Installed v${n}. Restart MCP to use.`)}catch(e){g.warn(`Auto-install failed`,{error:e instanceof Error?e.message:String(e),latestVersion:n})}}}catch{}}function A(){try{let e=u(d(),`.copilot`,`.aikit-scaffold.json`);return n(e)?JSON.parse(i(e,`utf-8`)).version??null:null}catch{return null}}function j(){try{let e=u(process.cwd(),`.github`,`.aikit-scaffold.json`);return n(e)?JSON.parse(i(e,`utf-8`)).version??null:null}catch{return null}}let M=`idle`,N=null,P=null;function F(){return{state:M,error:N}}function I(){M=`idle`,N=null}function L(){try{let t=S(),r=A(),i=j(),a=r!=null&&r!==t,o=i!=null&&i!==t;if(O(),!a&&!o||(P!==t&&(I(),P=t),M!==`idle`))return;M=`pending`,N=null,g.info(`Scaffold version mismatch — auto-upgrading`,{serverVersion:t,userScaffoldVersion:r,workspaceScaffoldVersion:i});let s=c(e(import.meta.url)),l=[u(s,`..`,`..`,`..`,`bin`,`aikit.mjs`),u(s,`..`,`bin`,`aikit.mjs`),...process.argv[1]?[u(c(process.argv[1]),`aikit.mjs`)]:[]],d=l.find(e=>n(e));if(!d){M=`failed`,N=`aikit CLI binary not found. Tried: ${l.join(`, `)}`,g.warn(`Cannot auto-upgrade: aikit CLI binary not found`,{candidates:l,platform:process.platform});return}f(process.execPath,[d,`upgrade`],{timeout:3e4,windowsHide:!0},(e,n,r)=>{e?(M=`failed`,N=e.message,g.warn(`Auto-upgrade failed`,{error:e.message,stderr:r?.slice(0,500),binPath:d,platform:process.platform})):(M=`success`,N=null,g.info(`Auto-upgrade completed to version ${t}`))}).unref()}catch(e){M=`failed`,N=e instanceof Error?e.message:String(e),g.warn(`Auto-upgrade check failed`,{error:N})}}export{L as autoUpgradeScaffold,O as checkForUpdates,S as getCurrentVersion,F as getUpgradeState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fileURLToPath as e}from"node:url";import{createLogger as t}from"../../core/dist/index.js";import{existsSync as n,mkdirSync as r,readFileSync as i,renameSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,resolve as u}from"node:path";import{execFile as d,execSync as f}from"node:child_process";import{homedir as p}from"node:os";const m=`@vpxa/aikit`,h=`https://registry.npmjs.org/${m}/latest`,g=t(`server`),_=l(p(),`.aikit`),v=l(_,`current-version.json`),y=l(_,`versions`),b=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/;function x(e){if(!b.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}function S(){let t=u(c(e(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(i(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function C(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function w(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}async function T(e){x(e);let t=`v${e}`,i=l(y,`${t}-staging`),c=l(y,t);try{n(i)&&o(i,{recursive:!0,force:!0}),r(i,{recursive:!0}),f(`tar -xzf "${f(`npm pack ${m}@${e}`,{cwd:i,encoding:`utf-8`,timeout:6e4,windowsHide:!0}).trim()}"`,{cwd:i,encoding:`utf-8`,timeout:3e4,windowsHide:!0});let u=l(i,`package`);f(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:u,encoding:`utf-8`,timeout:12e4,windowsHide:!0});let d=l(u,`packages`,`server`,`dist`,`bin.js`);if(!n(d))throw Error(`Server entry not found at ${d}`);if(!n(l(u,`node_modules`)))throw Error(`node_modules not found — npm install may have failed`);let p=`${v}.tmp`;s(p,JSON.stringify({version:e,installedAt:new Date().toISOString()},null,2)),a(p,v),n(c)&&o(c,{recursive:!0,force:!0}),a(u,c),g.info(`Installed version ${t}`,{targetDir:c})}finally{n(i)&&o(i,{recursive:!0,force:!0})}}async function E(){try{let e=i(v,`utf-8`),{version:t}=JSON.parse(e),r=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!r.ok)return;let o=(await r.json()).version;if(!o||o===t||!w(o,t))return;if(n(l(y,`v${o}`))){let e=`${v}.tmp`;s(e,JSON.stringify({version:o,installedAt:new Date().toISOString()},null,2)),a(e,v),g.info(`Re-activated existing version v${o} — no download needed`);return}g.info(`New version available: ${o}. Installing...`),await T(o),g.info(`Updated to v${o}. Restart to use.`)}catch(e){g.error(`Background update check failed: ${e instanceof Error?e.message:String(e)}`)}}function D(){if(n(v)){E();return}let e=S();fetch(h,{signal:AbortSignal.timeout(1e4)})
|
|
1
|
+
import{fileURLToPath as e}from"node:url";import{createLogger as t}from"../../core/dist/index.js";import{existsSync as n,mkdirSync as r,readFileSync as i,renameSync as a,rmSync as o,writeFileSync as s}from"node:fs";import{dirname as c,join as l,resolve as u}from"node:path";import{execFile as d,execSync as f}from"node:child_process";import{homedir as p}from"node:os";const m=`@vpxa/aikit`,h=`https://registry.npmjs.org/${m}/latest`,g=t(`server`),_=l(p(),`.aikit`),v=l(_,`current-version.json`),y=l(_,`versions`),b=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/;function x(e){if(!b.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}function S(){let t=u(c(e(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(i(t,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function C(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function w(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}async function T(e){x(e);let t=`v${e}`,i=l(y,`${t}-staging`),c=l(y,t);try{n(i)&&o(i,{recursive:!0,force:!0}),r(i,{recursive:!0}),f(`tar -xzf "${f(`npm pack ${m}@${e}`,{cwd:i,encoding:`utf-8`,timeout:6e4,windowsHide:!0}).trim()}"`,{cwd:i,encoding:`utf-8`,timeout:3e4,windowsHide:!0});let u=l(i,`package`);f(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:u,encoding:`utf-8`,timeout:12e4,windowsHide:!0});let d=l(u,`packages`,`server`,`dist`,`bin.js`);if(!n(d))throw Error(`Server entry not found at ${d}`);if(!n(l(u,`node_modules`)))throw Error(`node_modules not found — npm install may have failed`);let p=`${v}.tmp`;s(p,JSON.stringify({version:e,installedAt:new Date().toISOString()},null,2)),a(p,v),n(c)&&o(c,{recursive:!0,force:!0}),a(u,c),g.info(`Installed version ${t}`,{targetDir:c})}finally{n(i)&&o(i,{recursive:!0,force:!0})}}async function E(){try{let e=i(v,`utf-8`),{version:t}=JSON.parse(e),r=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!r.ok)return;let o=(await r.json()).version;if(!o||o===t||!w(o,t))return;if(n(l(y,`v${o}`))){let e=`${v}.tmp`;s(e,JSON.stringify({version:o,installedAt:new Date().toISOString()},null,2)),a(e,v),g.info(`Re-activated existing version v${o} — no download needed`);return}g.info(`New version available: ${o}. Installing...`),await T(o),g.info(`Updated to v${o}. Restart to use.`)}catch(e){g.error(`Background update check failed: ${e instanceof Error?e.message:String(e)}`)}}let D=null;function O(){return D||(D=k().finally(()=>{D=null}),D)}async function k(){if(n(v)){await E();return}let e=S();try{let t=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!t.ok)return;let n=(await t.json()).version;if(!n)return;if(C(e,n)<0){g.info(`Newer version available — installing`,{currentVersion:e,latestVersion:n});try{await T(n),g.info(`Installed v${n}. Restart MCP to use.`)}catch(e){g.warn(`Auto-install failed`,{error:e instanceof Error?e.message:String(e),latestVersion:n})}}}catch{}}function A(){try{let e=u(p(),`.copilot`,`.aikit-scaffold.json`);return n(e)?JSON.parse(i(e,`utf-8`)).version??null:null}catch{return null}}function j(){try{let e=u(process.cwd(),`.github`,`.aikit-scaffold.json`);return n(e)?JSON.parse(i(e,`utf-8`)).version??null:null}catch{return null}}let M=`idle`,N=null,P=null;function F(){return{state:M,error:N}}function I(){M=`idle`,N=null}function L(){try{let t=S(),r=A(),i=j(),a=r!=null&&r!==t,o=i!=null&&i!==t;if(O(),!a&&!o||(P!==t&&(I(),P=t),M!==`idle`))return;M=`pending`,N=null,g.info(`Scaffold version mismatch — auto-upgrading`,{serverVersion:t,userScaffoldVersion:r,workspaceScaffoldVersion:i});let s=c(e(import.meta.url)),l=[u(s,`..`,`..`,`..`,`bin`,`aikit.mjs`),u(s,`..`,`bin`,`aikit.mjs`),...process.argv[1]?[u(c(process.argv[1]),`aikit.mjs`)]:[]],f=l.find(e=>n(e));if(!f){M=`failed`,N=`aikit CLI binary not found. Tried: ${l.join(`, `)}`,g.warn(`Cannot auto-upgrade: aikit CLI binary not found`,{candidates:l,platform:process.platform});return}d(process.execPath,[f,`upgrade`],{timeout:3e4,windowsHide:!0},(e,n,r)=>{e?(M=`failed`,N=e.message,g.warn(`Auto-upgrade failed`,{error:e.message,stderr:r?.slice(0,500),binPath:f,platform:process.platform})):(M=`success`,N=null,g.info(`Auto-upgrade completed to version ${t}`))}).unref()}catch(e){M=`failed`,N=e instanceof Error?e.message:String(e),g.warn(`Auto-upgrade check failed`,{error:N})}}export{L as autoUpgradeScaffold,O as checkForUpdates,S as getCurrentVersion,F as getUpgradeState};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EXEC_HOOKS as e,HOOK_EVENTS as t,HOOK_TOOL_MATCHERS as n,SUPPORTED_PLATFORMS as r}from"../definitions/exec-hooks.mjs";const i={PreCompact:3e3,PostToolUse:3e3},a={copilot:`hooks.json`,claude:`hooks-settings.json`,copilotCli:`hooks.json`,hermes:`hooks.json`},o=r;function s(e){if(!o.includes(e))throw Error(`Unknown platform: "${e}". Supported: ${o.join(`, `)}. Add it to SUPPORTED_PLATFORMS in exec-hooks.mjs first, then add entries to HOOK_EVENTS, HOOK_TOOL_MATCHERS, and FILE_NAMES.`);for(let[n,r]of Object.entries(t))if(!(e in r))throw Error(`Platform "${e}" is missing from HOOK_EVENTS.${n}. Add a "${e}" key to HOOK_EVENTS.${n} in exec-hooks.mjs.`);for(let[t,r]of Object.entries(n))if(!(e in r))throw Error(`Platform "${e}" is missing from HOOK_TOOL_MATCHERS.${t}. Add a "${e}" key to HOOK_TOOL_MATCHERS.${t} in exec-hooks.mjs.`);if(!(e in a))throw Error(`Platform "${e}" is missing from FILE_NAMES. Add "${e}: '<filename>'" to FILE_NAMES in adapters/hooks.mjs.`)}function c(e,t){return(e.matcher||[]).flatMap(e=>{let r=n[e];if(!r)throw Error(`Unknown hook matcher: ${e}`);return r[t]||[]})}function l(e,t,n,r){let a=`${n}/${e.script}`;return c(e,r),r===`copilot`?{event:t,steps:[{type:`command`,command:`node`,args:[a],timeout:i[e.event]||5e3}]}:r===`claude`?{type:`command`,command:`node ${a}`}:{command:`node`,args:[a]}}function u(n,r){if(s(n),n===`copilot`){let i=Object.values(e).
|
|
1
|
+
import{EXEC_HOOKS as e,HOOK_EVENTS as t,HOOK_TOOL_MATCHERS as n,SUPPORTED_PLATFORMS as r}from"../definitions/exec-hooks.mjs";const i={PreCompact:3e3,PostToolUse:3e3},a={copilot:`hooks.json`,claude:`hooks-settings.json`,copilotCli:`hooks.json`,hermes:`hooks.json`},o=r;function s(e){if(!o.includes(e))throw Error(`Unknown platform: "${e}". Supported: ${o.join(`, `)}. Add it to SUPPORTED_PLATFORMS in exec-hooks.mjs first, then add entries to HOOK_EVENTS, HOOK_TOOL_MATCHERS, and FILE_NAMES.`);for(let[n,r]of Object.entries(t))if(!(e in r))throw Error(`Platform "${e}" is missing from HOOK_EVENTS.${n}. Add a "${e}" key to HOOK_EVENTS.${n} in exec-hooks.mjs.`);for(let[t,r]of Object.entries(n))if(!(e in r))throw Error(`Platform "${e}" is missing from HOOK_TOOL_MATCHERS.${t}. Add a "${e}" key to HOOK_TOOL_MATCHERS.${t} in exec-hooks.mjs.`);if(!(e in a))throw Error(`Platform "${e}" is missing from FILE_NAMES. Add "${e}: '<filename>'" to FILE_NAMES in adapters/hooks.mjs.`)}function c(e,t){return(e.matcher||[]).flatMap(e=>{let r=n[e];if(!r)throw Error(`Unknown hook matcher: ${e}`);return r[t]||[]})}function l(e,t,n,r){let a=`${n}/${e.script}`;return c(e,r),r===`copilot`?{event:t,steps:[{type:`command`,command:`node`,args:[a],timeout:i[e.event]||5e3}]}:r===`claude`?{type:`command`,command:`node ${a}`}:{command:`node`,args:[a]}}function u(n,r){if(s(n),n===`copilot`){let i=Object.values(e).flatMap(e=>{let i=t[e.event]?.[n];return i?l(e,i,r,n):(console.warn(`[aikit] Unsupported hook event ${e.event} for ${n} — skipping`),[])});return[{path:a[n],content:JSON.stringify({hooks:i},null,2)}]}let i={};for(let a of Object.values(e)){let e=t[a.event]?.[n];if(!e){console.warn(`[aikit] Unsupported hook event ${a.event} for ${n} — skipping`);continue}i[e]||=[],i[e].push(l(a,e,r,n))}return[{path:a[n],content:JSON.stringify({hooks:i},null,2)}]}function d(){return[`_runtime.mjs`,...Object.values(e).map(e=>e.script)]}export{u as generateHooks,d as getHookScriptFiles};
|
|
@@ -26,4 +26,4 @@ ${e(a)}
|
|
|
26
26
|
${o}
|
|
27
27
|
${s}`}}const i={Orchestrator:{title:`The Master Conductor`,description:`Master conductor that orchestrates the full development lifecycle: Planning → Implementation → Review → Recovery → Commit`,argumentHint:null,toolRole:`orchestrator`,sharedBase:null,sharedProtocols:[`conversation-compression`,`decision-protocol`,`forge-protocol`,`thinking-principles`],category:`orchestration`,skills:[[`aikit`,`**Always** — AI Kit recall, flow status, search, and ctx ref reuse`]]},Planner:{title:`The Strategic Architect`,description:`Autonomous planner that researches codebases and writes comprehensive TDD implementation plans`,compactRole:`TDD implementation plans`,argumentHint:null,toolRole:`planner`,sharedBase:`code-agent-base`,sharedProtocols:[`thinking-principles`,`planning-principles`],category:`orchestration`,skills:[[`aikit`,`**Always** — AI Kit reading plans, recall, and compressed context reuse`]]},Implementer:{title:`The Code Builder`,description:`Persistent implementation agent that writes code following TDD practices until all tasks are complete`,compactRole:`New features, wire up, build`,argumentHint:`Implementation task, feature, or phase from plan`,toolRole:`codeAgent`,sharedBase:`code-agent-base`,sharedProtocols:[`engineering-principles`],category:`implementation`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When writing TypeScript code — type patterns, generics, utility types`]]},Frontend:{title:`The UI Specialist`,description:`UI/UX specialist for React, styling, responsive design, and frontend implementation`,compactRole:`UI/UX, React, styling, responsive`,argumentHint:`UI component, styling task, or frontend feature`,toolRole:`codeAgent`,sharedBase:`code-agent-base`,sharedProtocols:[`engineering-principles`],category:`implementation`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`react`,`When building React components — hooks, patterns, Server Components`],[`typescript`,`When writing TypeScript code — type patterns, generics, utility types`],[`frontend-design`,`When implementing UI/UX — design systems, accessibility, responsive patterns`]]},Refactor:{title:`The Code Sculptor`,description:`Code refactoring specialist that improves structure, readability, and maintainability`,compactRole:`Cleanup, simplify, DRY, extract`,argumentHint:`Code, component, or pattern to refactor`,toolRole:`refactor`,sharedBase:`code-agent-base`,sharedProtocols:[`engineering-principles`],category:`implementation`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`]]},Debugger:{title:`The Problem Solver`,description:`Expert debugger that diagnoses issues, traces errors, and provides solutions using AI Kit traces and compressed context before raw file reads`,compactRole:`Bug diagnosis, error tracing`,argumentHint:`Error message, stack trace, or description of issue`,toolRole:`debugger`,sharedBase:`code-agent-base`,sharedProtocols:[`engineering-principles`],category:`diagnostics`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When writing TypeScript code — type patterns, generics, utility types`]]},Security:{title:`The Vulnerability Hunter`,description:`Security specialist that analyzes code for vulnerabilities and compliance`,compactRole:`Vulnerability analysis, auth hardening`,argumentHint:`Code, feature, or component to security review`,toolRole:`security`,sharedBase:`code-agent-base`,sharedProtocols:[`engineering-principles`],category:`diagnostics`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When reviewing code — security patterns, type safety`]]},Documenter:{title:`The Knowledge Keeper`,description:`Documentation specialist that creates and maintains comprehensive project documentation`,compactRole:`Project documentation`,argumentHint:`Component, API, feature, or area to document`,toolRole:`documenter`,sharedBase:`code-agent-base`,sharedProtocols:[`thinking-principles`,`documentation-principles`],category:`documentation`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`present`,`When presenting documentation previews or architecture visuals to the user`],[`docs`,`When creating or updating project documentation — docs/ convention, architecture blueprints, Diátaxis framework`]]},Explorer:{title:`The Rapid Scout`,description:`Rapid codebase exploration to find files, usages, dependencies, and structural context`,compactRole:`Rapid codebase navigation`,argumentHint:`Find files, usages, and context related to: {topic or goal}`,toolRole:`explorer`,sharedBase:null,sharedProtocols:[`thinking-principles`],category:`exploration`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`]]},Researcher:{title:`The Context Gatherer`,description:`Deep analysis, architecture review, and multi-model decision protocol participant`,compactRole:`Multi-model deep research`,argumentHint:`Research question, problem statement, or subsystem to investigate`,toolRole:`researcher`,sharedBase:`researcher-base`,sharedProtocols:[`thinking-principles`],category:`research`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`lesson-learned`,`When analyzing past changes to extract engineering principles`],[`c4-architecture`,`When researching system architecture — produce C4 diagrams`],[`adr-skill`,`When the research involves a technical decision — draft an ADR`]],variants:{Alpha:n({description:`Primary deep research agent — also serves as default Researcher`,lensName:`Contrarian`,lensDescription:`deep research`,lensPrompt:`actively look for flaws, fatal assumptions, and hidden risks in every approach. The best ideas survive adversarial pressure.`,identityIntro:`, the primary deep research agent. During multi-model decision sessions, you provide deep reasoning and nuanced system design.`,requiredOutputSection:`Depth Analysis`,requiredOutputItems:[`Deep-dive into ONE chosen subsystem (most structurally central to the question)`,`Full evidence chain: file:line citations for every structural claim`,"At least 2 `compact`/`file_summary` extracts woven into the narrative"],focusAreas:[`For every proposed approach, actively seek the fatal flaw or hidden assumption`,`Ask: "Under what conditions does this approach fail catastrophically?"`,`Prefer uncomfortable truths over comfortable consensus`],variantSummary:`You are the DEFAULT researcher. When the Orchestrator needs breadth + depth, they
|
|
28
28
|
dispatch you alone. Your lens: thorough, evidence-first, exhaustive + contrarian.`}),Beta:n({description:`Research variant — pragmatic analysis with focus on trade-offs and edge cases`,lensName:`First Principles`,lensDescription:`pragmatic analysis`,lensPrompt:`strip away assumptions, decompose to ground truths, and rebuild reasoning from scratch.`,identityIntro:`, a variant of the Researcher agent optimized for **pragmatic analysis**. Focus on trade-offs, edge cases, and practical constraints. Challenge assumptions and highlight risks the primary researcher may overlook.`,requiredOutputSection:`Failure Modes & Counter-Evidence`,requiredOutputItems:[`At least 3 adversarial claims challenging your own primary finding`,`For each counter-claim: the condition under which it would be TRUE, and the
|
|
29
|
-
evidence (file:line or search receipt) that currently falsifies it`,"Any unresolved counter-evidence flagged as `⚠ UNRESOLVED`"],focusAreas:[`Strip every assumption: "Is this truly required, or just inherited convention?"`,`Decompose to ground truths, then rebuild the reasoning from scratch`,`If the current approach exists only because "that's how it's always been done", flag it`],variantSummary:"Your lens: pragmatic skepticism + first principles. Mark competing claims as `A` (Assumed)\nby default; challenge before promoting to `V`."}),Gamma:n({description:`Research variant — broad pattern matching across domains and technologies`,lensName:`Expansionist`,lensDescription:`cross-domain pattern matching`,lensPrompt:`look for the bigger opportunity, find what's undervalued, and identify patterns others dismiss.`,identityIntro:`, a variant of the Researcher agent optimized for **cross-domain pattern matching**. Draw connections from other domains, frameworks, and industries. Bring breadth where Alpha brings depth.`,requiredOutputSection:`Cross-Domain Analogies`,requiredOutputItems:[`At least 2 patterns from other tools/frameworks/domains that apply to the question`,"For each: the external source (cite via `web_search` or `web_fetch` receipt) and\n how it maps to our codebase",`One "missing pattern we should adopt" recommendation`],focusAreas:[`Ask: "What's the bigger opportunity everyone else is ignoring?"`,`Seek undervalued approaches and non-obvious connections across domains`,`Challenge narrow framing: "Is this really just an X problem, or is it also a Y problem?"`],variantSummary:"Your lens: cross-domain pattern matching + expansionist. Weight `web_search` + `web_fetch`\nhigher than peers. Assume the LLM's training data is stale — verify with fresh searches."}),Delta:n({description:`Research variant — implementation feasibility and performance implications`,lensName:`Executor`,lensDescription:`implementation feasibility`,lensPrompt:`focus on what can actually be built, the fastest path to value, and real-world constraints.`,identityIntro:`, a variant of the Researcher agent optimized for **implementation feasibility**. Focus on performance implications, scaling concerns, and concrete implementation paths. Ground theoretical proposals in practical reality.`,requiredOutputSection:`Implementation Cost & Feasibility`,requiredOutputItems:["Complexity snapshot: you MUST call `measure({ path })` on any file ≥ 50 LOC in the\n target subsystem at least once and quote the `cognitiveComplexity` result","Blast radius estimate: `blast_radius({ changed_files })` on the proposed edits",`Time/risk table: | Change | Lines | Risk | Effort |`,`Feasibility verdict: SAFE / RISKY / INFEASIBLE with one-line justification`],focusAreas:[`Ask: "Can this actually be built? What's the fastest path to a working version?"`,`Ground every proposal in concrete effort: lines of code, files changed, risk`,`Reject elegant theory that can't survive contact with the codebase`],variantSummary:'Your lens: implementation feasibility + executor. Prefer `measure` + `blast_radius` +\n`analyze({ aspect: "patterns", ... })` over abstract reasoning.'})}},"Code-Reviewer":{title:`The Quality Guardian`,description:`Code review specialist analyzing code for quality, security, performance, and maintainability`,compactRole:`Dual-perspective code review`,argumentHint:`File path, PR, or code to review`,toolRole:`reviewer`,sharedBase:`code-reviewer-base`,sharedProtocols:[`thinking-principles`,`review-principles`],category:`review`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When reviewing TypeScript code — type patterns, best practices`]],variants:{Alpha:r({roleName:`Code-Reviewer`,description:`Primary code reviewer`,lensName:`Compliance & Red-Team`,lensDescription:`compliance and red-teaming`,lensPrompt:`you hunt for correctness bugs, security holes, and contract violations that will break in production.`,identityIntro:`, the primary Code-Reviewer agent.`,focusAreas:[`**Correctness** — Logic errors, race conditions, null/undefined paths, off-by-one`,`**Security** — OWASP Top 10, input validation, secrets, injection vectors`,`**Contract compliance** — Does this honor its type signatures, API contracts, and invariants?`,`**Error handling** — What happens on the unhappy path? Missing try/catch, swallowed errors`],instinct:`Your instinct: "How does this break?" Think like an attacker and a pessimist.`,closing:`When in doubt, flag it — false positives are cheaper than missed bugs in production.`}),Beta:r({roleName:`Code-Reviewer`,description:`Code reviewer variant — different LLM perspective for dual review`,lensName:`Quality & Engineering Excellence`,lensDescription:`quality and engineering excellence`,lensPrompt:`you focus on maintainability, performance, testing, and whether the code will age well.`,identityIntro:`, the secondary Code-Reviewer agent.`,focusAreas:[`**Maintainability** — Naming clarity, single responsibility, cognitive complexity, DRY`,`**Performance** — N+1 queries, unnecessary allocations, missing caching, O(n²) where O(n) suffices`,`**Testing** — Coverage for new/changed logic, edge cases, test readability`,`**Patterns** — Consistency with existing codebase conventions, idiomatic usage`],instinct:`Your instinct: "Will a new team member understand this in 6 months?" Think like a mentor.`,closing:`Prefer actionable suggestions over vague concerns. Show the better version when possible.`})}},"Architect-Reviewer":{title:`The Structural Guardian`,description:`Reviews architecture for pattern adherence, SOLID compliance, dependency direction, and structural integrity`,compactRole:`Architecture review`,argumentHint:`Files, PR, or subsystem to architecture-review`,toolRole:`reviewer`,sharedBase:`architect-reviewer-base`,sharedProtocols:[`thinking-principles`,`review-principles`],category:`review`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`c4-architecture`,`When reviewing architectural diagrams or boundary changes`],[`adr-skill`,`When the review involves architecture decisions — reference or create ADRs`]],extraBody:`You are **not** the Code-Reviewer agent. Code-Reviewer handles correctness, testing, security, and code quality. You handle the big picture: service boundaries, dependency direction, pattern adherence, and structural health.`,variants:{Alpha:r({roleName:`Architect-Reviewer`,description:`Primary architecture reviewer`,lensName:`Structural Prosecutor`,lensDescription:`structural prosecution`,lensPrompt:`you challenge architectural choices, find boundary violations, and test whether the design survives growth.`,identityIntro:`, the primary Architect-Reviewer agent.`,focusHeading:`Your primary focus areas:`,focusAreas:[`**Boundary violations** — Does this cross package/module boundaries it shouldn't?`,`**Dependency direction** — Are dependencies flowing inward? Any layer leakage?`,`**Hidden coupling** — Shared mutable state, implicit contracts, temporal coupling`,`**Scalability stress** — What breaks at 10x load, 10x data, 10x features?`],instinct:`Your instinct: "This design will fail when..." Challenge every architectural assumption.`,closing:`If a boundary is crossed, require justification or block.`}),Beta:r({roleName:`Architect-Reviewer`,description:`Architecture reviewer variant — different LLM perspective for dual review`,lensName:`Pragmatic Defense`,lensDescription:`pragmatic defense`,lensPrompt:`you evaluate whether the architecture is proportional to the problem, and defend reasonable trade-offs.`,identityIntro:`, the secondary Architect-Reviewer agent.`,focusHeading:`Your primary focus areas:`,focusAreas:[`**Proportionality** — Is the architecture proportional to the problem? Over-engineering is a defect.`,`**Trade-off validity** — Are the trade-offs explicitly acknowledged and reasonable?`,`**Migration path** — Can this evolve without a rewrite? Is there a clear upgrade path?`,`**Team ergonomics** — Can the team actually maintain this? Does it match their skills?`],instinct:`Your instinct: "Is this the simplest architecture that solves the actual problem?"`,closing:`Push back on unnecessary complexity. Defend working solutions against premature abstraction.`})}}};export{i as AGENTS};
|
|
29
|
+
evidence (file:line or search receipt) that currently falsifies it`,"Any unresolved counter-evidence flagged as `⚠ UNRESOLVED`"],focusAreas:[`Strip every assumption: "Is this truly required, or just inherited convention?"`,`Decompose to ground truths, then rebuild the reasoning from scratch`,`If the current approach exists only because "that's how it's always been done", flag it`],variantSummary:"Your lens: pragmatic skepticism + first principles. Mark competing claims as `A` (Assumed)\nby default; challenge before promoting to `V`."}),Gamma:n({description:`Research variant — broad pattern matching across domains and technologies`,lensName:`Expansionist`,lensDescription:`cross-domain pattern matching`,lensPrompt:`look for the bigger opportunity, find what's undervalued, and identify patterns others dismiss.`,identityIntro:`, a variant of the Researcher agent optimized for **cross-domain pattern matching**. Draw connections from other domains, frameworks, and industries. Bring breadth where Alpha brings depth.`,requiredOutputSection:`Cross-Domain Analogies`,requiredOutputItems:[`At least 2 patterns from other tools/frameworks/domains that apply to the question`,"For each: the external source (cite via `web_search` or `web_fetch` receipt) and\n how it maps to our codebase",`One "missing pattern we should adopt" recommendation`],focusAreas:[`Ask: "What's the bigger opportunity everyone else is ignoring?"`,`Seek undervalued approaches and non-obvious connections across domains`,`Challenge narrow framing: "Is this really just an X problem, or is it also a Y problem?"`],variantSummary:"Your lens: cross-domain pattern matching + expansionist. Weight `web_search` + `web_fetch`\nhigher than peers. Assume the LLM's training data is stale — verify with fresh searches."}),Delta:n({description:`Research variant — implementation feasibility and performance implications`,lensName:`Executor`,lensDescription:`implementation feasibility`,lensPrompt:`focus on what can actually be built, the fastest path to value, and real-world constraints.`,identityIntro:`, a variant of the Researcher agent optimized for **implementation feasibility**. Focus on performance implications, scaling concerns, and concrete implementation paths. Ground theoretical proposals in practical reality.`,requiredOutputSection:`Implementation Cost & Feasibility`,requiredOutputItems:["Complexity snapshot: you MUST call `measure({ path })` on any file ≥ 50 LOC in the\n target subsystem at least once and quote the `cognitiveComplexity` result","Blast radius estimate: `blast_radius({ changed_files })` on the proposed edits",`Time/risk table: | Change | Lines | Risk | Effort |`,`Feasibility verdict: SAFE / RISKY / INFEASIBLE with one-line justification`],focusAreas:[`Ask: "Can this actually be built? What's the fastest path to a working version?"`,`Ground every proposal in concrete effort: lines of code, files changed, risk`,`Reject elegant theory that can't survive contact with the codebase`],variantSummary:'Your lens: implementation feasibility + executor. Prefer `measure` + `blast_radius` +\n`analyze({ items: [{aspect: "patterns", ...}] })` over abstract reasoning.'})}},"Code-Reviewer":{title:`The Quality Guardian`,description:`Code review specialist analyzing code for quality, security, performance, and maintainability`,compactRole:`Dual-perspective code review`,argumentHint:`File path, PR, or code to review`,toolRole:`reviewer`,sharedBase:`code-reviewer-base`,sharedProtocols:[`thinking-principles`,`review-principles`],category:`review`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`typescript`,`When reviewing TypeScript code — type patterns, best practices`]],variants:{Alpha:r({roleName:`Code-Reviewer`,description:`Primary code reviewer`,lensName:`Compliance & Red-Team`,lensDescription:`compliance and red-teaming`,lensPrompt:`you hunt for correctness bugs, security holes, and contract violations that will break in production.`,identityIntro:`, the primary Code-Reviewer agent.`,focusAreas:[`**Correctness** — Logic errors, race conditions, null/undefined paths, off-by-one`,`**Security** — OWASP Top 10, input validation, secrets, injection vectors`,`**Contract compliance** — Does this honor its type signatures, API contracts, and invariants?`,`**Error handling** — What happens on the unhappy path? Missing try/catch, swallowed errors`],instinct:`Your instinct: "How does this break?" Think like an attacker and a pessimist.`,closing:`When in doubt, flag it — false positives are cheaper than missed bugs in production.`}),Beta:r({roleName:`Code-Reviewer`,description:`Code reviewer variant — different LLM perspective for dual review`,lensName:`Quality & Engineering Excellence`,lensDescription:`quality and engineering excellence`,lensPrompt:`you focus on maintainability, performance, testing, and whether the code will age well.`,identityIntro:`, the secondary Code-Reviewer agent.`,focusAreas:[`**Maintainability** — Naming clarity, single responsibility, cognitive complexity, DRY`,`**Performance** — N+1 queries, unnecessary allocations, missing caching, O(n²) where O(n) suffices`,`**Testing** — Coverage for new/changed logic, edge cases, test readability`,`**Patterns** — Consistency with existing codebase conventions, idiomatic usage`],instinct:`Your instinct: "Will a new team member understand this in 6 months?" Think like a mentor.`,closing:`Prefer actionable suggestions over vague concerns. Show the better version when possible.`})}},"Architect-Reviewer":{title:`The Structural Guardian`,description:`Reviews architecture for pattern adherence, SOLID compliance, dependency direction, and structural integrity`,compactRole:`Architecture review`,argumentHint:`Files, PR, or subsystem to architecture-review`,toolRole:`reviewer`,sharedBase:`architect-reviewer-base`,sharedProtocols:[`thinking-principles`,`review-principles`],category:`review`,skills:[[`aikit`,`**Always** — AI Kit tool signatures, search, analysis`],[`c4-architecture`,`When reviewing architectural diagrams or boundary changes`],[`adr-skill`,`When the review involves architecture decisions — reference or create ADRs`]],extraBody:`You are **not** the Code-Reviewer agent. Code-Reviewer handles correctness, testing, security, and code quality. You handle the big picture: service boundaries, dependency direction, pattern adherence, and structural health.`,variants:{Alpha:r({roleName:`Architect-Reviewer`,description:`Primary architecture reviewer`,lensName:`Structural Prosecutor`,lensDescription:`structural prosecution`,lensPrompt:`you challenge architectural choices, find boundary violations, and test whether the design survives growth.`,identityIntro:`, the primary Architect-Reviewer agent.`,focusHeading:`Your primary focus areas:`,focusAreas:[`**Boundary violations** — Does this cross package/module boundaries it shouldn't?`,`**Dependency direction** — Are dependencies flowing inward? Any layer leakage?`,`**Hidden coupling** — Shared mutable state, implicit contracts, temporal coupling`,`**Scalability stress** — What breaks at 10x load, 10x data, 10x features?`],instinct:`Your instinct: "This design will fail when..." Challenge every architectural assumption.`,closing:`If a boundary is crossed, require justification or block.`}),Beta:r({roleName:`Architect-Reviewer`,description:`Architecture reviewer variant — different LLM perspective for dual review`,lensName:`Pragmatic Defense`,lensDescription:`pragmatic defense`,lensPrompt:`you evaluate whether the architecture is proportional to the problem, and defend reasonable trade-offs.`,identityIntro:`, the secondary Architect-Reviewer agent.`,focusHeading:`Your primary focus areas:`,focusAreas:[`**Proportionality** — Is the architecture proportional to the problem? Over-engineering is a defect.`,`**Trade-off validity** — Are the trade-offs explicitly acknowledged and reasonable?`,`**Migration path** — Can this evolve without a rewrite? Is there a clear upgrade path?`,`**Team ergonomics** — Can the team actually maintain this? Does it match their skills?`],instinct:`Your instinct: "Is this the simplest architecture that solves the actual problem?"`,closing:`Push back on unnecessary complexity. Defend working solutions against premature abstraction.`})}}};export{i as AGENTS};
|
|
@@ -19,7 +19,7 @@ import{postTaskLesson as e,preTaskKnowledgeRecall as t}from"./protocols.mjs";con
|
|
|
19
19
|
> **HARD RULE:** FIRST ACTION in EVERY session MUST be \`status({})\`. No exceptions. It verifies tools, workspace, index. Skipping it causes blind work and degraded tool use.
|
|
20
20
|
|
|
21
21
|
1. \`status({})\` — onboard ❌ → \`onboard({ path: "." })\`, wait, note **Onboard Directory**
|
|
22
|
-
|
|
22
|
+
2. Read onboard artifacts: \`compact({ items: [{path: "<Onboard Dir>/synthesis-guide.md"}] })\`, \`structure.md\`, \`code-map.md\`
|
|
23
23
|
3. Read \`aikit\` skill and \`AGENTS.md\` (decision + FORGE protocols are inlined below)
|
|
24
24
|
4. Read \`multi-agents-development\` skill — **REQUIRED before delegation**
|
|
25
25
|
5. Read \`present\` skill — **REQUIRED before return Output**
|
|
@@ -158,7 +158,7 @@ import{postTaskLesson as e,preTaskKnowledgeRecall as t}from"./protocols.mjs";con
|
|
|
158
158
|
**Subagent prompt template:**
|
|
159
159
|
1. **Scope** — exact files + boundary
|
|
160
160
|
2. **Goal** — acceptance criteria, testable
|
|
161
|
-
|
|
161
|
+
3. **Arch Context** — pick by \`config.tokenBudget\`: efficient → \`stratum_card({ files: ['<path>'], query: '<what matters>', tier: 'T1' })\`, normal → \`compact({ items: [{path, query}] })\` or \`compact({ref, query?})\`, full → \`digest({ sources: [...], query: '<what matters>' })\`. Default to efficient.
|
|
162
162
|
4. **Constraints** — patterns, conventions
|
|
163
163
|
5. **Prior Knowledge** — Fetch topic-scoped knowledge: \`knowledge({ action: "lesson", subAction: "list-lessons", topic: "<2-3 task keywords>", minConfidence: 70 })\` + \`search({ query: "<task area>", category: "conventions", limit: 3 })\`. Include HIGH-confidence results (≥70) under \`## Prior Knowledge\`. Skip if none.
|
|
164
164
|
6. **Artifacts Path** — the active flow's run directory and artifacts path from \`flow({ action: 'status' })\` (e.g. \`.flows/add-authentication/.spec/\`)
|
|
@@ -197,7 +197,7 @@ import{postTaskLesson as e,preTaskKnowledgeRecall as t}from"./protocols.mjs";con
|
|
|
197
197
|
|
|
198
198
|
### Context Gathering for Subagent Prompts
|
|
199
199
|
|
|
200
|
-
Default to \`stratum_card({ files: ['<path>'], query: '<what matters>', tier: 'T1' })\`; upgrade to \`compact({ path, query })\`, \`compact({ ref, query? })\`, or \`digest\`; use \`read_file\` only for exact edit lines.
|
|
200
|
+
Default to \`stratum_card({ files: ['<path>'], query: '<what matters>', tier: 'T1' })\`; upgrade to \`compact({ items: [{path, query}] })\`, \`compact({ ref, query? })\`, or \`digest\`; use \`read_file\` only for exact edit lines.
|
|
201
201
|
|
|
202
202
|
**Knowledge injection (MANDATORY for Standard+ tier):** Before any subagent prompt, call:
|
|
203
203
|
- \`knowledge({ action: "lesson", subAction: "list-lessons", topic: "<task keywords>", minConfidence: 70 })\`
|
|
@@ -424,7 +424,7 @@ import{postTaskLesson as e,preTaskKnowledgeRecall as t}from"./protocols.mjs";con
|
|
|
424
424
|
## Pre-Edit Checklist
|
|
425
425
|
|
|
426
426
|
1. **Understand consumers** — \`graph({action:'find_nodes', name_pattern:'<target>'})\` → \`graph({action:'neighbors', node_id, direction:'incoming'})\`
|
|
427
|
-
2. **Compress, don't raw-read** — \`file_summary\` then \`compact({path, query})\` or \`compact({ref, query?})\`; \`read_file\` only for exact edit lines
|
|
427
|
+
2. **Compress, don't raw-read** — \`file_summary\` then \`compact({ items: [{path, query}] })\` or \`compact({ref, query?})\`; \`read_file\` only for exact edit lines
|
|
428
428
|
3. **Snapshot risky edits** — \`checkpoint({action:'save', label:'pre-<scope>'})\` before cross-cutting changes
|
|
429
429
|
4. **Estimate blast radius** — run \`blast_radius\` before and after shared/public symbol changes
|
|
430
430
|
5. **TDD when tests exist** — failing test first, then minimum code
|
|
@@ -711,7 +711,7 @@ After shared bootstrap, run \`search({ query: "security vulnerabilities conventi
|
|
|
711
711
|
## Documentation Protocol
|
|
712
712
|
|
|
713
713
|
1. **AI Kit Recall** — \`search({ query: "documentation <area>" })\` + \`knowledge({ action: "list" })\`
|
|
714
|
-
2. **Analyze** — \`analyze({ aspect: "structure", ... })\`, \`analyze({ aspect: "entry_points", ... })\`, \`file_summary\`
|
|
714
|
+
2. **Analyze** — \`analyze({ items: [{aspect: "structure", ...}] })\`, \`analyze({ items: [{aspect: "entry_points", ...}] })\`, \`file_summary\`
|
|
715
715
|
3. **Draft** — write docs following project conventions
|
|
716
716
|
4. **Cross-reference** — link related docs, keep consistency
|
|
717
717
|
5. **Persist** — \`knowledge({ action: "remember", title: "Docs: <standard>", content: "<details>", category: "conventions" })\` for new standards
|
|
@@ -806,7 +806,7 @@ When dispatched inside an active flow:
|
|
|
806
806
|
| Find files for a feature | \`find\`, \`scope_map\` |
|
|
807
807
|
| Map a symbol's usage | \`symbol\`, \`trace\` |
|
|
808
808
|
| Map module relationships | \`graph({ action: 'neighbors' })\` — import/export edges across packages |
|
|
809
|
-
| Understand a package | \`analyze({ aspect: "structure", ... })\`, \`analyze({ aspect: "dependencies", ... })\`, \`file_summary\` |
|
|
809
|
+
| Understand a package | \`analyze({ items: [{aspect: "structure", ...}] })\`, \`analyze({ items: [{aspect: "dependencies", ...}] })\`, \`file_summary\` |
|
|
810
810
|
| Check impact of a change | \`blast_radius\` |
|
|
811
811
|
|
|
812
812
|
## Output Format
|
|
@@ -103,11 +103,11 @@ If \`docs/\` doesn't exist, run the **Architecture Blueprint Workflow** from the
|
|
|
103
103
|
\`\`\`
|
|
104
104
|
# Step 1: Generate content with AI Kit tools
|
|
105
105
|
produce_knowledge({ scope: "." }) # → Foundation for docs/README.md
|
|
106
|
-
analyze({ aspect: "structure", path: "." }) # → docs/architecture/overview.md structure
|
|
107
|
-
analyze({ aspect: "diagram", path: "." }) # → docs/architecture/ Mermaid diagrams
|
|
108
|
-
analyze({ aspect: "dependencies", path: "." }) # → docs/architecture/overview.md deps section
|
|
109
|
-
analyze({ aspect: "entry_points", path: "." }) # → docs/reference/api.md foundation
|
|
110
|
-
analyze({ aspect: "patterns", path: "." }) # → docs/architecture/overview.md patterns
|
|
106
|
+
analyze({ items: [{aspect: "structure", path: "."}] }) # → docs/architecture/overview.md structure
|
|
107
|
+
analyze({ items: [{aspect: "diagram", path: "."}] }) # → docs/architecture/ Mermaid diagrams
|
|
108
|
+
analyze({ items: [{aspect: "dependencies", path: "."}] }) # → docs/architecture/overview.md deps section
|
|
109
|
+
analyze({ items: [{aspect: "entry_points", path: "."}] }) # → docs/reference/api.md foundation
|
|
110
|
+
analyze({ items: [{aspect: "patterns", path: "."}] }) # → docs/architecture/overview.md patterns
|
|
111
111
|
|
|
112
112
|
# Step 2: Create the docs/ tree from tool outputs
|
|
113
113
|
docs/
|
|
@@ -130,7 +130,7 @@ Use the \`docs\` skill Architecture Blueprint sections as the template.
|
|
|
130
130
|
When \`docs/\` already exists:
|
|
131
131
|
|
|
132
132
|
\`\`\`
|
|
133
|
-
compact({ path: "docs/architecture/overview.md", query: "section to update" }) # Read target section
|
|
133
|
+
compact({ items: [{path: "docs/architecture/overview.md", query: "section to update"}] }) # Read target section
|
|
134
134
|
blast_radius({ path: ".", files: ["<files>"] }) # What's affected
|
|
135
135
|
\`\`\`
|
|
136
136
|
|
|
@@ -234,12 +234,12 @@ This is NOT just documentation generation — it is a full **analyze → underst
|
|
|
234
234
|
Run all analysis tools in parallel to build a comprehensive baseline:
|
|
235
235
|
|
|
236
236
|
1. **Onboard** — \`onboard({ path: "." })\` if not already done (check \`status()\` first)
|
|
237
|
-
2. **Structure** — \`analyze({ aspect: "structure", path: "." })\`
|
|
238
|
-
3. **Dependencies** — \`analyze({ aspect: "dependencies", path: "." })\`
|
|
239
|
-
4. **Symbols** — \`analyze({ aspect: "symbols", path: "." })\`
|
|
240
|
-
5. **Patterns** — \`analyze({ aspect: "patterns", path: "." })\`
|
|
241
|
-
6. **Entry Points** — \`analyze({ aspect: "entry_points", path: "." })\`
|
|
242
|
-
7. **Diagrams** — \`analyze({ aspect: "diagram", path: "." })\`
|
|
237
|
+
2. **Structure** — \`analyze({ items: [{aspect: "structure", path: "."}] })\`
|
|
238
|
+
3. **Dependencies** — \`analyze({ items: [{aspect: "dependencies", path: "."}] })\`
|
|
239
|
+
4. **Symbols** — \`analyze({ items: [{aspect: "symbols", path: "."}] })\`
|
|
240
|
+
5. **Patterns** — \`analyze({ items: [{aspect: "patterns", path: "."}] })\`
|
|
241
|
+
6. **Entry Points** — \`analyze({ items: [{aspect: "entry_points", path: "."}] })\`
|
|
242
|
+
7. **Diagrams** — \`analyze({ items: [{aspect: "diagram", path: "."}] })\`
|
|
243
243
|
8. **Health Audit** — \`audit({ path: "." })\`
|
|
244
244
|
9. **Complexity** — \`measure({ path: "." })\`
|
|
245
245
|
10. **Git Context** — \`git_context({ include_diff: true })\`
|
|
@@ -253,10 +253,10 @@ Build a navigable knowledge graph of the codebase:
|
|
|
253
253
|
|
|
254
254
|
1. **Discover modules** — \`graph({ action: 'find_nodes' })\` to get all indexed modules
|
|
255
255
|
2. **Map relationships** — For key modules, \`graph({ action: 'neighbors', node_id, direction: 'both' })\`
|
|
256
|
-
3. **Trace critical paths** — Use \`trace({ start: "<entry-point>", direction: "forward" })\` on each entry point
|
|
256
|
+
3. **Trace critical paths** — Use \`trace({ items: [{start: "<entry-point>", direction: "forward"}] })\` on each entry point
|
|
257
257
|
4. **Identify layers** — Classify modules into architectural layers (API, Service, Domain, Data, Infrastructure, UI, Utility, Config)
|
|
258
258
|
5. **Detect communities** — \`graph({ action: 'detect_communities' })\` to find natural module clusters
|
|
259
|
-
6. **Symbol deep-dive** — For each public API/export, \`symbol({ name })\` to understand usage
|
|
259
|
+
6. **Symbol deep-dive** — For each public API/export, \`symbol({ items: [{name}] })\` to understand usage
|
|
260
260
|
|
|
261
261
|
Persist the graph structure and layer classification.
|
|
262
262
|
|
|
@@ -366,10 +366,10 @@ Create interactive HTML documentation using C4 architecture viewers and code tou
|
|
|
366
366
|
|
|
367
367
|
\`\`\`
|
|
368
368
|
onboard({ path: "." }) # If not done (check status() first)
|
|
369
|
-
analyze({ aspect: "structure", path: "." }) # Directory layout
|
|
370
|
-
analyze({ aspect: "dependencies", path: "." }) # Module graph
|
|
371
|
-
analyze({ aspect: "entry_points", path: "." }) # API surface
|
|
372
|
-
analyze({ aspect: "diagram", path: "." }) # Architecture diagram data
|
|
369
|
+
analyze({ items: [{aspect: "structure", path: "."}] }) # Directory layout
|
|
370
|
+
analyze({ items: [{aspect: "dependencies", path: "."}] }) # Module graph
|
|
371
|
+
analyze({ items: [{aspect: "entry_points", path: "."}] }) # API surface
|
|
372
|
+
analyze({ items: [{aspect: "diagram", path: "."}] }) # Architecture diagram data
|
|
373
373
|
graph({ action: "find_nodes" }) # Module graph for C4 mapping
|
|
374
374
|
graph({ action: "detect_communities" }) # Natural module clusters
|
|
375
375
|
\`\`\`
|
|
@@ -49,7 +49,7 @@ Use AI Kit retrieval/compression first. Native tools are fallback only.
|
|
|
49
49
|
|
|
50
50
|
${e()}
|
|
51
51
|
|
|
52
|
-
> **Path Note:** \`compact({ path, query })\` and \`file_summary({ path })\` accept any absolute path. Cached \`ctxc_...\` values are reversible refs passed as \`ref\` to \`compact({ ref })\` or \`compact({ ref, query? })\`; do not invent a separate \`read\`/\`id\` contract.
|
|
52
|
+
> **Path Note:** \`compact({ items: [{path, query}] })\` and \`file_summary({ items: [{path}] })\` accept any absolute path. Cached \`ctxc_...\` values are reversible refs passed as \`ref\` to \`compact({ ref })\` or \`compact({ ref, query? })\`; do not invent a separate \`read\`/\`id\` contract.
|
|
53
53
|
|
|
54
54
|
**\`read_file\` is ONLY for exact edit lines.** Use \`file_summary\` or \`compact\` first.
|
|
55
55
|
|
|
@@ -110,7 +110,7 @@ If reqs/design are unclear, return \`NEEDS_CONTEXT\`.
|
|
|
110
110
|
## Information Lookup Order (MANDATORY)
|
|
111
111
|
|
|
112
112
|
Follow this order. Do not skip to step 3 before checking steps 1-2.
|
|
113
|
-
Use \`compact({ path: "<dir>/<file>" })\` for onboard artifacts.
|
|
113
|
+
Use \`compact({ items: [{path: "<dir>/<file>"}] })\` for onboard artifacts.
|
|
114
114
|
|
|
115
115
|
### Step 1: Onboard Artifacts (pre-analyzed, fastest)
|
|
116
116
|
|
|
@@ -182,9 +182,9 @@ Use targeted searches before expensive work:
|
|
|
182
182
|
|---|---|
|
|
183
183
|
| \`graph({ action: 'neighbors', node_id })\` | Module relationships |
|
|
184
184
|
| \`find({ pattern })\` | Locate files by name/glob |
|
|
185
|
-
| \`symbol({ name })\` | Definition + refs |
|
|
186
|
-
| \`trace({ start, direction })\` | Call/data flow |
|
|
187
|
-
| \`compact({ path, query })\` | Read specific section of a file |
|
|
185
|
+
| \`symbol({ items: [{name}] })\` | Definition + refs |
|
|
186
|
+
| \`trace({ items: [{start, direction}] })\` | Call/data flow |
|
|
187
|
+
| \`compact({ items: [{path, query}] })\` | Read specific section of a file |
|
|
188
188
|
| \`compact({ ref, query? })\` | Reuse cached search/find/knowledge/compact output |
|
|
189
189
|
| \`read_file\` | **ONLY** when you need exact lines for a pending edit |
|
|
190
190
|
|
|
@@ -248,11 +248,11 @@ Verify before asserting.
|
|
|
248
248
|
|
|
249
249
|
| Before you... | First verify with... |
|
|
250
250
|
|---------------|---------------------|
|
|
251
|
-
| Reference a file path | \`find({ pattern })\` or \`file_summary({ path })\` |
|
|
252
|
-
| Call a function/method | \`symbol({ name })\` |
|
|
251
|
+
| Reference a file path | \`find({ pattern })\` or \`file_summary({ items: [{path}] })\` |
|
|
252
|
+
| Call a function/method | \`symbol({ items: [{name}] })\` |
|
|
253
253
|
| Claim a dependency exists | \`search({ query: "package-name" })\` or check \`package.json\` |
|
|
254
254
|
| Assert a fix works | \`check({})\` + \`test_run({})\` |
|
|
255
|
-
| Describe behavior | \`compact({ path, query })\` |
|
|
255
|
+
| Describe behavior | \`compact({ items: [{path, query}] })\` |
|
|
256
256
|
|
|
257
257
|
**Rule:** Not verified this session → unverified.
|
|
258
258
|
|
|
@@ -389,7 +389,7 @@ Always return this structure when invoked as a sub-agent:
|
|
|
389
389
|
Follow **MANDATORY FIRST ACTION** and **Information Lookup Order** from code-agent-base:
|
|
390
390
|
1. Run \`status({})\` — check Onboard Status and note the **Onboard Directory** path
|
|
391
391
|
2. If onboard shows ❌ → Run \`onboard({ path: '.' })\` and wait for completion
|
|
392
|
-
3. If onboard shows ✅ → Read relevant onboard artifacts using \`compact({ path: '<Onboard Directory>/<file>' })\` before exploring
|
|
392
|
+
3. If onboard shows ✅ → Read relevant onboard artifacts using \`compact({ items: [{path: '<Onboard Directory>/<file>'}] })\` before exploring
|
|
393
393
|
|
|
394
394
|
Start with pre-analyzed artifacts.
|
|
395
395
|
|
|
@@ -484,7 +484,7 @@ For questions that require trying approach A vs approach B in isolation:
|
|
|
484
484
|
Follow **MANDATORY FIRST ACTION** and **Information Lookup Order** from code-agent-base:
|
|
485
485
|
1. Run \`status({})\` — check Onboard Status and note the **Onboard Directory** path
|
|
486
486
|
2. If onboard shows ❌ → Run \`onboard({ path: '.' })\` and wait for completion
|
|
487
|
-
3. If onboard shows ✅ → Read relevant onboard artifacts using \`compact({ path: '<Onboard Directory>/<file>' })\` — especially \`patterns.md\` and \`api-surface.md\` for review context
|
|
487
|
+
3. If onboard shows ✅ → Read relevant onboard artifacts using \`compact({ items: [{path: '<Onboard Directory>/<file>'}] })\` — especially \`patterns.md\` and \`api-surface.md\` for review context
|
|
488
488
|
|
|
489
489
|
${t(`reviewer`)}
|
|
490
490
|
|
|
@@ -549,7 +549,7 @@ ${n()}
|
|
|
549
549
|
Follow **MANDATORY FIRST ACTION** and **Information Lookup Order** from code-agent-base:
|
|
550
550
|
1. Run \`status({})\` — check Onboard Status and note the **Onboard Directory** path
|
|
551
551
|
2. If onboard shows ❌ → Run \`onboard({ path: '.' })\` and wait for completion
|
|
552
|
-
3. If onboard shows ✅ → Read relevant onboard artifacts using \`compact({ path: '<Onboard Directory>/<file>' })\` — especially \`structure.md\`, \`dependencies.md\`, and \`diagram.md\` for architecture context
|
|
552
|
+
3. If onboard shows ✅ → Read relevant onboard artifacts using \`compact({ items: [{path: '<Onboard Directory>/<file>'}] })\` — especially \`structure.md\`, \`dependencies.md\`, and \`diagram.md\` for architecture context
|
|
553
553
|
|
|
554
554
|
${t(`reviewer`)}
|
|
555
555
|
|