@inkeep/open-knowledge 0.0.0-dev-20260423022549 → 0.0.0-dev-20260423025054
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 +4 -4
- package/dist/constants-CctQOxTv.mjs +2 -0
- package/dist/index.mjs +1 -1
- package/dist/{init-CovbSAcF.mjs → init-B3ycweHs.mjs} +3 -3
- package/dist/{init-DkOc_rH4.mjs → init-BBEtdFbt.mjs} +1 -1
- package/dist/{init-CN7wn7Mw.mjs → init-CXgpPYnX.mjs} +2 -2
- package/dist/init-CfiW8yzl.mjs +1 -0
- package/dist/loader-CRv6YUEt.mjs +1 -0
- package/dist/{loader-Dc--x7jS.mjs → loader-DC05jP_i.mjs} +2 -2
- package/dist/paths-DKYbHoVz.mjs +1 -0
- package/dist/{paths-CWvcLdGz.mjs → paths-DjCE6HsL.mjs} +2 -2
- package/dist/preview-C9MefMSi.mjs +1 -0
- package/dist/{preview-CLEFq2Qk.mjs → preview-D89OyWfK.mjs} +2 -2
- package/dist/public/assets/{index-CcvrsPse.js → index-BzYIvdsQ.js} +7 -7
- package/dist/public/index.html +14 -1
- package/dist/src-C9R5iE4n.mjs +1 -0
- package/dist/start-AX9SNvdk.mjs +1 -0
- package/dist/{start-Pm1FWiVR.mjs → start-B5aAHuCo.mjs} +2 -2
- package/package.json +1 -1
- package/dist/constants-CssIsAar.mjs +0 -2
- package/dist/init-BusLtanu.mjs +0 -1
- package/dist/loader-BBlbnLWs.mjs +0 -1
- package/dist/paths-CMZmck8P.mjs +0 -1
- package/dist/preview-Bqx92atL.mjs +0 -1
- package/dist/src-CghXssk6.mjs +0 -1
- package/dist/start-D3hu5Ksg.mjs +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as e,i as t}from"./constants-
|
|
2
|
+
import{a as e,i as t}from"./constants-CctQOxTv.mjs";import{O as n,c as r,k as i}from"./src-CQw-HNNM.mjs";import{n as a,t as o}from"./paths-DjCE6HsL.mjs";import{ct as s,lt as c,ot as l,p as u,st as d,tt as f}from"./src-y0OBZgkE.mjs";import{c as p,f as m,r as h}from"./server-lock-B4frNnOB.mjs";import{i as g}from"./init-CXgpPYnX.mjs";import{t as _}from"./is-object-DaHwJLOe.mjs";import{r as v}from"./init-B3ycweHs.mjs";import{i as y,n as ee,t as b}from"./loader-DC05jP_i.mjs";import{o as x,s as S}from"./start-B5aAHuCo.mjs";import"./src-C9R5iE4n.mjs";import{Command as C}from"commander";import{appendFileSync as w,closeSync as T,existsSync as E,mkdirSync as D,openSync as te,readFileSync as O,readdirSync as ne,realpathSync as re,statSync as ie,unlinkSync as ae,writeFileSync as oe}from"node:fs";import{homedir as se,hostname as ce}from"node:os";import{basename as le,dirname as ue,isAbsolute as de,join as fe,relative as pe,resolve as k}from"node:path";import{parse as me,stringify as he}from"yaml";import{createOAuthDeviceAuth as ge}from"@octokit/auth-oauth-device";import _e from"@inquirer/password";import{Octokit as ve}from"@octokit/rest";import{fileURLToPath as ye}from"node:url";import{randomUUID as be}from"node:crypto";import{execFileSync as xe,spawn as Se}from"node:child_process";import A from"simple-git";import{readFile as Ce,readdir as we,stat as Te}from"node:fs/promises";import{createServer as Ee,request as De}from"node:http";import Oe from"picomatch";import{z as j}from"zod";import{McpServer as ke}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Ae}from"@modelcontextprotocol/sdk/server/stdio.js";import{RootsListChangedNotificationSchema as je}from"@modelcontextprotocol/sdk/types.js";import{AsyncLocalStorage as Me}from"node:async_hooks";import{Bash as Ne,ReadWriteFs as Pe}from"just-bash";import Fe from"shell-quote";const Ie=`open-knowledge`;var Le=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(Ie,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(Ie,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(Ie,e).deletePassword()}catch{}}},Re=class{backend=`file`;authFile;constructor(e){this.authFile=e??fe(se(),`.open-knowledge`,`auth.yml`)}read(){if(!E(this.authFile))return{};try{return me(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=ue(this.authFile);E(t)||D(t,{recursive:!0,mode:448}),oe(this.authFile,he(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 ze(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(Ie,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
|
|
3
3
|
`),new Le}catch{return process.stderr.write(`[auth] token storage: file (~/.open-knowledge/auth.yml)
|
|
4
4
|
`),new Re(e)}}async function Be(e,t,n){let r=Ve(await He(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 Ve(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 He(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 Ue(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 Be(process.stdin,process.stdout,t);process.exit(n)}),t}async function We(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=ge({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 Ge(e){return process.env.OPEN_KNOWLEDGE_GITHUB_CLIENT_ID??e?.github?.oauthAppClientId??`Ov23liqlSd0V1MwR6rhI`}const Ke=new Set([`gitlab.com`,`bitbucket.org`,`codeberg.org`,`gitea.com`,`sr.ht`,`sourcehut.org`]);function qe(e){let t=e.toLowerCase().replace(/:\d+$/,``);Ke.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 Je(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Ye(e,t,n,r=We){let i=Ge(n),{host:a,json:o}=e;qe(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?Je(!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?Je(!0,{type:`complete`,host:a,login:c}):process.stderr.write(`✓ Logged in as ${c} on ${a}\n`)}function Xe(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 Ye(n,await t(),e())})}async function Ze(e,t,n){let{host:r,json:i}=e;qe(r);let a=await(n??(()=>_e({message:`Enter PAT:`})))();a||(process.stderr.write(`No token provided
|
|
@@ -7,7 +7,7 @@ import{a as e,i as t}from"./constants-CssIsAar.mjs";import{O as n,c as r,k as i}
|
|
|
7
7
|
`),process.exit(1)}await t.set(r,c,a,{gitProtocol:`https`,name:l,email:u}),i?process.stdout.write(`${JSON.stringify({type:`complete`,host:r,login:c})}\n`):process.stderr.write(`✓ PAT stored for ${c} on ${r}\n`)}function Qe(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 Ze(t,await e())})}async function $e(e,t){let{host:n,json:r}=e;qe(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 ve({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 et(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 $e(t,await e())})}async function tt(e,t){let{host:n}=e;await t.clear(n),process.stderr.write(`✓ Signed out from ${n}\n`)}function nt(e){return new C(`signout`).description(`Remove stored credentials`).option(`--host <host>`,`GitHub hostname`,`github.com`).action(async t=>{await tt(t,await e())})}async function rt(e,t){let{host:n,json:r}=e;qe(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 ve({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 it(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 rt(t,await e())})}function at(e){let t=new C(`auth`);t.description(`GitHub authentication management`);let n=()=>ze(),r=e??(()=>({}));return t.addCommand(Xe(r,n)),t.addCommand(it(n)),t.addCommand(et(n)),t.addCommand(nt(n)),t.addCommand(Qe(n)),t.addCommand(Ue(n)),t}function ot(e,t,n={}){let r=p(e,t);if(!E(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??ce();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 st(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 ct(e){let t=e.inspect??(t=>ot(e.lockDir,t)),n=e.unlink??(e=>ae(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=st(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 lt(e){return new C(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{ct({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}function ut(){try{let e=xe(`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 dt(e,t,n={},r=ut){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 ft(e){return e.replace(/:\d+$/,``)}function pt(e){let t=e.trim();if(!t)return null;{let e=/^https?:\/\/([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`https`,hostname:ft(e[1]),owner:e[2],name:e[3]}}{let e=/^ssh:\/\/(?:[\w.-]+@)?([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`ssh`,hostname:ft(e[1]),owner:e[2],name:e[3]}}{let e=/^git:\/\/([^/?#]+)\/([\w.\-~%]+)\/([\w.\-~%]+?)(?:\.git)?\/?$/.exec(t);if(e)return{protocol:`git`,hostname:ft(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 mt=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function ht(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 mt)if(n.includes(e))return{stage:t[1],pct:Math.round(i+r/100*(a-i))};return null}function gt(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function _t(e,t,n,r=process.cwd()){let i=pt(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=t.dir?k(r,t.dir):k(r,i.name);if(E(a)&&ne(a).length>0)throw Error(`Target directory is not empty: ${a}`);let o=await ze(),s=await dt(i.hostname,o,{}),c=A({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=ht(e);n&&n.pct!==l&&(l=n.pct,gt(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
|
-
`),!E(k(a,`.open-knowledge`)))try{let[{runInit:e},{ensureOkGitignoredAtRoot:t}]=await Promise.all([import(`./init-
|
|
10
|
+
`),!E(k(a,`.open-knowledge`)))try{let[{runInit:e},{ensureOkGitignoredAtRoot:t}]=await Promise.all([import(`./init-CfiW8yzl.mjs`),import(`./init-BBEtdFbt.mjs`)]);await e({cwd:a,mcp:!1});try{t(a)}catch{}}catch{}return a}function vt(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 _t(t,{json:r.json,dir:n},i);if(r.json)gt(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-AX9SNvdk.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?gt(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}const yt=new Me;var bt=class e{sessionId;corrId;component;constructor(e=`mcp`,t){this.sessionId=t??be().slice(0,12),this.corrId=be().slice(0,8),this.component=e}info(e,t={}){this.emit(`info`,e,t)}warn(e,t={}){this.emit(`warn`,e,t)}error(e,t,n={}){let r=t?{error:t instanceof Error?t.message:String(t),...n}:n;this.emit(`error`,e,r)}debug(e,t={}){(process.env.MCP_DEBUG===`1`||process.env.DEBUG?.includes(`mcp`))&&this.emit(`debug`,e,t)}child(t){return new e(t??this.component,this.sessionId)}asCallback(){return e=>this.info(e)}emit(e,t,n){let r={ts:new Date().toISOString(),level:e,sessionId:this.sessionId,corrId:this.corrId,component:this.component,msg:t,...n},i=`${JSON.stringify(r)}\n`;process.stderr.write(i);let a=process.env.OK_LOG_FILE;if(a)try{w(a,i)}catch(e){console.warn(`[mcp-logger] Failed to write to OK_LOG_FILE: ${e instanceof Error?e.message:e}`)}}};function xt(e=`mcp`){return new bt(e)}function St(e,t){return yt.run(e,t)}function Ct(){return yt.getStore()}const wt=new Set([`find`,`markdown`,`replace`]),Tt=[`backlinks`,`deadLinks`,`documents`,`enrichedPaths`,`entries`,`forwardLinks`,`hints`,`hubs`,`orphans`,`results`],Et=[`checkpointRef`,`cwd`,`fileCount`,`matchCount`,`ok`,`query`,`stdoutTruncated`,`truncated`];function M(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Dt(e){return M(e)&&`requestId`in e}function Ot(e,t){if(wt.has(e))return{redacted:!0,type:`string`,length:t.length,lines:t.length===0?0:t.split(`
|
|
11
11
|
`).length};let n=e===`command`?240:120;return t.length<=n?t:{type:`string`,length:t.length,preview:`${t.slice(0,n)}...`}}function kt(e,t){if(t===null)return null;if(typeof t==`string`)return Ot(e,t);if(typeof t==`number`||typeof t==`boolean`)return t;if(Array.isArray(t))return{type:`array`,length:t.length};if(M(t)){let e=Object.keys(t).sort();return{type:`object`,keyCount:e.length,keys:e.slice(0,12)}}if(t!==void 0)return{type:typeof t}}function At(e,t){return M(t)?Object.fromEntries(Object.entries(t).map(([e,t])=>[e,kt(e,t)])):kt(e,t)}function jt(e){let t={structuredKeys:Object.keys(e).sort()};for(let n of Et)n in e&&(t[n]=e[n]);for(let n of Tt){let r=e[n];Array.isArray(r)&&(t[`${n}Count`]=r.length)}return`previewUrl`in e&&(t.previewUrl=e.previewUrl??null),`previewUrlSource`in e&&(t.previewUrlSource=e.previewUrlSource),typeof e.stdout==`string`&&(t.stdoutChars=e.stdout.length),Array.isArray(e.warnings)&&(t.warningsCount=e.warnings.length),M(e.warning)&&(t.warning=!0,`previewUrl`in e.warning&&(t.warningPreviewUrl=e.warning.previewUrl??null)),M(e.ui)&&(t.uiBaseUrl=typeof e.ui.baseUrl==`string`||e.ui.baseUrl===null?e.ui.baseUrl:void 0,t.uiPort=typeof e.ui.port==`number`||e.ui.port===null?e.ui.port:void 0),t}function Mt(e){if(!M(e))return{resultType:typeof e};let t={isError:e.isError===!0};return Array.isArray(e.content)&&(t.contentItems=e.content.length,t.contentTextChars=e.content.reduce((e,t)=>M(t)&&typeof t.text==`string`?e+t.text.length:e,0)),M(e.structuredContent)&&Object.assign(t,jt(e.structuredContent)),t}function Nt(e){return{connectionId:e.connectionId.slice(0,8),displayName:e.displayName,...e.clientInfo?.name?{clientName:e.clientInfo.name}:{},...e.label?{label:e.label}:{}}}function Pt(e){let t=e.at(-1);return Dt(t)?{toolArgs:e.length>1?e[0]:void 0,extra:t}:{toolArgs:e[0],extra:void 0}}function Ft(e,t,n){let r=n.logger;return r?async(...i)=>{let a=r.child(),o=Date.now(),{toolArgs:s,extra:c}=Pt(i);a.info(`tool start`,{tool:e,...c?.requestId===void 0?{}:{requestId:c.requestId},...c?.sessionId?{transportSessionId:c.sessionId}:{},...n.identityRef?.current?{agent:Nt(n.identityRef.current)}:{},...s===void 0?{}:{args:At(e,s)}});try{let n=await St(a,async()=>await t(...i));return a.info(`tool finish`,{tool:e,...c?.requestId===void 0?{}:{requestId:c.requestId},durationMs:Date.now()-o,result:Mt(n)}),n}catch(t){throw a.error(`tool error`,t,{tool:e,...c?.requestId===void 0?{}:{requestId:c.requestId},durationMs:Date.now()-o}),t}}:t}function It(e,t){if(!t.logger)return e;let n=e.tool.bind(e),r=Object.create(e);return r.tool=((...e)=>{let r=String(e[0]),i=e.at(-1);if(typeof i!=`function`)return n(...e);let a=[...e];return a[a.length-1]=Ft(r,i,t),n(...a)}),r}const N="Absolute host path to resolve the request against. Defaults only when the MCP client advertises exactly one root; otherwise pass `cwd` explicitly.";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 Lt(e,t){return typeof e==`function`?await e(t):e}async function Rt(e,t){return typeof e==`function`?await e(t):e}async function L(e,t,n){let r;try{r=await e(n)}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}try{let e=await Rt(t,r);return{ok:!0,cwd:r,config:e}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}async function R(e,t,n,r){let i=await L(e,t,r);if(!i.ok)return i;let{cwd:a,config:o}=i;try{return{ok:!0,cwd:a,config:o,url:await Lt(n,a)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}function z(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 B(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 V(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 zt(e,t){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.
|
|
12
12
|
|
|
13
13
|
Topic: ${e}
|
|
@@ -591,6 +591,6 @@ Folder metadata lives in \`config.yml\`, **not** in content files — this is in
|
|
|
591
591
|
${Object.entries(bi).map(([e,t])=>`### \`${e}\`\n${t}`).join(`
|
|
592
592
|
|
|
593
593
|
`)}
|
|
594
|
-
`}async function Di(e,t){try{let t=e.replace(`ws://`,`http://`).replace(`wss://`,`https://`);return(await fetch(`${t}/api/document`,{signal:AbortSignal.timeout(2e3)})).ok}catch(n){return t.warn(`Hocuspocus probe failed`,{serverUrl:e,error:n instanceof Error?n.message:String(n)}),!1}}async function Oi(n){let{projectDir:r,serverUrl:i,config:a,startupConfig:o,bypassProjectSelection:s=!1}=n;if(X=xt(),X.info(`MCP server starting`,{startupCwd:r,bypassProjectSelection:s,serverUrlType:typeof i==`string`?`explicit`:`lazy`}),typeof i==`string`){let e=await Di(i,X);X.info(`Hocuspocus detection complete`,{serverUrl:i,available:e})}else X.info(`server discovery is lazy per effective cwd`);let c=new ke({name:t,version:e},{instructions:Ei(o,{dynamicConfig:typeof a==`function`&&!s})}),l=wi({startupCwd:r,bypassProjectSelection:s,listRoots:()=>c.server.listRoots(),logger:X}),u=Ti({startupCwd:r,resolveCwd:l.resolveCwd,bypassProjectSelection:s}),d=u.resolveCwdForTools;c.server.setNotificationHandler(je,async()=>{l.invalidateRoots()});let f=async e=>{if(typeof i==`string`)return i.replace(`ws://`,`http://`).replace(`wss://`,`https://`);let t=e??await d();return(typeof i==`function`?await i(t):i)?.replace(`ws://`,`http://`).replace(`wss://`,`https://`)},p=be(),m=process.env.AGENT_LABEL||void 0,h={current:{connectionId:p,label:m,displayName:m??`Agent`,colorSeed:m??p}};c.server.oninitialized=()=>{let e=c.server.getClientVersion();h.current={connectionId:p,clientInfo:e?{name:e.name,version:e.version}:void 0,label:m,displayName:m??e?.name??`Agent`,colorSeed:m??e?.name??p},X?.info(`agent identity established`,{displayName:h.current.displayName,connectionId:p.slice(0,8),clientName:e?.name})},xi(c,{serverUrl:f,resolveCwd:d,config:a,identityRef:h,logger:X});let g=new Ae;await c.connect(g),X.info(`MCP server running on stdio`);let{startKeepalive:_}=await import(`./keepalive-UJIeMtkM.mjs`),v=_({resolveWsUrl:async()=>{let e=await u.getKeepaliveCwd();if(!e)return;let t=await f(e);if(t)return t.replace(/^http:/,`ws:`).replace(/^https:/,`wss:`)},connectionId:`agent-${p}`,logger:X.child(`keepalive`)}),y=e=>{X?.info(`MCP server shutting down`,{signal:e});try{v.close()}catch{}process.exit(0)};process.on(`SIGINT`,()=>y(`SIGINT`)),process.on(`SIGTERM`,()=>y(`SIGTERM`))}function ki(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function Ai(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 ji(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??Se,a=e.readErrorLog??(e=>E(e)?O(e,`utf-8`).trim():``),o=e.openErrorLog??(e=>te(e,`w`)),s=e.closeFd??(e=>T(e)),c=e.timeoutMs??5e3,l=e.pollIntervalMs??100,u=Ai({host:e.host,portOverride:e.portOverride,envAutoStart:e.envAutoStart,configAutoStart:e.configAutoStart,readLock:t,isAlive:n});if(e.logger?.info(`auto-start decision`,{action:u.action,message:u.message,contentDir:e.contentDir}),u.action===`connect`)return{serverUrl:u.url,message:u.message};if(u.action===`disk-only`)return{serverUrl:void 0,message:u.message};E(e.lockDir)||D(e.lockDir,{recursive:!0});let d=fe(e.lockDir,`last-spawn-error.log`),f=o(d),p,g,_=S();e.logger?.info(`spawning server`,{command:_.command,cwd:e.contentDir,timeoutMs:c});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 t=a(d);throw e.logger?.error(`spawn failed`,void 0,{error:g,stderr:t}),Error(`Error: spawn failed: ${g}${t?` stderr:\n${t}`:``}`)}await r(l);let i=t();if(i&&i.port>0&&n(i.pid)){let t=`ws://localhost:${i.port}`;return e.logger?.info(`server ready after spawn`,{url:t,pid:i.pid}),{serverUrl:t,message:`spawned ok start; connected at ${t} (pid ${i.pid})`}}}if(g){let t=a(d);throw e.logger?.error(`spawn failed (post-deadline)`,void 0,{error:g,stderr:t}),Error(`Error: spawn failed: ${g}${t?` stderr:\n${t}`:``}`)}let y=a(d),ee=(c/1e3).toFixed(c%1e3==0?0:2),b=p?.pid,x=``;throw typeof b==`number`&&(x=n(b)?` child pid=${b} is still running — raise OK_MCP_SPAWN_TIMEOUT_MS if this is a slow boot.`:` child pid=${b} exited — check last-spawn-error.log.`),e.logger?.error(`spawn poll timeout`,void 0,{timeoutMs:c,childPid:b,childAlive:typeof b==`number`?n(b):void 0,stderr:y||void 0}),Error(`Error: server did not start within ${ee}s.${x}${y?` stderr:\n${y}`:``}`)}function Mi(e){if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t)||t<=0)return async()=>void 0;let n=`ws://${e.host}:${t}`;return async()=>n}let t=e.ensureServerRunningFn??ji,n=e.cacheMs??1e3,r=new Map,i=new Map;return async s=>{let c=await y(s??e.startupCwd),l=Date.now(),u=r.get(c);if(u&&u.expiresAt>l)return e.logger?.debug(`server url cache hit`,{cwd:c,url:u.url}),u.url;let d=i.get(c);if(d)return e.logger?.debug(`server url resolution pending`,{cwd:c}),await d;e.logger?.debug(`server url cache miss`,{cwd:c});let f=(async()=>{let i=await e.resolveConfig(c),s=o(i,c),l=a(s),u=e.readLock,d=u?()=>u(l):void 0,f=await t({lockDir:l,contentDir:s,host:i.server.host,portOverride:void 0,envAutoStart:e.envAutoStart,configAutoStart:i.mcp.autoStart,logger:e.logger,timeoutMs:e.timeoutMs,pollIntervalMs:e.pollIntervalMs,spawn:e.spawn,readLock:d,isAlive:e.isAlive,sleep:e.sleep,readErrorLog:e.readErrorLog,openErrorLog:e.openErrorLog,closeFd:e.closeFd});return r.set(c,{url:f.serverUrl,expiresAt:Date.now()+n}),f.serverUrl})();i.set(c,f);try{return await f}finally{i.delete(c)}}}function Ni(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=b({startupCwd:r,startupConfig:n}),a=ki(process.env.OK_MCP_SPAWN_TIMEOUT_MS),o,s;if(t.port!==void 0){let e=Number.parseInt(t.port,10);Number.isNaN(e)?(o=void 0,s=`invalid --port value '${t.port}' — disk-only mode`):e>0?(o=`ws://${n.server.host}:${e}`,s=`using --port override, connecting to ${o}`):(o=void 0,s=`--port=0 — disk-only mode`)}else o=Mi({startupCwd:r,resolveConfig:i,host:n.server.host,portOverride:void 0,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:a}),s=`project server discovery/autostart is lazy per effective cwd`;process.stderr.write(`[mcp] ${s}\n`),await Oi({projectDir:r,serverUrl:o,config:i,startupConfig:n,bypassProjectSelection:t.port!==void 0})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function Pi(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-
|
|
595
|
-
`)),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 Fi({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 Li(e){return new C(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Fi({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 Ri(e){return new C(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Fi({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 zi(e,t){return{server:Bi(`server`,e),ui:Bi(`ui`,t)}}function Bi(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 Vi(e){return`${Hi(e.server)}\n${Hi(e.ui)}`}function Hi(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 Ui(e){let t=e.inspect??(t=>ot(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=zi(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(Vi(r)),r}function Wi(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=>{Ui({lockDir:a(o(e(),process.cwd())),json:t.json===!0})})}function Gi(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 Ki(e){let t=e.inspect??(t=>ot(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=Gi(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 qi(e){return new C(`stop`).description(`Stop the running open-knowledge server and UI (live only)`).action(()=>{Ki({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}const Ji=1e4,Yi=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function Xi(e){let t=e.upstreamTimeoutMs??Ji,n=Ee((n,r)=>{Qi(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 Zi(e,t,n){Qi(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??Ji)}function Qi(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of Yi)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=De({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of Yi)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 $i(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function ea(e){let{existsSync:t}=await import(`node:fs`),{createServer:n}=await import(`node:http`),{resolve:i}=await import(`node:path`),{acquireUiLock:a,readServerLock:o,releaseUiLock:s,updateUiLockPort:c}=await import(`./src-FL3Ydra9.mjs`),{default:l}=await import(`sirv`),{resolveContentDir:u,resolveLockDir:d}=await import(`./paths-CMZmck8P.mjs`),f=u(e.config,e.cwd),p=d(f);a(p,{port:0,worktreeRoot:e.cwd});let m=import.meta.dirname??new URL(`.`,import.meta.url).pathname,h=[i(m,`public`),i(m,`../../app/dist`),i(m,`../../../app/dist`)].find(e=>t(e)),g=h?l(h,{single:!0,gzip:!0,immutable:!0}):null,_=t(f)?l(f,{dotfiles:!1,dev:!0}):null,v=e.port,y=null,ee=(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}Zi(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):ta(t)});return}if(g){g(e,t);return}ta(t)},b=e.host===void 0?[`::1`,`127.0.0.1`]:[e.host],x=[],S=e.port;try{for(let e of b){let t=n(ee);x.push(t),await new Promise((n,r)=>{let i=e=>r(e);t.once(`error`,i),t.listen(S,e,()=>{t.off(`error`,i);let e=t.address();typeof e==`object`&&e&&(S=e.port),n()})})}}catch(e){await Promise.all(x.map(e=>new Promise(t=>{try{e.close(()=>t())}catch{t()}})));try{s(p)}catch{}throw e}let C=S;v=C,c(p,C);let w=e.scheduler??r,T=e.safetyNetMs??432e5,E=null,D=!1,te=!1,O=()=>{D||(D=!0,E!==null&&(w.clearTimeout(E),E=null))},ne=()=>{if(O(),!te){te=!0;try{s(p)}catch{}}},re=()=>{D||T<=0||(E!==null&&(w.clearTimeout(E),E=null),E=w.setTimeout(()=>{E=null,console.warn(`[ui] safety-net (${T}ms) reached — shutting down (D-025 backstop)`);try{e.onSafetyNet?.()}catch{}for(let e of x)try{e.close()}catch{}ne()},T))},ie=()=>{D||T<=0||re()};return y=ie,re(),{httpServers:x,port:C,release:ne,detachSafetyNet:O,nudgeSafetyNet:ie}}function ta(e){e.writeHead(404),e.end(`Not found`)}function na(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 ra(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-FL3Ydra9.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 Xi({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function ia(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-xJqYhQcY.mjs`),{UiLockCollisionError:r}=await import(`./src-FL3Ydra9.mjs`),{resolveContentDir:i,resolveLockDir:a}=await import(`./paths-CMZmck8P.mjs`),o=e(),s=t.host,c;try{c=na(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}try{let e=await ea({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)}};$i(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 ra({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(e).option(`--cwd <path>`,`Working directory`).option(`--log-level <level>`,`Log level`,`info`).option(`--no-color`,`Disable color output`).option(`--color`,`Force color output`).hook(`preAction`,e=>{let t=e.opts(),n=t.cwd;n!==void 0&&process.chdir(n);let{config:r}=ee(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 aa=x(()=>$);Q.addCommand(aa,{isDefault:!0});const oa=Ni(()=>$);Q.addCommand(oa),Q.addCommand(v());const sa=Pi(()=>$);Q.addCommand(sa);const ca=ia(()=>$);Q.addCommand(ca),Q.addCommand(qi(()=>$)),Q.addCommand(lt(()=>$)),Q.addCommand(Wi(()=>$)),Q.addCommand(at(()=>$)),Q.addCommand(vt(()=>$)),Q.addCommand(Ii(()=>$)),Q.addCommand(Ri(()=>$)),Q.addCommand(Li(()=>$)),await Q.parseAsync();export{};
|
|
594
|
+
`}async function Di(e,t){try{let t=e.replace(`ws://`,`http://`).replace(`wss://`,`https://`);return(await fetch(`${t}/api/document`,{signal:AbortSignal.timeout(2e3)})).ok}catch(n){return t.warn(`Hocuspocus probe failed`,{serverUrl:e,error:n instanceof Error?n.message:String(n)}),!1}}async function Oi(n){let{projectDir:r,serverUrl:i,config:a,startupConfig:o,bypassProjectSelection:s=!1}=n;if(X=xt(),X.info(`MCP server starting`,{startupCwd:r,bypassProjectSelection:s,serverUrlType:typeof i==`string`?`explicit`:`lazy`}),typeof i==`string`){let e=await Di(i,X);X.info(`Hocuspocus detection complete`,{serverUrl:i,available:e})}else X.info(`server discovery is lazy per effective cwd`);let c=new ke({name:t,version:e},{instructions:Ei(o,{dynamicConfig:typeof a==`function`&&!s})}),l=wi({startupCwd:r,bypassProjectSelection:s,listRoots:()=>c.server.listRoots(),logger:X}),u=Ti({startupCwd:r,resolveCwd:l.resolveCwd,bypassProjectSelection:s}),d=u.resolveCwdForTools;c.server.setNotificationHandler(je,async()=>{l.invalidateRoots()});let f=async e=>{if(typeof i==`string`)return i.replace(`ws://`,`http://`).replace(`wss://`,`https://`);let t=e??await d();return(typeof i==`function`?await i(t):i)?.replace(`ws://`,`http://`).replace(`wss://`,`https://`)},p=be(),m=process.env.AGENT_LABEL||void 0,h={current:{connectionId:p,label:m,displayName:m??`Agent`,colorSeed:m??p}};c.server.oninitialized=()=>{let e=c.server.getClientVersion();h.current={connectionId:p,clientInfo:e?{name:e.name,version:e.version}:void 0,label:m,displayName:m??e?.name??`Agent`,colorSeed:m??e?.name??p},X?.info(`agent identity established`,{displayName:h.current.displayName,connectionId:p.slice(0,8),clientName:e?.name})},xi(c,{serverUrl:f,resolveCwd:d,config:a,identityRef:h,logger:X});let g=new Ae;await c.connect(g),X.info(`MCP server running on stdio`);let{startKeepalive:_}=await import(`./keepalive-UJIeMtkM.mjs`),v=_({resolveWsUrl:async()=>{let e=await u.getKeepaliveCwd();if(!e)return;let t=await f(e);if(t)return t.replace(/^http:/,`ws:`).replace(/^https:/,`wss:`)},connectionId:`agent-${p}`,logger:X.child(`keepalive`)}),y=e=>{X?.info(`MCP server shutting down`,{signal:e});try{v.close()}catch{}process.exit(0)};process.on(`SIGINT`,()=>y(`SIGINT`)),process.on(`SIGTERM`,()=>y(`SIGTERM`))}function ki(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function Ai(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 ji(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??Se,a=e.readErrorLog??(e=>E(e)?O(e,`utf-8`).trim():``),o=e.openErrorLog??(e=>te(e,`w`)),s=e.closeFd??(e=>T(e)),c=e.timeoutMs??5e3,l=e.pollIntervalMs??100,u=Ai({host:e.host,portOverride:e.portOverride,envAutoStart:e.envAutoStart,configAutoStart:e.configAutoStart,readLock:t,isAlive:n});if(e.logger?.info(`auto-start decision`,{action:u.action,message:u.message,contentDir:e.contentDir}),u.action===`connect`)return{serverUrl:u.url,message:u.message};if(u.action===`disk-only`)return{serverUrl:void 0,message:u.message};E(e.lockDir)||D(e.lockDir,{recursive:!0});let d=fe(e.lockDir,`last-spawn-error.log`),f=o(d),p,g,_=S();e.logger?.info(`spawning server`,{command:_.command,cwd:e.contentDir,timeoutMs:c});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 t=a(d);throw e.logger?.error(`spawn failed`,void 0,{error:g,stderr:t}),Error(`Error: spawn failed: ${g}${t?` stderr:\n${t}`:``}`)}await r(l);let i=t();if(i&&i.port>0&&n(i.pid)){let t=`ws://localhost:${i.port}`;return e.logger?.info(`server ready after spawn`,{url:t,pid:i.pid}),{serverUrl:t,message:`spawned ok start; connected at ${t} (pid ${i.pid})`}}}if(g){let t=a(d);throw e.logger?.error(`spawn failed (post-deadline)`,void 0,{error:g,stderr:t}),Error(`Error: spawn failed: ${g}${t?` stderr:\n${t}`:``}`)}let y=a(d),ee=(c/1e3).toFixed(c%1e3==0?0:2),b=p?.pid,x=``;throw typeof b==`number`&&(x=n(b)?` child pid=${b} is still running — raise OK_MCP_SPAWN_TIMEOUT_MS if this is a slow boot.`:` child pid=${b} exited — check last-spawn-error.log.`),e.logger?.error(`spawn poll timeout`,void 0,{timeoutMs:c,childPid:b,childAlive:typeof b==`number`?n(b):void 0,stderr:y||void 0}),Error(`Error: server did not start within ${ee}s.${x}${y?` stderr:\n${y}`:``}`)}function Mi(e){if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t)||t<=0)return async()=>void 0;let n=`ws://${e.host}:${t}`;return async()=>n}let t=e.ensureServerRunningFn??ji,n=e.cacheMs??1e3,r=new Map,i=new Map;return async s=>{let c=await y(s??e.startupCwd),l=Date.now(),u=r.get(c);if(u&&u.expiresAt>l)return e.logger?.debug(`server url cache hit`,{cwd:c,url:u.url}),u.url;let d=i.get(c);if(d)return e.logger?.debug(`server url resolution pending`,{cwd:c}),await d;e.logger?.debug(`server url cache miss`,{cwd:c});let f=(async()=>{let i=await e.resolveConfig(c),s=o(i,c),l=a(s),u=e.readLock,d=u?()=>u(l):void 0,f=await t({lockDir:l,contentDir:s,host:i.server.host,portOverride:void 0,envAutoStart:e.envAutoStart,configAutoStart:i.mcp.autoStart,logger:e.logger,timeoutMs:e.timeoutMs,pollIntervalMs:e.pollIntervalMs,spawn:e.spawn,readLock:d,isAlive:e.isAlive,sleep:e.sleep,readErrorLog:e.readErrorLog,openErrorLog:e.openErrorLog,closeFd:e.closeFd});return r.set(c,{url:f.serverUrl,expiresAt:Date.now()+n}),f.serverUrl})();i.set(c,f);try{return await f}finally{i.delete(c)}}}function Ni(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=b({startupCwd:r,startupConfig:n}),a=ki(process.env.OK_MCP_SPAWN_TIMEOUT_MS),o,s;if(t.port!==void 0){let e=Number.parseInt(t.port,10);Number.isNaN(e)?(o=void 0,s=`invalid --port value '${t.port}' — disk-only mode`):e>0?(o=`ws://${n.server.host}:${e}`,s=`using --port override, connecting to ${o}`):(o=void 0,s=`--port=0 — disk-only mode`)}else o=Mi({startupCwd:r,resolveConfig:i,host:n.server.host,portOverride:void 0,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:a}),s=`project server discovery/autostart is lazy per effective cwd`;process.stderr.write(`[mcp] ${s}\n`),await Oi({projectDir:r,serverUrl:o,config:i,startupConfig:n,bypassProjectSelection:t.port!==void 0})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function Pi(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-C9MefMSi.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 Fi(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=A({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
|
|
595
|
+
`)),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 Fi({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 Li(e){return new C(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Fi({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 Ri(e){return new C(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Fi({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 zi(e,t){return{server:Bi(`server`,e),ui:Bi(`ui`,t)}}function Bi(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 Vi(e){return`${Hi(e.server)}\n${Hi(e.ui)}`}function Hi(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 Ui(e){let t=e.inspect??(t=>ot(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=zi(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(Vi(r)),r}function Wi(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=>{Ui({lockDir:a(o(e(),process.cwd())),json:t.json===!0})})}function Gi(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 Ki(e){let t=e.inspect??(t=>ot(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=Gi(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 qi(e){return new C(`stop`).description(`Stop the running open-knowledge server and UI (live only)`).action(()=>{Ki({lockDir:a(o(e(),process.cwd()))}).failed.length>0&&(process.exitCode=1)})}const Ji=1e4,Yi=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function Xi(e){let t=e.upstreamTimeoutMs??Ji,n=Ee((n,r)=>{Qi(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 Zi(e,t,n){Qi(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??Ji)}function Qi(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of Yi)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=De({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of Yi)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 $i(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function ea(e){let{existsSync:t}=await import(`node:fs`),{createServer:n}=await import(`node:http`),{resolve:i}=await import(`node:path`),{acquireUiLock:a,readServerLock:o,releaseUiLock:s,updateUiLockPort:c}=await import(`./src-FL3Ydra9.mjs`),{default:l}=await import(`sirv`),{resolveContentDir:u,resolveLockDir:d}=await import(`./paths-DKYbHoVz.mjs`),f=u(e.config,e.cwd),p=d(f);a(p,{port:0,worktreeRoot:e.cwd});let m=import.meta.dirname??new URL(`.`,import.meta.url).pathname,h=[i(m,`public`),i(m,`../../app/dist`),i(m,`../../../app/dist`)].find(e=>t(e)),g=h?l(h,{single:!0,gzip:!0,immutable:!0}):null,_=t(f)?l(f,{dotfiles:!1,dev:!0}):null,v=e.port,y=null,ee=(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}Zi(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):ta(t)});return}if(g){g(e,t);return}ta(t)},b=e.host===void 0?[`::1`,`127.0.0.1`]:[e.host],x=[],S=e.port;try{for(let e of b){let t=n(ee);x.push(t),await new Promise((n,r)=>{let i=e=>r(e);t.once(`error`,i),t.listen(S,e,()=>{t.off(`error`,i);let e=t.address();typeof e==`object`&&e&&(S=e.port),n()})})}}catch(e){await Promise.all(x.map(e=>new Promise(t=>{try{e.close(()=>t())}catch{t()}})));try{s(p)}catch{}throw e}let C=S;v=C,c(p,C);let w=e.scheduler??r,T=e.safetyNetMs??432e5,E=null,D=!1,te=!1,O=()=>{D||(D=!0,E!==null&&(w.clearTimeout(E),E=null))},ne=()=>{if(O(),!te){te=!0;try{s(p)}catch{}}},re=()=>{D||T<=0||(E!==null&&(w.clearTimeout(E),E=null),E=w.setTimeout(()=>{E=null,console.warn(`[ui] safety-net (${T}ms) reached — shutting down (D-025 backstop)`);try{e.onSafetyNet?.()}catch{}for(let e of x)try{e.close()}catch{}ne()},T))},ie=()=>{D||T<=0||re()};return y=ie,re(),{httpServers:x,port:C,release:ne,detachSafetyNet:O,nudgeSafetyNet:ie}}function ta(e){e.writeHead(404),e.end(`Not found`)}function na(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 ra(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-FL3Ydra9.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 Xi({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function ia(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-xJqYhQcY.mjs`),{UiLockCollisionError:r}=await import(`./src-FL3Ydra9.mjs`),{resolveContentDir:i,resolveLockDir:a}=await import(`./paths-DKYbHoVz.mjs`),o=e(),s=t.host,c;try{c=na(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}try{let e=await ea({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)}};$i(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 ra({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(e).option(`--cwd <path>`,`Working directory`).option(`--log-level <level>`,`Log level`,`info`).option(`--no-color`,`Disable color output`).option(`--color`,`Force color output`).hook(`preAction`,e=>{let t=e.opts(),n=t.cwd;n!==void 0&&process.chdir(n);let{config:r}=ee(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 aa=x(()=>$);Q.addCommand(aa,{isDefault:!0});const oa=Ni(()=>$);Q.addCommand(oa),Q.addCommand(v());const sa=Pi(()=>$);Q.addCommand(sa);const ca=ia(()=>$);Q.addCommand(ca),Q.addCommand(qi(()=>$)),Q.addCommand(lt(()=>$)),Q.addCommand(Wi(()=>$)),Q.addCommand(at(()=>$)),Q.addCommand(vt(()=>$)),Q.addCommand(Ii(()=>$)),Q.addCommand(Ri(()=>$)),Q.addCommand(Li(()=>$)),await Q.parseAsync();export{};
|
|
596
596
|
//# sourceMappingURL=cli.mjs.map
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,r as t}from"./loader-
|
|
1
|
+
import{n as e,r as t}from"./loader-DC05jP_i.mjs";import"./src-C9R5iE4n.mjs";export{t as ConfigSchema,e as loadConfig};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{i as e}from"./constants-
|
|
1
|
+
import{i as e}from"./constants-CctQOxTv.mjs";import{O as t}from"./src-CQw-HNNM.mjs";import{n,t as r}from"./src-y0OBZgkE.mjs";import{o as i,s as a}from"./init-CXgpPYnX.mjs";import{t as o}from"./preview-D89OyWfK.mjs";import{t as s}from"./is-object-DaHwJLOe.mjs";import{Command as c}from"commander";import{existsSync as l,mkdirSync as u,readFileSync as d,writeFileSync as f}from"node:fs";import{homedir as p}from"node:os";import{basename as m,dirname as h,isAbsolute as g,join as _,posix as v,relative as y,resolve as b,sep as x,win32 as S}from"node:path";import{parse as C,stringify as w}from"smol-toml";const T=[`claude`,`claude-desktop`,`cursor`,`vscode`,`windsurf`,`codex`],E=[`@inkeep/open-knowledge`,`mcp`],ee={MCP_DEBUG:`1`,OK_LOG_FILE:`/tmp/ok-mcp.log`};function D(e=process.argv[1]){if(!e)throw Error(`Cannot infer the local CLI entry for --dev-mcp because process.argv[1] is empty.`);let t=b(e);if(m(t)===`cli.mjs`&&m(h(t))===`dist`)return t;let n=t.split(x),r=n.lastIndexOf(`packages`);if(r===-1||n[r+1]!==`cli`)throw Error(`Cannot infer the repo root for --dev-mcp from ${t}. Run the local CLI from this repo so the built dist path can be derived.`);let i=n.slice(0,r);return _(i.length===0?x:i.join(x),`packages`,`cli`,`dist`,`cli.mjs`)}function O(e={}){return e.mode===`dev`?{command:`node`,args:[D(e.cliEntryPath),`mcp`],env:{...ee}}:{command:`npx`,args:[...E]}}function k(e){return e===`win32`?S:v}function A(e={}){let t=e.platformName??process.platform,n=e.home??p(),r=e.env??process.env,i=k(t);return t===`darwin`?i.join(n,`Library`,`Application Support`):t===`win32`?r.APPDATA??i.join(n,`AppData`,`Roaming`):r.XDG_CONFIG_HOME??i.join(n,`.config`)}function j(e={}){let t=e.platformName??process.platform,n=e.home??p();return k(t).join(n,`.claude.json`)}function M(e={}){let t=e.platformName??process.platform,n=e.home??p(),r=e.env??process.env;if(t===`darwin`)return v.join(n,`Library`,`Application Support`,`Claude`,`claude_desktop_config.json`);if(t===`win32`){let e=r.APPDATA??S.join(n,`AppData`,`Roaming`);return S.join(e,`Claude`,`claude_desktop_config.json`)}throw Error(`Claude Desktop is not available on ${t}. Supported: macOS, Windows.`)}function N(e={}){let t=e.platformName??process.platform,n=e.home??p();return k(t).join(n,`.cursor`,`mcp.json`)}function P(e={}){return k(e.platformName??process.platform).join(A(e),`Code`,`User`,`mcp.json`)}function F(e={}){let t=e.platformName??process.platform,n=e.home??p();return k(t).join(n,`.codeium`,`windsurf`,`mcp_config.json`)}function I(e={}){let t=e.platformName??process.platform,n=e.home??p();return(e.env??process.env).CODEX_HOME??k(t).join(n,`.codex`)}function L(e={}){return k(e.platformName??process.platform).join(I(e),`config.toml`)}function R(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>R(e,t[n]));if(s(e)&&s(t)){let n=Object.keys(e).sort(),r=Object.keys(t).sort();return n.length===r.length&&n.every((e,t)=>e===r[t])&&n.every(n=>R(e[n],t[n]))}return!1}function z(e,t){return Object.entries(t).every(([t,n])=>R(e[t],n))}function B(e,t){return{...e,...t}}function V(e){return{...e,isCompatible(t,n,r){return z(t,e.buildEntry(n,r))},mergeManagedFields(t,n,r){return B(t,e.buildEntry(n,r))}}}const H={claude:V({id:`claude`,label:`Claude Code`,configPath:(e,t)=>j({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>O(t),scope:`global`,detectPath:(e,t)=>_(t??p(),`.claude`),legacyProjectConfigPath:e=>_(e,`.mcp.json`),instructionsPath:e=>_(e,`CLAUDE.md`)}),"claude-desktop":V({id:`claude-desktop`,label:`Claude Desktop`,configPath:(e,t)=>M({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>O(t),scope:`global`,detectPath:(e,t)=>h(M({home:t}))}),cursor:V({id:`cursor`,label:`Cursor`,configPath:(e,t)=>N({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>O(t),scope:`global`,detectPath:(e,t)=>h(N({home:t})),legacyProjectConfigPath:e=>_(e,`.cursor`,`mcp.json`)}),vscode:V({id:`vscode`,label:`VS Code`,configPath:(e,t)=>P({home:t}),format:`json`,topLevelKey:`servers`,serverName:()=>e,buildEntry:(e,t)=>({type:`stdio`,...O(t)}),scope:`global`,detectPath:(e,t)=>h(P({home:t})),legacyProjectConfigPath:e=>_(e,`.vscode`,`mcp.json`)}),windsurf:V({id:`windsurf`,label:`Windsurf`,configPath:(e,t)=>F({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>O(t),scope:`global`,detectPath:(e,t)=>h(F({home:t}))}),codex:V({id:`codex`,label:`Codex`,configPath:(e,t)=>L({home:t}),format:`toml`,topLevelKey:`mcp_servers`,serverName:()=>e,buildEntry:(e,t)=>O(t),scope:`global`,detectPath:(e,t)=>h(L({home:t})),legacyProjectConfigPath:e=>_(e,`.codex`,`config.toml`)})};function U(e){let t=e.filter(e=>!(e in H));if(t.length>0)throw Error(`Unknown editor(s): ${t.join(`, `)}. Valid options: ${T.join(`, `)}`);return e.map(e=>H[e])}function W(e){if(!l(e))return{};let t=d(e,`utf-8`).trim();if(t===``)return{};try{let n=JSON.parse(t);if(s(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 G(e){if(!l(e))return{};let t=d(e,`utf-8`).trim();if(t===``)return{};try{let n=C(t);if(s(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 K(e,t){u(h(e),{recursive:!0}),f(e,`${JSON.stringify(t,null,2)}\n`,`utf-8`)}function q(e,t){u(h(e),{recursive:!0});let n=w(t);f(e,n.endsWith(`
|
|
2
2
|
`)?n:`${n}\n`,`utf-8`)}const J=`0.0.1`,Y=`open-knowledge-ui`;function te(e,t={}){let n=_(e,`.claude`,`launch.json`),r=t.mode===`dev`?{name:Y,runtimeExecutable:`node`,runtimeArgs:[D(t.cliEntryPath),`ui`],port:3e3}:{name:Y,runtimeExecutable:`npx`,runtimeArgs:[`@inkeep/open-knowledge`,`ui`],port:3e3};try{if(!l(n))return u(h(n),{recursive:!0}),f(n,`${JSON.stringify({version:J,configurations:[r]},null,2)}\n`,`utf-8`),{action:`created`,configPath:n};let e=d(n,`utf-8`).trim(),t=e?JSON.parse(e):{};if(!s(t))return{action:`failed`,configPath:n,error:`launch.json root is not an object`};let i=Array.isArray(t.configurations)?t.configurations:[],a=i.findIndex(e=>s(e)&&e.name===Y);a>=0?i[a]=r:i.push(r);let o={...t,version:t.version??J,configurations:i};return f(n,`${JSON.stringify(o,null,2)}\n`,`utf-8`),{action:a>=0?`merged`:`created`,configPath:n}}catch(e){return{action:`failed`,configPath:n,error:e instanceof Error?e.message:String(e)}}}function X(e,t,n){try{return l(e.detectPath?.(t,n)??h(e.configPath(t,n)))}catch{return!1}}function ne(e,t,n,r){let i=e.serverName(t),a;try{a=e.configPath(t,r)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:``,serverName:i,error:t instanceof Error?t.message:String(t)}}if(!X(e,t,r))return{editorId:e.id,label:e.label,action:`skipped-missing`,configPath:a,serverName:i};let o;try{o=e.format===`toml`?G(a):W(a)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}let s=o[e.topLevelKey]??{},c=s[i],l;try{l=e.buildEntry(t,n)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}let u={...o,[e.topLevelKey]:{...s,[i]:l}};try{e.format===`toml`?q(a,u):K(a,u)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}return{editorId:e.id,label:e.label,action:c===void 0?`written`:`overwritten`,configPath:a,serverName:i}}function re(e,t){let n=e.legacyProjectConfigPath?.(t);if(!(!n||!l(n)))return{editorId:e.id,label:e.label,path:n}}async function Z(e={}){let t=b(e.cwd??process.cwd()),r={mode:e.devMcp?`dev`:`published`,cliEntryPath:e.cliEntryPath},o=await n(t),s;try{s=i(t)}catch(n){let r=H.claude.configPath(t,e.home);return{contentCreated:[],contentSkipped:[],editors:[],legacyProjectConfigs:[],rootInstructions:[],didGitInit:o.didInit,mcpAction:`failed`,mcpPath:r,mcpError:`Content scaffolding failed: ${n instanceof Error?n.message:String(n)}`}}let c=U(e.editors??$(t,e.home)),l=c.filter(n=>X(n,t,e.home)),u=[];for(let n of c){if(e.mcp===!1){let r=``;try{r=n.configPath(t,e.home)}catch{}u.push({editorId:n.id,label:n.label,action:`skipped-flag`,configPath:r,serverName:n.serverName(t)});continue}u.push(ne(n,t,r,e.home))}let d=e.mcp===!1?[]:l.map(e=>re(e,t)).filter(e=>e!==void 0),f=l.some(e=>e.id===`claude`)&&e.mcp!==!1?te(t,r):void 0,p=l.map(e=>e.instructionsPath?.(t)).filter(e=>e!==void 0).map(e=>g(e)?y(t,e):e),m=e.rootInstructions===!1?[]:a(t,!0,p),h=e.mcp===!1?`skipped-flag`:`skipped-missing`,_=u.find(e=>e.editorId===`claude`)??u[0]??{action:h,configPath:H.claude.configPath(t,e.home)};return{contentCreated:s.created,contentSkipped:s.skipped,editors:u,legacyProjectConfigs:d,rootInstructions:m,launchJson:f,didGitInit:o.didInit,mcpAction:_.action,mcpPath:_.configPath,mcpError:`error`in _?_.error:void 0}}function Q(e,n){let r=[],i=e.editors.some(e=>e.action===`written`||e.action===`overwritten`),a=e.editors.some(e=>e.action===`failed`),s=e.editors.length>0&&e.editors.every(e=>e.action===`skipped-flag`),c=e.editors.length>0&&e.editors.every(e=>e.action===`skipped-missing`),l=e=>{let t=e.configPath.startsWith(n)?y(n,e.configPath):e.configPath;switch(e.action){case`created`:return` app preview server ${t} configured for Claude Code Desktop embedded browser`;case`merged`:return` app preview server ${t} updated for Claude Code Desktop embedded browser`;case`failed`:return` app preview server ${t} FAILED: ${e.error}`}};e.didGitInit&&r.push(`Initialized git repo at ${n}/.git/ (default branch: main)`);let u=_(n,t);if(e.contentCreated.length>0?(r.push(`Content scaffolded at ${u}/`),r.push(` Created: ${e.contentCreated.join(`, `)}`)):r.push(`Content already present at ${u}/`),e.contentSkipped.length>0&&r.push(` Skipped (already exist): ${e.contentSkipped.join(`, `)}`),r.push(``),e.mcpError&&e.editors.length===0)r.push(`Warning: ${e.mcpError}`);else if(e.editors.length===0)r.push(`MCP server configuration:`),r.push(e.mcpAction===`skipped-flag`?` MCP config not written — use without --no-mcp to configure editors`:` No supported editor config directories detected; skipped MCP registration`);else if(s)r.push(`MCP config not written — use without --no-mcp to configure editors`);else if(c)r.push(`MCP server configuration:`),r.push(` No supported editor config directories detected; skipped MCP registration`);else{r.push(`MCP server configuration:`);for(let t of e.editors){let i=t.configPath.startsWith(n)?y(n,t.configPath):t.configPath.replace(/^\/Users\/[^/]+/,`~`),a=t.serverName===`open-knowledge`?``:` (${t.serverName})`,o=` `.repeat(Math.max(1,14-t.label.length)),s=t.editorId===`claude-desktop`&&(t.action===`written`||t.action===`overwritten`)?` — quit and relaunch Claude Desktop to activate`:``;switch(t.action){case`written`:r.push(` ${t.label}${o}${i} registered${a}${s}`);break;case`overwritten`:r.push(` ${t.label}${o}${i} updated${a}${s}`);break;case`skipped-missing`:r.push(` ${t.label}${o}${i} config root missing; skipped`);break;case`failed`:r.push(` ${t.label}${o}${i} FAILED: ${t.error}`);break;case`skipped-flag`:break}t.editorId===`claude`&&e.launchJson&&r.push(l(e.launchJson))}}if(a&&(r.push(``),r.push(`For failed editors, add the MCP server entry manually. See:`),r.push(` https://github.com/inkeep/open-knowledge#mcp-setup`)),e.legacyProjectConfigs.length>0){r.push(``),r.push(`Legacy project MCP configs detected:`);for(let t of e.legacyProjectConfigs)r.push(` ${t.label} ${y(n,t.path)}`);r.push(` These project-local files may override the new global config. Remove them if you want fully user-scoped MCP setup in this project.`)}if(e.rootInstructions.length>0){let t=e.rootInstructions.filter(e=>e.action!==`skipped-symlink`);if(t.length>0){r.push(``),r.push(`Root instructions:`);for(let e of t){let t=e.path.startsWith(n)?y(n,e.path):e.path,i=` `.repeat(Math.max(1,14-e.file.length));switch(e.action){case`created`:r.push(` ${e.file}${i}${t} created`);break;case`appended`:r.push(` ${e.file}${i}${t} appended Open Knowledge section`);break;case`replaced`:r.push(` ${e.file}${i}${t} replaced Open Knowledge section`);break;case`skipped-existing`:r.push(` ${e.file}${i}${t} already has Open Knowledge section`);break}}}}if(e.preview?(r.push(``),r.push(o(e.preview,n))):e.previewWarning&&(r.push(``),r.push(`Content preview unavailable: ${e.previewWarning}`)),i){let t=e.editors.filter(e=>e.action===`written`||e.action===`overwritten`).map(e=>e.label);r.push(``),r.push(`Next steps:`),r.push(` 1. Open your editor (${t.join(` / `)})`),r.push(` 2. Approve the MCP server when prompted`),r.push(` 3. The knowledge base is ready — use the three workflow tools:`),r.push(` - mcp__open-knowledge__init-content — bootstrap articles from the codebase`),r.push(` - mcp__open-knowledge__ingest — capture an external source`),r.push(` - mcp__open-knowledge__research — gather sources and write findings`)}return r.join(`
|
|
3
3
|
`)}function $(e,t){let n=[];for(let r of T)X(H[r],e,t)&&n.push(r);return n}function ie(){return new c(`init`).description(`Scaffold ${t}/ in the current directory and register the MCP server for your editor(s)`).option(`--mcp`,`Register the MCP server for selected editors (default: true)`,!0).option(`--no-mcp`,`Scaffold the ${t}/ directory but do not touch MCP config`).option(`--dev-mcp`,`Register a local dev MCP entry using node + packages/cli/dist/cli.mjs with debug logging`).action(async e=>{let t=process.cwd(),n;try{n=await Z({cwd:t,mcp:e.mcp,devMcp:e.devMcp})}catch(e){if(e instanceof r){process.stderr.write(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.
|
|
4
|
-
`),e.stderr&&process.stderr.write(`${e.stderr.trim()}\n`),process.exitCode=1;return}throw e}try{let{previewContent:e}=await import(`./preview-
|
|
5
|
-
//# sourceMappingURL=init-
|
|
4
|
+
`),e.stderr&&process.stderr.write(`${e.stderr.trim()}\n`),process.exitCode=1;return}throw e}try{let{previewContent:e}=await import(`./preview-C9MefMSi.mjs`),{loadConfig:r}=await import(`./loader-CRv6YUEt.mjs`),{resolveContentDir:i}=await import(`./paths-DKYbHoVz.mjs`),{config:a}=r(t),o=i(a,t);n.preview=e({projectDir:t,contentDir:o,include:a.content.include,exclude:a.content.exclude})}catch(e){n.previewWarning=e instanceof Error?e.message:String(e)}process.stdout.write(`${Q(n,t)}\n`),(n.editors.some(e=>e.action===`failed`)||n.mcpAction===`failed`)&&(process.exitCode=1)})}export{Z as i,Q as n,ie as r,$ as t};
|
|
5
|
+
//# sourceMappingURL=init-B3ycweHs.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./init-
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./init-CXgpPYnX.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{n as e,r as t,t as n}from"./constants-
|
|
1
|
+
import{n as e,r as t,t as n}from"./constants-CctQOxTv.mjs";import{O as r}from"./src-CQw-HNNM.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=`# ${r}/ — 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,r){let a=[n,...r??[]],u=new Set,d=[];for(let n of a){let r=
|
|
|
227
227
|
|
|
228
228
|
`)?`
|
|
229
229
|
`:``}${n}`,`utf-8`),`appended`)}const x=[{name:n,content:m},{name:`.gitignore`,content:`${e}/\nserver.lock\nui.lock\nsync-state.json\n`},{name:t,content:h}];function S(t){let n=u(t,r),i=[],o=[];a(n,{recursive:!0}),a(l(n,e),{recursive:!0});for(let e of x)y(l(n,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-
|
|
230
|
+
//# sourceMappingURL=init-CXgpPYnX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"./init-B3ycweHs.mjs";export{r as detectInstalledEditors,t as formatInitResult,n as initCommand,e as runInit};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./loader-DC05jP_i.mjs";export{e as loadConfig};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{r as e}from"./constants-
|
|
1
|
+
import{r as e}from"./constants-CctQOxTv.mjs";import{O as t}from"./src-CQw-HNNM.mjs";import{t as n}from"./is-object-DaHwJLOe.mjs";import{existsSync as r,readFileSync as i}from"node:fs";import{homedir as a}from"node:os";import{resolve as o}from"node:path";import{parse as s}from"yaml";import{realpath as c}from"node:fs/promises";import{z as l}from"zod";async function u(e){let t=o(e);try{return await c(t)}catch(e){if(e.code!==`ENOENT`){let n=e instanceof Error?e.message:String(e);console.warn(`[normalize-cwd] realpath failed for ${t}: ${n}`)}return t}}const d=l.object({title:l.string().optional(),description:l.string().optional(),tags:l.array(l.string()).optional()}).strict(),f=l.object({match:l.string().min(1,"`match` must be a non-empty glob pattern (e.g. 'specs/**' or 'reports/*/**')"),frontmatter:d}).strict(),p=l.object({content:l.object({dir:l.string().default(`.`),include:l.array(l.string()).min(1).default([`**/*.md`,`**/*.mdx`]),exclude:l.array(l.string()).default([])}).default({dir:`.`,include:[`**/*.md`,`**/*.mdx`],exclude:[]}),github:l.object({oauthAppClientId:l.string().default(`Ov23liqlSd0V1MwR6rhI`)}).default({oauthAppClientId:`Ov23liqlSd0V1MwR6rhI`}),sync:l.object({enabled:l.boolean().optional(),pushIntervalSeconds:l.number().int().min(1).default(60),pullIntervalSeconds:l.number().int().min(1).default(30),autoCommit:l.boolean().default(!0),autoPush:l.boolean().default(!0),autoPull:l.boolean().default(!0),commitMessage:l.string().default(`auto`)}).default({pushIntervalSeconds:60,pullIntervalSeconds:30,autoCommit:!0,autoPush:!0,autoPull:!0,commitMessage:`auto`}),server:l.object({port:l.number().int().min(0).max(65535).default(0),host:l.string().regex(/^[\w.\-:]+$/,`Invalid hostname`).default(`localhost`),openOnAgentEdit:l.boolean().default(!1)}).default({port:0,host:`localhost`,openOnAgentEdit:!1}),persistence:l.object({debounceMs:l.number().int().min(0).default(2e3),maxDebounceMs:l.number().int().min(0).default(1e4)}).default({debounceMs:2e3,maxDebounceMs:1e4}),preview:l.object({baseUrl:l.url().optional()}).default({}),folders:l.array(f).default([]),mcp:l.object({autoStart:l.boolean().default(!0),tools:l.object({read_document:l.object({historyDepth:l.number().int().min(0).default(5)}).default({historyDepth:5}),search:l.object({maxResults:l.number().int().min(1).default(50)}).default({maxResults:50})}).default({read_document:{historyDepth:5},search:{maxResults:50}})}).default({autoStart:!0,tools:{read_document:{historyDepth:5},search:{maxResults:50}}})});function m(e,t){let r={...e};for(let i of Object.keys(t)){let a=e[i],o=t[i];n(o)&&n(a)?r[i]=m(a,o):o!==void 0&&(r[i]=o)}return r}function h(e){if(!r(e))return null;try{let t=s(i(e,`utf-8`));return n(t)?t:null}catch(t){return console.warn(`[config] Failed to parse ${e}: ${t instanceof Error?t.message:t}`),null}}function g(n){let r=n??process.cwd(),i=[],s=o(a(),t,e),c={},l=h(s);l&&(c=m(c,l),i.push(s));let u=o(r,t,e),d=h(u);d&&(c=m(c,d),i.push(u));let f=p.safeParse(c);if(!f.success){let e=f.error.issues.map(e=>` ${e.path.join(`.`)}: ${e.message}`);throw Error(`Invalid configuration:\n${e.join(`
|
|
2
2
|
`)}`)}return{config:f.data,sources:i}}function _(e,t=process.env){let n=e;return t.PORT&&(n={...n,server:{...n.server,port:Number(t.PORT)}}),t.HOST&&(n={...n,server:{...n.server,host:t.HOST}}),n}function v(e){let t=e.env??process.env,n=e.cacheMs??1e3,r=e.loadConfigFn??g,i=new Map,a=new Map,o=u(e.startupCwd);return async s=>{let c=await u(s??e.startupCwd),l=Date.now(),d=i.get(c);if(d&&d.expiresAt>l)return d.config;let f=a.get(c);if(f)return await f;let p=(async()=>{if(c===await o){let r=_(e.startupConfig,t);return i.set(c,{config:r,expiresAt:Date.now()+n}),r}let a=_(r(c).config,t);return i.set(c,{config:a,expiresAt:Date.now()+n}),a})();a.set(c,p);try{return await p}finally{a.delete(c)}}}export{u as i,g as n,p as r,v as t};
|
|
3
|
-
//# sourceMappingURL=loader-
|
|
3
|
+
//# sourceMappingURL=loader-DC05jP_i.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./paths-DjCE6HsL.mjs";export{t as resolveContentDir,e as resolveLockDir};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"./constants-
|
|
2
|
-
//# sourceMappingURL=paths-
|
|
1
|
+
import"./constants-CctQOxTv.mjs";import{O as e}from"./src-CQw-HNNM.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-DjCE6HsL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,t}from"./preview-D89OyWfK.mjs";export{t as formatPreviewBlock,e as previewContent};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import"./constants-
|
|
1
|
+
import"./constants-CctQOxTv.mjs";import{O as e}from"./src-CQw-HNNM.mjs";import{p as t}from"./src-y0OBZgkE.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-
|
|
3
|
+
//# sourceMappingURL=preview-D89OyWfK.mjs.map
|