@inkeep/open-knowledge 0.6.0-beta.27 → 0.6.0-beta.29
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/THIRD_PARTY_NOTICES.md +1 -0
- package/dist/assets/skills/discovery/SKILL.md +1 -1
- package/dist/assets/skills/project/SKILL.md +47 -14
- package/dist/cli.mjs +4 -4
- package/dist/constants-Dscszaxu.mjs +2 -0
- package/dist/{dist-CabLlUBg.mjs → dist-BfPQorHm.mjs} +97 -16
- package/dist/{dist-DJIHw74T.mjs → dist-DSv1IKWQ.mjs} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{init-f7hc44jV.mjs → init-BuOingDl.mjs} +4 -4
- package/dist/init-Dy_X5Ny_.mjs +1 -0
- package/dist/{loader-BJUDFpoL.mjs → loader-CMnGoGVv.mjs} +2 -2
- package/dist/loader-OUeDnqbO.mjs +1 -0
- package/dist/{preview-CwDrnGYG.mjs → preview-ClzCw0fP.mjs} +2 -2
- package/dist/preview-D3f1d9Nx.mjs +1 -0
- package/dist/public/assets/{ActivityModeContent-DgIc2sdR.js → ActivityModeContent-f87lu1R1.js} +1 -1
- package/dist/public/assets/DocumentContext-BVFYhVUK.js +58 -0
- package/dist/public/assets/GraphPanel-0aB3TF2C.js +46 -0
- package/dist/public/assets/{SettingsDialogBody-CGtuMTew.js → SettingsDialogBody-B_UH7Jye.js} +2 -2
- package/dist/public/assets/{SourceEditor-D7VMRb2T.js → SourceEditor-C3ri5HiW.js} +1 -1
- package/dist/public/assets/{config-validation-events-r7c4lDHn.js → config-validation-events-BQa42yM4.js} +5 -5
- package/dist/public/assets/index-B1yTHJ6f.css +1 -0
- package/dist/public/assets/index-BeHs1Y8X.js +1915 -0
- package/dist/public/assets/{prop-types-CesXwSs1.js → prop-types-C7ZcPhvT.js} +199 -137
- package/dist/public/assets/{target-navigation-intent-C2Y4hErJ.js → target-navigation-intent-B_XxwO2E.js} +1 -1
- package/dist/public/assets/{toggle-group-C5-7zOwD.js → toggle-group-vVm0xmLD.js} +1 -1
- package/dist/public/assets/{typing-burst-detector-DxAhmDCN.js → typing-burst-detector-CC-taYRN.js} +1 -1
- package/dist/public/index.html +8 -8
- package/dist/{repair-launch-json-3aLQL0ng.mjs → repair-launch-json-B5T2opBx.mjs} +2 -2
- package/dist/{repair-mcp-configs-D9JauDTC.mjs → repair-mcp-configs-COcqSad9.mjs} +2 -2
- package/dist/{src-FF4OrywJ.mjs → src-7yGQ76KG.mjs} +2 -2
- package/dist/start-BgFQ9_EU.mjs +1 -0
- package/dist/{start-BkD7jnzN.mjs → start-C99xslyK.mjs} +2 -2
- package/package.json +1 -1
- package/dist/constants-BW8yygT3.mjs +0 -2
- package/dist/init-BO6mopII.mjs +0 -1
- package/dist/loader-CTvz2ve-.mjs +0 -1
- package/dist/preview-Cy2C-Bmn.mjs +0 -1
- package/dist/public/assets/DocumentContext-B8wHzXLX.js +0 -52
- package/dist/public/assets/GraphPanel-DxBhsg4w.js +0 -46
- package/dist/public/assets/index-BpdCqq0y.css +0 -1
- package/dist/public/assets/index-CrdR0rmr.js +0 -1915
- package/dist/start-NziN0vJh.mjs +0 -1
|
@@ -6297,6 +6297,7 @@ The following MIT-licensed packages are patched in this repository via Bun's `pa
|
|
|
6297
6297
|
| Package | Patch file |
|
|
6298
6298
|
| --- | --- |
|
|
6299
6299
|
| `@handlewithcare/remark-prosemirror@0.1.5` | `patches/@handlewithcare%2Fremark-prosemirror@0.1.5.patch` |
|
|
6300
|
+
| `@pierre/trees@1.0.0-beta.3` | `patches/@pierre%2Ftrees@1.0.0-beta.3.patch` |
|
|
6300
6301
|
| `@tiptap/extension-drag-handle@3.22.3` | `patches/@tiptap%2Fextension-drag-handle@3.22.3.patch` |
|
|
6301
6302
|
| `@tiptap/y-tiptap@3.0.3` | `patches/@tiptap%2Fy-tiptap@3.0.3.patch` |
|
|
6302
6303
|
| `react-medium-image-zoom@5.4.3` | `patches/react-medium-image-zoom@5.4.3.patch` |
|
|
@@ -3,7 +3,7 @@ name: open-knowledge-discovery
|
|
|
3
3
|
description: "Read when the user asks what Open Knowledge is, wants to install it on a repository, wants to share an Open Knowledge project with collaborators, or asks how `ok init` / `ok install-skill` / OK Desktop set up a project. Do NOT load to perform Open Knowledge reads/writes — the runtime guidance for editing markdown inside an initialized OK project ships as a separate project-local skill at `.claude/skills/open-knowledge/` whenever `ok init` runs. If the user appears to be editing markdown inside a `.ok/` project and this is the only OK skill loaded, advise them to re-run `ok init` to install the project-local skill."
|
|
4
4
|
compatibility: "Any agent host — no MCP server required. Pure discovery + install guidance."
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.6.0-beta.
|
|
6
|
+
version: "0.6.0-beta.29"
|
|
7
7
|
author: "Inkeep"
|
|
8
8
|
repository: "https://github.com/inkeep/open-knowledge"
|
|
9
9
|
---
|
|
@@ -3,7 +3,7 @@ name: open-knowledge
|
|
|
3
3
|
description: "MUST invoke before reading or editing any `.md` / `.mdx` file, and before any `mcp__open-knowledge__*` tool call (`exec`, `search`, `write_document`, `edit_document`, and the rest). This skill is installed into the repository by `ok init`, so its presence alone means this is an Open Knowledge project — its runtime contract governs every markdown file here, with no need to probe for a `.ok/` directory. Authoritative agent-runtime contract; supersedes the overlapping MCP server `instructions` echo."
|
|
4
4
|
compatibility: "Claude Code, Claude Desktop, Claude Cowork, Claude.ai web. Requires Open Knowledge MCP server + code execution."
|
|
5
5
|
metadata:
|
|
6
|
-
version: "0.6.0-beta.
|
|
6
|
+
version: "0.6.0-beta.29"
|
|
7
7
|
author: "Inkeep"
|
|
8
8
|
repository: "https://github.com/inkeep/open-knowledge"
|
|
9
9
|
---
|
|
@@ -24,11 +24,11 @@ Open Knowledge (OK) is a markdown-CRDT collaboration platform exposed via MCP. T
|
|
|
24
24
|
|
|
25
25
|
Everything below is depth. Read on demand.
|
|
26
26
|
|
|
27
|
-
## Tool index —
|
|
27
|
+
## Tool index — 22 tools
|
|
28
28
|
|
|
29
29
|
The full MCP surface, grouped by risk-level. Every tool's `kind` / `action` set is single-risk-level (never a read and a write behind one discriminator).
|
|
30
30
|
|
|
31
|
-
- **Reads** — `exec` (primary; shell-style `cat`/`ls`/`grep`/`find` with frontmatter + backlink + history enrichment), `search` (ranked, BM25 + recency), `get_history` (versions for a doc), `links` (`kind: 'backlinks'|'forward'|'dead'|'orphans'|'hubs'|'suggest'`), `get_config` (resolved config), `get_components` (canonical component schemas), `get_preview_url` (browser-reachable preview URL on demand).
|
|
31
|
+
- **Reads** — `exec` (primary; shell-style `cat`/`ls`/`grep`/`find` with frontmatter + backlink + history enrichment), `search` (ranked, BM25 + recency), `get_history` (versions for a doc), `links` (`kind: 'backlinks'|'forward'|'dead'|'orphans'|'hubs'|'suggest'`), `get_config` (resolved config), `get_components` (canonical component JSX schemas), `get_authoring_palette` (markdown-native authoring forms + themed `html preview` embed starters + theme tokens), `get_preview_url` (browser-reachable preview URL on demand).
|
|
32
32
|
- **Writes** — `write_document` (new or full-replace; supports `template:` instantiation), `edit_document` (body-only find/replace), `edit_frontmatter` (1-2 keys via RFC 7396 JSON Merge Patch — preferred), `delete_document`, `rename` (probes file vs folder; rewrites referrers), `version` (`action: 'save'|'rollback'`), `folder_config` (`action: 'set-rule'|'write-template'|'delete-template'`).
|
|
33
33
|
- **GitHub-sync conflicts** — `list_conflicts` (enumerate), `get_conflict_content` (base/ours/theirs stages + lifecycle), `resolve_conflict` (write a chosen resolution + commit; destructive). Mutating writes against a doc in conflict return RFC 9457 `urn:ok:error:doc-in-conflict` (409); `exec("cat …")` returns `lifecycle: {status, reason} | null` so you can detect the state proactively. See *Conflict-aware writes*.
|
|
34
34
|
- **Workflow** — `ingest`, `research`, `consolidate`, `discover` (return procedural guides, not data).
|
|
@@ -132,22 +132,55 @@ The gate covers `write_document`, `edit_document`, `delete_document`, `rename`,
|
|
|
132
132
|
|
|
133
133
|
The resolve operation is best-effort and NOT atomic: `git checkout --ours/--theirs && git add` may succeed but the subsequent `git commit --no-edit` can fail (pre-commit hook rejection, locked index). On commit failure the staged files are re-`git add`-ed back into the unmerged index and the tracked entry remains in `conflicts.json` — re-call `resolve_conflict` after the user clears the blocker.
|
|
134
134
|
|
|
135
|
-
## Components —
|
|
135
|
+
## Components — write the markdown-native form, not JSX
|
|
136
136
|
|
|
137
|
-
OK
|
|
137
|
+
OK auto-promotes markdown-native syntax into themed canonical components at parse time. **Write the markdown-native form — don't reach for JSX when one exists.** The promoted component is themed, accessible, and part of the content graph; hand-rolled JSX is none of those, and it fights the model's markdown prior instead of using it.
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
| Want | Write this (markdown-native) | Promotes to |
|
|
140
|
+
| --- | --- | --- |
|
|
141
|
+
| Callout / admonition | `> [!NOTE]` + body — 15 types (NOTE, TIP, IMPORTANT, WARNING, CAUTION, …); append `+` / `-` (`> [!NOTE]+`) to make it foldable | themed Callout |
|
|
142
|
+
| Collapsible section | `<details><summary>Title</summary>` … `</details>` | themed Accordion |
|
|
143
|
+
| Diagram | a ` ```mermaid ` fenced block (flowchart, sequence, class, state, ER, gantt, pie) | Mermaid diagram |
|
|
144
|
+
| Math | `$x$` inline, `$$…$$` block | KaTeX Math |
|
|
145
|
+
| Inline a doc or asset | `![[file]]` | wiki embed |
|
|
142
146
|
|
|
143
|
-
**
|
|
144
|
-
- ` ```mermaid ` — Mermaid diagram (flowchart, sequence, class, state, ER, gantt, pie).
|
|
145
|
-
- ` ```html preview ` (also `htm preview` / `xml preview`) — live iframe preview. Author a standalone HTML/JS/CSS page in the fence; it executes inside the editor. Use this for anything interactive (charts via Chart.js / D3, calculators, animations, demos). Optional `h=<value>` / `w=<value>` fence-meta tokens set iframe size.
|
|
146
|
-
- ` ```<lang> ` (other languages) — syntax-highlighted code block, no preview.
|
|
147
|
+
`Tabs` is the lone canonical with **no** markdown-native form — write the JSX directly (`<Tabs><Tab label="…">…</Tab></Tabs>`). For any canonical's full JSX prop schema, call `get_components({ ids })`. If no canonical fits, any `<TagName>…</TagName>` falls through as raw MDX — but prefer a canonical when one matches.
|
|
147
148
|
|
|
148
|
-
**
|
|
149
|
+
**Discover the palette in one call.** `get_authoring_palette` returns every markdown-native form (copy-ready `example` + `guidance`), the themed `html preview` embed starters, and the injected theme-token list — the source of truth for component-forward, themed authoring. Canonical names/counts beyond the markdown-native set are project-specific; the inventory in the `write_document` / `edit_document` descriptions and `get_components` are authoritative for those.
|
|
149
150
|
|
|
150
|
-
**
|
|
151
|
+
**Show findings, don't just tell them.** When a point is quantitative or comparative — a trend over time, a breakdown, a before/after, a ranking, a distribution — present it visually: a chart or stat-card `html preview` embed, a ` ```mermaid ` diagram, a table, or a Callout for the headline takeaway. Prose-only buries the insight. This matters most where the document's job is to make findings legible — **`research` reports and `consolidate` articles especially**, and any write-up meant to present results. A research article with three dense paragraphs of numbers should have been a chart. Reach for `get_authoring_palette` as you draft, not after.
|
|
152
|
+
|
|
153
|
+
### `html preview` — themed interactive embeds
|
|
154
|
+
|
|
155
|
+
A ` ```html preview ` fence (also `htm` / `xml`) renders a standalone HTML/CSS/JS page as a live sandboxed iframe — the extend-to-anything primitive for charts, stat cards, custom SVG, calculators, demos. The iframe auto-sizes to its content; pass `h=` / `w=` (e.g. ` ```html preview h=400px `) only to pin a fixed size.
|
|
156
|
+
|
|
157
|
+
**Start from a starter — don't hand-roll.** `get_authoring_palette` returns `embedPatterns` (chart, stat cards, custom SVG, interactive control), each already wired to the theme tokens. Copy one and fill in your data — that is the only path that cannot render unthemed. Hand-author a fence from scratch only when no starter is close.
|
|
158
|
+
|
|
159
|
+
**MUST — never hardcode colors in an `html preview` embed.** OK injects its theme tokens into every preview iframe; an embed that hardcodes hex / `rgb()` renders unthemed — a white box on a dark page, clashing with every component around it. This is the single most common embed mistake. Wire every color to a token: `var(--chart-1..5)` for chart series, `var(--foreground)` / `var(--muted-foreground)` for text, `var(--card)` / `var(--background)` for surfaces, plus `var(--border)`, `var(--primary)`, `var(--radius)`. Don't set a `body` background at all unless you specifically mean to — the iframe already carries a themed one.
|
|
160
|
+
|
|
161
|
+
````
|
|
162
|
+
```html preview
|
|
163
|
+
<div style="font-family:system-ui;padding:20px;color:var(--foreground)">
|
|
164
|
+
<h3 style="margin:0 0 10px">Themed embed</h3>
|
|
165
|
+
<div style="display:flex;gap:8px">
|
|
166
|
+
<div style="flex:1;height:48px;background:var(--chart-1);border-radius:var(--radius)"></div>
|
|
167
|
+
<div style="flex:1;height:48px;background:var(--chart-2);border-radius:var(--radius)"></div>
|
|
168
|
+
<div style="flex:1;height:48px;background:var(--chart-3);border-radius:var(--radius)"></div>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
```
|
|
172
|
+
````
|
|
173
|
+
|
|
174
|
+
Done wrong, that same embed is `body{background:#fff;color:#1a1a1a}` with a `background:#2563eb` bar — a white box with a hardcoded blue, blind to the reader's theme.
|
|
175
|
+
|
|
176
|
+
**Charts.** A pure-CSS or inline-SVG chart wired to `var(--chart-*)` re-skins on a theme toggle for free — prefer it. A JS charting library (Chart.js, D3) works too, but a themed `body` does NOT theme the colors you pass the library in JS — read the token at runtime instead of hardcoding:
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
const c1 = getComputedStyle(document.documentElement).getPropertyValue('--chart-1').trim();
|
|
180
|
+
// → pass c1 to Chart.js / D3 as the series color
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Boundary.** Reach for a canonical (via its markdown-native form) when one matches the semantic need — it is themed and integrated. Reach for ` ```html preview ` for interactive or bespoke content no canonical covers. ` ```<lang> ` fences for other languages are plain syntax-highlighted code, no preview.
|
|
151
184
|
|
|
152
185
|
## Grounding — every factual claim needs a source (MUST)
|
|
153
186
|
|
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,E as s,Ei as c,En as l,Gr as u,Hr as d,Kr as f,Mi as p,Ni as m,Oi as h,Rn as ee,Si as te,Ti as g,U as ne,Ur as _,Wn as v,Wr as y,Wt as re,Xr as ie,Yr as b,Z as ae,cr as oe,fn as se,hi as ce,it as le,ji as ue,ki as x,m as de,nt as fe,pi as pe,qn as me,qr as he,tn as ge,wi as S,xi as _e,yi as ve,z as ye}from"./dist-
|
|
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,E as s,Ei as c,En as l,Gr as u,Hr as d,Kr as f,Mi as p,Ni as m,Oi as h,Rn as ee,Si as te,Ti as g,U as ne,Ur as _,Wn as v,Wr as y,Wt as re,Xr as ie,Yr as b,Z as ae,cr as oe,fn as se,hi as ce,it as le,ji as ue,ki as x,m as de,nt as fe,pi as pe,qn as me,qr as he,tn as ge,wi as S,xi as _e,yi as ve,z as ye}from"./dist-BfPQorHm.mjs";import{n as be,r as xe,t as C}from"./dist-bundle-BSdjl7Rj.mjs";import{A as Se,C as Ce,D as we,E as Te,O as Ee,S as De,T as Oe,b as ke,j as Ae,k as je,o as Me,p as Ne,w as Pe,x as Fe}from"./init-BuOingDl.mjs";import{c as Ie,f as Le,l as Re,n as ze,s as w}from"./server-lock-BniQ3qki-CadPGoZN.mjs";import{i as Be}from"./git-handle-CjyGVy33-CK0dYQ8y.mjs";import{n as Ve}from"./constants-Dscszaxu.mjs";import{i as He}from"./src-7yGQ76KG.mjs";import{n as Ue,t as We}from"./loader-CMnGoGVv.mjs";import{d as Ge,f as Ke,l as qe,m as Je,p as Ye,s as Xe}from"./start-C99xslyK.mjs";import{c as Ze,i as T,n as E,o as D,r as O,s as Qe,t as k}from"./colors-BtKMHmBX.mjs";import{execFileSync as $e,execSync as et,spawn as tt,spawnSync as A}from"node:child_process";import nt,{basename as rt,dirname as it,isAbsolute as at,join as j,relative as ot,resolve as M}from"node:path";import{closeSync as st,existsSync as N,lstatSync as ct,mkdirSync as lt,mkdtempSync as ut,openSync as dt,readFileSync as P,readdirSync as ft,realpathSync as pt,rmSync as mt,statSync as ht,unlinkSync as gt,writeFileSync as _t}from"node:fs";import vt from"node:process";import{homedir as yt,hostname as bt,tmpdir as xt}from"node:os";import{fileURLToPath as St}from"node:url";import{AsyncLocalStorage as Ct,AsyncResource as wt}from"node:async_hooks";import{stripVTControlCharacters as Tt,styleText as F}from"node:util";import*as Et from"node:readline";import{randomUUID as Dt}from"node:crypto";import{realpath as Ot}from"node:fs/promises";import{setTimeout as kt}from"node:timers/promises";import{createInterface as At}from"node:readline/promises";var jt=m();const Mt=`open-knowledge`;var Nt=class{backend=`keyring`;async get(e){let{Entry:t}=await import(`@napi-rs/keyring`);try{let n=new t(Mt,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(Mt,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(Mt,e).deletePassword()}catch{}}},Pt=class{backend=`file`;authFile;constructor(e){this.authFile=e??j(yt(),`.ok`,`auth.yml`)}read(){if(!N(this.authFile))return{};try{return(0,jt.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=it(this.authFile);N(t)||lt(t,{recursive:!0,mode:448}),_t(this.authFile,(0,jt.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 Ft(e){try{let{Entry:e}=await import(`@napi-rs/keyring`);return new e(Mt,`__probe__`),process.stderr.write(`[auth] token storage: OS keychain
|
|
3
3
|
`),new Nt}catch{return process.stderr.write(`[auth] token storage: file (~/.ok/auth.yml)
|
|
4
4
|
`),new Pt(e)}}async function It(e,t){let n=[],r=new Pt(t);await r.get(e)!=null&&(await r.clear(e),n.push(`file`));try{let{Entry:t}=await import(`@napi-rs/keyring`);new t(Mt,`__probe__`);let r=new Nt;await r.get(e)!=null&&(await r.clear(e),n.push(`keychain`))}catch{}return{touched:n}}async function Lt(e,t,n){let r=Rt(await zt(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 Rt(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 zt(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 Bt(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 Lt(process.stdin,process.stdout,t);process.exit(n)}),n}function Vt(e){let t=e.endpoint.DEFAULTS;return/^https:\/\/(api\.)?github\.com$/.test(t.baseUrl)?`https://github.com`:t.baseUrl.replace(`/api/v3`,``)}async function Ht(e,t,n){let r={baseUrl:Vt(e),headers:{accept:`application/json`},...n},i=await e(t,r);if(`error`in i.data){let n=new be(`${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 Ut(e){let t=e.request||C,n={client_id:e.clientId};return`scopes`in e&&Array.isArray(e.scopes)&&(n.scope=e.scopes.join(` `)),Ht(t,`POST /login/device/code`,n)}async function Wt(e){let t=await Ht(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=Gt(e,t.data.expires_in),n.refreshTokenExpiresAt=Gt(e,t.data.refresh_token_expires_in)}delete n.scopes}return{...t,authentication:n}}function Gt(e,t){return new Date(e+t*1e3).toISOString()}async function Kt(e,t){let n=qt(e,t.auth);if(n)return n;let{data:r}=await Ut({clientType:e.clientType,clientId:e.clientId,request:t.request||e.request,scopes:t.auth.scopes||e.scopes});await e.onVerification(r);let i=await Yt(t.request||e.request,e.clientId,e.clientType,r);return e.authentication=i,i}function qt(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 Jt(e){await new Promise(t=>setTimeout(t,e*1e3))}async function Yt(e,t,n,r){try{let i={clientId:t,request:e,code:r.device_code},{authentication:a}=n===`oauth-app`?await Wt({...i,clientType:`oauth-app`}):await Wt({...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 Jt(r.interval),Yt(e,t,n,r);if(a===`slow_down`)return await Jt(r.interval+7),Yt(e,t,n,r);throw i}}async function Xt(e,t){return Kt(e,{auth:t})}async function Zt(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 Kt(e,{request:t,auth:{type:`oauth`}});return i.headers.authorization=`token ${a}`,t(i)}var Qt=`0.0.0-development`;function $t(e){let t=e.request||C.defaults({headers:{"user-agent":`octokit-auth-oauth-device.js/${Qt} ${xe()}`}}),{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(Xt.bind(null,i),{hook:Zt.bind(null,i)})}async function en(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=$t({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 tn={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 nn;(function(e){})(nn||={});function rn(e){return ue(_e,e)}function an(){return process.env.OPEN_KNOWLEDGE_GITHUB_CLIENT_ID??`Ov23liqlSd0V1MwR6rhI`}const on=new Set([`gitlab.com`,`bitbucket.org`,`codeberg.org`,`gitea.com`,`sr.ht`,`sourcehut.org`]);function I(e){let t=e.toLowerCase().replace(/:\d+$/,``);on.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 sn(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function cn(e,t,n=en){let r=an(),{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?sn(!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?sn(!0,{type:`complete`,host:i,login:s}):process.stderr.write(`✓ Logged in as ${s} on ${i}\n`)}function ln(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 cn(t,await e())})}const un=e=>e.name===`enter`||e.name===`return`;var dn=class extends Error{name=`AbortPromptError`;message=`Prompt was aborted`;constructor(e){super(),this.cause=e?.cause}},fn=class extends Error{name=`CancelPromptError`;message=`Prompt was canceled`},pn=class extends Error{name=`ExitPromptError`},mn=class extends Error{name=`HookError`},hn=class extends Error{name=`ValidationError`};const gn=new Ct;function _n(e){return{rl:e,hooks:[],hooksCleanup:[],hooksEffect:[],index:0,handleChange(){}}}function vn(e,t){let n=_n(e);return gn.run(n,()=>{function e(e){n.handleChange=()=>{n.index=0,e()},n.handleChange()}return t(e)})}function L(){let e=gn.getStore();if(!e)throw new mn(`[Inquirer] Hook functions can only be called from within a prompt`);return e}function yn(){return L().rl}function bn(e){return wt.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 xn(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 Sn(){L().handleChange()}const Cn={queue(e){let t=L(),{index:n}=t;t.hooksEffect.push(()=>{t.hooksCleanup[n]?.();let r=e(yn());if(r!=null&&typeof r!=`function`)throw new hn(`useEffect return value must be a cleanup function or nothing.`);t.hooksCleanup[n]=r})},run(){let e=L();bn(()=>{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 wn(e){return typeof e==`function`}function R(e){return xn(t=>{let n=wt.bind(function(e){t.get()!==e&&(t.set(e),Sn())});if(t.initialized)return[t.get(),n];let r=wn(e)?e():e;return t.set(r),[r,n]})}function Tn(e,t){xn(n=>{let r=n.get();(!Array.isArray(r)||t.some((e,t)=>!Object.is(e,r[t])))&&Cn.queue(e),n.set(t)})}const En={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 Dn(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 On(...e){let t={};for(let n of e)for(let[e,r]of Object.entries(n)){let n=t[e];t[e]=Dn(n)&&Dn(r)?On(n,r):r}return t}function kn(...e){return On(En,...e.filter(e=>e!=null))}function An({status:e=`idle`,theme:t}){let[n,r]=R(!1),[i,a]=R(0),{prefix:o,spinner:s}=kn(t);return Tn(()=>{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 jn(e){return R({current:e})[0]}function Mn(e){let t=jn(e);t.current=e,Tn(e=>{let n=!1,r=bn((r,i)=>{n||t.current(i,e)});return e.input.on(`keypress`,r),()=>{n=!0,e.input.removeListener(`keypress`,r)}},[])}var Nn=e(Se(),1);function Pn(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 qr(){return new t(`signout`).description(`Remove stored credentials`).option(`--host <host>`,`GitHub hostname`,`github.com`).action(async e=>{await Kr(e)})}async function Jr(e,t,n=Hr){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 Yr(e,t){let{host:n,json:r}=e;I(n);let i=await Jr(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 Xr(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 Yr(t,await e())})}function Zr(){let e=new t(`auth`);e.description(`GitHub authentication management`);let n=()=>Ft();return e.addCommand(ln(n)),e.addCommand(Xr(n)),e.addCommand(Gr(n)),e.addCommand(qr()),e.addCommand(Br(n)),e.addCommand(Bt(n)),e}function V(e,t,n={}){let r=Re(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`||!Ie(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??bt();return a.hostname===o?{status:`alive`,lockPath:r,lock:a}:{status:`foreign-host`,lockPath:r,lock:a}}function Qr(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 $r(e){let t=e.inspect??(t=>V(e.lockDir,t)),n=e.unlink??(e=>gt(e)),r=e.log??(e=>console.log(e)),i=e.error??(e=>console.error(e)),a=Qr(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 ei(e){return new t(`clean`).description(`Prune stale / corrupt open-knowledge lock files (never touches live locks)`).action(()=>{e(),$r({lockDir:me(process.cwd())}).failed.length>0&&(process.exitCode=1)})}async function ti(e,t,n={},r=Hr){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 ni(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 ri=[[`count`,0,10],[`compress`,10,20],[`receiv`,20,60],[`resolv`,60,100]];function ii(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 ri)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 ai(e){return typeof e!=`string`||e.length===0?[`--progress`]:[`--progress`,`-b`,e]}const oi=ce;async function si(e){try{return await e.clone(ai(e.branch)),{fellBack:!1}}catch(t){if(e.branch!==null&&oi(t))return e.onFallback(e.branch),await e.clone(ai(null)),{fellBack:!0};throw t}}function ci(e,t,n){return e===`https`&&t===`github.com`&&n}async function li(e,t,n,r=process.cwd()){let i=He(e);if(!i)throw Error(`Invalid git URL: ${e}`);let a=t.dir?M(r,t.dir):M(r,i.name);if(N(a)&&ft(a).length>0)throw Error(`Target directory is not empty: ${a}`);let o=await Ft(),s=i.protocol===`https`&&i.hostname===`github.com`?await ni(i.owner,i.name):!1,c=ci(i.protocol,i.hostname,s)?{tier:`none`,credentialArgs:[]}:await ti(i.hostname,o,{}),l=Be({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=ii(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 si({branch:typeof t.branch==`string`&&t.branch.length>0?t.branch:null,clone:t=>l.clone(e,a,t),onFallback:e=>{H(t.json,{type:`branch-fallback`,branch:e}),t.json||process.stderr.write(`\n Branch '${e}' not found upstream — cloning default branch instead.\n`)}}),t.json||process.stderr.write(`
|
|
22
|
-
`);try{let{runInit:e}=await import(`./init-
|
|
22
|
+
`);try{let{runInit:e}=await import(`./init-Dy_X5Ny_.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{ui(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 ui(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`:(_t(t,`${n}${n.length===0||n.endsWith(`
|
|
24
24
|
`)?``:`
|
|
25
|
-
`}.ok/\n`,`utf-8`),`appended`)}function di(e){return new t(`clone`).description(`Clone a git repository and open it`).argument(`<url>`,`Repository URL or owner/repo shorthand`).argument(`[dir]`,`Target directory (default: ./<repo-name>)`).option(`--json`,`Output JSONL progress events`,!1).option(`-b, --branch <branch>`,`Branch to check out (falls back to default if missing)`).action(async(t,n,r)=>{let i=e();try{let a=await li(t,{json:r.json,dir:n,branch:r.branch??null},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-
|
|
25
|
+
`}.ok/\n`,`utf-8`),`appended`)}function di(e){return new t(`clone`).description(`Clone a git repository and open it`).argument(`<url>`,`Repository URL or owner/repo shorthand`).argument(`[dir]`,`Target directory (default: ./<repo-name>)`).option(`--json`,`Output JSONL progress events`,!1).option(`-b, --branch <branch>`,`Branch to check out (falls back to default if missing)`).action(async(t,n,r)=>{let i=e();try{let a=await li(t,{json:r.json,dir:n,branch:r.branch??null},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-BgFQ9_EU.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 fi=[[`sync`],[`persistence`,`debounceMs`],[`persistence`,`maxDebounceMs`],[`server`,`port`],[`content`,`include`],[`content`,`exclude`]];function pi(e={}){let t=e.log??(e=>console.error(e)),n=e.error??(e=>console.error(e)),r=e.loadConfigFn??Ue;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 mi(e){let t=(0,jt.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 fi)t.hasIn(e)&&n.push(e.join(`.`));return n}function hi(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function gi(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=hi(i)?i:{};e[r]=a,e=a}e[n[n.length-1]]=null}return t}async function _i(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??ie,s=[];(r===`project`||r===`both`)&&s.push({scope:`project`,absPath:b(`project`,a,e.homedirOverride)}),(r===`user`||r===`both`)&&s.push({scope:`user`,absPath:b(`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=mi(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:gi(fi.filter(e=>r.includes(e.join(`.`)))),homedirOverride:e.homedirOverride});if(!s.ok){c.push({path:n,scope:t,found:r,removed:[],error:pe(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 vi(){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(()=>{pi({}).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 _i({scope:t,dryRun:e.dryRun})).ok||(process.exitCode=1)}),e}var U=e(Ze(),1);const W=2e3,yi=2e3,bi=[/cli\.mjs/,/(^|[\s/])(open-knowledge|ok)\s+(start|mcp|ui)(\s|$)/,/Open Knowledge(?:\.app| Helper)/,/(^|[\s/])bun([\s/]).*?(run dev|packages\/app|vite|hocuspocus)/,/(^|[\s/])node([\s/]).*?(packages\/(cli|app)|vite|hocuspocus)/,/(^|\s)--ok-lock-dir-b64=/,/(^|\s)--ok-project-path=/];function xi(e){return bi.some(t=>t.test(e))}function Si(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 at(e)?e:null}catch{return null}}function Ci(e){let t=e.indexOf(`--ok-project-path=`);if(t===-1)return null;let n=t+18,r=e.slice(n),i=r.search(/\s--/),a=(i===-1?r:r.slice(0,i)).trim();return a&&at(a)?a:null}function wi(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)&&xi(a)&&t.push({pid:o,command:a})}return t}function Ti(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)&&xi(o)&&t.push({pid:s,command:o})}return t}async function Ei(){let e=A(`pgrep`,[`-a`,`-f`,`cli\\.mjs|open-knowledge|Open Knowledge(\\.app| Helper)|--ok-lock-dir-b64=|--ok-project-path=|(^|[ /])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=wi(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?[]:Ti(t.stdout)}function Di(e){let t=e.trim().split(/\s+/).filter(Boolean);for(let e of t){if(e.startsWith(`@`))continue;let t=rt(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 Oi(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 ki(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 Ai(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 ji(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 To=class extends TransformStream{constructor({onError:e,onRetry:t,onComment:n}={}){let r;super({start(i){r=Co({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 Eo={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}},Do=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=la(t?.fetch,t?.requestInit),this._sessionId=t?.sessionId,this._reconnectionOptions=t?.reconnectionOptions??Eo}async _authThenStart(){if(!this._authProvider)throw new J(`No auth provider`);let e;try{e=await $a(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=ca(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 To({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=_.parse(JSON.parse(e.data));he(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 $a(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:f(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}=ro(o);if(this._resourceMetadataUrl=t,this._scope=n,await $a(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}=ro(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 $a(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(),u(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=>_.parse(e)):[_.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 Oo(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 ko(e){if(e===void 0||e===``)return;let t=Number.parseInt(e,10);if(!(Number.isNaN(t)||t<=0))return t}function Ao(e){return e===`0.0.0.0`||e===`::`?`localhost`:e.includes(`:`)&&!e.startsWith(`[`)?`[${e}]`:e}function jo(e,t){return`http://${Ao(e)}:${t}/mcp`}function Mo(e,t){return`ws://${Ao(e)}:${t}`}function No(e){let t=new URL(e);return t.protocol=t.protocol===`https:`?`wss:`:`ws:`,t.pathname=``,t.search=``,t.hash=``,t.toString().replace(/\/$/,``)}function Po(e,t){if(!(!e||e.port<=0)&&t(e.pid))return e.port}function Fo(e){return N(e)?P(e,`utf-8`).trim():``}function Io(e,t){return`server did not start within ${e}ms${t?` stderr:\n${t}`:``}`}function Lo(e){if(e&&typeof e==`object`&&`method`in e&&`id`in e)return e.id}function Ro(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 zo(e,t){return{jsonrpc:`2.0`,id:e,error:{code:-32e3,message:t instanceof Error?t.message:String(t)}}}async function Bo(e){let t=e.readLock??(()=>Le(e.lockDir)),n=e.isAlive??w,r=e.sleep??(e=>kt(e)),i=e.spawn??tt,a=e.readErrorLog??Fo,o=e.openErrorLog??(e=>dt(e,`w`)),s=e.closeFd??st,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 jo(`localhost`,t)}let u=Po(t(),n);if(u!==void 0)return jo(`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)||lt(e.lockDir,{recursive:!0});let d=j(e.lockDir,`last-spawn-error.log`),f=o(d),p,m,h=Ge();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 ee=Date.now()+c;for(;Date.now()<ee;){if(m){let e=a(d),t=e?` stderr:\n${e}`:``;throw Error(`spawn failed: ${m}${t}`)}await r(l);let e=Po(t(),n);if(e!==void 0)return jo(`localhost`,e)}if(m){let e=a(d),t=e?` stderr:\n${e}`:``;throw Error(`spawn failed: ${m}${t}`)}throw Error(Io(c,a(d)))}function Vo(e,t){if(e.portOverride!==void 0)return No(t);let n=e.readLock??(()=>Le(e.lockDir)),r=e.isAlive??w,i=Po(n(),r);if(i!==void 0)return Mo(`localhost`,i)}async function Ho(e,t={}){let n=t.stderr??process.stderr,r=t.requestTimeoutMs??12e4,i=t.createStdioTransport?t.createStdioTransport(t.stdin,t.stdout):new na(t.stdin,t.stdout),a=t.createHttpTransport?t.createHttpTransport(new URL(e)):new Do(new URL(e),{fetch:Oo(r),...t.connectionId===void 0?{}:{requestInit:{headers:{[s]:t.connectionId}}}}),o=!1,c=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=()=>{c()},a.onclose=()=>{c()};let l=Promise.resolve();i.onmessage=e=>{l=l.then(async()=>{try{await a.send(e)}catch(t){let r=Lo(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(zo(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=Ro(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 c(),e}return{close:c}}async function Uo(e){let t=e.stderr??process.stderr,n=e.bridgeFn??Ho,r=await Bo(e),i=e.createConnectionId?.()??Dt(),a=!1,o=(e.startKeepalive??oa)({connectionId:i,resolveWsUrl:async()=>Vo(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 Wo=St(import.meta.url);function Go(e){let t=M(e);for(;;){if(se(t))return t;let n=it(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 \`${ve}\`).`);t=n}}function Ko(e){try{let t=new URL(e);return t.protocol===`file:`?St(t):void 0}catch{return}}async function qo(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=Ko(n[0].uri);return r===void 0&&e.log?.(`single root URI not usable as fs path: ${n[0].uri}`),r}async function Jo(e,t){if(e!==void 0)return Go(e);let n=await t();if(n!==void 0)return Go(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 Yo(e){let t=process.stderr,n=e.spawnTimeoutMs??ko(process.env.OK_MCP_SPAWN_TIMEOUT_MS),r=e.envAutoStart??process.env.OK_MCP_AUTOSTART,i=We({startupCwd:e.startupCwd,startupConfig:e.startupConfig}),o=new d({name:a,version:ze},{instructions:le({dir:`.`})});ge(o);let s=Dt(),c={current:{connectionId:s,displayName:s,colorSeed:s}},l=new Map,u=e=>{if(l.has(e))return;let n=re(e),r=c.current,i=oa({connectionId:s,displayName:r.displayName,clientName:r.clientInfo?.name??r.displayName,colorSeed:r.colorSeed,resolveWsUrl:async()=>Vo({lockDir:n,contentDir:e},``),log:n=>t.write(`[mcp] keepalive[${e}]: ${n}\n`)});l.set(e,i)},f=()=>qo({getClientCapabilities:()=>o.server.getClientCapabilities(),listRoots:()=>o.server.listRoots(),log:e=>t.write(`[mcp] ${e}\n`)}),p=e=>Jo(e,f),m=async e=>{let t;if(e===void 0){let e=await f();if(e===void 0)return;t=Go(e)}else t=Go(e);let a=await i(t),o=await Bo({lockDir:re(t),contentDir:v(a,t),envAutoStart:r,...n===void 0?{}:{timeoutMs:n}});return u(t),o.replace(/\/mcp$/,``)};o.server.oninitialized=()=>{let e=o.server.getClientVersion(),t=oe(e?.name,s);c.current={connectionId:s,clientInfo:e?{name:t,version:e.version}:void 0,displayName:t,colorSeed:t}},ee(o,{serverUrl:m,resolveCwd:p,config:i,identityRef:c});let h=new na,te=!1,g,ne=async()=>{if(te)return;te=!0,g?.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(),h.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(h),t.write(`[mcp] global stdio server ready (per-call project routing)
|
|
61
61
|
`);let _=!1,y=()=>{_||(_=!0,setTimeout(()=>{t.write(`[mcp] shutdown deadline (5s) reached — forcing exit(1)
|
|
62
|
-
`),process.exit(1)},5e3).unref(),ne().finally(()=>{process.exit(0)}))};if(process.once(`SIGINT`,y),process.once(`SIGTERM`,y),sa({log:e=>t.write(`${e}\n`),transport:h,process,stdin:process.stdin}),process.platform===`darwin`){let e=aa(Wo,{realpathSync:pt,statInoSync:e=>ht(e).ino,log:e=>t.write(`${e}\n`)});if(e!==void 0){t.write(`[mcp] bundle identity anchor=${e.resolvedPath} inode=${e.inode} version=${ze}\n`);let{resolvedPath:n,inode:r}=e;g=ia({detect:()=>ra({bundleAnchorPath:Wo,currentInode:r,platform:process.platform,realpath:pt,statInode:e=>ht(e).ino}),onReplaced:e=>{t.write(`[mcp] bundle replaced anchor=${n} bootInode=${e.currentInode} onDiskInode=${e.onDiskInode} version=${ze} — exiting for host respawn\n`),y()},log:e=>t.write(`[mcp] ${e}\n`)})}}return{close:ne}}function Xo(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=ko(process.env.OK_MCP_SPAWN_TIMEOUT_MS);await Uo({lockDir:``,contentDir:``,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:e});return}await Yo({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 Zo(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-
|
|
62
|
+
`),process.exit(1)},5e3).unref(),ne().finally(()=>{process.exit(0)}))};if(process.once(`SIGINT`,y),process.once(`SIGTERM`,y),sa({log:e=>t.write(`${e}\n`),transport:h,process,stdin:process.stdin}),process.platform===`darwin`){let e=aa(Wo,{realpathSync:pt,statInoSync:e=>ht(e).ino,log:e=>t.write(`${e}\n`)});if(e!==void 0){t.write(`[mcp] bundle identity anchor=${e.resolvedPath} inode=${e.inode} version=${ze}\n`);let{resolvedPath:n,inode:r}=e;g=ia({detect:()=>ra({bundleAnchorPath:Wo,currentInode:r,platform:process.platform,realpath:pt,statInode:e=>ht(e).ino}),onReplaced:e=>{t.write(`[mcp] bundle replaced anchor=${n} bootInode=${e.currentInode} onDiskInode=${e.onDiskInode} version=${ze} — exiting for host respawn\n`),y()},log:e=>t.write(`[mcp] ${e}\n`)})}}return{close:ne}}function Xo(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=ko(process.env.OK_MCP_SPAWN_TIMEOUT_MS);await Uo({lockDir:``,contentDir:``,portOverride:t.port,envAutoStart:process.env.OK_MCP_AUTOSTART,timeoutMs:e});return}await Yo({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 Zo(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-D3f1d9Nx.mjs`),r=e(),i=process.cwd(),a=v(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 Qo(e){return e==null?!1:e.includes(`--type=utility`)&&e.includes(`--utility-sub-type=node.mojom.NodeService`)}function $o(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 es(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:Di(r),command:r,isDesktop:Qo(r)}}function ts(e){return e.ui==null?!1:e.ui.status===`alive`||e.ui.status===`foreign-host`}function ns(e){let t=e.server.status;return t===`alive`||t===`foreign-host`?e.isDesktop?`desktop`:t===`alive`?`running`:`foreign`:t===`dead-pid`&&ts(e)?`ui-orphan`:`stale`}const rs=new Set([`running`,`desktop`,`foreign`,`ui-orphan`]);function is(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 as(e){return e==null?`—`:`${e.cpuPercent.toFixed(1)}% / ${e.memPercent.toFixed(1)}%`}function os(e){return`${as(e.server.usage)} | ${as(e.ui?.usage??null)}`}function ss(e){return`${e.server.port===0?`(starting)`:String(e.server.port)} / ${e.ui==null||e.ui.status===`dead-pid`?`—`:String(e.ui.port)}`}function cs(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=ns(e),n=t===`ui-orphan`&&e.ui!=null?e.ui.pid:e.server.pid;return[e.directory,ss(e),os(e),t,String(n),$o(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=is(ns(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 ls(e={}){let t=e.discover??Fi,n=e.inspect??V,r=e.log??(e=>console.log(e)),i=e.resolveCommand??Oi,a=e.resolveUsage??ki,o=await t(),s=[];for(let e of o){let t=n(e,`server`),r=n(e,`ui`),o=es(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:ns(e)}));r(JSON.stringify(e,null,2));return}r(cs(e.all?s:s.filter(e=>rs.has(ns(e)))))}function us(){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 ls({all:t.all===!0||e===`all`,json:t.json===!0})})}function X(e,t){e&&process.stdout.write(`${JSON.stringify(t)}\n`)}async function ds(e,t,n=process.cwd()){let r=e.op??`sync`,i=Le(me(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=Be({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 fs(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 ds({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 ps(e){return new t(`pull`).description(`Pull changes from the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ds({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 ms(e){return new t(`push`).description(`Push commits to the remote`).option(`--json`,`Output JSONL progress events`,!1).action(async t=>{try{await ds({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 hs(e){return typeof e==`string`&&r.includes(e)}async function gs(e={}){let t=M(e.cwd??process.cwd()),n=e.pack??`knowledge-base`;if(!ye[n])return{status:`failed`,message:`${O(`Error:`)} Unknown pack "${n}". Available: ${r.join(`, `)}`,exitCode:1};let i;try{i=await l({projectDir:t,rootDir:e.root,packId:n})}catch(e){return e instanceof ne?{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=ye[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${vs(i,t)}`,plan:i,exitCode:0};if(!e.yes&&!await ys(`${k(`Plan:`)}\n\n${vs(i,t)}\n\n${k(`Apply?`)} ${E(`[Y/n] `)}`,e.confirmStream))return{status:`cancelled`,message:E(`Cancelled.`),plan:i,exitCode:0};let a=await ae(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:[`${Qe(`Applied`)} ${a.applied} entries, ${Qe(String(a.errors.length))} error(s):`,...e].join(`
|
|
65
65
|
`),plan:i,exitCode:1}}let o=ye[n].name;return{status:`applied`,message:`${D(`✓ Seeded ${o}`)} ${E(`(${a.applied} entries, ${a.durationMs}ms)`)}`,plan:i,exitCode:0}}function _s(){let e=[k(`Available packs:`)];for(let t of r){let n=ye[t];e.push(` ${D(t)} ${E(`—`)} ${n.name}: ${n.description}`)}return e.join(`
|