@inkeep/open-knowledge 0.5.0-beta.42 → 0.5.0-beta.44

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.
@@ -3,7 +3,7 @@ name: open-knowledge
3
3
  description: "MUST invoke when the project contains a .ok/ directory — before any read or edit of .md / .mdx files, any mcp__open-knowledge__ tool call, and any write_document / edit_document. Skip if no .ok/ — not an Open Knowledge project. Carries preview-attach (open preview browser at session start; one-shot on `action: attach-preview-once`; surface to user on `action: start-ui` when no UI is running), STOP rules for native Read/Grep/Edit on in-scope markdown, grounding rules (every factual claim needs a source), standard markdown linking with get_dead_links verification, image sourcing + alt-text + source-citation rules, folder-first organization with opt-in nested .ok/ frontmatter + templates, and the anti-pattern table."
4
4
  compatibility: "Claude Code, Claude Desktop, Claude Cowork, Claude.ai web. Requires Open Knowledge MCP server + code execution."
5
5
  metadata:
6
- version: "0.5.0-beta.42"
6
+ version: "0.5.0-beta.44"
7
7
  author: "Inkeep"
8
8
  repository: "https://github.com/inkeep/open-knowledge"
9
9
  ---
@@ -176,7 +176,10 @@ Knowledge-base docs are factual artifacts — whether the project is a wiki, an
176
176
  1. Fetch it (`WebFetch` / `curl` / your host's equivalent) and save to a local path.
177
177
  2. Reference with a relative markdown image link.
178
178
  3. Cite the source in a caption (see §4 below).
179
- - **Conventional location:** `assets/images/<topic>/<filename>` under the content root. If the project already has a different convention, follow it — check via `exec("ls -A assets/")` or `exec("find . -type d -name images")` first.
179
+ - **Conventional location depends on placement model.** OK runs two distinct asset-placement models:
180
+ - **(a) Free-form image embeds inside a doc you're authoring** — co-located **alongside the referencing doc** (same directory as the doc that embeds them). This matches the editor's drop-to-doc-folder default and the `attachmentFolderPath: "./"` semantic from the asset-embed surface. Sha256 same-directory dedup operates on this layout.
181
+ - **(b) Raw sources preserved via `ingest`** — co-located **inside `external-sources/`** under the content root, alongside the wrapper markdown that embeds them (`external-sources/<slug>.<ext>` + `external-sources/<slug>.md`). This is the Karpathy layer-1 convention; the wrapper IS the referring doc, so binary + wrapper are same-dir-as-referring per the asset-embed contract. Cross-folder consumers (e.g., `research/foo.md`) resolve `![[<slug>.<ext>]]` via the basename index.
182
+ - If the project already has a different convention, follow it — check via `exec("ls -A")` first.
180
183
  - If you cannot fetch (no network, paywalled source, etc.): DON'T invent a local path. Either omit the image or mark inline `(TODO: image needs sourcing from <URL>)` for a human.
181
184
 
182
185
  ### 3. Alt-text discipline
@@ -214,6 +217,33 @@ tags:
214
217
 
215
218
  Folder-level defaults that any new doc here inherits live in opt-in nested `<folder>/.ok/frontmatter.yml` and merge at read time — see *Folder structure + metadata* below.
216
219
 
220
+ **Binary-source wrappers (`ingest`-produced).** Docs that wrap a co-located binary file under `external-sources/` carry extra frontmatter keys so the wrapper-binary pair is fully described and re-ingest can detect changes:
221
+
222
+ ```yaml
223
+ ---
224
+ title: ...
225
+ description: ...
226
+ source_url: https://example.com/file.pdf
227
+ source_path: ./<slug>.<ext> # relative to this wrapper
228
+ media_type: application/pdf # RFC 6838 type/subtype
229
+ bytes: 1234567 # integer
230
+ sha256: <64-char hex> # of the embedded binary
231
+ date_fetched: YYYY-MM-DD
232
+ preservation: binary # OR: text-only (shell-less fallback) / text-extracted (genuine HTML source)
233
+ supersedes: # OPTIONAL — present on dated-sibling wrappers from a re-ingest
234
+ - <prior-slug>.md # YAML list (matches consolidate's shape so downstream tooling reads uniformly)
235
+ tags:
236
+ - source
237
+ - immutable
238
+ - layer-ingest
239
+ - binary # OR: text — matches the `preservation` mode
240
+ ---
241
+
242
+ ![[<slug>.<ext>]]
243
+ ```
244
+
245
+ The wrapper body is just the wiki-embed (`![[<slug>.<ext>]]`). For PDFs and opaque attachments this renders as a Notion-style File row that click-dispatches to the appropriate viewer; explicit `<Pdf src="./<slug>.pdf" />` JSX is the opt-in inline canvas viewer. See `ingest`'s tool body for the full re-ingest + size + executable rules.
246
+
217
247
  **Editing frontmatter.** `edit_document` does NOT change frontmatter — it's body-only by design; frontmatter-intersecting find/replace calls return HTTP 400. For single-key edits (set / create / delete one or a few properties), prefer `frontmatter_patch({ docName, patch: { key: value } })` — JSON Merge Patch (RFC 7396), `null` deletes, field-level CRDT merge for concurrent edits, atomic per-call. For full-document rewrites (≥3-5 frontmatter keys changing, or body and frontmatter together), call `write_document({ docName, position: "replace", markdown })` and include the new YAML block at the top of `markdown`. Folder defaults from the nested `.ok/frontmatter.yml` cascade still merge at read time, so you only need to declare keys that differ from the cascade.
218
248
 
219
249
  ## Follow project conventions — read folder defaults before writing (MUST)
@@ -404,7 +434,7 @@ Three correspond to [Karpathy's three-layer knowledge-base pattern](https://gist
404
434
 
405
435
  | Tool | Layer | When to invoke |
406
436
  | ------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
407
- | `ingest` | Raw sources (immutable) | User shares a URL/PDF/file to preserve verbatim, **OR you fetched a URL** (`WebFetch` / `WebSearch` / equivalent) to ground a claim that's about to land in the knowledge base. The KB is closed-loop — agent-initiated fetches are not exempt. No analysis in the file itself — takeaways go back to the user in chat. |
437
+ | `ingest` | Raw sources (immutable) | User shares a URL/PDF/file to preserve verbatim, **OR you fetched a URL** (`WebFetch` / `WebSearch` / equivalent) to ground a claim that's about to land in the knowledge base. The KB is closed-loop — agent-initiated fetches are not exempt. **Binary sources** (PDFs, images, audio, Office docs) are preserved verbatim, not text-scraped — the tool body documents the binary-vs-text classification, write-path STOP gates (executable, size, scheme), re-ingest semantics, and shell-less fallback. No analysis in the file itself — takeaways go back to the user in chat. |
408
438
  | `research` | KB, provisional | User asks you to investigate, compare alternatives, or synthesize multiple sources. Produces a `status: provisional` article with a `sources:` list. Follows scan-first routing, a STOP scoping gate, 3P-external framing, and a validate checklist — the tool body enforces each step. |
409
439
  | `consolidate` | KB, canonical | Team has actually decided after research and wants the outcome committed as source-of-truth. Starts with a STOP gate confirming the decision exists; writes a `status: canonical` article with a `supersedes:` chain. |
410
440
  | `discover` | Project metadata | First arrival at a repo with existing content AND no folder frontmatter / templates set. Extracts conventions from siblings; activates the link graph (orphans, hubs, untextualized mentions); proposes folder frontmatter + templates + `.okignore`; per-phase user confirmation. Requires `ok start` running (Phase 1 step 0 gates). Skip on empty repos (use `ok seed`). One-shot; idempotent on re-run. |
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{o as e}from"./chunk-FK9Q3tQk.mjs";import{t}from"./esm-CEs3LWY3.mjs";import{Ai as n,B as r,Ci as i,D as a,Di as o,Dn as s,E as c,Ei as l,Gn as u,Gr as d,Gt as f,Hr as p,Jn as m,Kr as h,Mi as g,Oi as _,Si as v,Ti as y,U as b,Ur as x,Wr as S,Xr as ee,Yr as te,Z as ne,bi as re,cr as ie,it as ae,ji as oe,ki as se,m as ce,nn as le,nt as ue,pi as de,pn as fe,qr as pe,vi as me,wi as he,xi as ge,z as _e,zn as ve}from"./dist-DhjzONr6.mjs";import{n as ye,r as be,t as C}from"./dist-bundle-BSdjl7Rj.mjs";import{C as xe,D as Se,E as Ce,O as we,S as Te,T as Ee,a as De,b as Oe,f as ke,k as Ae,v as je,w as Me,x as Ne,y as Pe}from"./init-C83LwZ9L.mjs";import{c as Fe,f as Ie,l as Le,n as Re,s as w}from"./server-lock-D7DXNVql-BRVVzA6T.mjs";import{i as ze}from"./git-handle-DwfYp_z--CfyPz4Dz.mjs";import{n as Be}from"./constants-Co5pHcW2.mjs";import{i as Ve}from"./src-Qw69gDuh.mjs";import{n as He,t as Ue}from"./loader-BzMkwP2B.mjs";import{d as We,f as Ge,l as Ke,m as qe,p as Je,s as Ye}from"./start-DjkaPQd5.mjs";import{c as Xe,i as T,n as E,o as D,r as O,s as Ze,t as k}from"./colors-BtKMHmBX.mjs";import{execFileSync as Qe,execSync as $e,spawn as et,spawnSync as A}from"node:child_process";import tt,{basename as nt,dirname as rt,isAbsolute as it,join as j,relative as at,resolve as M}from"node:path";import{closeSync as ot,existsSync as N,mkdirSync as st,mkdtempSync as ct,openSync as lt,readFileSync as P,readdirSync as ut,realpathSync as dt,rmSync as ft,statSync as pt,unlinkSync as mt,writeFileSync as ht}from"node:fs";import gt from"node:process";import{homedir as _t,hostname as vt,tmpdir as yt}from"node:os";import{fileURLToPath as bt}from"node:url";import{AsyncLocalStorage as xt,AsyncResource as St}from"node:async_hooks";import{stripVTControlCharacters as Ct,styleText as F}from"node:util";import*as wt from"node:readline";import{randomUUID as Tt}from"node:crypto";import{realpath as Et}from"node:fs/promises";import{setTimeout as Dt}from"node:timers/promises";import{createInterface as Ot}from"node:readline/promises";var kt=g();const At=`open-knowledge`;var jt=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(At,e).getPassword();return n==null?null:JSON.parse(n)}catch{return null}}async set(e,t,n,r){let{Entry:i}=await import(`@napi-rs/keyring`),a=new i(At,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(At,e).deletePassword()}catch{}}},Mt=class{backend=`file`;authFile;constructor(e){this.authFile=e??j(_t(),`.ok`,`auth.yml`)}read(){if(!N(this.authFile))return{};try{return(0,kt.parse)(P(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=rt(this.authFile);N(t)||st(t,{recursive:!0,mode:448}),ht(this.authFile,(0,kt.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)}};async function Nt(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(At,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
2
+ import{o as e}from"./chunk-FK9Q3tQk.mjs";import{t}from"./esm-CEs3LWY3.mjs";import{Ai as n,B as r,Ci as i,D as a,Di as o,Dn as s,E as c,Ei as l,Gn as u,Gr as d,Gt as f,Hr as p,Jn as m,Kr as h,Mi as g,Oi as _,Si as v,Ti as y,U as b,Ur as x,Wr as S,Xr as ee,Yr as te,Z as ne,bi as re,cr as ie,it as ae,ji as oe,ki as se,m as ce,nn as le,nt as ue,pi as de,pn as fe,qr as pe,vi as me,wi as he,xi as ge,z as _e,zn as ve}from"./dist-CQVP3NVF.mjs";import{n as ye,r as be,t as C}from"./dist-bundle-BSdjl7Rj.mjs";import{C as xe,D as Se,E as Ce,O as we,S as Te,T as Ee,a as De,b as Oe,f as ke,k as Ae,v as je,w as Me,x as Ne,y as Pe}from"./init-CzIlOXY5.mjs";import{c as Fe,f as Ie,l as Le,n as Re,s as w}from"./server-lock-D7DXNVql-BRVVzA6T.mjs";import{i as ze}from"./git-handle-DwfYp_z--CfyPz4Dz.mjs";import{n as Be}from"./constants-SS3E-YX9.mjs";import{i as Ve}from"./src-DPfUVBkb.mjs";import{n as He,t as Ue}from"./loader-B93v7E2S.mjs";import{d as We,f as Ge,l as Ke,m as qe,p as Je,s as Ye}from"./start-Pye6UK9z.mjs";import{c as Xe,i as T,n as E,o as D,r as O,s as Ze,t as k}from"./colors-BtKMHmBX.mjs";import{execFileSync as Qe,execSync as $e,spawn as et,spawnSync as A}from"node:child_process";import tt,{basename as nt,dirname as rt,isAbsolute as it,join as j,relative as at,resolve as M}from"node:path";import{closeSync as ot,existsSync as N,mkdirSync as st,mkdtempSync as ct,openSync as lt,readFileSync as P,readdirSync as ut,realpathSync as dt,rmSync as ft,statSync as pt,unlinkSync as mt,writeFileSync as ht}from"node:fs";import gt from"node:process";import{homedir as _t,hostname as vt,tmpdir as yt}from"node:os";import{fileURLToPath as bt}from"node:url";import{AsyncLocalStorage as xt,AsyncResource as St}from"node:async_hooks";import{stripVTControlCharacters as Ct,styleText as F}from"node:util";import*as wt from"node:readline";import{randomUUID as Tt}from"node:crypto";import{realpath as Et}from"node:fs/promises";import{setTimeout as Dt}from"node:timers/promises";import{createInterface as Ot}from"node:readline/promises";var kt=g();const At=`open-knowledge`;var jt=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(At,e).getPassword();return n==null?null:JSON.parse(n)}catch{return null}}async set(e,t,n,r){let{Entry:i}=await import(`@napi-rs/keyring`),a=new i(At,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(At,e).deletePassword()}catch{}}},Mt=class{backend=`file`;authFile;constructor(e){this.authFile=e??j(_t(),`.ok`,`auth.yml`)}read(){if(!N(this.authFile))return{};try{return(0,kt.parse)(P(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=rt(this.authFile);N(t)||st(t,{recursive:!0,mode:448}),ht(this.authFile,(0,kt.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)}};async function Nt(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(At,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
3
3
  `),new jt}catch{return process.stderr.write(`[auth] token storage: file (~/.ok/auth.yml)
4
4
  `),new Mt(e)}}async function Pt(e,t){let n=[],r=new Mt(t);await r.get(e)!=null&&(await r.clear(e),n.push(`file`));try{let{Entry:t}=await import(`@napi-rs/keyring`);new t(At,`__probe__`);let r=new jt;await r.get(e)!=null&&(await r.clear(e),n.push(`keychain`))}catch{}return{touched:n}}async function Ft(e,t,n){let r=It(await Lt(e)).host??``;if(!r)return 1;let i=await n.get(r);if(i==null)return 1;let a=e=>e.replace(/[\r\n]/g,``);return t.write(`username=${a(i.login)}\npassword=${a(i.token)}\n`),0}function It(e){let t={};for(let n of e.split(`
5
5
  `)){let e=n.trim();if(e===``)continue;let r=e.indexOf(`=`);r!==-1&&(t[e.slice(0,r)]=e.slice(r+1))}return t}function Lt(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 Rt(e){let n=new t(`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 t=await e(),n=await Ft(process.stdin,process.stdout,t);process.exit(n)}),n}function zt(e){let t=e.endpoint.DEFAULTS;return/^https:\/\/(api\.)?github\.com$/.test(t.baseUrl)?`https://github.com`:t.baseUrl.replace(`/api/v3`,``)}async function Bt(e,t,n){let r={baseUrl:zt(e),headers:{accept:`application/json`},...n},i=await e(t,r);if(`error`in i.data){let n=new ye(`${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 Vt(e){let t=e.request||C,n={client_id:e.clientId};return`scopes`in e&&Array.isArray(e.scopes)&&(n.scope=e.scopes.join(` `)),Bt(t,`POST /login/device/code`,n)}async function Ht(e){let t=await Bt(e.request||C,`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=Ut(e,t.data.expires_in),n.refreshTokenExpiresAt=Ut(e,t.data.refresh_token_expires_in)}delete n.scopes}return{...t,authentication:n}}function Ut(e,t){return new Date(e+t*1e3).toISOString()}async function Wt(e,t){let n=Gt(e,t.auth);if(n)return n;let{data:r}=await Vt({clientType:e.clientType,clientId:e.clientId,request:t.request||e.request,scopes:t.auth.scopes||e.scopes});await e.onVerification(r);let i=await qt(t.request||e.request,e.clientId,e.clientType,r);return e.authentication=i,i}function Gt(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 Kt(e){await new Promise(t=>setTimeout(t,e*1e3))}async function qt(e,t,n,r){try{let i={clientId:t,request:e,code:r.device_code},{authentication:a}=n===`oauth-app`?await Ht({...i,clientType:`oauth-app`}):await Ht({...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 Kt(r.interval),qt(e,t,n,r);if(a===`slow_down`)return await Kt(r.interval+7),qt(e,t,n,r);throw i}}async function Jt(e,t){return Wt(e,{auth:t})}async function Yt(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 Wt(e,{request:t,auth:{type:`oauth`}});return i.headers.authorization=`token ${a}`,t(i)}var Xt=`0.0.0-development`;function Zt(e){let t=e.request||C.defaults({headers:{"user-agent":`octokit-auth-oauth-device.js/${Xt} ${be()}`}}),{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(Jt.bind(null,i),{hook:Yt.bind(null,i)})}async function Qt(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=Zt({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-BmF5_Mcp.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??[]}}const $t={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 en;(function(e){})(en||={});function tn(e){return n(re,e)}function nn(){return process.env.OPEN_KNOWLEDGE_GITHUB_CLIENT_ID??`Ov23liqlSd0V1MwR6rhI`}const rn=new Set([`gitlab.com`,`bitbucket.org`,`codeberg.org`,`gitea.com`,`sr.ht`,`sourcehut.org`]);function I(e){let t=e.toLowerCase().replace(/:\d+$/,``);rn.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 an(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function on(e,t,n=Qt){let r=nn(),{host:i,json:a}=e;I(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?an(!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?an(!0,{type:`complete`,host:i,login:s}):process.stderr.write(`✓ Logged in as ${s} on ${i}\n`)}function sn(e){return new t(`login`).description(`Authenticate with GitHub via Device Flow`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{await on(t,await e())})}const cn=e=>e.name===`enter`||e.name===`return`;var ln=class extends Error{name=`AbortPromptError`;message=`Prompt was aborted`;constructor(e){super(),this.cause=e?.cause}},un=class extends Error{name=`CancelPromptError`;message=`Prompt was canceled`},dn=class extends Error{name=`ExitPromptError`},fn=class extends Error{name=`HookError`},pn=class extends Error{name=`ValidationError`};const mn=new xt;function hn(e){return{rl:e,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function gn(e,t){let n=hn(e);return mn.run(n,()=>{function e(e){n.handleChange=()=>{n.index=0,e()},n.handleChange()}return t(e)})}function L(){let e=mn.getStore();if(!e)throw new fn(`[Inquirer] Hook functions can only be called from within a prompt`);return e}function _n(){return L().rl}function vn(e){return St.bind((...t)=>{let n=L(),r=!1,i=n.handleChange;n.handleChange=()=>{r=!0};let a=e(...t);return r&&i(),n.handleChange=i,a})}function yn(e){let t=L(),{index:n}=t,r=e({get(){return t.hooks[n]},set(e){t.hooks[n]=e},initialized:n in t.hooks});return t.index++,r}function bn(){L().handleChange()}const xn={queue(e){let t=L(),{index:n}=t;t.hooksEffect.push(()=>{t.hooksCleanup[n]?.();let r=e(_n());if(r!=null&&typeof r!=`function`)throw new pn(`useEffect return value must be a cleanup function or nothing.`);t.hooksCleanup[n]=r})},run(){let e=L();vn(()=>{e.hooksEffect.forEach(e=>{e()}),e.hooksEffect.length=0})()},clearAll(){let e=L();e.hooksCleanup.forEach(e=>{e?.()}),e.hooksEffect.length=0,e.hooksCleanup.length=0}};function Sn(e){return typeof e==`function`}function R(e){return yn(t=>{let n=St.bind(function(e){t.get()!==e&&(t.set(e),bn())});if(t.initialized)return[t.get(),n];let r=Sn(e)?e():e;return t.set(r),[r,n]})}function Cn(e,t){yn(n=>{let r=n.get();(!Array.isArray(r)||t.some((e,t)=>!Object.is(e,r[t])))&&xn.queue(e),n.set(t)})}const wn={prefix:{idle:F(`blue`,`?`),done:F(`green`,Ae.tick)},spinner:{interval:80,frames:[`⠋`,`⠙`,`⠹`,`⠸`,`⠼`,`⠴`,`⠦`,`⠧`,`⠇`,`⠏`].map(e=>F(`yellow`,e))},style:{answer:e=>F(`cyan`,e),message:e=>F(`bold`,e),error:e=>F(`red`,`> ${e}`),defaultAnswer:e=>F(`dim`,`(${e})`),help:e=>F(`dim`,e),highlight:e=>F(`cyan`,e),key:e=>F(`cyan`,F(`bold`,`<${e}>`))}};function Tn(e){if(typeof e!=`object`||!e)return!1;let t=e;for(;Object.getPrototypeOf(t)!==null;)t=Object.getPrototypeOf(t);return Object.getPrototypeOf(e)===t}function En(...e){let t={};for(let n of e)for(let[e,r]of Object.entries(n)){let n=t[e];t[e]=Tn(n)&&Tn(r)?En(n,r):r}return t}function Dn(...e){return En(wn,...e.filter(e=>e!=null))}function On({status:e=`idle`,theme:t}){let[n,r]=R(!1),[i,a]=R(0),{prefix:o,spinner:s}=Dn(t);return Cn(()=>{if(e===`loading`){let e,t=-1,n=setTimeout(()=>{r(!0),e=setInterval(()=>{t+=1,a(t%s.frames.length)},s.interval)},300);return()=>{clearTimeout(n),clearInterval(e)}}else r(!1)},[e]),n?s.frames[i]:typeof o==`string`?o:o[e===`loading`?`idle`:e]??o.idle}function kn(e){return R({current:e})[0]}function An(e){let t=kn(e);t.current=e,Cn(e=>{let n=!1,r=vn((r,i)=>{n||t.current(i,e)});return e.input.on(`keypress`,r),()=>{n=!0,e.input.removeListener(`keypress`,r)}},[])}var jn=e(we(),1);function Mn(e,t){return e.split(`
@@ -19,10 +19,10 @@ import{o as e}from"./chunk-FK9Q3tQk.mjs";import{t}from"./esm-CEs3LWY3.mjs";impor
19
19
  `)}function Gr(){return new t(`signout`).description(`Remove stored credentials`).option(`--host <host>`,`GitHub hostname`,`github.com`).action(async e=>{await Wr(e)})}async function Kr(e,t,n=Br){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}}async function qr(e,t){let{host:n,json:r}=e;I(n);let i=await Kr(n,t);i.tier===`none`&&(r?process.stdout.write(`${JSON.stringify({type:`status`,host:n,authenticated:!1})}\n`):process.stderr.write(`Not logged in to ${n}\n`),process.exit(1));let a=n===`github.com`?void 0:`https://${n}/api/v3`,o=new B({auth:i.token,...a?{baseUrl:a}:{}});try{let{data:e}=await o.users.getAuthenticated();r?process.stdout.write(`${JSON.stringify({type:`status`,host:n,authenticated:!0,tier:i.tier,login:e.login,name:e.name,email:e.email})}\n`):process.stderr.write(`✓ Logged in as ${e.login} on ${n}\n`)}catch{r?process.stdout.write(JSON.stringify({type:`status`,host:n,authenticated:!1,error:`token invalid`})+`
20
20
  `):process.stderr.write(`✗ Token invalid for ${n}\n`),process.exit(1)}}function Jr(e){return new t(`status`).description(`Show authentication status`).option(`--host <host>`,`GitHub or GitHub Enterprise hostname`,`github.com`).option(`--json`,`Output JSON`,!1).action(async t=>{await qr(t,await e())})}function Yr(){let e=new t(`auth`);e.description(`GitHub authentication management`);let n=()=>Nt();return e.addCommand(sn(n)),e.addCommand(Jr(n)),e.addCommand(Ur(n)),e.addCommand(Gr()),e.addCommand(Rr(n)),e.addCommand(Rt(n)),e}function V(e,t,n={}){let r=Le(e,t);if(!N(r))return{status:`missing`,lockPath:r};let i;try{i=JSON.parse(P(r,`utf-8`))}catch{return{status:`corrupt`,lockPath:r}}if(!i||typeof i!=`object`||!Fe(i.pid))return{status:`corrupt`,lockPath:r};let a=i;if(!(n.isAlive??w)(a.pid))return{status:`dead-pid`,lockPath:r,lock:a};let o=n.host??vt();return a.hostname===o?{status:`alive`,lockPath:r,lock:a}:{status:`foreign-host`,lockPath:r,lock:a}}function Xr(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 Zr(e){let t=e.inspect??(t=>V(e.lockDir,t)),n=e.unlink??(e=>mt(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=Xr(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 Qr(e){return new t(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{e(),Zr({lockDir:m(process.cwd())}).failed.length>0&&(process.exitCode=1)})}async function $r(e,t,n={},r=Br){if(!n.skipGhDetect&&r().available)return{tier:`A`,credentialArgs:[`-c`,`credential.helper=!gh auth git-credential`]};let i=await t.get(e);return i==null?{tier:`none`,credentialArgs:[]}:{tier:i.gitProtocol===`ssh`?`C`:`B`,credentialArgs:[`-c`,`credential.helper=!open-knowledge auth git-credential`]}}async function ei(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 ti=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function ni(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 ti)if(n.includes(e))return{stage:t[1],pct:Math.round(i+r/100*(a-i))};return null}function H(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}function ri(e,t,n){return e===`https`&&t===`github.com`&&n}async function ii(e,t,n,r=process.cwd()){let i=Ve(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=t.dir?M(r,t.dir):M(r,i.name);if(N(a)&&ut(a).length>0)throw Error(`Target directory is not empty: ${a}`);let o=await Nt(),s=i.protocol===`https`&&i.hostname===`github.com`?await ei(i.owner,i.name):!1,c=ri(i.protocol,i.hostname,s)?{tier:`none`,credentialArgs:[]}:await $r(i.hostname,o,{}),l=ze({baseDir:r,config:c.credentialArgs.length>=2?[c.credentialArgs[1]]:[],unsafe:{allowUnsafeCredentialHelper:!0}}).env({GIT_TERMINAL_PROMPT:`0`}),u=-1;l.outputHandler((e,n,r)=>{r.on(`data`,e=>{let n=e.toString(`utf-8`);for(let e of n.split(`
21
21
  `)){let n=ni(e);n&&n.pct!==u&&(u=n.pct,H(t.json,{type:`progress`,pct:n.pct,stage:n.stage}),t.json||process.stderr.write(`\r Cloning ${n.pct}%`))}})}),await l.clone(e,a,[`--progress`]),t.json||process.stderr.write(`
22
- `);try{let{runInit:e}=await import(`./init-C9m6w7yf.mjs`),n=await e({cwd:a,mcp:!1});if(n.contentUpdated.length>0){let e=`auto-init: updated ${n.contentUpdated.join(`, `)}`;t.json?H(!0,{type:`warning`,message:e}):process.stderr.write(` ${e}\n`)}}catch(e){let n=e instanceof Error?e.message:String(e);t.json?H(!0,{type:`warning`,message:`auto-init: ${n}`}):process.stderr.write(` auto-init: ${n}\n`)}try{ai(a)}catch(e){let n=e instanceof Error?e.message:String(e);t.json?H(!0,{type:`warning`,message:`git-exclude: ${n}`}):process.stderr.write(` git-exclude: ${n}\n`)}return a}function ai(e){let t=j(e,`.git`,`info`,`exclude`);if(!N(t))return`no-exclude`;let n=P(t,`utf-8`),r=new Set([`.ok`,`.ok/`,`/.ok`,`/.ok/`]);return n.split(`
22
+ `);try{let{runInit:e}=await import(`./init-CXHjEcRB.mjs`),n=await e({cwd:a,mcp:!1});if(n.contentUpdated.length>0){let e=`auto-init: updated ${n.contentUpdated.join(`, `)}`;t.json?H(!0,{type:`warning`,message:e}):process.stderr.write(` ${e}\n`)}}catch(e){let n=e instanceof Error?e.message:String(e);t.json?H(!0,{type:`warning`,message:`auto-init: ${n}`}):process.stderr.write(` auto-init: ${n}\n`)}try{ai(a)}catch(e){let n=e instanceof Error?e.message:String(e);t.json?H(!0,{type:`warning`,message:`git-exclude: ${n}`}):process.stderr.write(` git-exclude: ${n}\n`)}return a}function ai(e){let t=j(e,`.git`,`info`,`exclude`);if(!N(t))return`no-exclude`;let n=P(t,`utf-8`),r=new Set([`.ok`,`.ok/`,`/.ok`,`/.ok/`]);return n.split(`
23
23
  `).map(e=>e.trim()).some(e=>r.has(e))?`already-present`:(ht(t,`${n}${n.length===0||n.endsWith(`
24
24
  `)?``:`
25
- `}.ok/\n`,`utf-8`),`appended`)}function oi(e){return new t(`clone`).description(`Clone a git repository and open it`).argument(`<url>`,`Repository URL or owner/repo shorthand`).argument(`[dir]`,`Target directory (default: ./<repo-name>)`).option(`--json`,`Output JSONL progress events`,!1).action(async(t,n,r)=>{let i=e();try{let a=await ii(t,{json:r.json,dir:n},i);if(r.json)H(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-D_t9jHk0.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?H(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}const si=[[`sync`],[`persistence`,`debounceMs`],[`persistence`,`maxDebounceMs`],[`server`,`port`],[`content`,`include`],[`content`,`exclude`]];function ci(e={}){let t=e.log??(e=>console.error(e)),n=e.error??(e=>console.error(e)),r=e.loadConfigFn??He;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 li(e){let t=(0,kt.parseDocument)(P(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 si)t.hasIn(e)&&n.push(e.join(`.`));return n}function ui(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function di(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=ui(i)?i:{};e[r]=a,e=a}e[n[n.length-1]]=null}return t}async function fi(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??ee,s=[];(r===`project`||r===`both`)&&s.push({scope:`project`,absPath:te(`project`,a,e.homedirOverride)}),(r===`user`||r===`both`)&&s.push({scope:`user`,absPath:te(`user`,a,e.homedirOverride)});let c=[],l=!0;for(let{scope:t,absPath:n}of s){if(!N(n)){c.push({path:n,scope:t,found:[],removed:[]});continue}let r;try{r=li(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:di(si.filter(e=>r.includes(e.join(`.`)))),homedirOverride:e.homedirOverride});if(!s.ok){c.push({path:n,scope:t,found:r,removed:[],error:de(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 pi(){let e=new t(`config`).description(`Inspect and maintain Open Knowledge configuration files`);return e.command(`validate`).description(`Validate the merged config (defaults → user → project)`).action(()=>{ci({}).ok||(process.exitCode=1)}),e.command(`migrate`).description(`Remove deprecated config fields (sync.*, persistence.{debounceMs,maxDebounceMs}, server.port, content.{include,exclude}) idempotently`).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 fi({scope:t,dryRun:e.dryRun})).ok||(process.exitCode=1)}),e}var U=e(Xe(),1);const W=2e3,mi=[/cli\.mjs/,/(^|[\s/])(open-knowledge|ok)\s+(start|mcp|ui)(\s|$)/,/(^|[\s/])bun([\s/]).*?(run dev|packages\/app|vite|hocuspocus)/,/(^|[\s/])node([\s/]).*?(packages\/(cli|app)|vite|hocuspocus)/,/(^|\s)--ok-lock-dir-b64=/];function hi(e){return mi.some(t=>t.test(e))}function gi(e){let t=e.trim().split(/\s+/).find(e=>e.startsWith(`--ok-lock-dir-b64=`));if(t==null)return null;let n=t.slice(18);if(!n)return null;try{let e=Buffer.from(n,`base64url`).toString(`utf8`);return it(e)?e:null}catch{return null}}function _i(e){let t=[];for(let n of e.split(`
25
+ `}.ok/\n`,`utf-8`),`appended`)}function oi(e){return new t(`clone`).description(`Clone a git repository and open it`).argument(`<url>`,`Repository URL or owner/repo shorthand`).argument(`[dir]`,`Target directory (default: ./<repo-name>)`).option(`--json`,`Output JSONL progress events`,!1).action(async(t,n,r)=>{let i=e();try{let a=await ii(t,{json:r.json,dir:n},i);if(r.json)H(!0,{type:`complete`,dir:a});else{process.stderr.write(`✓ Cloned to ${a}\n`),process.chdir(a);let{startCommand:t}=await import(`./start-DOTmfJ-6.mjs`);await t(e).parseAsync([],{from:`user`})}}catch(e){let t=e instanceof Error?e.message:String(e);r.json?H(!0,{type:`error`,message:t}):process.stderr.write(`✗ ${t}\n`),process.exitCode=1}})}const si=[[`sync`],[`persistence`,`debounceMs`],[`persistence`,`maxDebounceMs`],[`server`,`port`],[`content`,`include`],[`content`,`exclude`]];function ci(e={}){let t=e.log??(e=>console.error(e)),n=e.error??(e=>console.error(e)),r=e.loadConfigFn??He;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 li(e){let t=(0,kt.parseDocument)(P(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 si)t.hasIn(e)&&n.push(e.join(`.`));return n}function ui(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function di(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=ui(i)?i:{};e[r]=a,e=a}e[n[n.length-1]]=null}return t}async function fi(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??ee,s=[];(r===`project`||r===`both`)&&s.push({scope:`project`,absPath:te(`project`,a,e.homedirOverride)}),(r===`user`||r===`both`)&&s.push({scope:`user`,absPath:te(`user`,a,e.homedirOverride)});let c=[],l=!0;for(let{scope:t,absPath:n}of s){if(!N(n)){c.push({path:n,scope:t,found:[],removed:[]});continue}let r;try{r=li(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:di(si.filter(e=>r.includes(e.join(`.`)))),homedirOverride:e.homedirOverride});if(!s.ok){c.push({path:n,scope:t,found:r,removed:[],error:de(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 pi(){let e=new t(`config`).description(`Inspect and maintain Open Knowledge configuration files`);return e.command(`validate`).description(`Validate the merged config (defaults → user → project)`).action(()=>{ci({}).ok||(process.exitCode=1)}),e.command(`migrate`).description(`Remove deprecated config fields (sync.*, persistence.{debounceMs,maxDebounceMs}, server.port, content.{include,exclude}) idempotently`).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 fi({scope:t,dryRun:e.dryRun})).ok||(process.exitCode=1)}),e}var U=e(Xe(),1);const W=2e3,mi=[/cli\.mjs/,/(^|[\s/])(open-knowledge|ok)\s+(start|mcp|ui)(\s|$)/,/(^|[\s/])bun([\s/]).*?(run dev|packages\/app|vite|hocuspocus)/,/(^|[\s/])node([\s/]).*?(packages\/(cli|app)|vite|hocuspocus)/,/(^|\s)--ok-lock-dir-b64=/];function hi(e){return mi.some(t=>t.test(e))}function gi(e){let t=e.trim().split(/\s+/).find(e=>e.startsWith(`--ok-lock-dir-b64=`));if(t==null)return null;let n=t.slice(18);if(!n)return null;try{let e=Buffer.from(n,`base64url`).toString(`utf8`);return it(e)?e:null}catch{return null}}function _i(e){let t=[];for(let n of e.split(`
26
26
  `)){let e=n.trim();if(!e)continue;let r=e.indexOf(` `);if(r===-1)continue;let i=e.slice(0,r),a=e.slice(r+1),o=Number.parseInt(i,10);!Number.isNaN(o)&&hi(a)&&t.push({pid:o,command:a})}return t}function vi(e){let t=[],n=e.split(`
27
27
  `);for(let e=1;e<n.length;e++){let r=n[e]?.trim();if(!r)continue;let i=r.indexOf(` `);if(i===-1)continue;let a=r.slice(0,i),o=r.slice(i+1).trim(),s=Number.parseInt(a,10);!Number.isNaN(s)&&hi(o)&&t.push({pid:s,command:o})}return t}async function yi(){let e=A(`pgrep`,[`-a`,`-f`,`cli\\.mjs|open-knowledge|--ok-lock-dir-b64=|(^|[ /])ok[ ]+(start|mcp|ui)([ ]|$)|packages/(cli|app)|hocuspocus|vite`],{encoding:`utf-8`,timeout:W});if(!(e.error!=null&&e.error.code===`ENOENT`)){let t=e.stdout??``,n=_i(t);if(n.length>0||t.trim()===``)return n}let t=A(`ps`,[`-axo`,`pid,command`],{encoding:`utf-8`,timeout:W});return t.error!=null||!t.stdout?[]:vi(t.stdout)}function bi(e){let t=e.trim().split(/\s+/).filter(Boolean);for(let e of t){if(e.startsWith(`@`))continue;let t=nt(e);if(t===`open-knowledge`||t===`ok`||e.endsWith(`/packages/cli/src/cli.ts`)||e.endsWith(`/packages/cli/dist/cli.mjs`)||t===`cli.mjs`||t===`cli.ts`)return e}return null}function xi(e){let t=A(`ps`,[`-p`,String(e),`-o`,`command=`],{encoding:`utf-8`,timeout:W});return t.error!=null||!t.stdout?null:t.stdout.trim()||null}function Si(e){let t=A(`ps`,[`-p`,String(e),`-o`,`%cpu=,%mem=`],{encoding:`utf-8`,timeout:W});if(t.error!=null||!t.stdout)return null;let[n,r]=t.stdout.trim().split(/\s+/),i=Number.parseFloat(n??``),a=Number.parseFloat(r??``);return Number.isNaN(i)||Number.isNaN(a)?null:{cpuPercent:i,memPercent:a}}async function Ci(e){let t=A(`lsof`,[`-p`,String(e),`-a`,`-d`,`cwd`,`-Fn`],{encoding:`utf-8`,timeout:W});if(t.error!=null)return null;let n=t.stdout??``;for(let e of n.split(`
28
28
  `))if(e.startsWith(`n`)&&e.length>1)return e.slice(1);return null}function wi(e){let t=[],n=e.split(`
@@ -59,7 +59,7 @@ setTimeout(() => process.exit(2), ${t+1e4});
59
59
  `,r),o=-1;if(i!==-1&&a!==-1?o=Math.min(i,a):i===-1?a!==-1&&(o=a):o=i===e.length-1?-1:i,o===-1){n=e.slice(r);break}else{let n=e.slice(r,o);t.push(n),r=o+1,e[r-1]===`\r`&&e[r]===`
60
60
  `&&r++}}return[t,n]}var mo=class extends TransformStream{constructor({onError:e,onRetry:t,onComment:n}={}){let r;super({start(i){r=fo({onEvent:e=>{i.enqueue(e)},onError(t){e===`terminate`?i.error(t):typeof e==`function`&&e(t)},onRetry:t,onComment:n})},transform(e){r.feed(e)}})}};const ho={initialReconnectionDelay:1e3,maxReconnectionDelay:3e4,reconnectionDelayGrowFactor:1.5,maxRetries:2};var Y=class extends Error{constructor(e,t){super(`Streamable HTTP error: ${t}`),this.code=e}},go=class{constructor(e,t){this._hasCompletedAuthFlow=!1,this._url=e,this._resourceMetadataUrl=void 0,this._scope=void 0,this._requestInit=t?.requestInit,this._authProvider=t?.authProvider,this._fetch=t?.fetch,this._fetchWithInit=Qi(t?.fetch,t?.requestInit),this._sessionId=t?.sessionId,this._reconnectionOptions=t?.reconnectionOptions??ho}async _authThenStart(){if(!this._authProvider)throw new J(`No auth provider`);let e;try{e=await Ha(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})}catch(e){throw this.onerror?.(e),e}if(e!==`AUTHORIZED`)throw new J;return await this._startOrAuthSse({resumptionToken:void 0})}async _commonHeaders(){let e={};if(this._authProvider){let t=await this._authProvider.tokens();t&&(e.Authorization=`Bearer ${t.access_token}`)}this._sessionId&&(e[`mcp-session-id`]=this._sessionId),this._protocolVersion&&(e[`mcp-protocol-version`]=this._protocolVersion);let t=Zi(this._requestInit?.headers);return new Headers({...e,...t})}async _startOrAuthSse(e){let{resumptionToken:t}=e;try{let n=await this._commonHeaders();n.set(`Accept`,`text/event-stream`),t&&n.set(`last-event-id`,t);let r=await(this._fetch??fetch)(this._url,{method:`GET`,headers:n,signal:this._abortController?.signal});if(!r.ok){if(await r.body?.cancel(),r.status===401&&this._authProvider)return await this._authThenStart();if(r.status===405)return;throw new Y(r.status,`Failed to open SSE stream: ${r.statusText}`)}this._handleSseStream(r.body,e,!0)}catch(e){throw this.onerror?.(e),e}}_getNextReconnectionDelay(e){if(this._serverRetryMs!==void 0)return this._serverRetryMs;let t=this._reconnectionOptions.initialReconnectionDelay,n=this._reconnectionOptions.reconnectionDelayGrowFactor,r=this._reconnectionOptions.maxReconnectionDelay;return Math.min(t*n**+e,r)}_scheduleReconnection(e,t=0){let n=this._reconnectionOptions.maxRetries;if(t>=n){this.onerror?.(Error(`Maximum reconnection attempts (${n}) exceeded.`));return}let r=this._getNextReconnectionDelay(t);this._reconnectionTimeout=setTimeout(()=>{this._startOrAuthSse(e).catch(n=>{this.onerror?.(Error(`Failed to reconnect SSE stream: ${n instanceof Error?n.message:String(n)}`)),this._scheduleReconnection(e,t+1)})},r)}_handleSseStream(e,t,n){if(!e)return;let{onresumptiontoken:r,replayMessageId:i}=t,a,o=!1,s=!1;(async()=>{try{let t=e.pipeThrough(new TextDecoderStream).pipeThrough(new mo({onRetry:e=>{this._serverRetryMs=e}})).getReader();for(;;){let{value:e,done:n}=await t.read();if(n)break;if(e.id&&(a=e.id,o=!0,r?.(e.id)),e.data&&(!e.event||e.event===`message`))try{let t=x.parse(JSON.parse(e.data));pe(t)&&(s=!0,i!==void 0&&(t.id=i)),this.onmessage?.(t)}catch(e){this.onerror?.(e)}}(n||o)&&!s&&this._abortController&&!this._abortController.signal.aborted&&this._scheduleReconnection({resumptionToken:a,onresumptiontoken:r,replayMessageId:i},0)}catch(e){if(this.onerror?.(Error(`SSE stream disconnected: ${e}`)),(n||o)&&!s&&this._abortController&&!this._abortController.signal.aborted)try{this._scheduleReconnection({resumptionToken:a,onresumptiontoken:r,replayMessageId:i},0)}catch(e){this.onerror?.(Error(`Failed to reconnect: ${e instanceof Error?e.message:String(e)}`))}}})()}async start(){if(this._abortController)throw Error(`StreamableHTTPClientTransport already started! If using Client class, note that connect() calls start() automatically.`);this._abortController=new AbortController}async finishAuth(e){if(!this._authProvider)throw new J(`No auth provider`);if(await Ha(this._authProvider,{serverUrl:this._url,authorizationCode:e,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!==`AUTHORIZED`)throw new J(`Failed to authorize`)}async close(){this._reconnectionTimeout&&=(clearTimeout(this._reconnectionTimeout),void 0),this._abortController?.abort(),this.onclose?.()}async send(e,t){try{let{resumptionToken:n,onresumptiontoken:r}=t||{};if(n){this._startOrAuthSse({resumptionToken:n,replayMessageId:h(e)?e.id:void 0}).catch(e=>this.onerror?.(e));return}let i=await this._commonHeaders();i.set(`content-type`,`application/json`),i.set(`accept`,`application/json, text/event-stream`);let a={...this._requestInit,method:`POST`,headers:i,body:JSON.stringify(e),signal:this._abortController?.signal},o=await(this._fetch??fetch)(this._url,a),s=o.headers.get(`mcp-session-id`);if(s&&(this._sessionId=s),!o.ok){let t=await o.text().catch(()=>null);if(o.status===401&&this._authProvider){if(this._hasCompletedAuthFlow)throw new Y(401,`Server returned 401 after successful authentication`);let{resourceMetadataUrl:t,scope:n}=Ka(o);if(this._resourceMetadataUrl=t,this._scope=n,await Ha(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetchWithInit})!==`AUTHORIZED`)throw new J;return this._hasCompletedAuthFlow=!0,this.send(e)}if(o.status===403&&this._authProvider){let{resourceMetadataUrl:t,scope:n,error:r}=Ka(o);if(r===`insufficient_scope`){let r=o.headers.get(`WWW-Authenticate`);if(this._lastUpscopingHeader===r)throw new Y(403,`Server returned 403 after trying upscoping`);if(n&&(this._scope=n),t&&(this._resourceMetadataUrl=t),this._lastUpscopingHeader=r??void 0,await Ha(this._authProvider,{serverUrl:this._url,resourceMetadataUrl:this._resourceMetadataUrl,scope:this._scope,fetchFn:this._fetch})!==`AUTHORIZED`)throw new J;return this.send(e)}}throw new Y(o.status,`Error POSTing to endpoint: ${t}`)}if(this._hasCompletedAuthFlow=!1,this._lastUpscopingHeader=void 0,o.status===202){await o.body?.cancel(),d(e)&&this._startOrAuthSse({resumptionToken:void 0}).catch(e=>this.onerror?.(e));return}let c=(Array.isArray(e)?e:[e]).filter(e=>`method`in e&&`id`in e&&e.id!==void 0).length>0,l=o.headers.get(`content-type`);if(c)if(l?.includes(`text/event-stream`))this._handleSseStream(o.body,{onresumptiontoken:r},!1);else if(l?.includes(`application/json`)){let e=await o.json(),t=Array.isArray(e)?e.map(e=>x.parse(e)):[x.parse(e)];for(let e of t)this.onmessage?.(e)}else throw await o.body?.cancel(),new Y(-1,`Unexpected content type: ${l}`);else await o.body?.cancel()}catch(e){throw this.onerror?.(e),e}}get sessionId(){return this._sessionId}async terminateSession(){if(this._sessionId)try{let e=await this._commonHeaders(),t={...this._requestInit,method:`DELETE`,headers:e,signal:this._abortController?.signal},n=await(this._fetch??fetch)(this._url,t);if(await n.body?.cancel(),!n.ok&&n.status!==405)throw new Y(n.status,`Failed to terminate session: ${n.statusText}`);this._sessionId=void 0}catch(e){throw this.onerror?.(e),e}}setProtocolVersion(e){this._protocolVersion=e}get protocolVersion(){return this._protocolVersion}async resumeStream(e,t){await this._startOrAuthSse({resumptionToken:e,onresumptiontoken:t?.onresumptiontoken})}};function _o(e){return(t,n)=>{if((n?.method??`GET`).toUpperCase()===`GET`)return globalThis.fetch(t,n);let r=new AbortController,i=setTimeout(()=>r.abort(Error(`MCP request timed out after ${e}ms`)),e),a=n?.signal instanceof AbortSignal?AbortSignal.any([n.signal,r.signal]):r.signal;return globalThis.fetch(t,{...n,signal:a}).finally(()=>clearTimeout(i))}}function vo(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function yo(e){return e===`0.0.0.0`||e===`::`?`localhost`:e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function bo(e,t){return`http://${yo(e)}:${t}/mcp`}function xo(e,t){return`ws://${yo(e)}:${t}`}function So(e){let t=new URL(e);return t.protocol=t.protocol===`https:`?`wss:`:`ws:`,t.pathname=``,t.search=``,t.hash=``,t.toString().replace(/\/$/,``)}function Co(e,t){if(!(!e||e.port<=0)&&t(e.pid))return e.port}function wo(e){return N(e)?P(e,`utf-8`).trim():``}function To(e,t){return`server did not start within ${e}ms${t?` stderr:\n${t}`:``}`}function Eo(e){if(e&&typeof e==`object`&&`method`in e&&`id`in e)return e.id}function Do(e){if(!e||typeof e!=`object`||!(`result`in e))return;let t=e.result;if(!t||typeof t!=`object`||!(`protocolVersion`in t))return;let n=t.protocolVersion;return typeof n==`string`?n:void 0}function Oo(e,t){return{jsonrpc:`2.0`,id:e,error:{code:-32e3,message:t instanceof Error?t.message:String(t)}}}async function ko(e){let t=e.readLock??(()=>Ie(e.lockDir)),n=e.isAlive??w,r=e.sleep??(e=>Dt(e)),i=e.spawn??et,a=e.readErrorLog??wo,o=e.openErrorLog??(e=>lt(e,`w`)),s=e.closeFd??ot,c=e.timeoutMs??5e3,l=e.pollIntervalMs??100;if(e.portOverride!==void 0){let t=Number.parseInt(e.portOverride,10);if(Number.isNaN(t)||t<=0)throw Error(`invalid --port value '${e.portOverride}' — HTTP MCP shim requires a positive port`);return bo(`localhost`,t)}let u=Co(t(),n);if(u!==void 0)return bo(`localhost`,u);if(e.envAutoStart===`0`)throw Error(`Open Knowledge server is not running and OK_MCP_AUTOSTART=0 disables auto-start.`);N(e.lockDir)||st(e.lockDir,{recursive:!0});let d=j(e.lockDir,`last-spawn-error.log`),f=o(d),p,m,h=We();try{try{p=i(h.command,[...h.prefixArgs,`start`],{detached:!0,stdio:[`ignore`,`ignore`,f],cwd:e.contentDir,env:{...process.env,OK_LOCK_KIND:`mcp-spawned`}}),p.on(`error`,e=>{m=e instanceof Error?e.message:String(e)}),p.unref()}catch(e){m=e instanceof Error?e.message:String(e)}}finally{try{s(f)}catch{}}let g=Date.now()+c;for(;Date.now()<g;){if(m){let e=a(d),t=e?` stderr:\n${e}`:``;throw Error(`spawn failed: ${m}${t}`)}await r(l);let e=Co(t(),n);if(e!==void 0)return bo(`localhost`,e)}if(m){let e=a(d),t=e?` stderr:\n${e}`:``;throw Error(`spawn failed: ${m}${t}`)}throw Error(To(c,a(d)))}function Ao(e,t){if(e.portOverride!==void 0)return So(t);let n=e.readLock??(()=>Ie(e.lockDir)),r=e.isAlive??w,i=Co(n(),r);if(i!==void 0)return xo(`localhost`,i)}async function jo(e,t={}){let n=t.stderr??process.stderr,r=t.requestTimeoutMs??12e4,i=t.createStdioTransport?t.createStdioTransport(t.stdin,t.stdout):new Ki(t.stdin,t.stdout),a=t.createHttpTransport?t.createHttpTransport(new URL(e)):new go(new URL(e),{fetch:_o(r),...t.connectionId===void 0?{}:{requestInit:{headers:{[c]:t.connectionId}}}}),o=!1,s=async()=>{o||(o=!0,t.onclose?.(),await Promise.allSettled([i.close(),a.close()]))};i.onerror=e=>{n.write(`[mcp-shim] stdio error: ${e.message}\n`)},a.onerror=e=>{n.write(`[mcp-shim] HTTP transport error: ${e.message}\n`)},i.onclose=()=>{s()},a.onclose=()=>{s()};let l=Promise.resolve();i.onmessage=e=>{l=l.then(async()=>{try{await a.send(e)}catch(t){let r=Eo(e);if(r===void 0){n.write(`[mcp-shim] failed to forward stdio notification: ${t instanceof Error?t.message:String(t)}\n`);return}await i.send(Oo(r,t)).catch(e=>{n.write(`[mcp-shim] failed to write stdio error response: ${e instanceof Error?e.message:String(e)}\n`)})}}).catch(e=>{n.write(`[mcp-shim] unexpected stdio forwarding failure: ${e instanceof Error?e.message:String(e)}\n`)})},a.onmessage=e=>{let t=Do(e);t&&a.setProtocolVersion?.(t),i.send(e).catch(e=>{n.write(`[mcp-shim] failed to write stdio response: ${e instanceof Error?e.message:String(e)}\n`)})};try{await a.start(),await i.start()}catch(e){throw await s(),e}return{close:s}}async function Mo(e){let t=e.stderr??process.stderr,n=e.bridgeFn??jo,r=await ko(e),i=e.createConnectionId?.()??Tt(),a=!1,o=(e.startKeepalive??Xi)({connectionId:i,resolveWsUrl:async()=>Ao(e,r),log:e=>t.write(`[mcp-shim] keepalive: ${e}\n`)});t.write(`[mcp-shim] proxying stdio to ${r}\n`);let s;try{s=await n(r,{stderr:t,connectionId:i,onclose:()=>{a||(o.close(),process.exit(0))}})}catch(e){throw o.close(),e}let c=()=>{a=!0,o.close(),s.close().finally(()=>{process.exit(0)})};process.once(`SIGINT`,c),process.once(`SIGTERM`,c)}const No=bt(import.meta.url);function Po(e){let t=M(e);for(;;){if(fe(t))return t;let n=rt(t);if(n===t)throw Error(`No Open Knowledge project found at or above ${e}. Pass an explicit \`cwd\` argument that points inside an OK project (a directory with a \`${me}\`).`);t=n}}function Fo(e){try{let t=new URL(e);return t.protocol===`file:`?bt(t):void 0}catch{return}}async function Io(e){if(!e.getClientCapabilities()?.roots)return;let t;try{t=await e.listRoots()}catch(t){e.log?.(`listRoots fallback failed: ${t instanceof Error?t.message:String(t)}`);return}let n=t.roots??[];if(n.length!==1)return;let r=Fo(n[0].uri);return r===void 0&&e.log?.(`single root URI not usable as fs path: ${n[0].uri}`),r}async function Lo(e,t){if(e!==void 0)return Po(e);let n=await t();if(n!==void 0)return Po(n);throw Error("`cwd` is required for tool calls against the global MCP server. Pass an absolute path inside an Open Knowledge project, or have the MCP client advertise a single root.")}async function Ro(e){let t=process.stderr,n=e.spawnTimeoutMs??vo(process.env.OK_MCP_SPAWN_TIMEOUT_MS),r=e.envAutoStart??process.env.OK_MCP_AUTOSTART,i=Ue({startupCwd:e.startupCwd,startupConfig:e.startupConfig}),o=new p({name:a,version:Re},{instructions:ae({dir:`.`})});le(o);let s=Tt(),c={current:{connectionId:s,displayName:s,colorSeed:s}},l=new Map,d=e=>{if(l.has(e))return;let n=f(e),r=c.current,i=Xi({connectionId:s,displayName:r.displayName,clientName:r.clientInfo?.name??r.displayName,colorSeed:r.colorSeed,resolveWsUrl:async()=>Ao({lockDir:n,contentDir:e},``),log:n=>t.write(`[mcp] keepalive[${e}]: ${n}\n`)});l.set(e,i)},m=()=>Io({getClientCapabilities:()=>o.server.getClientCapabilities(),listRoots:()=>o.server.listRoots(),log:e=>t.write(`[mcp] ${e}\n`)}),h=e=>Lo(e,m),g=async e=>{let t;if(e===void 0){let e=await m();if(e===void 0)return;t=Po(e)}else t=Po(e);let a=await i(t),o=await ko({lockDir:f(t),contentDir:u(a,t),envAutoStart:r,...n===void 0?{}:{timeoutMs:n}});return d(t),o.replace(/\/mcp$/,``)};o.server.oninitialized=()=>{let e=o.server.getClientVersion(),t=ie(e?.name,s);c.current={connectionId:s,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}},ve(o,{serverUrl:g,resolveCwd:h,config:i,identityRef:c});let _=new Ki,v=!1,y,b=async()=>{if(v)return;v=!0,y?.stop();for(let e of l.values())try{e.close()}catch(e){t.write(`[mcp] keepalive close error: ${e instanceof Error?e.message:String(e)}\n`)}l.clear();let e=await Promise.allSettled([o.close(),_.close()]);for(let n of e)if(n.status===`rejected`){let e=n.reason;t.write(`[mcp] shutdown close error: ${e instanceof Error?e.message:String(e)}\n`)}};await o.connect(_),t.write(`[mcp] global stdio server ready (per-call project routing)
61
61
  `);let x=!1,S=()=>{x||(x=!0,setTimeout(()=>{t.write(`[mcp] shutdown deadline (5s) reached — forcing exit(1)
62
- `),process.exit(1)},5e3).unref(),b().finally(()=>{process.exit(0)}))};if(process.once(`SIGINT`,S),process.once(`SIGTERM`,S),process.platform===`darwin`){let e=Yi(No,{realpathSync:dt,statInoSync:e=>pt(e).ino,log:e=>t.write(`${e}\n`)});if(e!==void 0){t.write(`[mcp] bundle identity anchor=${e.resolvedPath} inode=${e.inode} version=${Re}\n`);let{resolvedPath:n,inode:r}=e;y=Ji({detect:()=>qi({bundleAnchorPath:No,currentInode:r,platform:process.platform,realpath:dt,statInode:e=>pt(e).ino}),onReplaced:e=>{t.write(`[mcp] bundle replaced anchor=${n} bootInode=${e.currentInode} onDiskInode=${e.onDiskInode} version=${Re} — exiting for host respawn\n`),S()},log:e=>t.write(`[mcp] ${e}\n`)})}}return{close:b}}function zo(e){return new t(`mcp`).description(`Start MCP stdio server for project knowledge base`).option(`-p, --port <port>`,`Override per-call routing and proxy stdio to this HTTP MCP port`,void 0).action(async t=>{try{let n=e(),r=process.cwd();if(t.port!==void 0){let e=vo(process.env.OK_MCP_SPAWN_TIMEOUT_MS);await Mo({lockDir:``,contentDir:``,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:e});return}await Ro({startupCwd:r,startupConfig:n})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function Bo(e){return new t(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-CJUr5n6r.mjs`),r=e(),i=process.cwd(),a=u(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 Vo(e){return e==null?!1:e.includes(`--type=utility`)&&e.includes(`--utility-sub-type=node.mojom.NodeService`)}function Ho(e,t=Date.now()){let n=new Date(e).getTime();if(Number.isNaN(n))return`—`;let r=t-n,i=Math.floor(r/1e3);if(i<60)return`${i}s`;let a=Math.floor(i/60);if(a<60)return`${a}m ago`;let o=Math.floor(a/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function Uo(e,t,n,r,i,a){if(t.status===`missing`||t.status===`corrupt`)return null;let o=t.lock,s=null;if(n.status!==`missing`&&n.status!==`corrupt`){let e=n.lock;s={port:e.port,status:n.status,pid:e.pid,startedAt:e.startedAt,usage:a}}return{directory:o.worktreeRoot,server:{port:o.port,status:t.status,pid:o.pid,startedAt:o.startedAt,usage:i},ui:s,hostname:o.hostname,lockPath:t.lockPath,binary:r==null?null:bi(r),command:r,isDesktop:Vo(r)}}function Wo(e){return e.ui==null?!1:e.ui.status===`alive`||e.ui.status===`foreign-host`}function Go(e){let t=e.server.status;return t===`alive`||t===`foreign-host`?e.isDesktop?`desktop`:t===`alive`?`running`:`foreign`:t===`dead-pid`&&Wo(e)?`ui-orphan`:`stale`}const Ko=new Set([`running`,`desktop`,`foreign`,`ui-orphan`]);function qo(e){switch(e){case`running`:return U.default.green(e);case`desktop`:return U.default.blue(e);case`foreign`:return U.default.cyan(e);case`ui-orphan`:return U.default.magenta(e);case`stale`:return U.default.yellow(e)}}function Jo(e){return e==null?`—`:`${e.cpuPercent.toFixed(1)}% / ${e.memPercent.toFixed(1)}%`}function Yo(e){return`${Jo(e.server.usage)} | ${Jo(e.ui?.usage??null)}`}function Xo(e){return`${e.server.port===0?`(starting)`:String(e.server.port)} / ${e.ui==null||e.ui.status===`dead-pid`?`—`:String(e.ui.port)}`}function Zo(e){if(e.length===0)return`No open-knowledge servers found.`;let t=[`DIRECTORY`,`PORTS (API/UI)`,`CPU/MEM (API | UI)`,`STATUS`,`PID`,`STARTED`,`BINARY`],n=e.map(e=>{let t=Go(e),n=t===`ui-orphan`&&e.ui!=null?e.ui.pid:e.server.pid;return[e.directory,Xo(e),Yo(e),t,String(n),Ho(e.server.startedAt),e.binary??`—`]}),r=t.length,i=t.map(e=>e.length);for(let e of n)for(let t=0;t<r;t++)i[t]=Math.max(i[t]??0,(e[t]??``).length);let a=t.map((e,t)=>e.padEnd(i[t]??0)).join(` `).trimEnd(),o=e.map((e,t)=>{let a=n[t]??[],o=[];for(let t=0;t<r;t++){let n=(a[t]??``).padEnd(i[t]??0);if(t===3){let r=a[t]??``;n=qo(Go(e))+` `.repeat(Math.max(0,(i[t]??0)-r.length))}o.push(n)}return o.join(` `).trimEnd()}),s=U.default.dim(`To stop a server: ok stop <port|pid|directory|all>`);return[a,...o,``,s].join(`
62
+ `),process.exit(1)},5e3).unref(),b().finally(()=>{process.exit(0)}))};if(process.once(`SIGINT`,S),process.once(`SIGTERM`,S),process.platform===`darwin`){let e=Yi(No,{realpathSync:dt,statInoSync:e=>pt(e).ino,log:e=>t.write(`${e}\n`)});if(e!==void 0){t.write(`[mcp] bundle identity anchor=${e.resolvedPath} inode=${e.inode} version=${Re}\n`);let{resolvedPath:n,inode:r}=e;y=Ji({detect:()=>qi({bundleAnchorPath:No,currentInode:r,platform:process.platform,realpath:dt,statInode:e=>pt(e).ino}),onReplaced:e=>{t.write(`[mcp] bundle replaced anchor=${n} bootInode=${e.currentInode} onDiskInode=${e.onDiskInode} version=${Re} — exiting for host respawn\n`),S()},log:e=>t.write(`[mcp] ${e}\n`)})}}return{close:b}}function zo(e){return new t(`mcp`).description(`Start MCP stdio server for project knowledge base`).option(`-p, --port <port>`,`Override per-call routing and proxy stdio to this HTTP MCP port`,void 0).action(async t=>{try{let n=e(),r=process.cwd();if(t.port!==void 0){let e=vo(process.env.OK_MCP_SPAWN_TIMEOUT_MS);await Mo({lockDir:``,contentDir:``,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:e});return}await Ro({startupCwd:r,startupConfig:n})}catch(e){process.stderr.write(`MCP server failed to start: ${e instanceof Error?e.message:String(e)}\n`),process.exitCode=1}})}function Bo(e){return new t(`preview`).description(`Show what content the watcher will track (read-only)`).action(async()=>{let{previewContent:t,formatPreviewBlock:n}=await import(`./preview-BD6NhOot.mjs`),r=e(),i=process.cwd(),a=u(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 Vo(e){return e==null?!1:e.includes(`--type=utility`)&&e.includes(`--utility-sub-type=node.mojom.NodeService`)}function Ho(e,t=Date.now()){let n=new Date(e).getTime();if(Number.isNaN(n))return`—`;let r=t-n,i=Math.floor(r/1e3);if(i<60)return`${i}s`;let a=Math.floor(i/60);if(a<60)return`${a}m ago`;let o=Math.floor(a/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function Uo(e,t,n,r,i,a){if(t.status===`missing`||t.status===`corrupt`)return null;let o=t.lock,s=null;if(n.status!==`missing`&&n.status!==`corrupt`){let e=n.lock;s={port:e.port,status:n.status,pid:e.pid,startedAt:e.startedAt,usage:a}}return{directory:o.worktreeRoot,server:{port:o.port,status:t.status,pid:o.pid,startedAt:o.startedAt,usage:i},ui:s,hostname:o.hostname,lockPath:t.lockPath,binary:r==null?null:bi(r),command:r,isDesktop:Vo(r)}}function Wo(e){return e.ui==null?!1:e.ui.status===`alive`||e.ui.status===`foreign-host`}function Go(e){let t=e.server.status;return t===`alive`||t===`foreign-host`?e.isDesktop?`desktop`:t===`alive`?`running`:`foreign`:t===`dead-pid`&&Wo(e)?`ui-orphan`:`stale`}const Ko=new Set([`running`,`desktop`,`foreign`,`ui-orphan`]);function qo(e){switch(e){case`running`:return U.default.green(e);case`desktop`:return U.default.blue(e);case`foreign`:return U.default.cyan(e);case`ui-orphan`:return U.default.magenta(e);case`stale`:return U.default.yellow(e)}}function Jo(e){return e==null?`—`:`${e.cpuPercent.toFixed(1)}% / ${e.memPercent.toFixed(1)}%`}function Yo(e){return`${Jo(e.server.usage)} | ${Jo(e.ui?.usage??null)}`}function Xo(e){return`${e.server.port===0?`(starting)`:String(e.server.port)} / ${e.ui==null||e.ui.status===`dead-pid`?`—`:String(e.ui.port)}`}function Zo(e){if(e.length===0)return`No open-knowledge servers found.`;let t=[`DIRECTORY`,`PORTS (API/UI)`,`CPU/MEM (API | UI)`,`STATUS`,`PID`,`STARTED`,`BINARY`],n=e.map(e=>{let t=Go(e),n=t===`ui-orphan`&&e.ui!=null?e.ui.pid:e.server.pid;return[e.directory,Xo(e),Yo(e),t,String(n),Ho(e.server.startedAt),e.binary??`—`]}),r=t.length,i=t.map(e=>e.length);for(let e of n)for(let t=0;t<r;t++)i[t]=Math.max(i[t]??0,(e[t]??``).length);let a=t.map((e,t)=>e.padEnd(i[t]??0)).join(` `).trimEnd(),o=e.map((e,t)=>{let a=n[t]??[],o=[];for(let t=0;t<r;t++){let n=(a[t]??``).padEnd(i[t]??0);if(t===3){let r=a[t]??``;n=qo(Go(e))+` `.repeat(Math.max(0,(i[t]??0)-r.length))}o.push(n)}return o.join(` `).trimEnd()}),s=U.default.dim(`To stop a server: ok stop <port|pid|directory|all>`);return[a,...o,``,s].join(`
63
63
  `)}async function Qo(e={}){let t=e.discover??Ti,n=e.inspect??V,r=e.log??(e=>console.log(e)),i=e.resolveCommand??xi,a=e.resolveUsage??Si,o=await t(),s=[];for(let e of o){let t=n(e,`server`),r=n(e,`ui`),o=Uo(e,t,r,t.status===`missing`||t.status===`corrupt`?null:i(t.lock.pid),t.status===`missing`||t.status===`corrupt`?null:a(t.lock.pid),r.status===`missing`||r.status===`corrupt`?null:a(r.lock.pid));o!=null&&s.push(o)}if(e.json){let e=s.map(e=>({...e,displayStatus:Go(e)}));r(JSON.stringify(e,null,2));return}r(Zo(e.all?s:s.filter(e=>Ko.has(Go(e)))))}function $o(){return new t(`ps`).description(`List all running open-knowledge servers`).argument(`[modifier]`,`"all" to include stale (dead-pid) entries`).option(`--all`,`Include stale (dead-pid) entries (foreign-host shows by default)`).option(`--json`,`Emit structured JSON (always includes all statuses)`).action(async(e,t)=>{await Qo({all:t.all===!0||e===`all`,json:t.json===!0})})}function X(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function es(e,t,n=process.cwd()){let r=e.op??`sync`,i=Ie(m(n));if(i&&i.port>0){let t=`http://127.0.0.1:${i.port}/api/sync/trigger`;e.json||process.stderr.write(`Triggering ${r} via running server (port ${i.port})\n`);try{let n=await fetch(t,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({op:r})});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.title??e.error??e.message??`Server responded with ${n.status}`)}X(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=ze({baseDir:n});if(r===`sync`||r===`pull`){X(e.json,{type:`step`,step:`pull`});let t=await a.pull();X(e.json,{type:`pull`,summary:t.summary}),e.json||process.stderr.write(` pull: ${t.summary.changes} changes\n`)}(r===`sync`||r===`push`)&&(X(e.json,{type:`step`,step:`push`}),await a.push(),X(e.json,{type:`push`,ok:!0}),e.json||process.stderr.write(` push: ok
64
64
  `)),X(e.json,{type:`complete`,op:r}),e.json||process.stderr.write(`✓ ${r} complete\n`)}function ts(e){return new t(`sync`).description(`Commit, pull, and push to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await es({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 ns(e){return new t(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await es({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 rs(e){return new t(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await es({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 is(e){return typeof e==`string`&&r.includes(e)}async function as(e={}){let t=M(e.cwd??process.cwd()),n=e.pack??`knowledge-base`;if(!_e[n])return{status:`failed`,message:`${O(`Error:`)} Unknown pack "${n}". Available: ${r.join(`, `)}`,exitCode:1};let i;try{i=await s({projectDir:t,rootDir:e.root,packId:n})}catch(e){return e instanceof b?{status:`prerequisite-missing`,message:`${O(`Error:`)} ${e.message}`,exitCode:1}:{status:`failed`,message:`${O(`Error:`)} ${e instanceof Error?e.message:String(e)}`,exitCode:1}}if(i.created.length===0){let e=_e[n].name;return{status:`no-op`,message:`${D(`Your ${e} pack is already seeded.`)}\n${E(`Nothing to do.`)}`,plan:i,exitCode:0}}if(e.dryRun)return{status:`dry-run`,message:`${k(`Plan (dry-run — no changes made):`)}\n\n${ss(i,t)}`,plan:i,exitCode:0};if(!e.yes&&!await cs(`${k(`Plan:`)}\n\n${ss(i,t)}\n\n${k(`Apply?`)} ${E(`[Y/n] `)}`,e.confirmStream))return{status:`cancelled`,message:E(`Cancelled.`),plan:i,exitCode:0};let a=await ne(i,{projectDir:t,packId:n});if(a.errors.length>0){let e=a.errors.map(e=>` ${O(`✗`)} ${e.path}: ${e.error}`);return{status:`failed`,message:[`${Ze(`Applied`)} ${a.applied} entries, ${Ze(String(a.errors.length))} error(s):`,...e].join(`
65
65
  `),plan:i,exitCode:1}}let o=_e[n].name;return{status:`applied`,message:`${D(`✓ Seeded ${o}`)} ${E(`(${a.applied} entries, ${a.durationMs}ms)`)}`,plan:i,exitCode:0}}function os(){let e=[k(`Available packs:`)];for(let t of r){let n=_e[t];e.push(` ${D(t)} ${E(`—`)} ${n.name}: ${n.description}`)}return e.join(`
@@ -0,0 +1,2 @@
1
+ import"./dist-CQVP3NVF.mjs";var e=`0.5.0-beta.44`;const t=`config.yml`,n=e;export{n,t};
2
+ //# sourceMappingURL=constants-SS3E-YX9.mjs.map