@inkeep/open-knowledge 0.12.0-beta.14 → 0.12.0-beta.16
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/assets/skills/discovery/SKILL.md +1 -1
- package/dist/assets/skills/project/SKILL.md +1 -1
- package/dist/cli.mjs +5 -5
- package/dist/constants-LYTkNwGp.mjs +2 -0
- package/dist/{dist-DtdRtabl.mjs → dist-D7myPw4s.mjs} +4 -4
- package/dist/{dist-kEYk7308.mjs → dist-GL5zcXSU.mjs} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/init-CQ1uWx-G.mjs +1 -0
- package/dist/{init-DAuset3t.mjs → init-mCZ3XQ1R.mjs} +4 -4
- package/dist/loader-BKje-0vK.mjs +1 -0
- package/dist/{loader-CaLEJbcQ.mjs → loader-B_EDN7s4.mjs} +2 -2
- package/dist/preview-CiO0g9mW.mjs +1 -0
- package/dist/{preview-b2rfnpjL.mjs → preview-DuxBWllB.mjs} +2 -2
- package/dist/public/assets/{index-D6s4l6eX.css → index-BXgWyDFu.css} +1 -1
- package/dist/public/assets/{index-BxMKAgUQ.js → index-CEtMQRxi.js} +73 -73
- package/dist/public/index.html +2 -2
- package/dist/{repair-launch-json-Bisx03pf.mjs → repair-launch-json-CfUZnvkR.mjs} +2 -2
- package/dist/{repair-mcp-configs-3etDglgV.mjs → repair-mcp-configs-tF1J1wYs.mjs} +2 -2
- package/dist/repair-skills-BSA3PyS7.mjs +1 -0
- package/dist/{repair-skills-BCUJOnkF.mjs → repair-skills-uHQb0hCn.mjs} +2 -2
- package/dist/{src-CmFWAq4o.mjs → src-C4WXOsUI.mjs} +2 -2
- package/dist/start-B3JYhwpU.mjs +1 -0
- package/dist/{start-MXkiMrR1.mjs → start-_DhBxzcl.mjs} +2 -2
- package/dist/{write-project-skill-BOmI_IcM.mjs → write-project-skill-DnuutHfZ.mjs} +2 -2
- package/package.json +1 -1
- package/dist/constants-BkXmZuXM.mjs +0 -2
- package/dist/init-TKxHSMWv.mjs +0 -1
- package/dist/loader-B0LEWbj7.mjs +0 -1
- package/dist/preview-CWoKWF6e.mjs +0 -1
- package/dist/repair-skills-BOGjGitt.mjs +0 -1
- package/dist/start-DiBErYZV.mjs +0 -1
|
@@ -3,7 +3,7 @@ name: open-knowledge-discovery
|
|
|
3
3
|
description: "Read when the user asks what Open Knowledge is, wants to install it on a repository, wants to share an Open Knowledge project with collaborators, or asks how `ok init` / `ok install-skill` / OK Desktop set up a project. Do NOT load to perform Open Knowledge reads/writes — the runtime guidance for editing markdown inside an initialized OK project ships as a separate project-local skill at `.claude/skills/open-knowledge/` whenever `ok init` runs. If the user appears to be editing markdown inside a `.ok/` project and this is the only OK skill loaded, advise them to re-run `ok init` to install the project-local skill."
|
|
4
4
|
compatibility: "Any agent host — no MCP server required. Pure discovery + install guidance."
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.12.0-beta.
|
|
6
|
+
version: "0.12.0-beta.16"
|
|
7
7
|
author: "Inkeep"
|
|
8
8
|
repository: "https://github.com/inkeep/open-knowledge"
|
|
9
9
|
---
|
|
@@ -3,7 +3,7 @@ name: open-knowledge
|
|
|
3
3
|
description: "MUST invoke before reading or editing any `.md` / `.mdx` file, and before any `mcp__open-knowledge__*` tool call (`exec`, `search`, `write`, `edit`, and the rest). This skill is installed into the repository by `ok init`, so its presence alone means this is an Open Knowledge project — its runtime contract governs every markdown file here, with no need to probe for a `.ok/` directory. Authoritative agent-runtime contract; supersedes the overlapping MCP server `instructions` echo."
|
|
4
4
|
compatibility: "Claude Code, Claude Desktop, Claude Cowork, Claude.ai web. Requires Open Knowledge MCP server + code execution."
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.12.0-beta.
|
|
6
|
+
version: "0.12.0-beta.16"
|
|
7
7
|
author: "Inkeep"
|
|
8
8
|
repository: "https://github.com/inkeep/open-knowledge"
|
|
9
9
|
---
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{s as e}from"./chunk-C94x7I9S.mjs";import{t}from"./esm-BLMtE3s6.mjs";import{Di as n,Ei as r,Hi as i,Ji as a,Ri as o,Sa as s,Ui as c,Wi as l,Wr as u,Xi as d,Yi as f,Zi as p,bn as m,f as h,ia as g,ji as _,n as v,s as y,sa as b,ta as x,xa as S,xr as C}from"./server-lock-BpjJj3OD-CUhVvie4.mjs";import{a as ee,n as w,r as te,t as ne}from"./gh-detect-CNO7EkgF.mjs";import{r as re}from"./git-handle--dq7Gq14-BpH0pmv5.mjs";import{Ar as ie,Bi as ae,Cn as oe,F as se,Gi as ce,Gt as le,Hi as ue,Hr as de,Ir as fe,Ji as pe,Jt as me,Mt as he,P as ge,Pn as _e,Q as ve,Qi as ye,Rn as be,T as xe,Ui as Se,Vi as Ce,Wi as we,Xi as Te,Yn as Ee,Z as De,Zi as Oe,_ as ke,_n as Ae,_t as je,at as Me,br as Ne,c as Pe,cn as Fe,ea as Ie,gr as Le,hr as Re,it as ze,ln as Be,mt as Ve,rn as He,rt as Ue,ti as We,tt as Ge,v as Ke,w as qe,wt as Je,xt as Ye,zr as T}from"./dist-
|
|
2
|
+
import{s as e}from"./chunk-C94x7I9S.mjs";import{t}from"./esm-BLMtE3s6.mjs";import{Di as n,Ei as r,Hi as i,Ji as a,Ri as o,Sa as s,Ui as c,Wi as l,Wr as u,Xi as d,Yi as f,Zi as p,bn as m,f as h,ia as g,ji as _,n as v,s as y,sa as b,ta as x,xa as S,xr as C}from"./server-lock-BpjJj3OD-CUhVvie4.mjs";import{a as ee,n as w,r as te,t as ne}from"./gh-detect-CNO7EkgF.mjs";import{r as re}from"./git-handle--dq7Gq14-BpH0pmv5.mjs";import{Ar as ie,Bi as ae,Cn as oe,F as se,Gi as ce,Gt as le,Hi as ue,Hr as de,Ir as fe,Ji as pe,Jt as me,Mt as he,P as ge,Pn as _e,Q as ve,Qi as ye,Rn as be,T as xe,Ui as Se,Vi as Ce,Wi as we,Xi as Te,Yn as Ee,Z as De,Zi as Oe,_ as ke,_n as Ae,_t as je,at as Me,br as Ne,c as Pe,cn as Fe,ea as Ie,gr as Le,hr as Re,it as ze,ln as Be,mt as Ve,rn as He,rt as Ue,ti as We,tt as Ge,v as Ke,w as qe,wt as Je,xt as Ye,zr as T}from"./dist-D7myPw4s.mjs";import{t as Xe}from"./yazl-Docqgl6q.mjs";import{n as Ze,r as Qe,t as E}from"./dist-bundle-D75dREX-.mjs";import{B as $e,C as et,E as tt,F as nt,H as rt,I as it,L as at,M as ot,N as st,P as ct,R as lt,S as ut,T as dt,V as ft,b as pt,u as mt,v as ht,w as gt,z as _t}from"./init-mCZ3XQ1R.mjs";import{a as vt,c as yt,h as bt,i as xt,l as St,m as Ct,o as wt,s as Tt,u as Et}from"./src-C4WXOsUI.mjs";import{n as Dt,t as Ot}from"./constants-LYTkNwGp.mjs";import{n as kt,t as At}from"./loader-B_EDN7s4.mjs";import{S as jt,_ as Mt,b as Nt,m as Pt,x as Ft,y as It}from"./start-_DhBxzcl.mjs";import{c as Lt,i as D,n as O,o as k,r as A,s as j,t as M}from"./colors-8SzMRIVy.mjs";import{n as Rt}from"./repair-skills-uHQb0hCn.mjs";import{execFile as zt,execSync as Bt,spawn as N,spawnSync as Vt}from"node:child_process";import{accessSync as Ht,closeSync as Ut,constants as Wt,cpSync as Gt,createWriteStream as Kt,existsSync as P,mkdirSync as F,mkdtempSync as qt,openSync as Jt,readFileSync as I,readdirSync as Yt,realpathSync as Xt,rmSync as Zt,statSync as Qt,unlinkSync as $t,writeFileSync as L}from"node:fs";import en,{basename as R,dirname as tn,join as z,relative as nn,resolve as B,sep as rn}from"node:path";import an from"node:process";import{arch as on,freemem as sn,homedir as cn,platform as ln,release as un,tmpdir as dn,totalmem as fn,type as pn,uptime as mn}from"node:os";import{fileURLToPath as hn}from"node:url";import{rm as gn}from"node:fs/promises";import{createHash as _n,randomUUID as vn}from"node:crypto";import{setTimeout as yn}from"node:timers/promises";import{promisify as bn,stripVTControlCharacters as xn,styleText as V}from"node:util";import{AsyncLocalStorage as Sn,AsyncResource as Cn}from"node:async_hooks";import*as wn from"node:readline";import{createInterface as Tn}from"node:readline/promises";const En={invalid_type:`invalid_type`,too_big:`too_big`,too_small:`too_small`,invalid_format:`invalid_format`,not_multiple_of:`not_multiple_of`,unrecognized_keys:`unrecognized_keys`,invalid_union:`invalid_union`,invalid_key:`invalid_key`,invalid_element:`invalid_element`,invalid_value:`invalid_value`,custom:`custom`};var Dn;(function(e){})(Dn||={});function On(e){return b(o,e)}async function kn(e,t,n,r){let i=An(await jn(e)).host??``,a=e=>e.replace(/[\r\n]/g,``);if(!i)return r?.log?.warn({outcome:`no-host`,backend:n.backend},`[auth] git-credential get`),1;let o=process.env.OK_GH_TOKEN,s=process.env.OK_GH_TOKEN_HOST;if(o&&s===i)return r?.log?.debug({host:i,outcome:`gh-env-token`,backend:n.backend},`[auth] git-credential get`),t.write(`username=x-access-token\npassword=${a(o)}\n`),0;let c=await n.get(i),l=r?.getDiag?.(),u=c==null?l?.kind??`absent`:`found`;if(r?.log){let e={host:i,outcome:u,backend:n.backend,...l?.error?{keychainError:l.error}:{}};u===`found`?r.log.debug(e,`[auth] git-credential get`):r.log.warn(e,`[auth] git-credential get`)}return c==null?1:(t.write(`username=${a(c.login)}\npassword=${a(c.token)}\n`),0)}function An(e){let t={};for(let n of e.split(`
|
|
3
3
|
`)){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 jn(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 Mn(e,n){let r=new t(`git-credential`);return r.description(`Git credential helper (git credential-helper protocol)`),r.command(`get`).description(`Lookup credentials from TokenStore (called by git)`).action(async()=>{let t=n?.();try{let n,r=await e({onKeychainRead:e=>{n=e},onBackendSelected:e=>{e.backend===`file`&&e.reason&&t?.warn({backend:`file`,reason:e.reason},`[auth] token storage fallback`)}}),i=await kn(process.stdin,process.stdout,r,{log:t,getDiag:()=>n});await Ae(t),process.exit(i)}catch(e){t?.error({error:e instanceof Error?e.message:String(e)},`[auth] git-credential get: unexpected error`),await Ae(t),process.exit(1)}}),r}function Nn(e){let t=e.endpoint.DEFAULTS;return/^https:\/\/(api\.)?github\.com$/.test(t.baseUrl)?`https://github.com`:t.baseUrl.replace(`/api/v3`,``)}async function Pn(e,t,n){let r={baseUrl:Nn(e),headers:{accept:`application/json`},...n},i=await e(t,r);if(`error`in i.data){let n=new Ze(`${i.data.error_description} (${i.data.error}, ${i.data.error_uri})`,400,{request:e.endpoint.merge(t,r)});throw n.response=i,n}return i}async function Fn(e){let t=e.request||E,n={client_id:e.clientId};return`scopes`in e&&Array.isArray(e.scopes)&&(n.scope=e.scopes.join(` `)),Pn(t,`POST /login/device/code`,n)}async function In(e){let t=await Pn(e.request||E,`POST /login/oauth/access_token`,{client_id:e.clientId,device_code:e.code,grant_type:`urn:ietf:params:oauth:grant-type:device_code`}),n={clientType:e.clientType,clientId:e.clientId,token:t.data.access_token,scopes:t.data.scope.split(/\s+/).filter(Boolean)};if(`clientSecret`in e&&(n.clientSecret=e.clientSecret),e.clientType===`github-app`){if(`refresh_token`in t.data){let e=new Date(t.headers.date).getTime();n.refreshToken=t.data.refresh_token,n.expiresAt=Ln(e,t.data.expires_in),n.refreshTokenExpiresAt=Ln(e,t.data.refresh_token_expires_in)}delete n.scopes}return{...t,authentication:n}}function Ln(e,t){return new Date(e+t*1e3).toISOString()}async function Rn(e,t){let n=zn(e,t.auth);if(n)return n;let{data:r}=await Fn({clientType:e.clientType,clientId:e.clientId,request:t.request||e.request,scopes:t.auth.scopes||e.scopes});await e.onVerification(r);let i=await Vn(t.request||e.request,e.clientId,e.clientType,r);return e.authentication=i,i}function zn(e,t){if(t.refresh===!0||!e.authentication)return!1;if(e.clientType===`github-app`)return e.authentication;let n=e.authentication;return(`scopes`in t&&t.scopes||e.scopes).join(` `)===n.scopes.join(` `)?n:!1}async function Bn(e){await new Promise(t=>setTimeout(t,e*1e3))}async function Vn(e,t,n,r){try{let i={clientId:t,request:e,code:r.device_code},{authentication:a}=n===`oauth-app`?await In({...i,clientType:`oauth-app`}):await In({...i,clientType:`github-app`});return{type:`token`,tokenType:`oauth`,...a}}catch(i){if(!i.response)throw i;let a=i.response.data.error;if(a===`authorization_pending`)return await Bn(r.interval),Vn(e,t,n,r);if(a===`slow_down`)return await Bn(r.interval+7),Vn(e,t,n,r);throw i}}async function Hn(e,t){return Rn(e,{auth:t})}async function Un(e,t,n,r){let i=t.endpoint.merge(n,r);if(/\/login\/(oauth\/access_token|device\/code)$/.test(i.url))return t(i);let{token:a}=await Rn(e,{request:t,auth:{type:`oauth`}});return i.headers.authorization=`token ${a}`,t(i)}var Wn=`0.0.0-development`;function Gn(e){let t=e.request||E.defaults({headers:{"user-agent":`octokit-auth-oauth-device.js/${Wn} ${Qe()}`}}),{request:n=t,...r}=e,i=e.clientType===`github-app`?{...r,clientType:`github-app`,request:n}:{...r,clientType:`oauth-app`,request:n,scopes:e.scopes||[]};if(!e.clientId)throw Error(`[@octokit/auth-oauth-device] "clientId" option must be set (https://github.com/octokit/auth-oauth-device.js#usage)`);if(!e.onVerification)throw Error(`[@octokit/auth-oauth-device] "onVerification" option must be a function (https://github.com/octokit/auth-oauth-device.js#usage)`);return Object.assign(Hn.bind(null,i),{hook:Un.bind(null,i)})}async function Kn(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=Gn({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(`./dist-bundle-BnlRWriT.mjs`)).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 qn(){return process.env.OPEN_KNOWLEDGE_GITHUB_CLIENT_ID??`Ov23liqlSd0V1MwR6rhI`}const Jn=new Set([`gitlab.com`,`bitbucket.org`,`codeberg.org`,`gitea.com`,`sr.ht`,`sourcehut.org`]);function H(e){let t=e.toLowerCase().replace(/:\d+$/,``);Jn.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 Yn(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Xn(e,t,n=Kn){let r=qn(),{host:i,json:a}=e;H(i),a||process.stderr.write(`Logging in to ${i}\n`);let o=await n({clientId:r,host:i===`github.com`?void 0:i,onVerification:e=>{e.userCode,e.verificationUri,a?Yn(!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`)}}),s=`unknown`,c,l;try{let e=i===`github.com`?`https://api.github.com`:`https://${i}/api/v3`,t=await fetch(`${e}/user`,{headers:{Authorization:`Bearer ${o.token}`,"User-Agent":`open-knowledge-cli`,Accept:`application/vnd.github+json`}});if(t.ok){let e=await t.json();s=e.login??s,c=e.name??void 0,l=e.email??void 0}}catch{}await t.set(i,s,o.token,{gitProtocol:`https`,name:c,email:l}),a?Yn(!0,{type:`complete`,host:i,login:s}):process.stderr.write(`✓ Logged in as ${s} on ${i}\n`)}function Zn(e){return new t(`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 t=>{await Xn(t,await e())})}const Qn=e=>e.name===`enter`||e.name===`return`;var $n=class extends Error{name=`AbortPromptError`;message=`Prompt was aborted`;constructor(e){super(),this.cause=e?.cause}},er=class extends Error{name=`CancelPromptError`;message=`Prompt was canceled`},tr=class extends Error{name=`ExitPromptError`},nr=class extends Error{name=`HookError`},rr=class extends Error{name=`ValidationError`};const ir=new Sn;function ar(e){return{rl:e,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function or(e,t){let n=ar(e);return ir.run(n,()=>{function e(e){n.handleChange=()=>{n.index=0,e()},n.handleChange()}return t(e)})}function U(){let e=ir.getStore();if(!e)throw new nr(`[Inquirer] Hook functions can only be called from within a prompt`);return e}function sr(){return U().rl}function cr(e){return Cn.bind((...t)=>{let n=U(),r=!1,i=n.handleChange;n.handleChange=()=>{r=!0};let a=e(...t);return r&&i(),n.handleChange=i,a})}function lr(e){let t=U(),{index:n}=t,r=e({get(){return t.hooks[n]},set(e){t.hooks[n]=e},initialized:n in t.hooks});return t.index++,r}function ur(){U().handleChange()}const dr={queue(e){let t=U(),{index:n}=t;t.hooksEffect.push(()=>{t.hooksCleanup[n]?.();let r=e(sr());if(r!=null&&typeof r!=`function`)throw new rr(`useEffect return value must be a cleanup function or nothing.`);t.hooksCleanup[n]=r})},run(){let e=U();cr(()=>{e.hooksEffect.forEach(e=>{e()}),e.hooksEffect.length=0})()},clearAll(){let e=U();e.hooksCleanup.forEach(e=>{e?.()}),e.hooksEffect.length=0,e.hooksCleanup.length=0}};function fr(e){return typeof e==`function`}function W(e){return lr(t=>{let n=Cn.bind(function(e){t.get()!==e&&(t.set(e),ur())});if(t.initialized)return[t.get(),n];let r=fr(e)?e():e;return t.set(r),[r,n]})}function pr(e,t){lr(n=>{let r=n.get();(!Array.isArray(r)||t.some((e,t)=>!Object.is(e,r[t])))&&dr.queue(e),n.set(t)})}const mr={prefix:{idle:V(`blue`,`?`),done:V(`green`,rt.tick)},spinner:{interval:80,frames:[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`].map(e=>V(`yellow`,e))},style:{answer:e=>V(`cyan`,e),message:e=>V(`bold`,e),error:e=>V(`red`,`> ${e}`),defaultAnswer:e=>V(`dim`,`(${e})`),help:e=>V(`dim`,e),highlight:e=>V(`cyan`,e),key:e=>V(`cyan`,V(`bold`,`<${e}>`))}};function hr(e){if(typeof e!=`object`||!e)return!1;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function gr(...e){let t={};for(let n of e)for(let[e,r]of Object.entries(n)){let n=t[e];t[e]=hr(n)&&hr(r)?gr(n,r):r}return t}function _r(...e){return gr(mr,...e.filter(e=>e!=null))}function vr({status:e=`idle`,theme:t}){let[n,r]=W(!1),[i,a]=W(0),{prefix:o,spinner:s}=_r(t);return pr(()=>{if(e===`loading`){let e,t=-1,n=setTimeout(()=>{r(!0),e=setInterval(()=>{t+=1,a(t%s.frames.length)},s.interval)},300);return()=>{clearTimeout(n),clearInterval(e)}}else r(!1)},[e]),n?s.frames[i]:typeof o==`string`?o:o[e===`loading`?`idle`:e]??o.idle}function yr(e){return W({current:e})[0]}function br(e){let t=yr(e);t.current=e,pr(e=>{let n=!1,r=cr((r,i)=>{n||t.current(i,e)});return e.input.on(`keypress`,r),()=>{n=!0,e.input.removeListener(`keypress`,r)}},[])}var xr=e(ft(),1);function Sr(e,t){return e.split(`
|
|
4
4
|
`).flatMap(e=>$e(e,t,{trim:!1,hard:!0}).split(`
|
|
5
5
|
`).map(e=>e.trimEnd())).join(`
|
|
@@ -19,7 +19,7 @@ import{s as e}from"./chunk-C94x7I9S.mjs";import{t}from"./esm-BLMtE3s6.mjs";impor
|
|
|
19
19
|
`),patterns:[...t],lineCount:n}}const Hi=z(cn(),`.ok`,`logs`),Ui=z(cn(),`.ok`,`bug-reports`);function Wi(e){let t=z(e,`.ok`,`config.yml`);if(P(t))try{let e=I(t,`utf8`).match(/^\s*name:\s*['"]?(.+?)['"]?\s*$/m);if(e?.[1])return e[1]}catch{}return P(z(e,`.ok`))?_n(`sha256`).update(B(e)).digest(`hex`).slice(0,12):null}function Gi(){let e={timestamp:new Date().toISOString(),platform:ln(),osType:pn(),osRelease:un(),hostname:`[redacted]`,uptime:mn(),freeMem:sn(),totalMem:fn(),nodeVersion:process.version,bunVersion:process.versions.bun??null,v8Version:process.versions.v8??null,pid:process.pid};try{e.macosVersion=Bt(`sw_vers -productVersion 2>/dev/null`,{encoding:`utf8`}).trim()}catch{}try{let t=z(__dirname,`..`,`..`,`package.json`);P(t)&&(e.okVersion=JSON.parse(I(t,`utf8`)).version)}catch{}return e}function Ki(e){if(!P(Hi))return{files:[],dir:Hi};let t=Yt(Hi).filter(e=>e.endsWith(`.log`)||/\.log\.\d+$/.test(e)).map(e=>z(Hi,e));if(e&&t.length>0){let n=t.filter(t=>{try{return I(t,`utf8`).includes(`"project":"${e}"`)}catch{return!0}});n.length>0&&(t=n)}return{files:t,dir:Hi}}function qi(e){let t=z(e,`.ok`,`local`);return P(t)?{files:[`server.lock`,`last-spawn-error.log`].map(e=>z(t,e)).filter(e=>P(e)),dir:t}:{files:[],dir:null}}function Ji(e){let t=z(e,`.ok`,`local`,`logs`);return P(t)?{files:[`server-current.jsonl`,`server-prev.jsonl`].map(e=>z(t,e)).filter(e=>P(e)),dir:t}:{files:[],dir:null}}async function Yi(t){let n=Cu();F(Ui,{recursive:!0});let r=z(Ui,`${new Date().toISOString().replace(/[:.]/g,`-`)}-bugreport.zip`);n?.info({projectSlug:t.projectSlug},`gathering diagnostic data`);let i=Gi(),{files:a}=Ki(t.projectSlug),{files:o}=qi(t.cwd),{files:s}=Ji(t.cwd);n?.info({logFileCount:a.length,lockFileCount:o.length,localSinkFileCount:s.length},`files collected`);let c=[],l=[],{ZipFile:u}=await import(`./yazl-CQSNnbvt.mjs`).then(t=>e(t.default,1)),d=new u;for(let e of a)try{let{redacted:t,patterns:n,lineCount:r}=Vi(I(e,`utf8`)),i=`logs/${R(e)}`;d.addBuffer(Buffer.from(t,`utf8`),i),l.push(i),n.length>0&&c.push({file:i,lineCount:r,patterns:n})}catch{}for(let e of o)try{let{redacted:t,patterns:n,lineCount:r}=Vi(I(e,`utf8`)),i=`lockdir/${R(e)}`;d.addBuffer(Buffer.from(t,`utf8`),i),l.push(i),n.length>0&&c.push({file:i,lineCount:r,patterns:n})}catch{}for(let e of s)try{let{redacted:t,patterns:n,lineCount:r}=Vi(I(e,`utf8`)),i=`local-logs/${R(e)}`;d.addBuffer(Buffer.from(t,`utf8`),i),l.push(i),n.length>0&&c.push({file:i,lineCount:r,patterns:n})}catch{}let f=JSON.stringify(i,null,2);d.addBuffer(Buffer.from(f,`utf8`),`sysinfo.json`),l.push(`sysinfo.json`);let p={generatedAt:new Date().toISOString(),disciplineVersion:`1.0.0`,projectSlug:t.projectSlug,files:l,redactions:c,sysinfo:i};d.addBuffer(Buffer.from(JSON.stringify(p,null,2),`utf8`),`MANIFEST.json`);let m=c.reduce((e,t)=>e+t.lineCount,0),h=[`# Bug Report Bundle`,``,`Generated: ${p.generatedAt}`,`Project: ${t.projectSlug??`(unscoped)`}`,`Discipline version: ${p.disciplineVersion}`,``,`## Contents`,``,...l.map(e=>`- ${e}`),``,`## Privacy`,``,`This bundle was auto-redacted before packaging.`,`Patterns checked: ${Bi.join(`, `)}`,m>0?`${m} line(s) were scrubbed across ${c.length} file(s).`:`No redactions were needed.`,`See MANIFEST.json for the full redaction audit report.`,``,`This bundle is safe to attach to a GitHub issue.`].join(`
|
|
20
20
|
`);d.addBuffer(Buffer.from(h,`utf8`),`README.md`),d.end();let g=Kt(r);if(d.outputStream.pipe(g),await new Promise((e,t)=>{g.on(`close`,e),g.on(`error`,t)}),n?.info({bundlePath:r,fileCount:l.length,redactionCount:m},`bundle written`),process.stdout.write(`${r}\n`),m>0&&process.stderr.write(`ok bug-report: ${m} line(s) auto-redacted across ${c.length} file(s)\n`),!t.noReveal&&ln()===`darwin`)try{N(`/usr/bin/open`,[`-R`,r],{detached:!0,stdio:`ignore`}).unref()}catch{}return r}function Xi(){return new t(`bug-report`).description(`Generate a diagnostic bundle for bug reporting`).option(`--reveal`,`Reveal the bundle in Finder (default: true)`,!0).option(`--no-reveal`,`Do not reveal the bundle in Finder`).action(async e=>{let t=process.cwd(),n=Wi(t);try{await Yi({projectSlug:n,cwd:t,noReveal:!e.reveal})}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`ok bug-report: failed — ${t}\n`),process.exitCode=1}})}function Zi(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 Qi(e){let t=e.inspect??(t=>bt(e.lockDir,t)),n=e.unlink??(e=>$t(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=Zi(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 $i(e){return new t(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{e(),Qi({lockDir:T(process.cwd())}).failed.length>0&&(process.exitCode=1)})}async function ea(e,t,n={},r=ne){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`]}}async function ta(e,t,n=fetch){let r=new AbortController,i=setTimeout(()=>r.abort(),5e3);try{return(await n(`https://api.github.com/repos/${encodeURIComponent(e)}/${encodeURIComponent(t)}`,{signal:r.signal,headers:{"User-Agent":`open-knowledge-cli`,Accept:`application/vnd.github+json`}})).status===200}catch{return!1}finally{clearTimeout(i)}}const na=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function ra(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 na)if(n.includes(e))return{stage:t[1],pct:Math.round(i+r/100*(a-i))};return null}function q(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}function ia(e=process.env){let t={};for(let[n,r]of Object.entries(e))r!==void 0&&(t[n]=r);return t.GIT_TERMINAL_PROMPT=`0`,t.LANG=`C`,t.LC_ALL=`C`,t}function aa(e){return typeof e!=`string`||e.length===0?[`--progress`]:[`--progress`,`-b`,e]}const oa=u;async function sa(e){try{return await e.clone(aa(e.branch)),{fellBack:!1}}catch(t){if(e.branch!==null&&oa(t))return e.onFallback(e.branch),await e.clone(aa(null)),{fellBack:!0};throw t}}function ca(e,t,n){return e===`https`&&t===`github.com`&&n}async function la(e,t,n,r=process.cwd()){let i=Ct(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=t.dir?B(r,t.dir):B(r,i.name);if(P(a)&&Yt(a).length>0)throw Error(`Target directory is not empty: ${a}`);let o=ee(),s=i.protocol===`https`&&i.hostname===`github.com`?await ta(i.owner,i.name):!1,c=ca(i.protocol,i.hostname,s)?{tier:`none`,credentialArgs:[]}:await ea(i.hostname,o,{}),l=ia(),u=re({baseDir:r,config:c.credentialArgs.length>=2?[c.credentialArgs[1]]:[],unsafe:{allowUnsafeCredentialHelper:!0}}).env(l),d=-1;u.outputHandler((e,n,r)=>{r.on(`data`,e=>{let n=e.toString(`utf-8`);for(let e of n.split(`
|
|
21
21
|
`)){let n=ra(e);n&&n.pct!==d&&(d=n.pct,q(t.json,{type:`progress`,pct:n.pct,stage:n.stage}),t.json||process.stderr.write(`\r Cloning ${n.pct}%`))}})}),await sa({branch:typeof t.branch==`string`&&t.branch.length>0?t.branch:null,clone:t=>u.clone(e,a,t),onFallback:e=>{q(t.json,{type:`branch-fallback`,branch:e}),t.json||process.stderr.write(`\n Branch '${e}' not found upstream — cloning default branch instead.\n`)}}),t.json||process.stderr.write(`
|
|
22
|
-
`);try{let{runInit:e}=await import(`./init-
|
|
22
|
+
`);try{let{runInit:e}=await import(`./init-CQ1uWx-G.mjs`),n=await e({cwd:a,mcp:!1});if(n.contentUpdated.length>0){let e=`auto-init: updated ${n.contentUpdated.join(`, `)}`;t.json?q(!0,{type:`warning`,message:e}):process.stderr.write(` ${e}\n`)}}catch(e){let n=e instanceof Error?e.message:String(e);t.json?q(!0,{type:`warning`,message:`auto-init: ${n}`}):process.stderr.write(` auto-init: ${n}\n`)}try{ua(a)}catch(e){let n=e instanceof Error?e.message:String(e);t.json?q(!0,{type:`warning`,message:`git-exclude: ${n}`}):process.stderr.write(` git-exclude: ${n}\n`)}return a}function ua(e){let t=pt(e,[`.ok/`]);return t.kind===`no-exclude`?`no-exclude`:t.kind===`refused-tracked`?`already-present`:t.appended.length>0?`appended`:`already-present`}function da(e){return new t(`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).option(`-b, --branch <branch>`,`Branch to check out (falls back to default if missing)`).action(async(t,n,r)=>{let i=e();try{let a=await la(t,{json:r.json,dir:n,branch:r.branch??null},i);if(r.json)q(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-B3JYhwpU.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?q(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}var fa=s();const pa=[[`sync`],[`persistence`,`debounceMs`],[`persistence`,`maxDebounceMs`],[`server`,`port`],...n.map(e=>e.path)];function ma(e={}){let t=e.log??(e=>console.error(e)),n=e.error??(e=>console.error(e)),r=e.loadConfigFn??kt;try{let{sources:n}=r(e.cwd);return t(`✓ Configuration valid (sources: ${n.length===0?`defaults only`:n.join(`, `)})`),{ok:!0}}catch(e){return n(e instanceof Error?e.message:String(e)),{ok:!1}}}function ha(e){let t=(0,fa.parseDocument)(I(e,`utf-8`));if(t.errors.length>0)throw Error(`Could not parse ${e}: ${t.errors.map(e=>e.message).join(`; `)}`);let n=[];for(let e of pa)t.hasIn(e)&&n.push(e.join(`.`));return n}function ga(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function _a(e){let t={};for(let n of e){let e=t;for(let t=0;t<n.length-1;t++){let r=n[t],i=e[r],a=ga(i)?i:{};e[r]=a,e=a}e[n[n.length-1]]=null}return t}async function va(e={}){let t=e.log??(e=>console.log(e)),n=e.error??(e=>console.error(e)),r=e.scope??`both`,i=e.dryRun??!1,a=e.cwd??process.cwd(),o=e.writeConfigPatchFn??Te,s=[];(r===`project`||r===`both`)&&s.push({scope:`project`,absPath:pe(`project`,a,e.homedirOverride)}),(r===`user`||r===`both`)&&s.push({scope:`user`,absPath:pe(`user`,a,e.homedirOverride)});let c=[],l=!0;for(let{scope:t,absPath:n}of s){if(!P(n)){c.push({path:n,scope:t,found:[],removed:[]});continue}let r;try{r=ha(n)}catch(e){let r=e instanceof Error?e.message:String(e);c.push({path:n,scope:t,found:[],removed:[],error:r}),l=!1;continue}if(r.length===0||i){c.push({path:n,scope:t,found:r,removed:[]});continue}let s=await o({cwd:a,scope:t,patch:_a(pa.filter(e=>r.includes(e.join(`.`)))),homedirOverride:e.homedirOverride});if(!s.ok){c.push({path:n,scope:t,found:r,removed:[],error:_(s.error)}),l=!1;continue}c.push({path:n,scope:t,found:r,removed:r})}for(let e of c)e.error&&n(`✗ ${e.path}: ${e.error}`);let u=c.some(e=>e.error!==void 0),d=c.reduce((e,t)=>e+t.found.length,0);if(d===0&&!u)t(`No deprecated fields found.`);else if(d>0)for(let e of c)e.error||(e.found.length===0?t(` ${e.path}: no deprecated fields`):t(i?`[dry-run] ${e.path}: would remove ${e.found.length} field(s): ${e.found.join(`, `)}`:`✓ ${e.path}: removed ${e.removed.length} field(s): ${e.removed.join(`, `)}`));return{outcomes:c,ok:l}}function ya(){let e=new t(`config`).description(`Inspect and maintain Open Knowledge configuration files`);return e.command(`validate`).description(`Validate the merged config (defaults → user → project)`).action(()=>{ma({}).ok||(process.exitCode=1)}),e.command(`migrate`).description(`Remove deprecated config fields from config.yml idempotently (every removed key in the registry — content.*, folders, appearance.editorModeDefault, server.host, etc. — plus the silently-dropped sync.*, persistence.*, server.port)`).option(`--scope <scope>`,`Which scope to migrate: project | user | both`,`both`).option(`--dry-run`,`Preview without writing`,!1).action(async e=>{let t=e.scope;if(t!==`project`&&t!==`user`&&t!==`both`){console.error(`Invalid --scope: ${t}. Expected: project | user | both`),process.exitCode=2;return}(await va({scope:t,dryRun:e.dryRun})).ok||(process.exitCode=1)}),e}var ba=e(Xe(),1),J=e(Lt(),1);const xa=new Set([`doc.name`]);function Sa(e){return`doc:${_n(`blake2b512`,{outputLength:32}).update(e).digest(`hex`).slice(0,8)}`}function Ca(e,t,n){let r=e.docNameMap[n];if(r===void 0){e.docNameMap[n]=t;return}if(r===t)return;let i=e.docNameCollisions[n];i?i.includes(t)||i.push(t):e.docNameCollisions[n]=[t]}function wa(e,t){let n=t.originalToHashed.get(e);if(n!==void 0)return n;let r=Sa(e);return t.originalToHashed.set(e,r),Ca(t,e,r),r}function Ta(e,t){return t.length===0||!e.includes(t)?e:e.split(t).join(`<CONTENT_DIR>`)}function Ea(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Da(e,t){if(typeof e==`string`)return Ta(e,t.contentDir);if(Array.isArray(e))return e.map(e=>Da(e,t));if(!Ea(e))return e;let n=typeof e.key==`string`&&xa.has(e.key)&&Ea(e.value)&&typeof e.value.stringValue==`string`?e.value.stringValue:null,r={};for(let[i,a]of Object.entries(e))if(n!==null&&i===`value`&&Ea(a)){let e=wa(n,t);r[i]={...a,stringValue:e}}else xa.has(i)&&typeof a==`string`?r[i]=wa(a,t):r[i]=Da(a,t);return r}function Oa(e,t){if(t.originalToHashed.size===0)return e;let n=Array.from(t.originalToHashed.entries()).sort(([e],[t])=>t.length-e.length),r=e;for(let[e,t]of n)e.length!==0&&r.includes(e)&&(r=r.split(e).join(t));return r}function ka(e,t){let n=I(e,`utf-8`);if(n.length===0)return;let r=n.endsWith(`
|
|
23
23
|
`),i=n.split(`
|
|
24
24
|
`),a=[];for(let e=0;e<i.length;e++){let n=i[e]??``;if(!(e===i.length-1&&n===``)){if(n.length===0){a.push(``);continue}try{let e=Da(JSON.parse(n),t);a.push(JSON.stringify(e))}catch{a.push(n)}}}L(e,r?`${a.join(`
|
|
25
25
|
`)}\n`:a.join(`
|
|
@@ -49,7 +49,7 @@ ws.addEventListener('error', () => process.exit(1));
|
|
|
49
49
|
setTimeout(() => process.exit(2), ${t+1e4});
|
|
50
50
|
`),r}async function Lo(e,t,n,r,i){let a=Io(e,t,z(r,`cpu.cpuprofile`)),o=!1,s=N(process.execPath,[a],{stdio:`ignore`}),c=setInterval(()=>{let e=Mo(n);e&&i(e)},1e3);await new Promise(e=>{s.once(`close`,t=>{o=t===0,e()}),setTimeout(()=>{s.kill(),e()},t+12e3)}),clearInterval(c);try{Zt(z(a,`..`),{recursive:!0,force:!0})}catch{}return o}function Ro(e){let t;try{t=JSON.parse(e)}catch{return`(could not parse profile)`}let n=new Map(t.nodes.map(e=>[e.id,e])),r=new Map;for(let e of t.nodes)for(let t of e.children??[])r.set(t,e.id);let i=new Map;for(let e of t.samples??[])i.set(e,(i.get(e)??0)+1);let a=t.samples?.length??0,o=t.endTime!=null&&t.startTime!=null?((t.endTime-t.startTime)/1e3).toFixed(2):`?`,s=[...i.entries()].sort((e,t)=>t[1]-e[1]).slice(0,10),c=[`samples ${a} duration_ms ${o}`,``,`Top leaf nodes`];for(let[e,t]of s){let r=n.get(e);if(!r)continue;let i=a>0?(t/a*100).toFixed(1):`0.0`,{functionName:o,url:s,lineNumber:l,columnNumber:u}=r.callFrame;c.push(` ${t} ${i}% id=${e} ${o||`(anonymous)`} ${s}:${l}:${u} hit=${r.hitCount??0}`)}c.push(``,`Top stacks`);let l=e=>{let t=[],i=e;for(;i!=null;){let e=n.get(i);if(!e)break;let{functionName:a,url:o,lineNumber:s,columnNumber:c}=e.callFrame;t.unshift(` ${a||`(anonymous)`} ${o} ${s} ${c}`),i=r.get(i)}return t};for(let[e,t]of s.slice(0,5)){let n=a>0?(t/a*100).toFixed(1):`0.0`;c.push(``,`--- ${t} ${n}%`,...l(e))}return c.join(`
|
|
51
51
|
`)}async function zo(e,t={}){let{pid:n,cpuProfileSecs:r=15,noInspector:i=!1}=e,a=t.log??(e=>console.log(e)),o=t.discover??yt,s=t.inspect??bt,c=t.resolveCommand??St,l=t.resolveUsage??Et,u=t.collectLsofFn??No,d=t.getEndpoints??Fo,f=t.profiler??Lo,p=t.isAlive??(e=>{try{return process.kill(e,0),!0}catch(e){return e.code===`EPERM`}}),m=t.sendSignal??((e,t)=>{process.kill(e,t)}),h=t.sleep??(e=>new Promise(t=>setTimeout(t,e))),g=r*1e3;if(!p(n)){a(J.default.red(`No process with pid ${n} found.`));return}let _=await o(),v=null,y=null;for(let e of _){let t=s(e,`server`);if(t.status!==`missing`&&t.status!==`corrupt`&&t.lock.pid===n){v=t.lock.worktreeRoot,y={lockDir:e,state:t.status,lockPath:t.lockPath,lock:t.lock};break}}let b=new Date().toISOString().replace(/[:.]/g,`-`),x=e.output?e.output:v?z(v,`.ok`,`local`,`diagnostics`,`process-${n}-${b}`):z(process.cwd(),`ok-diagnose-${n}-${b}`);try{F(x,{recursive:!0})}catch(e){a(J.default.red(`Cannot create output directory ${x}: ${e.message}`));return}a(J.default.bold(`Diagnosing pid ${n}`)),a(`Output: ${x}`),a(``);let S=(e,t)=>{L(z(x,e),t),a(` wrote ${e}`)},C=c(n),ee=l(n);S(`metadata.json`,JSON.stringify({capturedAt:new Date().toISOString(),pid:n,command:C,usage:ee,lockInfo:y},null,2)),a(` sampling lsof`);let w=u(n);if(w&&S(`lsof.txt`,w),!i){let e=w?Po(w).find(e=>e>=9229&&e<=9299)??9229:9229,t=d(e);if(!t||t.length===0){a(` no inspector on :${e}, sending SIGUSR1 to pid ${n}`);try{m(n,`SIGUSR1`),await h(2e3),t=d(e)}catch(e){a(J.default.yellow(` SIGUSR1 delivery failed: ${e.message}`))}}if(t&&t.length>0){S(`inspector-endpoints.json`,JSON.stringify(t,null,2));let e=t[0].webSocketDebuggerUrl;if(e){a(` capturing ${r}s CPU profile`);let t=[];await f(e,g,n,x,e=>t.push(e))?a(` wrote cpu.cpuprofile`):a(J.default.yellow(` CPU profile capture failed`)),t.length>0&&S(`process-stats.jsonl`,`${t.map(e=>JSON.stringify(e)).join(`
|
|
52
|
-
`)}\n`);try{S(`stacks.txt`,Ro(I(z(x,`cpu.cpuprofile`),`utf-8`)))}catch(e){a(J.default.yellow(` stacks.txt skipped: ${e.message}`))}}}else a(J.default.yellow(` Node inspector unavailable — skipping CPU profile`))}a(``),a(J.default.yellow(`⚠ Before sharing, review what each file contains:`)),a(` metadata.json — content directory paths, lock file locations, CPU/MEM at capture time`),a(` lsof.txt — all open files, network connections, and private paths for this process`),a(` inspector-endpoints.json — Node debugger metadata (titles, URLs)`),a(` cpu.cpuprofile — function names and source file paths from your Node process`),a(` stacks.txt — call stacks derived from cpu.cpuprofile; includes source paths`),a(` process-stats.jsonl — CPU/MEM/RSS numbers only; safe to share`),a(``),a(`Bundle: ${J.default.bold(x)}`)}async function Bo(e){let t=Tn({input:process.stdin,output:process.stdout});try{return(await t.question(e)).trim()}finally{t.close()}}async function Vo(e){let t=qt(z(dn(),`ok-bundle-process-`));return await zo({pid:e,output:t}),t}function Ho(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MB`:`${(n/1024).toFixed(1)} GB`}function Uo(e){let t=e.trim().toLowerCase();return t===`y`||t===`yes`}function Wo(e,t,n){let{summary:r,manifest:i}=t;e(``),e(J.default.bold(`ok diagnose bundle — content summary`)),e(``),e(` Files: ${r.fileCount}`),e(` Total size: ${Ho(r.totalBytes)} uncompressed`),e(` doc.name attributes: ${r.docNameCount} occurrence(s) in telemetry${r.redacted?` (values hashed)`:``}`),e(` Content-dir path: ${r.contentDirVisible?`visible (${i.contentDir.absolutePath})`:`not visible`}`),e(` Redacted: ${r.redacted?`yes`:`no`}`),e(` Server status: ${i.serverStatus}`),e(` Output: ${n}`),e(``)}async function Go(e,t={}){let n=t.log??(e=>console.log(e)),r=t.prompt??Bo,i=t.runProcessDiagnose??Vo,a=t.now??(()=>new Date),o;if(e.out!==void 0){o=e.out;let t=tn(o);if(!P(t))throw Error(`ok diagnose bundle: --out parent directory does not exist: ${t}. Create it first.`)}else{let t=a().toISOString().replace(/[:.]/g,`-`),n=z(e.contentDir,`.ok`,`local`,`diagnostics`);F(n,{recursive:!0}),o=z(n,`bundle-${t}.zip`)}let s;e.pid!==void 0&&(n(J.default.dim(`Running ok diagnose process ${e.pid} into a temp dir`)),s=await i(e.pid));let c=await lo({contentDir:e.contentDir,projectDir:e.projectDir,processDir:s,redact:e.redact===!0,deps:t.collectDeps});try{return c.manifest.serverStatus===`not-running`&&n(J.default.yellow(` server not running — live state unavailable`)),Wo(n,c,o),e.yes!==!0&&!Uo(await r(`Write bundle? [y/N]: `))?(n(J.default.dim(`Aborted; no bundle written.`)),{outputPath:null,declined:!0}):(await uo({collected:c,outputPath:o}),n(J.default.bold(`Bundle: ${o}`)),{outputPath:o,declined:!1})}finally{if(c.cleanup(),s!==void 0)try{Zt(s,{recursive:!0,force:!0})}catch{}}}function Ko(){let e=new t(`diagnose`).description(`Diagnostic utilities for open-knowledge processes`);return e.command(`process`).description(`Capture a diagnostic bundle (metadata, lsof, CPU profile) for a running process`).argument(`<pid>`,`Process ID to diagnose`).option(`--cpu-profile <seconds>`,`CPU profile duration (default: 15)`,`15`).option(`--output <dir>`,`Output directory`).option(`--no-inspector`,`Collect metadata only; skip Node inspector and CPU profile`).action(async(e,t)=>{let n=Number.parseInt(e,10);(Number.isNaN(n)||n<=0)&&(console.error(J.default.red(`Invalid pid '${e}': must be a positive integer`)),process.exit(1));let r=Number.parseInt(t.cpuProfile,10);(Number.isNaN(r)||r<=0)&&(console.error(J.default.red(`--cpu-profile must be a positive integer`)),process.exit(1)),await zo({pid:n,cpuProfileSecs:r,output:t.output,noInspector:!t.inspector})}),e.addCommand(jo()),e.command(`bundle`).description(`Capture a support bundle (telemetry + logs + server state) into a zip suitable for bug reports`).option(`--pid <pid>`,"Include `ok diagnose process <pid>` output under process/ in the bundle").option(`--out <path>`,`Write the zip to this path instead of the default location`).option(`--yes`,`Skip the y/N prompt`).option(`--redact`,`Hash doc names and strip the content-dir prefix from the staged bundle`).action(async e=>{let t;e.pid!==void 0&&(t=Number.parseInt(e.pid,10),(Number.isNaN(t)||t<=0)&&(console.error(J.default.red(`Invalid --pid '${e.pid}': must be a positive integer`)),process.exit(1)));try{let{loadConfig:n}=await import(`./loader-
|
|
52
|
+
`)}\n`);try{S(`stacks.txt`,Ro(I(z(x,`cpu.cpuprofile`),`utf-8`)))}catch(e){a(J.default.yellow(` stacks.txt skipped: ${e.message}`))}}}else a(J.default.yellow(` Node inspector unavailable — skipping CPU profile`))}a(``),a(J.default.yellow(`⚠ Before sharing, review what each file contains:`)),a(` metadata.json — content directory paths, lock file locations, CPU/MEM at capture time`),a(` lsof.txt — all open files, network connections, and private paths for this process`),a(` inspector-endpoints.json — Node debugger metadata (titles, URLs)`),a(` cpu.cpuprofile — function names and source file paths from your Node process`),a(` stacks.txt — call stacks derived from cpu.cpuprofile; includes source paths`),a(` process-stats.jsonl — CPU/MEM/RSS numbers only; safe to share`),a(``),a(`Bundle: ${J.default.bold(x)}`)}async function Bo(e){let t=Tn({input:process.stdin,output:process.stdout});try{return(await t.question(e)).trim()}finally{t.close()}}async function Vo(e){let t=qt(z(dn(),`ok-bundle-process-`));return await zo({pid:e,output:t}),t}function Ho(e){if(e<1024)return`${e} B`;let t=e/1024;if(t<1024)return`${t.toFixed(1)} KB`;let n=t/1024;return n<1024?`${n.toFixed(1)} MB`:`${(n/1024).toFixed(1)} GB`}function Uo(e){let t=e.trim().toLowerCase();return t===`y`||t===`yes`}function Wo(e,t,n){let{summary:r,manifest:i}=t;e(``),e(J.default.bold(`ok diagnose bundle — content summary`)),e(``),e(` Files: ${r.fileCount}`),e(` Total size: ${Ho(r.totalBytes)} uncompressed`),e(` doc.name attributes: ${r.docNameCount} occurrence(s) in telemetry${r.redacted?` (values hashed)`:``}`),e(` Content-dir path: ${r.contentDirVisible?`visible (${i.contentDir.absolutePath})`:`not visible`}`),e(` Redacted: ${r.redacted?`yes`:`no`}`),e(` Server status: ${i.serverStatus}`),e(` Output: ${n}`),e(``)}async function Go(e,t={}){let n=t.log??(e=>console.log(e)),r=t.prompt??Bo,i=t.runProcessDiagnose??Vo,a=t.now??(()=>new Date),o;if(e.out!==void 0){o=e.out;let t=tn(o);if(!P(t))throw Error(`ok diagnose bundle: --out parent directory does not exist: ${t}. Create it first.`)}else{let t=a().toISOString().replace(/[:.]/g,`-`),n=z(e.contentDir,`.ok`,`local`,`diagnostics`);F(n,{recursive:!0}),o=z(n,`bundle-${t}.zip`)}let s;e.pid!==void 0&&(n(J.default.dim(`Running ok diagnose process ${e.pid} into a temp dir`)),s=await i(e.pid));let c=await lo({contentDir:e.contentDir,projectDir:e.projectDir,processDir:s,redact:e.redact===!0,deps:t.collectDeps});try{return c.manifest.serverStatus===`not-running`&&n(J.default.yellow(` server not running — live state unavailable`)),Wo(n,c,o),e.yes!==!0&&!Uo(await r(`Write bundle? [y/N]: `))?(n(J.default.dim(`Aborted; no bundle written.`)),{outputPath:null,declined:!0}):(await uo({collected:c,outputPath:o}),n(J.default.bold(`Bundle: ${o}`)),{outputPath:o,declined:!1})}finally{if(c.cleanup(),s!==void 0)try{Zt(s,{recursive:!0,force:!0})}catch{}}}function Ko(){let e=new t(`diagnose`).description(`Diagnostic utilities for open-knowledge processes`);return e.command(`process`).description(`Capture a diagnostic bundle (metadata, lsof, CPU profile) for a running process`).argument(`<pid>`,`Process ID to diagnose`).option(`--cpu-profile <seconds>`,`CPU profile duration (default: 15)`,`15`).option(`--output <dir>`,`Output directory`).option(`--no-inspector`,`Collect metadata only; skip Node inspector and CPU profile`).action(async(e,t)=>{let n=Number.parseInt(e,10);(Number.isNaN(n)||n<=0)&&(console.error(J.default.red(`Invalid pid '${e}': must be a positive integer`)),process.exit(1));let r=Number.parseInt(t.cpuProfile,10);(Number.isNaN(r)||r<=0)&&(console.error(J.default.red(`--cpu-profile must be a positive integer`)),process.exit(1)),await zo({pid:n,cpuProfileSecs:r,output:t.output,noInspector:!t.inspector})}),e.addCommand(jo()),e.command(`bundle`).description(`Capture a support bundle (telemetry + logs + server state) into a zip suitable for bug reports`).option(`--pid <pid>`,"Include `ok diagnose process <pid>` output under process/ in the bundle").option(`--out <path>`,`Write the zip to this path instead of the default location`).option(`--yes`,`Skip the y/N prompt`).option(`--redact`,`Hash doc names and strip the content-dir prefix from the staged bundle`).action(async e=>{let t;e.pid!==void 0&&(t=Number.parseInt(e.pid,10),(Number.isNaN(t)||t<=0)&&(console.error(J.default.red(`Invalid --pid '${e.pid}': must be a positive integer`)),process.exit(1)));try{let{loadConfig:n}=await import(`./loader-BKje-0vK.mjs`),{resolveContentDir:r}=await import(`./dist-GL5zcXSU.mjs`),i=process.cwd(),{config:a}=n(i);await Go({contentDir:r(a,i),projectDir:i,pid:t,out:e.out,yes:e.yes===!0,redact:e.redact===!0})}catch(e){let t=e instanceof Error?e.message:String(e);console.error(J.default.red(t)),process.exit(1)}}),e}async function qo(){if(!process.stdin.isTTY){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString(`utf-8`).trim()}return(await Nr({message:`Enter OpenAI embeddings API key:`})).trim()}function Jo(e){return Ne(e)}async function Yo(){return(await He()).file?{present:!0,source:`file`}:process.env.OK_EMBEDDINGS_API_KEY?{present:!0,source:`env`}:{present:!1,source:null}}async function Xo(e){try{let t=h(T(e));if(!t||t.port<=0||!y(t.pid))return null;let n=await fetch(`http://127.0.0.1:${t.port}/api/semantic-status`,{signal:AbortSignal.timeout(1500)});if(!n.ok)return null;let r=await n.json();return typeof r.embedded!=`number`||typeof r.total!=`number`?null:{embedded:r.embedded,total:r.total}}catch{return null}}function Zo(){return new t(`set-key`).description(`Store your OpenAI embeddings API key in ~/.ok/secrets.yml`).action(async()=>{let e=await qo();if(!e){process.stderr.write(`No key provided.
|
|
53
53
|
`),process.exitCode=1;return}await le().set(e),process.stderr.write(`✓ OpenAI embeddings API key stored in ~/.ok/secrets.yml (0600, this machine only).
|
|
54
54
|
Now enable it per project — the easiest path is OK Desktop → Settings → This
|
|
55
55
|
project → Search (a toggle with an egress-confirmation prompt), or run
|
|
@@ -69,7 +69,7 @@ project → Search (a toggle with an egress-confirmation prompt), or run
|
|
|
69
69
|
`).filter(e=>e.startsWith(`worktree `)).length}catch{return 0}}function pl(e){let t=B(e);for(;;){if(Ee(t))return t;let n=tn(t);if(n===t)throw Error(`No Open Knowledge project found at or above ${e}. Pass an explicit \`cwd\` argument that points inside an OK project (a directory with a \`${r}\`).`);t=n}}function ml(e){try{let t=new URL(e);return t.protocol===`file:`?hn(t):void 0}catch{return}}async function hl(e){if(!e.getClientCapabilities()?.roots)return;let t;try{t=await e.listRoots()}catch(t){e.log?.(`listRoots fallback failed: ${t instanceof Error?t.message:String(t)}`);return}let n=t.roots??[];if(n.length!==1)return;let r=ml(n[0].uri);return r===void 0&&e.log?.(`single root URI not usable as fs path: ${n[0].uri}`),r}async function gl(e,t,n,r=pl){if(e!==void 0){let t=r(e);return{projectDir:t,viaRootGuess:!1,nextSticky:t}}if(t!==void 0){let e=r(t);return{projectDir:e,viaRootGuess:!1,nextSticky:e}}let i=await n();return i===void 0?{projectDir:void 0,viaRootGuess:!1,nextSticky:void 0}:{projectDir:r(i),viaRootGuess:!0,nextSticky:void 0}}async function _l(e){let t=process.stderr,n=e.spawnTimeoutMs??Yc(process.env.OK_MCP_SPAWN_TIMEOUT_MS),r=e.envAutoStart??process.env.OK_MCP_AUTOSTART,i=At({startupCwd:e.startupCwd,startupConfig:e.startupConfig}),a=new ae({name:se,version:v},{instructions:Je({dir:`.`})});be(a);let o=vn(),s={current:{connectionId:o,displayName:o,colorSeed:o}},c=new Map,l=e=>{if(c.has(e))return;let n=oe(e),r=s.current,i=gs({connectionId:o,displayName:r.displayName,clientName:r.clientInfo?.name??r.displayName,colorSeed:r.colorSeed,resolveWsUrl:async()=>sl({lockDir:n,contentDir:e},``),log:n=>t.write(`[mcp] keepalive[${e}]: ${n}\n`)});c.set(e,i)},u=()=>hl({getClientCapabilities:()=>a.server.getClientCapabilities(),listRoots:()=>a.server.listRoots(),log:e=>t.write(`[mcp] ${e}\n`)}),d,f=!1,p=async e=>{if(f)return;f=!0;let n=await fl(e);if(n<=1){f=!1;return}let r=`Routed to ${e} from the MCP client's single advertised root, but this repo has ${n} git worktrees. If you are working in a worktree, pass its path as \`cwd\` on OK tool calls once — it sticks for the session, so reads, writes, and the preview all target that worktree instead of this checkout.`;try{t.write(`[mcp] ${r}\n`),await a.server.sendLoggingMessage({level:`warning`,data:r})}catch{}},m=async e=>{let t=await gl(e,d,u);if(d=t.nextSticky??d,t.projectDir===void 0)throw Error("`cwd` is required for tool calls against the global MCP server. Pass an absolute path inside an Open Knowledge project, or have the MCP client advertise a single root.");return t.viaRootGuess&&p(t.projectDir),t.projectDir},h=async e=>{let t=await gl(e,d,u);if(d=t.nextSticky??d,t.projectDir===void 0)return;t.viaRootGuess&&p(t.projectDir);let a=t.projectDir,o=await i(a),s=await ol({lockDir:oe(a),contentDir:fe(o,a),envAutoStart:r,...n===void 0?{}:{timeoutMs:n}});return l(a),s.replace(/\/mcp$/,``)};a.server.oninitialized=()=>{let e=a.server.getClientVersion(),t=We(e?.name,o);s.current={connectionId:o,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}},ie(a,{serverUrl:h,resolveCwd:m,config:i,identityRef:s});let g=new bs,_=!1,y,b,x=async()=>{if(_)return;_=!0,y?.stop(),b?.stop();for(let e of c.values())try{e.close()}catch(e){t.write(`[mcp] keepalive close error: ${e instanceof Error?e.message:String(e)}\n`)}c.clear();let e=await Promise.allSettled([a.close(),g.close()]);for(let n of e)if(n.status===`rejected`){let e=n.reason;t.write(`[mcp] shutdown close error: ${e instanceof Error?e.message:String(e)}\n`)}};await a.connect(g),t.write(`[mcp] global stdio server ready (per-call project routing)
|
|
70
70
|
`);let S=!1,C=()=>{S||(S=!0,setTimeout(()=>{t.write(`[mcp] shutdown deadline (5s) reached — forcing exit(1)
|
|
71
71
|
`),process.exit(1)},5e3).unref(),x().finally(()=>{process.exit(0)}))};if(process.once(`SIGINT`,C),process.once(`SIGTERM`,C),process.stdin.on(`end`,()=>{t.write(`[mcp] stdin end — host disconnected, shutting down
|
|
72
|
-
`),C()}),process.stdin.on(`error`,e=>{t.write(`[mcp] stdin error (${e instanceof Error?e.message:String(e)}) — host disconnected, shutting down\n`),C()}),b=ws({getPpid:()=>process.ppid,onHostGone:e=>{t.write(`[mcp] ${e} — shutting down\n`),C()}}),Ts({log:e=>t.write(`${e}\n`),transport:g,process,stdin:process.stdin}),process.platform===`darwin`){let e=Cs(ul,{realpathSync:Xt,statInoSync:e=>Qt(e).ino,log:e=>t.write(`${e}\n`)});if(e!==void 0){t.write(`[mcp] bundle identity anchor=${e.resolvedPath} inode=${e.inode} version=${v}\n`);let{resolvedPath:n,inode:r}=e;y=Ss({detect:()=>xs({bundleAnchorPath:ul,currentInode:r,platform:process.platform,realpath:Xt,statInode:e=>Qt(e).ino}),onReplaced:e=>{t.write(`[mcp] bundle replaced anchor=${n} bootInode=${e.currentInode} onDiskInode=${e.onDiskInode} version=${v} — exiting for host respawn\n`),C()},log:e=>t.write(`[mcp] ${e}\n`)})}}return{close:x}}function vl(e){return new t(`mcp`).description(`Start MCP stdio server for project knowledge base`).option(`-p, --port <port>`,`Override per-call routing and proxy stdio to this HTTP MCP port (skips bundle proxy)`,void 0).option(`--no-bundle-proxy`,`Run the npm-fetched MCP server in-process instead of proxying to the macOS Desktop bundle (equivalent: OK_BUNDLE_PROXY=0)`).action(async t=>{try{let n=e(),r=process.cwd();if(t.port!==void 0){let e=Yc(process.env.OK_MCP_SPAWN_TIMEOUT_MS);await ll({lockDir:``,contentDir:``,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:e});return}let i=t.bundleProxy===!1?[...process.argv,`--no-bundle-proxy`]:process.argv,a=ps(process.env,i,process.platform);if(a.proxy){let e=fs(process.platform,cn(),{existsSync:P});if(e===null)ms({stderr:process.stderr,mode:`fallback-absent`,bundlePath:null,reason:`no installed Open Knowledge.app bundle found`});else try{await hs({bundlePath:e,argv:process.argv.slice(2),env:process.env,stderr:process.stderr});return}catch(t){ms({stderr:process.stderr,mode:`fallback-exec-failed`,bundlePath:e,reason:t instanceof Error?t.message:String(t)})}}else{let e=a.suppressedBy===`env`?`suppressed-env`:a.suppressedBy===`flag`?`suppressed-flag`:a.suppressedBy===`self`?`suppressed-self`:`suppressed-platform`;ms({stderr:process.stderr,mode:e,bundlePath:null,reason:null})}await _l({startupCwd:r,startupConfig:n})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function yl(e){let t={...e};return delete t.ELECTRON_RUN_AS_NODE,t}function bl(e=()=>Ft(Nt())){return{detectBundlePath:()=>e().bundlePath??null,resolveBaseUrl:e=>de({lockDir:T(e)}).baseUrl,openTarget:e=>{N(`open`,[e],{detached:!0,stdio:`ignore`,env:yl(process.env)}).unref()},log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}function xl(e,t,n){let r=B(t.project??process.cwd()),i=t.folder===!0||/\/+$/.test(e),a=e.replace(/\/+$/,``);if(!a)return n.error("Nothing to open: pass a doc path (e.g. `ok open specs/foo/SPEC`)."),1;if(a.startsWith(`/`)||a.includes(`\\`)||a.split(`/`).includes(`..`))return n.error(`Invalid name "${a}": must be a relative path with no '..' segments, leading '/', or backslashes.`),1;if(i){let e=n.resolveBaseUrl(r);if(!e)return n.error(`No Open Knowledge UI is running for ${r}. Folder preview requires a running UI — start one with \`ok ui\`, then retry.`),1;let t=`${e}/#/${Be(a)}`;return n.openTarget(t),n.log(`Opening folder ${a} in your browser: ${t}`),0}if(n.detectBundlePath()){let e=`openknowledge://open?project=${encodeURIComponent(r)}&doc=${encodeURIComponent(a)}`;return n.openTarget(e),n.log(`Opening ${a} in the Open Knowledge desktop app.`),0}let o=n.resolveBaseUrl(r);if(o){let e=`${o}/#/${Fe(a)}`;return n.openTarget(e),n.log(`Opening ${a} in your browser: ${e}`),0}return n.error("No Open Knowledge desktop app found and no UI is running. Install OK Desktop, or start a UI with `ok ui`, then retry."),1}function Sl(){return new t(`open`).description(`Open a doc in the OK Desktop app (folders open in the browser)`).argument(`<doc>`,`Extension-less doc path (e.g. specs/foo/SPEC), or a folder path with --folder`).option(`--folder`,`Treat <doc> as a folder and open the folder route in the browser`).option(`--project <dir>`,`Project root (defaults to the current directory)`).action((e,t)=>{process.exitCode=xl(e,t,bl())})}function Cl(e){return new t(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-
|
|
72
|
+
`),C()}),process.stdin.on(`error`,e=>{t.write(`[mcp] stdin error (${e instanceof Error?e.message:String(e)}) — host disconnected, shutting down\n`),C()}),b=ws({getPpid:()=>process.ppid,onHostGone:e=>{t.write(`[mcp] ${e} — shutting down\n`),C()}}),Ts({log:e=>t.write(`${e}\n`),transport:g,process,stdin:process.stdin}),process.platform===`darwin`){let e=Cs(ul,{realpathSync:Xt,statInoSync:e=>Qt(e).ino,log:e=>t.write(`${e}\n`)});if(e!==void 0){t.write(`[mcp] bundle identity anchor=${e.resolvedPath} inode=${e.inode} version=${v}\n`);let{resolvedPath:n,inode:r}=e;y=Ss({detect:()=>xs({bundleAnchorPath:ul,currentInode:r,platform:process.platform,realpath:Xt,statInode:e=>Qt(e).ino}),onReplaced:e=>{t.write(`[mcp] bundle replaced anchor=${n} bootInode=${e.currentInode} onDiskInode=${e.onDiskInode} version=${v} — exiting for host respawn\n`),C()},log:e=>t.write(`[mcp] ${e}\n`)})}}return{close:x}}function vl(e){return new t(`mcp`).description(`Start MCP stdio server for project knowledge base`).option(`-p, --port <port>`,`Override per-call routing and proxy stdio to this HTTP MCP port (skips bundle proxy)`,void 0).option(`--no-bundle-proxy`,`Run the npm-fetched MCP server in-process instead of proxying to the macOS Desktop bundle (equivalent: OK_BUNDLE_PROXY=0)`).action(async t=>{try{let n=e(),r=process.cwd();if(t.port!==void 0){let e=Yc(process.env.OK_MCP_SPAWN_TIMEOUT_MS);await ll({lockDir:``,contentDir:``,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:e});return}let i=t.bundleProxy===!1?[...process.argv,`--no-bundle-proxy`]:process.argv,a=ps(process.env,i,process.platform);if(a.proxy){let e=fs(process.platform,cn(),{existsSync:P});if(e===null)ms({stderr:process.stderr,mode:`fallback-absent`,bundlePath:null,reason:`no installed Open Knowledge.app bundle found`});else try{await hs({bundlePath:e,argv:process.argv.slice(2),env:process.env,stderr:process.stderr});return}catch(t){ms({stderr:process.stderr,mode:`fallback-exec-failed`,bundlePath:e,reason:t instanceof Error?t.message:String(t)})}}else{let e=a.suppressedBy===`env`?`suppressed-env`:a.suppressedBy===`flag`?`suppressed-flag`:a.suppressedBy===`self`?`suppressed-self`:`suppressed-platform`;ms({stderr:process.stderr,mode:e,bundlePath:null,reason:null})}await _l({startupCwd:r,startupConfig:n})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function yl(e){let t={...e};return delete t.ELECTRON_RUN_AS_NODE,t}function bl(e=()=>Ft(Nt())){return{detectBundlePath:()=>e().bundlePath??null,resolveBaseUrl:e=>de({lockDir:T(e)}).baseUrl,openTarget:e=>{N(`open`,[e],{detached:!0,stdio:`ignore`,env:yl(process.env)}).unref()},log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}function xl(e,t,n){let r=B(t.project??process.cwd()),i=t.folder===!0||/\/+$/.test(e),a=e.replace(/\/+$/,``);if(!a)return n.error("Nothing to open: pass a doc path (e.g. `ok open specs/foo/SPEC`)."),1;if(a.startsWith(`/`)||a.includes(`\\`)||a.split(`/`).includes(`..`))return n.error(`Invalid name "${a}": must be a relative path with no '..' segments, leading '/', or backslashes.`),1;if(i){let e=n.resolveBaseUrl(r);if(!e)return n.error(`No Open Knowledge UI is running for ${r}. Folder preview requires a running UI — start one with \`ok ui\`, then retry.`),1;let t=`${e}/#/${Be(a)}`;return n.openTarget(t),n.log(`Opening folder ${a} in your browser: ${t}`),0}if(n.detectBundlePath()){let e=`openknowledge://open?project=${encodeURIComponent(r)}&doc=${encodeURIComponent(a)}`;return n.openTarget(e),n.log(`Opening ${a} in the Open Knowledge desktop app.`),0}let o=n.resolveBaseUrl(r);if(o){let e=`${o}/#/${Fe(a)}`;return n.openTarget(e),n.log(`Opening ${a} in your browser: ${e}`),0}return n.error("No Open Knowledge desktop app found and no UI is running. Install OK Desktop, or start a UI with `ok ui`, then retry."),1}function Sl(){return new t(`open`).description(`Open a doc in the OK Desktop app (folders open in the browser)`).argument(`<doc>`,`Extension-less doc path (e.g. specs/foo/SPEC), or a folder path with --folder`).option(`--folder`,`Treat <doc> as a folder and open the folder route in the browser`).option(`--project <dir>`,`Project root (defaults to the current directory)`).action((e,t)=>{process.exitCode=xl(e,t,bl())})}function Cl(e){return new t(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-CiO0g9mW.mjs`),r=e(),i=process.cwd(),a=fe(r,i),o;try{o=t({projectDir:i,contentDir:a})}catch(e){console.error(`Content preview failed: ${e instanceof Error?e.message:String(e)}`),process.exitCode=1;return}process.stdout.write(`${n(o,i)}\n`),o.totalCount===0&&o.warnings.length>0&&(process.exitCode=1)})}function wl(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function Tl(e,t,n=process.cwd()){let r=e.op??`sync`,i=h(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`,...C({kind:`cli`,runtimeVersion:v})},body:JSON.stringify({op:r})});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.title??e.error??e.message??`Server responded with ${n.status}`)}wl(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 a=re({baseDir:n});if(r===`sync`||r===`pull`){wl(e.json,{type:`step`,step:`pull`});let t=await a.pull();wl(e.json,{type:`pull`,summary:t.summary}),e.json||process.stderr.write(` pull: ${t.summary.changes} changes\n`)}(r===`sync`||r===`push`)&&(wl(e.json,{type:`step`,step:`push`}),await a.push(),wl(e.json,{type:`push`,ok:!0}),e.json||process.stderr.write(` push: ok
|
|
73
73
|
`)),wl(e.json,{type:`complete`,op:r}),e.json||process.stderr.write(`✓ ${r} complete\n`)}function El(e){return new t(`sync`).description(`Commit, pull, and push to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Tl({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 Dl(e){return new t(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Tl({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 Ol(e){return new t(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await Tl({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 kl(e){return typeof e==`string`&&ve.includes(e)}async function Al(e={}){let t=B(e.cwd??process.cwd()),n=e.pack??`knowledge-base`;if(!De[n])return{status:`failed`,message:`${A(`Error:`)} Unknown pack "${n}". Available: ${ve.join(`, `)}`,exitCode:1};let r;try{r=await Re({projectDir:t,rootDir:e.root,packId:n})}catch(e){return e instanceof Ge?{status:`prerequisite-missing`,message:`${A(`Error:`)} ${e.message}`,exitCode:1}:{status:`failed`,message:`${A(`Error:`)} ${e instanceof Error?e.message:String(e)}`,exitCode:1}}if(r.created.length===0){let e=De[n].name;return{status:`no-op`,message:`${k(`Your ${e} pack is already seeded.`)}\n${O(`Nothing to do.`)}`,plan:r,exitCode:0}}if(e.dryRun)return{status:`dry-run`,message:`${M(`Plan (dry-run — no changes made):`)}\n\n${Ml(r,t)}`,plan:r,exitCode:0};if(!e.yes&&!await Nl(`${M(`Plan:`)}\n\n${Ml(r,t)}\n\n${M(`Apply?`)} ${O(`[Y/n] `)}`,e.confirmStream))return{status:`cancelled`,message:O(`Cancelled.`),plan:r,exitCode:0};let i=await Ve(r,{projectDir:t,packId:n});if(i.errors.length>0){let e=i.errors.map(e=>` ${A(`✗`)} ${e.path}: ${e.error}`);return{status:`failed`,message:[`${j(`Applied`)} ${i.applied} entries, ${j(String(i.errors.length))} error(s):`,...e].join(`
|
|
74
74
|
`),plan:r,exitCode:1}}let a=De[n].name,o=i.packSkillsInstalled.length>0?`\n${O(`Installed the ${a} skill for: ${i.packSkillsInstalled.join(`, `)}`)}`:``;return{status:`applied`,message:`${k(`✓ Seeded ${a}`)} ${O(`(${i.applied} entries, ${i.durationMs}ms)`)}${o}`,plan:r,exitCode:0}}function jl(){let e=[M(`Available packs:`)];for(let t of ve){let n=De[t];e.push(` ${k(t)} ${O(`—`)} ${n.name}: ${n.description}`)}return e.join(`
|
|
75
75
|
`)}function Ml(e,t){let n=[],r=e.created.filter(e=>e.kind===`folder`),i=e.created.filter(e=>e.kind===`file`);if(r.length>0){n.push(M(`Folders to create:`));for(let e of r)n.push(` ${k(`+`)} ${D(nn(t,B(t,e.path))||e.path)}${O(`/`)}`)}if(i.length>0){n.length>0&&n.push(``),n.push(M(`Files to create:`));for(let e of i)n.push(` ${k(`+`)} ${D(nn(t,B(t,e.path))||e.path)}`)}if(e.skipped.length>0){n.length>0&&n.push(``),n.push(O(`Already present (skipped):`));for(let t of e.skipped)n.push(` ${O(`· ${t.path} (${t.reason})`)}`)}if(e.warnings.length>0){n.length>0&&n.push(``),n.push(j(`Warnings:`));for(let t of e.warnings)n.push(` ${j(`!`)} ${t}`)}return n.join(`
|
|
@@ -78,7 +78,7 @@ project → Search (a toggle with an egress-confirmation prompt), or run
|
|
|
78
78
|
`);return}if(a){process.stdout.write(`${JSON.stringify({type:`error`,code:c.kind})}\n`);return}process.stderr.write(`✗ share name-check failed: ${c.kind}\n`),process.exit(1)}function Ll(e){return new t(`name-check`).description(`Check if owner/name is available on GitHub`).requiredOption(`--owner <owner>`,`GitHub owner (user or org)`).requiredOption(`--name <name>`,`Repository name`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await Il(t,await e())})}async function Rl(e){try{let t=[],n=await e.users.getAuthenticated();t.push({login:n.data.login,kind:`user`,avatarUrl:n.data.avatar_url});for await(let n of e.paginate.iterator(e.orgs.listMembershipsForAuthenticatedUser,{state:`active`,per_page:100}))for(let e of n.data)(e.permissions?.can_create_repository===!0||e.role===`admin`)&&t.push({login:e.organization.login,kind:`org`,avatarUrl:e.organization.avatar_url??void 0});return{kind:`ok`,owners:t}}catch(e){return e.status===401?{kind:`auth-required`}:{kind:`network`}}}async function zl(e,t){let{host:n,json:r}=e;H(n);let i=await ki(n,t);if(i==null){if(r){process.stdout.write(`${JSON.stringify({type:`error`,code:`auth-required`})}\n`);return}process.stderr.write(`Not logged in to ${n}\n`),process.exit(1)}let a=n===`github.com`?void 0:`https://${n}/api/v3`,o=await Rl(new K({auth:i,...a?{baseUrl:a}:{}}));if(o.kind===`ok`){if(r)process.stdout.write(`${JSON.stringify({type:`owners`,owners:o.owners})}\n`);else for(let e of o.owners)process.stdout.write(`${e.kind}\t${e.login}\n`);return}if(r){process.stdout.write(`${JSON.stringify({type:`error`,code:o.kind})}\n`);return}process.stderr.write(`✗ share owners failed: ${o.kind}\n`),process.exit(1)}function Bl(e){return new t(`owners`).description(`List GitHub owners eligible to host a new repository`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await zl(t,await e())})}function Vl(e){let t=e,n=t.status,r=t.response?.data,i=t.response?.headers,a=`${r?.message??r?.errors?.map(e=>e.message??``).join(`
|
|
79
79
|
`)??``}\n${t.message??``}`.toLowerCase();return n===401?`auth-required`:n===403?i?.[`x-github-sso`]||a.includes(`saml`)||a.includes(`sso`)?`saml-sso`:`network`:n===422&&(r?.errors?.some(e=>e.field===`name`)||a.includes(`already exists`)||a.includes(`name already exists`))?`name-conflict`:`network`}async function Hl(e){let{octokit:t,ownerLogin:n,ownerKind:r,name:i,visibility:a,description:o}=e,s=a===`private`;if(r===`user`){let{data:e}=await t.repos.createForAuthenticatedUser({name:i,private:s,...o?{description:o}:{}});return{cloneUrl:e.clone_url,defaultBranch:e.default_branch??`main`}}let{data:c}=await t.repos.createInOrg({org:n,name:i,visibility:a,...o?{description:o}:{}});return{cloneUrl:c.clone_url,defaultBranch:c.default_branch??`main`}}async function Ul(e,t,n){try{let{data:r}=await e.repos.get({owner:t,repo:n});return{cloneUrl:r.clone_url,defaultBranch:r.default_branch??`main`}}catch{return null}}async function Wl(e,t){return(await e.users.getAuthenticated()).data.login.toLowerCase()===t.toLowerCase()?`user`:`org`}function Gl(e){return re({baseDir:e,unsafe:{allowUnsafeCredentialHelper:!0}}).env({GIT_TERMINAL_PROMPT:`0`})}function Kl(e,t){if(!e.startsWith(`https://`))return e;try{if(new URL(e).hostname!==`github.com`)return e}catch{return e}return e.replace(`https://`,`https://x-access-token:${t}@`)}const ql={ensureOkScaffold:e=>{_e(e)},gitFactory:Gl};async function Jl(e){let t={...ql,...e.deps},n=B(e.projectDir),r;if(e.ownerKind)r=e.ownerKind;else try{r=await Wl(e.octokit,e.body.owner)}catch(e){return{kind:`error`,code:Vl(e)}}try{t.ensureOkScaffold(n)}catch{return{kind:`error`,code:`init-failed`}}let i=t.gitFactory(n);if(!P(z(n,`.git`)))try{await i.init()}catch{return{kind:`error`,code:`init-failed`}}let a;try{a=await Hl({octokit:e.octokit,ownerLogin:e.body.owner,ownerKind:r,name:e.body.name,visibility:e.body.visibility,description:e.body.description})}catch(t){if(Vl(t)===`name-conflict`){let t=await Ul(e.octokit,e.body.owner,e.body.name);if(t===null)return{kind:`error`,code:`name-conflict`};a=t}else return{kind:`error`,code:Vl(t)}}try{await i.addRemote(`origin`,a.cloneUrl)}catch(e){if(!String(e.message??``).toLowerCase().includes(`remote origin already exists`))return{kind:`error`,code:`push-failed`}}let o=!1;try{await i.raw([`rev-parse`,`--verify`,`HEAD`])}catch{o=!0}if(o)try{await i.add(`.`),await i.raw([`commit`,`--allow-empty`,`-m`,`Initial commit`])}catch{return{kind:`error`,code:`init-failed`}}let s=Kl(a.cloneUrl,e.token);try{await i.raw([`push`,s,`HEAD:refs/heads/${a.defaultBranch}`])}catch(e){let t=String(e.message??``).toLowerCase();return t.includes(`saml`)||t.includes(`sso`)?{kind:`error`,code:`saml-sso`}:{kind:`error`,code:`push-failed`}}try{await i.raw([`update-ref`,`refs/remotes/origin/${a.defaultBranch}`,`HEAD`])}catch{}return{kind:`ok`,value:{ownerLogin:e.body.owner,repoName:e.body.name,cloneUrl:a.cloneUrl,defaultBranch:a.defaultBranch}}}function Yl(e,t){if(!e){t.kind===`ok`?process.stdout.write(`✓ Published ${t.value.cloneUrl}\n`):(process.stderr.write(`✗ share publish failed: ${t.code}\n`),process.exit(1));return}if(t.kind===`ok`){process.stdout.write(`${JSON.stringify({type:`publish`,...t.value})}\n`);return}process.stdout.write(`${JSON.stringify({type:`error`,code:t.code})}\n`)}async function Xl(e,t){let{host:n,owner:r,name:i,visibility:a,description:o,projectDir:s,json:c}=e;H(n);let l=await ki(n,t);if(l==null){Yl(c,{kind:`error`,code:`auth-required`});return}let u=n===`github.com`?void 0:`https://${n}/api/v3`,d=new K({auth:l,...u?{baseUrl:u}:{}});try{Bt(`git config user.email`,{cwd:s,stdio:`ignore`})}catch{process.env.GIT_AUTHOR_NAME??=`Open Knowledge`,process.env.GIT_AUTHOR_EMAIL??=`noreply@inkeep.com`,process.env.GIT_COMMITTER_NAME??=`Open Knowledge`,process.env.GIT_COMMITTER_EMAIL??=`noreply@inkeep.com`}Yl(c,await Jl({octokit:d,token:l,projectDir:s,body:{owner:r,name:i,visibility:a,description:o}}))}function Zl(e){return new t(`publish`).description(`Publish a no-remote project to GitHub`).requiredOption(`--owner <owner>`,`GitHub owner (user or org)`).requiredOption(`--name <name>`,`Repository name`).requiredOption(`--visibility <visibility>`,`public or private`).option(`--description <description>`,`Repository description`).requiredOption(`--project-dir <projectDir>`,`Path to the project on disk`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{t.visibility!==`public`&&t.visibility!==`private`&&(process.stderr.write(`✗ visibility must be 'public' or 'private'
|
|
80
80
|
`),process.exit(1)),await Xl(t,await e())})}function Ql(){let e=new t(`share`);e.description(`Sharing flow operations (owners, name-check, publish)`);let n=()=>te();return e.addCommand(Bl(n)),e.addCommand(Ll(n)),e.addCommand(Zl(n)),e}function $l(){return new t(`share`).description(`Switch this project to shared mode (commit OK config alongside content)`).option(`--project <dir>`,`Project root (defaults to cwd)`).option(`--json`,`Output JSON`,!1).action(async e=>{let t=B(e.project??process.cwd()),n=dt(t),r=tt(t,et(t));if(r.kind===`no-exclude`){eu(e.json,t,r.reason);return}let i=dt(t);if(e.json){let e={type:`sharing-share`,projectRoot:t,mode:i,removed:r.removed};process.stdout.write(`${JSON.stringify(e)}\n`);return}if(n===`shared`){process.stderr.write(`${D(`Sharing mode is already`)} ${M(`shared`)} ${D(`— nothing to do.`)}\n`);return}process.stderr.write(`${k(`✓`)} ${M(`Sharing mode set to`)} ${k(`shared`)}\n`),process.stderr.write(` Removed OK paths from ${M(`.git/info/exclude`)}; commit the files to share with teammates.\n`)})}function eu(e,t,n){if(e){process.stdout.write(`${JSON.stringify({type:`sharing-share`,projectRoot:t,mode:`no-git`,removed:[],reason:n})}\n`);return}process.stderr.write(`${j({"no-git":`No git repository here — sharing mode does not apply.`,"no-info-dir":`The gitdir's info/ folder is absent; cannot toggle sharing mode.`,"malformed-pointer":"The .git pointer file is malformed (stale worktree). Run `git worktree prune` and try again.",inaccessible:`The .git path is inaccessible (permissions or mount issue).`}[n])}\n`)}function tu(){return new t(`status`).description(`Print the current sharing mode and the OK paths in .git/info/exclude`).option(`--project <dir>`,`Project root (defaults to cwd)`).option(`--json`,`Output JSON`,!1).action(async e=>{let t=B(e.project??process.cwd()),n=dt(t),r=[...ut(t)],i=gt(t,et(t)).tracked;if(e.json){let e={type:`sharing-status`,projectRoot:t,mode:n,excluded:r,trackedUpstream:i};process.stdout.write(`${JSON.stringify(e)}\n`);return}let a=[];if(a.push(`Open Knowledge sharing mode: ${nu(n)}`),a.push(``),a.push(`Excluded from git via ${M(`.git/info/exclude`)}:`),r.length===0)a.push(` (none)`);else for(let e of r)a.push(` ${e}`);if(a.push(``),a.push(`Other OK paths exist but are tracked upstream:`),i.length===0)a.push(` (none)`);else for(let e of i)a.push(` ${e}`);a.push(``),a.push(`Toggle with: ${D(n===`local-only`?`ok config-sharing share`:`ok config-sharing unshare`)}`),process.stdout.write(`${a.join(`
|
|
81
|
-
`)}\n`)})}function nu(e){switch(e){case`shared`:return k(`shared`);case`local-only`:return k(`local-only`);case`no-git`:return j(`no-git (not a git repository)`)}}function ru(){return new t(`unshare`).description(`Switch this project to local-only mode (add OK artifacts to .git/info/exclude so they stay out of git)`).option(`--project <dir>`,`Project root (defaults to cwd)`).option(`--json`,`Output JSON`,!1).action(async e=>{let t=B(e.project??process.cwd()),n=pt(t,et(t));if(n.kind===`refused-tracked`){if(e.json){let e={type:`sharing-unshare`,projectRoot:t,mode:`refused-tracked`,tracked:n.tracked,remediation:n.remediation};process.stdout.write(`${JSON.stringify(e)}\n`)}else process.stderr.write(`${n.remediation}\n`);process.exitCode=1;return}if(n.kind===`no-exclude`){iu(e.json,t,n.reason);return}let r=dt(t);if(e.json){let e={type:`sharing-unshare`,projectRoot:t,mode:r,appended:n.appended,alreadyPresent:n.alreadyPresent};process.stdout.write(`${JSON.stringify(e)}\n`);return}if(n.appended.length===0){process.stderr.write(`${M(`Sharing mode is already`)} ${k(`local-only`)} ${M(`— nothing to do.`)}\n`);return}process.stderr.write(`${k(`✓`)} ${M(`Sharing mode set to`)} ${k(`local-only`)}\n`),process.stderr.write(` Added ${n.appended.length} path(s) to ${M(`.git/info/exclude`)} (per-clone, not committed).\n`)})}function iu(e,t,n){if(e){process.stdout.write(`${JSON.stringify({type:`sharing-unshare`,projectRoot:t,mode:`no-git`,appended:[],alreadyPresent:[],reason:n})}\n`);return}process.stderr.write(`${j({"no-git":`No git repository here — sharing mode does not apply.`,"no-info-dir":`The gitdir's info/ folder is absent; cannot toggle sharing mode.`,"malformed-pointer":"The .git pointer file is malformed (stale worktree). Run `git worktree prune` and try again.",inaccessible:`The .git path is inaccessible (permissions or mount issue).`}[n])}\n`)}function au(){let e=new t(`config-sharing`);return e.description(`Manage Open Knowledge's git-sharing mode (share OK config with the team, or keep local-only on this machine)`),e.addCommand($l()),e.addCommand(ru()),e.addCommand(tu()),e}const ou=new Set([`--cwd`,`--log-level`]);function su(e){let t=[],n=null,r=!1;for(let i=0;i<e.length;i++){let a=e[i];if(a===`--help`||a===`-h`||a===`--version`||a===`-V`){r=!0;break}if(a===`--cwd`||a===`--log-level`){a===`--cwd`&&(n=e[i+1]??null),i++;continue}if(a.startsWith(`--cwd=`)){n=a.slice(6);continue}if(!a.startsWith(`--log-level=`)&&!(a===`--no-color`||a===`--color`)){if(a.startsWith(`-`)){ou.has(a)&&i++;continue}t.push(a)}}return{operands:t,cwd:n,sawTerminalFlag:r}}function cu(e,t){if(e.length===0)return null;let n=e[0];return n===`open`&&e[1]!==void 0&&t.isFileish(e[1])?e[1]:t.knownSubcommands.has(n)?null:t.isFileish(n)?n:null}function lu(e){return/\.(md|mdx)$/i.test(e)}function uu(e){let t={...e};return delete t.ELECTRON_RUN_AS_NODE,t}function du(e=()=>Ft(Nt())){return{prepare:Le,detectBundlePath:()=>e().bundlePath??null,openTarget:e=>{N(`open`,[e],{detached:!0,stdio:`ignore`,env:uu(process.env)}).unref()},runProjectOpen:(e,t)=>xl(e,{project:t},bl()),runBrowserOpen:e=>mu(e),log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}async function fu(e,t){let n;try{n=t.prepare(e)}catch(e){if(e instanceof ze||e instanceof Ue||e instanceof Me)return t.error(e.message),1;throw e}if(n.mode===`project`)return t.runProjectOpen(n.docName,n.projectRoot);if(t.detectBundlePath()){let e=`openknowledge://open?file=${encodeURIComponent(n.canonicalFilePath)}`;return t.openTarget(e),t.log(`Opening ${n.singleDocRelPath} in the Open Knowledge desktop app.`),0}return await t.runBrowserOpen(n),0}function pu(){let e=import.meta.dirname??new URL(`.`,import.meta.url).pathname;return[B(e,`public`),B(e,`../../app/dist`),B(e,`../../../app/dist`)].find(e=>P(e))}async function mu(e){let{createEphemeralProjectDir:t}=await import(`./dist-
|
|
81
|
+
`)}\n`)})}function nu(e){switch(e){case`shared`:return k(`shared`);case`local-only`:return k(`local-only`);case`no-git`:return j(`no-git (not a git repository)`)}}function ru(){return new t(`unshare`).description(`Switch this project to local-only mode (add OK artifacts to .git/info/exclude so they stay out of git)`).option(`--project <dir>`,`Project root (defaults to cwd)`).option(`--json`,`Output JSON`,!1).action(async e=>{let t=B(e.project??process.cwd()),n=pt(t,et(t));if(n.kind===`refused-tracked`){if(e.json){let e={type:`sharing-unshare`,projectRoot:t,mode:`refused-tracked`,tracked:n.tracked,remediation:n.remediation};process.stdout.write(`${JSON.stringify(e)}\n`)}else process.stderr.write(`${n.remediation}\n`);process.exitCode=1;return}if(n.kind===`no-exclude`){iu(e.json,t,n.reason);return}let r=dt(t);if(e.json){let e={type:`sharing-unshare`,projectRoot:t,mode:r,appended:n.appended,alreadyPresent:n.alreadyPresent};process.stdout.write(`${JSON.stringify(e)}\n`);return}if(n.appended.length===0){process.stderr.write(`${M(`Sharing mode is already`)} ${k(`local-only`)} ${M(`— nothing to do.`)}\n`);return}process.stderr.write(`${k(`✓`)} ${M(`Sharing mode set to`)} ${k(`local-only`)}\n`),process.stderr.write(` Added ${n.appended.length} path(s) to ${M(`.git/info/exclude`)} (per-clone, not committed).\n`)})}function iu(e,t,n){if(e){process.stdout.write(`${JSON.stringify({type:`sharing-unshare`,projectRoot:t,mode:`no-git`,appended:[],alreadyPresent:[],reason:n})}\n`);return}process.stderr.write(`${j({"no-git":`No git repository here — sharing mode does not apply.`,"no-info-dir":`The gitdir's info/ folder is absent; cannot toggle sharing mode.`,"malformed-pointer":"The .git pointer file is malformed (stale worktree). Run `git worktree prune` and try again.",inaccessible:`The .git path is inaccessible (permissions or mount issue).`}[n])}\n`)}function au(){let e=new t(`config-sharing`);return e.description(`Manage Open Knowledge's git-sharing mode (share OK config with the team, or keep local-only on this machine)`),e.addCommand($l()),e.addCommand(ru()),e.addCommand(tu()),e}const ou=new Set([`--cwd`,`--log-level`]);function su(e){let t=[],n=null,r=!1;for(let i=0;i<e.length;i++){let a=e[i];if(a===`--help`||a===`-h`||a===`--version`||a===`-V`){r=!0;break}if(a===`--cwd`||a===`--log-level`){a===`--cwd`&&(n=e[i+1]??null),i++;continue}if(a.startsWith(`--cwd=`)){n=a.slice(6);continue}if(!a.startsWith(`--log-level=`)&&!(a===`--no-color`||a===`--color`)){if(a.startsWith(`-`)){ou.has(a)&&i++;continue}t.push(a)}}return{operands:t,cwd:n,sawTerminalFlag:r}}function cu(e,t){if(e.length===0)return null;let n=e[0];return n===`open`&&e[1]!==void 0&&t.isFileish(e[1])?e[1]:t.knownSubcommands.has(n)?null:t.isFileish(n)?n:null}function lu(e){return/\.(md|mdx)$/i.test(e)}function uu(e){let t={...e};return delete t.ELECTRON_RUN_AS_NODE,t}function du(e=()=>Ft(Nt())){return{prepare:Le,detectBundlePath:()=>e().bundlePath??null,openTarget:e=>{N(`open`,[e],{detached:!0,stdio:`ignore`,env:uu(process.env)}).unref()},runProjectOpen:(e,t)=>xl(e,{project:t},bl()),runBrowserOpen:e=>mu(e),log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}async function fu(e,t){let n;try{n=t.prepare(e)}catch(e){if(e instanceof ze||e instanceof Ue||e instanceof Me)return t.error(e.message),1;throw e}if(n.mode===`project`)return t.runProjectOpen(n.docName,n.projectRoot);if(t.detectBundlePath()){let e=`openknowledge://open?file=${encodeURIComponent(n.canonicalFilePath)}`;return t.openTarget(e),t.log(`Opening ${n.singleDocRelPath} in the Open Knowledge desktop app.`),0}return await t.runBrowserOpen(n),0}function pu(){let e=import.meta.dirname??new URL(`.`,import.meta.url).pathname;return[B(e,`public`),B(e,`../../app/dist`),B(e,`../../../app/dist`)].find(e=>P(e))}async function mu(e){let{createEphemeralProjectDir:t}=await import(`./dist-GL5zcXSU.mjs`),{loadConfig:n}=await import(`./index.mjs`),{bootStartServer:r,resolveHost:i}=await import(`./start-B3JYhwpU.mjs`),{openBrowser:a}=await import(`./open-browser-DHTbHSqx.mjs`),o=pu();o||(process.stderr.write("Open Knowledge UI assets were not found. Reinstall @inkeep/open-knowledge, or build the app (`bun run build`) in a monorepo checkout.\n"),process.exit(1));let s=t(e.contentDir),c=!1,l,u=async()=>{if(!c){c=!0;try{await l?.destroy()}catch{}try{await gn(s,{recursive:!0,force:!0})}catch{}}},d=()=>{u().then(()=>process.exit(0))};process.once(`SIGINT`,d),process.once(`SIGTERM`,d);let{config:f}=n(s),p=i({},process.env);try{l=await r({config:f,cwd:s,host:p,port:0,projectDir:s,singleFile:e.canonicalFilePath,serveContentAssets:!0,reactShellDistDir:o})}catch(t){await u(),process.stderr.write(`Failed to open ${e.singleDocRelPath}: ${t instanceof Error?t.message:String(t)}\n`),process.exit(1)}let m=`http://${p}:${l.port}/#/${Fe(e.docName)}`;process.stdout.write(`Opening ${e.singleDocRelPath} in your browser: ${m}\n`),process.stdout.write(`Press Ctrl-C to close the session.
|
|
82
82
|
`),a(m),await new Promise(()=>{})}function hu(e,t){return{server:gu(`server`,e),ui:gu(`ui`,t)}}function gu(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 _u(e){return`${vu(e.server)}\n${vu(e.ui)}`}function vu(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 yu(e){let t=e.inspect??(t=>bt(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=hu(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(_u(r)),r}function bu(e){return new t(`status`).description(`Show live state of the server + ui lockfiles for this project`).option(`--json`,`Emit structured JSON instead of formatted text`).action(t=>{e(),yu({lockDir:T(process.cwd()),json:t.json===!0})})}function xu(e){return[e,`Copyright (C) 2026 Inkeep, Inc.`,`License GPL-3.0-or-later: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.`,`This is free software: you are free to change and redistribute it.`,`There is NO WARRANTY, to the extent permitted by law.`].join(`
|
|
83
83
|
`)}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 t;let $,Su;function Cu(){return Su}Q.name(`open-knowledge`).description(`Local-first knowledge base with CRDT collaboration`).usage(`[options] [file | command]`).version(xu(Dt)).option(`--cwd <path>`,`Working directory`).option(`--log-level <level>`,`Log level: silent, error, warn, info (default), debug, trace`,`info`).option(`--no-color`,`Disable color output`).option(`--color`,`Force color output`).hook(`preAction`,e=>{let t=e.opts().cwd;if(t!==void 0&&process.chdir(t),Q.getOptionValueSource(`logLevel`)===`cli`){let e=String(Q.opts().logLevel);process.env.LOG_LEVEL=e,process.env.OK_CONSOLE_LEVEL=e}let n=e.args?.[0],r=wt(n,process.cwd());r!==null&&(vt(process.cwd()),process.chdir(r),console.error(`[ok] Using Open Knowledge project at ${r}`));let{config:i}=kt(r??t);$=i;let a=e.args?.[0]??e.name()??`cli`;Su=me({name:`cli`,project:i.project?.name??void 0}),Su.info({command:a,cwd:process.cwd()},`cli command started`)}),Q.action(async()=>{if(Ft(Nt()).available){jt({spawn:N});return}await Pt($,{})});const wu=Mt(()=>$);Q.addCommand(wu);const Tu=vl(()=>$);Q.addCommand(Tu),Q.addCommand(mt()),Q.addCommand(Pl()),Q.addCommand(ls()),Q.addCommand(Rt());const Eu=Cl(()=>$);Q.addCommand(Eu);const Du=ht(()=>$);Q.addCommand(Du),Q.addCommand(Sl()),Q.addCommand(xt(()=>$)),Q.addCommand($i(()=>$)),Q.addCommand(bu(()=>$)),Q.addCommand(Tt()),Q.addCommand(Ko()),Q.addCommand(Xi()),Q.addCommand(ya()),Q.addCommand(Ri(Cu)),Q.addCommand(ts()),Q.addCommand(da(()=>$)),Q.addCommand(El(()=>$)),Q.addCommand(Ol(()=>$)),Q.addCommand(Dl(()=>$)),Q.addCommand(Ql()),Q.addCommand(au()),Q.addHelpText(`after`,`
|
|
84
84
|
Examples:
|