@vpxa/aikit 0.1.305 → 0.1.306
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/analyzers/dist/index.js +7 -7
- package/packages/blocks-core/dist/index.mjs +3 -2
- package/packages/cli/dist/index.js +19 -19
- package/packages/indexer/dist/index.js +1 -1
- package/packages/present/dist/index.html +3 -2
- package/packages/server/dist/auth-7LFAZQBu.js +1 -0
- package/packages/server/dist/auth-bEP-6uqy.js +2 -0
- package/packages/server/dist/bin.js +6 -6
- package/packages/server/dist/config-B-wvmMyo.js +1 -0
- package/packages/server/dist/config-Bx85fwRX.js +2 -0
- package/packages/server/dist/{curated-manager-i5QA4c79.js → curated-manager-BrgM_znO.js} +4 -4
- package/packages/server/dist/dashboard-static-Dw7Nsq4f.js +1 -0
- package/packages/server/dist/dashboard-static-dPnij4uF.js +2 -0
- package/packages/server/dist/index.d.ts +97 -88
- package/packages/server/dist/index.js +1 -1
- package/packages/server/dist/{promotion-DmwIVl0c.js → promotion-BGWhzk_I.js} +2 -2
- package/packages/server/dist/{promotion-bQutAIz-.js → promotion-RbjKfC88.js} +2 -2
- package/packages/server/dist/proxy.js +1 -1
- package/packages/server/dist/resolve-sibling-BmZ7AxaA.js +1 -0
- package/packages/server/dist/resolve-sibling-DrGKPpb0.js +2 -0
- package/packages/server/dist/{routes-1wkXLxXe.js → routes-C7bDyCOW.js} +2 -2
- package/packages/server/dist/{routes-KC-D2U8n.js → routes-CfG5gdSR.js} +2 -2
- package/packages/server/dist/{server-0bgaP0Re.js → server-B_KbLM43.js} +177 -175
- package/packages/server/dist/server-http-B-TDT3t-.js +2 -0
- package/packages/server/dist/server-http-BbuuthEP.js +1 -0
- package/packages/server/dist/server-stdio-BUb39kqq.js +2 -0
- package/packages/server/dist/server-stdio-Ch7yAxNk.js +1 -0
- package/packages/server/dist/{server-DQvOpYNO.js → server-utMi-Qu3.js} +177 -175
- package/packages/server/dist/server-utils-De-aZNQa.js +1 -0
- package/packages/server/dist/settings-static-BpQgaMRs.js +1 -0
- package/packages/server/dist/settings-static-MepJZjer.js +2 -0
- package/packages/server/dist/startup-maintenance-D0Uhpi3k.js +1 -0
- package/packages/server/dist/startup-maintenance-L9NUOBVy.js +2 -0
- package/packages/server/dist/version-check-6qDKknz4.js +1 -0
- package/packages/server/dist/version-check-DSWaugPC.js +2 -0
- package/packages/server/dist/workspace-bootstrap-BPWA6BVf.js +1 -0
- package/packages/server/viewers/canvas.html +3 -2
- package/packages/server/viewers/report-template.html +3 -2
- package/packages/server/viewers/tour-viewer.html +3 -2
- package/packages/store/dist/index.d.ts +3 -1
- package/packages/store/dist/index.js +24 -24
- package/scaffold/dist/adapters/hermes-agent.mjs +56 -0
- package/scaffold/dist/definitions/models.mjs +1 -1
- package/scaffold/dist/definitions/skills/c4-architecture.mjs +1 -1
- package/scaffold/dist/definitions/skills/docs.mjs +1 -1
- package/scaffold/dist/definitions/skills/present.mjs +1 -1
- package/scaffold/dist/generated/block-docs.mjs +13 -2
- package/packages/server/dist/auth-Bz5dmZgR.js +0 -1
- package/packages/server/dist/auth-lzZKfxlV.js +0 -2
- package/packages/server/dist/config-CaJwUDXI.js +0 -2
- package/packages/server/dist/config-_gMeJYrz.js +0 -1
- package/packages/server/dist/dashboard-static-CRfR1yKU.js +0 -2
- package/packages/server/dist/dashboard-static-FmfoS46e.js +0 -1
- package/packages/server/dist/resolve-sibling-1oDoO-Re.js +0 -1
- package/packages/server/dist/resolve-sibling-ByoHo7Tp.js +0 -2
- package/packages/server/dist/settings-static-B3lnYvcb.js +0 -2
- package/packages/server/dist/settings-static-BtvyIrza.js +0 -1
- package/packages/server/dist/version-check-CJK1Fwmy.js +0 -2
- package/packages/server/dist/version-check-yzdUDXHC.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./curated-manager-i5QA4c79.js";import{randomUUID as t}from"node:crypto";import{readFileSync as n}from"node:fs";import{dirname as r,resolve as i}from"node:path";import{fileURLToPath as a,pathToFileURL as o}from"node:url";import{parseArgs as s}from"node:util";import{createLogger as c,serializeError as l,setDetailedErrorLoggingEnabled as u}from"../../core/dist/index.js";const d=`__pending__:`;function f(e){return e.startsWith(d)}function p(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function m(e,t,n,r){e.status(t).json({jsonrpc:`2.0`,error:{code:n,message:r},id:null})}var h=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=p(e),i=r?this.runtimes.get(r):void 0;if(r&&!i){m(t,404,-32001,`Session not found`);return}if(!i){if(e.method!==`POST`){m(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`&&!f(r)&&this.options.onSessionActivity?.(r),e.method===`DELETE`&&!f(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&&!f(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){m(e,503,-32003,`Session capacity reached`);return}let n=this.now(),r=await this.options.createServer(),i={id:`${d}${t()}`,transport:void 0,createdAt:n,lastAccessAt:n,server:r,requestChain:Promise.resolve()},a=this.options.createTransport({sessionIdGenerator:()=>t(),onsessioninitialized:async e=>{this.runtimes.delete(i.id),i.id=e,this.runtimes.set(e,i),this.options.onSessionStart?.(e)},onsessionclosed:async e=>{e&&await this.closeSession(e,{closeTransport:!1})}});return i.transport=a,a.onclose=()=>{let e=i.transport.sessionId??i.id;this.closeSession(e,{closeTransport:!1})},this.runtimes.set(i.id,i),await r.connect(a),i}async withRuntimeLock(e,t){let n=e.requestChain,r;e.requestChain=new Promise(e=>{r=e}),await n;try{await t()}finally{r()}}};function g(e){let t=e.includes(`T`)?e:`${e.replace(` `,`T`)}Z`;return Date.parse(t)}var _=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=g(n.lastActivity);return Number.isFinite(r)&&e-r>=t}).map(e=>e.sessionId)}};function v(){try{let e=i(r(a(import.meta.url)),`..`,`..`,`..`,`package.json`);return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}const y=c(`server`);function b(e,t){return t?{version:e,...l(t)}:{version:e}}const x=/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/i;function S({requestOrigin:e,configuredOrigin:t,allowAnyOrigin:n,fallbackOrigin:r}){let i=t??r;return i===`*`?n?{allowOrigin:`*`,warn:!1}:e?x.test(e)?{allowOrigin:e,warn:!1}:{allowOrigin:null,warn:!0}:{allowOrigin:r,warn:!1}:{allowOrigin:i,warn:!1}}function C({limit:e,windowMs:t}){let n=new Map,r=(e,r)=>{let i=r-t,a=n.get(e)?.filter(e=>e>i)??[];return a.length===0?(n.delete(e),[]):(n.set(e,a),a)};return{allow(t,i=Date.now()){let a=r(t,i);return a.length>=e?!1:(a.push(i),n.set(t,a),!0)},getRetryAfterMs(n,i=Date.now()){let a=r(n,i);return a.length<e?0:Math.max(0,a[0]+t-i)}}}function w(e){return e.startsWith(`file://`)?a(e):e}function T(e){let t=i(e);return process.platform===`win32`?t.toLowerCase():t}function E(e){let t=new Map;for(let n of e){let e=w(n.uri);t.set(T(e),e)}return[...t.values()].sort((e,t)=>T(e).localeCompare(T(t)))}function D({config:e,roots:t}){let n=E(t);if(n.length===0)return null;let r=e.sources?.[0]?.path;if(r){let e=T(r),t=n.find(t=>T(t)===e);if(t)return t}return n[0]}function O({config:e,log:t,reconfigureForWorkspace:n,roots:r}){let i=E(r);if(i.length===0)return!1;let a=D({config:e,roots:i.map(e=>({uri:e}))});if(!a)return!1;let o=e.sources?.[0]?.path,s=o&&T(o)===T(a)?`configured-source`:`stable-sorted-root`;return t.debug(`MCP roots resolved`,{rootPath:a,rootCount:i.length,selectedBy:s}),n(e,a),e.allRoots=i,!0}async function k({config:e,indexMode:t,log:n,rootsChangedNotificationSchema:r,reconfigureForWorkspace:i,runInitialIndex:a,server:o,startInit:s,timeoutMs:c=5e3,getCwd:u=()=>process.cwd()}){let d=v(),f=!1,p=!1,m,h=o.server,g=e=>{let t=l(e),n=`${String(e)} ${String(t.message??``)}`.toLowerCase();return n.includes(`method not found`)||n.includes(`not supported`)||n.includes(`unsupported`)||n.includes(`unknown method`)||n.includes(`roots/list`)||n.includes(`timed out`)},_=()=>{f||(f=!0,s())},y=()=>{p||t!==`auto`||(p=!0,(async()=>{try{await a()}catch(e){n.error(`Initial index failed`,b(d,e))}})())},x=t=>t.length===0||(m&&=(clearTimeout(m),void 0),!O({config:e,log:n,reconfigureForWorkspace:i,roots:t}))?!1:(_(),y(),!0);try{if(x((await h.listRoots()).roots))return;n.debug(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(t){if(g(t)){n.warn(`MCP roots/list not supported by client; using cwd fallback`,{version:d,cwd:u(),...l(t)}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:u()}]})&&(_(),y());return}n.warn(`MCP roots/list failed during bootstrap; waiting for roots/list_changed notification`,{version:d,cwd:u(),...l(t)})}h.setNotificationHandler(r,async()=>{try{x((await h.listRoots()).roots)}catch(e){n.warn(`roots/list retry failed after notification`,b(d,e))}}),m=setTimeout(()=>{let t=u();n.debug(`Timed out waiting for MCP roots/list_changed; falling back to cwd workspace`,{cwd:t}),O({config:e,log:n,reconfigureForWorkspace:i,roots:[{uri:t}]})&&(_(),y())},c)}function A(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function j(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===o(e).href}catch{return!1}}function M(e){let t=e.headers[`mcp-session-id`];return Array.isArray(t)?t[0]:t}function N(e,t){let n=process.env[e];if(!n)return t;let r=Number.parseInt(n,10);return Number.isFinite(r)&&r>0?r:t}function P(){return j()?s({allowPositionals:!0,options:{transport:{type:`string`,default:A()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:A(),port:process.env.AIKIT_PORT??`3210`}}async function F(){let n=v(),r=P();process.on(`unhandledRejection`,e=>{y.error(`Unhandled rejection`,b(n,e))}),process.on(`uncaughtException`,e=>{y.error(`Uncaught exception — exiting`,b(n,e)),process.exit(1)});let i=(t,r)=>{t.then(async()=>{try{let{markPromoteRun:t,markPruneRun:n,prune:i,shouldRunStartupPrune:a,shouldRunWeeklyPromote:o}=await import(`../../tools/dist/index.js`),s=r();if(!s)return;if(a()){let e=await i({});n(),e.totalBytesFreed>0&&y.info(`Storage maintenance complete`,{forgeOrphans:e.forgeGroundOrphans.count,legacyLance:e.legacyLance.count,bytesFreed:e.totalBytesFreed});let{groupLessons:t,pruneLessons:r}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),a=await r(s.curated,s.stateStore,{dryRun:!1});a.pruned.length>0&&y.info(`Startup lesson prune complete`,{pruned:a.pruned.length});let o=await t(s.curated,s.stateStore,{dryRun:!1});(o.groupsCreated>0||o.lessonsGrouped>0)&&y.info(`Startup lesson grouping complete`,{groupsCreated:o.groupsCreated,lessonsGrouped:o.lessonsGrouped})}if(o()){let{DEFAULT_PROMOTE_CONFIG:n,collectWorkspaceLessons:r,getGlobalCuratedDir:i,promoteLessons:a,scanForDuplicates:o}=await import(`./promotion-DmwIVl0c.js`).then(e=>e.o),c=s.curated,l=new e(i(),c.store,c.embedder),u=await r(),d={...n,dryRun:!1},f=await a(o(u,d),l,d);t(),f.promoted.length>0&&y.info(`Weekly lesson promotion complete`,{promoted:f.promoted.length,candidates:f.candidates.length})}}catch(e){y.warn(`Startup maintenance failed (non-critical)`,b(n,e))}}).catch(()=>{})};if(y.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let[{default:e},{loadConfig:a,resolveIndexMode:o},{registerDashboardRoutes:s,resolveDashboardDir:c},{registerSettingsRoutes:d,resolveSettingsDir:f},{createSettingsRouter:p},{authMiddleware:m,getOrCreateToken:g}]=await Promise.all([import(`express`),import(`./config-_gMeJYrz.js`),import(`./dashboard-static-FmfoS46e.js`),import(`./settings-static-BtvyIrza.js`),import(`./routes-1wkXLxXe.js`),import(`./auth-Bz5dmZgR.js`).then(e=>e.t)]),v=a();u(v.logging?.errorDetails===!0),v.configError&&y.warn(`Config load failure`,{error:v.configError}),y.info(`Config loaded`,{sourceCount:v.sources.length,storePath:v.store.path});let x=e();x.use(e.json({limit:`1mb`}));let w=Number(r.port),T=`http://localhost:${w}`,E=process.env.AIKIT_CORS_ORIGIN??T,D=process.env.AIKIT_ALLOW_ANY_ORIGIN===`true`,O=N(`AIKIT_HTTP_MAX_SESSIONS`,8),k=N(`AIKIT_HTTP_SESSION_TIMEOUT_MINUTES`,30),A=N(`AIKIT_HTTP_SESSION_GC_INTERVAL_MINUTES`,5),j=C({limit:100,windowMs:6e4}),P=!1;x.use((e,t,n)=>{let r=Array.isArray(e.headers.origin)?e.headers.origin[0]:e.headers.origin,i=S({requestOrigin:r,configuredOrigin:E,allowAnyOrigin:D,fallbackOrigin:T});if(i.warn&&!P&&(P=!0,y.warn(`Rejected non-local CORS origin while AIKIT_CORS_ORIGIN=*`,{origin:r,allowAnyOriginEnv:`AIKIT_ALLOW_ANY_ORIGIN=true`})),r&&!i.allowOrigin){t.status(403).json({error:`Origin not allowed`});return}if(i.allowOrigin&&t.setHeader(`Access-Control-Allow-Origin`,i.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=g();x.use(m(F)),x.use(`/mcp`,(e,t,n)=>{let r=M(e)??e.ip??e.socket.remoteAddress??`anonymous`;if(j.allow(r)){n();return}let i=Math.max(1,Math.ceil(j.getRetryAfterMs(r)/1e3));t.setHeader(`Retry-After`,String(i)),t.status(429).json({jsonrpc:`2.0`,error:{code:-32003,message:`Rate limit exceeded`},id:null})});let I=!1;x.use(`/mcp`,(e,t,n)=>{if(!I){let t=e.headers[`x-workspace-root`];typeof t==`string`&&t.length>0&&(v.sources[0]={path:t,excludePatterns:v.sources[0]?.excludePatterns??[]},v.allRoots=[t],I=!0,y.debug(`Workspace root applied from proxy header`,{wsRoot:t}))}n()}),s(x,c(),y);let L=new Date().toISOString();x.use(`/settings/api`,p({log:y,mcpInfo:()=>({transport:`http`,port:w,pid:process.pid,startedAt:L})})),d(x,f(),y),x.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}),await r;try{let r=M(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:()=>t(),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(y.error(`MCP handler error`,l(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,t)=>{let n=M(e);if(U&&(!W||n!==G)){await U.handleRequest(e,t,e.body);return}await J(e,t)};x.post(`/mcp`,Y),x.get(`/mcp`,Y),x.delete(`/mcp`,Y);let X=x.listen(w,`127.0.0.1`,()=>{y.info(`MCP server listening`,{url:`http://127.0.0.1:${w}/mcp`,port:w}),setTimeout(async()=>{try{let[{createLazyServer:e,createMcpServer:t,ALL_TOOL_NAMES:r},{StreamableHTTPServerTransport:a},{checkForUpdates:s,autoUpgradeScaffold:c}]=await Promise.all([import(`./server-DQvOpYNO.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-yzdUDXHC.js`)]);s(),c(),setInterval(s,1440*60*1e3).unref();let u=o(v),d=e(v,u);K=async()=>{d.aikit&&await Promise.all([d.aikit.embedder.shutdown?.().catch(()=>{})??Promise.resolve(),d.aikit.graphStore.close().catch(()=>{}),d.aikit.closeStateStore?.().catch(()=>{})??Promise.resolve(),d.aikit.store.close().catch(()=>{})])},V=d.server,H=a,R=!0,y.debug(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:r.length,resourceCount:2}),d.startInit(),d.ready.then(()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);B=new _(d.aikit.stateStore,{staleTimeoutMinutes:k,gcIntervalMinutes:A,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(!d.aikit?.curated||!d.aikit?.stateStore)return;let{pruneLessons:e}=await import(`./evolution-BX_zTSdj.js`).then(e=>e.t),t=await e(d.aikit.curated,d.aikit.stateStore,{dryRun:!1});t.pruned.length>0&&y.info(`Session-end lesson prune`,{pruned:t.pruned.length})}}),U=new h({createServer:()=>{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);return t(d.aikit,v)},createTransport:e=>new a(e),maxSessions:O,sessionTimeoutMinutes:k,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)),y.info(`HTTP session runtime ready`,{maxSessions:O,sessionTimeoutMinutes:k,gcIntervalMinutes:A})}).catch(e=>y.error(`Failed to start session manager`,l(e))),u===`auto`?d.ready.then(async()=>{try{let e=v.sources.map(e=>e.path).join(`, `);y.info(`Running initial index`,{sourcePaths:e}),await d.runInitialIndex(),y.info(`Initial index complete`)}catch(e){y.error(`Initial index failed; will retry on aikit_reindex`,b(n,e))}}).catch(e=>y.error(`AI Kit init or indexing failed`,b(n,e))):u===`smart`?d.ready.then(async()=>{try{if(!d.aikit)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(d.aikit.indexer,v,d.aikit.store),n=d.aikit.store;z=t,t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),d.setSmartScheduler(t),y.debug(`Smart index scheduler started (HTTP mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit initialization failed`,b(n,e))):(d.ready.catch(e=>y.error(`AI Kit initialization failed`,b(n,e))),y.info(`Initial full indexing skipped in HTTP mode`,{indexMode:u})),i(d.ready,()=>d.aikit?{curated:d.aikit.curated,stateStore:d.aikit.stateStore}:null)}catch(e){y.error(`Failed to load server modules`,b(n,e))}},100)}),Z=!1,Q=async e=>{Z||(Z=!0,y.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`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:r},{createLazyServer:a},{checkForUpdates:o,autoUpgradeScaffold:s},{RootsListChangedNotificationSchema:c}]=await Promise.all([import(`./config-_gMeJYrz.js`),import(`./server-DQvOpYNO.js`),import(`./version-check-yzdUDXHC.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();u(l.logging?.errorDetails===!0),l.configError&&y.warn(`Config load failure`,{error:l.configError}),y.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),o(),s(),setInterval(o,1440*60*1e3).unref();let d=r(l),f=a(l,d),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),y.debug(`MCP server started`,{transport:`stdio`}),await k({config:l,indexMode:d,log:y,rootsChangedNotificationSchema:c,reconfigureForWorkspace:t,runInitialIndex:g,server:p,startInit:m});let x=null,S=null,C=!1,w=async e=>{C||(C=!0,y.info(`Shutdown signal received`,{signal:e}),x&&=(clearTimeout(x),null),S?.stop(),await import(`../../tools/dist/index.js`).then(({processStopAll:e})=>e()).catch(()=>{}),await v.close().catch(()=>void 0),await p.close().catch(()=>void 0),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(()=>{})]),process.exit(0))},T=()=>{x&&clearTimeout(x),x=setTimeout(async()=>{y.info(`Auto-shutdown: no activity for 30 minutes — releasing resources`);try{let e=f.aikit;e&&(e.embedder.shutdown?.().catch(()=>{}),e.store.releaseMemory?.(),e.graphStore.releaseMemory?.())}catch{}},18e5),x.unref&&x.unref()};T(),process.stdin.on(`data`,()=>T()),process.stdin.on(`end`,()=>void w(`stdin-end`)),process.stdin.on(`close`,()=>void w(`stdin-close`)),process.stdin.on(`error`,()=>void w(`stdin-error`)),process.on(`SIGINT`,()=>void w(`SIGINT`)),process.on(`SIGTERM`,()=>void w(`SIGTERM`)),h.catch(e=>{y.error(`Initialization failed — server will continue with limited tools`,b(n,e))}),d===`smart`?h.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,l,f.aikit.store);S=t;let n=f.aikit.store;t.start(),n.onBeforeClose&&n.onBeforeClose(()=>t.stop()),f.setSmartScheduler(t),y.debug(`Smart index scheduler started (stdio mode)`)}catch(e){y.error(`Failed to start smart index scheduler`,b(n,e))}}).catch(e=>y.error(`AI Kit init failed for smart scheduler`,b(n,e))):y.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:d}),i(h,()=>f.aikit?{curated:f.aikit.curated,stateStore:f.aikit.stateStore}:null)}}export{e as CuratedKnowledgeManager,O as applyWorkspaceRoots,k as bootstrapWorkspaceRoots,C as createSlidingWindowRateLimiter,F as main,S as resolveCorsOrigin,D as selectWorkspaceRoot};
|
|
1
|
+
import{a as e,i as t,n,r,t as i}from"./server-utils-De-aZNQa.js";import{n as a,r as o,t as s}from"./workspace-bootstrap-BPWA6BVf.js";import{t as c}from"./curated-manager-BrgM_znO.js";import{pathToFileURL as l}from"node:url";import{parseArgs as u}from"node:util";import{createLogger as d,serializeError as f}from"../../core/dist/index.js";const p=d(`server`);function m(e,t){return t?{version:e,...f(t)}:{version:e}}function h(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function g(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===l(e).href}catch{return!1}}function _(){return g()?u({allowPositionals:!0,options:{transport:{type:`string`,default:h()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:h(),port:process.env.AIKIT_PORT??`3210`}}async function v(){let e=t(),n=_();if(process.on(`unhandledRejection`,t=>{p.error(`Unhandled rejection`,m(e,t))}),process.on(`uncaughtException`,t=>{p.error(`Uncaught exception — exiting`,m(e,t)),process.exit(1)}),p.info(`Starting MCP AI Kit server`,{version:e}),n.transport===`http`){let{startHttpMode:t}=await import(`./server-http-BbuuthEP.js`);await t(e,n.port)}else{let{startStdioMode:t}=await import(`./server-stdio-Ch7yAxNk.js`);await t(e)}}export{c as CuratedKnowledgeManager,s as applyWorkspaceRoots,a as bootstrapWorkspaceRoots,i as createSlidingWindowRateLimiter,n as getSessionIdHeader,v as main,r as readPositiveIntEnv,t as readVersion,e as resolveCorsOrigin,o as selectWorkspaceRoot};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{t}from"./curated-manager-
|
|
2
|
-
`),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let r=await e.list({category:`lessons`,limit:1e3,orderBy:`updated`,order:`desc`});return(await Promise.all(r.map(async r=>{let i=await e.read(r.path),a=n(i.content),o=_(a.insight);return o?{workspace:t,path:r.path,title:a.title??i.title??r.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,t,n){return t.some(t=>r(t,e)>=n)}function C(){let e=
|
|
1
|
+
import{t as e}from"./rolldown-runtime-DT7IzrpZ.js";import{t}from"./curated-manager-BrgM_znO.js";import{f as n,r,u as i}from"./supersession-CWEne3av.js";import{getGlobalDataDir as a,isUserInstalled as o,listWorkspaces as s}from"../../core/dist/index.js";import{existsSync as c,mkdirSync as l}from"node:fs";import{join as u}from"node:path";var d=e({DEFAULT_PROMOTE_CONFIG:()=>f,collectWorkspaceLessons:()=>w,demoteLesson:()=>D,getGlobalCuratedDir:()=>C,promoteLessons:()=>E,scanForDuplicates:()=>T});const f={minWorkspaces:2,minAvgConfidence:80,similarityThreshold:.7,dryRun:!0};function p(e){return{minWorkspaces:Math.max(2,Math.trunc(e?.minWorkspaces??f.minWorkspaces)),minAvgConfidence:Math.min(100,Math.max(0,Math.trunc(e?.minAvgConfidence??f.minAvgConfidence))),similarityThreshold:Math.min(1,Math.max(0,e?.similarityThreshold??f.similarityThreshold)),dryRun:e?.dryRun??f.dryRun}}function m(e,t){let n=e.map(()=>[]);for(let i=0;i<e.length;i+=1)for(let a=i+1;a<e.length;a+=1)r(e[i].insight,e[a].insight)>=t&&(n[i].push(a),n[a].push(i));return n}function h(e){let t=new Set,n=[];for(let r=0;r<e.length;r+=1){if(t.has(r))continue;let i=[r],a=[];for(t.add(r);i.length>0;){let n=i.pop();if(n!==void 0){a.push(n);for(let r of e[n])t.has(r)||(t.add(r),i.push(r))}}n.push(a)}return n}function g(e){return new t(e,null,null)}function _(e){return(e??``).replace(/\s+/g,` `).trim()}function v(e){let t=_(e);return t.length<=80?t:`${t.slice(0,77).replace(/\s+\S*$/,``)}...`}function y(e){return i({title:v(e.insight),context:`Observed across ${e.foundIn.length} workspaces: ${e.foundIn.join(`, `)}`,insight:e.insight,evidence:[`Promoted from workspaces: ${e.foundIn.join(`, `)}`,`Average confidence: ${e.avgConfidence}/100`,`Reason: ${e.reason}`].join(`
|
|
2
|
+
`),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let r=await e.list({category:`lessons`,limit:1e3,orderBy:`updated`,order:`desc`});return(await Promise.all(r.map(async r=>{let i=await e.read(r.path),a=n(i.content),o=_(a.insight);return o?{workspace:t,path:r.path,title:a.title??i.title??r.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,t,n){return t.some(t=>r(t,e)>=n)}function C(){let e=u(a(),`global-knowledge`,`.ai`,`curated`);return c(e)||l(e,{recursive:!0}),e}async function w(e){let t=new Map;if(!o())return t;for(let e of s()){let n=u(e.workspacePath,`.ai`,`curated`);if(!c(n))continue;let r=await b(g(n),e.partition);r.length>0&&t.set(e.partition,r)}return t}function T(e,t=f){let n=p(t),r=[...e.values()].flat();if(r.length===0)return[];let i=h(m(r,n.similarityThreshold)),a=[];for(let e of i){let t=e.map(e=>r[e]),i=[...new Set(t.map(e=>e.workspace))].sort();if(i.length<n.minWorkspaces)continue;let o=Math.round(t.reduce((e,t)=>e+t.confidence,0)/t.length),s=[...t].sort((e,t)=>t.confidence-e.confidence||e.title.localeCompare(t.title)||e.path.localeCompare(t.path))[0];a.push({insight:s.insight,foundIn:i,avgConfidence:o,action:o>=n.minAvgConfidence?`promote`:`skip`,reason:o>=n.minAvgConfidence?`Shared across ${i.length} workspaces`:`Below confidence threshold`})}return a.sort((e,t)=>Number(t.action===`promote`)-Number(e.action===`promote`)||t.foundIn.length-e.foundIn.length||t.avgConfidence-e.avgConfidence||e.insight.localeCompare(t.insight))}async function E(e,t,n=f){let r=p(n),i=[],a=await x(t);for(let n of e){if(n.action!==`promote`||S(n.insight,a,r.similarityThreshold)||r.dryRun)continue;let e=await t.remember(v(n.insight),y(n),`lessons`,[`lesson`,`promoted`,`global`]);i.push(e.path),a.push(n.insight)}return{candidates:e,promoted:i}}async function D(e,t){try{return await e.forget(t,`Demoted from global knowledge partition`),{removed:!0,path:t}}catch(e){if(e instanceof Error&&/not found/i.test(e.message))return{removed:!1,path:t};throw e}}export{E as a,C as i,w as n,d as o,D as r,T as s,f as t};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{t as e}from"./rolldown-runtime-yuFVEuWy.js";import{t}from"./bin.js";import{f as n,r,u as i}from"./supersession-DO_ZROFl.js";import{
|
|
3
|
-
`),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let r=await e.list({category:`lessons`,limit:1e3,orderBy:`updated`,order:`desc`});return(await Promise.all(r.map(async r=>{let i=await e.read(r.path),a=n(i.content),o=_(a.insight);return o?{workspace:t,path:r.path,title:a.title??i.title??r.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,t,n){return t.some(t=>r(t,e)>=n)}function C(){let e=
|
|
2
|
+
import{t as e}from"./rolldown-runtime-yuFVEuWy.js";import{t}from"./bin.js";import{f as n,r,u as i}from"./supersession-DO_ZROFl.js";import{getGlobalDataDir as a,isUserInstalled as o,listWorkspaces as s}from"../../core/dist/index.js";import{existsSync as c,mkdirSync as l}from"node:fs";import{join as u}from"node:path";var d=e({DEFAULT_PROMOTE_CONFIG:()=>f,collectWorkspaceLessons:()=>w,demoteLesson:()=>D,getGlobalCuratedDir:()=>C,promoteLessons:()=>E,scanForDuplicates:()=>T});const f={minWorkspaces:2,minAvgConfidence:80,similarityThreshold:.7,dryRun:!0};function p(e){return{minWorkspaces:Math.max(2,Math.trunc(e?.minWorkspaces??f.minWorkspaces)),minAvgConfidence:Math.min(100,Math.max(0,Math.trunc(e?.minAvgConfidence??f.minAvgConfidence))),similarityThreshold:Math.min(1,Math.max(0,e?.similarityThreshold??f.similarityThreshold)),dryRun:e?.dryRun??f.dryRun}}function m(e,t){let n=e.map(()=>[]);for(let i=0;i<e.length;i+=1)for(let a=i+1;a<e.length;a+=1)r(e[i].insight,e[a].insight)>=t&&(n[i].push(a),n[a].push(i));return n}function h(e){let t=new Set,n=[];for(let r=0;r<e.length;r+=1){if(t.has(r))continue;let i=[r],a=[];for(t.add(r);i.length>0;){let n=i.pop();if(n!==void 0){a.push(n);for(let r of e[n])t.has(r)||(t.add(r),i.push(r))}}n.push(a)}return n}function g(e){return new t(e,null,null)}function _(e){return(e??``).replace(/\s+/g,` `).trim()}function v(e){let t=_(e);return t.length<=80?t:`${t.slice(0,77).replace(/\s+\S*$/,``)}...`}function y(e){return i({title:v(e.insight),context:`Observed across ${e.foundIn.length} workspaces: ${e.foundIn.join(`, `)}`,insight:e.insight,evidence:[`Promoted from workspaces: ${e.foundIn.join(`, `)}`,`Average confidence: ${e.avgConfidence}/100`,`Reason: ${e.reason}`].join(`
|
|
3
|
+
`),confidence:e.avgConfidence,tags:[`lesson`,`promoted`,`global`]})}async function b(e,t){let r=await e.list({category:`lessons`,limit:1e3,orderBy:`updated`,order:`desc`});return(await Promise.all(r.map(async r=>{let i=await e.read(r.path),a=n(i.content),o=_(a.insight);return o?{workspace:t,path:r.path,title:a.title??i.title??r.title,insight:o,confidence:a.confidence??0}:null}))).filter(e=>e!==null)}async function x(e){return(await b(e,`global`)).map(e=>e.insight)}function S(e,t,n){return t.some(t=>r(t,e)>=n)}function C(){let e=u(a(),`global-knowledge`,`.ai`,`curated`);return c(e)||l(e,{recursive:!0}),e}async function w(e){let t=new Map;if(!o())return t;for(let e of s()){let n=u(e.workspacePath,`.ai`,`curated`);if(!c(n))continue;let r=await b(g(n),e.partition);r.length>0&&t.set(e.partition,r)}return t}function T(e,t=f){let n=p(t),r=[...e.values()].flat();if(r.length===0)return[];let i=h(m(r,n.similarityThreshold)),a=[];for(let e of i){let t=e.map(e=>r[e]),i=[...new Set(t.map(e=>e.workspace))].sort();if(i.length<n.minWorkspaces)continue;let o=Math.round(t.reduce((e,t)=>e+t.confidence,0)/t.length),s=[...t].sort((e,t)=>t.confidence-e.confidence||e.title.localeCompare(t.title)||e.path.localeCompare(t.path))[0];a.push({insight:s.insight,foundIn:i,avgConfidence:o,action:o>=n.minAvgConfidence?`promote`:`skip`,reason:o>=n.minAvgConfidence?`Shared across ${i.length} workspaces`:`Below confidence threshold`})}return a.sort((e,t)=>Number(t.action===`promote`)-Number(e.action===`promote`)||t.foundIn.length-e.foundIn.length||t.avgConfidence-e.avgConfidence||e.insight.localeCompare(t.insight))}async function E(e,t,n=f){let r=p(n),i=[],a=await x(t);for(let n of e){if(n.action!==`promote`||S(n.insight,a,r.similarityThreshold)||r.dryRun)continue;let e=await t.remember(v(n.insight),y(n),`lessons`,[`lesson`,`promoted`,`global`]);i.push(e.path),a.push(n.insight)}return{candidates:e,promoted:i}}async function D(e,t){try{return await e.forget(t,`Demoted from global knowledge partition`),{removed:!0,path:t}}catch(e){if(e instanceof Error&&/not found/i.test(e.message))return{removed:!1,path:t};throw e}}export{E as a,C as i,w as n,d as o,D as r,T as s,f as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e}from"./auth-
|
|
1
|
+
import{n as e}from"./auth-7LFAZQBu.js";import{fileURLToPath as t}from"node:url";import{spawn as n}from"node:child_process";import{createInterface as r}from"node:readline";function i(e){let t=[],n=e.replace(/\r\n/g,`
|
|
2
2
|
`);for(let e of n.split(`
|
|
3
3
|
`))e.startsWith(`data: `)?t.push(e.slice(6)):e.startsWith(`data:`)&&t.push(e.slice(5));return t}const a={input:process.stdin,output:process.stdout,error:process.stderr,fetchImpl:globalThis.fetch,spawnImpl:n,readTokenImpl:e,sleep:e=>new Promise(t=>setTimeout(t,e))};async function o(e={},t={}){let n={...a,...t},o=c(e.port),l=`http://127.0.0.1:${o}`,g=await s(l,n.fetchImpl);if(!g&&e.autoStart!==!1)try{u(o,n),await d(l,3e4,n),g=!0}catch(e){n.error.write(`[aikit-proxy] ${h(e)}\n`)}else g||n.error.write(`[aikit-proxy] Daemon not running and autoStart=false
|
|
4
4
|
`);let _=n.readTokenImpl();if(!_){n.error.write(`[aikit-proxy] No token found at ~/.aikit/token
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createRequire as e}from"node:module";import{fileURLToPath as t}from"node:url";import{existsSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";const a=e(import.meta.url),o=import.meta.dirname??r(t(import.meta.url)),s=new Map;function c(e){let t=s.get(e);if(t!==void 0)return t;let c=i(o,`..`,`..`,e);if(n(i(c,`package.json`)))return s.set(e,c),c;try{let t=r(a.resolve(`@aikit/${e}/package.json`));return s.set(e,t),t}catch{}let l=o;for(let t=0;t<6;t++){let t=i(l,`packages`,e);if(n(i(t,`package.json`)))return s.set(e,t),t;let a=r(l);if(a===l)break;l=a}return s.set(e,null),null}function l(e,t=`dist`){let r=c(e);if(!r)return null;let a=i(r,t);return n(a)?a:null}function u(e,t){let r=c(e);if(!r)return null;for(let e of t){let t=i(r,e);if(n(t))return t}return null}export{u as n,c as r,l as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{createRequire as e}from"node:module";import{fileURLToPath as t}from"node:url";import{existsSync as n}from"node:fs";import{dirname as r,join as i}from"node:path";const a=e(import.meta.url),o=import.meta.dirname??r(t(import.meta.url)),s=new Map;function c(e){let t=s.get(e);if(t!==void 0)return t;let c=i(o,`..`,`..`,e);if(n(i(c,`package.json`)))return s.set(e,c),c;try{let t=r(a.resolve(`@aikit/${e}/package.json`));return s.set(e,t),t}catch{}let l=o;for(let t=0;t<6;t++){let t=i(l,`packages`,e);if(n(i(t,`package.json`)))return s.set(e,t),t;let a=r(l);if(a===l)break;l=a}return s.set(e,null),null}function l(e,t=`dist`){let r=c(e);if(!r)return null;let a=i(r,t);return n(a)?a:null}function u(e,t){let r=c(e);if(!r)return null;for(let e of t){let t=i(r,e);if(n(t))return t}return null}export{u as n,c as r,l as t};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{getGlobalDataDir as e,isUserInstalled as t}from"../../core/dist/index.js";import{existsSync as n,mkdirSync as r,readFileSync as i,renameSync as a,writeFileSync as o}from"node:fs";import{dirname as s,resolve as c}from"node:path";import{z as l}from"zod";import{Router as u}from"express";const d=[{key:`serverName`,type:`string`,default:`aikit`,description:`MCP server name advertised to clients.`,group:`general`,requiresRestart:!0},{key:`toolPrefix`,type:`string`,default:``,description:`Prefix prepended to every MCP tool name (e.g. "aikit_").`,group:`general`,requiresRestart:!0},{key:`toolProfile`,type:`string`,default:`full`,description:`Active tool profile.`,group:`general`,enum:[`full`,`safe`,`research`,`minimal`,`discovery`],requiresRestart:!0},{key:`autoIndex`,type:`boolean`,default:!1,description:`Deprecated. Prefer indexMode. true → auto, false → manual.`,group:`indexing`},{key:`indexMode`,type:`string`,default:`smart`,description:`Indexing strategy. auto = full on startup, manual = on demand, smart = on-demand + idle.`,group:`indexing`,enum:[`auto`,`manual`,`smart`]},{key:`sources`,type:`array`,description:`Source roots to index. Each entry has { path, excludePatterns }.`,group:`indexing`,requiresRestart:!0},{key:`indexing.chunkSize`,type:`number`,default:1500,description:`Maximum chunk size in characters.`,group:`indexing`},{key:`indexing.chunkOverlap`,type:`number`,default:200,description:`Overlap between adjacent chunks.`,group:`indexing`},{key:`indexing.minChunkSize`,type:`number`,default:100,description:`Minimum chunk size before merging into the next chunk.`,group:`indexing`},{key:`indexing.concurrency`,type:`number`,description:`Max files processed concurrently. Defaults to half of CPU cores.`,group:`indexing`},{key:`embedding.model`,type:`string`,default:`mixedbread-ai/mxbai-embed-large-v1`,description:`Embedding model identifier.`,group:`embedding`,requiresRestart:!0},{key:`embedding.dimensions`,type:`number`,default:1024,description:`Embedding vector dimensions. Must match the model.`,group:`embedding`,requiresRestart:!0},{key:`store.backend`,type:`string`,default:`sqlite-vec`,description:`Vector store backend (sqlite-vec | lancedb).`,group:`store`,requiresRestart:!0},{key:`store.path`,type:`string`,description:`Filesystem path for the vector store.`,group:`store`,requiresRestart:!0},{key:`curated.path`,type:`string`,description:`Path to curated knowledge directory.`,group:`store`,requiresRestart:!0},{key:`onboardDir`,type:`string`,description:`Directory for onboard / produce_knowledge output.`,group:`store`,requiresRestart:!0},{key:`stateDir`,type:`string`,description:`Directory for session state (stash, checkpoints, etc.).`,group:`store`,requiresRestart:!0},{key:`er.enabled`,type:`boolean`,default:!1,description:`Enable enterprise RAG bridge integration.`,group:`enterprise-bridge`,requiresRestart:!0},{key:`er.baseUrl`,type:`string`,description:`Base URL of the ER API.`,group:`enterprise-bridge`,requiresRestart:!0},{key:`er.timeoutMs`,type:`number`,default:5e3,description:`ER request timeout in milliseconds.`,group:`enterprise-bridge`},{key:`er.fallbackThreshold`,type:`number`,default:.45,description:`Vector similarity threshold below which ER fallback triggers.`,group:`enterprise-bridge`}],f=[{key:`AIKIT_TRANSPORT`,type:`string`,default:`stdio`,description:`MCP transport mode.`,group:`transport`,enum:[`stdio`,`http`],defaultScope:`workspace`},{key:`AIKIT_PORT`,type:`string`,default:`3210`,description:`HTTP port when transport = http.`,group:`transport`,defaultScope:`workspace`},{key:`AIKIT_CORS_ORIGIN`,type:`string`,description:`CORS Access-Control-Allow-Origin header for HTTP mode.`,group:`transport`,defaultScope:`workspace`},{key:`AIKIT_CONFIG_PATH`,type:`string`,description:`Override path to aikit.config.json.`,group:`paths`,defaultScope:`workspace`},{key:`AIKIT_WORKSPACE_ROOT`,type:`string`,description:`Override workspace root used when no config file is present.`,group:`paths`,defaultScope:`workspace`},{key:`AIKIT_GLOBAL_DATA_DIR`,type:`string`,description:`Override global data directory (default: ~/.aikit).`,group:`paths`,defaultScope:`global`},{key:`AIKIT_INDEX_MODE`,type:`string`,description:`Override config indexMode.`,group:`indexing`,enum:[`auto`,`manual`,`smart`],defaultScope:`workspace`},{key:`AIKIT_AUTO_INDEX`,type:`string`,description:`Legacy boolean override. Prefer AIKIT_INDEX_MODE.`,group:`indexing`,enum:[`true`,`false`],defaultScope:`workspace`},{key:`AIKIT_TOOLSET`,type:`string`,description:`Override active tool profile.`,group:`general`,defaultScope:`workspace`},{key:`AIKIT_BROWSER_DEFAULT_MODE`,type:`string`,default:`ui`,description:`Default browser launch mode for browser_* tools.`,group:`browser`,enum:[`ui`,`headless`,`panel`],defaultScope:`workspace`},{key:`AIKIT_BROWSER_PATH`,type:`string`,description:`Optional Playwright browser download path override.`,group:`browser`,defaultScope:`workspace`},{key:`AIKIT_BROWSER_IDLE_MINUTES`,type:`string`,default:`10`,description:`Idle shutdown timeout in minutes for the shared browser runtime.`,group:`browser`,defaultScope:`workspace`},{key:`AIKIT_BROWSER_EVAL_TIMEOUT_MS`,type:`string`,default:`5000`,description:`Default browser_eval timeout in milliseconds.`,group:`browser`,defaultScope:`workspace`},{key:`AIKIT_SEARCH_DEADLINE_MS`,type:`string`,default:`10000`,description:`Multi-provider web search deadline (milliseconds).`,group:`search-providers`,defaultScope:`global`},{key:`SEARXNG_URL`,type:`string`,description:`Optional SearXNG instance URL for the web_search tool.`,group:`search-providers`,defaultScope:`global`},{key:`GOOGLE_API_KEY`,type:`secret`,description:`Google Custom Search API key.`,group:`search-providers`,defaultScope:`global`},{key:`GOOGLE_CSE_ID`,type:`string`,description:`Google Custom Search Engine ID.`,group:`search-providers`,defaultScope:`global`},{key:`BRAVE_API_KEY`,type:`secret`,description:`Brave Search API key.`,group:`search-providers`,defaultScope:`global`},{key:`BING_API_KEY`,type:`secret`,description:`Bing Web Search API key.`,group:`search-providers`,defaultScope:`global`}];function p(e){return f.find(t=>t.key===e)}function m(e){let t=p(e);return t?t.type===`secret`:/(_KEY|_TOKEN|_SECRET|_PASSWORD|_PASS|_PWD)$/i.test(e)}const h=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$/;function g(e){let t=e.replace(/^\s+/,``);if(t.startsWith(`"`)){let e=1,n=``;for(;e<t.length;){let r=t[e];if(r===`\\`&&e+1<t.length){let r=t[e+1];r===`n`?n+=`
|
|
2
2
|
`:r===`r`?n+=`\r`:r===`t`?n+=` `:n+=r,e+=2;continue}if(r===`"`){let r=t.slice(e+1),i=r.indexOf(`#`),a=i===-1?``:r.slice(i);return{value:n,quoted:!0,inlineComment:a}}n+=r,e+=1}return{value:t.slice(1),quoted:!0,inlineComment:``}}let n=t.match(/(\s+#.*)$/);return n&&n.index!==void 0?{value:t.slice(0,n.index).trimEnd(),quoted:!1,inlineComment:n[1].trimStart()}:{value:t.trimEnd(),quoted:!1,inlineComment:``}}function _(e){let t;t=e.quoted||/[\s#"']/.test(e.value)||e.value.includes(`
|
|
3
3
|
`)||e.value.length===0?`"${e.value.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`).replace(/\n/g,`\\n`).replace(/\r/g,`\\r`).replace(/\t/g,`\\t`)}"`:e.value;let n=e.inlineComment?` ${e.inlineComment}`:``;return`${e.key}=${t}${n}`}function v(e){let t=[],n=e.split(/\r?\n/),r=e.endsWith(`
|
|
4
4
|
`)?n.slice(0,-1):n;for(let e of r){let n=e.match(h);if(!n){t.push({kind:`raw`,text:e});continue}let r=n[1],{value:i,quoted:a,inlineComment:o}=g(n[2]);t.push({kind:`assign`,key:r,value:i,quoted:a,inlineComment:o})}return{lines:t}}function y(e){return`${e.lines.map(e=>e.kind===`assign`?_(e):e.text).join(`
|
|
5
|
-
`)}\n`}function b(e){let t={};for(let n of e.lines)n.kind===`assign`&&(t[n.key]=n.value);return t}function x(e,t,n){let r=e.lines.map(e=>e.kind===`assign`&&e.key===t?{...e,value:n}:e);return e.lines.some(e=>e.kind===`assign`&&e.key===t)||r.push({kind:`assign`,key:t,value:n,quoted:!1,inlineComment:``}),{lines:r}}function S(e,t){return{lines:e.lines.filter(e=>!(e.kind===`assign`&&e.key===t))}}function C(e){return
|
|
5
|
+
`)}\n`}function b(e){let t={};for(let n of e.lines)n.kind===`assign`&&(t[n.key]=n.value);return t}function x(e,t,n){let r=e.lines.map(e=>e.kind===`assign`&&e.key===t?{...e,value:n}:e);return e.lines.some(e=>e.kind===`assign`&&e.key===t)||r.push({kind:`assign`,key:t,value:n,quoted:!1,inlineComment:``}),{lines:r}}function S(e,t){return{lines:e.lines.filter(e=>!(e.kind===`assign`&&e.key===t))}}function C(e){return c(e,`.env`)}function w(){return c(e(),`global.env`)}function T(e,t){return e===`workspace`?C(t):w()}function E(e){return n(e)?v(i(e,`utf-8`)):{lines:[]}}function D(e,t){let i=s(e);n(i)||r(i,{recursive:!0});let c=`${e}.${process.pid}.${Date.now()}.tmp`;o(c,y(t),{encoding:`utf-8`,mode:384}),a(c,e)}function O(e,t,r={}){let i=T(e,t),a=n(i),o=b(E(i)),s={};for(let[e,t]of Object.entries(o))s[e]=r.reveal||!m(e)?t:k(t);return{scope:e,path:i,exists:a,vars:s}}function k(e){return e.length===0?``:e.length<=4?`•`.repeat(e.length):`${e.slice(0,2)}${`•`.repeat(Math.min(e.length-4,12))}${e.slice(-2)}`}function A(){return process.env.AIKIT_WORKSPACE_ROOT??process.cwd()}function j(){return t()?`user`:`workspace`}function M(){let t=e();return n(t)||r(t,{recursive:!0}),t}var N=class extends Error{details;constructor(e,t){super(e),this.name=`ConfigValidationError`,this.details=t}};function P(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function F(e=A()){let t=process.env.AIKIT_CONFIG_PATH;return t?c(t):c(e,`aikit.config.json`)}function I(e){if(!n(e))return null;let t=i(e,`utf-8`),r=JSON.parse(t);if(!P(r))throw new N(`config-not-object`,[`Config file must contain a JSON object at the root.`]);return r}function L(e,t){let i=s(e);n(i)||r(i,{recursive:!0});let c=`${JSON.stringify(t,null,2)}\n`,l=`${e}.${process.pid}.${Date.now()}.tmp`;o(l,c,{encoding:`utf-8`}),a(l,e)}function R(e){return e.length===0?[]:e.split(`.`)}function z(e,t,n){let r=R(t);if(r.length===0)throw new N(`invalid-path`,[`Patch path must not be empty.`]);let i={...e},a=i;for(let e=0;e<r.length-1;e+=1){let t=r[e],n=r[e+1],i=/^\d+$/.test(n);if(Array.isArray(a)){let n=Number(t);if(!Number.isInteger(n))throw new N(`invalid-path`,[`Path segment "${t}" must be an integer index for array at depth ${e}.`]);let r=a[n];if(i){let e=Array.isArray(r)?[...r]:[];a[n]=e,a=e}else{let e=P(r)?{...r}:{};a[n]=e,a=e}continue}let o=a[t];if(i){let e=Array.isArray(o)?[...o]:[];a[t]=e,a=e}else{let e=P(o)?{...o}:{};a[t]=e,a=e}}let o=r[r.length-1];if(Array.isArray(a)){let e=Number(o);if(!Number.isInteger(e))throw new N(`invalid-path`,[`Path segment "${o}" must be an integer index for array.`]);a[e]=n}else a[o]=n;return i}function B(e,t){let n=R(t);if(n.length===0)throw new N(`invalid-path`,[`Patch path must not be empty.`]);let r={...e},i=r;for(let e=0;e<n.length-1;e+=1){let t=n[e];if(Array.isArray(i)){let e=Number(t);if(!Number.isInteger(e))return r;let n=i[e];if(!P(n)&&!Array.isArray(n))return r;let a=Array.isArray(n)?[...n]:{...n};i[e]=a,i=a;continue}let a=i[t];if(!P(a)&&!Array.isArray(a))return r;let o=Array.isArray(a)?[...a]:{...a};i[t]=o,i=o}let a=n[n.length-1];if(Array.isArray(i)){let e=Number(a);Number.isInteger(e)&&i.splice(e,1)}else delete i[a];return r}function V(e,t){let n=e;for(let e of t)n=e.op===`set`?z(n,e.path,e.value):B(n,e.path);return n}function H(e){let t=[];if(`autoIndex`in e&&e.autoIndex!==void 0&&typeof e.autoIndex!=`boolean`&&t.push(`autoIndex must be a boolean.`),`serverName`in e&&e.serverName!==void 0&&typeof e.serverName!=`string`&&t.push(`serverName must be a string.`),`toolPrefix`in e&&e.toolPrefix!==void 0&&typeof e.toolPrefix!=`string`&&t.push(`toolPrefix must be a string.`),`indexMode`in e&&e.indexMode!==void 0&&![`auto`,`manual`,`smart`].includes(e.indexMode)&&t.push(`indexMode must be one of: auto, manual, smart.`),(!Array.isArray(e.sources)||e.sources.length===0)&&t.push(`sources must be a non-empty array.`),`indexing`in e&&e.indexing!==void 0)if(!P(e.indexing))t.push(`indexing must be an object.`);else for(let n of[`chunkSize`,`chunkOverlap`,`minChunkSize`,`concurrency`]){let r=e.indexing[n];r!==void 0&&(typeof r!=`number`||!Number.isFinite(r)||r<=0)&&t.push(`indexing.${n} must be a positive number.`)}return`store`in e&&e.store!==void 0&&(P(e.store)?(typeof e.store.backend!=`string`&&t.push(`store.backend must be a string.`),typeof e.store.path!=`string`&&t.push(`store.path must be a string.`)):t.push(`store must be an object.`)),t}const U=l.object({ops:l.array(l.object({op:l.enum([`set`,`unset`]),path:l.string().min(1),value:l.unknown().optional()})).min(1)}),W=l.string().min(1).regex(/^[A-Za-z_][A-Za-z0-9_]*$/,`Invalid env key`),G=l.object({value:l.string(),scope:l.enum([`workspace`,`global`])}),K=l.enum([`workspace`,`global`]);function q(e,t,n,r){e.status(t).json({error:n,details:r})}function J(e){let t=u(),r=e.workspaceRoot??A;return t.get(`/status`,(t,i)=>{let a=r(),o=F(a);i.json({mode:j(),cwd:process.cwd(),workspaceRoot:a,configPath:o,configExists:n(o),globalDataDir:M(),envPaths:{workspace:C(a),global:w()},mcp:e.mcpInfo?.()??{transport:`http`,pid:process.pid,startedAt:new Date(0).toISOString()}})}),t.get(`/schema`,(e,t)=>{t.json({config:d,env:f})}),t.get(`/config`,(e,t)=>{let n=F(r());try{let e=I(n);t.json({path:n,exists:e!==null,content:e??{}})}catch(e){if(e instanceof N){q(t,400,e.message,e.details);return}q(t,500,`config-read-failed`,e instanceof Error?e.message:String(e))}}),t.patch(`/config`,(t,n)=>{let i=U.safeParse(t.body);if(!i.success){q(n,400,`invalid-body`,i.error.issues);return}let a=F(r()),o;try{o=I(a)??{}}catch(e){if(e instanceof N){q(n,400,e.message,e.details);return}q(n,500,`config-read-failed`,e instanceof Error?e.message:String(e));return}let s;try{s=V(o,i.data.ops)}catch(e){if(e instanceof N){q(n,400,e.message,e.details);return}q(n,400,`patch-failed`,e instanceof Error?e.message:String(e));return}let c=H(s);if(c.length>0){q(n,400,`invalid-config`,c);return}try{L(a,s)}catch(e){q(n,500,`config-write-failed`,e instanceof Error?e.message:String(e));return}e.log.info(`Settings: config updated`,{path:a,ops:i.data.ops.length}),n.json({path:a,content:s,restartRecommended:!0})}),t.get(`/env`,(t,n)=>{let i=t.query.reveal===`true`||t.query.reveal===`1`;i&&e.log.warn(`Settings: env values revealed`,{ip:t.ip??`unknown`});let a=r();n.json({workspace:O(`workspace`,a,{reveal:i}),global:O(`global`,a,{reveal:i}),processOverrides:Object.keys(process.env).filter(e=>e.startsWith(`AIKIT_`)||/^(SEARXNG_URL|GOOGLE_|BRAVE_|BING_)/.test(e)).sort()})}),t.put(`/env/:key`,(t,n)=>{let i=W.safeParse(t.params.key);if(!i.success){q(n,400,`invalid-key`,i.error.issues);return}let a=G.safeParse(t.body);if(!a.success){q(n,400,`invalid-body`,a.error.issues);return}let o=a.data.scope,s=T(o,r());try{D(s,x(E(s),i.data,a.data.value)),e.log.info(`Settings: env set`,{key:i.data,scope:o,path:s}),n.json({ok:!0,scope:o,path:s,restartRecommended:!0})}catch(e){q(n,500,`env-write-failed`,e instanceof Error?e.message:String(e))}}),t.delete(`/env/:key`,(t,n)=>{let i=W.safeParse(t.params.key);if(!i.success){q(n,400,`invalid-key`,i.error.issues);return}let a=K.safeParse(t.query.scope);if(!a.success){q(n,400,`invalid-scope`,a.error.issues);return}let o=a.data,s=T(o,r());try{D(s,S(E(s),i.data)),e.log.info(`Settings: env unset`,{key:i.data,scope:o,path:s}),n.json({ok:!0,scope:o,path:s,restartRecommended:!0})}catch(e){q(n,500,`env-write-failed`,e instanceof Error?e.message:String(e))}}),t}export{J as createSettingsRouter};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{
|
|
2
|
+
import{getGlobalDataDir as e,isUserInstalled as t}from"../../core/dist/index.js";import{existsSync as n,mkdirSync as r,readFileSync as i,renameSync as a,writeFileSync as o}from"node:fs";import{dirname as s,resolve as c}from"node:path";import{z as l}from"zod";import{Router as u}from"express";const d=[{key:`serverName`,type:`string`,default:`aikit`,description:`MCP server name advertised to clients.`,group:`general`,requiresRestart:!0},{key:`toolPrefix`,type:`string`,default:``,description:`Prefix prepended to every MCP tool name (e.g. "aikit_").`,group:`general`,requiresRestart:!0},{key:`toolProfile`,type:`string`,default:`full`,description:`Active tool profile.`,group:`general`,enum:[`full`,`safe`,`research`,`minimal`,`discovery`],requiresRestart:!0},{key:`autoIndex`,type:`boolean`,default:!1,description:`Deprecated. Prefer indexMode. true → auto, false → manual.`,group:`indexing`},{key:`indexMode`,type:`string`,default:`smart`,description:`Indexing strategy. auto = full on startup, manual = on demand, smart = on-demand + idle.`,group:`indexing`,enum:[`auto`,`manual`,`smart`]},{key:`sources`,type:`array`,description:`Source roots to index. Each entry has { path, excludePatterns }.`,group:`indexing`,requiresRestart:!0},{key:`indexing.chunkSize`,type:`number`,default:1500,description:`Maximum chunk size in characters.`,group:`indexing`},{key:`indexing.chunkOverlap`,type:`number`,default:200,description:`Overlap between adjacent chunks.`,group:`indexing`},{key:`indexing.minChunkSize`,type:`number`,default:100,description:`Minimum chunk size before merging into the next chunk.`,group:`indexing`},{key:`indexing.concurrency`,type:`number`,description:`Max files processed concurrently. Defaults to half of CPU cores.`,group:`indexing`},{key:`embedding.model`,type:`string`,default:`mixedbread-ai/mxbai-embed-large-v1`,description:`Embedding model identifier.`,group:`embedding`,requiresRestart:!0},{key:`embedding.dimensions`,type:`number`,default:1024,description:`Embedding vector dimensions. Must match the model.`,group:`embedding`,requiresRestart:!0},{key:`store.backend`,type:`string`,default:`sqlite-vec`,description:`Vector store backend (sqlite-vec | lancedb).`,group:`store`,requiresRestart:!0},{key:`store.path`,type:`string`,description:`Filesystem path for the vector store.`,group:`store`,requiresRestart:!0},{key:`curated.path`,type:`string`,description:`Path to curated knowledge directory.`,group:`store`,requiresRestart:!0},{key:`onboardDir`,type:`string`,description:`Directory for onboard / produce_knowledge output.`,group:`store`,requiresRestart:!0},{key:`stateDir`,type:`string`,description:`Directory for session state (stash, checkpoints, etc.).`,group:`store`,requiresRestart:!0},{key:`er.enabled`,type:`boolean`,default:!1,description:`Enable enterprise RAG bridge integration.`,group:`enterprise-bridge`,requiresRestart:!0},{key:`er.baseUrl`,type:`string`,description:`Base URL of the ER API.`,group:`enterprise-bridge`,requiresRestart:!0},{key:`er.timeoutMs`,type:`number`,default:5e3,description:`ER request timeout in milliseconds.`,group:`enterprise-bridge`},{key:`er.fallbackThreshold`,type:`number`,default:.45,description:`Vector similarity threshold below which ER fallback triggers.`,group:`enterprise-bridge`}],f=[{key:`AIKIT_TRANSPORT`,type:`string`,default:`stdio`,description:`MCP transport mode.`,group:`transport`,enum:[`stdio`,`http`],defaultScope:`workspace`},{key:`AIKIT_PORT`,type:`string`,default:`3210`,description:`HTTP port when transport = http.`,group:`transport`,defaultScope:`workspace`},{key:`AIKIT_CORS_ORIGIN`,type:`string`,description:`CORS Access-Control-Allow-Origin header for HTTP mode.`,group:`transport`,defaultScope:`workspace`},{key:`AIKIT_CONFIG_PATH`,type:`string`,description:`Override path to aikit.config.json.`,group:`paths`,defaultScope:`workspace`},{key:`AIKIT_WORKSPACE_ROOT`,type:`string`,description:`Override workspace root used when no config file is present.`,group:`paths`,defaultScope:`workspace`},{key:`AIKIT_GLOBAL_DATA_DIR`,type:`string`,description:`Override global data directory (default: ~/.aikit).`,group:`paths`,defaultScope:`global`},{key:`AIKIT_INDEX_MODE`,type:`string`,description:`Override config indexMode.`,group:`indexing`,enum:[`auto`,`manual`,`smart`],defaultScope:`workspace`},{key:`AIKIT_AUTO_INDEX`,type:`string`,description:`Legacy boolean override. Prefer AIKIT_INDEX_MODE.`,group:`indexing`,enum:[`true`,`false`],defaultScope:`workspace`},{key:`AIKIT_TOOLSET`,type:`string`,description:`Override active tool profile.`,group:`general`,defaultScope:`workspace`},{key:`AIKIT_BROWSER_DEFAULT_MODE`,type:`string`,default:`ui`,description:`Default browser launch mode for browser_* tools.`,group:`browser`,enum:[`ui`,`headless`,`panel`],defaultScope:`workspace`},{key:`AIKIT_BROWSER_PATH`,type:`string`,description:`Optional Playwright browser download path override.`,group:`browser`,defaultScope:`workspace`},{key:`AIKIT_BROWSER_IDLE_MINUTES`,type:`string`,default:`10`,description:`Idle shutdown timeout in minutes for the shared browser runtime.`,group:`browser`,defaultScope:`workspace`},{key:`AIKIT_BROWSER_EVAL_TIMEOUT_MS`,type:`string`,default:`5000`,description:`Default browser_eval timeout in milliseconds.`,group:`browser`,defaultScope:`workspace`},{key:`AIKIT_SEARCH_DEADLINE_MS`,type:`string`,default:`10000`,description:`Multi-provider web search deadline (milliseconds).`,group:`search-providers`,defaultScope:`global`},{key:`SEARXNG_URL`,type:`string`,description:`Optional SearXNG instance URL for the web_search tool.`,group:`search-providers`,defaultScope:`global`},{key:`GOOGLE_API_KEY`,type:`secret`,description:`Google Custom Search API key.`,group:`search-providers`,defaultScope:`global`},{key:`GOOGLE_CSE_ID`,type:`string`,description:`Google Custom Search Engine ID.`,group:`search-providers`,defaultScope:`global`},{key:`BRAVE_API_KEY`,type:`secret`,description:`Brave Search API key.`,group:`search-providers`,defaultScope:`global`},{key:`BING_API_KEY`,type:`secret`,description:`Bing Web Search API key.`,group:`search-providers`,defaultScope:`global`}];function p(e){return f.find(t=>t.key===e)}function m(e){let t=p(e);return t?t.type===`secret`:/(_KEY|_TOKEN|_SECRET|_PASSWORD|_PASS|_PWD)$/i.test(e)}const h=/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=(.*)$/;function g(e){let t=e.replace(/^\s+/,``);if(t.startsWith(`"`)){let e=1,n=``;for(;e<t.length;){let r=t[e];if(r===`\\`&&e+1<t.length){let r=t[e+1];r===`n`?n+=`
|
|
3
3
|
`:r===`r`?n+=`\r`:r===`t`?n+=` `:n+=r,e+=2;continue}if(r===`"`){let r=t.slice(e+1),i=r.indexOf(`#`),a=i===-1?``:r.slice(i);return{value:n,quoted:!0,inlineComment:a}}n+=r,e+=1}return{value:t.slice(1),quoted:!0,inlineComment:``}}let n=t.match(/(\s+#.*)$/);return n&&n.index!==void 0?{value:t.slice(0,n.index).trimEnd(),quoted:!1,inlineComment:n[1].trimStart()}:{value:t.trimEnd(),quoted:!1,inlineComment:``}}function _(e){let t;t=e.quoted||/[\s#"']/.test(e.value)||e.value.includes(`
|
|
4
4
|
`)||e.value.length===0?`"${e.value.replace(/\\/g,`\\\\`).replace(/"/g,`\\"`).replace(/\n/g,`\\n`).replace(/\r/g,`\\r`).replace(/\t/g,`\\t`)}"`:e.value;let n=e.inlineComment?` ${e.inlineComment}`:``;return`${e.key}=${t}${n}`}function v(e){let t=[],n=e.split(/\r?\n/),r=e.endsWith(`
|
|
5
5
|
`)?n.slice(0,-1):n;for(let e of r){let n=e.match(h);if(!n){t.push({kind:`raw`,text:e});continue}let r=n[1],{value:i,quoted:a,inlineComment:o}=g(n[2]);t.push({kind:`assign`,key:r,value:i,quoted:a,inlineComment:o})}return{lines:t}}function y(e){return`${e.lines.map(e=>e.kind===`assign`?_(e):e.text).join(`
|
|
6
|
-
`)}\n`}function b(e){let t={};for(let n of e.lines)n.kind===`assign`&&(t[n.key]=n.value);return t}function x(e,t,n){let r=e.lines.map(e=>e.kind===`assign`&&e.key===t?{...e,value:n}:e);return e.lines.some(e=>e.kind===`assign`&&e.key===t)||r.push({kind:`assign`,key:t,value:n,quoted:!1,inlineComment:``}),{lines:r}}function S(e,t){return{lines:e.lines.filter(e=>!(e.kind===`assign`&&e.key===t))}}function C(e){return
|
|
6
|
+
`)}\n`}function b(e){let t={};for(let n of e.lines)n.kind===`assign`&&(t[n.key]=n.value);return t}function x(e,t,n){let r=e.lines.map(e=>e.kind===`assign`&&e.key===t?{...e,value:n}:e);return e.lines.some(e=>e.kind===`assign`&&e.key===t)||r.push({kind:`assign`,key:t,value:n,quoted:!1,inlineComment:``}),{lines:r}}function S(e,t){return{lines:e.lines.filter(e=>!(e.kind===`assign`&&e.key===t))}}function C(e){return c(e,`.env`)}function w(){return c(e(),`global.env`)}function T(e,t){return e===`workspace`?C(t):w()}function E(e){return n(e)?v(i(e,`utf-8`)):{lines:[]}}function D(e,t){let i=s(e);n(i)||r(i,{recursive:!0});let c=`${e}.${process.pid}.${Date.now()}.tmp`;o(c,y(t),{encoding:`utf-8`,mode:384}),a(c,e)}function O(e,t,r={}){let i=T(e,t),a=n(i),o=b(E(i)),s={};for(let[e,t]of Object.entries(o))s[e]=r.reveal||!m(e)?t:k(t);return{scope:e,path:i,exists:a,vars:s}}function k(e){return e.length===0?``:e.length<=4?`•`.repeat(e.length):`${e.slice(0,2)}${`•`.repeat(Math.min(e.length-4,12))}${e.slice(-2)}`}function A(){return process.env.AIKIT_WORKSPACE_ROOT??process.cwd()}function j(){return t()?`user`:`workspace`}function M(){let t=e();return n(t)||r(t,{recursive:!0}),t}var N=class extends Error{details;constructor(e,t){super(e),this.name=`ConfigValidationError`,this.details=t}};function P(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function F(e=A()){let t=process.env.AIKIT_CONFIG_PATH;return t?c(t):c(e,`aikit.config.json`)}function I(e){if(!n(e))return null;let t=i(e,`utf-8`),r=JSON.parse(t);if(!P(r))throw new N(`config-not-object`,[`Config file must contain a JSON object at the root.`]);return r}function L(e,t){let i=s(e);n(i)||r(i,{recursive:!0});let c=`${JSON.stringify(t,null,2)}\n`,l=`${e}.${process.pid}.${Date.now()}.tmp`;o(l,c,{encoding:`utf-8`}),a(l,e)}function R(e){return e.length===0?[]:e.split(`.`)}function z(e,t,n){let r=R(t);if(r.length===0)throw new N(`invalid-path`,[`Patch path must not be empty.`]);let i={...e},a=i;for(let e=0;e<r.length-1;e+=1){let t=r[e],n=r[e+1],i=/^\d+$/.test(n);if(Array.isArray(a)){let n=Number(t);if(!Number.isInteger(n))throw new N(`invalid-path`,[`Path segment "${t}" must be an integer index for array at depth ${e}.`]);let r=a[n];if(i){let e=Array.isArray(r)?[...r]:[];a[n]=e,a=e}else{let e=P(r)?{...r}:{};a[n]=e,a=e}continue}let o=a[t];if(i){let e=Array.isArray(o)?[...o]:[];a[t]=e,a=e}else{let e=P(o)?{...o}:{};a[t]=e,a=e}}let o=r[r.length-1];if(Array.isArray(a)){let e=Number(o);if(!Number.isInteger(e))throw new N(`invalid-path`,[`Path segment "${o}" must be an integer index for array.`]);a[e]=n}else a[o]=n;return i}function B(e,t){let n=R(t);if(n.length===0)throw new N(`invalid-path`,[`Patch path must not be empty.`]);let r={...e},i=r;for(let e=0;e<n.length-1;e+=1){let t=n[e];if(Array.isArray(i)){let e=Number(t);if(!Number.isInteger(e))return r;let n=i[e];if(!P(n)&&!Array.isArray(n))return r;let a=Array.isArray(n)?[...n]:{...n};i[e]=a,i=a;continue}let a=i[t];if(!P(a)&&!Array.isArray(a))return r;let o=Array.isArray(a)?[...a]:{...a};i[t]=o,i=o}let a=n[n.length-1];if(Array.isArray(i)){let e=Number(a);Number.isInteger(e)&&i.splice(e,1)}else delete i[a];return r}function V(e,t){let n=e;for(let e of t)n=e.op===`set`?z(n,e.path,e.value):B(n,e.path);return n}function H(e){let t=[];if(`autoIndex`in e&&e.autoIndex!==void 0&&typeof e.autoIndex!=`boolean`&&t.push(`autoIndex must be a boolean.`),`serverName`in e&&e.serverName!==void 0&&typeof e.serverName!=`string`&&t.push(`serverName must be a string.`),`toolPrefix`in e&&e.toolPrefix!==void 0&&typeof e.toolPrefix!=`string`&&t.push(`toolPrefix must be a string.`),`indexMode`in e&&e.indexMode!==void 0&&![`auto`,`manual`,`smart`].includes(e.indexMode)&&t.push(`indexMode must be one of: auto, manual, smart.`),(!Array.isArray(e.sources)||e.sources.length===0)&&t.push(`sources must be a non-empty array.`),`indexing`in e&&e.indexing!==void 0)if(!P(e.indexing))t.push(`indexing must be an object.`);else for(let n of[`chunkSize`,`chunkOverlap`,`minChunkSize`,`concurrency`]){let r=e.indexing[n];r!==void 0&&(typeof r!=`number`||!Number.isFinite(r)||r<=0)&&t.push(`indexing.${n} must be a positive number.`)}return`store`in e&&e.store!==void 0&&(P(e.store)?(typeof e.store.backend!=`string`&&t.push(`store.backend must be a string.`),typeof e.store.path!=`string`&&t.push(`store.path must be a string.`)):t.push(`store must be an object.`)),t}const U=l.object({ops:l.array(l.object({op:l.enum([`set`,`unset`]),path:l.string().min(1),value:l.unknown().optional()})).min(1)}),W=l.string().min(1).regex(/^[A-Za-z_][A-Za-z0-9_]*$/,`Invalid env key`),G=l.object({value:l.string(),scope:l.enum([`workspace`,`global`])}),K=l.enum([`workspace`,`global`]);function q(e,t,n,r){e.status(t).json({error:n,details:r})}function J(e){let t=u(),r=e.workspaceRoot??A;return t.get(`/status`,(t,i)=>{let a=r(),o=F(a);i.json({mode:j(),cwd:process.cwd(),workspaceRoot:a,configPath:o,configExists:n(o),globalDataDir:M(),envPaths:{workspace:C(a),global:w()},mcp:e.mcpInfo?.()??{transport:`http`,pid:process.pid,startedAt:new Date(0).toISOString()}})}),t.get(`/schema`,(e,t)=>{t.json({config:d,env:f})}),t.get(`/config`,(e,t)=>{let n=F(r());try{let e=I(n);t.json({path:n,exists:e!==null,content:e??{}})}catch(e){if(e instanceof N){q(t,400,e.message,e.details);return}q(t,500,`config-read-failed`,e instanceof Error?e.message:String(e))}}),t.patch(`/config`,(t,n)=>{let i=U.safeParse(t.body);if(!i.success){q(n,400,`invalid-body`,i.error.issues);return}let a=F(r()),o;try{o=I(a)??{}}catch(e){if(e instanceof N){q(n,400,e.message,e.details);return}q(n,500,`config-read-failed`,e instanceof Error?e.message:String(e));return}let s;try{s=V(o,i.data.ops)}catch(e){if(e instanceof N){q(n,400,e.message,e.details);return}q(n,400,`patch-failed`,e instanceof Error?e.message:String(e));return}let c=H(s);if(c.length>0){q(n,400,`invalid-config`,c);return}try{L(a,s)}catch(e){q(n,500,`config-write-failed`,e instanceof Error?e.message:String(e));return}e.log.info(`Settings: config updated`,{path:a,ops:i.data.ops.length}),n.json({path:a,content:s,restartRecommended:!0})}),t.get(`/env`,(t,n)=>{let i=t.query.reveal===`true`||t.query.reveal===`1`;i&&e.log.warn(`Settings: env values revealed`,{ip:t.ip??`unknown`});let a=r();n.json({workspace:O(`workspace`,a,{reveal:i}),global:O(`global`,a,{reveal:i}),processOverrides:Object.keys(process.env).filter(e=>e.startsWith(`AIKIT_`)||/^(SEARXNG_URL|GOOGLE_|BRAVE_|BING_)/.test(e)).sort()})}),t.put(`/env/:key`,(t,n)=>{let i=W.safeParse(t.params.key);if(!i.success){q(n,400,`invalid-key`,i.error.issues);return}let a=G.safeParse(t.body);if(!a.success){q(n,400,`invalid-body`,a.error.issues);return}let o=a.data.scope,s=T(o,r());try{D(s,x(E(s),i.data,a.data.value)),e.log.info(`Settings: env set`,{key:i.data,scope:o,path:s}),n.json({ok:!0,scope:o,path:s,restartRecommended:!0})}catch(e){q(n,500,`env-write-failed`,e instanceof Error?e.message:String(e))}}),t.delete(`/env/:key`,(t,n)=>{let i=W.safeParse(t.params.key);if(!i.success){q(n,400,`invalid-key`,i.error.issues);return}let a=K.safeParse(t.query.scope);if(!a.success){q(n,400,`invalid-scope`,a.error.issues);return}let o=a.data,s=T(o,r());try{D(s,S(E(s),i.data)),e.log.info(`Settings: env unset`,{key:i.data,scope:o,path:s}),n.json({ok:!0,scope:o,path:s,restartRecommended:!0})}catch(e){q(n,500,`env-write-failed`,e instanceof Error?e.message:String(e))}}),t}export{J as createSettingsRouter};
|