@inkeep/open-knowledge 0.46.0-beta.8 → 0.46.0-beta.9
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/{acp-harness-probe-4DjqrOhu.mjs → acp-harness-probe-B3zP-iU3.mjs} +2 -2
- package/dist/cli.mjs +7 -7
- package/dist/constants-DJEQ5lbI.mjs +2 -0
- package/dist/git-handle-CZCF5f5x.mjs +1 -0
- package/dist/{git-handle-CUCj-M_k.mjs → git-handle-bsekfuqb.mjs} +3 -3
- package/dist/index.mjs +1 -1
- package/dist/{init-DWCsIT2Y.mjs → init-BSRAJcxJ.mjs} +3 -3
- package/dist/init-Nj3Qfja6.mjs +1 -0
- package/dist/{launch-json-removal-BCxhJz-M.mjs → launch-json-removal-Z49VHJab.mjs} +2 -2
- package/dist/{loader-84N4YMxM.mjs → loader-7F0JSi2o.mjs} +2 -2
- package/dist/loader-DEoi209o.mjs +1 -0
- package/dist/md-manager-DbwR9qMJ.mjs +2 -0
- package/dist/{open-browser-D-fJ9iwf.mjs → open-browser-DOh4nE9t.mjs} +2 -2
- package/dist/parse-worker.mjs +1 -1
- package/dist/{preview-Ce0jIM-0.mjs → preview-CI4qefY8.mjs} +2 -2
- package/dist/preview-rMognm1O.mjs +1 -0
- package/dist/public/assets/FeedbackForm-Dx8ISPUC.js +1 -0
- package/dist/public/assets/ShareBranchSwitchDialog-BOn9pwt8.js +1 -0
- package/dist/public/assets/{worktree-store-Cn9IFis3.js → auth-prompt-store-CmyRhcKh.js} +1 -1
- package/dist/public/assets/{globals-B5uVOYYT.js → globals-IzHn2MUy.js} +1 -1
- package/dist/public/assets/{index-DoyHoCFU.js → index-BW1cVj8N.js} +108 -108
- package/dist/public/assets/{uninstall-m1tFru3-.js → uninstall-BCLudTra.js} +1 -1
- package/dist/public/index.html +3 -3
- package/dist/public/uninstall.html +2 -2
- package/dist/{repair-launch-json-DKnGHC3s.mjs → repair-launch-json-Chs2wXL5.mjs} +2 -2
- package/dist/{repair-mcp-configs-BNqk430t.mjs → repair-mcp-configs-DC_Nk6wf.mjs} +2 -2
- package/dist/{repair-skills-HLaZ-M-Y.mjs → repair-skills-BW5UCBvh.mjs} +2 -2
- package/dist/repair-skills-v_TK3DOo.mjs +1 -0
- package/dist/server-lock-9cnBGhAH.mjs +1 -0
- package/dist/{server-lock-N4bxkmqA.mjs → server-lock-Cdm6cZ-8.mjs} +2 -2
- package/dist/{src-BldBF2Y_.mjs → src-2ftHD8eU.mjs} +1 -1
- package/dist/{src-B9fZz8CV.mjs → src-DrNAleIl.mjs} +2 -2
- package/dist/{src-BAuCUhtO.mjs → src-tAuEvoB8.mjs} +2 -2
- package/dist/{src-CBxmkYgG.mjs → src-zLMYDmwT.mjs} +4 -4
- package/dist/{start-CGRdHb1G.mjs → start-Bx6I5bEA.mjs} +3 -3
- package/dist/start-MnLPFpd0.mjs +1 -0
- package/dist/{write-project-skill-DZsw6Rkw.mjs → write-project-skill-xt4ohzdz.mjs} +2 -2
- package/package.json +4 -4
- package/dist/constants-GWFx-UC8.mjs +0 -2
- package/dist/git-handle-c0ljFZis.mjs +0 -1
- package/dist/init-ZV2BMIkj.mjs +0 -1
- package/dist/loader-gOaiaXCo.mjs +0 -1
- package/dist/md-manager-usiCjUg4.mjs +0 -2
- package/dist/preview-TJlA1vTS.mjs +0 -1
- package/dist/public/assets/FeedbackForm-YYOLAdPR.js +0 -1
- package/dist/public/assets/ShareBranchSwitchDialog-BT-R1a5Z.js +0 -1
- package/dist/repair-skills-COiT9pxq.mjs +0 -1
- package/dist/server-lock-DTx_HmnT.mjs +0 -1
- package/dist/start-uD8bt0wq.mjs +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{K as e}from"./sleep-IcuyYCzq.mjs";import{_ as t,b as n,d as r}from"./write-project-skill-
|
|
1
|
+
import{K as e}from"./sleep-IcuyYCzq.mjs";import{_ as t,b as n,d as r}from"./write-project-skill-xt4ohzdz.mjs";import{d as i}from"./init-BSRAJcxJ.mjs";import{execFileSync as a}from"node:child_process";import{dirname as o,join as s}from"node:path";import{existsSync as c,mkdirSync as l,readFileSync as u,writeFileSync as d}from"node:fs";import{homedir as f}from"node:os";var p=e();const m=`open-knowledge`;function h(e){try{e()}catch{}}var g=class{backend=`keyring`;constructor(e){this.onKeychainRead=e}async get(e){let{Entry:t}=await import(`@napi-rs/keyring`),n;try{n=new t(m,e).getPassword()}catch(t){return h(()=>this.onKeychainRead?.({kind:`read-error`,host:e,error:t instanceof Error?t.name:`unknown`})),null}if(n==null)return h(()=>this.onKeychainRead?.({kind:`absent`,host:e})),null;try{return JSON.parse(n)}catch{return h(()=>this.onKeychainRead?.({kind:`corrupt-entry`,host:e,error:`corrupt-entry`})),null}}async set(e,t,n,r){let{Entry:i}=await import(`@napi-rs/keyring`),a=new i(m,e),o={login:t,token:n,...r};a.setPassword(JSON.stringify(o))}async clear(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{new t(m,e).deletePassword()}catch{}}},_=class{backend=`file`;authFile;constructor(e){this.authFile=e??s(f(),`.ok`,`auth.yml`)}read(){if(!c(this.authFile))return{};try{return(0,p.parse)(u(this.authFile,`utf-8`))??{}}catch(e){let t=e instanceof Error?e.message:`unknown error`;return process.stderr.write(`[auth] Failed to parse ${this.authFile}: ${t}. Starting with empty credentials.\n`),{}}}write(e){let t=o(this.authFile);c(t)||l(t,{recursive:!0,mode:448}),d(this.authFile,(0,p.stringify)(e),{mode:384})}async get(e){return this.read()[e]??null}async set(e,t,n,r){let i=this.read();i[e]={login:t,token:n,...r},this.write(i)}async clear(e){let t=this.read();delete t[e],this.write(t)}},v=class{backend=`keyring`;constructor(e,t){this.keychain=e,this.file=t}async get(e){let t=await this.keychain.get(e);if(t!=null)return t;let n=await this.file.get(e);if(n==null)return null;try{await this.keychain.set(e,n.login,n.token,{gitProtocol:n.gitProtocol,name:n.name,email:n.email}),await this.file.clear(e),process.stderr.write(`[auth] migrated ${e} credential from ~/.ok/auth.yml to the OS keychain\n`)}catch{}return n}set(e,t,n,r){return this.keychain.set(e,t,n,r)}async clear(e){await this.keychain.clear(e),await this.file.get(e)!=null&&await this.file.clear(e)}};async function y(e,t){try{let{Entry:n}=await import(`@napi-rs/keyring`);return new n(m,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
|
|
2
2
|
`),h(()=>t?.onBackendSelected?.({backend:`keyring`})),new v(new g(t?.onKeychainRead),new _(e))}catch(n){let r=n instanceof Error?`${n.name}: ${n.message}`:String(n);return process.stderr.write(`[auth] token storage: file (~/.ok/auth.yml) — OS keychain unavailable: ${r}\n`),h(()=>t?.onBackendSelected?.({backend:`file`,reason:r})),new _(e)}}function b(e){let t=null;return function(){if(t)return t;let n=2e3;return t=(async()=>{let t=null,r=new Promise(r=>{t=setTimeout(()=>{process.stderr.write(`[auth] token storage: keyring init exceeded ${n}ms; falling back to file (~/.ok/auth.yml)\n`),r(new _(e))},n)});try{return await Promise.race([y(e),r])}catch{return new _(e)}finally{t!==null&&clearTimeout(t)}})(),t}}function x(e){let t=b(e);return{async get(e){let n=await(await t()).get(e);return n===null?null:{token:n.token}}}}function S(e){let t=b(e);return{backend:`file`,async get(e){return(await t()).get(e)},async set(e,n,r,i){return(await t()).set(e,n,r,i)},async clear(e){return(await t()).clear(e)}}}async function C(e,t){let n=[],r=new _(t);await r.get(e)!=null&&(await r.clear(e),n.push(`file`));let i;try{let{Entry:t}=await import(`@napi-rs/keyring`);new t(m,`__probe__`);let r,a=await new g(e=>{e.kind===`read-error`&&(r=e.error??`read-error`)}).get(e);if(r!==void 0)i=r;else if(a!=null)try{new t(m,e).deletePassword(),n.push(`keychain`)}catch(e){i=e instanceof Error?e.name:`delete-error`}}catch{}return{touched:n,keychainError:i}}const w=[`/opt/homebrew/bin/gh`,`/usr/local/bin/gh`,`/opt/local/bin/gh`,`/snap/bin/gh`,`/usr/bin/gh`],T={encoding:`utf-8`,stdio:[`ignore`,`pipe`,`pipe`],timeout:5e3,windowsHide:!0};function E(e,t={}){let n=t._exec??a,r=t._fileExists??c,i=[`auth`,`token`,...e?[`--hostname`,e]:[]],o=[`gh`,...w.filter(r)];for(let e of o)try{let t=n(e,i,T).toString().trim();if(t.length>0)return{available:!0,token:t}}catch{}return{available:!1}}function D(e,a,o){let s=r[e],c=e===`opencode`?n:t,l=[],u=s.projectConfigPath?.(a);u!==void 0&&l.push({scope:`project`,configPath:u});try{l.push({scope:`user`,configPath:s.configPath(a,o)})}catch{}for(let t of l){let n=i(s,a,o,t.configPath);if(n!==null&&c(n))return{editorId:e,scope:t.scope,configPath:t.configPath}}return null}export{x as a,y as i,E as n,S as o,C as r,D as t};
|
|
3
|
-
//# sourceMappingURL=acp-harness-probe-
|
|
3
|
+
//# sourceMappingURL=acp-harness-probe-B3zP-iU3.mjs.map
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{o as e}from"./chunk-DTipWd-i.mjs";import{$a as t,$o as n,At as r,Cs as i,Fa as a,Ji as o,Q as s,To as c,Uo as l,Yi as u,ao as d,eo as f,ga as p,go as m,gs as h,ha as g,ko as _,kt as v,ma as y,to as b,tt as x,w as S,xo as C,zo as w}from"./src-
|
|
2
|
+
import{o as e}from"./chunk-DTipWd-i.mjs";import{$a as t,$o as n,At as r,Cs as i,Fa as a,Ji as o,Q as s,To as c,Uo as l,Yi as u,ao as d,eo as f,ga as p,go as m,gs as h,ha as g,ko as _,kt as v,ma as y,to as b,tt as x,w as S,xo as C,zo as w}from"./src-tAuEvoB8.mjs";import{$t as T,Bt as ee,F as te,Ft as ne,Gr as re,Hr as ie,I as ae,Kr as oe,L as se,Mt as ce,Nt as le,P as ue,Pt as E,Q as de,Vr as D,X as fe,Xr as pe,Y as me,Z as he,Zr as ge,_ as _e,_a as ve,_i as ye,_r as be,a as xe,ai as Se,at as Ce,ct as we,dt as Te,en as Ee,f as De,ft as Oe,ga as ke,gi as Ae,gr as je,gt as Me,hi as Ne,hn as Pe,it as Fe,kr as Ie,lt as Le,mr as Re,mt as ze,n as Be,nn as Ve,nt as He,oi as Ue,ot as We,p as Ge,pt as Ke,q as qe,qn as Je,qt as Ye,r as Xe,si as O,st as Ze,t as Qe,ui as $e,ut as et,va as tt,vn as nt,w as rt,ya as it,yn as at,yr as ot,zt as st}from"./src-zLMYDmwT.mjs";import{C as ct,Ft as lt,I as ut,K as dt,N as ft,St as pt,X as mt,a as ht,ct as gt,dt as k,et as _t,ht as A,l as vt,lt as yt,nt as j,r as bt,tt as M,ut as xt,v as St,vt as Ct,y as wt,z as Tt}from"./sleep-IcuyYCzq.mjs";import{O as Et,P as Dt,k as Ot}from"./fs-traced-B-x7hAhD.mjs";import{a as kt}from"./git-handle-bsekfuqb.mjs";import{g as At,i as jt,x as Mt}from"./server-lock-Cdm6cZ-8.mjs";import{C as N,c as Nt,d as Pt,l as Ft,n as It,x as Lt}from"./write-project-skill-xt4ohzdz.mjs";import{C as Rt,D as zt,E as Bt,S as Vt,T as Ht,a as Ut,b as Wt,d as Gt,i as Kt,m as qt,o as Jt,p as Yt,s as Xt,v as Zt,x as Qt,y as $t}from"./src-DrNAleIl.mjs";import{c as en,i as P,n as F,o as I,r as L,s as R,t as z}from"./colors-BsmVIwfM.mjs";import{i as tn,n as nn,o as rn,r as an}from"./acp-harness-probe-B3zP-iU3.mjs";import{n as on,r as sn,t as cn}from"./dist-bundle-CFfKBclM.mjs";import{A as ln,B as un,C as dn,F as fn,H as pn,L as mn,M as hn,N as gn,O as _n,P as vn,R as yn,T as bn,U as xn,V as Sn,j as Cn,u as wn,w as Tn,z as En}from"./init-BSRAJcxJ.mjs";import{n as Dn,t as On}from"./constants-DJEQ5lbI.mjs";import{C as kn,D as An,E as jn,T as Mn,h as Nn,v as Pn,w as Fn}from"./start-Bx6I5bEA.mjs";import{n as In,t as Ln}from"./loader-7F0JSi2o.mjs";import{t as Rn}from"./launch-json-removal-Z49VHJab.mjs";import{n as zn}from"./repair-skills-BW5UCBvh.mjs";import{execFile as Bn,execFileSync as Vn,execSync as Hn,spawn as Un,spawnSync as Wn}from"node:child_process";import{basename as Gn,dirname as Kn,isAbsolute as qn,join as B,relative as V,resolve as H,sep as Jn}from"node:path";import{accessSync as Yn,appendFileSync as Xn,closeSync as Zn,constants as Qn,existsSync as U,lstatSync as $n,mkdirSync as er,mkdtempSync as tr,openSync as nr,readFileSync as W,readdirSync as rr,realpathSync as ir,renameSync as ar,rmSync as or,statSync as G,unlinkSync as sr,writeFileSync as cr}from"node:fs";import{homedir as lr,platform as ur,tmpdir as dr}from"node:os";import{rm as fr}from"node:fs/promises";import pr from"node:process";import{fileURLToPath as mr}from"node:url";import{randomUUID as hr}from"node:crypto";import{setTimeout as gr}from"node:timers/promises";import{promisify as _r}from"node:util";import{createServer as vr,request as yr}from"node:http";import{createInterface as br}from"node:readline/promises";import{connect as xr}from"node:net";const Sr={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 Cr;(function(e){})(Cr||={});function wr(e){return pt(mt,e)}async function Tr(e){let{projectDir:t,contentDir:n,baseConfig:r,targetPath:i,fix:a=!1}=e,s=[],c=Ie({projectDir:t,contentDir:n}),l=new Set,d=e=>{l.has(e)||(l.add(e),s.push(e))},f=be(t,r,d),p=new Map,m=e=>{let t=Kn(e),r=p.get(t);if(r)return r;let i=je(f,ot(n,e,d));return p.set(t,i),i},h=[],g=Er(i,n);g.kind===`file`?h.push(V(n,g.path)):_(g.path);function _(e){let t;try{t=rr(e,{withFileTypes:!0})}catch(t){s.push(`could not read directory ${V(n,e)||`.`}: ${Or(t)}`);return}for(let r of t){if(r.name.startsWith(`.`))continue;let t=B(e,r.name),i=V(n,t);if(r.isDirectory()){if(c.isDirExcluded(i))continue;_(t)}else if(r.isFile()){if(!Dr(r.name)||c.isExcluded(i))continue;h.push(i)}}}h.sort();let v=[],y=0,b=0,x=0;for(let e of h){let t=B(n,e),r;try{r=W(t,`utf-8`)}catch(t){s.push(`could not read ${e}: ${Or(t)}`);continue}let i=m(e),c=!1;if(a&&i.enabled){let n=o(r,i);if(n!==r){let i=`${t}.tmp.${process.pid}.${Date.now()}`;try{cr(i,n,`utf-8`),ar(i,t),r=n,c=!0,x++}catch(t){try{sr(i)}catch{}s.push(`could not write fix to ${e}: ${Or(t)}`)}}}let l=await u(r,i,e);for(let e of l)e.severity===`error`?y++:b++;v.push({file:e,diagnostics:l,fixed:c})}return{contentDir:n,files:v,warnings:s,fileCount:h.length,errorCount:y,warningCount:b,fixedCount:x}}function Er(e,t){if(e===void 0||e===``)return{kind:`dir`,path:t};let n=qn(e)?e:H(t,e);try{if(G(n).isFile())return{kind:`file`,path:n}}catch{}return{kind:`dir`,path:n}}function Dr(e){let t=e.toLowerCase();return l.some(e=>t.endsWith(e))}function Or(e){return e instanceof Error?e.message:String(e)}function kr(e){return new N(`lint`).description(`Lint markdown content (headless) — whole project, a folder, or a single file`).argument(`[path]`,`Folder or file to lint, relative to where you run the command`).option(`--json`,`Emit structured JSON instead of formatted text`).option(`--fix`,`Auto-fix fixable issues in place (markdownlint rules only)`).option(`--errors-only`,`Exit non-zero only on error-severity problems (findings are warning-severity unless your .markdownlint.* assigns a rule "error")`).action(async(t,n)=>{let r=e(),i=process.cwd(),a=Ue(r,i),o=t===void 0?void 0:Ar(t,Ht()),s=r.contentRules,c=await Tr({projectDir:i,contentDir:a,baseConfig:s?g(s):p,targetPath:o,fix:n.fix===!0});n.json===!0?process.stdout.write(`${JSON.stringify(c,null,2)}\n`):process.stdout.write(`${Nr(c)}\n`),(n.errorsOnly===!0?c.errorCount>0:jr(c))&&(process.exitCode=1)})}function Ar(e,t){return H(t,e)}function jr(e){return e.errorCount>0||e.warningCount>0}function Mr(e){let t=[z(e.file)+(e.fixed?F(` (fixed)`):``)];for(let n of e.diagnostics){let e=F(`${n.range.start.line+1}:${n.range.start.character+1}`.padEnd(7)),r=n.severity===`error`?L(`error `):R(`warning`);t.push(` ${e} ${r} ${n.message} ${F(`${n.source}/${n.code}`)}`)}return t.push(``),t}function Nr(e){let t=[];for(let n of e.files)n.diagnostics.length>0&&t.push(...Mr(n));for(let n of e.warnings)t.push(R(`! ${n}`));e.warnings.length>0&&t.push(``);let n=e.errorCount+e.warningCount;if(n===0)t.push(I(`✓ No problems in ${e.fileCount} file${e.fileCount===1?``:`s`}.`));else{let r=[`${n} problem${n===1?``:`s`}`];r.push(`${e.errorCount} error${e.errorCount===1?``:`s`}`),r.push(`${e.warningCount} warning${e.warningCount===1?``:`s`}`),t.push(`${L(r[0]??``)} (${r[1]}, ${r[2]}) across ${e.fileCount} file${e.fileCount===1?``:`s`}.`)}return e.fixedCount>0&&t.push(F(`Fixed ${e.fixedCount} file${e.fixedCount===1?``:`s`}.`)),t.join(`
|
|
3
3
|
`)}const Pr={out:e=>process.stdout.write(`${e}\n`),err:e=>process.stderr.write(`${e}\n`)};function Fr(e){return new N(`audit`).description(`Unified validation audit (markdown lint + broken internal links) via the running project server`).argument(`[path]`,`Folder or file to audit, relative to where you run the command`).option(`--json`,`Emit the full structured JSON response instead of formatted text`).option(`--errors-only`,`Exit non-zero only on error-severity problems (broken links default to warnings; the project's validation.links setting can raise them to errors)`).action(async(t,n)=>{let r=await Ir(t,n,e(),process.cwd(),Ht());r!==0&&(process.exitCode=r)})}async function Ir(e,t,n,r,i,a=Pr){let o=Ue(n,r),s;if(e!==void 0){let t=Lr(e,i,o);if(t===null)return a.err(`Path is outside the content directory (${o}): ${e}`),1;s=t===``?void 0:t}let c=jt(O(r));if(!c||c.port<=0)return a.err("OpenKnowledge server is not running — the links validator needs the live backlink index. Start it with `ok start` (or open OK Desktop) and re-run. For headless lint-only checks, use `ok lint`."),1;let l=s===void 0?``:`?path=${encodeURIComponent(s)}`,u;try{u=await fetch(`http://127.0.0.1:${c.port}/api/audit${l}`,{headers:h({kind:`cli`,runtimeVersion:At})})}catch(e){return a.err(`Could not reach the OpenKnowledge server on port ${c.port}: ${String(e)}`),1}if(!u.ok){let e=await u.json().catch(()=>({}));return a.err(`Audit failed: ${e.title??e.error??e.message??`server responded with ${u.status}`}`),1}let d=y.safeParse(await u.json().catch(()=>null));if(!d.success){let e=d.error.issues.map(e=>`${e.path.join(`.`)}: ${e.message}`).join(`; `);return a.err(`Audit failed: unexpected response shape from the server. Schema issues: ${e}`),1}let f=d.data;return t.json===!0?a.out(JSON.stringify(f,null,2)):a.out(Nr(Rr(f))),+(t.errorsOnly===!0?f.errorCount>0:f.errorCount+f.warningCount>0)}function Lr(e,t,n){let r=V(n,H(t,e));return r===``?``:r.startsWith(`..`)||qn(r)?null:r.split(Jn).join(`/`)}function Rr(e){return{files:e.files.map(e=>({file:e.file,fixed:!1,diagnostics:e.diagnostics})),warnings:e.warnings,fileCount:e.fileCount,errorCount:e.errorCount,warningCount:e.warningCount,fixedCount:0}}async function zr(e,t,n,r){let i=Br(await Vr(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 Br(e){let t={};for(let n of e.split(`
|
|
4
4
|
`)){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 Vr(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 Hr(e,t){let n=new N(`git-credential`);return n.description(`Git credential helper (git credential-helper protocol)`),n.command(`get`).description(`Lookup credentials from TokenStore (called by git)`).action(async()=>{let n=t?.();try{let t,r=await e({onKeychainRead:e=>{t=e},onBackendSelected:e=>{e.backend===`file`&&e.reason&&n?.warn({backend:`file`,reason:e.reason},`[auth] token storage fallback`)}}),i=await zr(process.stdin,process.stdout,r,{log:n,getDiag:()=>t});await Ge(n),process.exit(i)}catch(e){n?.error({err:e},`[auth] git-credential get: unexpected error`),await Ge(n),process.exit(1)}}),n}function Ur(e){let t=e.endpoint.DEFAULTS;return/^https:\/\/(api\.)?github\.com$/.test(t.baseUrl)?`https://github.com`:t.baseUrl.replace(`/api/v3`,``)}async function Wr(e,t,n){let r={baseUrl:Ur(e),headers:{accept:`application/json`},...n},i=await e(t,r);if(`error`in i.data){let n=new on(`${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 Gr(e){let t=e.request||cn,n={client_id:e.clientId};return`scopes`in e&&Array.isArray(e.scopes)&&(n.scope=e.scopes.join(` `)),Wr(t,`POST /login/device/code`,n)}async function Kr(e){let t=await Wr(e.request||cn,`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=qr(e,t.data.expires_in),n.refreshTokenExpiresAt=qr(e,t.data.refresh_token_expires_in)}delete n.scopes}return{...t,authentication:n}}function qr(e,t){return new Date(e+t*1e3).toISOString()}async function Jr(e,t){let n=Yr(e,t.auth);if(n)return n;let{data:r}=await Gr({clientType:e.clientType,clientId:e.clientId,request:t.request||e.request,scopes:t.auth.scopes||e.scopes});await e.onVerification(r);let i=await Zr(t.request||e.request,e.clientId,e.clientType,r);return e.authentication=i,i}function Yr(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 Xr(e){await new Promise(t=>setTimeout(t,e*1e3))}async function Zr(e,t,n,r){try{let i={clientId:t,request:e,code:r.device_code},{authentication:a}=n===`oauth-app`?await Kr({...i,clientType:`oauth-app`}):await Kr({...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 Xr(r.interval),Zr(e,t,n,r);if(a===`slow_down`)return await Xr(r.interval+7),Zr(e,t,n,r);throw i}}async function Qr(e,t){return Jr(e,{auth:t})}async function $r(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 Jr(e,{request:t,auth:{type:`oauth`}});return i.headers.authorization=`token ${a}`,t(i)}var ei=`0.0.0-development`;function ti(e){let t=e.request||cn.defaults({headers:{"user-agent":`octokit-auth-oauth-device.js/${ei} ${sn()}`}}),{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(Qr.bind(null,i),{hook:$r.bind(null,i)})}async function ni(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=ti({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-BT5p_5Yl.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 ri(){return process.env.OPEN_KNOWLEDGE_GITHUB_CLIENT_ID??`Ov23liqlSd0V1MwR6rhI`}function ii(e){let t=e.toLowerCase().replace(/:\d+$/,``);_.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 ai(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function oi(e,t,n=ni){let r=ri(),{host:i,json:a}=e;ii(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?ai(!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?ai(!0,{type:`complete`,host:i,login:s}):process.stderr.write(`✓ Logged in as ${s} on ${i}\n`)}function si(e){return new N(`login`).description(`Authenticate with GitHub via Device Flow`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname (default: workspace origin host)`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{let n=t.host??Re(process.cwd()),r=await e();await oi({...t,host:n},r)})}const ci={style:{maskedText:`[input is masked]`}};var li=mn((e,t)=>{let{validate:n=()=>!0}=e,r=Sn(ci,e.theme),[i,a]=pn(`idle`),[o,s]=pn(),[c,l]=pn(``),u=un({status:i,theme:r});En(async(e,r)=>{if(i===`idle`)if(xn(e)){let e=c;a(`loading`);let i=await n(e);i===!0?(l(e),a(`done`),t(e)):(r.write(c),s(i||`You must provide a valid value`),a(`idle`))}else l(r.line),s(void 0)});let d=r.style.message(e.message,i),f=``,p;e.mask?f=(typeof e.mask==`string`?e.mask:`*`).repeat(c.length):i!==`done`&&(p=`${r.style.help(r.style.maskedText)}${yn}`),i===`done`&&(f=r.style.answer(f));let m=``;return o&&(m=r.style.error(o)),[[u,d,e.mask?f:p].join(` `),m]});function ui(e,t,n,r){if(typeof n!=`function`)throw Error(`method for before hook must be a function`);return r||={},Array.isArray(t)?t.reverse().reduce((t,n)=>ui.bind(null,e,n,t,r),n)():Promise.resolve().then(()=>e.registry[t]?e.registry[t].reduce((e,t)=>t.hook.bind(null,e,r),n)():n(r))}function di(e,t,n,r){let i=r;e.registry[n]||(e.registry[n]=[]),t===`before`&&(r=(e,t)=>Promise.resolve().then(i.bind(null,t)).then(e.bind(null,t))),t===`after`&&(r=(e,t)=>{let n;return Promise.resolve().then(e.bind(null,t)).then(e=>(n=e,i(n,t))).then(()=>n)}),t===`error`&&(r=(e,t)=>Promise.resolve().then(e.bind(null,t)).catch(e=>i(e,t))),e.registry[n].push({hook:r,orig:i})}function fi(e,t,n){if(!e.registry[t])return;let r=e.registry[t].map(e=>e.orig).indexOf(n);r!==-1&&e.registry[t].splice(r,1)}const pi=Function.bind,mi=pi.bind(pi);function hi(e,t,n){let r=mi(fi,null).apply(null,n?[t,n]:[t]);e.api={remove:r},e.remove=r,[`before`,`error`,`after`,`wrap`].forEach(r=>{let i=n?[t,r,n]:[t,r];e[r]=e.api[r]=mi(di,null).apply(null,i)})}function gi(){let e=Symbol(`Singular`),t={registry:{}},n=ui.bind(null,t,e);return hi(n,t,e),n}function _i(){let e={registry:{}},t=ui.bind(null,e);return hi(t,e),t}var vi={Singular:gi,Collection:_i},yi=`0.0.0-development`;function bi(e){return`Request failed due to following response errors:
|
|
5
5
|
`+e.errors.map(e=>` - ${e.message}`).join(`
|
|
@@ -8,9 +8,9 @@ import{o as e}from"./chunk-DTipWd-i.mjs";import{$a as t,$o as n,At as r,Cs as i,
|
|
|
8
8
|
`),n.includes(`file`)&&process.stderr.write(` cleared from ~/.ok/auth.yml
|
|
9
9
|
`)}function ma(){return new N(`signout`).description(`Remove stored credentials`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname (default: workspace origin host)`).action(async e=>{let t=e.host??Re(process.cwd());await pa({...e,host:t})})}async function ha(e,t,n=nn){let r=n(e);if(r.available&&r.token)return{tier:`A`,token:r.token};let i=await t.get(e);return i==null?{tier:`none`}:{tier:i.gitProtocol===`ssh`?`C`:`B`,token:i.token}}function ga(e,t,n){return{type:`status`,host:e,backend:t,...n}}async function _a(e,t){let{host:n,json:r}=e;ii(n);let i=t.backend,a=await ha(n,t);a.tier===`none`&&(r?process.stdout.write(`${JSON.stringify(ga(n,i,{authenticated:!1}))}\n`):process.stderr.write(`Not logged in to ${n}\n`),process.exit(1));let o=n===`github.com`?void 0:`https://${n}/api/v3`,s=new ra({auth:a.token,...o?{baseUrl:o}:{}});try{let{data:e}=await s.users.getAuthenticated();r?process.stdout.write(`${JSON.stringify(ga(n,i,{authenticated:!0,tier:a.tier,login:e.login,name:e.name,email:e.email}))}\n`):process.stderr.write(`✓ Logged in as ${e.login} on ${n}\n`)}catch(e){let t=oa(e,n);r?process.stdout.write(`${JSON.stringify(ga(n,i,{authenticated:!1,error:t.message}))}\n`):process.stderr.write(`✗ ${t.message}\n`),process.exit(1)}}function va(e){return new N(`status`).description(`Show authentication status`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname (default: workspace origin host)`).option(`--json`,`Output JSON`,!1).action(async t=>{let n=t.host??Re(process.cwd());await _a({...t,host:n},await e())})}function ya(e){let t=new N(`auth`);t.description(`GitHub authentication management`);let n=e=>tn(void 0,e);return t.addCommand(si(n)),t.addCommand(va(n)),t.addCommand(fa(n)),t.addCommand(ma()),t.addCommand(la(n)),t.addCommand(Hr(n,e)),t}function ba(){return new N(`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=>{try{let{zipPath:t,summary:n}=await Wt({level:`standard`,projectDir:process.cwd(),redact:!0,outputPath:Rt(),logger:Nf()});if(process.stdout.write(`${t}\n`),n.redactedLineCount>0&&process.stderr.write(`ok bug-report: ${n.redactedLineCount} line(s) auto-redacted across ${n.redactions.length} file(s)\n`),e.reveal&&ur()===`darwin`)try{An(`/usr/bin/open`,[`-R`,t])}catch{}}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`ok bug-report: failed — ${t}\n`),process.exitCode=1}})}function xa(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 Sa(e){let t=e.inspect??(t=>$t(e.lockDir,t)),n=e.unlink??(e=>sr(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=xa(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 Ca(e){return new N(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{e(),Sa({lockDir:O(process.cwd())}).failed.length>0&&(process.exitCode=1)})}function wa(e){return`credential.helper=!${e.map(d).join(` `)} auth git-credential`}async function Ta(e,t,n={},r=nn){let i=[`credential.helper=`,wa(n.selfCliArgs??[`open-knowledge`])];if(!n.skipGhDetect){let t=r(e);if(t.available&&t.token)return{tier:`A`,gitConfig:i,relayToken:{token:t.token,host:e}}}let a=await t.get(e);return a==null?{tier:`none`,gitConfig:[]}:{tier:a.gitProtocol===`ssh`?`C`:`B`,gitConfig:i}}async function Ea(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 Da=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function Oa(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 Da)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 ka(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,t=process.env){let n=ka(t);return e.relayToken?(n.OK_GH_TOKEN=e.relayToken.token,n.OK_GH_TOKEN_HOST=e.relayToken.host):(delete n.OK_GH_TOKEN,delete n.OK_GH_TOKEN_HOST),n}function ja(e=process.argv,t=process.execPath){let n=e[1];return n?[t,n]:[t]}function Ma(e){return typeof e!=`string`||e.length===0?[`--progress`]:[`--progress`,`-b`,e]}const Na=f;async function Pa(e){try{return await e.clone(Ma(e.branch)),{fellBack:!1}}catch(t){if(e.branch!==null&&Na(t))return e.onFallback(e.branch),await e.clone(Ma(null)),{fellBack:!0};throw t}}function Fa(e,t){return{baseDir:e,config:t,unsafe:{allowUnsafeCredentialHelper:!0,allowUnsafePager:!0,allowUnsafeSshCommand:!0,allowUnsafeAskPass:!0,allowUnsafeEditor:!0}}}function Ia(e,t,n){return e===`https`&&t===`github.com`&&n}function La(e,t){let n=`${t.owner}/${t.name}`;return e===n||e===`${n}.git`?`https://${t.hostname}/${n}`:e}async function Ra(e,t,n,r=process.cwd()){let i=Zt(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=La(e,i),o=t.dir?H(r,t.dir):H(r,i.name);if(U(o)&&rr(o).length>0)throw Error(`Target directory is not empty: ${o}`);Ve();let s=rn(),c=i.protocol===`https`&&i.hostname===`github.com`?await Ea(i.owner,i.name):!1,l=Ia(i.protocol,i.hostname,c)?{tier:`none`,gitConfig:[]}:await Ta(i.hostname,s,{selfCliArgs:ja()}),u=Aa(l),d=kt(Fa(r,l.gitConfig)).env(u),f=-1;d.outputHandler((e,n,r)=>{r.on(`data`,e=>{let n=e.toString(`utf-8`);for(let e of n.split(`
|
|
10
10
|
`)){let n=Oa(e);n&&n.pct!==f&&(f=n.pct,q(t.json,{type:`progress`,pct:n.pct,stage:n.stage}),t.json||process.stderr.write(`\r Cloning ${n.pct}%`))}})}),await Pa({branch:typeof t.branch==`string`&&t.branch.length>0?t.branch:null,clone:e=>d.clone(a,o,e),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(`
|
|
11
|
-
`);try{let{runInit:e}=await import(`./init-
|
|
11
|
+
`);try{let{runInit:e}=await import(`./init-Nj3Qfja6.mjs`),n=await e({cwd:o,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{za(o)}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 o}function za(e){let t=_n(e,[`.ok/`]);return t.kind===`no-exclude`?`no-exclude`:t.kind===`refused-tracked`?`already-present`:t.appended.length>0?`appended`:`already-present`}const Ba=/^[A-Za-z0-9._/:@-]+$/;function Va(e){return Ba.test(e)?e:d(e)}function Ha(e,t){let n=typeof t==`string`&&t.length>0?` -b ${Va(t)}`:``;return`ok clone ${Va(e)}${n}`}function Ua(e){let n=t(e.error);if(n.kind!==`auth`)return null;if(b(n)){let t=Ha(e.url,e.branch);return[`✗ Couldn't clone ${e.url} — authentication is required.`,``,` To fix:`,` 1. Run: ok auth login`,` 2. Then re-run: ${t}`].join(`
|
|
12
12
|
`)}if(n.subclass===`403`){let t=typeof e.principal==`string`&&e.principal.length>0?` (signed in as @${e.principal} — may lack access)`:``;return`✗ Access denied when cloning ${e.url}${t}. Check that your account has access to the repository.`}return n.subclass===`ssh-auth`?`✗ Couldn't clone ${e.url} over SSH — authentication failed. Check that your SSH key is added to your GitHub account and the host key is trusted, or clone the HTTPS URL instead.`:["✗ Your GitHub token is missing required OAuth scopes — likely the `repo` scope.",``,` To fix:`," 1. Create a token with `repo` scope at https://github.com/settings/tokens",` 2. Run: ok auth pat`,` 3. Then re-run: ${Ha(e.url,e.branch)}`].join(`
|
|
13
|
-
`)}function Wa(e){let t=e.error instanceof Error?e.error.message:String(e.error);if(e.json){e.emit({type:`error`,message:t});return}let n=Ua({error:e.error,url:e.url,branch:e.branch,principal:e.principal});e.printStderr(`${n??`✗ ${t}`}\n`)}async function Ga(e,t){let n=(await e.get(t))?.login;return n&&n!==`unknown`?n:null}async function Ka(e){let n=t(e.error),r=null;if(!e.json&&n.kind===`auth`&&n.subclass===`403`){let t=Zt(e.url);t&&(r=await(e.resolvePrincipal??(e=>Ga(rn(),e)))(t.hostname))}Wa({error:e.error,url:e.url,branch:e.branch,json:e.json,principal:r,emit:e.emit,printStderr:e.printStderr})}function qa(e){return new N(`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 Ra(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-
|
|
13
|
+
`)}function Wa(e){let t=e.error instanceof Error?e.error.message:String(e.error);if(e.json){e.emit({type:`error`,message:t});return}let n=Ua({error:e.error,url:e.url,branch:e.branch,principal:e.principal});e.printStderr(`${n??`✗ ${t}`}\n`)}async function Ga(e,t){let n=(await e.get(t))?.login;return n&&n!==`unknown`?n:null}async function Ka(e){let n=t(e.error),r=null;if(!e.json&&n.kind===`auth`&&n.subclass===`403`){let t=Zt(e.url);t&&(r=await(e.resolvePrincipal??(e=>Ga(rn(),e)))(t.hostname))}Wa({error:e.error,url:e.url,branch:e.branch,json:e.json,principal:r,emit:e.emit,printStderr:e.printStderr})}function qa(e){return new N(`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 Ra(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-MnLPFpd0.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){if(e instanceof T||e instanceof Ee){r.json?q(!0,{type:`error`,message:e.message}):process.stderr.write(`${e.message}\n`),process.exitCode=78;return}await Ka({error:e,url:t,branch:r.branch??null,json:r.json,emit:e=>q(!0,e),printStderr:e=>process.stderr.write(e)}),process.exitCode=1}})}var Ja=dt();const Ya=[[`sync`],[`persistence`,`debounceMs`],[`persistence`,`maxDebounceMs`],[`server`,`port`],...ht.map(e=>e.path)];function Xa(e={}){let t=e.log??(e=>console.error(e)),n=e.error??(e=>console.error(e)),r=e.loadConfigFn??In;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 Za(e){let t=(0,Ja.parseDocument)(W(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 Ya)t.hasIn(e)&&n.push(e.join(`.`));return n}function Qa(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=Qa(i)?i:{};e[r]=a,e=a}e[n[n.length-1]]=null}return t}async function eo(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??Ot,s=[];(r===`project`||r===`both`)&&s.push({scope:`project`,absPath:Et(`project`,a,e.homedirOverride)}),(r===`user`||r===`both`)&&s.push({scope:`user`,absPath:Et(`user`,a,e.homedirOverride)});let c=[],l=!0;for(let{scope:t,absPath:n}of s){if(!U(n)){c.push({path:n,scope:t,found:[],removed:[]});continue}let r;try{r=Za(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(Ya.filter(e=>r.includes(e.join(`.`)))),homedirOverride:e.homedirOverride});if(!s.ok){c.push({path:n,scope:t,found:r,removed:[],error:vt(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 to(){let e=new N(`config`).description(`Inspect and maintain OpenKnowledge configuration files`);return e.command(`validate`).description(`Validate the merged config (defaults → user → project)`).action(()=>{Xa({}).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 eo({scope:t,dryRun:e.dryRun})).ok||(process.exitCode=1)}),e}const no=[` 1. ${z(`Customize`)} (sidebar) → ${z(`Skills`)}`,` 2. Click the ${z(`+`)} button`,` 3. Click ${z(`Create skill`)}`,` 4. Click ${z(`Upload skill`)}`,` 5. Pick ${z(`openknowledge.skill`)} from Downloads`],ro=P(` Open the Claude Desktop App, then: ${z(`Customize → Skills → + → Create skill → Upload skill`)} → pick the file.`);function io(e){let t=[I(`Built ${e.outputPath}`),F(` ${e.size} bytes • sha256 ${e.sha256?.slice(0,12)}…`)];return e.handoffError&&t.push(R(` Handoff failed: ${e.handoffError.message}`)),t.push(ro),t.join(`
|
|
14
14
|
`)}function ao(e){let t=e.skillVersion??`unknown`,n=e.recordedAt??`unknown`;return[P(`OpenKnowledge skill ${z(`v${t}`)} already delivered to Claude Desktop.`),F(` Recorded at ${n} in ~/.ok/skill-state.yml`),F(` Use ${z(`--force`)} to rebuild and re-open the install dialog.`)].join(`
|
|
15
15
|
`)}function oo(e){let t=e.skillVersion?` • Skill v${e.skillVersion}`:``;return[I(`Built ${e.outputPath}`),F(` ${e.size} bytes • sha256 ${e.sha256?.slice(0,12)}…${t}`),P(` Claude Desktop App opened. Now upload the file manually:`),...no,F(` If Claude Desktop didn't open, open it and start at step 1. The file is at ${e.outputPath}`)].join(`
|
|
16
16
|
`)}function so(e){return`${L(`Error:`)} ${e.buildError??`unknown build failure`}`}async function co(e={}){let t=await Je(e);return t.status===`failed`?{...t,message:so(t),exitCode:1}:t.status===`skip-current`?{...t,message:ao(t),exitCode:0}:t.status===`installed`?{...t,message:oo(t),exitCode:0}:{...t,message:io(t),exitCode:0}}function lo(){return new N(`cowork`).description("Build openknowledge.skill and open the Claude Desktop App so you can upload it for Claude Chat & Cowork. (Advanced/rarely needed — `ok init` already wires Claude.)").option(`--out <path>`,`Custom output path (default: ~/Downloads/openknowledge.skill)`).option(`--no-open`,`Build the file but skip the OS file-association handoff`).option(`--force`,`Bypass the install-state gate and rebuild unconditionally`).action(async e=>{let t=await co({out:e.out,noOpen:!e.open,force:e.force??!1});process.stdout.write(`${t.message}\n`),t.exitCode!==0&&process.exit(t.exitCode)})}async function uo(e,t){let n=br({input:t??process.stdin,output:process.stderr});try{let t=(await n.question(e)).trim().toLowerCase();return t===`y`||t===`yes`}finally{n.close()}}function fo(e={}){let t=e.productName??`OpenKnowledge`;return B(Lt(e),t)}function po(e){if(typeof e!=`object`||!e)return null;let t=e.recentProjects;if(!Array.isArray(t))return null;let n=[];for(let e of t){if(typeof e!=`object`||!e)continue;let t=e;typeof t.path==`string`&&typeof t.name==`string`&&n.push({path:t.path,name:t.name})}return n}function mo(e){let t=B(e,`state.json`);if(!U(t))return[];let n;try{n=JSON.parse(W(t,`utf-8`))}catch{return[]}return po(n)??[]}function ho(e){let t=B(e,`state.json`);if(!U(t))return!1;try{return po(JSON.parse(W(t,`utf-8`)))!==null}catch{return!1}}function J(e,t){return e===t?`~`:e.startsWith(`${t}/`)?`~${e.slice(t.length)}`:e}function go(e){return Jn===`/`?e:e.split(Jn).join(`/`)}function _o(e,t,n=`This project`){let r=[];r.push({kind:`stop-server`,group:n,label:`Stop the project server (if running)`,lockDir:O(e)});let i=new Set;for(let a of Ft){let o=Pt[a];if(!o.projectConfigPath)continue;let s=o.projectConfigPath(e);i.add(go(V(e,s))),r.push({kind:`mcp-entry`,group:n,label:`Remove OK's MCP entry from ${o.label} (${go(V(e,s))})`,editorId:a,scope:`project`,cwd:e,home:t,configPath:s})}r.push({kind:`launch-entry`,group:n,label:`Remove OK's entry from .claude/launch.json`,projectRoot:e}),r.push({kind:`git-exclude`,group:n,label:`Remove OK paths from .git/info/exclude`,projectRoot:e});let a=new Set([...Cn(e),...w]);for(let t of a){let a=t.replace(/\/$/,``);i.has(a)||a!==`.claude/launch.json`&&r.push({kind:`remove-path`,group:n,label:`Remove ${t}`,path:B(e,a),containWithin:e})}try{r.push({kind:`remove-path`,group:n,label:`Remove the OK shadow repo (.git/ok/)`,path:it(e)})}catch{}return r}function vo(e,t){return{scope:`deinit`,ops:_o(e,t)}}function yo(e){let{home:t,platform:n,host:r,lockDirs:i,marker:a,recentDeinitProjectRoots:o,purgeContent:s}=e,c=[];for(let e of i)c.push({kind:`stop-server`,group:`Running servers`,label:`Stop server at ${J(B(e,`..`,`..`),t)}`,lockDir:e});c.push({kind:`keychain-token`,group:`Credentials`,label:`Remove the GitHub credential (${r}) from the OS keychain + auth.yml`,host:r}),c.push({kind:`embeddings-key`,group:`Credentials`,label:`Remove all embeddings API keys (secrets.yml)`}),c.push(...xo(a,t));for(let e of Ft){let n=Pt[e],r;try{r=n.configPath(``,t)}catch{continue}c.push({kind:`mcp-entry`,group:`Editor MCP configs`,label:`Remove OK's MCP entry from ${n.label} (${J(r,t)})`,editorId:e,scope:`user`,cwd:t,home:t,configPath:r})}for(let e of Nt(t))c.push({kind:`remove-path`,group:`Skill bundles`,label:`Remove ${J(e.path,t)}`,path:e.path});c.push(...So(t,n,e.env));for(let e of o)c.push(..._o(e,t,`Project: ${Gn(e)}`));return c.push({kind:`remove-path`,group:`Global directory`,label:s?`Remove ~/.ok (including user-authored skills)`:`Remove ~/.ok (keeping ~/.ok/skills)`,path:B(t,`.ok`),preserve:s?void 0:[`skills`]}),{scope:`uninstall`,ops:c}}function bo(e){return[B(e,`.zshrc`),B(e,`.bash_profile`),B(e,`.config`,`fish`,`conf.d`,`open-knowledge.fish`)]}function xo(e,t){let n=[],r=new Set([...bo(t),...e?.rcFiles??[]]);for(let e of r)U(e)&&n.push({kind:`shell-block`,group:`Shell PATH`,label:`Strip the OK block from ${J(e,t)}`,rcFile:e});for(let r of e?.extraSymlinks??[])n.push({kind:`extra-symlink`,group:`Shell PATH`,label:`Remove the ok symlink at ${J(r.path,t)}`,path:r.path,target:r.target});return n}function So(e,t,n){if(t!==`darwin`)return[];let r={home:e,platformName:t,env:n},i=fo(r),a=fo({...r,productName:`Open Knowledge`}),o=B(e,`Library`,`Caches`,`OpenKnowledge-updater`);return[{kind:`remove-path`,group:`Application data`,label:`Remove ${J(i,e)}`,path:i},{kind:`remove-path`,group:`Application data`,label:`Remove ${J(a,e)} (only if it is OpenKnowledge's)`,path:a,requireOurState:!0},{kind:`remove-path`,group:`Application data`,label:`Remove ${J(o,e)}`,path:o}]}async function Co(e,t={}){let n=t.clearToken??an,r=t.clearEmbeddingsKey??re,i=t.stopServer??(e=>{let t=Kt({lockDir:e,log:()=>{},error:()=>{}});return{stopped:t.stopped.length,failed:t.failed.map(e=>({pid:e.target.pid,error:e.error}))}}),a=[];for(let t of e.ops)try{a.push(await wo(t,{clearToken:n,clearEmbeddingsKey:r,stopServer:i}))}catch(e){a.push({op:t,status:`failed`,detail:e instanceof Error?e.message:String(e)})}return{results:a,removed:a.filter(e=>e.status===`removed`),failed:a.filter(e=>e.status===`failed`)}}async function wo(e,t){switch(e.kind){case`stop-server`:{let{stopped:n,failed:r}=t.stopServer(e.lockDir);return r.length>0?{op:e,status:`failed`,detail:`could not stop the server (${r.map(e=>`pid ${e.pid}: ${e.error}`).join(`; `)}); a process may still be using files that were removed`}:{op:e,status:n>0?`removed`:`not-present`}}case`keychain-token`:{let{touched:n,keychainError:r}=await t.clearToken(e.host);return r?{op:e,status:`failed`,detail:`keychain unreachable (${r}); remove manually: Keychain Access → service "open-knowledge"`}:{op:e,status:n.length>0?`removed`:`not-present`}}case`embeddings-key`:{let{touched:n}=await t.clearEmbeddingsKey();return{op:e,status:n.length>0?`removed`:`not-present`}}case`shell-block`:{if(!U(e.rcFile))return{op:e,status:`not-present`};let{text:t,changed:n,emptyAfter:r}=qt(W(e.rcFile,`utf-8`));return n?r?(or(e.rcFile,{force:!0}),{op:e,status:`removed`,detail:`file removed (was OK-owned)`}):(Dt(e.rcFile,t,{mode:bn(e.rcFile)}),{op:e,status:`removed`}):{op:e,status:`not-present`}}case`extra-symlink`:return Gt(e.path,e.target)?(sr(e.path),{op:e,status:`removed`}):{op:e,status:`not-present`};case`mcp-entry`:{let t=Xt(Pt[e.editorId],e.cwd,e.home,e.configPath);switch(t.kind){case`removed`:return{op:e,status:`removed`};case`not-present`:return{op:e,status:`not-present`};case`left-foreign`:return{op:e,status:`skipped`,detail:`left a non-OK server in place`};case`declined`:return{op:e,status:`skipped`,detail:`declined (${t.reason})`};default:throw Error(`unhandled mcp-remove outcome: ${t.kind}`)}}case`launch-entry`:{let t=Rn(e.projectRoot);switch(t.kind){case`removed`:case`removed-file`:return{op:e,status:`removed`};case`not-present`:return{op:e,status:`not-present`};case`declined`:return{op:e,status:`skipped`,detail:`declined (unparseable)`};default:throw Error(`unhandled launch-remove outcome: ${t.kind}`)}}case`git-exclude`:{if(ln(e.projectRoot).length===0)return{op:e,status:`not-present`};let t=fn(e.projectRoot,Cn(e.projectRoot));return t.kind===`no-exclude`?t.reason===`inaccessible`?{op:e,status:`failed`,detail:`could not write .git/info/exclude (inaccessible)`}:{op:e,status:`not-present`,detail:t.reason}:{op:e,status:t.removed.length>0?`removed`:`not-present`}}case`remove-path`:return To(e)}}function To(e){if(e.requireOurState&&!ho(e.path))return{op:e,status:`skipped`,detail:`not verified as OpenKnowledge — left untouched`};e.containWithin&&It(e.path,e.containWithin);let t;try{t=$n(e.path)}catch(e){if(e.code!==`ENOENT`)throw e}if(!t)return{op:e,status:`not-present`};if(t.isSymbolicLink())return sr(e.path),{op:e,status:`removed`};if(e.preserve&&e.preserve.length>0){let t=new Set(e.preserve),n=!1;for(let r of rr(e.path))t.has(r)||(or(B(e.path,r),{recursive:!0,force:!0}),n=!0);return{op:e,status:n?`removed`:`not-present`}}return or(e.path,{recursive:!0,force:!0}),{op:e,status:`removed`}}function Eo(e){let t=new Map;for(let n of e){let e=t.get(n.group)??[];e.push(n),t.set(n.group,e)}return t}function Do(e){if(e.ops.length===0)return F(`Nothing to remove.`);let t=[];for(let[n,r]of Eo(e.ops)){t.length>0&&t.push(``),t.push(z(`${n}:`));for(let e of r)t.push(` ${R(`-`)} ${e.label}`)}return t.join(`
|
|
@@ -39,7 +39,7 @@ ws.addEventListener('error', () => process.exit(1));
|
|
|
39
39
|
setTimeout(() => process.exit(2), ${t+1e4});
|
|
40
40
|
`),r}async function ss(e,t,n,r,i){let a=os(e,t,B(r,`cpu.cpuprofile`)),o=!1,s=Un(process.execPath,[a],D({stdio:`ignore`})),c=setInterval(()=>{let e=ns(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{or(B(a,`..`),{recursive:!0,force:!0})}catch{}return o}function cs(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(`
|
|
41
41
|
`)}async function ls(e,t={}){let{pid:n,cpuProfileSecs:r=15,noInspector:i=!1}=e,a=t.log??(e=>console.log(e)),o=t.discover??He,s=t.inspect??$t,c=t.resolveCommand??Fe,l=t.resolveUsage??Ce,u=t.collectLsofFn??rs,d=t.getEndpoints??as,f=t.profiler??ss,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(Y.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?B(v,`.ok`,`local`,`diagnostics`,`process-${n}-${b}`):B(process.cwd(),`ok-diagnose-${n}-${b}`);try{er(x,{recursive:!0})}catch(e){a(Y.default.red(`Cannot create output directory ${x}: ${e.message}`));return}a(Y.default.bold(`Diagnosing pid ${n}`)),a(`Output: ${x}`),a(``);let S=(e,t)=>{cr(B(x,e),t),a(` wrote ${e}`)},C=c(n),w=l(n);S(`metadata.json`,JSON.stringify({capturedAt:new Date().toISOString(),pid:n,command:C,usage:w,lockInfo:y},null,2)),a(` sampling lsof`);let T=u(n);if(T&&S(`lsof.txt`,T),!i){let e=T?is(T).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(Y.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(Y.default.yellow(` CPU profile capture failed`)),t.length>0&&S(`process-stats.jsonl`,`${t.map(e=>JSON.stringify(e)).join(`
|
|
42
|
-
`)}\n`);try{S(`stacks.txt`,cs(W(B(x,`cpu.cpuprofile`),`utf-8`)))}catch(e){a(Y.default.yellow(` stacks.txt skipped: ${e.message}`))}}}else a(Y.default.yellow(` Node inspector unavailable — skipping CPU profile`))}a(``),a(Y.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: ${Y.default.bold(x)}`)}async function us(e){let t=br({input:process.stdin,output:process.stdout});try{return(await t.question(e)).trim()}finally{t.close()}}async function ds(e){let t=tr(B(dr(),`ok-bundle-process-`));return await ls({pid:e,output:t}),t}function fs(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 ps(e){let t=e.trim().toLowerCase();return t===`y`||t===`yes`}function ms(e){let{summary:t,manifest:n}=e;return t.redacted?t.contentDirVisible?`masked as <CONTENT_DIR>, but still present in some files`:`masked as <CONTENT_DIR>`:t.contentDirVisible?`visible (${n.contentDir.absolutePath})`:`not present`}function hs(e){let t=e.manifest.redaction.secretScrub;return t===void 0?Y.default.yellow(`NOT scrubbed (--no-redact): tokens and keys ship verbatim`):`scrubbed known credential formats (${t.redactedLineCount} line(s) across ${t.redactions.length} file(s))`}function gs(e,t,n){let{summary:r,manifest:i}=t;e(``),e(Y.default.bold(`ok diagnose bundle — what leaves this machine`)),e(``),e(` Files: ${r.fileCount}`),e(` Total size: ${fs(r.totalBytes)} uncompressed`),e(` Document names: included in cleartext (${r.docNameCount} doc.name occurrence(s) in telemetry)`),e(` Content-dir path: ${ms(t)}`),e(` Credentials: ${hs(t)}`),e(` Server status: ${i.serverStatus}`),e(` Output: ${n}`),e(``)}async function _s(e,t={}){let n=t.log??(e=>console.log(e)),r=t.prompt??us,i=t.runProcessDiagnose??ds,a=t.now??(()=>new Date),o;if(e.out!==void 0){o=e.out;let t=Kn(o);if(!U(t))throw Error(`ok diagnose bundle: --out parent directory does not exist: ${t}. Create it first.`)}else{let t=a().toISOString().replace(/[:.]/g,`-`),n=B(e.contentDir,`.ok`,`local`,`diagnostics`);er(n,{recursive:!0}),o=B(n,`bundle-${t}.zip`)}let s;e.pid!==void 0&&(n(Y.default.dim(`Running ok diagnose process ${e.pid} into a temp dir`)),s=await i(e.pid));let c=e.redact!==!1,l=await Qt({contentDir:e.contentDir,projectDir:e.projectDir,processDir:s,redact:c,scrubSecrets:c,deps:t.collectDeps});try{return l.manifest.serverStatus===`not-running`&&n(Y.default.yellow(` server not running — live state unavailable`)),gs(n,l,o),e.yes!==!0&&!ps(await r(`Write bundle? [y/N]: `))?(n(Y.default.dim(`Aborted; no bundle written.`)),{outputPath:null,declined:!0}):(await Vt({collected:l,outputPath:o}),n(Y.default.bold(`Bundle: ${o}`)),{outputPath:o,declined:!1})}finally{if(l.cleanup(),s!==void 0)try{or(s,{recursive:!0,force:!0})}catch{}}}function vs(){let e=new N(`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(Y.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(Y.default.red(`--cpu-profile must be a positive integer`)),process.exit(1)),await ls({pid:n,cpuProfileSecs:r,output:t.output,noInspector:!t.inspector})}),e.addCommand(ts()),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(`--no-redact`,`Write a raw bundle: skip credential scrubbing and content-dir path masking`).option(`--redact`,`Scrub credentials and mask the content-dir path (the default)`).action(async e=>{let t;e.pid!==void 0&&(t=Number.parseInt(e.pid,10),(Number.isNaN(t)||t<=0)&&(console.error(Y.default.red(`Invalid --pid '${e.pid}': must be a positive integer`)),process.exit(1)));try{let{loadConfig:n}=await import(`./loader-
|
|
42
|
+
`)}\n`);try{S(`stacks.txt`,cs(W(B(x,`cpu.cpuprofile`),`utf-8`)))}catch(e){a(Y.default.yellow(` stacks.txt skipped: ${e.message}`))}}}else a(Y.default.yellow(` Node inspector unavailable — skipping CPU profile`))}a(``),a(Y.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: ${Y.default.bold(x)}`)}async function us(e){let t=br({input:process.stdin,output:process.stdout});try{return(await t.question(e)).trim()}finally{t.close()}}async function ds(e){let t=tr(B(dr(),`ok-bundle-process-`));return await ls({pid:e,output:t}),t}function fs(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 ps(e){let t=e.trim().toLowerCase();return t===`y`||t===`yes`}function ms(e){let{summary:t,manifest:n}=e;return t.redacted?t.contentDirVisible?`masked as <CONTENT_DIR>, but still present in some files`:`masked as <CONTENT_DIR>`:t.contentDirVisible?`visible (${n.contentDir.absolutePath})`:`not present`}function hs(e){let t=e.manifest.redaction.secretScrub;return t===void 0?Y.default.yellow(`NOT scrubbed (--no-redact): tokens and keys ship verbatim`):`scrubbed known credential formats (${t.redactedLineCount} line(s) across ${t.redactions.length} file(s))`}function gs(e,t,n){let{summary:r,manifest:i}=t;e(``),e(Y.default.bold(`ok diagnose bundle — what leaves this machine`)),e(``),e(` Files: ${r.fileCount}`),e(` Total size: ${fs(r.totalBytes)} uncompressed`),e(` Document names: included in cleartext (${r.docNameCount} doc.name occurrence(s) in telemetry)`),e(` Content-dir path: ${ms(t)}`),e(` Credentials: ${hs(t)}`),e(` Server status: ${i.serverStatus}`),e(` Output: ${n}`),e(``)}async function _s(e,t={}){let n=t.log??(e=>console.log(e)),r=t.prompt??us,i=t.runProcessDiagnose??ds,a=t.now??(()=>new Date),o;if(e.out!==void 0){o=e.out;let t=Kn(o);if(!U(t))throw Error(`ok diagnose bundle: --out parent directory does not exist: ${t}. Create it first.`)}else{let t=a().toISOString().replace(/[:.]/g,`-`),n=B(e.contentDir,`.ok`,`local`,`diagnostics`);er(n,{recursive:!0}),o=B(n,`bundle-${t}.zip`)}let s;e.pid!==void 0&&(n(Y.default.dim(`Running ok diagnose process ${e.pid} into a temp dir`)),s=await i(e.pid));let c=e.redact!==!1,l=await Qt({contentDir:e.contentDir,projectDir:e.projectDir,processDir:s,redact:c,scrubSecrets:c,deps:t.collectDeps});try{return l.manifest.serverStatus===`not-running`&&n(Y.default.yellow(` server not running — live state unavailable`)),gs(n,l,o),e.yes!==!0&&!ps(await r(`Write bundle? [y/N]: `))?(n(Y.default.dim(`Aborted; no bundle written.`)),{outputPath:null,declined:!0}):(await Vt({collected:l,outputPath:o}),n(Y.default.bold(`Bundle: ${o}`)),{outputPath:o,declined:!1})}finally{if(l.cleanup(),s!==void 0)try{or(s,{recursive:!0,force:!0})}catch{}}}function vs(){let e=new N(`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(Y.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(Y.default.red(`--cpu-profile must be a positive integer`)),process.exit(1)),await ls({pid:n,cpuProfileSecs:r,output:t.output,noInspector:!t.inspector})}),e.addCommand(ts()),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(`--no-redact`,`Write a raw bundle: skip credential scrubbing and content-dir path masking`).option(`--redact`,`Scrub credentials and mask the content-dir path (the default)`).action(async e=>{let t;e.pid!==void 0&&(t=Number.parseInt(e.pid,10),(Number.isNaN(t)||t<=0)&&(console.error(Y.default.red(`Invalid --pid '${e.pid}': must be a positive integer`)),process.exit(1)));try{let{loadConfig:n}=await import(`./loader-DEoi209o.mjs`),{resolveContentDir:r}=await import(`./src-2ftHD8eU.mjs`),i=process.cwd(),{config:a}=n(i);await _s({contentDir:r(a,i),projectDir:i,pid:t,out:e.out,yes:e.yes===!0,redact:e.redact})}catch(e){let t=e instanceof Error?e.message:String(e);console.error(Y.default.red(t)),process.exit(1)}}),e}async function ys(){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 li({message:`Enter embeddings provider API key:`})).trim()}function bs(e){return ie(e)}async function xs(e,t){let n=await ge(oe(),e,t);return n.apiKey?{present:!0,notRequired:!1,source:n.source}:{present:!1,notRequired:n.keyless,source:null}}async function Ss(e){try{let t=jt(O(e));if(!t||t.port<=0||!Mt(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 Cs(){return new N(`set-key`).description(`Store the embeddings API key for THIS project's configured endpoint`).option(`--cwd <path>`,`Project directory (defaults to the current directory)`).action(async e=>{let t=await ys();if(!t){process.stderr.write(`No key provided.
|
|
43
43
|
`),process.exitCode=1;return}let n=H(e.cwd??process.cwd()),{baseUrl:r}=bs(n);try{await oe().setForProject(n,r,t)}catch(e){process.stderr.write(`Failed to store the embeddings key: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1;return}process.stderr.write(`✓ Embeddings API key stored for ${r}\n (kept in ~/.ok/secrets.yml, 0600, this machine only — never in the project).
|
|
44
44
|
Enable semantic search with \`ok embeddings enable\`, or in
|
|
45
45
|
OK Desktop → Settings → This project → Search.
|
|
@@ -74,7 +74,7 @@ ${t}`,d++;break;case`id`:l=t.includes(`\0`)?void 0:t;break;case`retry`:/^\d+$/.t
|
|
|
74
74
|
`).replace(/\n+$/,``);return e.endsWith(`
|
|
75
75
|
`)?`${c}\n`:c}function ku(e){return e.replace(/\r\n|\r|\n/g,`<br>`).replace(/\|/g,`\\|`)}function Au(e){return/\s/.test(e)?`<${e}>`:e}function ju(e,t={}){let{header:n,rows:r}=eu(e),i=n.length;if(i===0)return{table:``,columns:0,wide:!1};let a=t.wideThreshold??15,o=t.titleColumn??0;return{table:[`| ${n.map(ku).join(` | `)} |`,`| ${n.map(()=>`---`).join(` | `)} |`,...r.map(e=>`| ${n.map((n,r)=>{let i=e[r]??``,a=ku(i);if(r===o&&t.linkForTitle&&i.trim()!==``){let e=t.linkForTitle(i);if(e)return`[${a}](${Au(e)})`}return a}).join(` | `)} |`)].join(`
|
|
76
76
|
`),columns:i,wide:i>a}}function Mu(e,t){let n=e.match(/^#\s+(.+)$/m);return n?n[1].trim():t}function Nu(e,t){return`# ${e}\n\n${t}\n`}const Pu=[`links`,`frontmatter`,`callouts`,`images`,`tables`],Fu=/\.mdx?$/i;function Iu(e){return{isNotionExport:e,transforms:{links:0,frontmatter:0,callouts:0,images:0,tables:0},assetsExtracted:0,stubsCreated:0,csvsRemoved:0,wideTables:[],ambiguousTitleLinks:0,unreadable:[],filesChanged:0}}function Lu(e,t={}){let n=t.selected??new Set(Pu),r=xu(e);if(!r&&!t.force)return{changes:[],assets:[],deletions:[],report:Iu(!1)};let i=Iu(r),a=vu(e),o=lu(a,{onUnreadable:e=>i.unreadable.push(e)}),s=n.has(`tables`),c=new Map,l=new Set;for(let e of o){e.stubPath&&l.add(e.stubPath);for(let t of e.rowFiles)c.set(t,e)}let u=[],d=[],f=[];for(let e of a){if(!Fu.test(e)||s&&l.has(e))continue;let r;try{r=W(e,`utf8`)}catch{i.unreadable.push(e);continue}let a=r,o=(e,t)=>{a!==t&&(i.transforms[e]+=1)};if(n.has(`images`)){let n=a,r=$l(a,Gn(e),{strip:t.stripBase64});a=r.markdown;for(let t of r.assets)d.push({path:B(Kn(e),t.filename),bytes:t.bytes});i.assetsExtracted+=r.assets.length,o(`images`,n)}if(n.has(`callouts`)){let e=a;a=Yl(a),o(`callouts`,e)}if(n.has(`frontmatter`)){let t=c.get(e);if(t){let e=a;a=Ou(a,t.propertyKeys),o(`frontmatter`,e)}}if(n.has(`links`)){let e=a;a=_u(a,{redirectCsv:s}),o(`links`,e)}a!==r&&u.push({path:e,content:a})}if(s)for(let e of o){let r=ju(e.csvText,{linkForTitle:t=>{let n=ou(e.folderIndex,t);return n.ambiguous&&(i.ambiguousTitleLinks+=1),n.path?V(Kn(e.stubTargetPath),n.path):null}});if(r.columns===0)continue;let a=e.stubPath??e.stubTargetPath,o=null;if(e.stubPath)try{o=W(e.stubPath,`utf8`)}catch{i.unreadable.push(e.stubPath);continue}let c=Nu(o===null?e.fallbackTitle:Mu(o,e.fallbackTitle),r.table);n.has(`links`)&&(c=_u(c,{redirectCsv:s})),r.wide&&i.wideTables.push(a),o===null?(u.push({path:a,content:c}),i.stubsCreated+=1,i.transforms.tables+=1):c!==o&&(u.push({path:a,content:c}),i.transforms.tables+=1),t.removeCsv&&(f.push(e.csvPath),i.csvsRemoved+=1)}return i.filesChanged=new Set(u.map(e=>e.path)).size,{changes:u,assets:d,deletions:f,report:i}}function Ru(e){for(let t of e.assets)er(Kn(t.path),{recursive:!0}),cr(t.path,t.bytes);for(let t of e.changes)er(Kn(t.path),{recursive:!0}),cr(t.path,t.content,`utf8`);for(let t of e.deletions)try{sr(t)}catch(e){if(e.code!==`ENOENT`)throw e}}const zu={images:`Inline base64 images extracted`,callouts:`Notion <aside> callouts converted`,frontmatter:`Row properties lifted to frontmatter`,tables:`Databases rendered as tables`,links:`Internal links decoded`},Bu=[`images`,`callouts`,`frontmatter`,`tables`,`links`];function Vu(e,t){let n=[];n.push(t.applied?`Applied Notion cleanup in ${t.dir}`:`Dry run — no changes written (${t.dir})`);for(let t of Bu)n.push(` ${zu[t]}: ${e.transforms[t]}`);return n.push(` Assets written: ${e.assetsExtracted}`),e.stubsCreated>0&&n.push(` Database pages created (CSVs without a stub): ${e.stubsCreated}`),e.csvsRemoved>0&&n.push(` CSV files removed: ${e.csvsRemoved}`),n.push(` Files changed: ${e.filesChanged}`),e.ambiguousTitleLinks>0&&n.push(` Ambiguous title links left as plain text: ${e.ambiguousTitleLinks}`),e.wideTables.length>0&&n.push(` Wide tables (>15 columns): ${e.wideTables.length}`),e.unreadable.length>0&&n.push(` Skipped unreadable files: ${e.unreadable.length}`),!t.applied&&e.filesChanged+e.assetsExtracted+e.csvsRemoved>0&&(n.push(``),n.push(`Re-run with --apply to write these changes.`)),n.join(`
|
|
77
|
-
`)}function Hu(e,t){return JSON.stringify({applied:t.applied,...e},null,2)}function Uu(e){let t=new Set(Pu);return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>{if(!t.has(e))throw Error(`Unknown transform "${e}". Valid transforms: ${Pu.join(`, `)}`);return e})}function Wu(e,t){let n=new Set(Pu);if(e&&(n=new Set(Uu(e))),t)for(let e of Uu(t))n.delete(e);return n}function Gu(){let e=new N(`migrate`).description(`Migrate content from other tools into Open Knowledge`);return e.command(`notion [dir]`).description(`Clean up a Notion "Markdown & CSV" export in place (dry-run unless --apply)`).option(`--apply`,`write changes to disk (default: dry-run preview)`).option(`--strip-base64`,`delete inline base64 images instead of extracting them to files`).option(`--remove-csv`,`delete each "_all.csv" once its table page exists (destructive)`).option(`--only <transforms>`,`run only these transforms (comma-separated: links,frontmatter,callouts,images,tables)`).option(`--skip <transforms>`,`skip these transforms (comma-separated)`).option(`--force`,`run even if the directory is not detected as a Notion export`).option(`--json`,`print a machine-readable JSON report`).action((e,t)=>{let n=H(e??process.cwd()),r;try{r=Wu(t.only,t.skip)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=2;return}let i=Lu(n,{selected:r,stripBase64:t.stripBase64??!1,removeCsv:t.removeCsv??!1,force:t.force??!1}),{report:a}=i;if(!a.isNotionExport&&!t.force){t.json?console.log(JSON.stringify({refused:!0,reason:`not-a-notion-export`,dir:n},null,2)):console.error(`Not a Notion export: ${n}\nNo id-suffixed pages, "_all.csv", or inline base64 images were found. Re-run with --force to override.`),process.exitCode=2;return}if(t.apply)try{Ru(i)}catch(e){console.error(`Failed to apply changes: ${e instanceof Error?e.message:String(e)}`),process.exitCode=4;return}console.log(t.json?Hu(a,{applied:t.apply??!1}):Vu(a,{applied:t.apply??!1,dir:n})),a.filesChanged===0&&a.assetsExtracted===0&&i.deletions.length===0?process.exitCode=1:t.apply&&(a.ambiguousTitleLinks>0||a.wideTables.length>0)&&(process.exitCode=3)}),e}function Ku(e=()=>Mn(Fn())){return{detectBundlePath:()=>e().bundlePath??null,resolveBaseUrl:e=>de({lockDir:O(e)}).baseUrl,classifyName:(e,t)=>{let n=B(e,t);try{return G(n).isDirectory()?`folder`:`doc`}catch(e){let t=e?.code;return t!==`ENOENT`&&t!==`ENOTDIR`&&process.stderr.write(`[ok open] statSync failed for ${n} (${t??`unknown`}); treating as a doc\n`),`doc`}},openTarget:e=>{An(`open`,[e])},log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}function qu(e){return e.startsWith(`/`)||e.includes(`\\`)||e.split(`/`).includes(`..`)}function Ju(e){return e.error("No OpenKnowledge desktop app found and no UI is running. Install OK Desktop, or start a UI with `ok ui`, then retry."),1}function Yu(e,t,n,r){let i=`openknowledge://open?project=${encodeURIComponent(e)}&${t}=${encodeURIComponent(n)}`;r.openTarget(i)}function Xu(e,t,r){let i=H(t.project??process.cwd()),a=e.replace(/\/+$/,``);if(!a)return r.error("Nothing to open: pass a doc, folder, or skill name (e.g. `ok open specs/foo/SPEC`)."),1;if(qu(a))return r.error(`Invalid name "${a}": must be a relative path with no '..' segments, leading '/', or backslashes.`),1;if(t.skill===!0){let e=t.scope??`project`;if(!n.includes(e))return r.error(`Invalid --scope "${t.scope}": expected one of ${n.join(`, `)}.`),1;if(r.detectBundlePath())return Yu(i,`doc`,`__skill__/${e}/${a}`,r),r.log(`Opening skill ${a} (${e}) in the OpenKnowledge desktop app.`),0;let o=r.resolveBaseUrl(i);if(o){let t=`${o}/#/${he(e,a)}`;return r.openTarget(t),r.log(`Opening skill ${a} (${e}) in your browser: ${t}`),0}return Ju(r)}let o=/\/+$/.test(e)||r.classifyName(i,a)===`folder`,s=r.detectBundlePath();if(o){if(s)return Yu(i,`folder`,a,r),r.log(`Opening folder ${a} in the OpenKnowledge desktop app.`),0;let e=r.resolveBaseUrl(i);if(e){let t=`${e}/#/${fe(a)}`;return r.openTarget(t),r.log(`Opening folder ${a} in your browser: ${t}`),0}return Ju(r)}if(s)return Yu(i,`doc`,a,r),r.log(`Opening ${a} in the OpenKnowledge desktop app.`),0;let c=r.resolveBaseUrl(i);if(c){let e=`${c}/#/${me(a)}`;return r.openTarget(e),r.log(`Opening ${a} in your browser: ${e}`),0}return Ju(r)}function Zu(){return new N(`open`).description(`Open a doc, folder, or skill in the OK Desktop app (falls back to the browser UI). Docs and folders are auto-detected — no flag needed.`).argument(`<name>`,`Doc path (specs/foo/SPEC), folder path (specs/foo or specs/foo/), or a skill name with --skill`).option(`--skill`,`Open <name> as a skill in the skill editor`).option(`--scope <scope>`,`Skill scope when --skill is set: ${n.join(` | `)}`,`project`).option(`--project <dir>`,`Project root (defaults to the current directory)`).action((e,t)=>{process.exitCode=Xu(e,t,Ku())})}function Qu(e){return new N(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-
|
|
77
|
+
`)}function Hu(e,t){return JSON.stringify({applied:t.applied,...e},null,2)}function Uu(e){let t=new Set(Pu);return e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0).map(e=>{if(!t.has(e))throw Error(`Unknown transform "${e}". Valid transforms: ${Pu.join(`, `)}`);return e})}function Wu(e,t){let n=new Set(Pu);if(e&&(n=new Set(Uu(e))),t)for(let e of Uu(t))n.delete(e);return n}function Gu(){let e=new N(`migrate`).description(`Migrate content from other tools into Open Knowledge`);return e.command(`notion [dir]`).description(`Clean up a Notion "Markdown & CSV" export in place (dry-run unless --apply)`).option(`--apply`,`write changes to disk (default: dry-run preview)`).option(`--strip-base64`,`delete inline base64 images instead of extracting them to files`).option(`--remove-csv`,`delete each "_all.csv" once its table page exists (destructive)`).option(`--only <transforms>`,`run only these transforms (comma-separated: links,frontmatter,callouts,images,tables)`).option(`--skip <transforms>`,`skip these transforms (comma-separated)`).option(`--force`,`run even if the directory is not detected as a Notion export`).option(`--json`,`print a machine-readable JSON report`).action((e,t)=>{let n=H(e??process.cwd()),r;try{r=Wu(t.only,t.skip)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=2;return}let i=Lu(n,{selected:r,stripBase64:t.stripBase64??!1,removeCsv:t.removeCsv??!1,force:t.force??!1}),{report:a}=i;if(!a.isNotionExport&&!t.force){t.json?console.log(JSON.stringify({refused:!0,reason:`not-a-notion-export`,dir:n},null,2)):console.error(`Not a Notion export: ${n}\nNo id-suffixed pages, "_all.csv", or inline base64 images were found. Re-run with --force to override.`),process.exitCode=2;return}if(t.apply)try{Ru(i)}catch(e){console.error(`Failed to apply changes: ${e instanceof Error?e.message:String(e)}`),process.exitCode=4;return}console.log(t.json?Hu(a,{applied:t.apply??!1}):Vu(a,{applied:t.apply??!1,dir:n})),a.filesChanged===0&&a.assetsExtracted===0&&i.deletions.length===0?process.exitCode=1:t.apply&&(a.ambiguousTitleLinks>0||a.wideTables.length>0)&&(process.exitCode=3)}),e}function Ku(e=()=>Mn(Fn())){return{detectBundlePath:()=>e().bundlePath??null,resolveBaseUrl:e=>de({lockDir:O(e)}).baseUrl,classifyName:(e,t)=>{let n=B(e,t);try{return G(n).isDirectory()?`folder`:`doc`}catch(e){let t=e?.code;return t!==`ENOENT`&&t!==`ENOTDIR`&&process.stderr.write(`[ok open] statSync failed for ${n} (${t??`unknown`}); treating as a doc\n`),`doc`}},openTarget:e=>{An(`open`,[e])},log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}function qu(e){return e.startsWith(`/`)||e.includes(`\\`)||e.split(`/`).includes(`..`)}function Ju(e){return e.error("No OpenKnowledge desktop app found and no UI is running. Install OK Desktop, or start a UI with `ok ui`, then retry."),1}function Yu(e,t,n,r){let i=`openknowledge://open?project=${encodeURIComponent(e)}&${t}=${encodeURIComponent(n)}`;r.openTarget(i)}function Xu(e,t,r){let i=H(t.project??process.cwd()),a=e.replace(/\/+$/,``);if(!a)return r.error("Nothing to open: pass a doc, folder, or skill name (e.g. `ok open specs/foo/SPEC`)."),1;if(qu(a))return r.error(`Invalid name "${a}": must be a relative path with no '..' segments, leading '/', or backslashes.`),1;if(t.skill===!0){let e=t.scope??`project`;if(!n.includes(e))return r.error(`Invalid --scope "${t.scope}": expected one of ${n.join(`, `)}.`),1;if(r.detectBundlePath())return Yu(i,`doc`,`__skill__/${e}/${a}`,r),r.log(`Opening skill ${a} (${e}) in the OpenKnowledge desktop app.`),0;let o=r.resolveBaseUrl(i);if(o){let t=`${o}/#/${he(e,a)}`;return r.openTarget(t),r.log(`Opening skill ${a} (${e}) in your browser: ${t}`),0}return Ju(r)}let o=/\/+$/.test(e)||r.classifyName(i,a)===`folder`,s=r.detectBundlePath();if(o){if(s)return Yu(i,`folder`,a,r),r.log(`Opening folder ${a} in the OpenKnowledge desktop app.`),0;let e=r.resolveBaseUrl(i);if(e){let t=`${e}/#/${fe(a)}`;return r.openTarget(t),r.log(`Opening folder ${a} in your browser: ${t}`),0}return Ju(r)}if(s)return Yu(i,`doc`,a,r),r.log(`Opening ${a} in the OpenKnowledge desktop app.`),0;let c=r.resolveBaseUrl(i);if(c){let e=`${c}/#/${me(a)}`;return r.openTarget(e),r.log(`Opening ${a} in your browser: ${e}`),0}return Ju(r)}function Zu(){return new N(`open`).description(`Open a doc, folder, or skill in the OK Desktop app (falls back to the browser UI). Docs and folders are auto-detected — no flag needed.`).argument(`<name>`,`Doc path (specs/foo/SPEC), folder path (specs/foo or specs/foo/), or a skill name with --skill`).option(`--skill`,`Open <name> as a skill in the skill editor`).option(`--scope <scope>`,`Skill scope when --skill is set: ${n.join(` | `)}`,`project`).option(`--project <dir>`,`Project root (defaults to the current directory)`).action((e,t)=>{process.exitCode=Xu(e,t,Ku())})}function Qu(e){return new N(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-rMognm1O.mjs`),r=e(),i=process.cwd(),a=Ue(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 $u(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function ed(e,t,n=process.cwd()){let r=e.op??`sync`,i=jt(O(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`,...h({kind:`cli`,runtimeVersion:At})},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}`)}$u(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=kt({baseDir:n});if(r===`sync`||r===`pull`){$u(e.json,{type:`step`,step:`pull`});let t=await a.pull();$u(e.json,{type:`pull`,summary:t.summary}),e.json||process.stderr.write(` pull: ${t.summary.changes} changes\n`)}(r===`sync`||r===`push`)&&($u(e.json,{type:`step`,step:`push`}),await a.push(),$u(e.json,{type:`push`,ok:!0}),e.json||process.stderr.write(` push: ok
|
|
78
78
|
`)),$u(e.json,{type:`complete`,op:r}),e.json||process.stderr.write(`✓ ${r} complete\n`)}function td(e){return new N(`sync`).description(`Commit, pull, and push to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ed({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 nd(e){return new N(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ed({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 rd(e){return new N(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ed({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 id(e){return typeof e==`string`&&ee.includes(e)}async function ad(e={}){let t=H(e.cwd??process.cwd()),n=e.pack??`knowledge-base`;if(!st[n])return{status:`failed`,message:`${L(`Error:`)} Unknown pack "${n}". Available: ${ee.join(`, `)}`,exitCode:1};let r;try{r=await le({projectDir:t,rootDir:e.root,packId:n,skipPrerequisite:e.dryRun===!0})}catch(e){return e instanceof Ye?{status:`prerequisite-missing`,message:`${L(`Error:`)} ${e.message}`,exitCode:1}:{status:`failed`,message:`${L(`Error:`)} ${e instanceof Error?e.message:String(e)}`,exitCode:1}}if(r.created.length===0&&!r.packSkills?.some(e=>e.pending)){let e=st[n].name;return{status:`no-op`,message:`${I(`Your ${e} pack is already seeded.`)}\n${F(`Nothing to do.`)}`,plan:r,exitCode:0}}if(e.dryRun){let e=ce(st[n]);return{status:`dry-run`,message:`${z(`Reference this pack for inspiration (dry-run — no changes made):`)}\n\n${e}\n\n${z(`Plan:`)}\n\n${sd(r,t)}`,plan:r,exitCode:0}}if(!e.yes&&!await cd(`${z(`Plan:`)}\n\n${sd(r,t)}\n\n${z(`Apply?`)} ${F(`[Y/n] `)}`,e.confirmStream))return{status:`cancelled`,message:F(`Cancelled.`),plan:r,exitCode:0};let i=await E(r,{projectDir:t,packId:n});if(i.errors.length>0){let e=i.errors.map(e=>` ${L(`✗`)} ${e.path}: ${e.error}`);return{status:`failed`,message:[`${R(`Applied`)} ${i.applied} entries, ${R(String(i.errors.length))} error(s):`,...e].join(`
|
|
79
79
|
`),plan:r,exitCode:1}}let a=st[n].name,o=i.packSkillsInstalled.length>0?`\n${F(`Installed the ${a} skills for: ${i.packSkillsInstalled.join(`, `)}`)}`:``;return{status:`applied`,message:`${I(`✓ Seeded ${a}`)} ${F(`(${i.applied} entries, ${i.durationMs}ms)`)}${o}`,plan:r,exitCode:0}}function od(){let e=[z(`Available packs:`)];for(let t of ee){let n=st[t];e.push(` ${I(t)} ${F(`—`)} ${n.name}: ${n.description}`)}return e.join(`
|
|
80
80
|
`)}function sd(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(z(`Folders to create:`));for(let e of r)n.push(` ${I(`+`)} ${P(V(t,H(t,e.path))||e.path)}${F(`/`)}`)}if(i.length>0){n.length>0&&n.push(``),n.push(z(`Files to create:`));for(let e of i)n.push(` ${I(`+`)} ${P(V(t,H(t,e.path))||e.path)}`)}if(e.skipped.length>0){n.length>0&&n.push(``),n.push(F(`Already present (skipped):`));for(let t of e.skipped)n.push(` ${F(`· ${t.path} (${t.reason})`)}`)}if(e.warnings.length>0){n.length>0&&n.push(``),n.push(R(`Warnings:`));for(let t of e.warnings)n.push(` ${R(`!`)} ${t}`)}return n.join(`
|
|
@@ -83,9 +83,9 @@ ${t}`,d++;break;case`id`:l=t.includes(`\0`)?void 0:t;break;case`retry`:/^\d+$/.t
|
|
|
83
83
|
`);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 fd(e){return new N(`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 dd(t,await e())})}async function pd(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 md(e,t){let{host:n,json:r}=e;ii(n);let i=await ua(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 pd(new ra({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 hd(e){return new N(`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 md(t,await e())})}function gd(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(`
|
|
84
84
|
`)??``}\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 _d(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 vd(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 yd(e,t){return(await e.users.getAuthenticated()).data.login.toLowerCase()===t.toLowerCase()?`user`:`org`}function bd(e){return kt(Fa(e,[])).env(ka())}function xd(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 Sd={ensureOkScaffold:e=>{Pe(e)},gitFactory:bd};async function Cd(e){let t={...Sd,...e.deps},n=H(e.projectDir),r;if(e.ownerKind)r=e.ownerKind;else try{r=await yd(e.octokit,e.body.owner)}catch(e){return{kind:`error`,code:gd(e)}}try{t.ensureOkScaffold(n)}catch{return{kind:`error`,code:`init-failed`}}let i=t.gitFactory(n);if(!U(B(n,`.git`)))try{await i.init()}catch{return{kind:`error`,code:`init-failed`}}let a;try{a=await _d({octokit:e.octokit,ownerLogin:e.body.owner,ownerKind:r,name:e.body.name,visibility:e.body.visibility,description:e.body.description})}catch(t){if(gd(t)===`name-conflict`){let t=await vd(e.octokit,e.body.owner,e.body.name);if(t===null)return{kind:`error`,code:`name-conflict`};a=t}else return{kind:`error`,code:gd(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=xd(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 wd(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 Td(e,t){let{host:n,owner:r,name:i,visibility:a,description:o,projectDir:s,json:c}=e;ii(n);let l=await ua(n,t);if(l==null){wd(c,{kind:`error`,code:`auth-required`});return}let u=n===`github.com`?void 0:`https://${n}/api/v3`,d=new ra({auth:l,...u?{baseUrl:u}:{}});try{Hn(`git config user.email`,D({cwd:s,stdio:`ignore`}))}catch{process.env.GIT_AUTHOR_NAME??=`OpenKnowledge`,process.env.GIT_AUTHOR_EMAIL??=`noreply@inkeep.com`,process.env.GIT_COMMITTER_NAME??=`OpenKnowledge`,process.env.GIT_COMMITTER_EMAIL??=`noreply@inkeep.com`}wd(c,await Cd({octokit:d,token:l,projectDir:s,body:{owner:r,name:i,visibility:a,description:o}}))}function Ed(e){return new N(`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'
|
|
85
85
|
`),process.exit(1)),await Td(t,await e())})}function Dd(){let e=new N(`share`);e.description(`Sharing flow operations (owners, name-check, publish)`);let t=()=>tn();return e.addCommand(hd(t)),e.addCommand(fd(t)),e.addCommand(Ed(t)),e}function Od(){return new N(`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=H(e.project??process.cwd()),n=gn(t),r=fn(t,Cn(t));if(r.kind===`no-exclude`){kd(e.json,t,r.reason);return}let i=gn(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(`${P(`Sharing mode is already`)} ${z(`shared`)} ${P(`— nothing to do.`)}\n`);return}process.stderr.write(`${I(`✓`)} ${z(`Sharing mode set to`)} ${I(`shared`)}\n`),process.stderr.write(` Removed OK paths from ${z(`.git/info/exclude`)}; commit the files to share with teammates.\n`)})}function kd(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(`${R({"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 Ad(){return new N(`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=H(e.project??process.cwd()),n=gn(t),r=vn(t),i=[...ln(t)],a=hn(t,Cn(t)).tracked;if(e.json){let e={type:`sharing-status`,projectRoot:t,mode:n,skillsShared:r,excluded:i,trackedUpstream:a};process.stdout.write(`${JSON.stringify(e)}\n`);return}let o=[];if(o.push(`OpenKnowledge sharing mode: ${jd(n)}`),r&&o.push(` ${z(`.ok/skills`)} is committable (carved out); the rest of .ok/ stays local.`),o.push(``),o.push(`Excluded from git via ${z(`.git/info/exclude`)}:`),i.length===0)o.push(` (none)`);else for(let e of i)o.push(` ${e}`);if(o.push(``),o.push(`Other OK paths exist but are tracked upstream:`),a.length===0)o.push(` (none)`);else for(let e of a)o.push(` ${e}`);o.push(``),o.push(`Toggle with: ${P(n===`local-only`?`ok config-sharing share`:`ok config-sharing unshare`)}`),r&&o.push(` (that shares the whole project; to undo only the skills carve-out, use the desktop app: Settings > Config sharing)`),process.stdout.write(`${o.join(`
|
|
86
|
-
`)}\n`)})}function jd(e){switch(e){case`shared`:return I(`shared`);case`local-only`:return I(`local-only`);case`no-git`:return R(`no-git (not a git repository)`)}}function Md(){return new N(`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=H(e.project??process.cwd()),n=_n(t,Cn(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`){Nd(e.json,t,n.reason);return}let r=gn(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(`${z(`Sharing mode is already`)} ${I(`local-only`)} ${z(`— nothing to do.`)}\n`);return}process.stderr.write(`${I(`✓`)} ${z(`Sharing mode set to`)} ${I(`local-only`)}\n`),process.stderr.write(` Added ${n.appended.length} path(s) to ${z(`.git/info/exclude`)} (per-clone, not committed).\n`)})}function Nd(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(`${R({"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 Pd(){let e=new N(`config-sharing`);return e.description(`Manage OpenKnowledge's git-sharing mode (share OK config with the team, or keep local-only on this machine)`),e.addCommand(Od()),e.addCommand(Md()),e.addCommand(Ad()),e}const Fd=new Set([`--cwd`,`--log-level`]);function Id(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(`-`)){Fd.has(a)&&i++;continue}t.push(a)}}return{operands:t,cwd:n,sawTerminalFlag:r}}function Ld(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 Rd(e){return/\.(md|mdx)$/i.test(e)}function zd(e,t){if(Rd(t))return!0;try{return G(e).isFile()}catch(t){let n=t?.code;return n!==`ENOENT`&&n!==`ENOTDIR`&&process.stderr.write(`[ok] statSync failed for ${e} (${n??`unknown`}); treating as non-fileish\n`),!1}}function Bd(e=()=>Mn(Fn())){return{prepare:xe,detectBundlePath:()=>e().bundlePath??null,openTarget:e=>{An(`open`,[e])},runProjectOpen:(e,t)=>Xu(e,{project:t},Ku()),runBrowserOpen:e=>Ud(e),log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}async function Vd(e,t){let n;try{n=t.prepare(e)}catch(e){if(e instanceof Be||e instanceof Qe||e instanceof Xe)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 OpenKnowledge desktop app.`),0}return await t.runBrowserOpen(n),0}function Hd(){let e=import.meta.dirname??new URL(`.`,import.meta.url).pathname;return[H(e,`public`),H(e,`../../app/dist`),H(e,`../../../app/dist`)].find(e=>U(e))}async function Ud(e){let{createEphemeralProjectDir:t}=await import(`./src-
|
|
86
|
+
`)}\n`)})}function jd(e){switch(e){case`shared`:return I(`shared`);case`local-only`:return I(`local-only`);case`no-git`:return R(`no-git (not a git repository)`)}}function Md(){return new N(`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=H(e.project??process.cwd()),n=_n(t,Cn(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`){Nd(e.json,t,n.reason);return}let r=gn(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(`${z(`Sharing mode is already`)} ${I(`local-only`)} ${z(`— nothing to do.`)}\n`);return}process.stderr.write(`${I(`✓`)} ${z(`Sharing mode set to`)} ${I(`local-only`)}\n`),process.stderr.write(` Added ${n.appended.length} path(s) to ${z(`.git/info/exclude`)} (per-clone, not committed).\n`)})}function Nd(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(`${R({"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 Pd(){let e=new N(`config-sharing`);return e.description(`Manage OpenKnowledge's git-sharing mode (share OK config with the team, or keep local-only on this machine)`),e.addCommand(Od()),e.addCommand(Md()),e.addCommand(Ad()),e}const Fd=new Set([`--cwd`,`--log-level`]);function Id(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(`-`)){Fd.has(a)&&i++;continue}t.push(a)}}return{operands:t,cwd:n,sawTerminalFlag:r}}function Ld(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 Rd(e){return/\.(md|mdx)$/i.test(e)}function zd(e,t){if(Rd(t))return!0;try{return G(e).isFile()}catch(t){let n=t?.code;return n!==`ENOENT`&&n!==`ENOTDIR`&&process.stderr.write(`[ok] statSync failed for ${e} (${n??`unknown`}); treating as non-fileish\n`),!1}}function Bd(e=()=>Mn(Fn())){return{prepare:xe,detectBundlePath:()=>e().bundlePath??null,openTarget:e=>{An(`open`,[e])},runProjectOpen:(e,t)=>Xu(e,{project:t},Ku()),runBrowserOpen:e=>Ud(e),log:e=>process.stdout.write(`${e}\n`),error:e=>process.stderr.write(`${e}\n`)}}async function Vd(e,t){let n;try{n=t.prepare(e)}catch(e){if(e instanceof Be||e instanceof Qe||e instanceof Xe)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 OpenKnowledge desktop app.`),0}return await t.runBrowserOpen(n),0}function Hd(){let e=import.meta.dirname??new URL(`.`,import.meta.url).pathname;return[H(e,`public`),H(e,`../../app/dist`),H(e,`../../../app/dist`)].find(e=>U(e))}async function Ud(e){let{createEphemeralProjectDir:t}=await import(`./src-2ftHD8eU.mjs`),{loadConfig:n}=await import(`./index.mjs`),{bootStartServer:r,resolveHost:i}=await import(`./start-MnLPFpd0.mjs`),{openBrowser:a}=await import(`./open-browser-DOh4nE9t.mjs`),o=Hd();o||(process.stderr.write("OpenKnowledge 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 fr(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,idleThresholdMs:6e5})}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}/#/${me(e.docName)}`;process.env.OK_SINGLE_FILE_NO_OPEN===`1`?process.stdout.write(`Serving ${e.singleDocRelPath} (headless) at: ${m}\n`):(process.stdout.write(`Opening ${e.singleDocRelPath} in your browser: ${m}\n`),process.stdout.write(`Press Ctrl-C to close the session.
|
|
87
87
|
`),a(m)),await new Promise(()=>{})}function Wd(){let e=new N(`skills`).description(`Manage Open Knowledge skills for this project.`);return e.command(`installed`).description(`List every skill installed across all your agents (read-only).`).option(`--json`,`Emit the raw enumeration as JSON.`).action(e=>{let t=H(process.cwd()),n=tt(nt(t)?.rootPath??t),r=ye({projectDir:n}),i={...r,skills:r.skills.filter(e=>S(e.provenance,n))};if(e.json){process.stdout.write(`${JSON.stringify(i,null,2)}\n`);return}if(i.skills.length===0){process.stdout.write(`${F(`No installed skills found across any agent.`)}\n`);return}process.stdout.write(`${z(`${i.skills.length} installed skill(s):`)}\n`);for(let e of i.skills){let t=e.provenance.version?F(` v${e.provenance.version}`):``,n=[e.inert.commands&&`commands`,e.inert.hooks&&`hooks`,e.inert.mcp&&`mcp`].filter(Boolean),r=n.length>0?F(` [${n.join(`, `)}]`):``;process.stdout.write(` ${I(e.name)}${t} ${F(e.sourceHarnesses.join(`, `))}${r}\n`)}process.stdout.write(`\n${z(`${i.packs.length} pack(s):`)}\n`);for(let e of i.packs)process.stdout.write(` ${P(e.name)} ${F(`v${e.version}`)} — ${e.skills.length} skill(s)\n`)}),e.command(`import <source>`).description(`Import a skill into this project as versioned content (github owner/repo, a git URL, or a local path).`).option(`--skill <name>`,`Pick one skill from a multi-skill source.`).option(`--scope <scope>`,`project (default) or global.`,`project`).action(async(e,t)=>{let n=$t(O(process.cwd()),`server`);if(n.status!==`alive`){process.stderr.write(`${L(`Error:`)} no running Open Knowledge server for this project. Start it with ${z(`ok start`)} and retry.\n`),process.exitCode=1;return}let r;try{r=await fetch(`http://127.0.0.1:${n.lock.port}/api/skill/import`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({source:e,...t.skill?{skill:t.skill}:{},scope:t.scope===`global`?`global`:`project`})})}catch(e){let t=e instanceof Error?e.message:String(e);process.stderr.write(`${L(`Error:`)} could not reach the server: ${t}\n`),process.exitCode=1;return}let i=await r.json().catch(()=>({}));if(!r.ok){let e=i.detail??i.title??`HTTP ${r.status}`;process.stderr.write(`${L(`Import failed:`)} ${e}\n`),process.exitCode=1;return}let a=i.name;if(i.alreadyImported){process.stdout.write(`${P(`Already imported:`)} ${z(a)} (identical content).\n`);return}let o=i.provenance??{},s=i.collisionRenamedFrom;process.stdout.write(`${I(`Imported`)} ${z(a)}${s?F(` (renamed from ${s} — name was taken)`):``} from ${F(o.source??e)}${o.publisher?F(` · ${o.publisher}`):``}.\n${F(`Saved as versioned content in this project's skill home. Scripts shown, never run. Use the skill's install menu (or the install MCP verb) to add it to your other editors.`)}\n`);for(let e of i.warnings??[])process.stdout.write(` ${F(`! ${e}`)}\n`)}),e}function Gd(e,t){return{server:Kd(`server`,e),ui:Kd(`ui`,t)}}function Kd(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 qd(e){return`${Jd(e.server)}\n${Jd(e.ui)}`}function Jd(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 Yd(e){let t=e.inspect??(t=>$t(e.lockDir,t)),n=e.log??(e=>console.log(e)),r=Gd(t(`server`),t(`ui`));return e.json?n(JSON.stringify(r,null,2)):n(qd(r)),r}function Xd(e){return new N(`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(),Yd({lockDir:O(process.cwd()),json:t.json===!0})})}function Zd(e,t,n,r,i){let o=`urn:uuid:${hr()}`;if(e.headersSent||e.writableEnded||e.destroyed){console.error(`[ok ui] emitProblem called after headers sent — suppressed`,{type:n,status:t,instance:o});return}let s={type:n,title:r,status:t,instance:o,...i===void 0?{}:{detail:i}},c=a.safeParse(s);if(!c.success){console.error(`[ok ui] emitProblem produced an invalid ProblemDetails body:`,{issues:c.error.issues,originalStatus:t,body:s}),e.writeHead(500,{"Content-Type":`application/problem+json`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-store`}),e.end(JSON.stringify({type:`urn:ok:error:internal-server-error`,title:`Internal server error.`,status:500,instance:o}));return}e.writeHead(t,{"Content-Type":`application/problem+json`,"X-Content-Type-Options":`nosniff`,"Cache-Control":`no-store`}),e.end(JSON.stringify(s))}const Qd=1e4;function $d(e,t){let n=e.socket?.remoteAddress;if(n!==void 0&&!Ae(n))return Zd(t,403,`urn:ok:error:loopback-required`,`Request must originate from a loopback address.`),!0;if(!Ne(e.headers.host))return Zd(t,403,`urn:ok:error:host-not-allowed`,`Host header is not in the loopback allowlist.`),!0;let r=e.headers.origin;return r!==void 0&&!$e(r)?(Zd(t,403,`urn:ok:error:invalid-origin`,`Origin header is not in the loopback allowlist.`),!0):!1}const ef=3e4;function tf(e,t){let n=e.socket?.remoteAddress;if(n!==void 0&&!Ae(n)||!Ne(e.headers.host))return t.destroy(),!0;let r=e.headers.origin;return typeof r==`string`&&!$e(r)?(t.destroy(),!0):!1}function nf(e,t,n,r,i,a){a.add(t),t.once(`close`,()=>a.delete(t));let o=xr({host:r,port:i,timeout:Qd});a.add(o),o.once(`close`,()=>a.delete(o));let s=!1,c=n=>{if(!s){if(s=!0,n!==void 0){let t=n.err;console.warn(JSON.stringify({event:n.event,upstreamHost:r,upstreamPort:i,url:e.url,code:t instanceof Error?t.code:void 0,message:t instanceof Error?t.message:void 0}))}try{o.destroy()}catch{}try{t.destroy()}catch{}}};o.once(`connect`,()=>{o.setTimeout(0);let a=[`${e.method??`GET`} ${e.url??`/`} HTTP/1.1`,`host: ${r}:${i}`];for(let[t,n]of Object.entries(e.headers))if(t.toLowerCase()!==`host`&&n!==void 0)if(Array.isArray(n))for(let e of n)a.push(`${t}: ${e}`);else a.push(`${t}: ${n}`);try{o.write(`${a.join(`\r
|
|
88
|
-
`)}\r\n\r\n`),n.length>0&&o.write(n)}catch(e){c({event:`proxy-upgrade-handshake-write-failed`,err:e});return}o.on(`data`,e=>{t.writable&&t.write(e)}),t.on(`data`,e=>{o.writable&&o.write(e)})}),o.once(`timeout`,()=>{c({event:`proxy-upgrade-upstream-connect-timeout`})}),o.on(`error`,e=>c({event:`proxy-upgrade-upstream-error`,err:e})),t.on(`error`,e=>c({event:`proxy-upgrade-client-error`,err:e})),o.once(`close`,()=>c()),t.once(`close`,()=>c())}const rf=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function af(e){let t=e.upstreamTimeoutMs??Qd,n=new Set,r=vr((n,r)=>{$d(n,r)||sf(n,r,e.upstreamHost,e.upstreamPort,t)});r.on(`upgrade`,(t,r,i)=>{tf(t,r)||nf(t,r,i,e.upstreamHost,e.upstreamPort,n)}),await new Promise((t,n)=>{let i=e=>n(e);r.once(`error`,i),r.listen(e.listenPort,e.host,()=>{r.off(`error`,i),t()})});let i=r.address();return{httpServer:r,port:typeof i==`object`&&i?i.port:e.listenPort,close:()=>new Promise(e=>{for(let e of n)try{e.destroy()}catch{}n.clear(),r.close(()=>e()),r.closeIdleConnections()})}}function of(e,t,n){sf(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??Qd)}function sf(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of rf)delete a[e];e.setTimeout(ef,()=>{if(t.headersSent)try{t.end()}catch{}else try{Zd(t,408,`urn:ok:error:request-timeout`,`Proxy request exceeded the per-request deadline.`,`Slow-loris-class: client did not finish within ${ef/1e3}s.`)}catch{}try{e.socket?.destroy()}catch{}});let o=yr({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of rf)delete n[e];t.writeHead(e.statusCode??502,n),e.pipe(t),e.once(`error`,()=>{try{t.end()}catch{}})});i>0&&o.setTimeout(i,()=>{if(!t.headersSent)Zd(t,504,`urn:ok:error:gateway-timeout`,`Upstream did not respond before the gateway deadline.`,`Upstream timeout: ${i/1e3}s elapsed without a response.`);else try{t.end()}catch{}o.destroy()}),o.on(`error`,()=>{if(!t.headersSent)Zd(t,502,`urn:ok:error:collab-server-not-running`,`Collab server is unreachable.`,`Upstream connection failed or dropped before a response was received.`);else try{t.end()}catch{}}),e.on(`error`,()=>{o.destroy()}),e.pipe(o)}const cf=39847;async function lf(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function uf(e){let{existsSync:t}=await import(`node:fs`),{createServer:n}=await import(`node:http`),{resolve:r}=await import(`node:path`),{acquireUiLock:i,createAssetServeMiddleware:a,createContentFilter:o,readServerLock:s,releaseUiLock:c,updateUiLockPort:l}=await import(`./src-
|
|
88
|
+
`)}\r\n\r\n`),n.length>0&&o.write(n)}catch(e){c({event:`proxy-upgrade-handshake-write-failed`,err:e});return}o.on(`data`,e=>{t.writable&&t.write(e)}),t.on(`data`,e=>{o.writable&&o.write(e)})}),o.once(`timeout`,()=>{c({event:`proxy-upgrade-upstream-connect-timeout`})}),o.on(`error`,e=>c({event:`proxy-upgrade-upstream-error`,err:e})),t.on(`error`,e=>c({event:`proxy-upgrade-client-error`,err:e})),o.once(`close`,()=>c()),t.once(`close`,()=>c())}const rf=[`connection`,`keep-alive`,`proxy-authenticate`,`proxy-authorization`,`te`,`trailer`,`transfer-encoding`,`upgrade`,`cookie`,`set-cookie`];async function af(e){let t=e.upstreamTimeoutMs??Qd,n=new Set,r=vr((n,r)=>{$d(n,r)||sf(n,r,e.upstreamHost,e.upstreamPort,t)});r.on(`upgrade`,(t,r,i)=>{tf(t,r)||nf(t,r,i,e.upstreamHost,e.upstreamPort,n)}),await new Promise((t,n)=>{let i=e=>n(e);r.once(`error`,i),r.listen(e.listenPort,e.host,()=>{r.off(`error`,i),t()})});let i=r.address();return{httpServer:r,port:typeof i==`object`&&i?i.port:e.listenPort,close:()=>new Promise(e=>{for(let e of n)try{e.destroy()}catch{}n.clear(),r.close(()=>e()),r.closeIdleConnections()})}}function of(e,t,n){sf(e,t,n.upstreamHost,n.upstreamPort,n.upstreamTimeoutMs??Qd)}function sf(e,t,n,r,i){let a={...e.headers};delete a.host;for(let e of rf)delete a[e];e.setTimeout(ef,()=>{if(t.headersSent)try{t.end()}catch{}else try{Zd(t,408,`urn:ok:error:request-timeout`,`Proxy request exceeded the per-request deadline.`,`Slow-loris-class: client did not finish within ${ef/1e3}s.`)}catch{}try{e.socket?.destroy()}catch{}});let o=yr({host:n,port:r,method:e.method,path:e.url,headers:{...a,host:`${n}:${r}`}},e=>{let n={...e.headers};for(let e of rf)delete n[e];t.writeHead(e.statusCode??502,n),e.pipe(t),e.once(`error`,()=>{try{t.end()}catch{}})});i>0&&o.setTimeout(i,()=>{if(!t.headersSent)Zd(t,504,`urn:ok:error:gateway-timeout`,`Upstream did not respond before the gateway deadline.`,`Upstream timeout: ${i/1e3}s elapsed without a response.`);else try{t.end()}catch{}o.destroy()}),o.on(`error`,()=>{if(!t.headersSent)Zd(t,502,`urn:ok:error:collab-server-not-running`,`Collab server is unreachable.`,`Upstream connection failed or dropped before a response was received.`);else try{t.end()}catch{}}),e.on(`error`,()=>{o.destroy()}),e.pipe(o)}const cf=39847;async function lf(e){await Promise.all(e.map(e=>new Promise(t=>{e.close(()=>t())})))}async function uf(e){let{existsSync:t}=await import(`node:fs`),{createServer:n}=await import(`node:http`),{resolve:r}=await import(`node:path`),{acquireUiLock:i,createAssetServeMiddleware:a,createContentFilter:o,readServerLock:s,releaseUiLock:c,updateUiLockPort:l}=await import(`./src-2ftHD8eU.mjs`),{default:u}=await import(`./build-DcqN8tua.mjs`),{resolveContentDir:d,resolveLockDir:f}=await import(`./src-2ftHD8eU.mjs`),p=d(e.config,e.cwd),m=f(e.cwd);i(m,{port:0,worktreeRoot:e.cwd});let h=import.meta.dirname??new URL(`.`,import.meta.url).pathname,g=[r(h,`public`),r(h,`../../app/dist`),r(h,`../../../app/dist`)],_=e.assetDir??g.find(e=>t(e)),v=_?u(_,{single:!0,gzip:!0,etag:!0,dev:!0,extensions:[]}):null,y=t(p)?a({contentFilter:o({projectDir:e.cwd,contentDir:p}),contentSirv:u(p,{dotfiles:!1,dev:!0,extensions:[]}),inlineExtensions:Tt,assetExtensions:ft,blocklistExtensions:ut}):null,b=e.port,S=null,w=(e,t)=>{let n=e.url?.split(`?`)[0];if((n===`/`||n===``)&&(e.url=`/index.html`),!(n?.startsWith(`/api/`)&&$d(e,t))){if(n===`/api/config`&&(e.method===`GET`||e.method===`HEAD`)){S?.();let n=s(m),r=e.headers.host??`localhost:${b}`,i=n&&n.port>0?`ws://${r}/collab`:null,a=JSON.stringify({collabUrl:i,previewUrl:null,port:b});t.setHeader(`Content-Type`,`application/json`),t.setHeader(`Cache-Control`,`no-store`),t.setHeader(`X-Content-Type-Options`,`nosniff`),t.statusCode=200,e.method===`HEAD`?t.end():t.end(a);return}if(n?.startsWith(`/api/`)){S?.();let r=s(m);if(!r||r.port<=0){Zd(t,503,`urn:ok:error:collab-server-not-running`,"Collab server not running. Start `ok start` or run `ok status`.",`Path: ${n}`);return}of(e,t,{upstreamHost:C,upstreamPort:r.port});return}if(v&&n?.startsWith(`/assets/`)){v(e,t,()=>{y?y(e,t,()=>df(t)):df(t)});return}if(y){y(e,t,()=>{v?v(e,t):df(t)});return}if(v){v(e,t);return}df(t)}},T=new Set,ee=(e,t,n)=>{if(tf(e,t))return;let r=e.url?.split(`?`)[0]??``;if(r!==`/collab`&&!r.startsWith(`/collab/`)){t.destroy();return}let i=s(m);if(!i||i.port<=0){console.warn(JSON.stringify({event:`ok-ui-upgrade-no-collab-lock`,url:r,reason:"server.lock missing or port unbound — is `ok start` running?"})),t.destroy();return}nf(e,t,n,C,i.port,T)},te=()=>{for(let e of T)try{e.destroy()}catch{}T.clear()},ne=e.host===void 0?[`::1`,`127.0.0.1`]:[e.host],re=[],ie=e.port,ae=e=>e instanceof Error&&e.code===`EADDRINUSE`,oe=async()=>{await Promise.all(re.splice(0).map(e=>new Promise(t=>{try{e.close(()=>t())}catch{t()}})))},se=async e=>{ie=e;for(let e of ne){let t=n(w);t.on(`upgrade`,ee),re.push(t),await new Promise((n,r)=>{let i=e=>r(e);t.once(`error`,i),t.listen(ie,e,()=>{t.off(`error`,i);let e=t.address();typeof e==`object`&&e&&(ie=e.port),n()})})}};try{try{await se(e.port)}catch(t){if(e.fallbackToKernel===!0&&ae(t))await oe(),await se(0);else throw t}}catch(e){await oe();try{c(m)}catch{}throw e}let ce=ie;b=ce,l(m,ce);let le=e.scheduler??x,ue=e.safetyNetMs??432e5,E=null,de=!1,D=!1,fe=()=>{de||(de=!0,E!==null&&(le.clearTimeout(E),E=null))},pe=()=>{if(fe(),!D){D=!0;try{c(m)}catch{}}},me=()=>{de||ue<=0||(E!==null&&(le.clearTimeout(E),E=null),E=le.setTimeout(()=>{E=null,console.warn(`[ui] safety-net (${ue}ms) reached — shutting down (D-025 backstop)`);try{e.onSafetyNet?.()}catch{}te();for(let e of re)try{e.close()}catch{}pe()},ue))},he=()=>{de||ue<=0||me()};return S=he,me(),{httpServers:re,port:ce,release:pe,detachSafetyNet:fe,nudgeSafetyNet:he,drainUpgradeSockets:te}}function df(e){e.headersSent||e.writableEnded||e.destroyed||(e.setHeader(`X-Content-Type-Options`,`nosniff`),e.setHeader(`Cache-Control`,`no-store`),e.statusCode=404,e.end())}function ff(e,t){if(e!==void 0){let t=Number.parseInt(e,10);if(Number.isNaN(t)||t<0||t>65535)throw Error(`Invalid --port value '${e}'`);return{port:t,fallbackToKernel:!1}}if(t!==void 0&&t!==``){let e=Number.parseInt(t,10);if(Number.isNaN(e)||e<0||e>65535)throw Error(`Invalid PORT env value '${t}'`);return{port:e,fallbackToKernel:!1}}return{port:cf,fallbackToKernel:!0}}async function pf(e){let t=e.readLock??(async()=>{let{readUiLock:t}=await import(`./src-2ftHD8eU.mjs`);return t(e.lockDir)}),n=await t();if(!n)throw Error(`UI lock collision reported but the lock disappeared before handling — retry acquiring.`);if(n.port===e.requestedPort&&n.port>0)return{mode:`already-running`,port:n.port};let r=n.port;if(r===0){let n=Date.now()+(e.pollDeadlineMs??2e3),i=e.pollIntervalMs??100;for(;Date.now()<n;){await new Promise(e=>{setTimeout(e,i)});let e=await t();if(e&&e.port>0){r=e.port;break}}if(r===0)throw Error("UI did not bind within 2s; run `ok clean`");if(r===e.requestedPort)return{mode:`already-running`,port:r}}return{mode:`proxy`,handle:await af({listenPort:e.requestedPort,host:e.host,upstreamHost:`localhost`,upstreamPort:r}),upstreamPort:r}}function mf(e){return new N(`ui`).description(`Serve the OpenKnowledge React editor UI`).option(`-p, --port <port>`,`UI port (default: $PORT env or ${cf}, kernel-allocated fallback if busy)`).option(`-H, --host <host>`,"UI host. Default: two-socket loopback bind (`[::1]` + `127.0.0.1`) so cross-family collisions fail loud. Pass an explicit host (e.g. `127.0.0.1`, `0.0.0.0`) to bind a single socket on that host.").action(async t=>{let{dim:n}=await import(`./colors-MGDi6UGf.mjs`),{UiLockCollisionError:r}=await import(`./src-2ftHD8eU.mjs`),{resolveLockDir:i}=await import(`./src-2ftHD8eU.mjs`),a=e(),o=t.host,s;try{s=ff(t.port,process.env.PORT)}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exitCode=1;return}let c=s.port;try{let e=await uf({config:a,cwd:process.cwd(),port:c,fallbackToKernel:s.fallbackToKernel,host:o}),t=o===void 0||o===`::`||o===`0.0.0.0`?`localhost`:o;console.log(`${n(`[ui]`)} listening on http://${t}:${e.port}`);let r=!1,i=t=>{if(r)return;r=!0,console.log(n(`\n[ui] Shutting down (${t})`)),e.detachSafetyNet();let i=()=>{try{e.release()}finally{process.exit(process.exitCode??0)}};e.drainUpgradeSockets(),lf(e.httpServers).then(i,i),setTimeout(i,2e3).unref()};process.once(`SIGINT`,()=>i(`SIGINT`)),process.once(`SIGTERM`,()=>i(`SIGTERM`));return}catch(e){if(!(e instanceof r))throw e;let t=i(process.cwd()),a=o??`localhost`,s;try{s=await pf({requestedPort:c,host:a,lockDir:t})}catch(e){console.error(e instanceof Error?e.message:String(e)),process.exit(1)}if(s.mode===`already-running`){if(console.log(`UI already running at http://${a}:${s.port}`),hf(process)){await new Promise(e=>{let t=t=>{console.log(n(`\n[ui-keepalive] Shutting down (${t})`)),e()};process.once(`SIGINT`,()=>t(`SIGINT`)),process.once(`SIGTERM`,()=>t(`SIGTERM`))});return}process.exit(0)}console.log(`UI running at http://${a}:${s.upstreamPort}; acting as HTTP proxy on port ${s.handle.port}`);let l=!1,u=e=>{l||(l=!0,console.log(n(`\n[ui-proxy] Shutting down (${e})`)),s.handle.close().finally(()=>process.exit(process.exitCode??0)),setTimeout(()=>process.exit(process.exitCode??0),2e3).unref())};process.once(`SIGINT`,()=>u(`SIGINT`)),process.once(`SIGTERM`,()=>u(`SIGTERM`))}})}function hf(e){let t=e.stdout.isTTY===!0,n=typeof e.env.PORT==`string`&&e.env.PORT!==``;return!t||n}function gf(e){if(e.yes===!0||e.json===!0)return!1;let t=e.stdinIsTTY??process.stdin.isTTY,n=e.stdoutIsTTY??process.stdout.isTTY;return t===!0&&n===!0}async function _f(e,t){let n=br({input:e.input,output:e.output});try{return(await n.question(t)).trim()}finally{n.close()}}async function vf(e={}){let t={input:e.input??process.stdin,output:e.output??process.stderr};t.output.write(F(`
|
|
89
89
|
What you share is sent to the OpenKnowledge team.
|
|
90
90
|
`));let n=await dn({message:`Before you go, mind sharing why? (optional)`,default:null,pageSize:m.length+1,choices:[...m.map(e=>({name:e.label,value:e.value})),{name:`Skip, I'd rather not say`,value:null}]},t);if(n===null)return{};let r=await _f(t,F(`Anything else we should know? (optional) `)),i=await _f(t,F(`Email, if we may follow up (optional) `));return{reason:n,note:r||void 0,email:i||void 0}}async function yf(e){if(!gf(e))return`not-prompted`;let t;try{t=await(e.collect??(()=>vf(e)))()}catch{return`failed`}return v(t)?((e.output??process.stderr).write(`\n${z(`Thank you. We read every response.`)}\n\n`),(await(e.submit??r)({...t,source:`cli_uninstall`,appVersion:e.appVersion,platform:e.platform})).ok?`submitted`:`undelivered`):`skipped`}function bf(e,t,n=xf,r=U){let i=[];for(let t of[`/Applications/OpenKnowledge.app`,B(e,`Applications`,`OpenKnowledge.app`)])r(t)&&i.push({method:`app`,label:`OK Desktop (${t})`,instruction:`Move ${t} to the Trash (or: rm -rf "${t}")`});return n([`ls`,`-g`,`--depth=0`,`@inkeep/open-knowledge`])?.includes(`@inkeep/open-knowledge@`)&&i.push({method:`npm-global`,label:`npm global install`,instruction:`npm uninstall -g @inkeep/open-knowledge`}),t&&/[/\\]_npx[/\\]/.test(t)&&i.push({method:`npx`,label:`npx (ephemeral)`,instruction:`Nothing to uninstall — npx runs from a temporary cache. (Optional: npm cache clean --force)`}),i}function xf(e){try{return Vn(`npm`,e,D({encoding:`utf-8`,timeout:5e3,stdio:[`ignore`,`pipe`,`ignore`]}))}catch{return null}}const Sf=`━`.repeat(64);function Cf(e){let t=[R(Sf),z(` One more step — remove the OpenKnowledge app itself`),F(` (OpenKnowledge can't delete its own running binary — do this by hand.)`),``];if(e.length===0)t.push(F(` Install method not detected. If you installed it, remove it via:`)),t.push(` ${P(`OK Desktop`)} — move /Applications/OpenKnowledge.app to the Trash`),t.push(` ${P(`npm global`)} — npm uninstall -g @inkeep/open-knowledge`),t.push(` ${P(`npx`)} — nothing to remove (runs from a temporary cache)`);else for(let n of e)t.push(` ${P(n.label)}`),t.push(` ${n.instruction}`);return t.push(R(Sf)),t.join(`
|
|
91
91
|
`)}function wf(e){return H(e,`..`,`..`)}function Tf(e){return U(B(e,`.ok`))}async function Ef(e){let t=e.findRoot??nt,n=e.readRecents??mo,r=t(e.cwd)?.rootPath??null,i=fo({home:e.home,platformName:e.platform,env:e.env}),a=new Set;for(let e of n(i))a.add(H(e.path));let o=new Set(e.lockDirs.map(wf));for(let e of o)a.add(e);r&&a.delete(r);let s=[];r&&Tf(r)&&s.push({path:r,running:o.has(r),current:!0});for(let e of a)Tf(e)&&s.push({path:e,running:o.has(e),current:!1});return s.length===0?[]:e.allProjects?s.map(e=>e.path):e.yes||e.dryRun||!(e.isTTY??process.stdout.isTTY)?[]:(e.promptFn??Df)(s)}async function Df(e){return Tn({message:`Also remove OpenKnowledge from these projects? (space to toggle; none selected by default)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as e}from"./git-handle-bsekfuqb.mjs";export{e as createGitInstance};
|