@inkeep/open-knowledge 0.0.0-dev-20260421165805 → 0.0.0-dev-20260421173508

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{D as e,E as t,s as n}from"./src-Ds19hvLH.mjs";import{a as r,i}from"./constants-Dx_MrCyB.mjs";import{n as a,t as o}from"./paths-vKL8Dnp_.mjs";import{G as s,H as c,U as l,W as u,X as d,l as f}from"./src-9qc50QcN.mjs";import{c as p,f as m,r as h}from"./server-lock-ChItwD14.mjs";import{i as g}from"./init-8JV3QQNU.mjs";import{n as _}from"./colors-eCHTjaBL.mjs";import{t as v}from"./is-object-DVVYT5oa.mjs";import{r as y}from"./init-UYi5s8Q6.mjs";import{a as b,o as x}from"./start-CfpWFTzI.mjs";import{t as S}from"./loader-DqrtMiNp.mjs";import"./src-DvkXxOes.mjs";import{Command as C}from"commander";import{closeSync as w,existsSync as T,mkdirSync as E,openSync as D,readFileSync as O,readdirSync as ee,statSync as k,unlinkSync as A,writeFileSync as te}from"node:fs";import{homedir as ne,hostname as re}from"node:os";import{basename as ie,dirname as ae,isAbsolute as oe,join as se,relative as ce,resolve as j}from"node:path";import{parse as le,stringify as ue}from"yaml";import{createOAuthDeviceAuth as de}from"@octokit/auth-oauth-device";import fe from"@inquirer/password";import{Octokit as pe}from"@octokit/rest";import{fileURLToPath as me}from"node:url";import{randomUUID as he}from"node:crypto";import{execFileSync as ge,spawn as _e}from"node:child_process";import M from"simple-git";import{readFile as ve,readdir as ye,stat as be}from"node:fs/promises";import{createServer as xe,request as Se}from"node:http";import Ce from"picomatch";import{McpServer as we}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Te}from"@modelcontextprotocol/sdk/server/stdio.js";import{RootsListChangedNotificationSchema as Ee}from"@modelcontextprotocol/sdk/types.js";import{z as N}from"zod";import{Bash as De,ReadWriteFs as Oe}from"just-bash";import ke from"shell-quote";const Ae=`open-knowledge`;var je=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(Ae,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(Ae,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(Ae,e).deletePassword()}catch{}}},Me=class{backend=`file`;authFile;constructor(e){this.authFile=e??se(ne(),`.open-knowledge`,`auth.yml`)}read(){if(!T(this.authFile))return{};try{return le(O(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=ae(this.authFile);T(t)||E(t,{recursive:!0,mode:448}),te(this.authFile,ue(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 Ne(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(Ae,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
2
+ import{D as e,E as t,s as n}from"./src-Ds19hvLH.mjs";import{a as r,i}from"./constants-kK8FA_so.mjs";import{n as a,t as o}from"./paths-COFg_gne.mjs";import{G as s,H as c,U as l,W as u,X as d,l as f}from"./src-9qc50QcN.mjs";import{c as p,f as m,r as h}from"./server-lock-ChItwD14.mjs";import{i as g}from"./init-Djmfs2Ls.mjs";import{n as _}from"./colors-eCHTjaBL.mjs";import{t as v}from"./is-object-DVVYT5oa.mjs";import{r as y}from"./init-CDVXoJkt.mjs";import{a as b,o as x}from"./start-BeBgDf0l.mjs";import{t as S}from"./loader-B_agr6SC.mjs";import"./src-CQXKf0uA.mjs";import{Command as C}from"commander";import{closeSync as w,existsSync as T,mkdirSync as E,openSync as D,readFileSync as O,readdirSync as ee,statSync as k,unlinkSync as A,writeFileSync as te}from"node:fs";import{homedir as ne,hostname as re}from"node:os";import{basename as ie,dirname as ae,isAbsolute as oe,join as se,relative as ce,resolve as j}from"node:path";import{parse as le,stringify as ue}from"yaml";import{createOAuthDeviceAuth as de}from"@octokit/auth-oauth-device";import fe from"@inquirer/password";import{Octokit as pe}from"@octokit/rest";import{fileURLToPath as me}from"node:url";import{randomUUID as he}from"node:crypto";import{execFileSync as ge,spawn as _e}from"node:child_process";import M from"simple-git";import{readFile as ve,readdir as ye,stat as be}from"node:fs/promises";import{createServer as xe,request as Se}from"node:http";import Ce from"picomatch";import{McpServer as we}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Te}from"@modelcontextprotocol/sdk/server/stdio.js";import{RootsListChangedNotificationSchema as Ee}from"@modelcontextprotocol/sdk/types.js";import{z as N}from"zod";import{Bash as De,ReadWriteFs as Oe}from"just-bash";import ke from"shell-quote";const Ae=`open-knowledge`;var je=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(Ae,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(Ae,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(Ae,e).deletePassword()}catch{}}},Me=class{backend=`file`;authFile;constructor(e){this.authFile=e??se(ne(),`.open-knowledge`,`auth.yml`)}read(){if(!T(this.authFile))return{};try{return le(O(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=ae(this.authFile);T(t)||E(t,{recursive:!0,mode:448}),te(this.authFile,ue(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 Ne(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(Ae,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
3
3
  `),new je}catch{return process.stderr.write(`[auth] token storage: file (~/.open-knowledge/auth.yml)
4
4
  `),new Me(e)}}async function Pe(e,t,n){let r=Fe(await Ie(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 Fe(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 Ie(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 Le(e){let t=new C(`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 Pe(process.stdin,process.stdout,t);process.exit(n)}),t}async function Re(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=de({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 Be=new Set([`gitlab.com`,`bitbucket.org`,`codeberg.org`,`gitea.com`,`sr.ht`,`sourcehut.org`]);function Ve(e){let t=e.toLowerCase().replace(/:\d+$/,``);Be.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 He(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Ue(e,t,n,r=Re){let i=ze(n),{host:a,json:o}=e;Ve(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?He(!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?He(!0,{type:`complete`,host:a,login:c}):process.stderr.write(`✓ Logged in as ${c} on ${a}\n`)}function We(e,t){return new C(`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 Ue(n,await t(),e())})}async function Ge(e,t,n){let{host:r,json:i}=e;Ve(r);let a=await(n??(()=>fe({message:`Enter PAT:`})))();a||(process.stderr.write(`No token provided
@@ -7,7 +7,7 @@ import{D as e,E as t,s as n}from"./src-Ds19hvLH.mjs";import{a as r,i}from"./cons
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 Ke(e){return new C(`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 Ge(t,await e())})}async function qe(e,t){let{host:n,json:r}=e;Ve(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 pe({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 Je(e){return new C(`repos`).description(`List accessible repositories`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await qe(t,await e())})}async function Ye(e,t){let{host:n}=e;await t.clear(n),process.stderr.write(`✓ Signed out from ${n}\n`)}function Xe(e){return new C(`signout`).description(`Remove stored credentials`).option(`--host <host>`,`GitHub hostname`,`github.com`).action(async t=>{await Ye(t,await e())})}async function Ze(e,t){let{host:n,json:r}=e;Ve(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 pe({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 Qe(e){return new C(`status`).description(`Show authentication status`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await Ze(t,await e())})}function $e(e){let t=new C(`auth`);t.description(`GitHub authentication management`);let n=()=>Ne(),r=e??(()=>({}));return t.addCommand(We(r,n)),t.addCommand(Qe(n)),t.addCommand(Je(n)),t.addCommand(Xe(n)),t.addCommand(Ke(n)),t.addCommand(Le(n)),t}function et(e,t,n={}){let r=p(e,t);if(!T(r))return{status:`missing`,lockPath:r};let i;try{i=JSON.parse(O(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??re();return a.hostname===o?(n.isAlive??m)(a.pid)?{status:`alive`,lockPath:r,lock:a}:{status:`dead-pid`,lockPath:r,lock:a}:{status:`foreign-host`,lockPath:r,lock:a}}function tt(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 nt(e){let t=e.inspect??(t=>et(e.lockDir,t)),n=e.unlink??(e=>A(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=tt(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 rt(e){return new C(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{nt({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}function it(){try{let e=ge(`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 at(e,t,n={},r=it){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 ot(e){return e.replace(/:\d+$/,``)}function st(e){let t=e.trim();if(!t)return null;{let e=/^https?:\/\/([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`https`,hostname:ot(e[1]),owner:e[2],name:e[3]}}{let e=/^ssh:\/\/(?:[\w.-]+@)?([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`ssh`,hostname:ot(e[1]),owner:e[2],name:e[3]}}{let e=/^git:\/\/([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`git`,hostname:ot(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 ct=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function lt(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 ct)if(n.includes(e))return{stage:t[1],pct:Math.round(i+r/100*(a-i))};return null}function ut(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function dt(e,t,n,r=process.cwd()){let i=st(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=t.dir?j(r,t.dir):j(r,i.name);if(T(a)&&ee(a).length>0)throw Error(`Target directory is not empty: ${a}`);let o=await Ne(),s=await at(i.hostname,o,{}),c=M({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=lt(e);n&&n.pct!==l&&(l=n.pct,ut(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
- `),!T(j(a,`.open-knowledge`)))try{let[{runInit:e},{ensureOkGitignoredAtRoot:t}]=await Promise.all([import(`./init-DihXGBlf.mjs`),import(`./init-B0G3IY-y.mjs`)]);e({cwd:a,mcp:!1});try{t(a)}catch{}}catch{}return a}function ft(e){return new C(`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 dt(t,{json:r.json,dir:n},i);if(r.json)ut(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-DsMb_t62.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?ut(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}function P(e,t){return{content:[{type:`text`,text:e}],...t?{isError:!0}:{}}}function F(e,t,n){return{content:[{type:`text`,text:e}],structuredContent:t,...n?{isError:!0}:{}}}const I="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.";async function L(e){return typeof e==`function`?await e():e}function R(e){let t=e.toLowerCase();return t.endsWith(`.md`)?{ok:!0,docName:e.slice(0,-3)}:t.endsWith(`.mdx`)?{ok:!0,docName:e.slice(0,-4)}:t.endsWith(`.markdown`)?{ok:!1,error:`Error: docName "${e}" ends in ".markdown", which is not a supported extension. Use ".md" or ".mdx", or strip the extension to let the server auto-detect.`}:{ok:!0,docName:e}}async function z(e,t){let n;try{n=await fetch(`${e}${t}`,{signal:AbortSignal.timeout(3e4)})}catch(e){return{ok:!1,error:`Server unreachable: ${e instanceof Error?e.message:e}`}}try{return await n.json()}catch{return{ok:!1,error:`Server returned HTTP ${n.status} with non-JSON body`}}}async function B(e,t,n){let r;try{r=await fetch(`${e}${t}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:n?JSON.stringify(n):void 0,signal:AbortSignal.timeout(3e4)})}catch(e){return{ok:!1,error:`Server unreachable: ${e instanceof Error?e.message:e}`}}try{return await r.json()}catch{return{ok:!1,error:`Server returned HTTP ${r.status} with non-JSON body`}}}function pt(e,n){return`Promote existing research on this topic into a canonical article inside the project content directory. **Canonical, not provisional** — the output is the source of truth for future agents.
10
+ `),!T(j(a,`.open-knowledge`)))try{let[{runInit:e},{ensureOkGitignoredAtRoot:t}]=await Promise.all([import(`./init-BBMugPUT.mjs`),import(`./init-DYchL1fN.mjs`)]);e({cwd:a,mcp:!1});try{t(a)}catch{}}catch{}return a}function ft(e){return new C(`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 dt(t,{json:r.json,dir:n},i);if(r.json)ut(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-Baqnlhxv.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?ut(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}function P(e,t){return{content:[{type:`text`,text:e}],...t?{isError:!0}:{}}}function F(e,t,n){return{content:[{type:`text`,text:e}],structuredContent:t,...n?{isError:!0}:{}}}const I="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.";async function L(e){return typeof e==`function`?await e():e}function R(e){let t=e.toLowerCase();return t.endsWith(`.md`)?{ok:!0,docName:e.slice(0,-3)}:t.endsWith(`.mdx`)?{ok:!0,docName:e.slice(0,-4)}:t.endsWith(`.markdown`)?{ok:!1,error:`Error: docName "${e}" ends in ".markdown", which is not a supported extension. Use ".md" or ".mdx", or strip the extension to let the server auto-detect.`}:{ok:!0,docName:e}}async function z(e,t){let n;try{n=await fetch(`${e}${t}`,{signal:AbortSignal.timeout(3e4)})}catch(e){return{ok:!1,error:`Server unreachable: ${e instanceof Error?e.message:e}`}}try{return await n.json()}catch{return{ok:!1,error:`Server returned HTTP ${n.status} with non-JSON body`}}}async function B(e,t,n){let r;try{r=await fetch(`${e}${t}`,{method:`POST`,headers:{"Content-Type":`application/json`},body:n?JSON.stringify(n):void 0,signal:AbortSignal.timeout(3e4)})}catch(e){return{ok:!1,error:`Server unreachable: ${e instanceof Error?e.message:e}`}}try{return await r.json()}catch{return{ok:!1,error:`Server returned HTTP ${r.status} with non-JSON body`}}}function pt(e,n){return`Promote existing research on this topic into a canonical article inside the project content directory. **Canonical, not provisional** — the output is the source of truth for future agents.
11
11
 
12
12
  Topic: ${e}
13
13
 
@@ -590,6 +590,6 @@ Folder metadata lives in \`config.yml\`, **not** in content files — this is in
590
590
  ${Object.entries(qr).map(([e,t])=>`### \`${e}\`\n${t}`).join(`
591
591
 
592
592
  `)}
593
- `}async function Xr(e){try{let t=e.replace(`ws://`,`http://`).replace(`wss://`,`https://`);return(await fetch(`${t}/api/agent-undo-status`,{signal:AbortSignal.timeout(2e3)})).ok}catch(e){return X(`Hocuspocus check failed: ${e instanceof Error?e.message:String(e)}`),!1}}async function Zr(e){let{projectDir:t,serverUrl:n,config:s}=e;X(n?await Xr(n)?`Hocuspocus detected at ${n}`:`Hocuspocus not available at ${n} — using disk-only mode`:`No explicit server URL — will discover lazily from server.lock per call`);let c=new we({name:i,version:r},{instructions:Yr(s)}),l=[],u=!1;async function d(){try{l=(await c.server.listRoots()).roots.map(e=>e.uri).filter(e=>e.startsWith(`file://`)).map(e=>me(e)),X(l.length>0?`roots: ${l.join(`, `)}`:`client advertised no roots — falling back to startup cwd`)}catch(e){X(`listRoots unsupported by client (using startup cwd): ${e instanceof Error?e.message:String(e)}`)}finally{u=!0}}let f=!1;async function p(e){return e||(u||await d(),l.length===0?(f||=(X(`no client roots — falling back to startup cwd: ${t}`),!0),t):(f&&=(X(`client roots now available — using ${l[0]}`),!1),l[0]))}c.server.setNotificationHandler(Ee,async()=>{u=!1,await d()});let m=n?n.replace(`ws://`,`http://`).replace(`wss://`,`https://`):void 0,g=new Map,_=async()=>{if(m)return m;let e=await p(),t=Date.now(),n=g.get(e);if(n&&n.expiresAt>t)return n.url;let r=h(a(o(s,e))),i=r&&r.port>0?`http://localhost:${r.port}`:void 0;return g.set(e,{url:i,expiresAt:t+1e3}),i},v=he(),y=process.env.AGENT_LABEL||void 0,b={current:{connectionId:v,label:y,displayName:y??`Agent`,colorSeed:y??v}};c.server.oninitialized=()=>{let e=c.server.getClientVersion();b.current={connectionId:v,clientInfo:e?{name:e.name,version:e.version}:void 0,label:y,displayName:y??e?.name??`Agent`,colorSeed:y??e?.name??v},X(`Agent identity: ${b.current.displayName} (${v.slice(0,8)})`)},Jr(c,{serverUrl:_,resolveCwd:p,startupCwd:t,config:s,identityRef:b});let x=new Te;await c.connect(x),X(`MCP server running (stdio)`),d().catch(()=>{});let{startKeepalive:S}=await import(`./keepalive-D-FSaNO6.mjs`),C=S({resolveWsUrl:async()=>{let e=await _();if(e)return e.replace(/^http:/,`ws:`).replace(/^https:/,`wss:`)},log:X}),w=()=>{try{C.close()}catch{}process.exit(0)};process.on(`SIGINT`,w),process.on(`SIGTERM`,w)}function Qr(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function $r(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 ei(e){let t=e.readLock??(()=>h(e.lockDir)),n=e.isAlive??m,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),i=e.spawn??_e,a=e.readErrorLog??(e=>T(e)?O(e,`utf-8`).trim():``),o=e.openErrorLog??(e=>D(e,`w`)),s=e.closeFd??(e=>w(e)),c=e.timeoutMs??5e3,l=e.pollIntervalMs??100,u=$r({host:e.host,portOverride:e.portOverride,envAutoStart:e.envAutoStart,configAutoStart:e.configAutoStart,readLock:t,isAlive:n});if(u.action===`connect`)return{serverUrl:u.url,message:u.message};if(u.action===`disk-only`)return{serverUrl:void 0,message:u.message};T(e.lockDir)||E(e.lockDir,{recursive:!0});let d=se(e.lockDir,`last-spawn-error.log`),f=o(d),p,g,_=x();try{try{p=i(_.command,[..._.prefixArgs,`start`],{detached:!0,stdio:[`ignore`,`ignore`,f],cwd:e.contentDir}),p.on(`error`,e=>{g=e instanceof Error?e.message:String(e)}),p.unref()}catch(e){g=e instanceof Error?e.message:String(e)}}finally{try{s(f)}catch{}}let v=Date.now()+c;for(;Date.now()<v;){if(g){let e=a(d);throw Error(`OK: spawn failed: ${g}${e?` stderr:\n${e}`:``}`)}await r(l);let e=t();if(e&&e.port>0&&n(e.pid)){let t=`ws://localhost:${e.port}`;return{serverUrl:t,message:`spawned ok start; connected at ${t} (pid ${e.pid})`}}}if(g){let e=a(d);throw Error(`OK: spawn failed: ${g}${e?` stderr:\n${e}`:``}`)}let y=a(d),b=(c/1e3).toFixed(c%1e3==0?0:2),S=p?.pid,C=``;throw typeof S==`number`&&(C=n(S)?` child pid=${S} is still running — raise OK_MCP_SPAWN_TIMEOUT_MS if this is a slow boot.`:` child pid=${S} exited — check last-spawn-error.log.`),Error(`OK: server did not start within ${b}s.${C}${y?` stderr:\n${y}`:``}`)}function ti(e){return new C(`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(n,r),{serverUrl:s,message:c}=await ei({lockDir:a(i),contentDir:i,host:n.server.host,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,configAutoStart:n.mcp.autoStart,timeoutMs:Qr(process.env.OK_MCP_SPAWN_TIMEOUT_MS)});process.stderr.write(`[mcp] ${c}\n`),await Zr({projectDir:r,serverUrl:s,config:n})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function ni(e){return new C(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-2OHXLW85.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 ri(e,t,n=process.cwd()){let r=e.op??`sync`,i=h(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=M({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
594
- `)),Z(e.json,{type:`complete`,op:r}),e.json||process.stderr.write(`✓ ${r} complete\n`)}function ii(e){return new C(`sync`).description(`Commit, pull, and push to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ri({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 ai(e){return new C(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ri({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 oi(e){return new C(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ri({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)}})}function si(e,t){return{server:ci(`server`,e),ui:ci(`ui`,t)}}function ci(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 li(e){return`${ui(e.server)}\n${ui(e.ui)}`}function ui(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 di(e){let t=e.inspect??(t=>et(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=si(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(li(r)),r}function fi(e){return new C(`status`).description(`Show live state of the server + ui lockfiles for this project`).option(`--json`,`Emit structured JSON instead of formatted text`).action(t=>{di({lockDir:a(o(e(),process.cwd())),json:t.json===!0})})}function pi(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 mi(e){let t=e.inspect??(t=>et(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=pi(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 hi(e){return new C(`stop`).description(`Stop the running open-knowledge server and UI (live only)`).action(()=>{mi({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}const gi=1e4,_i=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function vi(e){let t=e.upstreamTimeoutMs??gi,n=xe((n,r)=>{bi(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 yi(e,t,n){bi(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??gi)}function bi(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of _i)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=Se({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of _i)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 xi(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function Si(e){let{existsSync:t}=await import(`node:fs`),{createServer:r}=await import(`node:http`),{resolve:i}=await import(`node:path`),{acquireUiLock:a,readServerLock:o,releaseUiLock:s,updateUiLockPort:c}=await import(`./src-ByMiIIub.mjs`),{default:l}=await import(`sirv`),{resolveContentDir:u,resolveLockDir:d}=await import(`./paths-DRfvViD6.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}):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}yi(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):Ci(t)});return}if(g){g(e,t);return}Ci(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=r(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??n,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 Ci(e){e.writeHead(404),e.end(`Not found`)}function wi(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 Ti(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-ByMiIIub.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 vi({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function Ei(e){return new C(`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-BNvy_pwG.mjs`),{UiLockCollisionError:r}=await import(`./src-ByMiIIub.mjs`),{resolveContentDir:i,resolveLockDir:a}=await import(`./paths-DRfvViD6.mjs`),o=e(),s=t.host,c;try{c=wi(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}try{let e=await Si({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)}};xi(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 Ti({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 C;let $;Q.name(`open-knowledge`).description(`Local-first knowledge base with CRDT collaboration`).version(r).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}=S(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 Di=b(()=>$);Q.addCommand(Di,{isDefault:!0});const Oi=ti(()=>$);Q.addCommand(Oi),Q.addCommand(y());const ki=ni(()=>$);Q.addCommand(ki);const Ai=Ei(()=>$);Q.addCommand(Ai),Q.addCommand(hi(()=>$)),Q.addCommand(rt(()=>$)),Q.addCommand(fi(()=>$)),Q.addCommand($e(()=>$)),Q.addCommand(ft(()=>$)),Q.addCommand(ii(()=>$)),Q.addCommand(oi(()=>$)),Q.addCommand(ai(()=>$)),await Q.parseAsync();export{};
593
+ `}async function Xr(e){try{let t=e.replace(`ws://`,`http://`).replace(`wss://`,`https://`);return(await fetch(`${t}/api/agent-undo-status`,{signal:AbortSignal.timeout(2e3)})).ok}catch(e){return X(`Hocuspocus check failed: ${e instanceof Error?e.message:String(e)}`),!1}}async function Zr(e){let{projectDir:t,serverUrl:n,config:s}=e;X(n?await Xr(n)?`Hocuspocus detected at ${n}`:`Hocuspocus not available at ${n} — using disk-only mode`:`No explicit server URL — will discover lazily from server.lock per call`);let c=new we({name:i,version:r},{instructions:Yr(s)}),l=[],u=!1;async function d(){try{l=(await c.server.listRoots()).roots.map(e=>e.uri).filter(e=>e.startsWith(`file://`)).map(e=>me(e)),X(l.length>0?`roots: ${l.join(`, `)}`:`client advertised no roots — falling back to startup cwd`)}catch(e){X(`listRoots unsupported by client (using startup cwd): ${e instanceof Error?e.message:String(e)}`)}finally{u=!0}}let f=!1;async function p(e){return e||(u||await d(),l.length===0?(f||=(X(`no client roots — falling back to startup cwd: ${t}`),!0),t):(f&&=(X(`client roots now available — using ${l[0]}`),!1),l[0]))}c.server.setNotificationHandler(Ee,async()=>{u=!1,await d()});let m=n?n.replace(`ws://`,`http://`).replace(`wss://`,`https://`):void 0,g=new Map,_=async()=>{if(m)return m;let e=await p(),t=Date.now(),n=g.get(e);if(n&&n.expiresAt>t)return n.url;let r=h(a(o(s,e))),i=r&&r.port>0?`http://localhost:${r.port}`:void 0;return g.set(e,{url:i,expiresAt:t+1e3}),i},v=he(),y=process.env.AGENT_LABEL||void 0,b={current:{connectionId:v,label:y,displayName:y??`Agent`,colorSeed:y??v}};c.server.oninitialized=()=>{let e=c.server.getClientVersion();b.current={connectionId:v,clientInfo:e?{name:e.name,version:e.version}:void 0,label:y,displayName:y??e?.name??`Agent`,colorSeed:y??e?.name??v},X(`Agent identity: ${b.current.displayName} (${v.slice(0,8)})`)},Jr(c,{serverUrl:_,resolveCwd:p,startupCwd:t,config:s,identityRef:b});let x=new Te;await c.connect(x),X(`MCP server running (stdio)`),d().catch(()=>{});let{startKeepalive:S}=await import(`./keepalive-D-FSaNO6.mjs`),C=S({resolveWsUrl:async()=>{let e=await _();if(e)return e.replace(/^http:/,`ws:`).replace(/^https:/,`wss:`)},log:X}),w=()=>{try{C.close()}catch{}process.exit(0)};process.on(`SIGINT`,w),process.on(`SIGTERM`,w)}function Qr(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function $r(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 ei(e){let t=e.readLock??(()=>h(e.lockDir)),n=e.isAlive??m,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e))),i=e.spawn??_e,a=e.readErrorLog??(e=>T(e)?O(e,`utf-8`).trim():``),o=e.openErrorLog??(e=>D(e,`w`)),s=e.closeFd??(e=>w(e)),c=e.timeoutMs??5e3,l=e.pollIntervalMs??100,u=$r({host:e.host,portOverride:e.portOverride,envAutoStart:e.envAutoStart,configAutoStart:e.configAutoStart,readLock:t,isAlive:n});if(u.action===`connect`)return{serverUrl:u.url,message:u.message};if(u.action===`disk-only`)return{serverUrl:void 0,message:u.message};T(e.lockDir)||E(e.lockDir,{recursive:!0});let d=se(e.lockDir,`last-spawn-error.log`),f=o(d),p,g,_=x();try{try{p=i(_.command,[..._.prefixArgs,`start`],{detached:!0,stdio:[`ignore`,`ignore`,f],cwd:e.contentDir}),p.on(`error`,e=>{g=e instanceof Error?e.message:String(e)}),p.unref()}catch(e){g=e instanceof Error?e.message:String(e)}}finally{try{s(f)}catch{}}let v=Date.now()+c;for(;Date.now()<v;){if(g){let e=a(d);throw Error(`OK: spawn failed: ${g}${e?` stderr:\n${e}`:``}`)}await r(l);let e=t();if(e&&e.port>0&&n(e.pid)){let t=`ws://localhost:${e.port}`;return{serverUrl:t,message:`spawned ok start; connected at ${t} (pid ${e.pid})`}}}if(g){let e=a(d);throw Error(`OK: spawn failed: ${g}${e?` stderr:\n${e}`:``}`)}let y=a(d),b=(c/1e3).toFixed(c%1e3==0?0:2),S=p?.pid,C=``;throw typeof S==`number`&&(C=n(S)?` child pid=${S} is still running — raise OK_MCP_SPAWN_TIMEOUT_MS if this is a slow boot.`:` child pid=${S} exited — check last-spawn-error.log.`),Error(`OK: server did not start within ${b}s.${C}${y?` stderr:\n${y}`:``}`)}function ti(e){return new C(`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(n,r),{serverUrl:s,message:c}=await ei({lockDir:a(i),contentDir:i,host:n.server.host,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,configAutoStart:n.mcp.autoStart,timeoutMs:Qr(process.env.OK_MCP_SPAWN_TIMEOUT_MS)});process.stderr.write(`[mcp] ${c}\n`),await Zr({projectDir:r,serverUrl:s,config:n})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function ni(e){return new C(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-DetiVbZd.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 ri(e,t,n=process.cwd()){let r=e.op??`sync`,i=h(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=M({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
594
+ `)),Z(e.json,{type:`complete`,op:r}),e.json||process.stderr.write(`✓ ${r} complete\n`)}function ii(e){return new C(`sync`).description(`Commit, pull, and push to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ri({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 ai(e){return new C(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ri({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 oi(e){return new C(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ri({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)}})}function si(e,t){return{server:ci(`server`,e),ui:ci(`ui`,t)}}function ci(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 li(e){return`${ui(e.server)}\n${ui(e.ui)}`}function ui(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 di(e){let t=e.inspect??(t=>et(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=si(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(li(r)),r}function fi(e){return new C(`status`).description(`Show live state of the server + ui lockfiles for this project`).option(`--json`,`Emit structured JSON instead of formatted text`).action(t=>{di({lockDir:a(o(e(),process.cwd())),json:t.json===!0})})}function pi(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 mi(e){let t=e.inspect??(t=>et(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=pi(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 hi(e){return new C(`stop`).description(`Stop the running open-knowledge server and UI (live only)`).action(()=>{mi({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}const gi=1e4,_i=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function vi(e){let t=e.upstreamTimeoutMs??gi,n=xe((n,r)=>{bi(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 yi(e,t,n){bi(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??gi)}function bi(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of _i)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=Se({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of _i)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 xi(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function Si(e){let{existsSync:t}=await import(`node:fs`),{createServer:r}=await import(`node:http`),{resolve:i}=await import(`node:path`),{acquireUiLock:a,readServerLock:o,releaseUiLock:s,updateUiLockPort:c}=await import(`./src-ByMiIIub.mjs`),{default:l}=await import(`sirv`),{resolveContentDir:u,resolveLockDir:d}=await import(`./paths-CbXnKMOT.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}):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}yi(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):Ci(t)});return}if(g){g(e,t);return}Ci(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=r(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??n,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 Ci(e){e.writeHead(404),e.end(`Not found`)}function wi(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 Ti(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-ByMiIIub.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 vi({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function Ei(e){return new C(`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-BNvy_pwG.mjs`),{UiLockCollisionError:r}=await import(`./src-ByMiIIub.mjs`),{resolveContentDir:i,resolveLockDir:a}=await import(`./paths-CbXnKMOT.mjs`),o=e(),s=t.host,c;try{c=wi(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}try{let e=await Si({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)}};xi(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 Ti({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 C;let $;Q.name(`open-knowledge`).description(`Local-first knowledge base with CRDT collaboration`).version(r).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}=S(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 Di=b(()=>$);Q.addCommand(Di,{isDefault:!0});const Oi=ti(()=>$);Q.addCommand(Oi),Q.addCommand(y());const ki=ni(()=>$);Q.addCommand(ki);const Ai=Ei(()=>$);Q.addCommand(Ai),Q.addCommand(hi(()=>$)),Q.addCommand(rt(()=>$)),Q.addCommand(fi(()=>$)),Q.addCommand($e(()=>$)),Q.addCommand(ft(()=>$)),Q.addCommand(ii(()=>$)),Q.addCommand(oi(()=>$)),Q.addCommand(ai(()=>$)),await Q.parseAsync();export{};
595
595
  //# sourceMappingURL=cli.mjs.map
@@ -0,0 +1,2 @@
1
+ import"./src-Ds19hvLH.mjs";var e=`0.0.0-dev-20260421173508`;const t=`AGENTS.md`,n=`config.yml`,r=`cache`,i=e,a=`open-knowledge`;export{i as a,a as i,r as n,n as r,t};
2
+ //# sourceMappingURL=constants-kK8FA_so.mjs.map
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{n as e,t}from"./loader-DqrtMiNp.mjs";import"./src-DvkXxOes.mjs";export{e as ConfigSchema,t as loadConfig};
1
+ import{n as e,t}from"./loader-B_agr6SC.mjs";import"./src-CQXKf0uA.mjs";export{e as ConfigSchema,t as loadConfig};
@@ -0,0 +1 @@
1
+ import{a as e,i as t,n,r,t as i}from"./init-CDVXoJkt.mjs";export{i as detectInstalledEditors,n as formatInitResult,r as initCommand,t as parseEditorFlag,e as runInit};
@@ -1,5 +1,5 @@
1
- import{E as e}from"./src-Ds19hvLH.mjs";import"./constants-Dx_MrCyB.mjs";import{o as t,s as n}from"./init-8JV3QQNU.mjs";import{t as r}from"./preview-DsPtfetJ.mjs";import{o as i}from"./colors-eCHTjaBL.mjs";import{t as a}from"./is-object-DVVYT5oa.mjs";import{Command as o}from"commander";import{existsSync as s,mkdirSync as c,readFileSync as l,realpathSync as u,writeFileSync as d}from"node:fs";import{homedir as f}from"node:os";import{basename as p,dirname as m,isAbsolute as h,join as g,relative as _,resolve as v}from"node:path";import{parse as y,stringify as b}from"smol-toml";const x=`open-knowledge`,S=`open-knowledge`,C=1e3;function w(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``);return t===``?`project`:t}function T(e){if(Array.isArray(e)){for(let t=0;t<e.length-1;t++)if(e[t]===`--cwd`){let n=e[t+1];return typeof n==`string`?n:void 0}}}function E(e){try{return u(e)}catch(t){if(t instanceof Error&&`code`in t&&t.code===`ENOENT`)return e;throw t}}function D(e){return a(e)?T(e.args)===void 0:!1}function O(e,t,n={}){let r=n.detectLegacy===!0,i=E(t);for(let[t,n]of Object.entries(e)){if(!t.startsWith(x)||!a(n))continue;let e=T(n.args);if(e!==void 0&&E(e)===i)return{key:t,existingEntry:n}}let o=`${x}-${w(p(i))}`;if(r){let t=e[S];if(t!==void 0&&D(t)){let n=k(e,o);return{key:n.key,existingEntry:t,migratedFromKey:S,...n.disambiguatedFrom===void 0?{}:{disambiguatedFrom:n.disambiguatedFrom}}}}if(e[o]===void 0)return{key:o,existingEntry:void 0};let s=k(e,o);return{key:s.key,existingEntry:void 0,...s.disambiguatedFrom===void 0?{}:{disambiguatedFrom:s.disambiguatedFrom}}}function k(e,t){if(e[t]===void 0)return{key:t};for(let n=2;n<=C;n++){let r=`${t}-${n}`;if(e[r]===void 0)return{key:r,disambiguatedFrom:t}}throw Error(`Unable to pick a unique server key: ${C} suffixes of ${t} are all taken.`)}const A=[`claude`,`cursor`,`vscode`,`codex`,`windsurf`,`claude-desktop`],j=[`@inkeep/open-knowledge`,`mcp`],M={claude:{id:`claude`,label:`Claude Code`,configPath:e=>g(e,`.mcp.json`),format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:j}),scope:`project`,instructionsPath:e=>g(e,`CLAUDE.md`)},cursor:{id:`cursor`,label:`Cursor`,configPath:e=>g(e,`.cursor`,`mcp.json`),format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:j}),scope:`project`},vscode:{id:`vscode`,label:`VS Code`,configPath:e=>g(e,`.vscode`,`mcp.json`),format:`json`,topLevelKey:`servers`,buildEntry:e=>({type:`stdio`,command:`npx`,args:j}),scope:`project`},codex:{id:`codex`,label:`Codex`,configPath:e=>g(e,`.codex`,`config.toml`),format:`toml`,topLevelKey:`mcp_servers`,buildEntry:e=>({command:`npx`,args:j}),scope:`project`},windsurf:{id:`windsurf`,label:`Windsurf`,configPath:(e,t)=>g(t??f(),`.codeium`,`windsurf`,`mcp_config.json`),format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:[...j,`--cwd`,e]}),resolveServerKey:(e,t)=>O(e,t,{detectLegacy:!0}),scope:`global`},"claude-desktop":{id:`claude-desktop`,label:`Claude Desktop`,configPath:(e,t)=>{let n=process.platform;if(n===`darwin`)return g(t??f(),`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`);if(n===`win32`)return g(process.env.APPDATA??g(t??f(),`AppData`,`Roaming`),`Claude`,`claude_desktop_config.json`);throw Error(`Claude Desktop is not available on ${n}. Supported: macOS, Windows.`)},format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:[...j,`--cwd`,e]}),resolveServerKey:(e,t)=>O(e,t,{detectLegacy:!1}),scope:`global`}};function N(e){let t=e.filter(e=>!(e in M));if(t.length>0)throw Error(`Unknown editor(s): ${t.join(`, `)}. Valid options: ${A.join(`, `)}`);return e.map(e=>M[e])}function P(e){if(!s(e))return{};let t=l(e,`utf-8`).trim();if(t===``)return{};try{let n=JSON.parse(t);if(a(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 F(e){if(!s(e))return{};let t=l(e,`utf-8`).trim();if(t===``)return{};try{let n=y(t);if(a(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 I(e,t){c(m(e),{recursive:!0}),d(e,`${JSON.stringify(t,null,2)}\n`,`utf-8`)}function L(e,t){c(m(e),{recursive:!0});let n=b(t);d(e,n.endsWith(`
1
+ import{E as e}from"./src-Ds19hvLH.mjs";import"./constants-kK8FA_so.mjs";import{o as t,s as n}from"./init-Djmfs2Ls.mjs";import{t as r}from"./preview-9I7U91l4.mjs";import{o as i}from"./colors-eCHTjaBL.mjs";import{t as a}from"./is-object-DVVYT5oa.mjs";import{Command as o}from"commander";import{existsSync as s,mkdirSync as c,readFileSync as l,realpathSync as u,writeFileSync as d}from"node:fs";import{homedir as f}from"node:os";import{basename as p,dirname as m,isAbsolute as h,join as g,relative as _,resolve as v}from"node:path";import{parse as y,stringify as b}from"smol-toml";const x=`open-knowledge`,S=`open-knowledge`,C=1e3;function w(e){let t=e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``);return t===``?`project`:t}function T(e){if(Array.isArray(e)){for(let t=0;t<e.length-1;t++)if(e[t]===`--cwd`){let n=e[t+1];return typeof n==`string`?n:void 0}}}function E(e){try{return u(e)}catch(t){if(t instanceof Error&&`code`in t&&t.code===`ENOENT`)return e;throw t}}function D(e){return a(e)?T(e.args)===void 0:!1}function O(e,t,n={}){let r=n.detectLegacy===!0,i=E(t);for(let[t,n]of Object.entries(e)){if(!t.startsWith(x)||!a(n))continue;let e=T(n.args);if(e!==void 0&&E(e)===i)return{key:t,existingEntry:n}}let o=`${x}-${w(p(i))}`;if(r){let t=e[S];if(t!==void 0&&D(t)){let n=k(e,o);return{key:n.key,existingEntry:t,migratedFromKey:S,...n.disambiguatedFrom===void 0?{}:{disambiguatedFrom:n.disambiguatedFrom}}}}if(e[o]===void 0)return{key:o,existingEntry:void 0};let s=k(e,o);return{key:s.key,existingEntry:void 0,...s.disambiguatedFrom===void 0?{}:{disambiguatedFrom:s.disambiguatedFrom}}}function k(e,t){if(e[t]===void 0)return{key:t};for(let n=2;n<=C;n++){let r=`${t}-${n}`;if(e[r]===void 0)return{key:r,disambiguatedFrom:t}}throw Error(`Unable to pick a unique server key: ${C} suffixes of ${t} are all taken.`)}const A=[`claude`,`cursor`,`vscode`,`codex`,`windsurf`,`claude-desktop`],j=[`@inkeep/open-knowledge`,`mcp`],M={claude:{id:`claude`,label:`Claude Code`,configPath:e=>g(e,`.mcp.json`),format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:j}),scope:`project`,instructionsPath:e=>g(e,`CLAUDE.md`)},cursor:{id:`cursor`,label:`Cursor`,configPath:e=>g(e,`.cursor`,`mcp.json`),format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:j}),scope:`project`},vscode:{id:`vscode`,label:`VS Code`,configPath:e=>g(e,`.vscode`,`mcp.json`),format:`json`,topLevelKey:`servers`,buildEntry:e=>({type:`stdio`,command:`npx`,args:j}),scope:`project`},codex:{id:`codex`,label:`Codex`,configPath:e=>g(e,`.codex`,`config.toml`),format:`toml`,topLevelKey:`mcp_servers`,buildEntry:e=>({command:`npx`,args:j}),scope:`project`},windsurf:{id:`windsurf`,label:`Windsurf`,configPath:(e,t)=>g(t??f(),`.codeium`,`windsurf`,`mcp_config.json`),format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:[...j,`--cwd`,e]}),resolveServerKey:(e,t)=>O(e,t,{detectLegacy:!0}),scope:`global`},"claude-desktop":{id:`claude-desktop`,label:`Claude Desktop`,configPath:(e,t)=>{let n=process.platform;if(n===`darwin`)return g(t??f(),`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`);if(n===`win32`)return g(process.env.APPDATA??g(t??f(),`AppData`,`Roaming`),`Claude`,`claude_desktop_config.json`);throw Error(`Claude Desktop is not available on ${n}. Supported: macOS, Windows.`)},format:`json`,topLevelKey:`mcpServers`,buildEntry:e=>({command:`npx`,args:[...j,`--cwd`,e]}),resolveServerKey:(e,t)=>O(e,t,{detectLegacy:!1}),scope:`global`}};function N(e){let t=e.filter(e=>!(e in M));if(t.length>0)throw Error(`Unknown editor(s): ${t.join(`, `)}. Valid options: ${A.join(`, `)}`);return e.map(e=>M[e])}function P(e){if(!s(e))return{};let t=l(e,`utf-8`).trim();if(t===``)return{};try{let n=JSON.parse(t);if(a(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 F(e){if(!s(e))return{};let t=l(e,`utf-8`).trim();if(t===``)return{};try{let n=y(t);if(a(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 I(e,t){c(m(e),{recursive:!0}),d(e,`${JSON.stringify(t,null,2)}\n`,`utf-8`)}function L(e,t){c(m(e),{recursive:!0});let n=b(t);d(e,n.endsWith(`
2
2
  `)?n:`${n}\n`,`utf-8`)}const R=`0.0.1`,z=`open-knowledge-ui`;function B(e,t){let n=[];e.runtimeExecutable!==t.runtimeExecutable&&n.push(`runtimeExecutable`);let r=e.runtimeArgs;return Array.isArray(r)&&r.length===t.runtimeArgs.length&&r.every((e,n)=>e===t.runtimeArgs[n])||n.push(`runtimeArgs`),e.port!==t.port&&n.push(`port`),n}function V(e,t){let n=g(e,`.claude`,`launch.json`),r={name:z,runtimeExecutable:`npx`,runtimeArgs:[`@inkeep/open-knowledge`,`ui`],port:3e3};try{if(!s(n))return c(m(n),{recursive:!0}),d(n,`${JSON.stringify({version:R,configurations:[r]},null,2)}\n`,`utf-8`),{action:`created`,configPath:n};let e=l(n,`utf-8`).trim(),i=e?JSON.parse(e):{};if(!a(i))return{action:`failed`,configPath:n,error:`launch.json root is not an object`};let o=Array.isArray(i.configurations)?i.configurations:[],u=o.findIndex(e=>a(e)&&e.name===z);if(u>=0&&!t){let e=o[u],t=B(e,r);return t.length>0?{action:`skipped-stale`,configPath:n,staleFields:t}:{action:`skipped-existing`,configPath:n}}u>=0?o[u]=r:o.push(r);let f={...i,version:i.version??R,configurations:o};return d(n,`${JSON.stringify(f,null,2)}\n`,`utf-8`),{action:`merged`,configPath:n}}catch(e){return{action:`failed`,configPath:n,error:e instanceof Error?e.message:String(e)}}}function H(e,t,n,r){let i;try{i=e.configPath(t,r)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:``,error:t instanceof Error?t.message:String(t)}}let a;try{a=e.format===`toml`?F(i):P(i)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:i,error:t instanceof Error?t.message:String(t)}}let o=a[e.topLevelKey]??{},s;try{s=e.resolveServerKey?.(o,t)??{key:`open-knowledge`,existingEntry:o[`open-knowledge`]}}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:i,error:t instanceof Error?t.message:String(t)}}let{key:c,existingEntry:l,disambiguatedFrom:u,migratedFromKey:d}=s;if(l!==void 0&&!n&&d===void 0)return{editorId:e.id,label:e.label,action:`skipped-existing`,configPath:i,serverKey:c};let f={...o};d!==void 0&&d!==c&&delete f[d],f[c]=e.buildEntry(t);let p={...a,[e.topLevelKey]:f};try{e.format===`toml`?L(i,p):I(i,p)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:i,error:t instanceof Error?t.message:String(t)}}let m=d===void 0&&l===void 0?`written`:`overwritten`;return{editorId:e.id,label:e.label,action:m,configPath:i,serverKey:c,...u===void 0?{}:{disambiguatedFrom:u},...d===void 0?{}:{migratedFromKey:d}}}function U(e={}){let r=v(e.cwd??process.cwd()),i;try{i=t(r)}catch(e){return{contentCreated:[],contentSkipped:[],editors:[],rootInstructions:[],mcpAction:`failed`,mcpPath:g(r,`.mcp.json`),mcpError:`Content scaffolding failed: ${e instanceof Error?e.message:String(e)}`}}let a=e.editors??[`claude`],o=N(a),s=[];for(let t of o){if(e.mcp===!1){let n=``;try{n=t.configPath(r,e.home)}catch{}s.push({editorId:t.id,label:t.label,action:`skipped-flag`,configPath:n});continue}s.push(H(t,r,e.force??!1,e.home))}let c=a.includes(`claude`)&&e.mcp!==!1?V(r,e.force??!1):void 0,l=o.map(e=>e.instructionsPath?.(r)).filter(e=>e!==void 0).map(e=>h(e)?_(r,e):e),u=e.rootInstructions===!1?[]:n(r,e.force??!1,l),d=s.find(e=>e.editorId===`claude`)??s[0]??{action:`skipped-flag`,configPath:g(r,`.mcp.json`)};return{contentCreated:i.created,contentSkipped:i.skipped,editors:s,rootInstructions:u,launchJson:c,mcpAction:d.action,mcpPath:d.configPath,mcpError:`error`in d?d.error:void 0}}function W(e,t){try{let n=l(e.configPath,`utf-8`).trim();if(n===``)return;let r=JSON.parse(n);if(!a(r))return;let i=r.mcpServers;if(!a(i))return;let o=i[t];if(!a(o))return;let s=o.args;if(!Array.isArray(s))return;let c=s.indexOf(`--cwd`);if(c<0||c===s.length-1)return;let u=s[c+1];return typeof u==`string`?u:void 0}catch{return}}function G(t,n){let a=[],o=g(n,e);if(t.contentCreated.length>0?(a.push(`Content scaffolded at ${o}/`),a.push(` Created: ${t.contentCreated.join(`, `)}`)):a.push(`Content already present at ${o}/`),t.contentSkipped.length>0&&a.push(` Skipped (already exist): ${t.contentSkipped.join(`, `)}`),a.push(``),t.editors.length===0)t.mcpError&&a.push(`Warning: ${t.mcpError}`);else{let e=t.editors.some(e=>e.action===`written`||e.action===`overwritten`),o=t.editors.some(e=>e.action===`failed`);if(t.editors.every(e=>e.action===`skipped-flag`))a.push(`MCP config not written — use without --no-mcp to configure editors`);else{a.push(`MCP server configuration:`);for(let e of t.editors){let t=e.configPath.startsWith(n)?_(n,e.configPath):e.configPath.replace(/^\/Users\/[^/]+/,`~`),r=` `.repeat(Math.max(1,14-e.label.length)),i=e.editorId===`claude-desktop`&&(e.action===`written`||e.action===`overwritten`)?` — quit and relaunch Claude Desktop to activate`:``;switch(e.action){case`written`:if(a.push(` ${e.label}${r}${t} registered${i}`),e.disambiguatedFrom!==void 0){let t=W(e,e.disambiguatedFrom),n=t?`(${e.disambiguatedFrom} is already registered for ${t})`:`(${e.disambiguatedFrom} is already registered for a different project)`;a.push(` ${` `.repeat(e.label.length)}${r}${n}`)}break;case`overwritten`:e.migratedFromKey===void 0?a.push(` ${e.label}${r}${t} overwritten (--force)${i}`):a.push(` ${e.label}${r}${t} overwritten — migrated legacy ${e.migratedFromKey} → ${e.serverKey??``}${i}`);break;case`skipped-existing`:{let n=e.serverKey,i=n!==void 0&&n!==`open-knowledge`?` (${n})`:``;a.push(` ${e.label}${r}${t} already configured${i}`);break}case`failed`:a.push(` ${e.label}${r}${t} FAILED: ${e.error}`);break;case`skipped-flag`:break}}}if(o&&(a.push(``),a.push(`For failed editors, add the MCP server entry manually. See:`),a.push(` https://github.com/inkeep/open-knowledge#mcp-setup`)),t.launchJson){let e=t.launchJson,r=e.configPath.startsWith(n)?_(n,e.configPath):e.configPath;switch(e.action){case`created`:a.push(` launch.json ${r} created (preview_start("${z}") ready)`);break;case`merged`:a.push(` launch.json ${r} merged open-knowledge entry`);break;case`skipped-existing`:a.push(` launch.json ${r} already has open-knowledge entry`);break;case`skipped-stale`:a.push(` launch.json ${r} ${i(`⚠ existing open-knowledge entry is out of date`)}`),e.staleFields&&e.staleFields.length>0&&a.push(` ${i(`${e.staleFields.join(`, `)} differ from current defaults`)}`),a.push(` ${i(`re-run with --force to update`)}`);break;case`failed`:a.push(` launch.json ${r} FAILED: ${e.error}`);break}}if(t.rootInstructions.length>0){let e=t.rootInstructions.filter(e=>e.action!==`skipped-symlink`);if(e.length>0){a.push(``),a.push(`Root instructions:`);for(let t of e){let e=t.path.startsWith(n)?_(n,t.path):t.path,r=` `.repeat(Math.max(1,14-t.file.length));switch(t.action){case`created`:a.push(` ${t.file}${r}${e} created`);break;case`appended`:a.push(` ${t.file}${r}${e} appended Open Knowledge section`);break;case`replaced`:a.push(` ${t.file}${r}${e} replaced Open Knowledge section (--force)`);break;case`skipped-existing`:a.push(` ${t.file}${r}${e} already has Open Knowledge section`);break}}}}if(t.preview?(a.push(``),a.push(r(t.preview,n))):t.previewWarning&&(a.push(``),a.push(`Content preview unavailable: ${t.previewWarning}`)),e){let e=t.editors.filter(e=>e.action===`written`||e.action===`overwritten`).map(e=>e.label);a.push(``),a.push(`Next steps:`),a.push(` 1. Open your editor (${e.join(` / `)})`),a.push(` 2. Approve the MCP server when prompted`),a.push(` 3. The knowledge base is ready — use the three workflow tools:`),a.push(` - mcp__open-knowledge__init-content — bootstrap articles from the codebase`),a.push(` - mcp__open-knowledge__ingest — capture an external source`),a.push(` - mcp__open-knowledge__research — gather sources and write findings`)}}return a.join(`
3
3
  `)}function K(e){switch(e){case`claude_desktop`:return`claude-desktop`;default:return e}}function q(e){if(e===`all`)return[...A];let t=e.split(`,`).map(e=>e.trim()).map(K);return N(t),t}function J(e,t){let n=[];for(let r of A){let i=M[r],a;try{a=i.configPath(e,t)}catch{continue}s(m(a))&&n.push(r)}return n}function Y(){return new o(`init`).description(`Scaffold ${e}/ 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 ${e}/ directory but do not touch MCP config`).option(`--force`,`Overwrite existing open-knowledge MCP entries (default: skip)`).option(`--editor <editors>`,`Target editor(s): ${A.join(`, `)}, all (comma-separated) — default: all detected editors (non-TTY) / preselects detected editors (TTY)`).action(async e=>{let t=process.cwd(),n;if(e.editor)try{n=q(e.editor)}catch(e){process.stderr.write(`${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1;return}else if(e.mcp!==!1&&process.stdin.isTTY){let{multiselect:e,isCancel:r}=await import(`@clack/prompts`),i=new Set(J(t));i.size===0&&process.stdout.write(`No MCP-capable editors detected — select manually, or cancel and use --editor <all|${A.join(`|`)}>.\n`);let a=await e({message:`Which tools do you use? (space to toggle, enter to confirm)`,options:A.flatMap(e=>{let n=M[e],r;try{r=n.scope===`global`?n.configPath(t).replace(/^\/Users\/[^/]+/,`~`):_(t,n.configPath(t))}catch{return[]}return[{value:e,label:n.label,hint:r,initialValue:i.has(e)}]}),required:!0});if(r(a)){process.stdout.write(`Init cancelled.
4
- `);return}n=a}else if(n=J(t),n.length===0){process.stderr.write(`No MCP-capable editors detected. Use --editor <all|${A.join(`|`)}> to force.\n`),process.exitCode=1;return}let r=U({cwd:t,mcp:e.mcp,force:e.force,editors:n});try{let{previewContent:e}=await import(`./preview-2OHXLW85.mjs`),{loadConfig:n}=await import(`./loader-oJkH9tG6.mjs`),{resolveContentDir:i}=await import(`./paths-DRfvViD6.mjs`),{config:a}=n(t);r.preview=e({projectDir:t,contentDir:i(a,t),include:a.content.include,exclude:a.content.exclude})}catch(e){r.previewWarning=e instanceof Error?e.message:String(e)}process.stdout.write(`${G(r,t)}\n`),(r.editors.some(e=>e.action===`failed`)||r.mcpAction===`failed`)&&(process.exitCode=1)})}export{U as a,q as i,G as n,Y as r,J as t};
5
- //# sourceMappingURL=init-UYi5s8Q6.mjs.map
4
+ `);return}n=a}else if(n=J(t),n.length===0){process.stderr.write(`No MCP-capable editors detected. Use --editor <all|${A.join(`|`)}> to force.\n`),process.exitCode=1;return}let r=U({cwd:t,mcp:e.mcp,force:e.force,editors:n});try{let{previewContent:e}=await import(`./preview-DetiVbZd.mjs`),{loadConfig:n}=await import(`./loader-G8JzZrJO.mjs`),{resolveContentDir:i}=await import(`./paths-CbXnKMOT.mjs`),{config:a}=n(t);r.preview=e({projectDir:t,contentDir:i(a,t),include:a.content.include,exclude:a.content.exclude})}catch(e){r.previewWarning=e instanceof Error?e.message:String(e)}process.stdout.write(`${G(r,t)}\n`),(r.editors.some(e=>e.action===`failed`)||r.mcpAction===`failed`)&&(process.exitCode=1)})}export{U as a,q as i,G as n,Y as r,J as t};
5
+ //# sourceMappingURL=init-CDVXoJkt.mjs.map
@@ -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-Djmfs2Ls.mjs";export{o as CLAUDE_MD_SECTION,n as OK_MARKER_BEGIN,i as OK_MARKER_END,t as PREVIEW_GUIDANCE,e as ensureOkGitignoredAtRoot,r as initContent,a as upsertRootInstructions};
@@ -1,4 +1,4 @@
1
- import{E as e}from"./src-Ds19hvLH.mjs";import{n as t,r as n,t as r}from"./constants-Dx_MrCyB.mjs";import{existsSync as i,mkdirSync as a,readFileSync as o,realpathSync as s,writeFileSync as c}from"node:fs";import{join as l,resolve as u}from"node:path";const d=`<!-- open-knowledge:begin -->`,f=`<!-- open-knowledge:end -->`,p=/<!-- open-knowledge:begin -->[\s\S]*?<!-- open-knowledge:end -->/,m=`# ${e}/ — Open Knowledge config
1
+ import{E as e}from"./src-Ds19hvLH.mjs";import{n as t,r as n,t as r}from"./constants-kK8FA_so.mjs";import{existsSync as i,mkdirSync as a,readFileSync as o,realpathSync as s,writeFileSync as c}from"node:fs";import{join as l,resolve as u}from"node:path";const d=`<!-- open-knowledge:begin -->`,f=`<!-- open-knowledge:end -->`,p=/<!-- open-knowledge:begin -->[\s\S]*?<!-- open-knowledge:end -->/,m=`# ${e}/ — Open Knowledge config
2
2
 
3
3
  This directory holds Open Knowledge's configuration for this project. It's **not** where content lives — content lives wherever \`content.dir\` + \`content.include\` in \`config.yml\` point. The default is the repo root with \`**/*.md\`, so any markdown file in the project is fair game. Inspect \`config.yml\` for the actual setting.
4
4
 
@@ -227,4 +227,4 @@ ${f}`;function v(e,t,n){let a=[r,...n??[]],u=new Set,d=[];for(let n of a){let r=
227
227
 
228
228
  `)?`
229
229
  `:``}${r}`,`utf-8`),`appended`)}const x=[{name:r,content:m},{name:`.gitignore`,content:`${t}/\nserver.lock\nui.lock\nsync-state.json\n`},{name:n,content:h}];function S(n){let r=u(n,e),i=[],o=[];a(r,{recursive:!0}),a(l(r,t),{recursive:!0});for(let e of x)y(l(r,e.name),e.content)?i.push(e.name):o.push(e.name);return{created:i,skipped:o}}export{b as a,g as i,d as n,S as o,f as r,v as s,_ as t};
230
- //# sourceMappingURL=init-8JV3QQNU.mjs.map
230
+ //# sourceMappingURL=init-Djmfs2Ls.mjs.map
@@ -1,3 +1,3 @@
1
- import{E as e}from"./src-Ds19hvLH.mjs";import{r as t}from"./constants-Dx_MrCyB.mjs";import{t as n}from"./is-object-DVVYT5oa.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{z as c}from"zod";const l=c.object({title:c.string().optional(),description:c.string().optional(),tags:c.array(c.string()).optional()}).strict(),u=c.object({match:c.string().min(1,"`match` must be a non-empty glob pattern (e.g. 'specs/**' or 'reports/*/**')"),frontmatter:l}).strict(),d=c.object({content:c.object({dir:c.string().default(`.`),include:c.array(c.string()).min(1).default([`**/*.md`,`**/*.mdx`]),exclude:c.array(c.string()).default([])}).default({dir:`.`,include:[`**/*.md`,`**/*.mdx`],exclude:[]}),github:c.object({oauthAppClientId:c.string().default(`Ov23liqlSd0V1MwR6rhI`)}).default({oauthAppClientId:`Ov23liqlSd0V1MwR6rhI`}),sync:c.object({enabled:c.boolean().optional(),pushIntervalSeconds:c.number().int().min(1).default(60),pullIntervalSeconds:c.number().int().min(1).default(30),autoCommit:c.boolean().default(!0),autoPush:c.boolean().default(!0),autoPull:c.boolean().default(!0),commitMessage:c.string().default(`auto`)}).default({pushIntervalSeconds:60,pullIntervalSeconds:30,autoCommit:!0,autoPush:!0,autoPull:!0,commitMessage:`auto`}),server:c.object({port:c.number().int().min(0).max(65535).default(0),host:c.string().regex(/^[\w.\-:]+$/,`Invalid hostname`).default(`localhost`),openOnAgentEdit:c.boolean().default(!1)}).default({port:0,host:`localhost`,openOnAgentEdit:!1}),persistence:c.object({debounceMs:c.number().int().min(0).default(2e3),maxDebounceMs:c.number().int().min(0).default(1e4)}).default({debounceMs:2e3,maxDebounceMs:1e4}),preview:c.object({baseUrl:c.url().optional()}).default({}),folders:c.array(u).default([]),mcp:c.object({autoStart:c.boolean().default(!0),tools:c.object({read_document:c.object({historyDepth:c.number().int().min(0).default(5)}).default({historyDepth:5}),search:c.object({maxResults:c.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 f(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]=f(a,o):o!==void 0&&(r[i]=o)}return r}function p(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 m(n){let r=n??process.cwd(),i=[],s=o(a(),e,t),c={},l=p(s);l&&(c=f(c,l),i.push(s));let u=o(r,e,t),m=p(u);m&&(c=f(c,m),i.push(u));let h=d.safeParse(c);if(!h.success){let e=h.error.issues.map(e=>` ${e.path.join(`.`)}: ${e.message}`);throw Error(`Invalid configuration:\n${e.join(`
1
+ import{E as e}from"./src-Ds19hvLH.mjs";import{r as t}from"./constants-kK8FA_so.mjs";import{t as n}from"./is-object-DVVYT5oa.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{z as c}from"zod";const l=c.object({title:c.string().optional(),description:c.string().optional(),tags:c.array(c.string()).optional()}).strict(),u=c.object({match:c.string().min(1,"`match` must be a non-empty glob pattern (e.g. 'specs/**' or 'reports/*/**')"),frontmatter:l}).strict(),d=c.object({content:c.object({dir:c.string().default(`.`),include:c.array(c.string()).min(1).default([`**/*.md`,`**/*.mdx`]),exclude:c.array(c.string()).default([])}).default({dir:`.`,include:[`**/*.md`,`**/*.mdx`],exclude:[]}),github:c.object({oauthAppClientId:c.string().default(`Ov23liqlSd0V1MwR6rhI`)}).default({oauthAppClientId:`Ov23liqlSd0V1MwR6rhI`}),sync:c.object({enabled:c.boolean().optional(),pushIntervalSeconds:c.number().int().min(1).default(60),pullIntervalSeconds:c.number().int().min(1).default(30),autoCommit:c.boolean().default(!0),autoPush:c.boolean().default(!0),autoPull:c.boolean().default(!0),commitMessage:c.string().default(`auto`)}).default({pushIntervalSeconds:60,pullIntervalSeconds:30,autoCommit:!0,autoPush:!0,autoPull:!0,commitMessage:`auto`}),server:c.object({port:c.number().int().min(0).max(65535).default(0),host:c.string().regex(/^[\w.\-:]+$/,`Invalid hostname`).default(`localhost`),openOnAgentEdit:c.boolean().default(!1)}).default({port:0,host:`localhost`,openOnAgentEdit:!1}),persistence:c.object({debounceMs:c.number().int().min(0).default(2e3),maxDebounceMs:c.number().int().min(0).default(1e4)}).default({debounceMs:2e3,maxDebounceMs:1e4}),preview:c.object({baseUrl:c.url().optional()}).default({}),folders:c.array(u).default([]),mcp:c.object({autoStart:c.boolean().default(!0),tools:c.object({read_document:c.object({historyDepth:c.number().int().min(0).default(5)}).default({historyDepth:5}),search:c.object({maxResults:c.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 f(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]=f(a,o):o!==void 0&&(r[i]=o)}return r}function p(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 m(n){let r=n??process.cwd(),i=[],s=o(a(),e,t),c={},l=p(s);l&&(c=f(c,l),i.push(s));let u=o(r,e,t),m=p(u);m&&(c=f(c,m),i.push(u));let h=d.safeParse(c);if(!h.success){let e=h.error.issues.map(e=>` ${e.path.join(`.`)}: ${e.message}`);throw Error(`Invalid configuration:\n${e.join(`
2
2
  `)}`)}return{config:h.data,sources:i}}export{d as n,m as t};
3
- //# sourceMappingURL=loader-DqrtMiNp.mjs.map
3
+ //# sourceMappingURL=loader-B_agr6SC.mjs.map
@@ -0,0 +1 @@
1
+ import{t as e}from"./loader-B_agr6SC.mjs";export{e as loadConfig};
@@ -0,0 +1,2 @@
1
+ import{E as e}from"./src-Ds19hvLH.mjs";import"./constants-kK8FA_so.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-COFg_gne.mjs.map
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./paths-COFg_gne.mjs";export{t as resolveContentDir,e as resolveLockDir};
@@ -1,3 +1,3 @@
1
- import{E as e}from"./src-Ds19hvLH.mjs";import"./constants-Dx_MrCyB.mjs";import{l as t}from"./src-9qc50QcN.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{E as e}from"./src-Ds19hvLH.mjs";import"./constants-kK8FA_so.mjs";import{l as t}from"./src-9qc50QcN.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-DsPtfetJ.mjs.map
3
+ //# sourceMappingURL=preview-9I7U91l4.mjs.map
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./preview-9I7U91l4.mjs";export{t as formatPreviewBlock,e as previewContent};