@vpxa/aikit 0.1.400 → 0.1.401

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/aikit",
3
- "version": "0.1.400",
3
+ "version": "0.1.401",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -66,6 +66,16 @@ interface AgentBrowserResult {
66
66
  stderr: string;
67
67
  exitCode: number;
68
68
  }
69
+ interface AgentBrowserExecDiagnostics {
70
+ timestamp: string;
71
+ binaryPath: string;
72
+ resolvedBinaryPath: string;
73
+ args: string[];
74
+ usedShell: boolean;
75
+ displayCommand: string;
76
+ exitCode?: number;
77
+ error?: string;
78
+ }
69
79
  //#endregion
70
80
  //#region packages/browser/src/session.d.ts
71
81
  /**
@@ -139,6 +149,7 @@ declare class BrowserEngine {
139
149
  private _currentMode;
140
150
  private _isLaunched;
141
151
  private idleTimer;
152
+ private _lastExecDiagnostics;
142
153
  readonly tabs: TabRegistry;
143
154
  private config;
144
155
  constructor(config?: Partial<BrowserConfig>);
@@ -149,10 +160,10 @@ declare class BrowserEngine {
149
160
  * Returns stdout/stderr/exitCode.
150
161
  */
151
162
  exec(command: string, ...args: string[]): Promise<AgentBrowserResult>;
163
+ getLastExecDiagnostics(): AgentBrowserExecDiagnostics | null;
164
+ private execWithDiagnostics;
152
165
  /** Run a command and resolve on process exit so child-owned browser pipes cannot keep us alive. */
153
166
  private execViaSpawn;
154
- /** Run a command through the platform shell for Windows command wrappers. */
155
- private execViaShell;
156
167
  /**
157
168
  * Execute a command scoped to a specific tab.
158
169
  * Prepends "tab <tabId>" to the command automatically.
@@ -278,4 +289,4 @@ declare function validateEvalResult(result: string, maxBytes: number): {
278
289
  //#region packages/browser/src/tools/index.d.ts
279
290
  declare function registerBrowserTools(server: McpServer, config: Record<string, unknown>): void;
280
291
  //#endregion
281
- export { AgentBrowserEngine, AgentBrowserResult, BrowserConfig, BrowserEngine, BrowserMode, DEFAULT_BROWSER_CONFIG, EvalValidationResult, PageInfo, SecurityCheckResult, SessionRegistry, TabInfo, TabRegistry, autoSelectMode, closeEngine, ensureAgentBrowserInstalled, getAgentBrowserVersion, getDaemonArgs, getDefaultBrowsersPath, getEngine, getLaunchArgs, isBrowserReady, isUrlAllowed, registerBrowserTools, resolveBrowsersPath, validateEvalResult };
292
+ export { AgentBrowserEngine, AgentBrowserExecDiagnostics, AgentBrowserResult, BrowserConfig, BrowserEngine, BrowserMode, DEFAULT_BROWSER_CONFIG, EvalValidationResult, PageInfo, SecurityCheckResult, SessionRegistry, TabInfo, TabRegistry, autoSelectMode, closeEngine, ensureAgentBrowserInstalled, getAgentBrowserVersion, getDaemonArgs, getDefaultBrowsersPath, getEngine, getLaunchArgs, isBrowserReady, isUrlAllowed, registerBrowserTools, resolveBrowsersPath, validateEvalResult };
@@ -1,4 +1,4 @@
1
- import{exec as e,execFileSync as t,execSync as n,spawn as r}from"node:child_process";import{closeSync as i,copyFileSync as a,existsSync as o,mkdirSync as s,openSync as c,readFileSync as l,readdirSync as u,unlinkSync as d,writeFileSync as f}from"node:fs";import{homedir as p,platform as m,tmpdir as h}from"node:os";import{dirname as g,join as _}from"node:path";import{z as v}from"zod";const y=`0.26.0`,b=`.agent-browser-version`;function x(e){return typeof e==`string`?e.trim():e instanceof Buffer?e.toString(`utf8`).trim():``}function S(){return _(p(),`.aikit`,`browsers`)}function C(e){return e.browsersPath??process.env.AIKIT_BROWSER_PATH??process.env.AIKIT_BROWSER_BROWSERS_PATH??S()}function w(){try{let e=n(`${m()===`win32`?`where`:`which`} agent-browser`,{encoding:`utf8`,windowsHide:!0,stdio:`pipe`,timeout:3e3}).trim().split(/\r?\n/).filter(Boolean);if(e.length===0)return null;if(m()===`win32`){for(let t of e){if(t.endsWith(`.exe`)&&o(t))return t;let e=_(g(t),`node_modules`,`agent-browser`,`bin`,`agent-browser-win32-x64.exe`);if(o(e))return e}for(let t of e){if(o(`${t}.exe`))return`${t}.exe`;if(o(`${t}.cmd`))return`${t}.cmd`;if(o(`${t}.bat`))return`${t}.bat`}}let t=e[0];return o(t)?t:null}catch{return null}}function T(e){return _(e,`agent-browser`,ee())}function ee(){switch(m()){case`win32`:return`agent-browser.exe`;default:return`agent-browser`}}function te(e,t){try{f(_(e,b),t,`utf8`)}catch{}}function ne(e){try{return l(_(e,b),`utf8`).trim()}catch{return null}}function re(e){let t=ne(e);return t?ie(t,y)>=0:!1}function ie(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<Math.max(n.length,r.length);e++){let t=n[e]||0,i=r[e]||0;if(t!==i)return t-i}return 0}function ae(e){return!!(o(_(e,`chrome`))||o(_(p(),`.cache`,`agent-browser`,`chrome`)))}async function oe(t,r){let i=w();if(i)return r?.(`Using globally installed agent-browser`),i;let c=C(t);o(c)||s(c,{recursive:!0});let l=T(c);if(o(l)&&re(c))return r?.(`Using cached agent-browser at ${l}`),l;r?.(`Downloading agent-browser (first use)...`),await new Promise((t,n)=>{let r=new AbortController,i=setTimeout(()=>r.abort(),12e4),a=e(`npx -y agent-browser@latest install --install-dir "${c}"`,{timeout:12e4,windowsHide:!0,encoding:`utf8`,env:{...process.env,AGENT_BROWSER_CACHE_DIR:c},signal:r.signal},(e,r,a)=>{if(clearTimeout(i),e){let t=x(a)||e.message||`Unknown agent-browser install failure`;n(Error(`Failed to install agent-browser: ${t}`));return}t()});a.stdin&&a.stdin.destroy()});let d=l;try{let e=n(m()===`win32`?`npx -y -p agent-browser node -e "process.stdout.write(__dirname)"`:`npx -y -p agent-browser which agent-browser 2>/dev/null || true`,{encoding:`utf8`,timeout:15e3,windowsHide:!0,stdio:`pipe`}).trim(),t=m()===`win32`?`agent-browser-win32-x64.exe`:m()===`darwin`?process.arch===`arm64`?`agent-browser-darwin-arm64`:`agent-browser-darwin-x64`:`agent-browser-linux-${process.arch===`arm64`?`arm64`:`x64`}`,i=[];e&&!e.includes(`MODULE_NOT_FOUND`)&&(i.push(e),i.push(_(e,`..`)));try{let e=_(n(`npm config get cache`,{encoding:`utf8`,timeout:5e3,windowsHide:!0,stdio:`pipe`}).trim(),`_npx`);if(o(e)){let n=u(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory())continue;let n=_(e,r.name,`node_modules`,`agent-browser`);if(o(_(n,`bin`,t))){i.push(n);break}}}}catch{}for(let e of i){let n=_(e,`bin`,t);if(o(n)){let t=_(c,`agent-browser`);o(t)||s(t,{recursive:!0});let i=T(c);a(n,i);let l=_(e,`bin`,`agent-browser.js`);o(l)&&a(l,_(t,`agent-browser.js`)),te(c,y),d=i,r?.(`Cached agent-browser at ${i}`);break}}}catch{}return r?.(`agent-browser ready`),d}async function se(e){try{return t(e,[`--version`],{encoding:`utf8`,windowsHide:!0,stdio:`pipe`,timeout:5e3}).trim()}catch{return null}}function ce(e){if(w())return!0;let t=C(e);return ae(t)||o(T(t))}const le=[`ui`,`headless`];function ue(e){return le.includes(e)?e:`headless`}function de(e){let t=[];return e===`headless`&&t.push(`--headless`),t}function fe(e){return{headless:e===`headless`,args:de(e)}}var E=class{tabs=new Map;labelToId=new Map;register(e,t,n,r){return this.tabs.set(e,{tabId:e,url:t,title:n??t,label:r,createdAt:new Date}),r&&this.labelToId.set(r,e),e}resolve(e){return this.tabs.has(e)?e:this.labelToId.get(e)||e}getTab(e){let t=this.tabs.get(e);if(!t)throw Error(`Tab not found: ${e}`);return t}updateTabInfo(e,t,n){let r=this.tabs.get(e);r&&this.tabs.set(e,{...r,url:t,title:n})}setSnapshot(e,t){let n=this.tabs.get(e);n&&this.tabs.set(e,{...n,snapshot:t})}getSnapshot(e){return this.tabs.get(e)?.snapshot}async removeTab(e){let t=this.tabs.get(e);t&&(t.label&&this.labelToId.delete(t.label),this.tabs.delete(e))}listTabs(){return[...this.tabs.values()]}listPages(){return this.listTabs().map(e=>({pageId:e.tabId,url:e.url,title:e.title,label:e.label,createdAt:e.createdAt}))}async closeAll(){this.tabs.clear(),this.labelToId.clear()}clear(){this.tabs.clear(),this.labelToId.clear()}get size(){return this.tabs.size}},pe=class{tabs=new E;registerPage(e,t,n,r){return this.tabs.register(e,t,n,r)}getPage(e){throw Error(`Direct Playwright Page access no longer supported with agent-browser. Use engine.exec() or engine.tabExec() for browser operations.`)}getPageInfo(e){let t=this.tabs.getTab(e);return{pageId:t.tabId,url:t.url,title:t.title,label:t.label,createdAt:t.createdAt}}resolvePageId(e){return this.tabs.resolve(e)}setSnapshot(e,t){this.tabs.setSnapshot(e,t)}getSnapshot(e){return this.tabs.getSnapshot(e)}updatePageInfo(e,t,n){this.tabs.updateTabInfo(e,t,n)}async removePage(e){await this.tabs.removeTab(e)}listPages(){return this.tabs.listPages()}async closeAll(){await this.tabs.closeAll()}get size(){return this.tabs.size}};const D={defaultMode:`ui`,browsersPath:null,userDataDirRoot:null,idleShutdownMinutes:0,allowInternalSchemes:!1,allowLoopback:!1,evalTimeoutMs:3e4,evalMaxResultBytes:262144,redactPasswordFieldsInScreenshots:!0,engine:`chrome`};function me(e){if(e.endsWith(`.exe`))return e;let t=_(g(e),`node_modules`,`agent-browser`,`bin`,`agent-browser-win32-x64.exe`);if(o(t))return t;if(!e.endsWith(`.cmd`)&&!e.endsWith(`.bat`)){if(o(`${e}.exe`))return`${e}.exe`;if(o(`${e}.cmd`))return`${e}.cmd`;if(o(`${e}.bat`))return`${e}.bat`}return e}var O=class{binaryPath=null;_currentMode=null;_isLaunched=!1;idleTimer=null;tabs=new E;config;constructor(e={}){this.config={...D,...e}}get currentMode(){return this._currentMode}async launch(e,t){let n=ue(e??this.config.defaultMode);if(!(this._isLaunched&&this._currentMode===n)){this._isLaunched&&this._currentMode!==n&&await this.close(),this._currentMode=n,this.binaryPath=await oe(this.config,t);try{let e=await this.exec(`--version`);t?.(`agent-browser ${e.stdout.trim()}`)}catch(e){throw Error(`agent-browser binary failed: ${e instanceof Error?e.message:String(e)}`)}this._isLaunched=!0,this.resetIdleTimer()}}async exec(e,...t){if(!this.binaryPath)throw Error(`agent-browser not launched. Call launch() first, or use getEngine() singleton.`);let n=this.binaryPath;m()===`win32`&&(n=me(n));let r=[e,...t];if(m()===`win32`&&(n.endsWith(`.cmd`)||n.endsWith(`.bat`))){let e=`"${n}" ${r.map(e=>/[^\w/:@.\-_{}()/\\]/.test(e)?`"${e.replace(/"/g,`""`)}"`:e).join(` `)}`;return await this.execViaShell(e)}return await this.execViaSpawn(n,r)}execViaSpawn(e,t,n={}){return new Promise((a,o)=>{let s=n.displayCommand??[e,...t].join(` `),u=!1,f=!1,p,m=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,g=_(h(),`aikit-agent-browser-${m}.stdout`),v=_(h(),`aikit-agent-browser-${m}.stderr`),y=c(g,`w+`),b=c(v,`w+`),x=r(e,t,{shell:n.shell??!1,stdio:[`ignore`,y,b],windowsHide:!0});x.unref(),i(y),i(b);let S=e=>{try{d(e)}catch{}},C=()=>{let e=``,t=``;try{e=l(g,`utf8`)}catch{e=``}try{t=l(v,`utf8`)}catch{t=``}return S(g),S(v),{stdout:e,stderr:t}},w=e=>{u||(u=!0,p&&clearTimeout(p),e())};p=setTimeout(()=>{f=!0,x.kill()},this.config.evalTimeoutMs),x.once(`error`,e=>{w(()=>{if(S(g),S(v),e.code===`ENOENT`){o(Error(`agent-browser binary not found at ${this.binaryPath}`));return}o(e)})}),x.once(`exit`,(e,t)=>{w(()=>{let n=C();if(f||t){o(Error(`agent-browser command timed out after ${this.config.evalTimeoutMs}ms: `+s));return}a({stdout:n.stdout,stderr:n.stderr,exitCode:e??0})})})})}execViaShell(e){return this.execViaSpawn(e,[],{shell:!0,displayCommand:e})}async tabExec(e,t,...n){return this.exec(`tab`,e,t,...n)}async open(e,t,n){await this.launch(t);let r=this._currentMode===`ui`?[`open`,e,`--headed`,`--json`]:[`tab`,`new`,e,`--json`],i=await this.exec(...r);if(i.exitCode!==0)throw Error(`agent-browser failed to open URL (exit ${i.exitCode}): ${i.stderr||i.stdout||`Unknown error`}`);let a=k(i.stdout)??await this.readActiveTabId()??this.nextLocalTabId();return this.tabs.register(a,e,i.stdout.trim(),n),this.resetIdleTimer(),a}async screenshot(e,t){let n=t?.format??`png`,r=n===`jpeg`?`image/jpeg`:`image/png`,i=n===`jpeg`?`jpg`:`png`,a=_(t?.screenshotDir??h(),`aikit-screenshot-${Date.now()}.${i}`),o=[a];t?.fullPage&&o.push(`--full`),t?.screenshotDir&&o.push(`--screenshot-dir`,t.screenshotDir),t?.format===`jpeg`&&o.push(`--screenshot-format`,`jpeg`),t?.quality&&o.push(`--screenshot-quality`,String(t.quality)),t?.annotate&&o.push(`--annotate`),await this.tabExec(e,`screenshot`,...o);let s=l(a),c=s.toString(`base64`);try{d(a)}catch{}return this.resetIdleTimer(),{base64:c,mimeType:r,bytes:s.length}}async screenshotActiveTab(e){let t=e?.format??`png`,n=t===`jpeg`?`image/jpeg`:`image/png`,r=t===`jpeg`?`jpg`:`png`,i=_(e?.screenshotDir??h(),`aikit-screenshot-${Date.now()}.${r}`),a=[i];e?.fullPage&&a.push(`--full`),e?.screenshotDir&&a.push(`--screenshot-dir`,e.screenshotDir),e?.format===`jpeg`&&a.push(`--screenshot-format`,`jpeg`),e?.quality&&a.push(`--screenshot-quality`,String(e.quality)),e?.annotate&&a.push(`--annotate`),e?.selector&&a.push(`--element`,e.selector),await this.exec(`screenshot`,...a);let o=l(i),s=o.toString(`base64`);try{d(i)}catch{}return this.resetIdleTimer(),{base64:s,mimeType:n,bytes:o.length}}async readSnapshot(e,t=!1){let n=t?[`-c`,`--json`]:[`-i`,`--json`],r=await this.tabExec(e,`snapshot`,...n);return this.resetIdleTimer(),r.stdout}async navigate(e,t){let n=await this.tabExec(e,`goto`,t);return this.resetIdleTimer(),n}async close(){this.stopIdleTimer(),this._isLaunched&&(await this.closeRuntimeSession(),this.tabs.clear(),this._isLaunched=!1,this._currentMode=null)}isLaunched(){return this._isLaunched}getConfig(){return this.config}getBinaryPath(){return this.binaryPath}resolvePageId(e){return this.tabs.resolve(e)}resetIdleTimer(){if(this.stopIdleTimer(),!Number.isFinite(this.config.idleShutdownMinutes)||this.config.idleShutdownMinutes<=0){this._currentMode===`ui`&&(this.idleTimer=setInterval(()=>{},6e4));return}let e=setTimeout(()=>{this.close()},this.config.idleShutdownMinutes*6e4);this._currentMode!==`ui`&&e.unref?.(),this.idleTimer=e}stopIdleTimer(){this.idleTimer&&=(clearTimeout(this.idleTimer),null)}async closeRuntimeSession(){try{await this.exec(`close`,`--all`).catch(()=>{})}catch{}}async readActiveTabId(){let e=await this.exec(`tab`,`list`,`--json`).catch(()=>null);return e?.exitCode===0?k(e.stdout):null}nextLocalTabId(){let e=this.tabs.listTabs().map(e=>/^t(\d+)$/.exec(e.tabId)?.[1]).filter(e=>e!==void 0).map(Number);return`t${e.length===0?1:Math.max(...e)+1}`}};function k(e){try{let t=JSON.parse(e);if(typeof t.data?.tabId==`string`)return t.data.tabId;let n=t.data?.tabs?.find(e=>e.active===!0);if(typeof n?.tabId==`string`)return n.tabId}catch{}return null}let A=null;function j(e){return A||=new O(e),A}async function he(){A&&=(await A.close(),null)}function M(e,t){try{let n=new URL(e),r=n.hostname.toLowerCase(),i=n.protocol.toLowerCase();return[`file:`,`chrome:`,`chrome-extension:`,`data:`,`javascript:`].includes(i)?t?.allowInternalSchemes?{allowed:!0}:{allowed:!1,reason:`Scheme '${i}' is blocked for security`}:[`169.254.169.254`,`metadata.google.internal`,`metadata.instance`].includes(r)?{allowed:!1,reason:`Cloud metadata endpoint '${r}' is blocked`}:n.hostname===`localhost`||r===`127.0.0.1`||r===`::1`||r.startsWith(`10.`)||r.startsWith(`172.`)||r.startsWith(`192.168.`)?t?.allowLoopback?{allowed:!0}:{allowed:!1,reason:`Internal host '${r}' requires allowLoopback=true`}:{allowed:!0}}catch{return{allowed:!1,reason:`Invalid URL`}}}function N(e,t){return Buffer.byteLength(e,`utf8`)<=t?{valid:!0,result:e,truncated:!1}:{valid:!0,result:`${Buffer.from(e).subarray(0,t).toString(`utf8`)}\n... [truncated]`,truncated:!0,reason:`Result exceeded ${t} bytes, truncated to ${t} bytes`}}const ge=[`ui`,`headless`];function _e(e){return typeof e==`object`&&e?e:null}function P(e){return typeof e==`string`&&e.length>0?e:void 0}function F(e){return typeof e==`boolean`?e:void 0}function I(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function L(e){return typeof e==`string`&&ge.includes(e)?e:void 0}function R(e){let t=process.env[e];if(!t)return;let n=Number(t);return Number.isFinite(n)?n:void 0}function ve(e){let t=_e(e.browser)??{};return{...D,defaultMode:L(process.env.AIKIT_BROWSER_DEFAULT_MODE)??L(t.defaultMode)??D.defaultMode,browsersPath:P(process.env.AIKIT_BROWSER_PATH)??P(process.env.AIKIT_BROWSER_BROWSERS_PATH)??P(t.browsersPath)??D.browsersPath,userDataDirRoot:P(t.userDataDirRoot)??D.userDataDirRoot,idleShutdownMinutes:R(`AIKIT_BROWSER_IDLE_MINUTES`)??I(t.idleShutdownMinutes)??D.idleShutdownMinutes,allowInternalSchemes:F(t.allowInternalSchemes)??D.allowInternalSchemes,allowLoopback:F(t.allowLoopback)??D.allowLoopback,evalTimeoutMs:R(`AIKIT_BROWSER_EVAL_TIMEOUT_MS`)??I(t.evalTimeoutMs)??D.evalTimeoutMs,evalMaxResultBytes:I(t.evalMaxResultBytes)??D.evalMaxResultBytes,redactPasswordFieldsInScreenshots:F(t.redactPasswordFieldsInScreenshots)??D.redactPasswordFieldsInScreenshots,engine:P(t.engine)??D.engine,proxy:P(t.proxy),viewport:P(t.viewport)}}function z(e,t){return{content:[{type:`text`,text:e}],structuredContent:t}}function B(e,t){let n=e.selector??e.ref??(e.element?`text=${e.element}`:void 0);if(!n)throw Error(`${t} requires selector, ref, or element`);return n}function V(e){try{let t=JSON.parse(e);if(t&&typeof t==`object`){let e=H(t);if(e.length>0)return e.join(`
1
+ import{exec as e,execFileSync as t,execSync as n,spawn as r}from"node:child_process";import{closeSync as i,copyFileSync as a,existsSync as o,mkdirSync as s,openSync as c,readFileSync as l,readdirSync as u,unlinkSync as d,writeFileSync as f}from"node:fs";import{homedir as p,platform as m,tmpdir as h}from"node:os";import{dirname as g,join as _}from"node:path";import{z as v}from"zod";const y=`0.26.0`,b=`.agent-browser-version`;function x(e){return typeof e==`string`?e.trim():e instanceof Buffer?e.toString(`utf8`).trim():``}function S(){return _(p(),`.aikit`,`browsers`)}function C(e){return e.browsersPath??process.env.AIKIT_BROWSER_PATH??process.env.AIKIT_BROWSER_BROWSERS_PATH??S()}function w(){try{let e=n(`${m()===`win32`?`where`:`which`} agent-browser`,{encoding:`utf8`,windowsHide:!0,stdio:`pipe`,timeout:3e3}).trim().split(/\r?\n/).filter(Boolean);if(e.length===0)return null;if(m()===`win32`){for(let t of e){if(t.endsWith(`.exe`)&&o(t))return t;let e=_(g(t),`node_modules`,`agent-browser`,`bin`,`agent-browser-win32-x64.exe`);if(o(e))return e}for(let t of e){if(o(`${t}.exe`))return`${t}.exe`;if(o(`${t}.cmd`))return`${t}.cmd`;if(o(`${t}.bat`))return`${t}.bat`}}let t=e[0];return o(t)?t:null}catch{return null}}function T(e){return _(e,`agent-browser`,ee())}function ee(){switch(m()){case`win32`:return`agent-browser.exe`;default:return`agent-browser`}}function te(e,t){try{f(_(e,b),t,`utf8`)}catch{}}function ne(e){try{return l(_(e,b),`utf8`).trim()}catch{return null}}function re(e){let t=ne(e);return t?ie(t,y)>=0:!1}function ie(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<Math.max(n.length,r.length);e++){let t=n[e]||0,i=r[e]||0;if(t!==i)return t-i}return 0}function ae(e){return!!(o(_(e,`chrome`))||o(_(p(),`.cache`,`agent-browser`,`chrome`)))}async function oe(t,r){let i=w();if(i)return r?.(`Using globally installed agent-browser`),i;let c=C(t);o(c)||s(c,{recursive:!0});let l=T(c);if(o(l)&&re(c))return r?.(`Using cached agent-browser at ${l}`),l;r?.(`Downloading agent-browser (first use)...`),await new Promise((t,n)=>{let r=new AbortController,i=setTimeout(()=>r.abort(),12e4),a=e(`npx -y agent-browser@latest install --install-dir "${c}"`,{timeout:12e4,windowsHide:!0,encoding:`utf8`,env:{...process.env,AGENT_BROWSER_CACHE_DIR:c},signal:r.signal},(e,r,a)=>{if(clearTimeout(i),e){let t=x(a)||e.message||`Unknown agent-browser install failure`;n(Error(`Failed to install agent-browser: ${t}`));return}t()});a.stdin&&a.stdin.destroy()});let d=l;try{let e=n(m()===`win32`?`npx -y -p agent-browser node -e "process.stdout.write(__dirname)"`:`npx -y -p agent-browser which agent-browser 2>/dev/null || true`,{encoding:`utf8`,timeout:15e3,windowsHide:!0,stdio:`pipe`}).trim(),t=m()===`win32`?`agent-browser-win32-x64.exe`:m()===`darwin`?process.arch===`arm64`?`agent-browser-darwin-arm64`:`agent-browser-darwin-x64`:`agent-browser-linux-${process.arch===`arm64`?`arm64`:`x64`}`,i=[];e&&!e.includes(`MODULE_NOT_FOUND`)&&(i.push(e),i.push(_(e,`..`)));try{let e=_(n(`npm config get cache`,{encoding:`utf8`,timeout:5e3,windowsHide:!0,stdio:`pipe`}).trim(),`_npx`);if(o(e)){let n=u(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory())continue;let n=_(e,r.name,`node_modules`,`agent-browser`);if(o(_(n,`bin`,t))){i.push(n);break}}}}catch{}for(let e of i){let n=_(e,`bin`,t);if(o(n)){let t=_(c,`agent-browser`);o(t)||s(t,{recursive:!0});let i=T(c);a(n,i);let l=_(e,`bin`,`agent-browser.js`);o(l)&&a(l,_(t,`agent-browser.js`)),te(c,y),d=i,r?.(`Cached agent-browser at ${i}`);break}}}catch{}return r?.(`agent-browser ready`),d}async function se(e){try{return t(e,[`--version`],{encoding:`utf8`,windowsHide:!0,stdio:`pipe`,timeout:5e3}).trim()}catch{return null}}function ce(e){if(w())return!0;let t=C(e);return ae(t)||o(T(t))}const le=[`ui`,`headless`];function ue(e){return le.includes(e)?e:`headless`}function de(e){let t=[];return e===`headless`&&t.push(`--headless`),t}function fe(e){return{headless:e===`headless`,args:de(e)}}var E=class{tabs=new Map;labelToId=new Map;register(e,t,n,r){return this.tabs.set(e,{tabId:e,url:t,title:n??t,label:r,createdAt:new Date}),r&&this.labelToId.set(r,e),e}resolve(e){return this.tabs.has(e)?e:this.labelToId.get(e)||e}getTab(e){let t=this.tabs.get(e);if(!t)throw Error(`Tab not found: ${e}`);return t}updateTabInfo(e,t,n){let r=this.tabs.get(e);r&&this.tabs.set(e,{...r,url:t,title:n})}setSnapshot(e,t){let n=this.tabs.get(e);n&&this.tabs.set(e,{...n,snapshot:t})}getSnapshot(e){return this.tabs.get(e)?.snapshot}async removeTab(e){let t=this.tabs.get(e);t&&(t.label&&this.labelToId.delete(t.label),this.tabs.delete(e))}listTabs(){return[...this.tabs.values()]}listPages(){return this.listTabs().map(e=>({pageId:e.tabId,url:e.url,title:e.title,label:e.label,createdAt:e.createdAt}))}async closeAll(){this.tabs.clear(),this.labelToId.clear()}clear(){this.tabs.clear(),this.labelToId.clear()}get size(){return this.tabs.size}},pe=class{tabs=new E;registerPage(e,t,n,r){return this.tabs.register(e,t,n,r)}getPage(e){throw Error(`Direct Playwright Page access no longer supported with agent-browser. Use engine.exec() or engine.tabExec() for browser operations.`)}getPageInfo(e){let t=this.tabs.getTab(e);return{pageId:t.tabId,url:t.url,title:t.title,label:t.label,createdAt:t.createdAt}}resolvePageId(e){return this.tabs.resolve(e)}setSnapshot(e,t){this.tabs.setSnapshot(e,t)}getSnapshot(e){return this.tabs.getSnapshot(e)}updatePageInfo(e,t,n){this.tabs.updateTabInfo(e,t,n)}async removePage(e){await this.tabs.removeTab(e)}listPages(){return this.tabs.listPages()}async closeAll(){await this.tabs.closeAll()}get size(){return this.tabs.size}};const D={defaultMode:`ui`,browsersPath:null,userDataDirRoot:null,idleShutdownMinutes:0,allowInternalSchemes:!1,allowLoopback:!1,evalTimeoutMs:3e4,evalMaxResultBytes:262144,redactPasswordFieldsInScreenshots:!0,engine:`chrome`};function me(e){if(e.endsWith(`.exe`))return e;let t=_(g(e),`node_modules`,`agent-browser`,`bin`,`agent-browser-win32-x64.exe`);if(o(t))return t;if(!e.endsWith(`.cmd`)&&!e.endsWith(`.bat`)){if(o(`${e}.exe`))return`${e}.exe`;if(o(`${e}.cmd`))return`${e}.cmd`;if(o(`${e}.bat`))return`${e}.bat`}return e}var O=class{binaryPath=null;_currentMode=null;_isLaunched=!1;idleTimer=null;_lastExecDiagnostics=null;tabs=new E;config;constructor(e={}){this.config={...D,...e}}get currentMode(){return this._currentMode}async launch(e,t){let n=ue(e??this.config.defaultMode);if(!(this._isLaunched&&this._currentMode===n)){this._isLaunched&&this._currentMode!==n&&await this.close(),this._currentMode=n,this.binaryPath=await oe(this.config,t);try{let e=await this.exec(`--version`);t?.(`agent-browser ${e.stdout.trim()}`)}catch(e){throw Error(`agent-browser binary failed: ${e instanceof Error?e.message:String(e)}`)}this._isLaunched=!0,this.resetIdleTimer()}}async exec(e,...t){if(!this.binaryPath)throw Error(`agent-browser not launched. Call launch() first, or use getEngine() singleton.`);let n=this.binaryPath;m()===`win32`&&(n=me(n));let r=[e,...t];if(m()===`win32`&&(n.endsWith(`.cmd`)||n.endsWith(`.bat`))){let e=`"${n}" ${r.map(e=>/[^\w/:@.\-_{}()/\\]/.test(e)?`"${e.replace(/"/g,`""`)}"`:e).join(` `)}`;return await this.execWithDiagnostics(e,[],!0,e,n,r)}return await this.execWithDiagnostics(n,r,!1,[n,...r].join(` `),n,r)}getLastExecDiagnostics(){return this._lastExecDiagnostics}async execWithDiagnostics(e,t,n,r,i,a){let o={timestamp:new Date().toISOString(),binaryPath:this.binaryPath??``,resolvedBinaryPath:i,args:a,usedShell:n,displayCommand:r};this._lastExecDiagnostics=o;try{let i=await this.execViaSpawn(e,t,{shell:n,displayCommand:r});return o.exitCode=i.exitCode,this._lastExecDiagnostics=o,i}catch(e){throw o.error=e instanceof Error?e.message:String(e),this._lastExecDiagnostics=o,e}}execViaSpawn(e,t,n={}){return new Promise((a,o)=>{let s=n.displayCommand??[e,...t].join(` `),u=!1,f=!1,p,m=`${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,g=_(h(),`aikit-agent-browser-${m}.stdout`),v=_(h(),`aikit-agent-browser-${m}.stderr`),y=c(g,`w+`),b=c(v,`w+`),x=r(e,t,{shell:n.shell??!1,stdio:[`ignore`,y,b],windowsHide:!0});x.unref(),i(y),i(b);let S=e=>{try{d(e)}catch{}},C=()=>{let e=``,t=``;try{e=l(g,`utf8`)}catch{e=``}try{t=l(v,`utf8`)}catch{t=``}return S(g),S(v),{stdout:e,stderr:t}},w=e=>{u||(u=!0,p&&clearTimeout(p),e())};p=setTimeout(()=>{f=!0,x.kill()},this.config.evalTimeoutMs),x.once(`error`,e=>{w(()=>{if(S(g),S(v),e.code===`ENOENT`){o(Error(`agent-browser binary not found at ${this.binaryPath}`));return}o(e)})}),x.once(`exit`,(e,t)=>{w(()=>{let n=C();if(f||t){o(Error(`agent-browser command timed out after ${this.config.evalTimeoutMs}ms: `+s));return}a({stdout:n.stdout,stderr:n.stderr,exitCode:e??0})})})})}async tabExec(e,t,...n){return this.exec(`tab`,e,t,...n)}async open(e,t,n){await this.launch(t);let r=this._currentMode===`ui`?[`open`,e,`--headed`,`--json`]:[`tab`,`new`,e,`--json`],i=await this.exec(...r);if(i.exitCode!==0)throw Error(`agent-browser failed to open URL (exit ${i.exitCode}): ${i.stderr||i.stdout||`Unknown error`}`);let a=k(i.stdout)??await this.readActiveTabId()??this.nextLocalTabId();return this.tabs.register(a,e,i.stdout.trim(),n),this.resetIdleTimer(),a}async screenshot(e,t){let n=t?.format??`png`,r=n===`jpeg`?`image/jpeg`:`image/png`,i=n===`jpeg`?`jpg`:`png`,a=_(t?.screenshotDir??h(),`aikit-screenshot-${Date.now()}.${i}`),o=[a];t?.fullPage&&o.push(`--full`),t?.screenshotDir&&o.push(`--screenshot-dir`,t.screenshotDir),t?.format===`jpeg`&&o.push(`--screenshot-format`,`jpeg`),t?.quality&&o.push(`--screenshot-quality`,String(t.quality)),t?.annotate&&o.push(`--annotate`),await this.tabExec(e,`screenshot`,...o);let s=l(a),c=s.toString(`base64`);try{d(a)}catch{}return this.resetIdleTimer(),{base64:c,mimeType:r,bytes:s.length}}async screenshotActiveTab(e){let t=e?.format??`png`,n=t===`jpeg`?`image/jpeg`:`image/png`,r=t===`jpeg`?`jpg`:`png`,i=_(e?.screenshotDir??h(),`aikit-screenshot-${Date.now()}.${r}`),a=[i];e?.fullPage&&a.push(`--full`),e?.screenshotDir&&a.push(`--screenshot-dir`,e.screenshotDir),e?.format===`jpeg`&&a.push(`--screenshot-format`,`jpeg`),e?.quality&&a.push(`--screenshot-quality`,String(e.quality)),e?.annotate&&a.push(`--annotate`),e?.selector&&a.push(`--element`,e.selector),await this.exec(`screenshot`,...a);let o=l(i),s=o.toString(`base64`);try{d(i)}catch{}return this.resetIdleTimer(),{base64:s,mimeType:n,bytes:o.length}}async readSnapshot(e,t=!1){let n=t?[`-c`,`--json`]:[`-i`,`--json`],r=await this.tabExec(e,`snapshot`,...n);return this.resetIdleTimer(),r.stdout}async navigate(e,t){let n=await this.tabExec(e,`goto`,t);return this.resetIdleTimer(),n}async close(){this.stopIdleTimer(),this._isLaunched&&(await this.closeRuntimeSession(),this.tabs.clear(),this._isLaunched=!1,this._currentMode=null)}isLaunched(){return this._isLaunched}getConfig(){return this.config}getBinaryPath(){return this.binaryPath}resolvePageId(e){return this.tabs.resolve(e)}resetIdleTimer(){if(this.stopIdleTimer(),!Number.isFinite(this.config.idleShutdownMinutes)||this.config.idleShutdownMinutes<=0){this._currentMode===`ui`&&(this.idleTimer=setInterval(()=>{},6e4));return}let e=setTimeout(()=>{this.close()},this.config.idleShutdownMinutes*6e4);this._currentMode!==`ui`&&e.unref?.(),this.idleTimer=e}stopIdleTimer(){this.idleTimer&&=(clearTimeout(this.idleTimer),null)}async closeRuntimeSession(){try{await this.exec(`close`,`--all`).catch(()=>{})}catch{}}async readActiveTabId(){let e=await this.exec(`tab`,`list`,`--json`).catch(()=>null);return e?.exitCode===0?k(e.stdout):null}nextLocalTabId(){let e=this.tabs.listTabs().map(e=>/^t(\d+)$/.exec(e.tabId)?.[1]).filter(e=>e!==void 0).map(Number);return`t${e.length===0?1:Math.max(...e)+1}`}};function k(e){try{let t=JSON.parse(e);if(typeof t.data?.tabId==`string`)return t.data.tabId;let n=t.data?.tabs?.find(e=>e.active===!0);if(typeof n?.tabId==`string`)return n.tabId}catch{}return null}let A=null;function j(e){return A||=new O(e),A}async function he(){A&&=(await A.close(),null)}function M(e,t){try{let n=new URL(e),r=n.hostname.toLowerCase(),i=n.protocol.toLowerCase();return[`file:`,`chrome:`,`chrome-extension:`,`data:`,`javascript:`].includes(i)?t?.allowInternalSchemes?{allowed:!0}:{allowed:!1,reason:`Scheme '${i}' is blocked for security`}:[`169.254.169.254`,`metadata.google.internal`,`metadata.instance`].includes(r)?{allowed:!1,reason:`Cloud metadata endpoint '${r}' is blocked`}:n.hostname===`localhost`||r===`127.0.0.1`||r===`::1`||r.startsWith(`10.`)||r.startsWith(`172.`)||r.startsWith(`192.168.`)?t?.allowLoopback?{allowed:!0}:{allowed:!1,reason:`Internal host '${r}' requires allowLoopback=true`}:{allowed:!0}}catch{return{allowed:!1,reason:`Invalid URL`}}}function N(e,t){return Buffer.byteLength(e,`utf8`)<=t?{valid:!0,result:e,truncated:!1}:{valid:!0,result:`${Buffer.from(e).subarray(0,t).toString(`utf8`)}\n... [truncated]`,truncated:!0,reason:`Result exceeded ${t} bytes, truncated to ${t} bytes`}}const ge=[`ui`,`headless`];function _e(e){return typeof e==`object`&&e?e:null}function P(e){return typeof e==`string`&&e.length>0?e:void 0}function F(e){return typeof e==`boolean`?e:void 0}function I(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function L(e){return typeof e==`string`&&ge.includes(e)?e:void 0}function R(e){let t=process.env[e];if(!t)return;let n=Number(t);return Number.isFinite(n)?n:void 0}function ve(e){let t=_e(e.browser)??{};return{...D,defaultMode:L(process.env.AIKIT_BROWSER_DEFAULT_MODE)??L(t.defaultMode)??D.defaultMode,browsersPath:P(process.env.AIKIT_BROWSER_PATH)??P(process.env.AIKIT_BROWSER_BROWSERS_PATH)??P(t.browsersPath)??D.browsersPath,userDataDirRoot:P(t.userDataDirRoot)??D.userDataDirRoot,idleShutdownMinutes:R(`AIKIT_BROWSER_IDLE_MINUTES`)??I(t.idleShutdownMinutes)??D.idleShutdownMinutes,allowInternalSchemes:F(t.allowInternalSchemes)??D.allowInternalSchemes,allowLoopback:F(t.allowLoopback)??D.allowLoopback,evalTimeoutMs:R(`AIKIT_BROWSER_EVAL_TIMEOUT_MS`)??I(t.evalTimeoutMs)??D.evalTimeoutMs,evalMaxResultBytes:I(t.evalMaxResultBytes)??D.evalMaxResultBytes,redactPasswordFieldsInScreenshots:F(t.redactPasswordFieldsInScreenshots)??D.redactPasswordFieldsInScreenshots,engine:P(t.engine)??D.engine,proxy:P(t.proxy),viewport:P(t.viewport)}}function z(e,t){return{content:[{type:`text`,text:e}],structuredContent:t}}function B(e,t){let n=e.selector??e.ref??(e.element?`text=${e.element}`:void 0);if(!n)throw Error(`${t} requires selector, ref, or element`);return n}function V(e){try{let t=JSON.parse(e);if(t&&typeof t==`object`){let e=H(t);if(e.length>0)return e.join(`
2
2
  `)}return JSON.stringify(t,null,2)}catch{return e}}function H(e,t=0,n=[]){let r=` `.repeat(t),i=typeof e.role==`string`?e.role.toUpperCase():``,a=typeof e.ref==`string`?e.ref:``,o=typeof e.name==`string`?e.name:``,s=typeof e.value==`string`?`="${e.value}"`:``,c=Array.isArray(e.children)?e.children:[];if(i&&a){let e=ye(i),t=o||s||``;n.push(`${r}[${e}] [${a}] ${t}`.trimEnd())}else if(o||i){let e=i.toLowerCase();n.push(`${r}${e}: ${o}`.trimEnd())}for(let e of c)typeof e==`object`&&e&&H(e,t+1,n);return n}function ye(e){return{BUTTON:`BUTTON`,LINK:`LINK`,TEXT_FIELD:`TEXTFIELD`,TEXTBOX:`TEXTFIELD`,COMBOBOX:`SELECT`,CHECKBOX:`CHECKBOX`,RADIO:`RADIO`,SWITCH:`SWITCH`,SLIDER:`SLIDER`,TAB:`TAB`,MENU_ITEM:`MENUITEM`,LISTBOX:`LIST`,GRID:`GRID`,TABLE:`TABLE`,HEADING:`HEADING`,IMAGE:`IMAGE`,IMG:`IMAGE`,PROGRESSBAR:`PROGRESS`,DIALOG:`DIALOG`,TOOLTIP:`TOOLTIP`,ALERT:`ALERT`,MENU:`MENU`,NAVIGATION:`NAV`,SEARCH:`SEARCH`,MAIN:`MAIN`,COMPLEMENTARY:`COMPLEMENT`,CONTENTINFO:`INFO`,REGION:`REGION`}[e]??e.slice(0,8)}function be(e){return async({pageId:t,kind:n,ref:r,selector:i,element:a,text:o,key:s,value:c,fromRef:l,fromSelector:u,toRef:d,toSelector:f})=>{let p=j(e),m=p.resolvePageId(t);switch(n){case`click`:{let e=B({ref:r,selector:i,element:a},`browser_act(click)`);await p.tabExec(m,`click`,e);break}case`type`:{let e=B({ref:r,selector:i,element:a},`browser_act(type)`);await p.tabExec(m,`fill`,e,o??``);break}case`press`:{let e=B({ref:r,selector:i,element:a},`browser_act(press)`);if(!s)throw Error(`browser_act(press) requires key`);await p.tabExec(m,`press`,e,s);break}case`hover`:{let e=B({ref:r,selector:i,element:a},`browser_act(hover)`);await p.tabExec(m,`hover`,e);break}case`drag`:{let e=B({ref:l??r,selector:u??i,element:a},`browser_act(drag) source`),t=B({ref:d,selector:f??c,element:a},`browser_act(drag) target`);await p.tabExec(m,`drag`,e,t);break}case`select`:{let e=B({ref:r,selector:i,element:a},`browser_act(select)`);if(c===void 0)throw Error(`browser_act(select) requires value`);await p.tabExec(m,`select`,e,c);break}case`scroll`:{if(i||r||a){let e=B({ref:r,selector:i,element:a},`browser_act(scroll)`);await p.tabExec(m,`scrollintoview`,e);break}let e=c??`down 500`;await p.tabExec(m,`scroll`,e);break}case`upload`:{let e=B({ref:r,selector:i,element:a},`browser_act(upload)`);if(!c)throw Error(`value (file path) required for upload`);await p.tabExec(m,`upload`,e,c);break}}return p.resetIdleTimer(),z(`ok`,{ok:!0})}}function xe(e){return async({pageId:t,subAction:n,level:r,bufferSize:i,expression:a})=>{let o=j(e),s=o.resolvePageId(t);switch(n){case`enable`:{let e=[`--enable`];return i&&e.push(`--buffer-size`,String(i)),r&&e.push(`--level`,r),await o.tabExec(s,`console`,...e),o.resetIdleTimer(),z(`Console capture enabled`,{enabled:!0})}case`get`:{let t=[`--json`];r&&t.push(`--level`,r);let n=await o.tabExec(s,`console`,...t);o.resetIdleTimer();let i=[];try{i=JSON.parse(n.stdout)}catch{i=[{raw:n.stdout}]}let c,l;if(a)try{c=(await o.tabExec(s,`evaluate`,`--timeout=${e.evalTimeoutMs}`,`--`,a)).stdout}catch(e){l=e instanceof Error?e.message:String(e)}return z(c===void 0?`Console has ${i.length} entries`:`Console has ${i.length} entries\nEvaluation: ${c}`,{entries:i,count:i.length,expression:a,evalResult:c,evalError:l})}case`clear`:return await o.tabExec(s,`console`,`clear`),o.resetIdleTimer(),z(`Console cleared`,{cleared:!0});default:return z(`Unknown console sub-action`,{error:`Unknown console sub-action`})}}}function Se(e){return async({pageId:t,accept:n,promptText:r})=>{let i=j(e),a=i.resolvePageId(t);if(n){let e=r?[`accept`,`--text`,r]:[`accept`];await i.tabExec(a,`dialog`,...e)}else await i.tabExec(a,`dialog`,`dismiss`);return i.resetIdleTimer(),z(`Dialog ${n?`accepted`:`dismissed`}`,{accepted:n})}}function Ce(e){return async({pageId:t})=>{let n=j(e),r=n.resolvePageId(t),i=await n.tabExec(r,`diff`,`snapshot`);return n.resetIdleTimer(),z(i.stdout,{pageId:r,diff:i.stdout})}}function we(e){return async({pageId:t,code:n,timeoutMs:r})=>{let i=j(e),a=i.resolvePageId(t),o=r??e.evalTimeoutMs,s=await i.tabExec(a,`evaluate`,`--timeout=${o}`,`--`,n);i.resetIdleTimer();let c=N(s.stdout,e.evalMaxResultBytes);return z(c.result,{pageId:a,result:c.result,truncated:c.truncated})}}function Te(e){return async({pageId:t,url:n,method:r,headers:i,body:a,timeoutMs:o,includeHeaders:s})=>{let c=j(e),l=c.resolvePageId(t),u=o??e.evalTimeoutMs,d=Ee(n,r??`GET`,s??!0,i,a),f=await c.tabExec(l,`evaluate`,`--timeout=${u}`,`--`,d);return c.resetIdleTimer(),z(f.stdout,{pageId:l,response:f.stdout})}}function Ee(e,t,n,r,i){let a={method:t,headers:r??{}};i&&[`POST`,`PUT`,`PATCH`].includes(t.toUpperCase())&&(a.body=i);let o=JSON.stringify(a);return n?`fetch(${JSON.stringify(e)}, ${o}).then(async r => {
3
3
  const text = await r.text();
4
4
  const headers = {};
@@ -2,7 +2,7 @@
2
2
  "manifest_version": "0.3",
3
3
  "name": "aikit",
4
4
  "display_name": "AI Kit",
5
- "version": "0.1.400",
5
+ "version": "0.1.401",
6
6
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
7
7
  "author": {
8
8
  "name": "AnVPX",
@@ -5,4 +5,4 @@ import{fileURLToPath as e,pathToFileURL as t}from"node:url";import{parseArgs as
5
5
  `).length,fileHash:this.hash(e.content),indexedAt:t,origin:`curated`,tags:e.frontmatter.tags,category:e.frontmatter.category,version:e.frontmatter.version}});try{return await this.store.upsert(i,r),e.length}catch(t){z.error(`Failed to upsert curated batch`,{batchSize:e.length,...o(t)});for(let t of e)n.push(`${t.relativePath}: upsert failed`);return 0}}catch(r){if(e.length===1)return z.error(`Failed to embed curated item`,{relativePath:e[0].relativePath,...o(r)}),n.push(`${e[0].relativePath}: reindex failed`),0;z.warn(`Curated embed batch failed, retrying with smaller chunks`,{batchSize:e.length,...o(r)});let i=Math.ceil(e.length/2),a=e.slice(0,i),s=e.slice(i);return await this.embedAndUpsertBatch(a,t,n)+await this.embedAndUpsertBatch(s,t,n)}}gitCommitKnowledge(e,t,n){try{if(!b(this.curatedDir))return;let r=this.knowledgeRefForPath(e);if(!r)return;x(r,`entry.md`,t,n,this.curatedDir)}catch{}}gitDeleteKnowledgeRef(e){try{if(!b(this.curatedDir))return;let t=this.knowledgeRefForPath(e);if(!t)return;S([`update-ref`,`-d`,t],this.curatedDir)}catch{}}knowledgeRefForPath(e){let t=e.replace(/\.md$/,``).split(`/`).map(e=>C(e)).join(`/`);return t.split(`/`).every(e=>y.test(e))?`${R}/${t}`:null}async indexCuratedFile(e,t,n){let r=await this.embedder.embed(t),i=`.ai/curated/${e}`,a=new Date().toISOString(),o={id:this.hashId(i,0),content:t,sourcePath:i,contentType:`curated-knowledge`,headingPath:n.title,chunkIndex:0,totalChunks:1,startLine:1,endLine:t.split(`
6
6
  `).length,fileHash:this.hash(t),indexedAt:a,origin:`curated`,tags:n.tags,category:n.category,version:n.version};await this.store.upsert([o],[r])}async indexCuratedFileBestEffort(e,t,n,i){if(r.instance().isDegraded(`embedder`)){z.debug(`Skipping vector indexing — embedder degraded`,{relativePath:e,operation:i,subsystem:`embedder`});return}try{await this.indexCuratedFile(e,t,n)}catch(t){z.warn(`Curated file persisted but vector indexing deferred`,{relativePath:e,operation:i,...o(t)})}}async discoverCategories(){return this.adapter.listDirectories()}guardPath(e){let t=e.replace(/^\.ai\/curated\//,``);if(t.endsWith(`.md`)||(t+=`.md`),t.includes(`..`)||l(t))throw Error(`Invalid path: ${t}. Must be relative within .ai/curated/ directory.`);let n=t.split(`/`)[0];return this.validateCategoryName(n),t}validateCategoryName(e){if(!/^[a-z][a-z0-9-]*$/.test(e))throw Error(`Invalid category name: "${e}". Must be lowercase kebab-case (e.g., "decisions", "api-contracts").`)}validateContentSize(e){if(Buffer.byteLength(e,`utf-8`)>L)throw Error(`Content exceeds maximum size of ${L/1024}KB`)}slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,80)}normalizeTags(e){return[...new Set(e.map(e=>e.trim()).filter(Boolean))]}sameTags(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}ensureCategoryPath(e,t){if(!e.startsWith(`${t}/`))throw Error(`Curated path "${e}" must stay within category "${t}"`)}async uniqueRelativePath(e,t){let n=`${e}/${t}.md`;if(!await this.adapter.exists(n))return n;for(let n=2;n<=100;n++){let r=`${e}/${t}-${n}.md`;if(!await this.adapter.exists(r))return r}throw Error(`Too many entries with slug "${t}" in category "${e}"`)}hash(e){return v(`sha256`).update(e).digest(`hex`).slice(0,16)}hashId(e,t){return this.hash(`${e}::${t}`)}serializeFile(e,t){return`${[`---`,`title: "${t.title.replace(/"/g,`\\"`)}"`,`category: ${t.category}`,`tags: [${t.tags.map(e=>`"${e}"`).join(`, `)}]`,`created: ${t.created}`,`updated: ${t.updated}`,`version: ${t.version}`,`origin: ${t.origin}`,`changelog:`,...t.changelog.map(e=>` - version: ${e.version}\n date: ${e.date}\n reason: "${e.reason.replace(/"/g,`\\"`)}"`),`---`].join(`
7
7
  `)}\n\n${e}\n`}parseFile(e){let t=e.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);if(!t)return{frontmatter:{title:`Untitled`,category:`notes`,tags:[],created:``,updated:``,version:1,origin:`curated`,changelog:[]},content:e};let n=t[1],r=t[2].trim(),i={},a=[],o=n.split(`
8
- `),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const V=i(`server`);function H(e,t){return t?{version:e,...o(t)}:{version:e}}function U(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function W(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===t(e).href}catch{return!1}}function G(){return W()?n({allowPositionals:!0,options:{transport:{type:`string`,default:U()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:U(),port:process.env.AIKIT_PORT??`3210`}}async function K(){let e=t=>{t.name===`ExperimentalWarning`&&t.message.includes(`SQLite`)||(process.off(`warning`,e),process.emitWarning(t),process.on(`warning`,e))};process.on(`warning`,e);let t=w(),n=G();if(process.on(`unhandledRejection`,e=>{V.error(`Unhandled rejection`,H(t,e))}),process.on(`uncaughtException`,e=>{V.error(`Uncaught exception — exiting`,H(t,e)),process.exit(1)}),V.info(`Starting MCP AI Kit server`,{version:t}),n.transport===`http`){let{startHttpMode:e}=await import(`./server-http-VZ97RQ2_.js`);await e(t,n.port)}else{let{startStdioMode:e}=await import(`./server-stdio-DYunLLYy.js`);await e(t)}}K();export{T as a,k as i,I as n,E as o,F as r,O as s,B as t};
8
+ `),s=!1,c={};for(let e of o){if(/^changelog:\s*$/.test(e)){s=!0;continue}if(s){let t=e.match(/^\s+-\s+version:\s*(\d+)$/);if(t){c.version!=null&&a.push(c),c={version:parseInt(t[1],10)};continue}let n=e.match(/^\s+date:\s*(.+)$/);if(n){c.date=n[1].trim();continue}let r=e.match(/^\s+reason:\s*"?(.*?)"?\s*$/);if(r){c.reason=r[1];continue}/^\w/.test(e)&&(s=!1,c.version!=null&&a.push(c),c={});continue}let t=e.match(/^(\w+):\s*(.*)$/);if(t){let e=t[1],n=t[2];typeof n==`string`&&n.startsWith(`[`)&&n.endsWith(`]`)?n=n.slice(1,-1).split(`,`).map(e=>e.trim().replace(/^"|"$/g,``)).filter(e=>e.length>0):typeof n==`string`&&/^\d+$/.test(n)?n=parseInt(n,10):typeof n==`string`&&n.startsWith(`"`)&&n.endsWith(`"`)&&(n=n.slice(1,-1)),i[e]=n}}return c.version!=null&&a.push(c),{frontmatter:{title:i.title??`Untitled`,category:i.category??`notes`,tags:i.tags??[],created:i.created??``,updated:i.updated??``,version:i.version??1,origin:`curated`,changelog:a},content:r}}};const V=i(`server`);function H(e,t){return t?{version:e,...o(t)}:{version:e}}function U(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function W(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===t(e).href}catch{return!1}}function G(){return W()?n({allowPositionals:!0,options:{transport:{type:`string`,default:U()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:U(),port:process.env.AIKIT_PORT??`3210`}}async function K(){let e=t=>{t.name===`ExperimentalWarning`&&t.message.includes(`SQLite`)||(process.off(`warning`,e),process.emitWarning(t),process.on(`warning`,e))};process.on(`warning`,e);let t=w(),n=G();if(process.on(`unhandledRejection`,e=>{V.error(`Unhandled rejection`,H(t,e))}),process.on(`uncaughtException`,e=>{V.error(`Uncaught exception — exiting`,H(t,e)),process.exit(1)}),V.info(`Starting MCP AI Kit server`,{version:t}),n.transport===`http`){let{startHttpMode:e}=await import(`./server-http-C8jeAK4J.js`);await e(t,n.port)}else{let{startStdioMode:e}=await import(`./server-stdio-D6bXTkAE.js`);await e(t)}}K();export{T as a,k as i,I as n,E as o,F as r,O as s,B as t};
@@ -351,4 +351,4 @@ svg text{fill:var(--body);font-family:var(--sans);font-size:12px}
351
351
  <\/script>
352
352
  </body>
353
353
  </html>`}const U=`<!-- DIAGRAM:SVG -->`;function W(e){let t=e.indexOf(U);if(t===-1)return null;let n=t+20,r=e.indexOf(U,n);if(r===-1)return null;let i=e.slice(n,r).trim();if(i.startsWith(`<svg`))return i;let a=e.slice(Math.max(0,t),r+20),o=a.match(/viewBox="([^"]+)"/),s=o?o[1]:`0 0 1200 800`,c=a.match(/width="(\d+)"/),l=c?c[1]:`1200`,u=a.match(/height="(\d+)"/);return[`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${s}" width="${l}" height="${u?u[1]:`800`}">`,` <defs>`,` <style>`,` text { font-family: system-ui, -apple-system, sans-serif; }`,` .title { font-size: 20px; font-weight: 600; fill: #fff; }`,` .subtitle { font-size: 14px; fill: #94a3b8; }`,` </style>`,` </defs>`,i,`</svg>`].join(`
354
- `)}function he(e){let t=e.match(/<title>([^<]+)<\/title>/);return t?t[1]:`diagram`}async function ge(e,t,n){let r=m(n);await h(r,{recursive:!0});let i=he(e).replace(/[^a-zA-Z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``).toLowerCase().slice(0,80)||`diagram`,a=p(r,`${i}.html`);await g(a,e,`utf-8`);let o=null,s=W(e);s&&(o=p(r,`${i}.svg`),await g(o,s,`utf-8`));let c=null;return t&&(c=p(r,`${i}.md`),await g(c,t,`utf-8`)),{htmlPath:a,svgPath:o,mdPath:c}}const G=10*1024*1024,K=2e3;function _e(e){try{return JSON.stringify(e)}catch{return``}}function ve(e){switch(e.diagram_type){case`architecture`:return ae(e);case`workflow`:return H(e);case`sequence`:return R(e);case`dataflow`:return ce(e);case`lifecycle`:return P(e)}}function q(e,t={}){Y(e);let n=J(e);if(n.length>0)throw Error(`Diagram validation failed: ${n.join(`; `)}`);let r=t.title??e.meta.title,i=t.subtitle??e.meta.subtitle,a=t.dualOutput??!0,{svg:o,cardsHtml:s,detailData:c}=ve(e),l=c&&Object.keys(c).length>0?`\n<script id="diagram-node-data" type="application/json">${_e(c)}<\/script>`:``,u=e.meta?.palette===`warm`?`warm`:`technical`;return{html:me().replaceAll(`[TITLE]`,X(r)).replaceAll(`[SUBTITLE]`,X(i??``)).replaceAll(`[PALETTE]`,u===`warm`?` data-palette="warm"`:``).replaceAll(`<!-- DIAGRAM:SVG -->`,o).replaceAll(`<!-- DIAGRAM:CARDS -->`,s).replace(`</body>`,`${l}\n</body>`),markdown:a?_(e):void 0}}function ye(e,t={}){return q(e,{...t,dualOutput:!1}).html}function be(e){return _(e)}function xe(e){try{return Y(e),J(e)}catch(e){return[e.message]}}function J(e){if(!e||typeof e!=`object`)return[`Input must be an object`];if(!e.diagram_type)return[`Missing diagram_type`];if(!e.meta?.title)return[`meta.title is required`];if(e.schema_version!==1)return[`schema_version must be 1`];let t=e.diagram_type,n=e,r=n.components??n.nodes??n.participants??n.states??[],i=n.connections??n.edges??n.messages??n.flows??n.transitions??[],a=new Set(r.map(e=>e.id));if(a.size!==r.length)return[`${t}: Node/component IDs must be unique`];for(let e of i){if(e.from&&!a.has(e.from))return[`${t}: Edge references unknown source "${e.from}"`];if(e.to&&!a.has(e.to))return[`${t}: Edge references unknown target "${e.to}"`]}return[]}function Y(e){let t=JSON.stringify(e),n=Buffer.byteLength(t,`utf-8`);if(n>G)throw Error(`Input too large: ${(n/1024/1024).toFixed(1)}MB (max ${G/1024/1024}MB)`);let r=e,i=r.components??r.nodes??r.participants??[];if(i.length>500)throw Error(`Too many components/nodes: ${i.length} (max 500)`);let a=r.connections??r.edges??r.messages??r.flows??r.transitions??[];if(a.length>K)throw Error(`Too many edges/connections: ${a.length} (max ${K})`)}function Se(e){return e.replace(/[^a-zA-Z0-9-_]/g,`_`).toLowerCase().slice(0,120)}function X(e){let t={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`};return String(e??``).replace(/[&<>"']/g,e=>t[e]??e)}const Z=d(`server`);function Q(e,t){return t?{version:e,...f(t)}:{version:e}}function $(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function Ce(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===l(e).href}catch{return!1}}function we(){return Ce()?u({allowPositionals:!0,options:{transport:{type:`string`,default:$()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:$(),port:process.env.AIKIT_PORT??`3210`}}async function Te(){let e=t=>{t.name===`ExperimentalWarning`&&t.message.includes(`SQLite`)||(process.off(`warning`,e),process.emitWarning(t),process.on(`warning`,e))};process.on(`warning`,e);let n=t(),r=we();if(process.on(`unhandledRejection`,e=>{Z.error(`Unhandled rejection`,Q(n,e))}),process.on(`uncaughtException`,e=>{Z.error(`Uncaught exception — exiting`,Q(n,e)),process.exit(1)}),Z.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let{startHttpMode:e}=await import(`./server-http-B6xxtb4O.js`);await e(n,r.port)}else{let{startStdioMode:e}=await import(`./server-stdio-rnmPVtJi.js`);await e(n)}}export{c as CuratedKnowledgeManager,s as applyWorkspaceRoots,a as bootstrapWorkspaceRoots,i as createSlidingWindowRateLimiter,ge as exportDiagram,W as extractSvg,n as getSessionIdHeader,Te as main,r as readPositiveIntEnv,t as readVersion,ye as renderHtml,be as renderMd,q as renderToResult,e as resolveCorsOrigin,Se as sanitizeTitle,o as selectWorkspaceRoot,xe as validate};
354
+ `)}function he(e){let t=e.match(/<title>([^<]+)<\/title>/);return t?t[1]:`diagram`}async function ge(e,t,n){let r=m(n);await h(r,{recursive:!0});let i=he(e).replace(/[^a-zA-Z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``).toLowerCase().slice(0,80)||`diagram`,a=p(r,`${i}.html`);await g(a,e,`utf-8`);let o=null,s=W(e);s&&(o=p(r,`${i}.svg`),await g(o,s,`utf-8`));let c=null;return t&&(c=p(r,`${i}.md`),await g(c,t,`utf-8`)),{htmlPath:a,svgPath:o,mdPath:c}}const G=10*1024*1024,K=2e3;function _e(e){try{return JSON.stringify(e)}catch{return``}}function ve(e){switch(e.diagram_type){case`architecture`:return ae(e);case`workflow`:return H(e);case`sequence`:return R(e);case`dataflow`:return ce(e);case`lifecycle`:return P(e)}}function q(e,t={}){Y(e);let n=J(e);if(n.length>0)throw Error(`Diagram validation failed: ${n.join(`; `)}`);let r=t.title??e.meta.title,i=t.subtitle??e.meta.subtitle,a=t.dualOutput??!0,{svg:o,cardsHtml:s,detailData:c}=ve(e),l=c&&Object.keys(c).length>0?`\n<script id="diagram-node-data" type="application/json">${_e(c)}<\/script>`:``,u=e.meta?.palette===`warm`?`warm`:`technical`;return{html:me().replaceAll(`[TITLE]`,X(r)).replaceAll(`[SUBTITLE]`,X(i??``)).replaceAll(`[PALETTE]`,u===`warm`?` data-palette="warm"`:``).replaceAll(`<!-- DIAGRAM:SVG -->`,o).replaceAll(`<!-- DIAGRAM:CARDS -->`,s).replace(`</body>`,`${l}\n</body>`),markdown:a?_(e):void 0}}function ye(e,t={}){return q(e,{...t,dualOutput:!1}).html}function be(e){return _(e)}function xe(e){try{return Y(e),J(e)}catch(e){return[e.message]}}function J(e){if(!e||typeof e!=`object`)return[`Input must be an object`];if(!e.diagram_type)return[`Missing diagram_type`];if(!e.meta?.title)return[`meta.title is required`];if(e.schema_version!==1)return[`schema_version must be 1`];let t=e.diagram_type,n=e,r=n.components??n.nodes??n.participants??n.states??[],i=n.connections??n.edges??n.messages??n.flows??n.transitions??[],a=new Set(r.map(e=>e.id));if(a.size!==r.length)return[`${t}: Node/component IDs must be unique`];for(let e of i){if(e.from&&!a.has(e.from))return[`${t}: Edge references unknown source "${e.from}"`];if(e.to&&!a.has(e.to))return[`${t}: Edge references unknown target "${e.to}"`]}return[]}function Y(e){let t=JSON.stringify(e),n=Buffer.byteLength(t,`utf-8`);if(n>G)throw Error(`Input too large: ${(n/1024/1024).toFixed(1)}MB (max ${G/1024/1024}MB)`);let r=e,i=r.components??r.nodes??r.participants??[];if(i.length>500)throw Error(`Too many components/nodes: ${i.length} (max 500)`);let a=r.connections??r.edges??r.messages??r.flows??r.transitions??[];if(a.length>K)throw Error(`Too many edges/connections: ${a.length} (max ${K})`)}function Se(e){return e.replace(/[^a-zA-Z0-9-_]/g,`_`).toLowerCase().slice(0,120)}function X(e){let t={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`};return String(e??``).replace(/[&<>"']/g,e=>t[e]??e)}const Z=d(`server`);function Q(e,t){return t?{version:e,...f(t)}:{version:e}}function $(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}function Ce(){let e=process.argv[1];if(!e)return!1;try{return import.meta.url===l(e).href}catch{return!1}}function we(){return Ce()?u({allowPositionals:!0,options:{transport:{type:`string`,default:$()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}).values:{transport:$(),port:process.env.AIKIT_PORT??`3210`}}async function Te(){let e=t=>{t.name===`ExperimentalWarning`&&t.message.includes(`SQLite`)||(process.off(`warning`,e),process.emitWarning(t),process.on(`warning`,e))};process.on(`warning`,e);let n=t(),r=we();if(process.on(`unhandledRejection`,e=>{Z.error(`Unhandled rejection`,Q(n,e))}),process.on(`uncaughtException`,e=>{Z.error(`Uncaught exception — exiting`,Q(n,e)),process.exit(1)}),Z.info(`Starting MCP AI Kit server`,{version:n}),r.transport===`http`){let{startHttpMode:e}=await import(`./server-http-B-ITMqdw.js`);await e(n,r.port)}else{let{startStdioMode:e}=await import(`./server-stdio-CvijXOp9.js`);await e(n)}}export{c as CuratedKnowledgeManager,s as applyWorkspaceRoots,a as bootstrapWorkspaceRoots,i as createSlidingWindowRateLimiter,ge as exportDiagram,W as extractSvg,n as getSessionIdHeader,Te as main,r as readPositiveIntEnv,t as readVersion,ye as renderHtml,be as renderMd,q as renderToResult,e as resolveCorsOrigin,Se as sanitizeTitle,o as selectWorkspaceRoot,xe as validate};