@inkeep/open-knowledge 0.0.0-dev-20260424195655 → 0.0.0-dev-20260424205527

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{i as e,r as t}from"./constants-DFnJ9to1.mjs";import{O as n,c as r,k as i}from"./src-CB-sXsMW.mjs";import{n as a,t as o}from"./paths-Cw2HIHgI.mjs";import{C as s,_t as c,gt as l,ht as u,ut as d,vt as f,w as p,x as m}from"./src-DBQiBMMB.mjs";import{c as h,f as g,r as _}from"./server-lock-4vgF5yho.mjs";import{i as v,n as y,o as b,r as x,s as S,t as C}from"./colors-Cmha5EZJ.mjs";import{t as w}from"./is-object-7k010cEq.mjs";import{r as T}from"./init-14nxErpx.mjs";import{i as E,n as D,t as O}from"./loader-CGbKkeEd.mjs";import{o as ee,s as k}from"./start-C0e6lay8.mjs";import"./src-ij172HYc.mjs";import{Command as A}from"commander";import{appendFileSync as te,closeSync as ne,existsSync as j,mkdirSync as re,openSync as ie,readFileSync as ae,readdirSync as oe,realpathSync as se,statSync as ce,unlinkSync as le,writeFileSync as ue}from"node:fs";import{homedir as de,hostname as fe}from"node:os";import{basename as pe,dirname as me,isAbsolute as he,join as ge,relative as _e,resolve as M}from"node:path";import{parse as ve,stringify as ye}from"yaml";import{createOAuthDeviceAuth as be}from"@octokit/auth-oauth-device";import xe from"@inquirer/password";import{Octokit as Se}from"@octokit/rest";import{fileURLToPath as Ce}from"node:url";import{randomUUID as we}from"node:crypto";import{execFileSync as Te,spawn as Ee}from"node:child_process";import De from"simple-git";import{readFile as Oe,readdir as ke,stat as Ae}from"node:fs/promises";import{createServer as je,request as Me}from"node:http";import Ne from"picomatch";import{z as N}from"zod";import{McpServer as Pe}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Fe}from"@modelcontextprotocol/sdk/server/stdio.js";import{RootsListChangedNotificationSchema as Ie}from"@modelcontextprotocol/sdk/types.js";import{AsyncLocalStorage as Le}from"node:async_hooks";import{Bash as Re,ReadWriteFs as ze}from"just-bash";import Be from"shell-quote";import{createInterface as Ve}from"node:readline/promises";const He=`open-knowledge`;var Ue=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(He,e).getPassword();return n==null?null:JSON.parse(n)}catch{return null}}async set(e,t,n,r){let{Entry:i}=await import(`@napi-rs/keyring`),a=new i(He,e),o={login:t,token:n,...r};a.setPassword(JSON.stringify(o))}async clear(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{new t(He,e).deletePassword()}catch{}}},We=class{backend=`file`;authFile;constructor(e){this.authFile=e??ge(de(),`.open-knowledge`,`auth.yml`)}read(){if(!j(this.authFile))return{};try{return ve(ae(this.authFile,`utf-8`))??{}}catch(e){let t=e instanceof Error?e.message:`unknown error`;return process.stderr.write(`[auth] Failed to parse ${this.authFile}: ${t}. Starting with empty credentials.\n`),{}}}write(e){let t=me(this.authFile);j(t)||re(t,{recursive:!0,mode:448}),ue(this.authFile,ye(e),{mode:384})}async get(e){return this.read()[e]??null}async set(e,t,n,r){let i=this.read();i[e]={login:t,token:n,...r},this.write(i)}async clear(e){let t=this.read();delete t[e],this.write(t)}};async function Ge(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(He,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
2
+ import{i as e,r as t}from"./constants-Dqmeg2oi.mjs";import{O as n,c as r,k as i}from"./src-CB-sXsMW.mjs";import{n as a,t as o}from"./paths-BN0gQKmX.mjs";import{C as s,_t as c,gt as l,ht as u,ut as d,vt as f,w as p,x as m}from"./src-DBQiBMMB.mjs";import{c as h,f as g,r as _}from"./server-lock-4vgF5yho.mjs";import{i as v,n as y,o as b,r as x,s as S,t as C}from"./colors-Cmha5EZJ.mjs";import{t as w}from"./is-object-7k010cEq.mjs";import{r as T}from"./init-DIbZ0Udv.mjs";import{i as E,n as D,t as O}from"./loader-CEfLKIxb.mjs";import{o as ee,s as k}from"./start-J6AfuX7h.mjs";import"./src-DjVVQCyp.mjs";import{Command as A}from"commander";import{appendFileSync as te,closeSync as ne,existsSync as j,mkdirSync as re,openSync as ie,readFileSync as ae,readdirSync as oe,realpathSync as se,statSync as ce,unlinkSync as le,writeFileSync as ue}from"node:fs";import{homedir as de,hostname as fe}from"node:os";import{basename as pe,dirname as me,isAbsolute as he,join as ge,relative as _e,resolve as M}from"node:path";import{parse as ve,stringify as ye}from"yaml";import{createOAuthDeviceAuth as be}from"@octokit/auth-oauth-device";import xe from"@inquirer/password";import{Octokit as Se}from"@octokit/rest";import{fileURLToPath as Ce}from"node:url";import{randomUUID as we}from"node:crypto";import{execFileSync as Te,spawn as Ee}from"node:child_process";import De from"simple-git";import{readFile as Oe,readdir as ke,stat as Ae}from"node:fs/promises";import{createServer as je,request as Me}from"node:http";import Ne from"picomatch";import{z as N}from"zod";import{McpServer as Pe}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Fe}from"@modelcontextprotocol/sdk/server/stdio.js";import{RootsListChangedNotificationSchema as Ie}from"@modelcontextprotocol/sdk/types.js";import{AsyncLocalStorage as Le}from"node:async_hooks";import{Bash as Re,ReadWriteFs as ze}from"just-bash";import Be from"shell-quote";import{createInterface as Ve}from"node:readline/promises";const He=`open-knowledge`;var Ue=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(He,e).getPassword();return n==null?null:JSON.parse(n)}catch{return null}}async set(e,t,n,r){let{Entry:i}=await import(`@napi-rs/keyring`),a=new i(He,e),o={login:t,token:n,...r};a.setPassword(JSON.stringify(o))}async clear(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{new t(He,e).deletePassword()}catch{}}},We=class{backend=`file`;authFile;constructor(e){this.authFile=e??ge(de(),`.open-knowledge`,`auth.yml`)}read(){if(!j(this.authFile))return{};try{return ve(ae(this.authFile,`utf-8`))??{}}catch(e){let t=e instanceof Error?e.message:`unknown error`;return process.stderr.write(`[auth] Failed to parse ${this.authFile}: ${t}. Starting with empty credentials.\n`),{}}}write(e){let t=me(this.authFile);j(t)||re(t,{recursive:!0,mode:448}),ue(this.authFile,ye(e),{mode:384})}async get(e){return this.read()[e]??null}async set(e,t,n,r){let i=this.read();i[e]={login:t,token:n,...r},this.write(i)}async clear(e){let t=this.read();delete t[e],this.write(t)}};async function Ge(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(He,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
3
3
  `),new Ue}catch{return process.stderr.write(`[auth] token storage: file (~/.open-knowledge/auth.yml)
4
4
  `),new We(e)}}async function Ke(e,t,n){let r=qe(await Je(e)).host??``;if(!r)return 1;let i=await n.get(r);if(i==null)return 1;let a=e=>e.replace(/[\r\n]/g,``);return t.write(`username=${a(i.login)}\npassword=${a(i.token)}\n`),0}function qe(e){let t={};for(let n of e.split(`
5
5
  `)){let e=n.trim();if(e===``)continue;let r=e.indexOf(`=`);r!==-1&&(t[e.slice(0,r)]=e.slice(r+1))}return t}function Je(e){return new Promise((t,n)=>{let r=[];e.on(`data`,e=>r.push(e)),e.on(`end`,()=>t(Buffer.concat(r).toString(`utf-8`))),e.on(`error`,n)})}function Ye(e){let t=new A(`git-credential`);return t.description(`Git credential helper (git credential-helper protocol)`),t.command(`get`).description(`Lookup credentials from TokenStore (called by git)`).action(async()=>{let t=await e(),n=await Ke(process.stdin,process.stdout,t);process.exit(n)}),t}async function Xe(e){let{clientId:t,scopes:n=[`repo`,`read:user`,`user:email`],onVerification:r,host:i}=e,a=i&&i!==`github.com`?`https://${i}/api/v3`:`https://api.github.com`,o=be({clientType:`oauth-app`,clientId:t,scopes:n,onVerification:async e=>{await r({verificationUri:e.verification_uri,userCode:e.user_code,expiresIn:e.expires_in,interval:e.interval})},request:a===`https://api.github.com`?void 0:(await import(`@octokit/request`)).request.defaults({baseUrl:a})}),s;try{s=await o({type:`oauth`})}catch(e){if(e instanceof Error){let t=e.message.toLowerCase();throw t.includes(`access_denied`)?Error(`Device-flow authorization was denied.`):t.includes(`expired_token`)||t.includes(`timeout`)||t.includes(`timed out`)?Error(`Device-flow code expired before authorization — please try again.`):Error(`GitHub sign-in failed: ${e.message}`)}throw e}return{token:s.token,tokenType:s.tokenType,scopes:s.scopes??[]}}function Ze(e){return process.env.OPEN_KNOWLEDGE_GITHUB_CLIENT_ID??e?.github?.oauthAppClientId??`Ov23liqlSd0V1MwR6rhI`}const Qe=new Set([`gitlab.com`,`bitbucket.org`,`codeberg.org`,`gitea.com`,`sr.ht`,`sourcehut.org`]);function $e(e){let t=e.toLowerCase().replace(/:\d+$/,``);Qe.has(t)&&(process.stderr.write(`Error: ${e} is not a GitHub host. Only GitHub and GitHub Enterprise Server are supported.\n`),process.exit(1))}function et(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function tt(e,t,n,r=Xe){let i=Ze(n),{host:a,json:o}=e;$e(a),o||process.stderr.write(`Logging in to ${a}…\n`);let s=await r({clientId:i,host:a===`github.com`?void 0:a,onVerification:e=>{e.userCode,e.verificationUri,o?et(!0,{type:`verification`,user_code:e.userCode,verification_uri:e.verificationUri,expires_in:e.expiresIn}):process.stderr.write(`Open: ${e.verificationUri}\nEnter code: ${e.userCode}\n`)}}),c=`unknown`,l,u;try{let e=a===`github.com`?`https://api.github.com`:`https://${a}/api/v3`,t=await fetch(`${e}/user`,{headers:{Authorization:`Bearer ${s.token}`,"User-Agent":`open-knowledge-cli`,Accept:`application/vnd.github+json`}});if(t.ok){let e=await t.json();c=e.login??c,l=e.name??void 0,u=e.email??void 0}}catch{}await t.set(a,c,s.token,{gitProtocol:`https`,name:l,email:u}),o?et(!0,{type:`complete`,host:a,login:c}):process.stderr.write(`✓ Logged in as ${c} on ${a}\n`)}function nt(e,t){return new A(`login`).description(`Authenticate with GitHub via Device Flow`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSONL progress events`,!1).action(async n=>{await tt(n,await t(),e())})}async function rt(e,t,n){let{host:r,json:i}=e;$e(r);let a=await(n??(()=>xe({message:`Enter PAT:`})))();a||(process.stderr.write(`No token provided
@@ -7,7 +7,7 @@ import{i as e,r as t}from"./constants-DFnJ9to1.mjs";import{O as n,c as r,k as i}
7
7
  `),process.exit(1)}await t.set(r,c,a,{gitProtocol:`https`,name:l,email:u}),i?process.stdout.write(`${JSON.stringify({type:`complete`,host:r,login:c})}\n`):process.stderr.write(`✓ PAT stored for ${c} on ${r}\n`)}function it(e){return new A(`pat`).description(`Store a Personal Access Token`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await rt(t,await e())})}async function at(e,t){let{host:n,json:r}=e;$e(n);let i=await t.get(n);i??(process.stderr.write(`Not logged in to ${n}\n`),process.exit(1));let a=n===`github.com`?void 0:`https://${n}/api/v3`,o=new Se({auth:i.token,...a?{baseUrl:a}:{}}),s=[];for await(let e of o.paginate.iterator(o.repos.listForAuthenticatedUser,{per_page:100,sort:`updated`}))for(let t of e.data)s.push({full_name:t.full_name,clone_url:t.clone_url,private:t.private});if(r)process.stdout.write(`${JSON.stringify({type:`repos`,host:n,repos:s})}\n`);else for(let e of s)process.stdout.write(`${e.full_name} ${e.clone_url}\n`)}function ot(e){return new A(`repos`).description(`List accessible repositories`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await at(t,await e())})}async function st(e,t){let{host:n}=e;await t.clear(n),process.stderr.write(`✓ Signed out from ${n}\n`)}function ct(e){return new A(`signout`).description(`Remove stored credentials`).option(`--host <host>`,`GitHub hostname`,`github.com`).action(async t=>{await st(t,await e())})}async function lt(e,t){let{host:n,json:r}=e;$e(n);let i=await t.get(n);i??(r?process.stdout.write(`${JSON.stringify({type:`status`,host:n,authenticated:!1})}\n`):process.stderr.write(`Not logged in to ${n}\n`),process.exit(1));let a=n===`github.com`?void 0:`https://${n}/api/v3`,o=new Se({auth:i.token,...a?{baseUrl:a}:{}});try{let{data:e}=await o.users.getAuthenticated();r?process.stdout.write(`${JSON.stringify({type:`status`,host:n,authenticated:!0,login:e.login,name:e.name,email:e.email})}\n`):process.stderr.write(`✓ Logged in as ${e.login} on ${n}\n`)}catch{r?process.stdout.write(JSON.stringify({type:`status`,host:n,authenticated:!1,error:`token invalid`})+`
8
8
  `):process.stderr.write(`✗ Token invalid for ${n}\n`),process.exit(1)}}function ut(e){return new A(`status`).description(`Show authentication status`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await lt(t,await e())})}function dt(e){let t=new A(`auth`);t.description(`GitHub authentication management`);let n=()=>Ge(),r=e??(()=>({}));return t.addCommand(nt(r,n)),t.addCommand(ut(n)),t.addCommand(ot(n)),t.addCommand(ct(n)),t.addCommand(it(n)),t.addCommand(Ye(n)),t}function ft(e,t,n={}){let r=h(e,t);if(!j(r))return{status:`missing`,lockPath:r};let i;try{i=JSON.parse(ae(r,`utf-8`))}catch{return{status:`corrupt`,lockPath:r}}if(!i||typeof i!=`object`||typeof i.pid!=`number`)return{status:`corrupt`,lockPath:r};let a=i,o=n.host??fe();return a.hostname===o?(n.isAlive??g)(a.pid)?{status:`alive`,lockPath:r,lock:a}:{status:`dead-pid`,lockPath:r,lock:a}:{status:`foreign-host`,lockPath:r,lock:a}}function pt(e,t){let n=[];for(let[r,i]of[[`server`,e],[`ui`,t]])(i.status===`dead-pid`||i.status===`corrupt`)&&n.push({name:r,lockPath:i.lockPath,reason:i.status});return{prune:n}}function mt(e){let t=e.inspect??(t=>ft(e.lockDir,t)),n=e.unlink??(e=>le(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=pt(t(`server`),t(`ui`));if(a.prune.length===0)return r(`No stale locks.`),{pruned:[],failed:[]};let o=[],s=[];for(let e of a.prune)try{n(e.lockPath),o.push(e)}catch(t){s.push({target:e,error:t instanceof Error?t.message:String(t)})}if(o.length>0){let e=o.map(e=>`${e.name} (${e.reason})`).join(`, `);r(`Pruned ${o.length} stale lock${o.length===1?``:`s`}: ${e}`)}return s.length>0&&i(`Failed to prune: ${s.map(({target:e,error:t})=>`${e.name} (${e.lockPath}): ${t}`).join(`; `)}`),{pruned:o,failed:s}}function ht(e){return new A(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{mt({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}function gt(){try{let e=Te(`gh`,[`auth`,`token`],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`pipe`],timeout:5e3}).trim();return e.length===0?{available:!1}:{available:!0,token:e}}catch{return{available:!1}}}async function _t(e,t,n={},r=gt){if(!n.skipGhDetect&&r().available)return{tier:`A`,credentialArgs:[`-c`,`credential.helper=!gh auth git-credential`]};let i=await t.get(e);return i==null?{tier:`none`,credentialArgs:[]}:{tier:i.gitProtocol===`ssh`?`C`:`B`,credentialArgs:[`-c`,`credential.helper=!open-knowledge auth git-credential`]}}function vt(e){return e.replace(/:\d+$/,``)}function yt(e){let t=e.trim();if(!t)return null;{let e=/^https?:\/\/([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`https`,hostname:vt(e[1]),owner:e[2],name:e[3]}}{let e=/^ssh:\/\/(?:[\w.-]+@)?([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`ssh`,hostname:vt(e[1]),owner:e[2],name:e[3]}}{let e=/^git:\/\/([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`git`,hostname:vt(e[1]),owner:e[2],name:e[3]}}{let e=/^(?:[\w.-]+@)?([\w.-]+):([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?$/.exec(t);if(e?.[1].includes(`.`)||e&&t.startsWith(`git@`))return{protocol:`ssh`,hostname:e[1],owner:e[2],name:e[3]}}{let e=/^git:([\w.-]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`git`,hostname:e[1],owner:e[2],name:e[3]}}if(!t.includes(`://`)&&!t.includes(`@`)&&!t.startsWith(`/`)){let e=/^([\w.-]+)\/([\w.\-~%]+?)(?:\.git)?$/.exec(t);if(e)return{protocol:`https`,hostname:`github.com`,owner:e[1],name:e[2]}}return null}const bt=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function xt(e){let t=/^([\w ]+):\s+(\d+)%/.exec(e.trim());if(!t)return null;let n=t[1].toLowerCase(),r=Number(t[2]);for(let[e,i,a]of bt)if(n.includes(e))return{stage:t[1],pct:Math.round(i+r/100*(a-i))};return null}function St(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Ct(e,t,n,r=process.cwd()){let i=yt(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=t.dir?M(r,t.dir):M(r,i.name);if(j(a)&&oe(a).length>0)throw Error(`Target directory is not empty: ${a}`);let o=await Ge(),s=await _t(i.hostname,o,{}),c=De({baseDir:r,config:s.credentialArgs.length>=2?[s.credentialArgs[1]]:[],unsafe:{allowUnsafeCredentialHelper:!0}}).env({GIT_TERMINAL_PROMPT:`0`}),l=-1;if(c.outputHandler((e,n,r)=>{r.on(`data`,e=>{let n=e.toString(`utf-8`);for(let e of n.split(`
9
9
  `)){let n=xt(e);n&&n.pct!==l&&(l=n.pct,St(t.json,{type:`progress`,pct:n.pct,stage:n.stage}),t.json||process.stderr.write(`\r Cloning… ${n.pct}%`))}})}),await c.clone(e,a,[`--progress`]),t.json||process.stderr.write(`
10
- `),!j(M(a,`.open-knowledge`)))try{let[{runInit:e},{ensureOkGitignoredAtRoot:t}]=await Promise.all([import(`./init-BUjbq0wU.mjs`),import(`./init-CDn_Us0v.mjs`)]);await e({cwd:a,mcp:!1});try{t(a)}catch{}}catch{}return a}function wt(e){return new A(`clone`).description(`Clone a git repository and open it`).argument(`<url>`,`Repository URL or owner/repo shorthand`).argument(`[dir]`,`Target directory (default: ./<repo-name>)`).option(`--json`,`Output JSONL progress events`,!1).action(async(t,n,r)=>{let i=e();try{let a=await Ct(t,{json:r.json,dir:n},i);if(r.json)St(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-DG-wBj9K.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?St(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}const Tt=new Le;var Et=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??we().slice(0,12),this.corrId=we().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,n={}){let r=t?{error:t instanceof Error?t.message:String(t),...n}:n;this.emit(`error`,e,r)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,n){let r={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...n},i=`${JSON.stringify(r)}\n`;process.stderr.write(i);let a=process.env.OK_LOG_FILE;if(a)try{te(a,i)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function Dt(e=`mcp`){return new Et(e)}function Ot(e,t){return Tt.run(e,t)}function kt(){return Tt.getStore()}const At=new Set([`find`,`markdown`,`replace`]),jt=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],Mt=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function P(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Nt(e){return P(e)&&`requestId`in e}function Pt(e,t){if(At.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
10
+ `),!j(M(a,`.open-knowledge`)))try{let[{runInit:e},{ensureOkGitignoredAtRoot:t}]=await Promise.all([import(`./init-3UxRGVAs.mjs`),import(`./init-AmgsVReV.mjs`)]);await e({cwd:a,mcp:!1});try{t(a)}catch{}}catch{}return a}function wt(e){return new A(`clone`).description(`Clone a git repository and open it`).argument(`<url>`,`Repository URL or owner/repo shorthand`).argument(`[dir]`,`Target directory (default: ./<repo-name>)`).option(`--json`,`Output JSONL progress events`,!1).action(async(t,n,r)=>{let i=e();try{let a=await Ct(t,{json:r.json,dir:n},i);if(r.json)St(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-Dta5BSHL.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?St(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}const Tt=new Le;var Et=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??we().slice(0,12),this.corrId=we().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,n={}){let r=t?{error:t instanceof Error?t.message:String(t),...n}:n;this.emit(`error`,e,r)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,n){let r={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...n},i=`${JSON.stringify(r)}\n`;process.stderr.write(i);let a=process.env.OK_LOG_FILE;if(a)try{te(a,i)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function Dt(e=`mcp`){return new Et(e)}function Ot(e,t){return Tt.run(e,t)}function kt(){return Tt.getStore()}const At=new Set([`find`,`markdown`,`replace`]),jt=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],Mt=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function P(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Nt(e){return P(e)&&`requestId`in e}function Pt(e,t){if(At.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
11
11
  `).length};let n=e===`command`?240:120;return t.length<=n?t:{type:`string`,length:t.length,preview:`${t.slice(0,n)}...`}}function Ft(e,t){if(t===null)return null;if(typeof t==`string`)return Pt(e,t);if(typeof t==`number`||typeof t==`boolean`)return t;if(Array.isArray(t))return{type:`array`,length:t.length};if(P(t)){let e=Object.keys(t).sort();return{type:`object`,keyCount:e.length,keys:e.slice(0,12)}}if(t!==void 0)return{type:typeof t}}function It(e,t){return P(t)?Object.fromEntries(Object.entries(t).map(([e,t])=>[e,Ft(e,t)])):Ft(e,t)}function Lt(e){let t={structuredKeys:Object.keys(e).sort()};for(let n of Mt)n in e&&(t[n]=e[n]);for(let n of jt){let r=e[n];Array.isArray(r)&&(t[`${n}Count`]=r.length)}return`previewUrl`in e&&(t.previewUrl=e.previewUrl??null),`previewUrlSource`in e&&(t.previewUrlSource=e.previewUrlSource),typeof e.stdout==`string`&&(t.stdoutChars=e.stdout.length),Array.isArray(e.warnings)&&(t.warningsCount=e.warnings.length),P(e.warning)&&(t.warning=!0,`previewUrl`in e.warning&&(t.warningPreviewUrl=e.warning.previewUrl??null)),P(e.ui)&&(t.uiBaseUrl=typeof e.ui.baseUrl==`string`||e.ui.baseUrl===null?e.ui.baseUrl:void 0,t.uiPort=typeof e.ui.port==`number`||e.ui.port===null?e.ui.port:void 0),t}function Rt(e){if(!P(e))return{resultType:typeof e};let t={isError:e.isError===!0};return Array.isArray(e.content)&&(t.contentItems=e.content.length,t.contentTextChars=e.content.reduce((e,t)=>P(t)&&typeof t.text==`string`?e+t.text.length:e,0)),P(e.structuredContent)&&Object.assign(t,Lt(e.structuredContent)),t}function zt(e){return{connectionId:e.connectionId.slice(0,8),displayName:e.displayName,...e.clientInfo?.name?{clientName:e.clientInfo.name}:{},...e.label?{label:e.label}:{}}}function Bt(e){let t=e.at(-1);return Nt(t)?{toolArgs:e.length>1?e[0]:void 0,extra:t}:{toolArgs:e[0],extra:void 0}}function Vt(e,t,n){let r=n.logger;return r?async(...i)=>{let a=r.child(),o=Date.now(),{toolArgs:s,extra:c}=Bt(i);a.info(`tool start`,{tool:e,...c?.requestId===void 0?{}:{requestId:c.requestId},...c?.sessionId?{transportSessionId:c.sessionId}:{},...n.identityRef?.current?{agent:zt(n.identityRef.current)}:{},...s===void 0?{}:{args:It(e,s)}});try{let n=await Ot(a,async()=>await t(...i));return a.info(`tool finish`,{tool:e,...c?.requestId===void 0?{}:{requestId:c.requestId},durationMs:Date.now()-o,result:Rt(n)}),n}catch(t){throw a.error(`tool error`,t,{tool:e,...c?.requestId===void 0?{}:{requestId:c.requestId},durationMs:Date.now()-o}),t}}:t}function Ht(e,t){if(!t.logger)return e;let n=e.tool.bind(e),r=Object.create(e);return r.tool=((...e)=>{let r=String(e[0]),i=e.at(-1);if(typeof i!=`function`)return n(...e);let a=[...e];return a[a.length-1]=Vt(r,i,t),n(...a)}),r}const F="Absolute host path to resolve the request against. Defaults only when the MCP client advertises exactly one root; otherwise pass `cwd` explicitly.",Ut=N.string().max(200).optional().describe(`Optional one-line user-outcome description (≤80 chars). Appears as a bullet in the timeline.`);function I(e,t){return{content:[{type:`text`,text:e}],...t?{isError:!0}:{}}}function L(e,t,n){return{content:[{type:`text`,text:e}],structuredContent:t,...n?{isError:!0}:{}}}const R="Error: Hocuspocus server is not running. Start it with `open-knowledge start`, then retry.\nFor disk-only writes without real-time sync, use your native Edit tool directly.",Wt={ingest:`raw-sources layer (preserve external material, no analysis)`,research:`wiki layer, provisional (synthesize findings that can still change)`,consolidate:`wiki layer, canonical (promote stabilized research to source-of-truth)`},Gt={ingest:"user shares a URL or file they want preserved, or `research` needs raw sources",research:"`ingest` has captured the relevant sources (or the user points at one)",consolidate:"`research` has produced a provisional article AND a decision has actually been made"},Kt={ingest:"often `research` on the same topic — or just stop; raw preservation is frequently enough on its own",research:"usually stop (research lives as provisional indefinitely) or `consolidate` once a decision lands",consolidate:"update 2–3 neighbor docs to link the new canonical article; research articles it supersedes gain a `superseded_by` pointer"};function qt(e){return`## Where this fits
12
12
 
13
13
  Open Knowledge accretes a persistent wiki through three workflow tools, mapped to [Karpathy's three-layer knowledge-base pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f):
@@ -664,8 +664,8 @@ Claude Code Desktop: \`preview_start("open-knowledge-ui")\`. Other hosts: open-U
664
664
  Detailed conventions (wiki-link authoring, frontmatter, anti-patterns) live in the installed \`open-knowledge\` Agent Skill. If missing, run \`npx @inkeep/open-knowledge init\`.
665
665
 
666
666
  **Escape hatch.** Native \`Read\`/\`Grep\`/\`Glob\` on \`.md\` is allowed ONLY when no OK MCP is registered, or immediately after an OK MCP call failed — then begin your sentence with \`Open Knowledge MCP unavailable:\`. Non-markdown: native tools always.
667
- `}async function Ni(e,t){try{let t=e.replace(`ws://`,`http://`).replace(`wss://`,`https://`);return(await fetch(`${t}/api/document`,{signal:AbortSignal.timeout(2e3)})).ok}catch(n){return t.warn(`Hocuspocus probe failed`,{serverUrl:e,error:n instanceof Error?n.message:String(n)}),!1}}async function Pi(n){let{projectDir:r,serverUrl:i,config:a,startupConfig:o,bypassProjectSelection:s=!1}=n;if(X=Dt(),X.info(`MCP server starting`,{startupCwd:r,bypassProjectSelection:s,serverUrlType:typeof i==`string`?`explicit`:`lazy`}),typeof i==`string`){let e=await Ni(i,X);X.info(`Hocuspocus detection complete`,{serverUrl:i,available:e})}else X.info(`server discovery is lazy per effective cwd`);let c=new Pe({name:t,version:e},{instructions:Mi(o,{dynamicConfig:typeof a==`function`&&!s})}),l=Ai({startupCwd:r,bypassProjectSelection:s,listRoots:()=>c.server.listRoots(),logger:X}),u=ji({startupCwd:r,resolveCwd:l.resolveCwd,bypassProjectSelection:s}),d=u.resolveCwdForTools;c.server.setNotificationHandler(Ie,async()=>{l.invalidateRoots()});let f=async e=>{if(typeof i==`string`)return i.replace(`ws://`,`http://`).replace(`wss://`,`https://`);let t=e??await d();return(typeof i==`function`?await i(t):i)?.replace(`ws://`,`http://`).replace(`wss://`,`https://`)},p=we(),m=process.env.AGENT_LABEL||void 0,h={current:{connectionId:p,label:m,displayName:m??`Agent`,colorSeed:m??p}};c.server.oninitialized=()=>{let e=c.server.getClientVersion();h.current={connectionId:p,clientInfo:e?{name:e.name,version:e.version}:void 0,label:m,displayName:m??e?.name??`Agent`,colorSeed:m??e?.name??p},X?.info(`agent identity established`,{displayName:h.current.displayName,connectionId:p.slice(0,8),clientName:e?.name})},Di(c,{serverUrl:f,resolveCwd:d,config:a,identityRef:h,logger:X});let g=new Fe;await c.connect(g),X.info(`MCP server running on stdio`);let{startKeepalive:_}=await import(`./keepalive-CfaIYv9f.mjs`),v=_({resolveWsUrl:async()=>{let e=await u.getKeepaliveCwd();if(!e)return;let t=await f(e);if(t)return t.replace(/^http:/,`ws:`).replace(/^https:/,`wss:`)},connectionId:`agent-${p}`,logger:X.child(`keepalive`)}),y=e=>{X?.info(`MCP server shutting down`,{signal:e});try{v.close()}catch{}process.exit(0)};process.on(`SIGINT`,()=>y(`SIGINT`)),process.on(`SIGTERM`,()=>y(`SIGTERM`))}function Fi(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function Ii(e){if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t))return{action:`disk-only`,message:`invalid --port value '${e.portOverride}' — disk-only mode`};if(t>0){let n=`ws://${e.host}:${t}`;return{action:`connect`,url:n,message:`using --port override, connecting to ${n}`}}return{action:`disk-only`,message:`--port=0 — disk-only mode`}}let t=e.readLock();if(t&&t.port>0&&e.isAlive(t.pid)){let e=`ws://localhost:${t.port}`;return{action:`connect`,url:e,message:`connected to running instance at ${e} (pid ${t.pid})`}}return e.envAutoStart===`0`?{action:`disk-only`,message:`auto-spawn disabled via OK_MCP_AUTOSTART=0 — disk-only mode`}:e.configAutoStart?t?{action:`spawn`,message:`existing lock is not usable (port=${t.port}, pid=${t.pid}) — spawning ok start`}:{action:`spawn`,message:`no running instance — spawning ok start`}:{action:`disk-only`,message:`auto-spawn disabled via config.mcp.autoStart=false — disk-only mode`}}async function Li(e){let t=e.readLock??(()=>_(e.lockDir)),n=e.isAlive??g,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),i=e.spawn??Ee,a=e.readErrorLog??(e=>j(e)?ae(e,`utf-8`).trim():``),o=e.openErrorLog??(e=>ie(e,`w`)),s=e.closeFd??(e=>ne(e)),c=e.timeoutMs??5e3,l=e.pollIntervalMs??100,u=Ii({host:e.host,portOverride:e.portOverride,envAutoStart:e.envAutoStart,configAutoStart:e.configAutoStart,readLock:t,isAlive:n});if(e.logger?.info(`auto-start decision`,{action:u.action,message:u.message,contentDir:e.contentDir}),u.action===`connect`)return{serverUrl:u.url,message:u.message};if(u.action===`disk-only`)return{serverUrl:void 0,message:u.message};j(e.lockDir)||re(e.lockDir,{recursive:!0});let d=ge(e.lockDir,`last-spawn-error.log`),f=o(d),p,m,h=k();e.logger?.info(`spawning server`,{command:h.command,cwd:e.contentDir,timeoutMs:c});try{try{p=i(h.command,[...h.prefixArgs,`start`],{detached:!0,stdio:[`ignore`,`ignore`,f],cwd:e.contentDir}),p.on(`error`,e=>{m=e instanceof Error?e.message:String(e)}),p.unref()}catch(e){m=e instanceof Error?e.message:String(e)}}finally{try{s(f)}catch{}}let v=Date.now()+c;for(;Date.now()<v;){if(m){let t=a(d);throw e.logger?.error(`spawn failed`,void 0,{error:m,stderr:t}),Error(`Error: spawn failed: ${m}${t?` stderr:\n${t}`:``}`)}await r(l);let i=t();if(i&&i.port>0&&n(i.pid)){let t=`ws://localhost:${i.port}`;return e.logger?.info(`server ready after spawn`,{url:t,pid:i.pid}),{serverUrl:t,message:`spawned ok start; connected at ${t} (pid ${i.pid})`}}}if(m){let t=a(d);throw e.logger?.error(`spawn failed (post-deadline)`,void 0,{error:m,stderr:t}),Error(`Error: spawn failed: ${m}${t?` stderr:\n${t}`:``}`)}let y=a(d),b=(c/1e3).toFixed(c%1e3==0?0:2),x=p?.pid,S=``;throw typeof x==`number`&&(S=n(x)?` child pid=${x} is still running — raise OK_MCP_SPAWN_TIMEOUT_MS if this is a slow boot.`:` child pid=${x} exited — check last-spawn-error.log.`),e.logger?.error(`spawn poll timeout`,void 0,{timeoutMs:c,childPid:x,childAlive:typeof x==`number`?n(x):void 0,stderr:y||void 0}),Error(`Error: server did not start within ${b}s.${S}${y?` stderr:\n${y}`:``}`)}function Ri(e){if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t)||t<=0)return async()=>void 0;let n=`ws://${e.host}:${t}`;return async()=>n}let t=e.ensureServerRunningFn??Li,n=e.cacheMs??1e3,r=new Map,i=new Map;return async s=>{let c=await E(s??e.startupCwd),l=Date.now(),u=r.get(c);if(u&&u.expiresAt>l)return e.logger?.debug(`server url cache hit`,{cwd:c,url:u.url}),u.url;let d=i.get(c);if(d)return e.logger?.debug(`server url resolution pending`,{cwd:c}),await d;e.logger?.debug(`server url cache miss`,{cwd:c});let f=(async()=>{let i=await e.resolveConfig(c),s=o(i,c),l=a(s),u=e.readLock,d=u?()=>u(l):void 0,f=await t({lockDir:l,contentDir:s,host:i.server.host,portOverride:void 0,envAutoStart:e.envAutoStart,configAutoStart:i.mcp.autoStart,logger:e.logger,timeoutMs:e.timeoutMs,pollIntervalMs:e.pollIntervalMs,spawn:e.spawn,readLock:d,isAlive:e.isAlive,sleep:e.sleep,readErrorLog:e.readErrorLog,openErrorLog:e.openErrorLog,closeFd:e.closeFd});return r.set(c,{url:f.serverUrl,expiresAt:Date.now()+n}),f.serverUrl})();i.set(c,f);try{return await f}finally{i.delete(c)}}}function zi(e){return new A(`mcp`).description(`Start MCP stdio server for project knowledge base`).option(`-p, --port <port>`,`Override port discovery and connect to this port (0 = disk-only)`,void 0).action(async t=>{try{let n=e(),r=process.cwd(),i=O({startupCwd:r,startupConfig:n}),a=Fi(process.env.OK_MCP_SPAWN_TIMEOUT_MS),o,s;if(t.port!==void 0){let e=Number.parseInt(t.port,10);Number.isNaN(e)?(o=void 0,s=`invalid --port value '${t.port}' — disk-only mode`):e>0?(o=`ws://${n.server.host}:${e}`,s=`using --port override, connecting to ${o}`):(o=void 0,s=`--port=0 — disk-only mode`)}else o=Ri({startupCwd:r,resolveConfig:i,host:n.server.host,portOverride:void 0,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:a}),s=`project server discovery/autostart is lazy per effective cwd`;process.stderr.write(`[mcp] ${s}\n`),await Pi({projectDir:r,serverUrl:o,config:i,startupConfig:n,bypassProjectSelection:t.port!==void 0})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function Bi(e){return new A(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-BcZ1UmA0.mjs`),r=e(),i=process.cwd(),a=o(r,i),s;try{s=t({projectDir:i,contentDir:a,include:r.content.include,exclude:r.content.exclude})}catch(e){console.error(`Content preview failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}process.stdout.write(`${n(s,i)}\n`),s.totalCount===0&&s.warnings.length>0&&(process.exitCode=1)})}function Z(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Vi(e,t,n=process.cwd()){let r=e.op??`sync`,i=_(a(o(t,n)));if(i&&i.port>0){let t=`http://127.0.0.1:${i.port}/api/sync/trigger`;e.json||process.stderr.write(`Triggering ${r} via running server (port ${i.port})…\n`);try{let n=await fetch(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({op:r})});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error??`Server responded with ${n.status}`)}Z(e.json,{type:`triggered`,op:r,port:i.port}),e.json||process.stderr.write(`✓ ${r} triggered\n`);return}catch(t){let n=t instanceof Error?t.message:String(t);e.json||process.stderr.write(`Server trigger failed (${n}), running directly…\n`)}}e.json||process.stderr.write(`Running ${r} directly (no live server)…\n`);let s=De({baseDir:n});if(r===`sync`||r===`pull`){Z(e.json,{type:`step`,step:`pull`});let t=await s.pull();Z(e.json,{type:`pull`,summary:t.summary}),e.json||process.stderr.write(` pull: ${t.summary.changes} changes\n`)}(r===`sync`||r===`push`)&&(Z(e.json,{type:`step`,step:`push`}),await s.push(),Z(e.json,{type:`push`,ok:!0}),e.json||process.stderr.write(` push: ok
667
+ `}async function Ni(e,t){try{let t=e.replace(`ws://`,`http://`).replace(`wss://`,`https://`);return(await fetch(`${t}/api/document`,{signal:AbortSignal.timeout(2e3)})).ok}catch(n){return t.warn(`Hocuspocus probe failed`,{serverUrl:e,error:n instanceof Error?n.message:String(n)}),!1}}async function Pi(n){let{projectDir:r,serverUrl:i,config:a,startupConfig:o,bypassProjectSelection:s=!1}=n;if(X=Dt(),X.info(`MCP server starting`,{startupCwd:r,bypassProjectSelection:s,serverUrlType:typeof i==`string`?`explicit`:`lazy`}),typeof i==`string`){let e=await Ni(i,X);X.info(`Hocuspocus detection complete`,{serverUrl:i,available:e})}else X.info(`server discovery is lazy per effective cwd`);let c=new Pe({name:t,version:e},{instructions:Mi(o,{dynamicConfig:typeof a==`function`&&!s})}),l=Ai({startupCwd:r,bypassProjectSelection:s,listRoots:()=>c.server.listRoots(),logger:X}),u=ji({startupCwd:r,resolveCwd:l.resolveCwd,bypassProjectSelection:s}),d=u.resolveCwdForTools;c.server.setNotificationHandler(Ie,async()=>{l.invalidateRoots()});let f=async e=>{if(typeof i==`string`)return i.replace(`ws://`,`http://`).replace(`wss://`,`https://`);let t=e??await d();return(typeof i==`function`?await i(t):i)?.replace(`ws://`,`http://`).replace(`wss://`,`https://`)},p=we(),m=process.env.AGENT_LABEL||void 0,h={current:{connectionId:p,label:m,displayName:m??`Agent`,colorSeed:m??p}};c.server.oninitialized=()=>{let e=c.server.getClientVersion();h.current={connectionId:p,clientInfo:e?{name:e.name,version:e.version}:void 0,label:m,displayName:m??e?.name??`Agent`,colorSeed:m??e?.name??p},X?.info(`agent identity established`,{displayName:h.current.displayName,connectionId:p.slice(0,8),clientName:e?.name})},Di(c,{serverUrl:f,resolveCwd:d,config:a,identityRef:h,logger:X});let g=new Fe;await c.connect(g),X.info(`MCP server running on stdio`);let{startKeepalive:_}=await import(`./keepalive-CfaIYv9f.mjs`),v=_({resolveWsUrl:async()=>{let e=await u.getKeepaliveCwd();if(!e)return;let t=await f(e);if(t)return t.replace(/^http:/,`ws:`).replace(/^https:/,`wss:`)},connectionId:`agent-${p}`,logger:X.child(`keepalive`)}),y=e=>{X?.info(`MCP server shutting down`,{signal:e});try{v.close()}catch{}process.exit(0)};process.on(`SIGINT`,()=>y(`SIGINT`)),process.on(`SIGTERM`,()=>y(`SIGTERM`))}function Fi(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function Ii(e){if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t))return{action:`disk-only`,message:`invalid --port value '${e.portOverride}' — disk-only mode`};if(t>0){let n=`ws://${e.host}:${t}`;return{action:`connect`,url:n,message:`using --port override, connecting to ${n}`}}return{action:`disk-only`,message:`--port=0 — disk-only mode`}}let t=e.readLock();if(t&&t.port>0&&e.isAlive(t.pid)){let e=`ws://localhost:${t.port}`;return{action:`connect`,url:e,message:`connected to running instance at ${e} (pid ${t.pid})`}}return e.envAutoStart===`0`?{action:`disk-only`,message:`auto-spawn disabled via OK_MCP_AUTOSTART=0 — disk-only mode`}:e.configAutoStart?t?{action:`spawn`,message:`existing lock is not usable (port=${t.port}, pid=${t.pid}) — spawning ok start`}:{action:`spawn`,message:`no running instance — spawning ok start`}:{action:`disk-only`,message:`auto-spawn disabled via config.mcp.autoStart=false — disk-only mode`}}async function Li(e){let t=e.readLock??(()=>_(e.lockDir)),n=e.isAlive??g,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),i=e.spawn??Ee,a=e.readErrorLog??(e=>j(e)?ae(e,`utf-8`).trim():``),o=e.openErrorLog??(e=>ie(e,`w`)),s=e.closeFd??(e=>ne(e)),c=e.timeoutMs??5e3,l=e.pollIntervalMs??100,u=Ii({host:e.host,portOverride:e.portOverride,envAutoStart:e.envAutoStart,configAutoStart:e.configAutoStart,readLock:t,isAlive:n});if(e.logger?.info(`auto-start decision`,{action:u.action,message:u.message,contentDir:e.contentDir}),u.action===`connect`)return{serverUrl:u.url,message:u.message};if(u.action===`disk-only`)return{serverUrl:void 0,message:u.message};j(e.lockDir)||re(e.lockDir,{recursive:!0});let d=ge(e.lockDir,`last-spawn-error.log`),f=o(d),p,m,h=k();e.logger?.info(`spawning server`,{command:h.command,cwd:e.contentDir,timeoutMs:c});try{try{p=i(h.command,[...h.prefixArgs,`start`],{detached:!0,stdio:[`ignore`,`ignore`,f],cwd:e.contentDir}),p.on(`error`,e=>{m=e instanceof Error?e.message:String(e)}),p.unref()}catch(e){m=e instanceof Error?e.message:String(e)}}finally{try{s(f)}catch{}}let v=Date.now()+c;for(;Date.now()<v;){if(m){let t=a(d);throw e.logger?.error(`spawn failed`,void 0,{error:m,stderr:t}),Error(`Error: spawn failed: ${m}${t?` stderr:\n${t}`:``}`)}await r(l);let i=t();if(i&&i.port>0&&n(i.pid)){let t=`ws://localhost:${i.port}`;return e.logger?.info(`server ready after spawn`,{url:t,pid:i.pid}),{serverUrl:t,message:`spawned ok start; connected at ${t} (pid ${i.pid})`}}}if(m){let t=a(d);throw e.logger?.error(`spawn failed (post-deadline)`,void 0,{error:m,stderr:t}),Error(`Error: spawn failed: ${m}${t?` stderr:\n${t}`:``}`)}let y=a(d),b=(c/1e3).toFixed(c%1e3==0?0:2),x=p?.pid,S=``;throw typeof x==`number`&&(S=n(x)?` child pid=${x} is still running — raise OK_MCP_SPAWN_TIMEOUT_MS if this is a slow boot.`:` child pid=${x} exited — check last-spawn-error.log.`),e.logger?.error(`spawn poll timeout`,void 0,{timeoutMs:c,childPid:x,childAlive:typeof x==`number`?n(x):void 0,stderr:y||void 0}),Error(`Error: server did not start within ${b}s.${S}${y?` stderr:\n${y}`:``}`)}function Ri(e){if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t)||t<=0)return async()=>void 0;let n=`ws://${e.host}:${t}`;return async()=>n}let t=e.ensureServerRunningFn??Li,n=e.cacheMs??1e3,r=new Map,i=new Map;return async s=>{let c=await E(s??e.startupCwd),l=Date.now(),u=r.get(c);if(u&&u.expiresAt>l)return e.logger?.debug(`server url cache hit`,{cwd:c,url:u.url}),u.url;let d=i.get(c);if(d)return e.logger?.debug(`server url resolution pending`,{cwd:c}),await d;e.logger?.debug(`server url cache miss`,{cwd:c});let f=(async()=>{let i=await e.resolveConfig(c),s=o(i,c),l=a(s),u=e.readLock,d=u?()=>u(l):void 0,f=await t({lockDir:l,contentDir:s,host:i.server.host,portOverride:void 0,envAutoStart:e.envAutoStart,configAutoStart:i.mcp.autoStart,logger:e.logger,timeoutMs:e.timeoutMs,pollIntervalMs:e.pollIntervalMs,spawn:e.spawn,readLock:d,isAlive:e.isAlive,sleep:e.sleep,readErrorLog:e.readErrorLog,openErrorLog:e.openErrorLog,closeFd:e.closeFd});return r.set(c,{url:f.serverUrl,expiresAt:Date.now()+n}),f.serverUrl})();i.set(c,f);try{return await f}finally{i.delete(c)}}}function zi(e){return new A(`mcp`).description(`Start MCP stdio server for project knowledge base`).option(`-p, --port <port>`,`Override port discovery and connect to this port (0 = disk-only)`,void 0).action(async t=>{try{let n=e(),r=process.cwd(),i=O({startupCwd:r,startupConfig:n}),a=Fi(process.env.OK_MCP_SPAWN_TIMEOUT_MS),o,s;if(t.port!==void 0){let e=Number.parseInt(t.port,10);Number.isNaN(e)?(o=void 0,s=`invalid --port value '${t.port}' — disk-only mode`):e>0?(o=`ws://${n.server.host}:${e}`,s=`using --port override, connecting to ${o}`):(o=void 0,s=`--port=0 — disk-only mode`)}else o=Ri({startupCwd:r,resolveConfig:i,host:n.server.host,portOverride:void 0,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:a}),s=`project server discovery/autostart is lazy per effective cwd`;process.stderr.write(`[mcp] ${s}\n`),await Pi({projectDir:r,serverUrl:o,config:i,startupConfig:n,bypassProjectSelection:t.port!==void 0})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function Bi(e){return new A(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-DzHGOZjd.mjs`),r=e(),i=process.cwd(),a=o(r,i),s;try{s=t({projectDir:i,contentDir:a,include:r.content.include,exclude:r.content.exclude})}catch(e){console.error(`Content preview failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}process.stdout.write(`${n(s,i)}\n`),s.totalCount===0&&s.warnings.length>0&&(process.exitCode=1)})}function Z(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Vi(e,t,n=process.cwd()){let r=e.op??`sync`,i=_(a(o(t,n)));if(i&&i.port>0){let t=`http://127.0.0.1:${i.port}/api/sync/trigger`;e.json||process.stderr.write(`Triggering ${r} via running server (port ${i.port})…\n`);try{let n=await fetch(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({op:r})});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.error??`Server responded with ${n.status}`)}Z(e.json,{type:`triggered`,op:r,port:i.port}),e.json||process.stderr.write(`✓ ${r} triggered\n`);return}catch(t){let n=t instanceof Error?t.message:String(t);e.json||process.stderr.write(`Server trigger failed (${n}), running directly…\n`)}}e.json||process.stderr.write(`Running ${r} directly (no live server)…\n`);let s=De({baseDir:n});if(r===`sync`||r===`pull`){Z(e.json,{type:`step`,step:`pull`});let t=await s.pull();Z(e.json,{type:`pull`,summary:t.summary}),e.json||process.stderr.write(` pull: ${t.summary.changes} changes\n`)}(r===`sync`||r===`push`)&&(Z(e.json,{type:`step`,step:`push`}),await s.push(),Z(e.json,{type:`push`,ok:!0}),e.json||process.stderr.write(` push: ok
668
668
  `)),Z(e.json,{type:`complete`,op:r}),e.json||process.stderr.write(`✓ ${r} complete\n`)}function Hi(e){return new A(`sync`).description(`Commit, pull, and push to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Vi({json:t.json,op:`sync`},e())}catch(e){let n=e instanceof Error?e.message:String(e);t.json?process.stdout.write(`${JSON.stringify({type:`error`,message:n})}\n`):process.stderr.write(`✗ sync failed: ${n}\n`),process.exit(1)}})}function Ui(e){return new A(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Vi({json:t.json,op:`pull`},e())}catch(e){let n=e instanceof Error?e.message:String(e);t.json?process.stdout.write(`${JSON.stringify({type:`error`,message:n})}\n`):process.stderr.write(`✗ pull failed: ${n}\n`),process.exit(1)}})}function Wi(e){return new A(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Vi({json:t.json,op:`push`},e())}catch(e){let n=e instanceof Error?e.message:String(e);t.json?process.stdout.write(`${JSON.stringify({type:`error`,message:n})}\n`):process.stderr.write(`✗ push failed: ${n}\n`),process.exit(1)}})}async function Gi(e={}){let t=M(e.cwd??process.cwd()),n;try{n=await m({projectDir:t})}catch(e){return e instanceof s?{status:`prerequisite-missing`,message:`${x(`Error:`)} ${e.message}`,exitCode:1}:{status:`failed`,message:`${x(`Error:`)} ${e instanceof Error?e.message:String(e)}`,exitCode:1}}if(n.created.length===0&&n.configEdits.length===0)return{status:`no-op`,message:`${b(`Your knowledge base is already seeded.`)}\n${y(`Nothing to do.`)}`,plan:n,exitCode:0};if(e.dryRun)return{status:`dry-run`,message:`${C(`Plan (dry-run — no changes made):`)}\n\n${Ki(n,t)}`,plan:n,exitCode:0};if(!e.yes&&!await qi(`${C(`Plan:`)}\n\n${Ki(n,t)}\n\n${C(`Apply?`)} ${y(`[Y/n] `)}`,e.confirmStream))return{status:`cancelled`,message:y(`Cancelled.`),plan:n,exitCode:0};let r=await p(n,{projectDir:t});if(r.errors.length>0){let e=r.errors.map(e=>` ${x(`✗`)} ${e.path}: ${e.error}`);return{status:`failed`,message:[`${S(`Applied`)} ${r.applied} entries, ${S(String(r.errors.length))} error(s):`,...e].join(`
669
669
  `),plan:n,exitCode:1}}return{status:`applied`,message:`${b(`✓ Seeded knowledge base`)} ${y(`(${r.applied} entries, ${r.durationMs}ms)`)}`,plan:n,exitCode:0}}function Ki(e,t){let n=[],r=e.created.filter(e=>e.kind===`folder`),i=e.created.filter(e=>e.kind===`file`);if(r.length>0){n.push(C(`Folders to create:`));for(let e of r)n.push(` ${b(`+`)} ${v(_e(t,M(t,e.path))||e.path)}${y(`/`)}`)}if(i.length>0){n.length>0&&n.push(``),n.push(C(`Files to create:`));for(let e of i)n.push(` ${b(`+`)} ${v(_e(t,M(t,e.path))||e.path)}`)}if(e.configEdits.length>0){n.length>0&&n.push(``),n.push(C(`config.yml folders: entries to add:`));for(let t of e.configEdits)n.push(` ${b(`+`)} ${v(t.folderMatch)} ${y(`—`)} ${t.entry.frontmatter.title??``}`)}if(e.skipped.length>0){n.length>0&&n.push(``),n.push(y(`Already present (skipped):`));for(let t of e.skipped)n.push(` ${y(`· ${t.path} (${t.reason})`)}`)}if(e.warnings.length>0){n.length>0&&n.push(``),n.push(S(`Warnings:`));for(let t of e.warnings)n.push(` ${S(`!`)} ${t}`)}return n.join(`
670
- `)}async function qi(e,t){let n=Ve({input:t??process.stdin,output:process.stdout});try{let t=(await n.question(e)).trim().toLowerCase();return t===``||t===`y`||t===`yes`}finally{n.close()}}function Ji(){return new A(`seed`).description(`Scaffold the Karpathy three-layer knowledge-base structure (external-sources/, research/, articles/) + log.md + config.yml folders: entries`).argument(`[path]`,`Project directory (defaults to cwd)`).option(`-y, --yes`,`Skip confirmation prompt`).option(`--dry-run`,`Print the plan and exit without writing`).action(async(e,t)=>{let n=await Gi({cwd:e??process.cwd(),yes:t.yes,dryRun:t.dryRun});process.stdout.write(`${n.message}\n`),n.exitCode!==0&&(process.exitCode=n.exitCode)})}function Yi(e,t){return{server:Xi(`server`,e),ui:Xi(`ui`,t)}}function Xi(e,t){switch(t.status){case`missing`:return{name:e,state:`missing`,alive:!1};case`corrupt`:return{name:e,state:`corrupt`,alive:!1};case`foreign-host`:return{name:e,state:`foreign-host`,pid:t.lock.pid,port:t.lock.port,startedAt:t.lock.startedAt,host:t.lock.hostname,alive:`unknown`};case`dead-pid`:return{name:e,state:`dead-pid`,pid:t.lock.pid,port:t.lock.port,startedAt:t.lock.startedAt,host:t.lock.hostname,alive:!1};case`alive`:return{name:e,state:`alive`,pid:t.lock.pid,port:t.lock.port,startedAt:t.lock.startedAt,host:t.lock.hostname,alive:!0}}}function Zi(e){return`${Qi(e.server)}\n${Qi(e.ui)}`}function Qi(e){let t=e.name===`server`?`server`:`ui `;return e.state===`missing`?`${t} not running`:e.state===`corrupt`?`${t} lock file corrupt — run \`ok clean\``:e.state===`foreign-host`?`${t} foreign host (${e.host}) pid=${e.pid} port=${e.port}`:e.state===`dead-pid`?`${t} stale (dead pid=${e.pid}) — run \`ok clean\``:`${t} alive pid=${e.pid} port=${e.port} started=${e.startedAt}`}function $i(e){let t=e.inspect??(t=>ft(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=Yi(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(Zi(r)),r}function ea(e){return new A(`status`).description(`Show live state of the server + ui lockfiles for this project`).option(`--json`,`Emit structured JSON instead of formatted text`).action(t=>{$i({lockDir:a(o(e(),process.cwd())),json:t.json===!0})})}function ta(e,t){let n=[];return e.status===`alive`&&n.push({name:`server`,pid:e.lock.pid,port:e.lock.port}),t.status===`alive`&&n.push({name:`ui`,pid:t.lock.pid,port:t.lock.port}),{targets:n}}function na(e){let t=e.inspect??(t=>ft(e.lockDir,t)),n=e.kill??((e,t)=>process.kill(e,t)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=ta(t(`server`),t(`ui`));if(a.targets.length===0)return r(`No running open-knowledge processes.`),{stopped:[],failed:[],hadTargets:!1};let o=[],s=[];for(let e of a.targets)try{n(e.pid,`SIGTERM`),o.push(e)}catch(t){s.push({target:e,error:t instanceof Error?t.message:String(t)})}return o.length>0&&r(`Stopped: ${o.map(e=>`${e.name} (pid=${e.pid}, port=${e.port})`).join(`, `)}`),s.length>0&&i(`Failed to stop: ${s.map(({target:e,error:t})=>`${e.name} (pid=${e.pid}): ${t}`).join(`; `)}`),{stopped:o,failed:s,hadTargets:!0}}function ra(e){return new A(`stop`).description(`Stop the running open-knowledge server and UI (live only)`).action(()=>{na({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}const ia=1e4,aa=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function oa(e){let t=e.upstreamTimeoutMs??ia,n=je((n,r)=>{ca(n,r,e.upstreamHost,e.upstreamPort,t)});await new Promise((t,r)=>{let i=e=>r(e);n.once(`error`,i),n.listen(e.listenPort,e.host,()=>{n.off(`error`,i),t()})});let r=n.address();return{httpServer:n,port:typeof r==`object`&&r?r.port:e.listenPort,close:()=>new Promise(e=>{n.close(()=>e())})}}function sa(e,t,n){ca(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??ia)}function ca(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of aa)delete a[e];e.setTimeout(3e4,()=>{if(t.headersSent)try{t.end()}catch{}else try{t.writeHead(408,{"Content-Type":`text/plain`}),t.end(`Request Timeout`)}catch{}try{e.socket?.destroy()}catch{}});let o=Me({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of aa)delete n[e];t.writeHead(e.statusCode??502,n),e.pipe(t),e.once(`error`,()=>{try{t.end()}catch{}})});i>0&&o.setTimeout(i,()=>{if(!t.headersSent)t.writeHead(504,{"Content-Type":`text/plain`}),t.end(`Gateway Timeout`);else try{t.end()}catch{}o.destroy()}),o.on(`error`,()=>{if(!t.headersSent)t.writeHead(502,{"Content-Type":`text/plain`}),t.end(`Bad Gateway`);else try{t.end()}catch{}}),e.on(`error`,()=>{o.destroy()}),e.pipe(o)}async function la(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function ua(e){let{existsSync:t}=await import(`node:fs`),{createServer:n}=await import(`node:http`),{resolve:i}=await import(`node:path`),{acquireUiLock:a,readServerLock:o,releaseUiLock:s,updateUiLockPort:c}=await import(`./src-zcKwR9RH.mjs`),{default:l}=await import(`sirv`),{resolveContentDir:u,resolveLockDir:d}=await import(`./paths-BqubmGF4.mjs`),f=u(e.config,e.cwd),p=d(f);a(p,{port:0,worktreeRoot:e.cwd});let m=import.meta.dirname??new URL(`.`,import.meta.url).pathname,h=[i(m,`public`),i(m,`../../app/dist`),i(m,`../../../app/dist`)].find(e=>t(e)),g=h?l(h,{single:!0,gzip:!0,immutable:!0}):null,_=t(f)?l(f,{dotfiles:!1,dev:!0}):null,v=e.port,y=null,b=(e,t)=>{let n=e.url?.split(`?`)[0];if(n===`/api/config`&&(e.method===`GET`||e.method===`HEAD`)){y?.();let n=o(p),r=n&&n.port>0?`ws://localhost:${n.port}/collab`:null,i=JSON.stringify({collabUrl:r,previewUrl:null,port:v});t.setHeader(`Content-Type`,`application/json`),t.setHeader(`Cache-Control`,`no-store`),t.setHeader(`X-Content-Type-Options`,`nosniff`),t.statusCode=200,e.method===`HEAD`?t.end():t.end(i);return}if(n?.startsWith(`/api/`)){y?.();let r=o(p);if(!r||r.port<=0){t.writeHead(503,{"Content-Type":`application/json`,"Cache-Control":`no-store`}),t.end(JSON.stringify({error:"Collab server not running. Start `ok start` or run `ok status`.",path:n}));return}sa(e,t,{upstreamHost:`localhost`,upstreamPort:r.port});return}if(decodeURIComponent(n?.replace(/^\//,``)??``)&&_){t.setHeader(`X-Content-Type-Options`,`nosniff`),_(e,t,()=>{g?g(e,t):da(t)});return}if(g){g(e,t);return}da(t)},x=e.host===void 0?[`::1`,`127.0.0.1`]:[e.host],S=[],C=e.port;try{for(let e of x){let t=n(b);S.push(t),await new Promise((n,r)=>{let i=e=>r(e);t.once(`error`,i),t.listen(C,e,()=>{t.off(`error`,i);let e=t.address();typeof e==`object`&&e&&(C=e.port),n()})})}}catch(e){await Promise.all(S.map(e=>new Promise(t=>{try{e.close(()=>t())}catch{t()}})));try{s(p)}catch{}throw e}let w=C;v=w,c(p,w);let T=e.scheduler??r,E=e.safetyNetMs??432e5,D=null,O=!1,ee=!1,k=()=>{O||(O=!0,D!==null&&(T.clearTimeout(D),D=null))},A=()=>{if(k(),!ee){ee=!0;try{s(p)}catch{}}},te=()=>{O||E<=0||(D!==null&&(T.clearTimeout(D),D=null),D=T.setTimeout(()=>{D=null,console.warn(`[ui] safety-net (${E}ms) reached — shutting down (D-025 backstop)`);try{e.onSafetyNet?.()}catch{}for(let e of S)try{e.close()}catch{}A()},E))},ne=()=>{O||E<=0||te()};return y=ne,te(),{httpServers:S,port:w,release:A,detachSafetyNet:k,nudgeSafetyNet:ne}}function da(e){e.writeHead(404),e.end(`Not found`)}function fa(e,t){if(e!==void 0){let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<0||t>65535)throw Error(`Invalid --port value '${e}'`);return t}if(t!==void 0&&t!==``){let e=Number.parseInt(t,10);if(Number.isNaN(e)||e<0||e>65535)throw Error(`Invalid PORT env value '${t}'`);return e}return 0}async function pa(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-zcKwR9RH.mjs`);return t(e.lockDir)}),n=await t();if(!n)throw Error(`UI lock collision reported but the lock disappeared before handling — retry acquiring.`);if(n.port===e.requestedPort&&n.port>0)return{mode:`already-running`,port:n.port};let r=n.port;if(r===0){let n=Date.now()+(e.pollDeadlineMs??2e3),i=e.pollIntervalMs??100;for(;Date.now()<n;){await new Promise(e=>{setTimeout(e,i)});let e=await t();if(e&&e.port>0){r=e.port;break}}if(r===0)throw Error("UI did not bind within 2s; run `ok clean`");if(r===e.requestedPort)return{mode:`already-running`,port:r}}return{mode:`proxy`,handle:await oa({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function ma(e){return new A(`ui`).description(`Serve the Open Knowledge React editor UI`).option(`-p, --port <port>`,`UI port (default: $PORT env or 0 / kernel-allocated)`).option(`-H, --host <host>`,"UI host. Default: two-socket loopback bind (`[::1]` + `127.0.0.1`) so cross-family collisions fail loud (D-033). Pass an explicit host (e.g. `127.0.0.1`, `0.0.0.0`) to bind a single socket on that host.").action(async t=>{let{dim:n}=await import(`./colors-CxLEz90E.mjs`),{UiLockCollisionError:r}=await import(`./src-zcKwR9RH.mjs`),{resolveContentDir:i,resolveLockDir:a}=await import(`./paths-BqubmGF4.mjs`),o=e(),s=t.host,c;try{c=fa(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}try{let e=await ua({config:o,cwd:process.cwd(),port:c,host:s}),t=s===void 0||s===`::`||s===`0.0.0.0`?`localhost`:s;console.log(`${n(`[ui]`)} listening on http://${t}:${e.port}`);let r=!1,i=t=>{if(r)return;r=!0,console.log(n(`\n[ui] Shutting down (${t})...`)),e.detachSafetyNet();let i=()=>{try{e.release()}finally{process.exit(process.exitCode??0)}};la(e.httpServers).then(i,i),setTimeout(i,2e3).unref()};process.once(`SIGINT`,()=>i(`SIGINT`)),process.once(`SIGTERM`,()=>i(`SIGTERM`));return}catch(e){if(!(e instanceof r))throw e;let t=a(i(o,process.cwd())),l=s??`localhost`,u;try{u=await pa({requestedPort:c,host:l,lockDir:t})}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}u.mode===`already-running`&&(console.log(`UI already running at http://${l}:${u.port}`),process.exit(0)),console.log(`UI running at http://${l}:${u.upstreamPort}; acting as HTTP proxy on port ${u.handle.port}`);let d=!1,f=e=>{d||(d=!0,console.log(n(`\n[ui-proxy] Shutting down (${e})...`)),u.handle.close().finally(()=>process.exit(process.exitCode??0)),setTimeout(()=>process.exit(process.exitCode??0),2e3).unref())};process.once(`SIGINT`,()=>f(`SIGINT`)),process.once(`SIGTERM`,()=>f(`SIGTERM`))}})}process.argv.includes(`--no-color`)?(process.env.NO_COLOR=`1`,delete process.env.FORCE_COLOR):process.argv.includes(`--color`)&&(process.env.FORCE_COLOR=`1`,delete process.env.NO_COLOR);const Q=new A;let $;Q.name(`open-knowledge`).description(`Local-first knowledge base with CRDT collaboration`).version(e).option(`--cwd <path>`,`Working directory`).option(`--log-level <level>`,`Log level`,`info`).option(`--no-color`,`Disable color output`).option(`--color`,`Force color output`).hook(`preAction`,e=>{let t=e.opts(),n=t.cwd;n!==void 0&&process.chdir(n);let{config:r}=D(n),i=e.args.length===0?t:e.commands[0]?.opts()??{};i.port!==void 0&&(r.server.port=Number(i.port)),i.host!==void 0&&(r.server.host=i.host),process.env.PORT&&(r.server.port=Number(process.env.PORT)),process.env.HOST&&(r.server.host=process.env.HOST),$=r});const ha=ee(()=>$);Q.addCommand(ha,{isDefault:!0});const ga=zi(()=>$);Q.addCommand(ga),Q.addCommand(T()),Q.addCommand(Ji());const _a=Bi(()=>$);Q.addCommand(_a);const va=ma(()=>$);Q.addCommand(va),Q.addCommand(ra(()=>$)),Q.addCommand(ht(()=>$)),Q.addCommand(ea(()=>$)),Q.addCommand(dt(()=>$)),Q.addCommand(wt(()=>$)),Q.addCommand(Hi(()=>$)),Q.addCommand(Wi(()=>$)),Q.addCommand(Ui(()=>$)),await Q.parseAsync();export{};
670
+ `)}async function qi(e,t){let n=Ve({input:t??process.stdin,output:process.stdout});try{let t=(await n.question(e)).trim().toLowerCase();return t===``||t===`y`||t===`yes`}finally{n.close()}}function Ji(){return new A(`seed`).description(`Scaffold the Karpathy three-layer knowledge-base structure (external-sources/, research/, articles/) + log.md + config.yml folders: entries`).argument(`[path]`,`Project directory (defaults to cwd)`).option(`-y, --yes`,`Skip confirmation prompt`).option(`--dry-run`,`Print the plan and exit without writing`).action(async(e,t)=>{let n=await Gi({cwd:e??process.cwd(),yes:t.yes,dryRun:t.dryRun});process.stdout.write(`${n.message}\n`),n.exitCode!==0&&(process.exitCode=n.exitCode)})}function Yi(e,t){return{server:Xi(`server`,e),ui:Xi(`ui`,t)}}function Xi(e,t){switch(t.status){case`missing`:return{name:e,state:`missing`,alive:!1};case`corrupt`:return{name:e,state:`corrupt`,alive:!1};case`foreign-host`:return{name:e,state:`foreign-host`,pid:t.lock.pid,port:t.lock.port,startedAt:t.lock.startedAt,host:t.lock.hostname,alive:`unknown`};case`dead-pid`:return{name:e,state:`dead-pid`,pid:t.lock.pid,port:t.lock.port,startedAt:t.lock.startedAt,host:t.lock.hostname,alive:!1};case`alive`:return{name:e,state:`alive`,pid:t.lock.pid,port:t.lock.port,startedAt:t.lock.startedAt,host:t.lock.hostname,alive:!0}}}function Zi(e){return`${Qi(e.server)}\n${Qi(e.ui)}`}function Qi(e){let t=e.name===`server`?`server`:`ui `;return e.state===`missing`?`${t} not running`:e.state===`corrupt`?`${t} lock file corrupt — run \`ok clean\``:e.state===`foreign-host`?`${t} foreign host (${e.host}) pid=${e.pid} port=${e.port}`:e.state===`dead-pid`?`${t} stale (dead pid=${e.pid}) — run \`ok clean\``:`${t} alive pid=${e.pid} port=${e.port} started=${e.startedAt}`}function $i(e){let t=e.inspect??(t=>ft(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=Yi(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(Zi(r)),r}function ea(e){return new A(`status`).description(`Show live state of the server + ui lockfiles for this project`).option(`--json`,`Emit structured JSON instead of formatted text`).action(t=>{$i({lockDir:a(o(e(),process.cwd())),json:t.json===!0})})}function ta(e,t){let n=[];return e.status===`alive`&&n.push({name:`server`,pid:e.lock.pid,port:e.lock.port}),t.status===`alive`&&n.push({name:`ui`,pid:t.lock.pid,port:t.lock.port}),{targets:n}}function na(e){let t=e.inspect??(t=>ft(e.lockDir,t)),n=e.kill??((e,t)=>process.kill(e,t)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=ta(t(`server`),t(`ui`));if(a.targets.length===0)return r(`No running open-knowledge processes.`),{stopped:[],failed:[],hadTargets:!1};let o=[],s=[];for(let e of a.targets)try{n(e.pid,`SIGTERM`),o.push(e)}catch(t){s.push({target:e,error:t instanceof Error?t.message:String(t)})}return o.length>0&&r(`Stopped: ${o.map(e=>`${e.name} (pid=${e.pid}, port=${e.port})`).join(`, `)}`),s.length>0&&i(`Failed to stop: ${s.map(({target:e,error:t})=>`${e.name} (pid=${e.pid}): ${t}`).join(`; `)}`),{stopped:o,failed:s,hadTargets:!0}}function ra(e){return new A(`stop`).description(`Stop the running open-knowledge server and UI (live only)`).action(()=>{na({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}const ia=1e4,aa=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function oa(e){let t=e.upstreamTimeoutMs??ia,n=je((n,r)=>{ca(n,r,e.upstreamHost,e.upstreamPort,t)});await new Promise((t,r)=>{let i=e=>r(e);n.once(`error`,i),n.listen(e.listenPort,e.host,()=>{n.off(`error`,i),t()})});let r=n.address();return{httpServer:n,port:typeof r==`object`&&r?r.port:e.listenPort,close:()=>new Promise(e=>{n.close(()=>e())})}}function sa(e,t,n){ca(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??ia)}function ca(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of aa)delete a[e];e.setTimeout(3e4,()=>{if(t.headersSent)try{t.end()}catch{}else try{t.writeHead(408,{"Content-Type":`text/plain`}),t.end(`Request Timeout`)}catch{}try{e.socket?.destroy()}catch{}});let o=Me({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of aa)delete n[e];t.writeHead(e.statusCode??502,n),e.pipe(t),e.once(`error`,()=>{try{t.end()}catch{}})});i>0&&o.setTimeout(i,()=>{if(!t.headersSent)t.writeHead(504,{"Content-Type":`text/plain`}),t.end(`Gateway Timeout`);else try{t.end()}catch{}o.destroy()}),o.on(`error`,()=>{if(!t.headersSent)t.writeHead(502,{"Content-Type":`text/plain`}),t.end(`Bad Gateway`);else try{t.end()}catch{}}),e.on(`error`,()=>{o.destroy()}),e.pipe(o)}async function la(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function ua(e){let{existsSync:t}=await import(`node:fs`),{createServer:n}=await import(`node:http`),{resolve:i}=await import(`node:path`),{acquireUiLock:a,readServerLock:o,releaseUiLock:s,updateUiLockPort:c}=await import(`./src-zcKwR9RH.mjs`),{default:l}=await import(`sirv`),{resolveContentDir:u,resolveLockDir:d}=await import(`./paths-HWNY8fZl.mjs`),f=u(e.config,e.cwd),p=d(f);a(p,{port:0,worktreeRoot:e.cwd});let m=import.meta.dirname??new URL(`.`,import.meta.url).pathname,h=[i(m,`public`),i(m,`../../app/dist`),i(m,`../../../app/dist`)].find(e=>t(e)),g=h?l(h,{single:!0,gzip:!0,immutable:!0}):null,_=t(f)?l(f,{dotfiles:!1,dev:!0}):null,v=e.port,y=null,b=(e,t)=>{let n=e.url?.split(`?`)[0];if(n===`/api/config`&&(e.method===`GET`||e.method===`HEAD`)){y?.();let n=o(p),r=n&&n.port>0?`ws://localhost:${n.port}/collab`:null,i=JSON.stringify({collabUrl:r,previewUrl:null,port:v});t.setHeader(`Content-Type`,`application/json`),t.setHeader(`Cache-Control`,`no-store`),t.setHeader(`X-Content-Type-Options`,`nosniff`),t.statusCode=200,e.method===`HEAD`?t.end():t.end(i);return}if(n?.startsWith(`/api/`)){y?.();let r=o(p);if(!r||r.port<=0){t.writeHead(503,{"Content-Type":`application/json`,"Cache-Control":`no-store`}),t.end(JSON.stringify({error:"Collab server not running. Start `ok start` or run `ok status`.",path:n}));return}sa(e,t,{upstreamHost:`localhost`,upstreamPort:r.port});return}if(decodeURIComponent(n?.replace(/^\//,``)??``)&&_){t.setHeader(`X-Content-Type-Options`,`nosniff`),_(e,t,()=>{g?g(e,t):da(t)});return}if(g){g(e,t);return}da(t)},x=e.host===void 0?[`::1`,`127.0.0.1`]:[e.host],S=[],C=e.port;try{for(let e of x){let t=n(b);S.push(t),await new Promise((n,r)=>{let i=e=>r(e);t.once(`error`,i),t.listen(C,e,()=>{t.off(`error`,i);let e=t.address();typeof e==`object`&&e&&(C=e.port),n()})})}}catch(e){await Promise.all(S.map(e=>new Promise(t=>{try{e.close(()=>t())}catch{t()}})));try{s(p)}catch{}throw e}let w=C;v=w,c(p,w);let T=e.scheduler??r,E=e.safetyNetMs??432e5,D=null,O=!1,ee=!1,k=()=>{O||(O=!0,D!==null&&(T.clearTimeout(D),D=null))},A=()=>{if(k(),!ee){ee=!0;try{s(p)}catch{}}},te=()=>{O||E<=0||(D!==null&&(T.clearTimeout(D),D=null),D=T.setTimeout(()=>{D=null,console.warn(`[ui] safety-net (${E}ms) reached — shutting down (D-025 backstop)`);try{e.onSafetyNet?.()}catch{}for(let e of S)try{e.close()}catch{}A()},E))},ne=()=>{O||E<=0||te()};return y=ne,te(),{httpServers:S,port:w,release:A,detachSafetyNet:k,nudgeSafetyNet:ne}}function da(e){e.writeHead(404),e.end(`Not found`)}function fa(e,t){if(e!==void 0){let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<0||t>65535)throw Error(`Invalid --port value '${e}'`);return t}if(t!==void 0&&t!==``){let e=Number.parseInt(t,10);if(Number.isNaN(e)||e<0||e>65535)throw Error(`Invalid PORT env value '${t}'`);return e}return 0}async function pa(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-zcKwR9RH.mjs`);return t(e.lockDir)}),n=await t();if(!n)throw Error(`UI lock collision reported but the lock disappeared before handling — retry acquiring.`);if(n.port===e.requestedPort&&n.port>0)return{mode:`already-running`,port:n.port};let r=n.port;if(r===0){let n=Date.now()+(e.pollDeadlineMs??2e3),i=e.pollIntervalMs??100;for(;Date.now()<n;){await new Promise(e=>{setTimeout(e,i)});let e=await t();if(e&&e.port>0){r=e.port;break}}if(r===0)throw Error("UI did not bind within 2s; run `ok clean`");if(r===e.requestedPort)return{mode:`already-running`,port:r}}return{mode:`proxy`,handle:await oa({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function ma(e){return new A(`ui`).description(`Serve the Open Knowledge React editor UI`).option(`-p, --port <port>`,`UI port (default: $PORT env or 0 / kernel-allocated)`).option(`-H, --host <host>`,"UI host. Default: two-socket loopback bind (`[::1]` + `127.0.0.1`) so cross-family collisions fail loud (D-033). Pass an explicit host (e.g. `127.0.0.1`, `0.0.0.0`) to bind a single socket on that host.").action(async t=>{let{dim:n}=await import(`./colors-CxLEz90E.mjs`),{UiLockCollisionError:r}=await import(`./src-zcKwR9RH.mjs`),{resolveContentDir:i,resolveLockDir:a}=await import(`./paths-HWNY8fZl.mjs`),o=e(),s=t.host,c;try{c=fa(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}try{let e=await ua({config:o,cwd:process.cwd(),port:c,host:s}),t=s===void 0||s===`::`||s===`0.0.0.0`?`localhost`:s;console.log(`${n(`[ui]`)} listening on http://${t}:${e.port}`);let r=!1,i=t=>{if(r)return;r=!0,console.log(n(`\n[ui] Shutting down (${t})...`)),e.detachSafetyNet();let i=()=>{try{e.release()}finally{process.exit(process.exitCode??0)}};la(e.httpServers).then(i,i),setTimeout(i,2e3).unref()};process.once(`SIGINT`,()=>i(`SIGINT`)),process.once(`SIGTERM`,()=>i(`SIGTERM`));return}catch(e){if(!(e instanceof r))throw e;let t=a(i(o,process.cwd())),l=s??`localhost`,u;try{u=await pa({requestedPort:c,host:l,lockDir:t})}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}u.mode===`already-running`&&(console.log(`UI already running at http://${l}:${u.port}`),process.exit(0)),console.log(`UI running at http://${l}:${u.upstreamPort}; acting as HTTP proxy on port ${u.handle.port}`);let d=!1,f=e=>{d||(d=!0,console.log(n(`\n[ui-proxy] Shutting down (${e})...`)),u.handle.close().finally(()=>process.exit(process.exitCode??0)),setTimeout(()=>process.exit(process.exitCode??0),2e3).unref())};process.once(`SIGINT`,()=>f(`SIGINT`)),process.once(`SIGTERM`,()=>f(`SIGTERM`))}})}process.argv.includes(`--no-color`)?(process.env.NO_COLOR=`1`,delete process.env.FORCE_COLOR):process.argv.includes(`--color`)&&(process.env.FORCE_COLOR=`1`,delete process.env.NO_COLOR);const Q=new A;let $;Q.name(`open-knowledge`).description(`Local-first knowledge base with CRDT collaboration`).version(e).option(`--cwd <path>`,`Working directory`).option(`--log-level <level>`,`Log level`,`info`).option(`--no-color`,`Disable color output`).option(`--color`,`Force color output`).hook(`preAction`,e=>{let t=e.opts(),n=t.cwd;n!==void 0&&process.chdir(n);let{config:r}=D(n),i=e.args.length===0?t:e.commands[0]?.opts()??{};i.port!==void 0&&(r.server.port=Number(i.port)),i.host!==void 0&&(r.server.host=i.host),process.env.PORT&&(r.server.port=Number(process.env.PORT)),process.env.HOST&&(r.server.host=process.env.HOST),$=r});const ha=ee(()=>$);Q.addCommand(ha,{isDefault:!0});const ga=zi(()=>$);Q.addCommand(ga),Q.addCommand(T()),Q.addCommand(Ji());const _a=Bi(()=>$);Q.addCommand(_a);const va=ma(()=>$);Q.addCommand(va),Q.addCommand(ra(()=>$)),Q.addCommand(ht(()=>$)),Q.addCommand(ea(()=>$)),Q.addCommand(dt(()=>$)),Q.addCommand(wt(()=>$)),Q.addCommand(Hi(()=>$)),Q.addCommand(Wi(()=>$)),Q.addCommand(Ui(()=>$)),await Q.parseAsync();export{};
671
671
  //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1,2 @@
1
+ import"./src-CB-sXsMW.mjs";var e=`0.0.0-dev-20260424205527`;const t=`config.yml`,n=`cache`,r=e,i=`open-knowledge`;export{r as i,t as n,i as r,n as t};
2
+ //# sourceMappingURL=constants-Dqmeg2oi.mjs.map
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{c as e,i as t,l as n,o as r,s as i,t as a}from"./init-14nxErpx.mjs";import{n as o,r as s}from"./loader-CGbKkeEd.mjs";import"./src-ij172HYc.mjs";export{e as ALL_EDITOR_IDS,s as ConfigSchema,n as EDITOR_TARGETS,a as detectInstalledEditors,o as loadConfig,t as readExistingMcpEntry,r as writeEditorMcpConfig,i as writeUserMcpConfigs};
1
+ import{c as e,i as t,l as n,o as r,s as i,t as a}from"./init-DIbZ0Udv.mjs";import{n as o,r as s}from"./loader-CEfLKIxb.mjs";import"./src-DjVVQCyp.mjs";export{e as ALL_EDITOR_IDS,s as ConfigSchema,n as EDITOR_TARGETS,a as detectInstalledEditors,o as loadConfig,t as readExistingMcpEntry,r as writeEditorMcpConfig,i as writeUserMcpConfigs};
@@ -0,0 +1 @@
1
+ import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./init-DIbZ0Udv.mjs";export{o as detectInstalledEditors,n as formatInitResult,i as initCommand,t as readExistingMcpEntry,e as runInit,r as writeEditorMcpConfig,a as writeUserMcpConfigs};
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./init-i7vPAWv4.mjs";export{t as ensureOkGitignoredAtRoot,e as initContent};
@@ -1,5 +1,5 @@
1
- import{r as e}from"./constants-DFnJ9to1.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{n,r,t as i}from"./src-DBQiBMMB.mjs";import{n as a}from"./init-BGPwx74o.mjs";import{t as o}from"./preview-9UMLu9Js.mjs";import{s}from"./colors-Cmha5EZJ.mjs";import{t as c}from"./is-object-7k010cEq.mjs";import{Command as l}from"commander";import{existsSync as u,mkdirSync as d,readFileSync as f,writeFileSync as p}from"node:fs";import{homedir as m}from"node:os";import{basename as h,dirname as g,join as _,posix as v,relative as y,resolve as b,sep as x,win32 as S}from"node:path";import{parse as ee,stringify as C}from"smol-toml";const w=[`claude`,`claude-desktop`,`cursor`,`vscode`,`windsurf`,`codex`],T=[`@inkeep/open-knowledge`,`mcp`],te={MCP_DEBUG:`1`,OK_LOG_FILE:`/tmp/ok-mcp.log`};function E(e=process.argv[1]){if(!e)throw Error(`Cannot infer the local CLI entry for --dev-mcp because process.argv[1] is empty.`);let t=b(e);if(h(t)===`cli.mjs`&&h(g(t))===`dist`)return t;let n=t.split(x),r=n.lastIndexOf(`packages`);if(r===-1||n[r+1]!==`cli`)throw Error(`Cannot infer the repo root for --dev-mcp from ${t}. Run the local CLI from this repo so the built dist path can be derived.`);let i=n.slice(0,r);return _(i.length===0?x:i.join(x),`packages`,`cli`,`dist`,`cli.mjs`)}function D(e={}){return e.cliPath?{command:e.cliPath,args:[`mcp`]}:e.mode===`dev`?{command:`node`,args:[E(e.cliEntryPath),`mcp`],env:{...te}}:{command:`npx`,args:[...T]}}function O(e){return e===`win32`?S:v}function k(e={}){let t=e.platformName??process.platform,n=e.home??m(),r=e.env??process.env,i=O(t);return t===`darwin`?i.join(n,`Library`,`Application Support`):t===`win32`?r.APPDATA??i.join(n,`AppData`,`Roaming`):r.XDG_CONFIG_HOME??i.join(n,`.config`)}function A(e={}){let t=e.platformName??process.platform,n=e.home??m();return O(t).join(n,`.claude.json`)}function j(e={}){let t=e.platformName??process.platform,n=e.home??m(),r=e.env??process.env;if(t===`darwin`)return v.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`);if(t===`win32`){let e=r.APPDATA??S.join(n,`AppData`,`Roaming`);return S.join(e,`Claude`,`claude_desktop_config.json`)}throw Error(`Claude Desktop is not available on ${t}. Supported: macOS, Windows.`)}function M(e={}){let t=e.platformName??process.platform,n=e.home??m();return O(t).join(n,`.cursor`,`mcp.json`)}function N(e={}){return O(e.platformName??process.platform).join(k(e),`Code`,`User`,`mcp.json`)}function P(e={}){let t=e.platformName??process.platform,n=e.home??m();return O(t).join(n,`.codeium`,`windsurf`,`mcp_config.json`)}function F(e={}){let t=e.platformName??process.platform,n=e.home??m();return(e.env??process.env).CODEX_HOME??O(t).join(n,`.codex`)}function I(e={}){return O(e.platformName??process.platform).join(F(e),`config.toml`)}function L(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>L(e,t[n]));if(c(e)&&c(t)){let n=Object.keys(e).sort(),r=Object.keys(t).sort();return n.length===r.length&&n.every((e,t)=>e===r[t])&&n.every(n=>L(e[n],t[n]))}return!1}function R(e,t){return Object.entries(t).every(([t,n])=>L(e[t],n))}function z(e,t){return{...e,...t}}function B(e){return{...e,isCompatible(t,n,r){return R(t,e.buildEntry(n,r))},mergeManagedFields(t,n,r){return z(t,e.buildEntry(n,r))}}}const V={claude:B({id:`claude`,label:`Claude Code`,configPath:(e,t)=>A({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>_(t??m(),`.claude`),legacyProjectConfigPath:e=>_(e,`.mcp.json`)}),"claude-desktop":B({id:`claude-desktop`,label:`Claude Desktop`,configPath:(e,t)=>j({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(j({home:t}))}),cursor:B({id:`cursor`,label:`Cursor`,configPath:(e,t)=>M({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(M({home:t})),legacyProjectConfigPath:e=>_(e,`.cursor`,`mcp.json`)}),vscode:B({id:`vscode`,label:`VS Code`,configPath:(e,t)=>N({home:t}),format:`json`,topLevelKey:`servers`,serverName:()=>e,buildEntry:(e,t)=>({type:`stdio`,...D(t)}),scope:`global`,detectPath:(e,t)=>g(N({home:t})),legacyProjectConfigPath:e=>_(e,`.vscode`,`mcp.json`)}),windsurf:B({id:`windsurf`,label:`Windsurf`,configPath:(e,t)=>P({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(P({home:t}))}),codex:B({id:`codex`,label:`Codex`,configPath:(e,t)=>I({home:t}),format:`toml`,topLevelKey:`mcp_servers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(I({home:t})),legacyProjectConfigPath:e=>_(e,`.codex`,`config.toml`)})};function H(e){let t=e.filter(e=>!(e in V));if(t.length>0)throw Error(`Unknown editor(s): ${t.join(`, `)}. Valid options: ${w.join(`, `)}`);return e.map(e=>V[e])}function U(e){if(!u(e))return{};let t=f(e,`utf-8`).trim();if(t===``)return{};try{let n=JSON.parse(t);if(c(n))return n;throw Error(`${e} root must be a JSON object`)}catch(t){throw t instanceof SyntaxError?Error(`${e} contains invalid JSON: ${t.message}`):t}}function W(e){if(!u(e))return{};let t=f(e,`utf-8`).trim();if(t===``)return{};try{let n=ee(t);if(c(n))return n;throw Error(`${e} root must be a TOML table`)}catch(t){throw Error(`${e} contains invalid TOML: ${t instanceof Error?t.message:String(t)}`)}}function G(e,t){d(g(e),{recursive:!0}),p(e,`${JSON.stringify(t,null,2)}\n`,`utf-8`)}function K(e,t){d(g(e),{recursive:!0});let n=C(t);p(e,n.endsWith(`
1
+ import{r as e}from"./constants-Dqmeg2oi.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{n,r,t as i}from"./src-DBQiBMMB.mjs";import{n as a}from"./init-i7vPAWv4.mjs";import{t as o}from"./preview-BmSvc-WZ.mjs";import{s}from"./colors-Cmha5EZJ.mjs";import{t as c}from"./is-object-7k010cEq.mjs";import{Command as l}from"commander";import{existsSync as u,mkdirSync as d,readFileSync as f,writeFileSync as p}from"node:fs";import{homedir as m}from"node:os";import{basename as h,dirname as g,join as _,posix as v,relative as y,resolve as b,sep as x,win32 as S}from"node:path";import{parse as ee,stringify as C}from"smol-toml";const w=[`claude`,`claude-desktop`,`cursor`,`vscode`,`windsurf`,`codex`],T=[`@inkeep/open-knowledge`,`mcp`],te={MCP_DEBUG:`1`,OK_LOG_FILE:`/tmp/ok-mcp.log`};function E(e=process.argv[1]){if(!e)throw Error(`Cannot infer the local CLI entry for --dev-mcp because process.argv[1] is empty.`);let t=b(e);if(h(t)===`cli.mjs`&&h(g(t))===`dist`)return t;let n=t.split(x),r=n.lastIndexOf(`packages`);if(r===-1||n[r+1]!==`cli`)throw Error(`Cannot infer the repo root for --dev-mcp from ${t}. Run the local CLI from this repo so the built dist path can be derived.`);let i=n.slice(0,r);return _(i.length===0?x:i.join(x),`packages`,`cli`,`dist`,`cli.mjs`)}function D(e={}){return e.cliPath?{command:e.cliPath,args:[`mcp`]}:e.mode===`dev`?{command:`node`,args:[E(e.cliEntryPath),`mcp`],env:{...te}}:{command:`npx`,args:[...T]}}function O(e){return e===`win32`?S:v}function k(e={}){let t=e.platformName??process.platform,n=e.home??m(),r=e.env??process.env,i=O(t);return t===`darwin`?i.join(n,`Library`,`Application Support`):t===`win32`?r.APPDATA??i.join(n,`AppData`,`Roaming`):r.XDG_CONFIG_HOME??i.join(n,`.config`)}function A(e={}){let t=e.platformName??process.platform,n=e.home??m();return O(t).join(n,`.claude.json`)}function j(e={}){let t=e.platformName??process.platform,n=e.home??m(),r=e.env??process.env;if(t===`darwin`)return v.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`);if(t===`win32`){let e=r.APPDATA??S.join(n,`AppData`,`Roaming`);return S.join(e,`Claude`,`claude_desktop_config.json`)}throw Error(`Claude Desktop is not available on ${t}. Supported: macOS, Windows.`)}function M(e={}){let t=e.platformName??process.platform,n=e.home??m();return O(t).join(n,`.cursor`,`mcp.json`)}function N(e={}){return O(e.platformName??process.platform).join(k(e),`Code`,`User`,`mcp.json`)}function P(e={}){let t=e.platformName??process.platform,n=e.home??m();return O(t).join(n,`.codeium`,`windsurf`,`mcp_config.json`)}function F(e={}){let t=e.platformName??process.platform,n=e.home??m();return(e.env??process.env).CODEX_HOME??O(t).join(n,`.codex`)}function I(e={}){return O(e.platformName??process.platform).join(F(e),`config.toml`)}function L(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>L(e,t[n]));if(c(e)&&c(t)){let n=Object.keys(e).sort(),r=Object.keys(t).sort();return n.length===r.length&&n.every((e,t)=>e===r[t])&&n.every(n=>L(e[n],t[n]))}return!1}function R(e,t){return Object.entries(t).every(([t,n])=>L(e[t],n))}function z(e,t){return{...e,...t}}function B(e){return{...e,isCompatible(t,n,r){return R(t,e.buildEntry(n,r))},mergeManagedFields(t,n,r){return z(t,e.buildEntry(n,r))}}}const V={claude:B({id:`claude`,label:`Claude Code`,configPath:(e,t)=>A({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>_(t??m(),`.claude`),legacyProjectConfigPath:e=>_(e,`.mcp.json`)}),"claude-desktop":B({id:`claude-desktop`,label:`Claude Desktop`,configPath:(e,t)=>j({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(j({home:t}))}),cursor:B({id:`cursor`,label:`Cursor`,configPath:(e,t)=>M({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(M({home:t})),legacyProjectConfigPath:e=>_(e,`.cursor`,`mcp.json`)}),vscode:B({id:`vscode`,label:`VS Code`,configPath:(e,t)=>N({home:t}),format:`json`,topLevelKey:`servers`,serverName:()=>e,buildEntry:(e,t)=>({type:`stdio`,...D(t)}),scope:`global`,detectPath:(e,t)=>g(N({home:t})),legacyProjectConfigPath:e=>_(e,`.vscode`,`mcp.json`)}),windsurf:B({id:`windsurf`,label:`Windsurf`,configPath:(e,t)=>P({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(P({home:t}))}),codex:B({id:`codex`,label:`Codex`,configPath:(e,t)=>I({home:t}),format:`toml`,topLevelKey:`mcp_servers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>g(I({home:t})),legacyProjectConfigPath:e=>_(e,`.codex`,`config.toml`)})};function H(e){let t=e.filter(e=>!(e in V));if(t.length>0)throw Error(`Unknown editor(s): ${t.join(`, `)}. Valid options: ${w.join(`, `)}`);return e.map(e=>V[e])}function U(e){if(!u(e))return{};let t=f(e,`utf-8`).trim();if(t===``)return{};try{let n=JSON.parse(t);if(c(n))return n;throw Error(`${e} root must be a JSON object`)}catch(t){throw t instanceof SyntaxError?Error(`${e} contains invalid JSON: ${t.message}`):t}}function W(e){if(!u(e))return{};let t=f(e,`utf-8`).trim();if(t===``)return{};try{let n=ee(t);if(c(n))return n;throw Error(`${e} root must be a TOML table`)}catch(t){throw Error(`${e} contains invalid TOML: ${t instanceof Error?t.message:String(t)}`)}}function G(e,t){d(g(e),{recursive:!0}),p(e,`${JSON.stringify(t,null,2)}\n`,`utf-8`)}function K(e,t){d(g(e),{recursive:!0});let n=C(t);p(e,n.endsWith(`
2
2
  `)?n:`${n}\n`,`utf-8`)}const q=`0.0.1`,J=`open-knowledge-ui`;function ne(e,t={}){let n=_(e,`.claude`,`launch.json`),r=t.mode===`dev`?{name:J,runtimeExecutable:`node`,runtimeArgs:[E(t.cliEntryPath),`ui`],port:3e3}:{name:J,runtimeExecutable:`npx`,runtimeArgs:[`@inkeep/open-knowledge`,`ui`],port:3e3};try{if(!u(n))return d(g(n),{recursive:!0}),p(n,`${JSON.stringify({version:q,configurations:[r]},null,2)}\n`,`utf-8`),{action:`created`,configPath:n};let e=f(n,`utf-8`).trim(),t=e?JSON.parse(e):{};if(!c(t))return{action:`failed`,configPath:n,error:`launch.json root is not an object`};let i=Array.isArray(t.configurations)?t.configurations:[],a=i.findIndex(e=>c(e)&&e.name===J);a>=0?i[a]=r:i.push(r);let o={...t,version:t.version??q,configurations:i};return p(n,`${JSON.stringify(o,null,2)}\n`,`utf-8`),{action:a>=0?`merged`:`created`,configPath:n}}catch(e){return{action:`failed`,configPath:n,error:e instanceof Error?e.message:String(e)}}}function Y(e,t,n){try{return u(e.detectPath?.(t,n)??g(e.configPath(t,n)))}catch{return!1}}function X(e,t,n,r){let i=e.serverName(t),a;try{a=e.configPath(t,r)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:``,serverName:i,error:t instanceof Error?t.message:String(t)}}if(!n.skipAvailabilityCheck&&!Y(e,t,r))return{editorId:e.id,label:e.label,action:`skipped-missing`,configPath:a,serverName:i};let o;try{o=e.format===`toml`?W(a):U(a)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}let s=o[e.topLevelKey]??{},c=s[i],l;try{l=e.buildEntry(t,n)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}let u={...o,[e.topLevelKey]:{...s,[i]:l}};try{e.format===`toml`?K(a,u):G(a,u)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}return{editorId:e.id,label:e.label,action:c===void 0?`written`:`overwritten`,configPath:a,serverName:i}}function re(e,t){let n=e.legacyProjectConfigPath?.(t);if(!(!n||!u(n)))return{editorId:e.id,label:e.label,path:n}}async function ie(e){let t=H(e.editors),n={mode:`published`,cliPath:e.cliPath,skipAvailabilityCheck:!0};return t.map(t=>X(t,``,n,e.home))}function ae(e,t,n){let r;try{r=e.configPath(t,n)}catch{return null}let i;try{i=e.format===`toml`?W(r):U(r)}catch{return null}let a=i[e.topLevelKey];if(!c(a))return null;let o=a[e.serverName(t)];return c(o)?o:null}async function Z(e={}){let t=b(e.cwd??process.cwd()),n={mode:e.devMcp?`dev`:`published`,cliEntryPath:e.cliEntryPath},o=await r(t),s;try{s=a(t)}catch(n){let r=V.claude.configPath(t,e.home);return{contentCreated:[],contentSkipped:[],editors:[],legacyProjectConfigs:[],didGitInit:o.didInit,mcpAction:`failed`,mcpPath:r,mcpError:`Content scaffolding failed: ${n instanceof Error?n.message:String(n)}`}}let c=H(e.editors??$(t,e.home)),l=c.filter(n=>Y(n,t,e.home)),u=[];for(let r of c){if(e.mcp===!1){let n=``;try{n=r.configPath(t,e.home)}catch{}u.push({editorId:r.id,label:r.label,action:`skipped-flag`,configPath:n,serverName:r.serverName(t)});continue}u.push(X(r,t,n,e.home))}let d=e.mcp===!1?[]:l.map(e=>re(e,t)).filter(e=>e!==void 0),f=l.some(e=>e.id===`claude`)&&e.mcp!==!1?ne(t,n):void 0,p=await(e.installUserSkill??i)({home:e.home}),m=e.mcp===!1?`skipped-flag`:`skipped-missing`,h=u.find(e=>e.editorId===`claude`)??u[0]??{action:m,configPath:V.claude.configPath(t,e.home)};return{contentCreated:s.created,contentSkipped:s.skipped,editors:u,legacyProjectConfigs:d,launchJson:f,skillInstall:p,didGitInit:o.didInit,mcpAction:h.action,mcpPath:h.configPath,mcpError:`error`in h?h.error:void 0}}function Q(e,n){let r=[],i=e.editors.some(e=>e.action===`written`||e.action===`overwritten`),a=e.editors.some(e=>e.action===`failed`),c=e.editors.length>0&&e.editors.every(e=>e.action===`skipped-flag`),l=e.editors.length>0&&e.editors.every(e=>e.action===`skipped-missing`),u=e=>{let t=e.configPath.startsWith(n)?y(n,e.configPath):e.configPath;switch(e.action){case`created`:return` app preview server ${t} configured for Claude Code Desktop embedded browser`;case`merged`:return` app preview server ${t} updated for Claude Code Desktop embedded browser`;case`failed`:return` app preview server ${t} FAILED: ${e.error}`}};e.didGitInit&&r.push(`Initialized git repo at ${n}/.git/ (default branch: main)`);let d=_(n,t);if(e.contentCreated.length>0?(r.push(`Content scaffolded at ${d}/`),r.push(` Created: ${e.contentCreated.join(`, `)}`)):r.push(`Content already present at ${d}/`),e.contentSkipped.length>0&&r.push(` Skipped (already exist): ${e.contentSkipped.join(`, `)}`),r.push(``),e.mcpError&&e.editors.length===0)r.push(`Warning: ${e.mcpError}`);else if(e.editors.length===0)r.push(`MCP server configuration:`),r.push(e.mcpAction===`skipped-flag`?` MCP config not written — use without --no-mcp to configure editors`:` No supported editor config directories detected; skipped MCP registration`);else if(c)r.push(`MCP config not written — use without --no-mcp to configure editors`);else if(l)r.push(`MCP server configuration:`),r.push(` No supported editor config directories detected; skipped MCP registration`);else{r.push(`MCP server configuration:`);for(let t of e.editors){let i=t.configPath.startsWith(n)?y(n,t.configPath):t.configPath.replace(/^\/Users\/[^/]+/,`~`),a=t.serverName===`open-knowledge`?``:` (${t.serverName})`,o=` `.repeat(Math.max(1,14-t.label.length)),s=t.editorId===`claude-desktop`&&(t.action===`written`||t.action===`overwritten`)?` — quit and relaunch Claude Desktop to activate`:``;switch(t.action){case`written`:r.push(` ${t.label}${o}${i} registered${a}${s}`);break;case`overwritten`:r.push(` ${t.label}${o}${i} updated${a}${s}`);break;case`skipped-missing`:r.push(` ${t.label}${o}${i} config root missing; skipped`);break;case`failed`:r.push(` ${t.label}${o}${i} FAILED: ${t.error}`);break;case`skipped-flag`:break}t.editorId===`claude`&&e.launchJson&&r.push(u(e.launchJson))}}if(a&&(r.push(``),r.push(`For failed editors, add the MCP server entry manually. See:`),r.push(` https://github.com/inkeep/open-knowledge#mcp-setup`)),e.legacyProjectConfigs.length>0){r.push(``),r.push(`Legacy project MCP configs detected:`);for(let t of e.legacyProjectConfigs)r.push(` ${t.label} ${y(n,t.path)}`);r.push(` These project-local files may override the new global config. Remove them if you want fully user-scoped MCP setup in this project.`)}if(e.skillInstall)switch(r.push(``),r.push(`User-global skill:`),e.skillInstall){case`installed`:r.push(" open-knowledge installed to detected agent hosts via `npx skills`");break;case`skip-current`:r.push(` open-knowledge already installed at current version`);break;case`failed`:r.push(` ${s(`open-knowledge install failed — MCP still configured; run manually:`)}`),r.push(` ${s(` npx skills@~1.5.0 add <bundled-path> --agent '*' -g -y --copy`)}`);break}if(e.preview?(r.push(``),r.push(o(e.preview,n))):e.previewWarning&&(r.push(``),r.push(`Content preview unavailable: ${e.previewWarning}`)),i){let t=e.editors.filter(e=>e.action===`written`||e.action===`overwritten`).map(e=>e.label);r.push(``),r.push(`Next steps:`),r.push(` 1. Open your editor (${t.join(` / `)})`),r.push(` 2. Approve the MCP server when prompted`),r.push(` 3. (Optional) scaffold the starter knowledge-base structure:`),r.push(` - ok seed`),r.push(` 4. Use the three MCP workflow tools as you build the wiki:`),r.push(` - mcp__open-knowledge__ingest — capture an external source`),r.push(` - mcp__open-knowledge__research — gather sources and write findings`),r.push(` - mcp__open-knowledge__consolidate — promote research to canonical articles`)}return r.join(`
3
3
  `)}function $(e,t){let n=[];for(let r of w)Y(V[r],e,t)&&n.push(r);return n}function oe(){return new l(`init`).description(`Scaffold ${t}/ in the current directory and register the MCP server for your editor(s)`).option(`--mcp`,`Register the MCP server for selected editors (default: true)`,!0).option(`--no-mcp`,`Scaffold the ${t}/ directory but do not touch MCP config`).option(`--dev-mcp`,`Register a local dev MCP entry using node + packages/cli/dist/cli.mjs with debug logging`).action(async e=>{let t=process.cwd(),r;try{r=await Z({cwd:t,mcp:e.mcp,devMcp:e.devMcp})}catch(e){if(e instanceof n){process.stderr.write(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.
4
- `),e.stderr&&process.stderr.write(`${e.stderr.trim()}\n`),process.exitCode=1;return}throw e}try{let{previewContent:e}=await import(`./preview-BcZ1UmA0.mjs`),{loadConfig:n}=await import(`./loader-2r36tVmb.mjs`),{resolveContentDir:i}=await import(`./paths-BqubmGF4.mjs`),{config:a}=n(t),o=i(a,t);r.preview=e({projectDir:t,contentDir:o,include:a.content.include,exclude:a.content.exclude})}catch(e){r.previewWarning=e instanceof Error?e.message:String(e)}process.stdout.write(`${Q(r,t)}\n`),(r.editors.some(e=>e.action===`failed`)||r.mcpAction===`failed`)&&(process.exitCode=1)})}export{Z as a,w as c,ae as i,V as l,Q as n,X as o,oe as r,ie as s,$ as t};
5
- //# sourceMappingURL=init-14nxErpx.mjs.map
4
+ `),e.stderr&&process.stderr.write(`${e.stderr.trim()}\n`),process.exitCode=1;return}throw e}try{let{previewContent:e}=await import(`./preview-DzHGOZjd.mjs`),{loadConfig:n}=await import(`./loader-CQUrJ6T-.mjs`),{resolveContentDir:i}=await import(`./paths-HWNY8fZl.mjs`),{config:a}=n(t),o=i(a,t);r.preview=e({projectDir:t,contentDir:o,include:a.content.include,exclude:a.content.exclude})}catch(e){r.previewWarning=e instanceof Error?e.message:String(e)}process.stdout.write(`${Q(r,t)}\n`),(r.editors.some(e=>e.action===`failed`)||r.mcpAction===`failed`)&&(process.exitCode=1)})}export{Z as a,w as c,ae as i,V as l,Q as n,X as o,oe as r,ie as s,$ as t};
5
+ //# sourceMappingURL=init-DIbZ0Udv.mjs.map
@@ -1,4 +1,4 @@
1
- import{n as e,t}from"./constants-DFnJ9to1.mjs";import{O as n}from"./src-CB-sXsMW.mjs";import{existsSync as r,mkdirSync as i,readFileSync as a,writeFileSync as o}from"node:fs";import{join as s,resolve as c}from"node:path";const l=`# Open Knowledge — workspace configuration
1
+ import{n as e,t}from"./constants-Dqmeg2oi.mjs";import{O as n}from"./src-CB-sXsMW.mjs";import{existsSync as r,mkdirSync as i,readFileSync as a,writeFileSync as o}from"node:fs";import{join as s,resolve as c}from"node:path";const l=`# Open Knowledge — workspace configuration
2
2
  #
3
3
  # This file overrides built-in defaults for this workspace. Every key below
4
4
  # is commented out and shows its current default value. Uncomment any key
@@ -117,4 +117,4 @@ import{n as e,t}from"./constants-DFnJ9to1.mjs";import{O as n}from"./src-CB-sXsMW
117
117
 
118
118
  `)?`
119
119
  `:``}${i}`,`utf-8`),`appended`)}const f=[{name:`.gitignore`,content:`${t}/\nserver.lock\nui.lock\nsync-state.json\n`},{name:e,content:l}];function p(e){let r=c(e,n),a=[],o=[];i(r,{recursive:!0}),i(s(r,t),{recursive:!0});for(let e of f)u(s(r,e.name),e.content)?a.push(e.name):o.push(e.name);return{created:a,skipped:o}}export{p as n,d as t};
120
- //# sourceMappingURL=init-BGPwx74o.mjs.map
120
+ //# sourceMappingURL=init-i7vPAWv4.mjs.map
@@ -1,3 +1,3 @@
1
- import{n as e}from"./constants-DFnJ9to1.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{t as n}from"./is-object-7k010cEq.mjs";import{existsSync as r,readFileSync as i}from"node:fs";import{homedir as a}from"node:os";import{resolve as o}from"node:path";import{parse as s}from"yaml";import{realpath as c}from"node:fs/promises";import{z as l}from"zod";async function u(e){let t=o(e);try{return await c(t)}catch(e){if(e.code!==`ENOENT`){let n=e instanceof Error?e.message:String(e);console.warn(`[normalize-cwd] realpath failed for ${t}: ${n}`)}return t}}const d=l.object({title:l.string().optional(),description:l.string().optional(),tags:l.array(l.string()).optional()}).strict(),f=l.object({match:l.string().min(1,"`match` must be a non-empty glob pattern (e.g. 'specs/**' or 'reports/*/**')"),frontmatter:d}).strict(),p=l.object({content:l.object({dir:l.string().default(`.`),include:l.array(l.string()).min(1).default([`**/*.md`,`**/*.mdx`]),exclude:l.array(l.string()).default([])}).default({dir:`.`,include:[`**/*.md`,`**/*.mdx`],exclude:[]}),github:l.object({oauthAppClientId:l.string().default(`Ov23liqlSd0V1MwR6rhI`)}).default({oauthAppClientId:`Ov23liqlSd0V1MwR6rhI`}),sync:l.object({enabled:l.boolean().optional(),pushIntervalSeconds:l.number().int().min(1).default(60),pullIntervalSeconds:l.number().int().min(1).default(30),autoCommit:l.boolean().default(!0),autoPush:l.boolean().default(!0),autoPull:l.boolean().default(!0),commitMessage:l.string().default(`auto`)}).default({pushIntervalSeconds:60,pullIntervalSeconds:30,autoCommit:!0,autoPush:!0,autoPull:!0,commitMessage:`auto`}),server:l.object({port:l.number().int().min(0).max(65535).default(0),host:l.string().regex(/^[\w.\-:]+$/,`Invalid hostname`).default(`localhost`),openOnAgentEdit:l.boolean().default(!1)}).default({port:0,host:`localhost`,openOnAgentEdit:!1}),persistence:l.object({debounceMs:l.number().int().min(0).default(2e3),maxDebounceMs:l.number().int().min(0).default(1e4)}).default({debounceMs:2e3,maxDebounceMs:1e4}),preview:l.object({baseUrl:l.url().optional()}).default({}),folders:l.array(f).default([]),mcp:l.object({autoStart:l.boolean().default(!0),tools:l.object({read_document:l.object({historyDepth:l.number().int().min(0).default(5)}).default({historyDepth:5}),search:l.object({maxResults:l.number().int().min(1).default(50)}).default({maxResults:50})}).default({read_document:{historyDepth:5},search:{maxResults:50}})}).default({autoStart:!0,tools:{read_document:{historyDepth:5},search:{maxResults:50}}})});function m(e,t){let r={...e};for(let i of Object.keys(t)){let a=e[i],o=t[i];n(o)&&n(a)?r[i]=m(a,o):o!==void 0&&(r[i]=o)}return r}function h(e){if(!r(e))return null;try{let t=s(i(e,`utf-8`));return n(t)?t:null}catch(t){return console.warn(`[config] Failed to parse ${e}: ${t instanceof Error?t.message:t}`),null}}function g(n){let r=n??process.cwd(),i=[],s=o(a(),t,e),c={},l=h(s);l&&(c=m(c,l),i.push(s));let u=o(r,t,e),d=h(u);d&&(c=m(c,d),i.push(u));let f=p.safeParse(c);if(!f.success){let e=f.error.issues.map(e=>` ${e.path.join(`.`)}: ${e.message}`);throw Error(`Invalid configuration:\n${e.join(`
1
+ import{n as e}from"./constants-Dqmeg2oi.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{t as n}from"./is-object-7k010cEq.mjs";import{existsSync as r,readFileSync as i}from"node:fs";import{homedir as a}from"node:os";import{resolve as o}from"node:path";import{parse as s}from"yaml";import{realpath as c}from"node:fs/promises";import{z as l}from"zod";async function u(e){let t=o(e);try{return await c(t)}catch(e){if(e.code!==`ENOENT`){let n=e instanceof Error?e.message:String(e);console.warn(`[normalize-cwd] realpath failed for ${t}: ${n}`)}return t}}const d=l.object({title:l.string().optional(),description:l.string().optional(),tags:l.array(l.string()).optional()}).strict(),f=l.object({match:l.string().min(1,"`match` must be a non-empty glob pattern (e.g. 'specs/**' or 'reports/*/**')"),frontmatter:d}).strict(),p=l.object({content:l.object({dir:l.string().default(`.`),include:l.array(l.string()).min(1).default([`**/*.md`,`**/*.mdx`]),exclude:l.array(l.string()).default([])}).default({dir:`.`,include:[`**/*.md`,`**/*.mdx`],exclude:[]}),github:l.object({oauthAppClientId:l.string().default(`Ov23liqlSd0V1MwR6rhI`)}).default({oauthAppClientId:`Ov23liqlSd0V1MwR6rhI`}),sync:l.object({enabled:l.boolean().optional(),pushIntervalSeconds:l.number().int().min(1).default(60),pullIntervalSeconds:l.number().int().min(1).default(30),autoCommit:l.boolean().default(!0),autoPush:l.boolean().default(!0),autoPull:l.boolean().default(!0),commitMessage:l.string().default(`auto`)}).default({pushIntervalSeconds:60,pullIntervalSeconds:30,autoCommit:!0,autoPush:!0,autoPull:!0,commitMessage:`auto`}),server:l.object({port:l.number().int().min(0).max(65535).default(0),host:l.string().regex(/^[\w.\-:]+$/,`Invalid hostname`).default(`localhost`),openOnAgentEdit:l.boolean().default(!1)}).default({port:0,host:`localhost`,openOnAgentEdit:!1}),persistence:l.object({debounceMs:l.number().int().min(0).default(2e3),maxDebounceMs:l.number().int().min(0).default(1e4)}).default({debounceMs:2e3,maxDebounceMs:1e4}),preview:l.object({baseUrl:l.url().optional()}).default({}),folders:l.array(f).default([]),mcp:l.object({autoStart:l.boolean().default(!0),tools:l.object({read_document:l.object({historyDepth:l.number().int().min(0).default(5)}).default({historyDepth:5}),search:l.object({maxResults:l.number().int().min(1).default(50)}).default({maxResults:50})}).default({read_document:{historyDepth:5},search:{maxResults:50}})}).default({autoStart:!0,tools:{read_document:{historyDepth:5},search:{maxResults:50}}})});function m(e,t){let r={...e};for(let i of Object.keys(t)){let a=e[i],o=t[i];n(o)&&n(a)?r[i]=m(a,o):o!==void 0&&(r[i]=o)}return r}function h(e){if(!r(e))return null;try{let t=s(i(e,`utf-8`));return n(t)?t:null}catch(t){return console.warn(`[config] Failed to parse ${e}: ${t instanceof Error?t.message:t}`),null}}function g(n){let r=n??process.cwd(),i=[],s=o(a(),t,e),c={},l=h(s);l&&(c=m(c,l),i.push(s));let u=o(r,t,e),d=h(u);d&&(c=m(c,d),i.push(u));let f=p.safeParse(c);if(!f.success){let e=f.error.issues.map(e=>` ${e.path.join(`.`)}: ${e.message}`);throw Error(`Invalid configuration:\n${e.join(`
2
2
  `)}`)}return{config:f.data,sources:i}}function _(e,t=process.env){let n=e;return t.PORT&&(n={...n,server:{...n.server,port:Number(t.PORT)}}),t.HOST&&(n={...n,server:{...n.server,host:t.HOST}}),n}function v(e){let t=e.env??process.env,n=e.cacheMs??1e3,r=e.loadConfigFn??g,i=new Map,a=new Map,o=u(e.startupCwd);return async s=>{let c=await u(s??e.startupCwd),l=Date.now(),d=i.get(c);if(d&&d.expiresAt>l)return d.config;let f=a.get(c);if(f)return await f;let p=(async()=>{if(c===await o){let r=_(e.startupConfig,t);return i.set(c,{config:r,expiresAt:Date.now()+n}),r}let a=_(r(c).config,t);return i.set(c,{config:a,expiresAt:Date.now()+n}),a})();a.set(c,p);try{return await p}finally{a.delete(c)}}}export{u as i,g as n,p as r,v as t};
3
- //# sourceMappingURL=loader-CGbKkeEd.mjs.map
3
+ //# sourceMappingURL=loader-CEfLKIxb.mjs.map
@@ -0,0 +1 @@
1
+ import{n as e}from"./loader-CEfLKIxb.mjs";export{e as loadConfig};
@@ -1,2 +1,2 @@
1
- import"./constants-DFnJ9to1.mjs";import{O as e}from"./src-CB-sXsMW.mjs";import{resolve as t}from"node:path";function n(e,n){return t(n,e.content.dir)}function r(n){return t(n,e)}export{r as n,n as t};
2
- //# sourceMappingURL=paths-Cw2HIHgI.mjs.map
1
+ import"./constants-Dqmeg2oi.mjs";import{O as e}from"./src-CB-sXsMW.mjs";import{resolve as t}from"node:path";function n(e,n){return t(n,e.content.dir)}function r(n){return t(n,e)}export{r as n,n as t};
2
+ //# sourceMappingURL=paths-BN0gQKmX.mjs.map
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./paths-BN0gQKmX.mjs";export{t as resolveContentDir,e as resolveLockDir};
@@ -1,3 +1,3 @@
1
- import"./constants-DFnJ9to1.mjs";import{O as e}from"./src-CB-sXsMW.mjs";import{h as t}from"./src-DBQiBMMB.mjs";import{existsSync as n,lstatSync as r,readdirSync as i,realpathSync as a,statSync as o}from"node:fs";import{join as s,relative as c}from"node:path";function l(e){let{projectDir:n,contentDir:l,include:u,exclude:d,sampleCap:f=5}=e,p=[],m=[];try{r(l)}catch(e){return{totalCount:0,sample:[],contentDir:l,include:u,exclude:d,warnings:[`cannot access content directory ${l}: ${e instanceof Error?e.message:String(e)}`]}}let h;try{h=t({projectDir:n,contentDir:l,includePatterns:u,excludePatterns:d})}catch(e){return{totalCount:0,sample:[],contentDir:l,include:u,exclude:d,warnings:[e instanceof Error?e.message:String(e)]}}function g(e){let t;try{t=i(e,{withFileTypes:!0})}catch(t){let n=t instanceof Error?t.message:String(t);p.push(`could not read directory ${c(l,e)||`.`}: ${n}`);return}for(let n of t){let t=s(e,n.name);if(n.isSymbolicLink()){let e;try{e=a(t)}catch(e){let n=e.code;n===`ENOENT`||n===`ELOOP`?p.push(`broken or cyclic symlink: ${c(l,t)}`):p.push(`cannot resolve symlink ${c(l,t)}: ${n??`unknown error`}`);continue}let n;try{n=o(e)}catch{continue}if(n.isDirectory()){let e=c(l,t);if(h.isDirExcluded(e))continue;g(t)}else if(n.isFile()){let e=c(l,t);if(h.isExcluded(e))continue;m.push(e)}}else if(n.isDirectory()){let e=c(l,t);if(h.isDirExcluded(e))continue;g(t)}else if(n.isFile()){let e=c(l,t);if(h.isExcluded(e))continue;m.push(e)}}}return g(l),{totalCount:m.length,sample:m.slice(0,f),contentDir:l,include:u,exclude:d,warnings:p}}function u(t,r){let i=[],a=c(r,t.contentDir),o=a===``?`./`:`./${a}`;i.push(`Content:`),i.push(` Found ${t.totalCount} markdown files in ${o}`);let l=t.include.join(`, `),u=t.exclude.length>0?t.exclude.join(`, `):`(none)`;if(i.push(` Scope: include=${l} exclude=${u}`),t.sample.length>0){let e=t.sample.join(`, `),n=t.totalCount>t.sample.length?`, …`:``;i.push(` Sample: ${e}${n}`)}if(t.warnings.length>0)for(let e of t.warnings)i.push(` Warning: ${e}`);return i.push(``),n(s(r,`.open-knowledge`,`config.yml`))?(i.push(` To adjust, edit ${e}/config.yml:`),i.push(` content:`),i.push(` include: ${JSON.stringify(t.include)}`),i.push(` exclude: ${JSON.stringify(t.exclude)}`)):(i.push(" Run `open-knowledge init` to scaffold config, then adjust:"),i.push(` ${e}/config.yml → content.include / content.exclude`)),i.push(``),i.push(` Re-check anytime: open-knowledge preview`),i.join(`
1
+ import"./constants-Dqmeg2oi.mjs";import{O as e}from"./src-CB-sXsMW.mjs";import{h as t}from"./src-DBQiBMMB.mjs";import{existsSync as n,lstatSync as r,readdirSync as i,realpathSync as a,statSync as o}from"node:fs";import{join as s,relative as c}from"node:path";function l(e){let{projectDir:n,contentDir:l,include:u,exclude:d,sampleCap:f=5}=e,p=[],m=[];try{r(l)}catch(e){return{totalCount:0,sample:[],contentDir:l,include:u,exclude:d,warnings:[`cannot access content directory ${l}: ${e instanceof Error?e.message:String(e)}`]}}let h;try{h=t({projectDir:n,contentDir:l,includePatterns:u,excludePatterns:d})}catch(e){return{totalCount:0,sample:[],contentDir:l,include:u,exclude:d,warnings:[e instanceof Error?e.message:String(e)]}}function g(e){let t;try{t=i(e,{withFileTypes:!0})}catch(t){let n=t instanceof Error?t.message:String(t);p.push(`could not read directory ${c(l,e)||`.`}: ${n}`);return}for(let n of t){let t=s(e,n.name);if(n.isSymbolicLink()){let e;try{e=a(t)}catch(e){let n=e.code;n===`ENOENT`||n===`ELOOP`?p.push(`broken or cyclic symlink: ${c(l,t)}`):p.push(`cannot resolve symlink ${c(l,t)}: ${n??`unknown error`}`);continue}let n;try{n=o(e)}catch{continue}if(n.isDirectory()){let e=c(l,t);if(h.isDirExcluded(e))continue;g(t)}else if(n.isFile()){let e=c(l,t);if(h.isExcluded(e))continue;m.push(e)}}else if(n.isDirectory()){let e=c(l,t);if(h.isDirExcluded(e))continue;g(t)}else if(n.isFile()){let e=c(l,t);if(h.isExcluded(e))continue;m.push(e)}}}return g(l),{totalCount:m.length,sample:m.slice(0,f),contentDir:l,include:u,exclude:d,warnings:p}}function u(t,r){let i=[],a=c(r,t.contentDir),o=a===``?`./`:`./${a}`;i.push(`Content:`),i.push(` Found ${t.totalCount} markdown files in ${o}`);let l=t.include.join(`, `),u=t.exclude.length>0?t.exclude.join(`, `):`(none)`;if(i.push(` Scope: include=${l} exclude=${u}`),t.sample.length>0){let e=t.sample.join(`, `),n=t.totalCount>t.sample.length?`, …`:``;i.push(` Sample: ${e}${n}`)}if(t.warnings.length>0)for(let e of t.warnings)i.push(` Warning: ${e}`);return i.push(``),n(s(r,`.open-knowledge`,`config.yml`))?(i.push(` To adjust, edit ${e}/config.yml:`),i.push(` content:`),i.push(` include: ${JSON.stringify(t.include)}`),i.push(` exclude: ${JSON.stringify(t.exclude)}`)):(i.push(" Run `open-knowledge init` to scaffold config, then adjust:"),i.push(` ${e}/config.yml → content.include / content.exclude`)),i.push(``),i.push(` Re-check anytime: open-knowledge preview`),i.join(`
2
2
  `)}export{l as n,u as t};
3
- //# sourceMappingURL=preview-9UMLu9Js.mjs.map
3
+ //# sourceMappingURL=preview-BmSvc-WZ.mjs.map
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./preview-BmSvc-WZ.mjs";export{t as formatPreviewBlock,e as previewContent};
@@ -0,0 +1 @@
1
+ import"./init-DIbZ0Udv.mjs";import"./loader-CEfLKIxb.mjs";export{};
@@ -0,0 +1 @@
1
+ import{o as e}from"./start-J6AfuX7h.mjs";export{e as startCommand};
@@ -1,2 +1,2 @@
1
- import{i as e}from"./constants-DFnJ9to1.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{Command as n}from"commander";import{closeSync as r,existsSync as i,mkdirSync as a,openSync as o}from"node:fs";import{join as s}from"node:path";import{spawn as c}from"node:child_process";function l(){let e=process.execPath,t=process.argv[1];return t?{command:e,prefixArgs:[t]}:(console.warn(`[self-spawn] process.argv[1] is empty — falling back to \`npx @inkeep/open-knowledge\`. This re-introduces the version-drift surface that re-exec was fixing. Observed argv: ${JSON.stringify(process.argv)}`),{command:`npx`,prefixArgs:[`@inkeep/open-knowledge`]})}function u(e){return e.uiLock?e.isAlive(e.uiLock.pid)?{action:`skip`,reason:`alive`,pid:e.uiLock.pid,port:e.uiLock.port}:{action:`spawn`,reason:`stale`,stalePid:e.uiLock.pid}:{action:`spawn`,reason:`absent`}}function d(e){i(e.lockDir)||a(e.lockDir,{recursive:!0});let t=o(s(e.lockDir,`last-spawn-error.log`),`w`),n=e.spawn??c,{PORT:u,...d}=process.env,f=l();try{let r=n(f.command,[...f.prefixArgs,...e.args??[`ui`]],{detached:!0,stdio:[`ignore`,`ignore`,t],cwd:e.cwd,env:d});return r.unref(),r}finally{try{r(t)}catch{}}}async function f(e){let t=e.now()+e.timeoutMs;for(;e.now()<t;){let t=e.readUiLock();if(t&&t.port>0)return t.port;await e.sleep(e.pollIntervalMs)}let n=e.readUiLock();return n&&n.port>0?n.port:null}function p(e){let t=e.sigtermGraceMs??1e4,n=e.sigtermPollIntervalMs??200,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));return async()=>{try{let i=e.readUiLock();if(i&&e.isAlive(i.pid))try{e.killPid(i.pid,`SIGTERM`),e.log?.info({pid:i.pid,port:i.port},`idle-shutdown: SIGTERM UI sibling`);let a=Date.now()+t;for(;Date.now()<a&&e.isAlive(i.pid);)await r(n);if(e.isAlive(i.pid))try{e.killPid(i.pid,`SIGKILL`),e.log?.warn({pid:i.pid,graceMs:t},`idle-shutdown: SIGTERM grace expired — escalated to SIGKILL`)}catch(t){e.log?.error({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: SIGKILL failed`)}}catch(t){e.log?.warn({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: failed to SIGTERM UI sibling`)}}catch(t){e.log?.warn({err:t instanceof Error?t.message:String(t)},`idle-shutdown: UI lookup failed; proceeding with destroy`)}await e.destroy()}}async function m(e){let{config:n,cwd:r}=e,i=e.skipAutoInit??!1,a=e.skipUiAutoSpawn??!1,o=e.idleThresholdMs??18e5,{existsSync:s,mkdirSync:c}=await import(`node:fs`),{resolve:l}=await import(`node:path`),{bootServer:m,ensureProjectGit:h,getLogger:g,isProcessAlive:_,readUiLock:v}=await import(`./src-zcKwR9RH.mjs`),{resolveContentDir:y}=await import(`./paths-BqubmGF4.mjs`),b=e.log??g(`start`),x=y(n,r);s(x)||(c(x,{recursive:!0}),b.info({contentDir:x},`Created content directory`));let S=!s(l(r,t)),C=i?void 0:async()=>{try{let{initContent:e}=await import(`./init-CDn_Us0v.mjs`),t=e(r);return S||t.created.length>0}catch(e){return console.warn(`Auto-init failed:`,e instanceof Error?e.message:e),!1}},w=!1,T=l(x,t),E=n.server.openOnAgentEdit?()=>{if(w)return;let e=v(T);if(!e||e.port<=0||!_(e.pid))return;w=!0;let t=`http://localhost:${e.port}`;import(`./open-browser-T-bOz6ZQ.mjs`).then(({openBrowser:e})=>e(t)).catch(()=>{})}:void 0,D=null,O=await m({contentDir:x,projectDir:r,contentRoot:n.content.dir,port:n.server.port,host:n.server.host,quiet:!1,debounce:n.persistence.debounceMs,maxDebounce:n.persistence.maxDebounceMs,includePatterns:n.content.include,excludePatterns:n.content.exclude,onAgentWrite:E,localOpCliArgs:[process.execPath,process.argv[1]],attachUiSibling:!0,idleShutdownMs:o,skipAutoInit:i,autoInitFn:C,ensureProjectGitFn:i?void 0:()=>h(r),spawnUiSiblingFn:async({lockDir:t})=>{if(D=u({uiLock:v(t),isAlive:_}),D.action===`spawn`&&!a)try{d({lockDir:t,cwd:r,spawn:e.spawn}),b.info({reason:D.reason},`[start] auto-spawned ok ui sibling`)}catch(e){console.warn(`[start] failed to auto-spawn ok ui: ${e instanceof Error?e.message:String(e)}`)}else D.action===`skip`&&b.info({port:D.port,pid:D.pid},`UI already running at port ${D.port}`)},idleShutdownHandler:e=>p({readUiLock:()=>v(O.lockDir),isAlive:_,killPid:(e,t)=>{process.kill(e,t)},destroy:e,log:b}),log:b});D||={action:`skip`,reason:`alive`,pid:0,port:0};let k=D,A=null;if(k.action===`skip`)A=k.port>0?k.port:null;else if(!a){let t=e.uiBindTimeoutMs??3e3;A=await f({readUiLock:()=>v(O.lockDir),now:Date.now,sleep:e=>new Promise(t=>setTimeout(t,e)),timeoutMs:t,pollIntervalMs:50}),A===null&&b.warn({timeoutMs:t},`[start] ok ui did not bind within timeout — banner falls back to API URL`)}return{httpServer:O.httpServer,destroy:O.destroy,lockDir:O.lockDir,contentDir:x,port:O.port,ready:O.ready,degraded:O.degraded,uiSpawnDecision:D,resolvedUiPort:A,didAutoInit:O.didAutoInit,didGitInit:O.didGitInit}}function h(r){return new n(`start`).description(`Start the knowledge base collab server`).option(`-p, --port <port>`,`Server port`,void 0).option(`-H, --host <host>`,`Server host`,void 0).option(`--open`,`Open browser after start`).option(`--no-init`,`Skip auto-scaffolding of ${t}/`).action(async n=>{let{renderBanner:i}=await import(`./banner-CI3--er0.mjs`),{dim:a,error:o,info:s,warning:c}=await import(`./colors-CxLEz90E.mjs`),l=r(),u=process.cwd();n.port!==void 0&&(l.server.port=Number(n.port)),n.host!==void 0&&(l.server.host=n.host);let d;try{d=await m({config:l,cwd:u,skipAutoInit:n.init===!1})}catch(e){let{ProjectGitInitError:t}=await import(`./src-zcKwR9RH.mjs`);e instanceof t&&(console.error(o(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.`)),e.stderr&&console.error(a(e.stderr.trim())),process.exit(1)),console.error(`${o(`Failed to start:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exit(1)}let f=!1,p=async e=>{if(!f){f=!0,console.log(a(`\nShutting down (${e})...`));try{await d.destroy()}catch(e){console.error(`${o(`destroy() failed:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exitCode=1}process.exit(process.exitCode??0)}};process.once(`SIGINT`,()=>{p(`SIGINT`)}),process.once(`SIGTERM`,()=>{p(`SIGTERM`)});let h=`http://${l.server.host}:${d.port}`,g=l.server.host===`0.0.0.0`||l.server.host===`::`?`http://0.0.0.0:${d.port}`:void 0,_=d.resolvedUiPort,v=_!==null&&_>0?`http://${l.server.host}:${_}`:h;console.log(i({name:`open-knowledge`,version:e,localUrl:v,apiUrl:v===h?void 0:h,networkUrl:g})),d.didAutoInit&&(console.log(` ${s(`✓`)} Scaffolded ${t}/ (first run)`),console.log(` ${a("Tip: Run `open-knowledge init` to register MCP tools for Claude Code")}\n`));let y={"shadow-repo":`Version history and branch-switch safety unavailable`,"file-watcher":`External file changes will not sync to the editor`,"head-watcher":`Git branch switches may cause document inconsistency`};d.ready.then(async()=>{if(d.degraded.length>0){console.log();for(let e of d.degraded){let t=y[e]??`${e} (check server logs for details)`;console.warn(` ${c(`⚠`)} ${c(e)}: ${a(t)}`)}console.log()}if(d.didAutoInit||d.didGitInit)if(d.didGitInit&&console.log(`\n ${s(`✓`)} Initialized git repo at ${u}/.git/ (default branch: main)`),d.didAutoInit)try{let{previewContent:e,formatPreviewBlock:t}=await import(`./preview-BcZ1UmA0.mjs`),n=e({projectDir:u,contentDir:d.contentDir,include:l.content.include,exclude:l.content.exclude});console.log(`\n${t(n,u)}\n`)}catch(e){console.warn(`Content preview unavailable: ${e instanceof Error?e.message:String(e)}`)}else console.log();if(n.open){let{openBrowser:e}=await import(`./open-browser-T-bOz6ZQ.mjs`);e(v)}}).catch(e=>{console.error(` ${o(`Server initialization failed:`)} ${e instanceof Error?e.message:String(e)}`)})})}export{d as a,u as i,m as n,h as o,p as r,l as s,f as t};
2
- //# sourceMappingURL=start-C0e6lay8.mjs.map
1
+ import{i as e}from"./constants-Dqmeg2oi.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{Command as n}from"commander";import{closeSync as r,existsSync as i,mkdirSync as a,openSync as o}from"node:fs";import{join as s}from"node:path";import{spawn as c}from"node:child_process";function l(){let e=process.execPath,t=process.argv[1];return t?{command:e,prefixArgs:[t]}:(console.warn(`[self-spawn] process.argv[1] is empty — falling back to \`npx @inkeep/open-knowledge\`. This re-introduces the version-drift surface that re-exec was fixing. Observed argv: ${JSON.stringify(process.argv)}`),{command:`npx`,prefixArgs:[`@inkeep/open-knowledge`]})}function u(e){return e.uiLock?e.isAlive(e.uiLock.pid)?{action:`skip`,reason:`alive`,pid:e.uiLock.pid,port:e.uiLock.port}:{action:`spawn`,reason:`stale`,stalePid:e.uiLock.pid}:{action:`spawn`,reason:`absent`}}function d(e){i(e.lockDir)||a(e.lockDir,{recursive:!0});let t=o(s(e.lockDir,`last-spawn-error.log`),`w`),n=e.spawn??c,{PORT:u,...d}=process.env,f=l();try{let r=n(f.command,[...f.prefixArgs,...e.args??[`ui`]],{detached:!0,stdio:[`ignore`,`ignore`,t],cwd:e.cwd,env:d});return r.unref(),r}finally{try{r(t)}catch{}}}async function f(e){let t=e.now()+e.timeoutMs;for(;e.now()<t;){let t=e.readUiLock();if(t&&t.port>0)return t.port;await e.sleep(e.pollIntervalMs)}let n=e.readUiLock();return n&&n.port>0?n.port:null}function p(e){let t=e.sigtermGraceMs??1e4,n=e.sigtermPollIntervalMs??200,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));return async()=>{try{let i=e.readUiLock();if(i&&e.isAlive(i.pid))try{e.killPid(i.pid,`SIGTERM`),e.log?.info({pid:i.pid,port:i.port},`idle-shutdown: SIGTERM UI sibling`);let a=Date.now()+t;for(;Date.now()<a&&e.isAlive(i.pid);)await r(n);if(e.isAlive(i.pid))try{e.killPid(i.pid,`SIGKILL`),e.log?.warn({pid:i.pid,graceMs:t},`idle-shutdown: SIGTERM grace expired — escalated to SIGKILL`)}catch(t){e.log?.error({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: SIGKILL failed`)}}catch(t){e.log?.warn({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: failed to SIGTERM UI sibling`)}}catch(t){e.log?.warn({err:t instanceof Error?t.message:String(t)},`idle-shutdown: UI lookup failed; proceeding with destroy`)}await e.destroy()}}async function m(e){let{config:n,cwd:r}=e,i=e.skipAutoInit??!1,a=e.skipUiAutoSpawn??!1,o=e.idleThresholdMs??18e5,{existsSync:s,mkdirSync:c}=await import(`node:fs`),{resolve:l}=await import(`node:path`),{bootServer:m,ensureProjectGit:h,getLogger:g,isProcessAlive:_,readUiLock:v}=await import(`./src-zcKwR9RH.mjs`),{resolveContentDir:y}=await import(`./paths-HWNY8fZl.mjs`),b=e.log??g(`start`),x=y(n,r);s(x)||(c(x,{recursive:!0}),b.info({contentDir:x},`Created content directory`));let S=!s(l(r,t)),C=i?void 0:async()=>{try{let{initContent:e}=await import(`./init-AmgsVReV.mjs`),t=e(r);return S||t.created.length>0}catch(e){return console.warn(`Auto-init failed:`,e instanceof Error?e.message:e),!1}},w=!1,T=l(x,t),E=n.server.openOnAgentEdit?()=>{if(w)return;let e=v(T);if(!e||e.port<=0||!_(e.pid))return;w=!0;let t=`http://localhost:${e.port}`;import(`./open-browser-T-bOz6ZQ.mjs`).then(({openBrowser:e})=>e(t)).catch(()=>{})}:void 0,D=null,O=await m({contentDir:x,projectDir:r,contentRoot:n.content.dir,port:n.server.port,host:n.server.host,quiet:!1,debounce:n.persistence.debounceMs,maxDebounce:n.persistence.maxDebounceMs,includePatterns:n.content.include,excludePatterns:n.content.exclude,onAgentWrite:E,localOpCliArgs:[process.execPath,process.argv[1]],attachUiSibling:!0,idleShutdownMs:o,skipAutoInit:i,autoInitFn:C,ensureProjectGitFn:i?void 0:()=>h(r),spawnUiSiblingFn:async({lockDir:t})=>{if(D=u({uiLock:v(t),isAlive:_}),D.action===`spawn`&&!a)try{d({lockDir:t,cwd:r,spawn:e.spawn}),b.info({reason:D.reason},`[start] auto-spawned ok ui sibling`)}catch(e){console.warn(`[start] failed to auto-spawn ok ui: ${e instanceof Error?e.message:String(e)}`)}else D.action===`skip`&&b.info({port:D.port,pid:D.pid},`UI already running at port ${D.port}`)},idleShutdownHandler:e=>p({readUiLock:()=>v(O.lockDir),isAlive:_,killPid:(e,t)=>{process.kill(e,t)},destroy:e,log:b}),log:b});D||={action:`skip`,reason:`alive`,pid:0,port:0};let k=D,A=null;if(k.action===`skip`)A=k.port>0?k.port:null;else if(!a){let t=e.uiBindTimeoutMs??3e3;A=await f({readUiLock:()=>v(O.lockDir),now:Date.now,sleep:e=>new Promise(t=>setTimeout(t,e)),timeoutMs:t,pollIntervalMs:50}),A===null&&b.warn({timeoutMs:t},`[start] ok ui did not bind within timeout — banner falls back to API URL`)}return{httpServer:O.httpServer,destroy:O.destroy,lockDir:O.lockDir,contentDir:x,port:O.port,ready:O.ready,degraded:O.degraded,uiSpawnDecision:D,resolvedUiPort:A,didAutoInit:O.didAutoInit,didGitInit:O.didGitInit}}function h(r){return new n(`start`).description(`Start the knowledge base collab server`).option(`-p, --port <port>`,`Server port`,void 0).option(`-H, --host <host>`,`Server host`,void 0).option(`--open`,`Open browser after start`).option(`--no-init`,`Skip auto-scaffolding of ${t}/`).action(async n=>{let{renderBanner:i}=await import(`./banner-CI3--er0.mjs`),{dim:a,error:o,info:s,warning:c}=await import(`./colors-CxLEz90E.mjs`),l=r(),u=process.cwd();n.port!==void 0&&(l.server.port=Number(n.port)),n.host!==void 0&&(l.server.host=n.host);let d;try{d=await m({config:l,cwd:u,skipAutoInit:n.init===!1})}catch(e){let{ProjectGitInitError:t}=await import(`./src-zcKwR9RH.mjs`);e instanceof t&&(console.error(o(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.`)),e.stderr&&console.error(a(e.stderr.trim())),process.exit(1)),console.error(`${o(`Failed to start:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exit(1)}let f=!1,p=async e=>{if(!f){f=!0,console.log(a(`\nShutting down (${e})...`));try{await d.destroy()}catch(e){console.error(`${o(`destroy() failed:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exitCode=1}process.exit(process.exitCode??0)}};process.once(`SIGINT`,()=>{p(`SIGINT`)}),process.once(`SIGTERM`,()=>{p(`SIGTERM`)});let h=`http://${l.server.host}:${d.port}`,g=l.server.host===`0.0.0.0`||l.server.host===`::`?`http://0.0.0.0:${d.port}`:void 0,_=d.resolvedUiPort,v=_!==null&&_>0?`http://${l.server.host}:${_}`:h;console.log(i({name:`open-knowledge`,version:e,localUrl:v,apiUrl:v===h?void 0:h,networkUrl:g})),d.didAutoInit&&(console.log(` ${s(`✓`)} Scaffolded ${t}/ (first run)`),console.log(` ${a("Tip: Run `open-knowledge init` to register MCP tools for Claude Code")}\n`));let y={"shadow-repo":`Version history and branch-switch safety unavailable`,"file-watcher":`External file changes will not sync to the editor`,"head-watcher":`Git branch switches may cause document inconsistency`};d.ready.then(async()=>{if(d.degraded.length>0){console.log();for(let e of d.degraded){let t=y[e]??`${e} (check server logs for details)`;console.warn(` ${c(`⚠`)} ${c(e)}: ${a(t)}`)}console.log()}if(d.didAutoInit||d.didGitInit)if(d.didGitInit&&console.log(`\n ${s(`✓`)} Initialized git repo at ${u}/.git/ (default branch: main)`),d.didAutoInit)try{let{previewContent:e,formatPreviewBlock:t}=await import(`./preview-DzHGOZjd.mjs`),n=e({projectDir:u,contentDir:d.contentDir,include:l.content.include,exclude:l.content.exclude});console.log(`\n${t(n,u)}\n`)}catch(e){console.warn(`Content preview unavailable: ${e instanceof Error?e.message:String(e)}`)}else console.log();if(n.open){let{openBrowser:e}=await import(`./open-browser-T-bOz6ZQ.mjs`);e(v)}}).catch(e=>{console.error(` ${o(`Server initialization failed:`)} ${e instanceof Error?e.message:String(e)}`)})})}export{d as a,u as i,m as n,h as o,p as r,l as s,f as t};
2
+ //# sourceMappingURL=start-J6AfuX7h.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/open-knowledge",
3
- "version": "0.0.0-dev-20260424195655",
3
+ "version": "0.0.0-dev-20260424205527",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -1,2 +0,0 @@
1
- import"./src-CB-sXsMW.mjs";var e=`0.0.0-dev-20260424195655`;const t=`config.yml`,n=`cache`,r=e,i=`open-knowledge`;export{r as i,t as n,i as r,n as t};
2
- //# sourceMappingURL=constants-DFnJ9to1.mjs.map
@@ -1 +0,0 @@
1
- import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./init-14nxErpx.mjs";export{o as detectInstalledEditors,n as formatInitResult,i as initCommand,t as readExistingMcpEntry,e as runInit,r as writeEditorMcpConfig,a as writeUserMcpConfigs};
@@ -1 +0,0 @@
1
- import{n as e,t}from"./init-BGPwx74o.mjs";export{t as ensureOkGitignoredAtRoot,e as initContent};
@@ -1 +0,0 @@
1
- import{n as e}from"./loader-CGbKkeEd.mjs";export{e as loadConfig};
@@ -1 +0,0 @@
1
- import{n as e,t}from"./paths-Cw2HIHgI.mjs";export{t as resolveContentDir,e as resolveLockDir};
@@ -1 +0,0 @@
1
- import{n as e,t}from"./preview-9UMLu9Js.mjs";export{t as formatPreviewBlock,e as previewContent};
@@ -1 +0,0 @@
1
- import"./init-14nxErpx.mjs";import"./loader-CGbKkeEd.mjs";export{};
@@ -1 +0,0 @@
1
- import{o as e}from"./start-C0e6lay8.mjs";export{e as startCommand};