@inkeep/open-knowledge 0.0.0-dev-20260424071819 → 0.0.0-dev-20260424150009

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.
Files changed (69) hide show
  1. package/dist/assets/skills/open-knowledge/SKILL.md +228 -0
  2. package/dist/{banner-cxbl_Ely.mjs → banner-CI3--er0.mjs} +2 -2
  3. package/dist/{chokidar-C6yIgAJZ.mjs → chokidar-Z9-8o-jG.mjs} +1 -1
  4. package/dist/cli.mjs +348 -274
  5. package/dist/colors-Cmha5EZJ.mjs +2 -0
  6. package/dist/colors-CxLEz90E.mjs +1 -0
  7. package/dist/constants-QFqPbiZ7.mjs +2 -0
  8. package/dist/{execAsync-DPeftusp.mjs → execAsync-CUbOIvpN.mjs} +1 -1
  9. package/dist/{execAsync-DhDvXMWQ.mjs → execAsync-CjzNx_Wg.mjs} +1 -1
  10. package/dist/{execAsync-RJZP-H-A.mjs → execAsync-xymjJFLm.mjs} +1 -1
  11. package/dist/{getMachineId-bsd-DcLiB1Fb.mjs → getMachineId-bsd-B_JlAoG9.mjs} +2 -2
  12. package/dist/{getMachineId-bsd-B-D2bOSl.mjs → getMachineId-bsd-CMAUw13R.mjs} +2 -2
  13. package/dist/{getMachineId-bsd-Dl-xGqjV.mjs → getMachineId-bsd-DrOrzTD2.mjs} +2 -2
  14. package/dist/{getMachineId-darwin-A7Xy885j.mjs → getMachineId-darwin-BQcf5peQ.mjs} +2 -2
  15. package/dist/{getMachineId-darwin-BQro2RrT.mjs → getMachineId-darwin-DC2qb-xd.mjs} +2 -2
  16. package/dist/{getMachineId-darwin-DPoYqu2E.mjs → getMachineId-darwin-DTGIdpu7.mjs} +2 -2
  17. package/dist/{getMachineId-linux-BwDCbiIf.mjs → getMachineId-linux-C3A6DqVu.mjs} +1 -1
  18. package/dist/{getMachineId-linux-DLyT3DBf.mjs → getMachineId-linux-CMta7vmz.mjs} +1 -1
  19. package/dist/{getMachineId-linux-B6DWkXLm.mjs → getMachineId-linux-nez-pYOw.mjs} +1 -1
  20. package/dist/{getMachineId-unsupported-CnUw0N-q.mjs → getMachineId-unsupported-BrxgPAkN.mjs} +1 -1
  21. package/dist/{getMachineId-unsupported-VfwZ1yF9.mjs → getMachineId-unsupported-gFGrtRr7.mjs} +1 -1
  22. package/dist/{getMachineId-unsupported-CQbaY6vv.mjs → getMachineId-unsupported-j-7WDfTT.mjs} +1 -1
  23. package/dist/{getMachineId-win-Bmzw0GhO.mjs → getMachineId-win-CfF1zVez.mjs} +2 -2
  24. package/dist/{getMachineId-win-DHI6zfnJ.mjs → getMachineId-win-D8Js6D_D.mjs} +2 -2
  25. package/dist/{getMachineId-win-BYymgu0m.mjs → getMachineId-win-DsIEIIis.mjs} +2 -2
  26. package/dist/index.d.mts +0 -7
  27. package/dist/index.mjs +1 -1
  28. package/dist/init-Bw4LWW1o.mjs +1 -0
  29. package/dist/init-D0FupYPY.mjs +1 -0
  30. package/dist/init-D2rQPwU1.mjs +120 -0
  31. package/dist/init-DUIYyxaK.mjs +5 -0
  32. package/dist/{is-object-DVVYT5oa.mjs → is-object-7k010cEq.mjs} +1 -1
  33. package/dist/{keepalive-BqSeN73F.mjs → keepalive-CfaIYv9f.mjs} +1 -1
  34. package/dist/{loader-C-EaZX2e.mjs → loader-C3Wwbx8H.mjs} +2 -2
  35. package/dist/loader-DNeW8gS5.mjs +1 -0
  36. package/dist/{paths-BPoLusOz.mjs → paths-Ba3tNHQr.mjs} +2 -2
  37. package/dist/paths-ORyeejxG.mjs +1 -0
  38. package/dist/preview-BR34uHnQ.mjs +1 -0
  39. package/dist/{preview-T_RVYqtF.mjs → preview-QLsD0vVK.mjs} +2 -2
  40. package/dist/public/assets/McpConsentDialogBody-BpxsNx0A.js +1 -0
  41. package/dist/public/assets/index-Bnp3jcJM.js +27 -0
  42. package/dist/public/assets/index-tR5M38z1.css +1 -0
  43. package/dist/public/index.html +2 -2
  44. package/dist/src-CeiyJxyd.mjs +1 -0
  45. package/dist/{src-DQq7h88V.mjs → src-DIoA15kL.mjs} +25 -8
  46. package/dist/src-lFQj9tkB.mjs +1 -0
  47. package/dist/start-B9LXLMio.mjs +1 -0
  48. package/dist/{start-B84Wdu83.mjs → start-C79L5QTe.mjs} +2 -2
  49. package/dist/{wrapper-DhAZwCvI.mjs → wrapper-BlhyhsXg.mjs} +1 -1
  50. package/package.json +6 -2
  51. package/scripts/postinstall.mjs +53 -0
  52. package/scripts/probe-exec.ts +100 -0
  53. package/scripts/probe-read-document.ts +111 -0
  54. package/dist/colors-CDmFQ1jq.mjs +0 -1
  55. package/dist/colors-CEQEtnHQ.mjs +0 -2
  56. package/dist/constants-CXDXntb9.mjs +0 -2
  57. package/dist/init-BBVwEA2N.mjs +0 -5
  58. package/dist/init-DsXM9hPp.mjs +0 -1
  59. package/dist/init-DvES_bXI.mjs +0 -1
  60. package/dist/init-QQvPB0Au.mjs +0 -230
  61. package/dist/loader-Ck-HQgHI.mjs +0 -1
  62. package/dist/paths-B483looM.mjs +0 -1
  63. package/dist/preview-C5sfPOVh.mjs +0 -1
  64. package/dist/public/assets/McpConsentDialogBody-Dg7gdIrj.js +0 -1
  65. package/dist/public/assets/index-B33JcCrk.js +0 -27
  66. package/dist/public/assets/index-Cj5uVVs3.css +0 -1
  67. package/dist/src-DN3CCqaD.mjs +0 -1
  68. package/dist/src-DuGm387u.mjs +0 -1
  69. package/dist/start-h-f1SVhW.mjs +0 -1
@@ -0,0 +1 @@
1
+ import"./src-CB-sXsMW.mjs";import{Bt as e,ct as t,dt as n,ft as r,i,lt as a,n as o,r as s,ut as c}from"./src-DIoA15kL.mjs";import{f as l,r as u}from"./server-lock-4vgF5yho.mjs";export{o as ProjectGitInitError,t as UiLockCollisionError,a as acquireUiLock,i as bootServer,s as ensureProjectGit,e as getLogger,l as isProcessAlive,u as readServerLock,c as readUiLock,n as releaseUiLock,r as updateUiLockPort};
@@ -0,0 +1 @@
1
+ import{o as e}from"./start-C79L5QTe.mjs";export{e as startCommand};
@@ -1,2 +1,2 @@
1
- import{a as e}from"./constants-CXDXntb9.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{Command as n}from"commander";import{closeSync as r,existsSync as i,mkdirSync as a,openSync as o}from"node:fs";import{join as s}from"node:path";import{spawn as c}from"node:child_process";function l(){let e=process.execPath,t=process.argv[1];return t?{command:e,prefixArgs:[t]}:(console.warn(`[self-spawn] process.argv[1] is empty — falling back to \`npx @inkeep/open-knowledge\`. This re-introduces the version-drift surface that re-exec was fixing. Observed argv: ${JSON.stringify(process.argv)}`),{command:`npx`,prefixArgs:[`@inkeep/open-knowledge`]})}function u(e){return e.uiLock?e.isAlive(e.uiLock.pid)?{action:`skip`,reason:`alive`,pid:e.uiLock.pid,port:e.uiLock.port}:{action:`spawn`,reason:`stale`,stalePid:e.uiLock.pid}:{action:`spawn`,reason:`absent`}}function d(e){i(e.lockDir)||a(e.lockDir,{recursive:!0});let t=o(s(e.lockDir,`last-spawn-error.log`),`w`),n=e.spawn??c,{PORT:u,...d}=process.env,f=l();try{let r=n(f.command,[...f.prefixArgs,...e.args??[`ui`]],{detached:!0,stdio:[`ignore`,`ignore`,t],cwd:e.cwd,env:d});return r.unref(),r}finally{try{r(t)}catch{}}}async function f(e){let t=e.now()+e.timeoutMs;for(;e.now()<t;){let t=e.readUiLock();if(t&&t.port>0)return t.port;await e.sleep(e.pollIntervalMs)}let n=e.readUiLock();return n&&n.port>0?n.port:null}function p(e){let t=e.sigtermGraceMs??1e4,n=e.sigtermPollIntervalMs??200,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));return async()=>{try{let i=e.readUiLock();if(i&&e.isAlive(i.pid))try{e.killPid(i.pid,`SIGTERM`),e.log?.info({pid:i.pid,port:i.port},`idle-shutdown: SIGTERM UI sibling`);let a=Date.now()+t;for(;Date.now()<a&&e.isAlive(i.pid);)await r(n);if(e.isAlive(i.pid))try{e.killPid(i.pid,`SIGKILL`),e.log?.warn({pid:i.pid,graceMs:t},`idle-shutdown: SIGTERM grace expired — escalated to SIGKILL`)}catch(t){e.log?.error({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: SIGKILL failed`)}}catch(t){e.log?.warn({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: failed to SIGTERM UI sibling`)}}catch(t){e.log?.warn({err:t instanceof Error?t.message:String(t)},`idle-shutdown: UI lookup failed; proceeding with destroy`)}await e.destroy()}}async function m(e){let{config:n,cwd:r}=e,i=e.skipAutoInit??!1,a=e.skipUiAutoSpawn??!1,o=e.idleThresholdMs??18e5,{existsSync:s,mkdirSync:c}=await import(`node:fs`),{resolve:l}=await import(`node:path`),{bootServer:m,ensureProjectGit:h,getLogger:g,isProcessAlive:_,readUiLock:v}=await import(`./src-DuGm387u.mjs`),{resolveContentDir:y}=await import(`./paths-B483looM.mjs`),b=e.log??g(`start`),x=y(n,r);s(x)||(c(x,{recursive:!0}),b.info({contentDir:x},`Created content directory`));let S=!s(l(r,t)),C=i?void 0:async()=>{try{let{initContent:e}=await import(`./init-DsXM9hPp.mjs`),t=e(r);return S||t.created.length>0}catch(e){return console.warn(`Auto-init failed:`,e instanceof Error?e.message:e),!1}},w=!1,T=l(x,t),E=n.server.openOnAgentEdit?()=>{if(w)return;let e=v(T);if(!e||e.port<=0||!_(e.pid))return;w=!0;let t=`http://localhost:${e.port}`;import(`./open-browser-T-bOz6ZQ.mjs`).then(({openBrowser:e})=>e(t)).catch(()=>{})}:void 0,D=null,O=await m({contentDir:x,projectDir:r,contentRoot:n.content.dir,port:n.server.port,host:n.server.host,quiet:!1,debounce:n.persistence.debounceMs,maxDebounce:n.persistence.maxDebounceMs,includePatterns:n.content.include,excludePatterns:n.content.exclude,onAgentWrite:E,localOpCliArgs:[process.execPath,process.argv[1]],attachUiSibling:!0,idleShutdownMs:o,skipAutoInit:i,autoInitFn:C,ensureProjectGitFn:i?void 0:()=>h(r),spawnUiSiblingFn:async({lockDir:t})=>{if(D=u({uiLock:v(t),isAlive:_}),D.action===`spawn`&&!a)try{d({lockDir:t,cwd:r,spawn:e.spawn}),b.info({reason:D.reason},`[start] auto-spawned ok ui sibling`)}catch(e){console.warn(`[start] failed to auto-spawn ok ui: ${e instanceof Error?e.message:String(e)}`)}else D.action===`skip`&&b.info({port:D.port,pid:D.pid},`UI already running at port ${D.port}`)},idleShutdownHandler:e=>p({readUiLock:()=>v(O.lockDir),isAlive:_,killPid:(e,t)=>{process.kill(e,t)},destroy:e,log:b}),log:b});D||={action:`skip`,reason:`alive`,pid:0,port:0};let k=D,A=null;if(k.action===`skip`)A=k.port>0?k.port:null;else if(!a){let t=e.uiBindTimeoutMs??3e3;A=await f({readUiLock:()=>v(O.lockDir),now:Date.now,sleep:e=>new Promise(t=>setTimeout(t,e)),timeoutMs:t,pollIntervalMs:50}),A===null&&b.warn({timeoutMs:t},`[start] ok ui did not bind within timeout — banner falls back to API URL`)}return{httpServer:O.httpServer,destroy:O.destroy,lockDir:O.lockDir,contentDir:x,port:O.port,ready:O.ready,degraded:O.degraded,uiSpawnDecision:D,resolvedUiPort:A,didAutoInit:O.didAutoInit,didGitInit:O.didGitInit}}function h(r){return new n(`start`).description(`Start the knowledge base collab server`).option(`-p, --port <port>`,`Server port`,void 0).option(`-H, --host <host>`,`Server host`,void 0).option(`--open`,`Open browser after start`).option(`--no-init`,`Skip auto-scaffolding of ${t}/`).action(async n=>{let{renderBanner:i}=await import(`./banner-cxbl_Ely.mjs`),{dim:a,error:o,info:s,warning:c}=await import(`./colors-CDmFQ1jq.mjs`),l=r(),u=process.cwd();n.port!==void 0&&(l.server.port=Number(n.port)),n.host!==void 0&&(l.server.host=n.host);let d;try{d=await m({config:l,cwd:u,skipAutoInit:n.init===!1})}catch(e){let{ProjectGitInitError:t}=await import(`./src-DuGm387u.mjs`);e instanceof t&&(console.error(o(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.`)),e.stderr&&console.error(a(e.stderr.trim())),process.exit(1)),console.error(`${o(`Failed to start:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exit(1)}let f=!1,p=async e=>{if(!f){f=!0,console.log(a(`\nShutting down (${e})...`));try{await d.destroy()}catch(e){console.error(`${o(`destroy() failed:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exitCode=1}process.exit(process.exitCode??0)}};process.once(`SIGINT`,()=>{p(`SIGINT`)}),process.once(`SIGTERM`,()=>{p(`SIGTERM`)});let h=`http://${l.server.host}:${d.port}`,g=l.server.host===`0.0.0.0`||l.server.host===`::`?`http://0.0.0.0:${d.port}`:void 0,_=d.resolvedUiPort,v=_!==null&&_>0?`http://${l.server.host}:${_}`:h;console.log(i({name:`open-knowledge`,version:e,localUrl:v,apiUrl:v===h?void 0:h,networkUrl:g})),d.didAutoInit&&(console.log(` ${s(`✓`)} Scaffolded ${t}/ (first run)`),console.log(` ${a("Tip: Run `open-knowledge init` to register MCP tools for Claude Code")}\n`));let y={"shadow-repo":`Version history and branch-switch safety unavailable`,"file-watcher":`External file changes will not sync to the editor`,"head-watcher":`Git branch switches may cause document inconsistency`};d.ready.then(async()=>{if(d.degraded.length>0){console.log();for(let e of d.degraded){let t=y[e]??`${e} (check server logs for details)`;console.warn(` ${c(`⚠`)} ${c(e)}: ${a(t)}`)}console.log()}if(d.didAutoInit||d.didGitInit)if(d.didGitInit&&console.log(`\n ${s(`✓`)} Initialized git repo at ${u}/.git/ (default branch: main)`),d.didAutoInit)try{let{previewContent:e,formatPreviewBlock:t}=await import(`./preview-C5sfPOVh.mjs`),n=e({projectDir:u,contentDir:d.contentDir,include:l.content.include,exclude:l.content.exclude});console.log(`\n${t(n,u)}\n`)}catch(e){console.warn(`Content preview unavailable: ${e instanceof Error?e.message:String(e)}`)}else console.log();if(n.open){let{openBrowser:e}=await import(`./open-browser-T-bOz6ZQ.mjs`);e(v)}}).catch(e=>{console.error(` ${o(`Server initialization failed:`)} ${e instanceof Error?e.message:String(e)}`)})})}export{d as a,u as i,m as n,h as o,p as r,l as s,f as t};
2
- //# sourceMappingURL=start-B84Wdu83.mjs.map
1
+ import{i as e}from"./constants-QFqPbiZ7.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{Command as n}from"commander";import{closeSync as r,existsSync as i,mkdirSync as a,openSync as o}from"node:fs";import{join as s}from"node:path";import{spawn as c}from"node:child_process";function l(){let e=process.execPath,t=process.argv[1];return t?{command:e,prefixArgs:[t]}:(console.warn(`[self-spawn] process.argv[1] is empty — falling back to \`npx @inkeep/open-knowledge\`. This re-introduces the version-drift surface that re-exec was fixing. Observed argv: ${JSON.stringify(process.argv)}`),{command:`npx`,prefixArgs:[`@inkeep/open-knowledge`]})}function u(e){return e.uiLock?e.isAlive(e.uiLock.pid)?{action:`skip`,reason:`alive`,pid:e.uiLock.pid,port:e.uiLock.port}:{action:`spawn`,reason:`stale`,stalePid:e.uiLock.pid}:{action:`spawn`,reason:`absent`}}function d(e){i(e.lockDir)||a(e.lockDir,{recursive:!0});let t=o(s(e.lockDir,`last-spawn-error.log`),`w`),n=e.spawn??c,{PORT:u,...d}=process.env,f=l();try{let r=n(f.command,[...f.prefixArgs,...e.args??[`ui`]],{detached:!0,stdio:[`ignore`,`ignore`,t],cwd:e.cwd,env:d});return r.unref(),r}finally{try{r(t)}catch{}}}async function f(e){let t=e.now()+e.timeoutMs;for(;e.now()<t;){let t=e.readUiLock();if(t&&t.port>0)return t.port;await e.sleep(e.pollIntervalMs)}let n=e.readUiLock();return n&&n.port>0?n.port:null}function p(e){let t=e.sigtermGraceMs??1e4,n=e.sigtermPollIntervalMs??200,r=e.sleep??(e=>new Promise(t=>setTimeout(t,e)));return async()=>{try{let i=e.readUiLock();if(i&&e.isAlive(i.pid))try{e.killPid(i.pid,`SIGTERM`),e.log?.info({pid:i.pid,port:i.port},`idle-shutdown: SIGTERM UI sibling`);let a=Date.now()+t;for(;Date.now()<a&&e.isAlive(i.pid);)await r(n);if(e.isAlive(i.pid))try{e.killPid(i.pid,`SIGKILL`),e.log?.warn({pid:i.pid,graceMs:t},`idle-shutdown: SIGTERM grace expired — escalated to SIGKILL`)}catch(t){e.log?.error({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: SIGKILL failed`)}}catch(t){e.log?.warn({pid:i.pid,err:t instanceof Error?t.message:String(t)},`idle-shutdown: failed to SIGTERM UI sibling`)}}catch(t){e.log?.warn({err:t instanceof Error?t.message:String(t)},`idle-shutdown: UI lookup failed; proceeding with destroy`)}await e.destroy()}}async function m(e){let{config:n,cwd:r}=e,i=e.skipAutoInit??!1,a=e.skipUiAutoSpawn??!1,o=e.idleThresholdMs??18e5,{existsSync:s,mkdirSync:c}=await import(`node:fs`),{resolve:l}=await import(`node:path`),{bootServer:m,ensureProjectGit:h,getLogger:g,isProcessAlive:_,readUiLock:v}=await import(`./src-lFQj9tkB.mjs`),{resolveContentDir:y}=await import(`./paths-ORyeejxG.mjs`),b=e.log??g(`start`),x=y(n,r);s(x)||(c(x,{recursive:!0}),b.info({contentDir:x},`Created content directory`));let S=!s(l(r,t)),C=i?void 0:async()=>{try{let{initContent:e}=await import(`./init-D0FupYPY.mjs`),t=e(r);return S||t.created.length>0}catch(e){return console.warn(`Auto-init failed:`,e instanceof Error?e.message:e),!1}},w=!1,T=l(x,t),E=n.server.openOnAgentEdit?()=>{if(w)return;let e=v(T);if(!e||e.port<=0||!_(e.pid))return;w=!0;let t=`http://localhost:${e.port}`;import(`./open-browser-T-bOz6ZQ.mjs`).then(({openBrowser:e})=>e(t)).catch(()=>{})}:void 0,D=null,O=await m({contentDir:x,projectDir:r,contentRoot:n.content.dir,port:n.server.port,host:n.server.host,quiet:!1,debounce:n.persistence.debounceMs,maxDebounce:n.persistence.maxDebounceMs,includePatterns:n.content.include,excludePatterns:n.content.exclude,onAgentWrite:E,localOpCliArgs:[process.execPath,process.argv[1]],attachUiSibling:!0,idleShutdownMs:o,skipAutoInit:i,autoInitFn:C,ensureProjectGitFn:i?void 0:()=>h(r),spawnUiSiblingFn:async({lockDir:t})=>{if(D=u({uiLock:v(t),isAlive:_}),D.action===`spawn`&&!a)try{d({lockDir:t,cwd:r,spawn:e.spawn}),b.info({reason:D.reason},`[start] auto-spawned ok ui sibling`)}catch(e){console.warn(`[start] failed to auto-spawn ok ui: ${e instanceof Error?e.message:String(e)}`)}else D.action===`skip`&&b.info({port:D.port,pid:D.pid},`UI already running at port ${D.port}`)},idleShutdownHandler:e=>p({readUiLock:()=>v(O.lockDir),isAlive:_,killPid:(e,t)=>{process.kill(e,t)},destroy:e,log:b}),log:b});D||={action:`skip`,reason:`alive`,pid:0,port:0};let k=D,A=null;if(k.action===`skip`)A=k.port>0?k.port:null;else if(!a){let t=e.uiBindTimeoutMs??3e3;A=await f({readUiLock:()=>v(O.lockDir),now:Date.now,sleep:e=>new Promise(t=>setTimeout(t,e)),timeoutMs:t,pollIntervalMs:50}),A===null&&b.warn({timeoutMs:t},`[start] ok ui did not bind within timeout — banner falls back to API URL`)}return{httpServer:O.httpServer,destroy:O.destroy,lockDir:O.lockDir,contentDir:x,port:O.port,ready:O.ready,degraded:O.degraded,uiSpawnDecision:D,resolvedUiPort:A,didAutoInit:O.didAutoInit,didGitInit:O.didGitInit}}function h(r){return new n(`start`).description(`Start the knowledge base collab server`).option(`-p, --port <port>`,`Server port`,void 0).option(`-H, --host <host>`,`Server host`,void 0).option(`--open`,`Open browser after start`).option(`--no-init`,`Skip auto-scaffolding of ${t}/`).action(async n=>{let{renderBanner:i}=await import(`./banner-CI3--er0.mjs`),{dim:a,error:o,info:s,warning:c}=await import(`./colors-CxLEz90E.mjs`),l=r(),u=process.cwd();n.port!==void 0&&(l.server.port=Number(n.port)),n.host!==void 0&&(l.server.host=n.host);let d;try{d=await m({config:l,cwd:u,skipAutoInit:n.init===!1})}catch(e){let{ProjectGitInitError:t}=await import(`./src-lFQj9tkB.mjs`);e instanceof t&&(console.error(o(`open-knowledge requires git to initialize a parent repo. Install git or run 'git init' yourself, then re-run.`)),e.stderr&&console.error(a(e.stderr.trim())),process.exit(1)),console.error(`${o(`Failed to start:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exit(1)}let f=!1,p=async e=>{if(!f){f=!0,console.log(a(`\nShutting down (${e})...`));try{await d.destroy()}catch(e){console.error(`${o(`destroy() failed:`)} ${e instanceof Error?e.stack??e.message:String(e)}`),process.exitCode=1}process.exit(process.exitCode??0)}};process.once(`SIGINT`,()=>{p(`SIGINT`)}),process.once(`SIGTERM`,()=>{p(`SIGTERM`)});let h=`http://${l.server.host}:${d.port}`,g=l.server.host===`0.0.0.0`||l.server.host===`::`?`http://0.0.0.0:${d.port}`:void 0,_=d.resolvedUiPort,v=_!==null&&_>0?`http://${l.server.host}:${_}`:h;console.log(i({name:`open-knowledge`,version:e,localUrl:v,apiUrl:v===h?void 0:h,networkUrl:g})),d.didAutoInit&&(console.log(` ${s(`✓`)} Scaffolded ${t}/ (first run)`),console.log(` ${a("Tip: Run `open-knowledge init` to register MCP tools for Claude Code")}\n`));let y={"shadow-repo":`Version history and branch-switch safety unavailable`,"file-watcher":`External file changes will not sync to the editor`,"head-watcher":`Git branch switches may cause document inconsistency`};d.ready.then(async()=>{if(d.degraded.length>0){console.log();for(let e of d.degraded){let t=y[e]??`${e} (check server logs for details)`;console.warn(` ${c(`⚠`)} ${c(e)}: ${a(t)}`)}console.log()}if(d.didAutoInit||d.didGitInit)if(d.didGitInit&&console.log(`\n ${s(`✓`)} Initialized git repo at ${u}/.git/ (default branch: main)`),d.didAutoInit)try{let{previewContent:e,formatPreviewBlock:t}=await import(`./preview-BR34uHnQ.mjs`),n=e({projectDir:u,contentDir:d.contentDir,include:l.content.include,exclude:l.content.exclude});console.log(`\n${t(n,u)}\n`)}catch(e){console.warn(`Content preview unavailable: ${e instanceof Error?e.message:String(e)}`)}else console.log();if(n.open){let{openBrowser:e}=await import(`./open-browser-T-bOz6ZQ.mjs`);e(v)}}).catch(e=>{console.error(` ${o(`Server initialization failed:`)} ${e instanceof Error?e.message:String(e)}`)})})}export{d as a,u as i,m as n,h as o,p as r,l as s,f as t};
2
+ //# sourceMappingURL=start-C79L5QTe.mjs.map
@@ -4,4 +4,4 @@ import{i as e,o as t,t as n}from"./chunk-FK9Q3tQk.mjs";var r=n(((e,t)=>{let n=[`
4
4
  `)+`\r
5
5
  \r
6
6
  `+n)}function w(e,t,n,r,i,a){if(e.listenerCount(`wsClientError`)){let r=Error(i);Error.captureStackTrace(r,w),e.emit(`wsClientError`,r,n,t)}else C(n,r,i,a)}}));p(),d(),o(),c(),l(),m(),f();var g=t(h(),1).default;export{g as WebSocketServer};
7
- //# sourceMappingURL=wrapper-DhAZwCvI.mjs.map
7
+ //# sourceMappingURL=wrapper-BlhyhsXg.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkeep/open-knowledge",
3
- "version": "0.0.0-dev-20260424071819",
3
+ "version": "0.0.0-dev-20260424150009",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,6 +20,7 @@
20
20
  },
21
21
  "files": [
22
22
  "dist",
23
+ "scripts",
23
24
  "!dist/**/*.map"
24
25
  ],
25
26
  "engines": {
@@ -30,8 +31,11 @@
30
31
  },
31
32
  "scripts": {
32
33
  "build:cli": "tsdown",
33
- "build:assets": "cp -r ../app/dist dist/public",
34
+ "build:app": "cp -r ../app/dist dist/public",
35
+ "build:skill-asset": "mkdir -p dist/assets/skills/open-knowledge && cp ../server/assets/skills/open-knowledge/SKILL.md dist/assets/skills/open-knowledge/SKILL.md",
36
+ "build:assets": "bun run build:app && bun run build:skill-asset",
34
37
  "build": "bun run build:cli && bun run build:assets",
38
+ "postinstall": "node scripts/postinstall.mjs",
35
39
  "test": "bun test",
36
40
  "typecheck": "tsc --noEmit",
37
41
  "prepublishOnly": "bun run build && bun run test"
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `@inkeep/open-knowledge` postinstall hook.
4
+ *
5
+ * Fires `installUserSkill()` once per `npm install` / `bun install` / `npx`
6
+ * cache population. Non-fatal: any failure is swallowed so the host install
7
+ * never blocks.
8
+ *
9
+ * Spec: 2026-04-22-mcp-guidance-no-project-pollution (FR12 / D20).
10
+ */
11
+
12
+ async function run() {
13
+ let installUserSkill;
14
+ try {
15
+ // Relative import resolves inside the published npm tarball at
16
+ // <pkg-root>/dist/index.mjs — the tsdown-bundled entry that re-exports
17
+ // `installUserSkill` from @inkeep/open-knowledge-server.
18
+ const mod = await import('../dist/index.mjs');
19
+ installUserSkill = mod.installUserSkill;
20
+ } catch {
21
+ // Dev-install scenarios (e.g. running `npm install` against a tarball
22
+ // where dist/ is missing, `--ignore-scripts`, or source-only installs)
23
+ // never block — fall through to exit 0.
24
+ return;
25
+ }
26
+
27
+ if (typeof installUserSkill !== 'function') return;
28
+
29
+ let result;
30
+ try {
31
+ result = await installUserSkill();
32
+ } catch {
33
+ // installUserSkill is documented as never-throws; this catch is pure
34
+ // defensive hardening so a broken build never blocks `npm install`.
35
+ return;
36
+ }
37
+
38
+ if (result === 'installed') {
39
+ process.stdout.write('[open-knowledge] Agent Skill installed to detected agent hosts.\n');
40
+ } else if (result === 'failed') {
41
+ process.stderr.write(
42
+ '[open-knowledge] Agent Skill auto-install failed; run manually: ' +
43
+ "npx skills@~1.5.0 add <bundled-path> --agent '*' -g -y --copy\n",
44
+ );
45
+ }
46
+ // result === 'skip-current' → silent.
47
+ }
48
+
49
+ // Fire-and-forget. Always exit 0 regardless of outcome per SPEC D20 —
50
+ // `npm install` must never fail because skill-install hit an edge case.
51
+ run().finally(() => {
52
+ process.exit(0);
53
+ });
@@ -0,0 +1,100 @@
1
+ /**
2
+ * End-to-end probe: buildExecResult through the full pipeline
3
+ * (parseCommand → just-bash → extractPaths → enrichPath → dual-channel
4
+ * response). Hand-runnable — not part of the test suite.
5
+ *
6
+ * Run via: `bun run packages/cli/scripts/probe-exec.ts`
7
+ */
8
+ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
9
+ import { tmpdir } from 'node:os';
10
+ import { resolve } from 'node:path';
11
+ import { commitWip, initShadowRepo, type WriterIdentity } from '@inkeep/open-knowledge-server';
12
+ import simpleGit from 'simple-git';
13
+ import { buildExecResult, type ExecStructuredResult } from '../src/mcp/tools/exec.ts';
14
+
15
+ const root = resolve(tmpdir(), `ok-exec-probe-${Date.now()}`);
16
+ mkdirSync(root, { recursive: true });
17
+
18
+ async function main(): Promise<void> {
19
+ const git = simpleGit(root);
20
+ await git.init();
21
+ await git.raw('config', 'user.name', 'Probe');
22
+ await git.raw('config', 'user.email', 'probe@t.test');
23
+ writeFileSync(resolve(root, 'README.md'), '# probe\n');
24
+ await git.add('README.md');
25
+ await git.commit('init');
26
+
27
+ const contentDir = resolve(root, 'articles');
28
+ mkdirSync(contentDir, { recursive: true });
29
+ writeFileSync(
30
+ resolve(contentDir, 'auth.md'),
31
+ '---\ntitle: Auth\ndescription: OAuth 2.0 flow\ntags:\n - auth\n - oauth\n---\n\n# Auth\n\nOAuth is...\n',
32
+ );
33
+ writeFileSync(
34
+ resolve(contentDir, 'sso.md'),
35
+ '---\ntitle: SSO\ntags:\n - auth\n---\n\n# SSO\n\noauth provider...\n',
36
+ );
37
+
38
+ // Shadow-repo activity
39
+ const shadow = await initShadowRepo(root);
40
+ const branch = (await simpleGit(root).revparse(['--abbrev-ref', 'HEAD'])).trim();
41
+ const agent: WriterIdentity = { id: 'agent-claude-7x', name: 'Claude (Tim)', email: 'a@ok.test' };
42
+ const human: WriterIdentity = { id: 'human-tim', name: 'Tim Cardona', email: 't@ok.test' };
43
+ await commitWip(shadow, human, contentDir, 'initial auth doc', branch);
44
+ await new Promise((r) => setTimeout(r, 1100));
45
+ writeFileSync(resolve(contentDir, 'auth.md'), '# Auth v2\n\noauth rewrite.\n');
46
+ await commitWip(shadow, agent, contentDir, 'rewrite §3 oauth examples', branch);
47
+
48
+ const deps = { projectDir: root, serverUrl: undefined as string | undefined };
49
+
50
+ const runs: Array<{ label: string; cmd: string }> = [
51
+ { label: 'cat single file (rich enrichment)', cmd: 'cat articles/auth.md' },
52
+ { label: 'ls directory (slim enrichment each)', cmd: 'ls articles/' },
53
+ { label: 'grep | head pipe', cmd: 'grep -rn oauth articles/ | head -5' },
54
+ { label: 'denied: awk (unknown_command)', cmd: 'awk BEGIN{print}' },
55
+ { label: 'denied: redirection (write_blocked)', cmd: 'cat articles/auth.md > out.txt' },
56
+ { label: 'denied: subshell (shell_construct_blocked)', cmd: 'cat `ls`' },
57
+ ];
58
+
59
+ for (const { label, cmd } of runs) {
60
+ console.log('\n═══════════════════════════════════════════════════════════');
61
+ console.log(` ${label}`);
62
+ console.log(` exec(${JSON.stringify(cmd)})`);
63
+ console.log('═══════════════════════════════════════════════════════════');
64
+ const result = (await buildExecResult({ command: cmd }, deps)) as {
65
+ content: Array<{ text: string }>;
66
+ structuredContent: ExecStructuredResult;
67
+ isError?: boolean;
68
+ };
69
+ console.log(result.content[0].text.slice(0, 900));
70
+ if (result.structuredContent.error) {
71
+ console.log(`\n [error.category] ${result.structuredContent.error.category}`);
72
+ } else {
73
+ console.log(`\n [enrichedPaths] ${result.structuredContent.enrichedPaths.length} path(s)`);
74
+ for (const m of result.structuredContent.enrichedPaths) {
75
+ if ((m as { type?: string }).type === 'directory') {
76
+ const d = m as {
77
+ path: string;
78
+ recursiveMdCount: number;
79
+ childDirCount: number;
80
+ };
81
+ console.log(
82
+ ` - ${d.path}/ (directory): ${d.recursiveMdCount} md, ${d.childDirCount} subdirs`,
83
+ );
84
+ } else {
85
+ const f = m as { path: string; title?: string; historySource: unknown };
86
+ const rich = f.historySource !== null ? ' (rich)' : '';
87
+ console.log(` - ${f.path}${rich}: ${f.title ?? '(no title)'}`);
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ console.log('\n═══════════════════════════════════════════════════════════');
94
+ }
95
+
96
+ try {
97
+ await main();
98
+ } finally {
99
+ rmSync(root, { recursive: true, force: true });
100
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * End-to-end probe: buildReadResult flowing through the shared enrichPath
3
+ * → readShadowLog → shadow-repo bare git reads. Confirms agent/human
4
+ * attribution lands in the rendered output (FR15/D12/D13/R3).
5
+ *
6
+ * Run via: `bun run packages/cli/scripts/probe-read-document.ts`
7
+ * Not part of the test suite — a hand-runnable probe.
8
+ */
9
+ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
10
+ import { tmpdir } from 'node:os';
11
+ import { resolve } from 'node:path';
12
+ import {
13
+ commitUpstreamImport,
14
+ commitWip,
15
+ initShadowRepo,
16
+ type WriterIdentity,
17
+ } from '@inkeep/open-knowledge-server';
18
+ import simpleGit from 'simple-git';
19
+ import { buildReadResult } from '../src/mcp/tools/read-document.ts';
20
+
21
+ const root = resolve(tmpdir(), `ok-probe-${Date.now()}`);
22
+ mkdirSync(root, { recursive: true });
23
+
24
+ async function main(): Promise<void> {
25
+ // 1. Set up a real git-backed project
26
+ const git = simpleGit(root);
27
+ await git.init();
28
+ await git.raw('config', 'user.name', 'Probe');
29
+ await git.raw('config', 'user.email', 'probe@t.test');
30
+ writeFileSync(resolve(root, 'README.md'), '# probe\n');
31
+ await git.add('README.md');
32
+ await git.commit('init');
33
+
34
+ const contentDir = resolve(root, 'content');
35
+ mkdirSync(contentDir, { recursive: true });
36
+ writeFileSync(
37
+ resolve(contentDir, 'auth.md'),
38
+ `---
39
+ title: Auth
40
+ description: OAuth 2.0 flow for SSO
41
+ tags:
42
+ - auth
43
+ - oauth
44
+ ---
45
+
46
+ # Auth
47
+
48
+ OAuth is a protocol that...
49
+ `,
50
+ );
51
+
52
+ // 2. Initialize the shadow repo and record some activity
53
+ const shadow = await initShadowRepo(root);
54
+ const branch = (await simpleGit(root).revparse(['--abbrev-ref', 'HEAD'])).trim();
55
+
56
+ const agent: WriterIdentity = {
57
+ id: 'agent-claude-code-7x',
58
+ name: 'Claude Code (Tim)',
59
+ email: 'agent@ok.test',
60
+ };
61
+ const human: WriterIdentity = {
62
+ id: 'human-tim',
63
+ name: 'Tim Cardona',
64
+ email: 'tim@ok.test',
65
+ };
66
+
67
+ await commitWip(shadow, human, contentDir, 'initial draft of auth doc', branch);
68
+ await new Promise((r) => setTimeout(r, 1100));
69
+ writeFileSync(resolve(contentDir, 'auth.md'), '# Auth v2\n\nRewrote §3 oauth examples.\n');
70
+ await commitWip(shadow, agent, contentDir, 'rewrite §3 oauth examples', branch);
71
+ await new Promise((r) => setTimeout(r, 1100));
72
+ writeFileSync(resolve(contentDir, 'auth.md'), '# Auth v3\n\nFixed typo.\n');
73
+ await commitWip(shadow, human, contentDir, 'typo fix', branch);
74
+ await new Promise((r) => setTimeout(r, 1100));
75
+ // And a fake "upstream" git pull import
76
+ const oldHead = 'a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0';
77
+ const newHead = 'f0e1d2c3b4a5f6e7d8c9b0a1f2e3d4c5b6a7f8e9';
78
+ await commitUpstreamImport(shadow, contentDir, oldHead, newHead, branch);
79
+
80
+ // 3. Call buildReadResult — the actual MCP-tool body, end to end
81
+ const output = await buildReadResult(
82
+ { path: 'content/auth.md' },
83
+ {
84
+ projectDir: root,
85
+ serverUrl: undefined, // disk-only, no Hocuspocus → backlinkCount stays null
86
+ config: {
87
+ mcp: {
88
+ tools: {
89
+ read_document: { historyDepth: 5 },
90
+ // biome-ignore lint/suspicious/noExplicitAny: probe-only cast; full config not needed
91
+ } as any,
92
+ // biome-ignore lint/suspicious/noExplicitAny: probe-only cast
93
+ } as any,
94
+ // biome-ignore lint/suspicious/noExplicitAny: probe-only cast
95
+ } as any,
96
+ },
97
+ );
98
+
99
+ console.log('═══════════════════════════════════════════════════════════');
100
+ console.log(' end-to-end probe: buildReadResult via shadow-repo');
101
+ console.log('═══════════════════════════════════════════════════════════');
102
+ console.log(output);
103
+ console.log('═══════════════════════════════════════════════════════════');
104
+ console.log(` project root: ${root}`);
105
+ }
106
+
107
+ try {
108
+ await main();
109
+ } finally {
110
+ rmSync(root, { recursive: true, force: true });
111
+ }
@@ -1 +0,0 @@
1
- import{i as e,n as t,o as n,r}from"./colors-CEQEtnHQ.mjs";export{t as dim,r as error,e as info,n as warning};
@@ -1,2 +0,0 @@
1
- import e from"picocolors";const t=t=>e.red(t),n=t=>e.yellow(t),r=t=>e.cyan(t),i=t=>e.gray(t),a=t=>e.bold(t);function o(t,n){return e.isColorSupported?`\u001B]8;;${n}\u0007${t}\u001B]8;;\u0007`:t}export{o as a,r as i,i as n,n as o,t as r,a as t};
2
- //# sourceMappingURL=colors-CEQEtnHQ.mjs.map
@@ -1,2 +0,0 @@
1
- import"./src-CB-sXsMW.mjs";var e=`0.0.0-dev-20260424071819`;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-CXDXntb9.mjs.map
@@ -1,5 +0,0 @@
1
- import{i as e}from"./constants-CXDXntb9.mjs";import{O as t}from"./src-CB-sXsMW.mjs";import{n,t as r}from"./src-DQq7h88V.mjs";import{o as i,s as a}from"./init-QQvPB0Au.mjs";import{t as o}from"./preview-T_RVYqtF.mjs";import{t as s}from"./is-object-DVVYT5oa.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`],ee=[`@inkeep/open-knowledge`,`mcp`],te={MCP_DEBUG:`1`,OK_LOG_FILE:`/tmp/ok-mcp.log`};function E(e=process.argv[1]){if(!e)throw Error(`Cannot infer the local CLI entry for --dev-mcp because process.argv[1] is empty.`);let t=b(e);if(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 D(e={}){return e.cliPath?{command:e.cliPath,args:[`mcp`]}:e.mode===`dev`?{command:`node`,args:[E(e.cliEntryPath),`mcp`],env:{...te}}:{command:`npx`,args:[...ee]}}function O(e){return e===`win32`?S:v}function k(e={}){let t=e.platformName??process.platform,n=e.home??p(),r=e.env??process.env,i=O(t);return t===`darwin`?i.join(n,`Library`,`Application Support`):t===`win32`?r.APPDATA??i.join(n,`AppData`,`Roaming`):r.XDG_CONFIG_HOME??i.join(n,`.config`)}function A(e={}){let t=e.platformName??process.platform,n=e.home??p();return O(t).join(n,`.claude.json`)}function j(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 M(e={}){let t=e.platformName??process.platform,n=e.home??p();return O(t).join(n,`.cursor`,`mcp.json`)}function N(e={}){return O(e.platformName??process.platform).join(k(e),`Code`,`User`,`mcp.json`)}function P(e={}){let t=e.platformName??process.platform,n=e.home??p();return O(t).join(n,`.codeium`,`windsurf`,`mcp_config.json`)}function F(e={}){let t=e.platformName??process.platform,n=e.home??p();return(e.env??process.env).CODEX_HOME??O(t).join(n,`.codex`)}function I(e={}){return O(e.platformName??process.platform).join(F(e),`config.toml`)}function L(e,t){if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t))return e.length===t.length&&e.every((e,n)=>L(e,t[n]));if(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=>L(e[n],t[n]))}return!1}function R(e,t){return Object.entries(t).every(([t,n])=>L(e[t],n))}function z(e,t){return{...e,...t}}function B(e){return{...e,isCompatible(t,n,r){return R(t,e.buildEntry(n,r))},mergeManagedFields(t,n,r){return z(t,e.buildEntry(n,r))}}}const V={claude:B({id:`claude`,label:`Claude Code`,configPath:(e,t)=>A({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>_(t??p(),`.claude`),legacyProjectConfigPath:e=>_(e,`.mcp.json`),instructionsPath:e=>_(e,`CLAUDE.md`)}),"claude-desktop":B({id:`claude-desktop`,label:`Claude Desktop`,configPath:(e,t)=>j({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>h(j({home:t}))}),cursor:B({id:`cursor`,label:`Cursor`,configPath:(e,t)=>M({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>h(M({home:t})),legacyProjectConfigPath:e=>_(e,`.cursor`,`mcp.json`)}),vscode:B({id:`vscode`,label:`VS Code`,configPath:(e,t)=>N({home:t}),format:`json`,topLevelKey:`servers`,serverName:()=>e,buildEntry:(e,t)=>({type:`stdio`,...D(t)}),scope:`global`,detectPath:(e,t)=>h(N({home:t})),legacyProjectConfigPath:e=>_(e,`.vscode`,`mcp.json`)}),windsurf:B({id:`windsurf`,label:`Windsurf`,configPath:(e,t)=>P({home:t}),format:`json`,topLevelKey:`mcpServers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>h(P({home:t}))}),codex:B({id:`codex`,label:`Codex`,configPath:(e,t)=>I({home:t}),format:`toml`,topLevelKey:`mcp_servers`,serverName:()=>e,buildEntry:(e,t)=>D(t),scope:`global`,detectPath:(e,t)=>h(I({home:t})),legacyProjectConfigPath:e=>_(e,`.codex`,`config.toml`)})};function H(e){let t=e.filter(e=>!(e in V));if(t.length>0)throw Error(`Unknown editor(s): ${t.join(`, `)}. Valid options: ${T.join(`, `)}`);return e.map(e=>V[e])}function U(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 W(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 G(e,t){u(h(e),{recursive:!0}),f(e,`${JSON.stringify(t,null,2)}\n`,`utf-8`)}function K(e,t){u(h(e),{recursive:!0});let n=w(t);f(e,n.endsWith(`
2
- `)?n:`${n}\n`,`utf-8`)}const q=`0.0.1`,J=`open-knowledge-ui`;function ne(e,t={}){let n=_(e,`.claude`,`launch.json`),r=t.mode===`dev`?{name:J,runtimeExecutable:`node`,runtimeArgs:[E(t.cliEntryPath),`ui`],port:3e3}:{name:J,runtimeExecutable:`npx`,runtimeArgs:[`@inkeep/open-knowledge`,`ui`],port:3e3};try{if(!l(n))return u(h(n),{recursive:!0}),f(n,`${JSON.stringify({version:q,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===J);a>=0?i[a]=r:i.push(r);let o={...t,version:t.version??q,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 Y(e,t,n){try{return l(e.detectPath?.(t,n)??h(e.configPath(t,n)))}catch{return!1}}function X(e,t,n,r){let i=e.serverName(t),a;try{a=e.configPath(t,r)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:``,serverName:i,error:t instanceof Error?t.message:String(t)}}if(!n.skipAvailabilityCheck&&!Y(e,t,r))return{editorId:e.id,label:e.label,action:`skipped-missing`,configPath:a,serverName:i};let o;try{o=e.format===`toml`?W(a):U(a)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}let s=o[e.topLevelKey]??{},c=s[i],l;try{l=e.buildEntry(t,n)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}let u={...o,[e.topLevelKey]:{...s,[i]:l}};try{e.format===`toml`?K(a,u):G(a,u)}catch(t){return{editorId:e.id,label:e.label,action:`failed`,configPath:a,serverName:i,error:t instanceof Error?t.message:String(t)}}return{editorId:e.id,label:e.label,action:c===void 0?`written`:`overwritten`,configPath:a,serverName:i}}function re(e,t){let n=e.legacyProjectConfigPath?.(t);if(!(!n||!l(n)))return{editorId:e.id,label:e.label,path:n}}async function ie(e){let t=H(e.editors),n={mode:`published`,cliPath:e.cliPath,skipAvailabilityCheck:!0};return t.map(t=>X(t,``,n,e.home))}function ae(e,t,n){let r;try{r=e.configPath(t,n)}catch{return null}let i;try{i=e.format===`toml`?W(r):U(r)}catch{return null}let a=i[e.topLevelKey];if(!s(a))return null;let o=a[e.serverName(t)];return s(o)?o:null}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=V.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=H(e.editors??$(t,e.home)),l=c.filter(n=>Y(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(X(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?ne(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:V.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
- `)}function $(e,t){let n=[];for(let r of T)Y(V[r],e,t)&&n.push(r);return n}function oe(){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-C5sfPOVh.mjs`),{loadConfig:r}=await import(`./loader-Ck-HQgHI.mjs`),{resolveContentDir:i}=await import(`./paths-B483looM.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 a,T as c,ae as i,V as l,Q as n,X as o,oe as r,ie as s,$ as t};
5
- //# sourceMappingURL=init-BBVwEA2N.mjs.map
@@ -1 +0,0 @@
1
- import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./init-QQvPB0Au.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 +0,0 @@
1
- import{a as e,i as t,n,o as r,r as i,s as a,t as o}from"./init-BBVwEA2N.mjs";export{o as detectInstalledEditors,n as formatInitResult,i as initCommand,t as readExistingMcpEntry,e as runInit,r as writeEditorMcpConfig,a as writeUserMcpConfigs};