@inkeep/open-knowledge 0.0.0-dev-20260424071819 → 0.0.0-dev-20260424150009
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/skills/open-knowledge/SKILL.md +228 -0
- package/dist/{banner-cxbl_Ely.mjs → banner-CI3--er0.mjs} +2 -2
- package/dist/{chokidar-C6yIgAJZ.mjs → chokidar-Z9-8o-jG.mjs} +1 -1
- package/dist/cli.mjs +348 -274
- package/dist/colors-Cmha5EZJ.mjs +2 -0
- package/dist/colors-CxLEz90E.mjs +1 -0
- package/dist/constants-QFqPbiZ7.mjs +2 -0
- package/dist/{execAsync-DPeftusp.mjs → execAsync-CUbOIvpN.mjs} +1 -1
- package/dist/{execAsync-DhDvXMWQ.mjs → execAsync-CjzNx_Wg.mjs} +1 -1
- package/dist/{execAsync-RJZP-H-A.mjs → execAsync-xymjJFLm.mjs} +1 -1
- package/dist/{getMachineId-bsd-DcLiB1Fb.mjs → getMachineId-bsd-B_JlAoG9.mjs} +2 -2
- package/dist/{getMachineId-bsd-B-D2bOSl.mjs → getMachineId-bsd-CMAUw13R.mjs} +2 -2
- package/dist/{getMachineId-bsd-Dl-xGqjV.mjs → getMachineId-bsd-DrOrzTD2.mjs} +2 -2
- package/dist/{getMachineId-darwin-A7Xy885j.mjs → getMachineId-darwin-BQcf5peQ.mjs} +2 -2
- package/dist/{getMachineId-darwin-BQro2RrT.mjs → getMachineId-darwin-DC2qb-xd.mjs} +2 -2
- package/dist/{getMachineId-darwin-DPoYqu2E.mjs → getMachineId-darwin-DTGIdpu7.mjs} +2 -2
- package/dist/{getMachineId-linux-BwDCbiIf.mjs → getMachineId-linux-C3A6DqVu.mjs} +1 -1
- package/dist/{getMachineId-linux-DLyT3DBf.mjs → getMachineId-linux-CMta7vmz.mjs} +1 -1
- package/dist/{getMachineId-linux-B6DWkXLm.mjs → getMachineId-linux-nez-pYOw.mjs} +1 -1
- package/dist/{getMachineId-unsupported-CnUw0N-q.mjs → getMachineId-unsupported-BrxgPAkN.mjs} +1 -1
- package/dist/{getMachineId-unsupported-VfwZ1yF9.mjs → getMachineId-unsupported-gFGrtRr7.mjs} +1 -1
- package/dist/{getMachineId-unsupported-CQbaY6vv.mjs → getMachineId-unsupported-j-7WDfTT.mjs} +1 -1
- package/dist/{getMachineId-win-Bmzw0GhO.mjs → getMachineId-win-CfF1zVez.mjs} +2 -2
- package/dist/{getMachineId-win-DHI6zfnJ.mjs → getMachineId-win-D8Js6D_D.mjs} +2 -2
- package/dist/{getMachineId-win-BYymgu0m.mjs → getMachineId-win-DsIEIIis.mjs} +2 -2
- package/dist/index.d.mts +0 -7
- package/dist/index.mjs +1 -1
- package/dist/init-Bw4LWW1o.mjs +1 -0
- package/dist/init-D0FupYPY.mjs +1 -0
- package/dist/init-D2rQPwU1.mjs +120 -0
- package/dist/init-DUIYyxaK.mjs +5 -0
- package/dist/{is-object-DVVYT5oa.mjs → is-object-7k010cEq.mjs} +1 -1
- package/dist/{keepalive-BqSeN73F.mjs → keepalive-CfaIYv9f.mjs} +1 -1
- package/dist/{loader-C-EaZX2e.mjs → loader-C3Wwbx8H.mjs} +2 -2
- package/dist/loader-DNeW8gS5.mjs +1 -0
- package/dist/{paths-BPoLusOz.mjs → paths-Ba3tNHQr.mjs} +2 -2
- package/dist/paths-ORyeejxG.mjs +1 -0
- package/dist/preview-BR34uHnQ.mjs +1 -0
- package/dist/{preview-T_RVYqtF.mjs → preview-QLsD0vVK.mjs} +2 -2
- package/dist/public/assets/McpConsentDialogBody-BpxsNx0A.js +1 -0
- package/dist/public/assets/index-Bnp3jcJM.js +27 -0
- package/dist/public/assets/index-tR5M38z1.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/src-CeiyJxyd.mjs +1 -0
- package/dist/{src-DQq7h88V.mjs → src-DIoA15kL.mjs} +25 -8
- package/dist/src-lFQj9tkB.mjs +1 -0
- package/dist/start-B9LXLMio.mjs +1 -0
- package/dist/{start-B84Wdu83.mjs → start-C79L5QTe.mjs} +2 -2
- package/dist/{wrapper-DhAZwCvI.mjs → wrapper-BlhyhsXg.mjs} +1 -1
- package/package.json +6 -2
- package/scripts/postinstall.mjs +53 -0
- package/scripts/probe-exec.ts +100 -0
- package/scripts/probe-read-document.ts +111 -0
- package/dist/colors-CDmFQ1jq.mjs +0 -1
- package/dist/colors-CEQEtnHQ.mjs +0 -2
- package/dist/constants-CXDXntb9.mjs +0 -2
- package/dist/init-BBVwEA2N.mjs +0 -5
- package/dist/init-DsXM9hPp.mjs +0 -1
- package/dist/init-DvES_bXI.mjs +0 -1
- package/dist/init-QQvPB0Au.mjs +0 -230
- package/dist/loader-Ck-HQgHI.mjs +0 -1
- package/dist/paths-B483looM.mjs +0 -1
- package/dist/preview-C5sfPOVh.mjs +0 -1
- package/dist/public/assets/McpConsentDialogBody-Dg7gdIrj.js +0 -1
- package/dist/public/assets/index-B33JcCrk.js +0 -27
- package/dist/public/assets/index-Cj5uVVs3.css +0 -1
- package/dist/src-DN3CCqaD.mjs +0 -1
- package/dist/src-DuGm387u.mjs +0 -1
- package/dist/start-h-f1SVhW.mjs +0 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: open-knowledge
|
|
3
|
+
description: "MUST invoke before ANY tool call in a project that contains a .open-knowledge/ directory. Also MUST invoke before any mcp__open-knowledge__ tool call, any write_document / edit_document, and any read or edit of a .md or .mdx file. Carries the preview-before-edit sequence (get_preview_url then open browser then write), STOP rules for native Read/Grep/Edit on in-scope markdown, grounding rules (every factual claim needs a source), standard markdown linking conventions with get_dead_links verification, image sourcing + alt-text + source-citation rules, folder-first organization with config.yml metadata, and the anti-pattern table. Do NOT assume the MCP server instructions or any AGENTS.md substitute for this skill — they overlap but this skill carries the full preview sequence, grounding rule, media rules, dead-link verification, and failure-mode guidance not in those surfaces."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Open Knowledge — agent guidance
|
|
7
|
+
|
|
8
|
+
Open Knowledge (OK) is a markdown-CRDT collaboration platform exposed via MCP. This skill carries the behavioral rules agents need to use it fluently. Every section is a MUST unless marked otherwise.
|
|
9
|
+
|
|
10
|
+
> Skill version: tracks `@inkeep/open-knowledge-server` package version. Check `cat ~/.open-knowledge/skill-installed-version` to see what's installed locally.
|
|
11
|
+
|
|
12
|
+
## STOP — native tools on in-scope `.md` / `.mdx`
|
|
13
|
+
|
|
14
|
+
When this workspace has Open Knowledge MCP configured, do **not** use your host's native file tools on markdown paths inside the content directory. The ban covers every common rationalization:
|
|
15
|
+
|
|
16
|
+
- **Native `Read` / `Grep` / `Glob` on in-scope `.md` / `.mdx`** — the original case.
|
|
17
|
+
- **`Bash ls` / `Bash find` / `Bash cat` on dirs containing in-scope markdown** — use `exec("ls …")` / `exec("find … -name '*.md'")` / `exec("cat …")` instead. Native returns bare names; `exec` returns frontmatter, backlink counts, and recent activity per child.
|
|
18
|
+
- **Glob patterns that target markdown** (`**/*.md`, any dir known to be markdown-heavy like `specs/**`, `reports/**`, `docs/**`) — use `exec` with `find`, or `list_documents({ dir })`.
|
|
19
|
+
- **Dispatching the Explore / general-purpose subagent for markdown-heavy exploration** — subagents use native `Read` / `Grep` / `Glob` internally and bypass Open Knowledge entirely. Do markdown exploration yourself via `exec` / `search`. Subagents remain appropriate for **source-code** exploration.
|
|
20
|
+
- **Reading `.open-knowledge/AGENTS.md` via native `Read`** — observed failure mode during M1 testing. The `.open-knowledge/` directory is in-scope; treat its contents the same as any other wiki file.
|
|
21
|
+
|
|
22
|
+
Why: native tools skip frontmatter, backlinks, shadow-repo activity, and project git history that OK's tools return for every matched wiki file. `exec` is the primary read surface; it runs read-only bash (`cat`, `ls`, `grep`, `find`, `head`, `tail`, `wc`, `sort`, `uniq`, `cut` — pipes OK) and returns raw stdout plus enriched metadata per file.
|
|
23
|
+
|
|
24
|
+
**MCP tool visibility — not seeing `exec` is NOT the escape hatch.** MCP wiring varies by client. Claude Code, Cursor, Codex, Windsurf, VS Code — each surfaces MCP differently. Server labels are user-defined; tools may not appear as top-level symbols named `exec` in your specific UI. If Open Knowledge is registered as an MCP server in this workspace, route markdown reads through its `exec` / `search` / `read_document` via your client's documented MCP invocation (including any generic "call MCP tool" flow). Registration is the test, not top-level-symbol visibility.
|
|
25
|
+
|
|
26
|
+
**Escape hatch.** Native `Read` / `Grep` / `Glob` on `.md` / `.mdx` is allowed **only** when no Open Knowledge MCP server is registered for this project, **or** immediately after you tried an MCP call and it failed — then begin a user-visible sentence with `Open Knowledge MCP unavailable:`. Never use the hatch because you skipped your client's MCP path, didn't see `exec` as a top-level tool, or rationalized the skill wasn't necessary.
|
|
27
|
+
|
|
28
|
+
**Source code and non-markdown files** (`.ts`, `.py`, `package.json`, …): native `Read` / `Grep` / `Glob` always.
|
|
29
|
+
|
|
30
|
+
## Reads — examples
|
|
31
|
+
|
|
32
|
+
- Read a file: `exec("cat <path>.md")` — contents + full rich enrichment
|
|
33
|
+
- List a directory: `exec("ls <dir>")` — per-child frontmatter, recursive markdown counts, most-recently-updated doc per subdir
|
|
34
|
+
- Search: `exec("grep -rn <term> <dir> | head -5")` — matches + enrichment on matched files
|
|
35
|
+
- Typed tools (`read_document`, `search`, `list_documents`) remain available — prefer them when a structured `structuredContent` shape is useful (e.g., passing results to another tool). For interactive reads, `exec` is lighter.
|
|
36
|
+
|
|
37
|
+
## Writing — preview-before-edit (REQUIRED)
|
|
38
|
+
|
|
39
|
+
Every call to `write_document` / `edit_document` MUST follow this sequence:
|
|
40
|
+
|
|
41
|
+
1. **Call `get_preview_url(docName)`.** If it returns `null`, the UI isn't running — start it (`ok ui` from a terminal, or `preview_start("open-knowledge-ui")` in Claude Code). Then call `get_preview_url` again. NEVER construct a preview URL by hand.
|
|
42
|
+
2. **Open that URL in your preview browser** so the user sees the document.
|
|
43
|
+
3. **Only then call `write_document` / `edit_document`** — the CRDT edit streams live into the already-open editor.
|
|
44
|
+
|
|
45
|
+
Never skip the preview step. The user expects to watch every edit land in real time. Write-tool responses include `previewUrl` (when resolvable) and a `warning` when no client is currently attached to the doc.
|
|
46
|
+
|
|
47
|
+
Native `Edit` / `sed` / direct `Write` on in-scope markdown is forbidden — it bypasses the CRDT and loses agent attribution in the shadow repo.
|
|
48
|
+
|
|
49
|
+
**No screenshots after edits.** Do NOT take `preview_screenshot` after every `edit_document` / `write_document`. Trust the CRDT tool response as confirmation the edit landed. Only screenshot when debugging a visual issue or when explicitly asked.
|
|
50
|
+
|
|
51
|
+
## Grounding — every factual claim needs a source (MUST)
|
|
52
|
+
|
|
53
|
+
Knowledge-base docs are factual artifacts. Every claim must be traceable to a source.
|
|
54
|
+
|
|
55
|
+
- **Every factual claim MUST cite its source at the point of claim.** No unsourced speculation.
|
|
56
|
+
- **Web sources** → inline markdown link: `[source name](https://example.com/path)`. Use your host's web-fetch / web-search tool (`WebFetch`, `WebSearch`, or equivalent) to find the source *first*. Don't write a fact and then look for a source to justify it.
|
|
57
|
+
- **Internal cross-refs** → standard markdown link to the OK doc that contains the authoritative claim: `[text](./path/to/doc.md)`. The linked doc itself must cite its sources — chains should terminate in external evidence eventually.
|
|
58
|
+
- **If you don't have evidence:**
|
|
59
|
+
1. Run a web search and cite the result, OR
|
|
60
|
+
2. Mark inline `(TODO: needs source)` so a human can verify, OR
|
|
61
|
+
3. Don't write the claim. Do NOT fabricate.
|
|
62
|
+
- Unsourced speculation looks authoritative but rots into tribal knowledge that can't be audited. The knowledge base loses its value if readers can't trust it.
|
|
63
|
+
- If a fact is in the knowledge base, a reader must be able to trace it to its origin. Grounded evidence is the knowledge base's core contract.
|
|
64
|
+
|
|
65
|
+
## Linking — use standard markdown links
|
|
66
|
+
|
|
67
|
+
- **Every noun-phrase that names another document should be linked** using standard markdown link syntax: `[text](./relative/path.md)` or `[text](/absolute/from/content-root.md)`.
|
|
68
|
+
- **External web sources** → `[source name](https://...)` — required for citations per the Grounding rule above.
|
|
69
|
+
- **Internal cross-refs between OK docs** → `[text](./other-doc.md)` — link liberally to aid navigation.
|
|
70
|
+
- **Never wrap a link in backticks.** `` `[text](./foo.md)` `` is a bug — the backticks make it render as literal code rather than a link.
|
|
71
|
+
- **Never use HTML anchors** (`<a href="...">`). Markdown link syntax only.
|
|
72
|
+
- **Verify before walking away.** After writing a doc, call `get_dead_links({ sourceDocNames: ['your/doc'] })` to find broken references. Fix each redlink or explicitly accept it.
|
|
73
|
+
- **The editor's red-underline visual lies.** Its dead-link detection tolerates slug-fallback (e.g., `foo` may appear resolved because `foo.md` exists at root). `get_dead_links` is strict-exact — trust the tool, not the visual.
|
|
74
|
+
|
|
75
|
+
**Note on wiki-link syntax (`[[Page]]`):** the parser still handles it for legacy content, but it's NO LONGER the recommended default. Write new content with standard markdown links per above.
|
|
76
|
+
|
|
77
|
+
## Media — images and attachments
|
|
78
|
+
|
|
79
|
+
### 1. Markdown syntax only
|
|
80
|
+
|
|
81
|
+
- Use markdown image syntax: ``.
|
|
82
|
+
- Do NOT emit HTML `<img src="...">` tags. They get preserved in the CRDT but don't participate in OK's content graph and don't render consistently across Fumadocs / preview surfaces.
|
|
83
|
+
- Paths resolve relative to the doc's own path (standard CommonMark).
|
|
84
|
+
|
|
85
|
+
### 2. Image sourcing — save locally, don't hot-link
|
|
86
|
+
|
|
87
|
+
- Agents MUST NOT embed external image URLs directly (e.g., ``). Hot-linked images rot when the source disappears, leak referrers, and don't travel if content is exported or archived.
|
|
88
|
+
- To use an image from an external source:
|
|
89
|
+
1. Fetch it (`WebFetch` / `curl` / your host's equivalent) and save to a local path.
|
|
90
|
+
2. Reference with a relative markdown image link.
|
|
91
|
+
3. Cite the source in a caption (see §4 below).
|
|
92
|
+
- **Conventional location:** `assets/images/<topic>/<filename>` under the content root. If the project already has a different convention, follow it — check via `exec("ls assets/")` or `exec("find . -type d -name images")` first.
|
|
93
|
+
- 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.
|
|
94
|
+
|
|
95
|
+
### 3. Alt-text discipline
|
|
96
|
+
|
|
97
|
+
- Every image needs **meaningful alt text** describing what the image shows, not what it is.
|
|
98
|
+
- Bad: `` (empty — invisible to assistive tech, zero searchability)
|
|
99
|
+
- Bad: `` (generic — same problem)
|
|
100
|
+
- Bad: `` (filename as alt — still generic)
|
|
101
|
+
- Good: ``
|
|
102
|
+
- Alt text is both an accessibility requirement AND a searchability signal — OK indexes alt text.
|
|
103
|
+
|
|
104
|
+
### 4. Cite image sources (Grounding rule applies)
|
|
105
|
+
|
|
106
|
+
- Every image pulled from the web needs a source caption right below it, per the Grounding rule:
|
|
107
|
+
```markdown
|
|
108
|
+

|
|
109
|
+
*Source: [Avatar Wiki — Aang](https://avatar.fandom.com/wiki/Aang#Avatar_State)*
|
|
110
|
+
```
|
|
111
|
+
- Original images (your own diagrams, screenshots of your own tool, etc.) may caption `*Original*` or omit the caption.
|
|
112
|
+
- Unattributed web images are a failure mode equivalent to unsourced factual claims.
|
|
113
|
+
|
|
114
|
+
## Frontmatter conventions
|
|
115
|
+
|
|
116
|
+
Open Knowledge has two metadata surfaces that merge at read time:
|
|
117
|
+
|
|
118
|
+
**Per-file frontmatter.** Every `.md` / `.mdx` file in the knowledge base should have YAML frontmatter:
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
---
|
|
122
|
+
title: Article Title (required)
|
|
123
|
+
description: Brief summary (required)
|
|
124
|
+
tags:
|
|
125
|
+
- relevant
|
|
126
|
+
- tags
|
|
127
|
+
---
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Folder-level defaults via `.open-knowledge/config.yml` `folders:`.** See next section.
|
|
131
|
+
|
|
132
|
+
## Follow `.open-knowledge/config.yml` — it is the project contract
|
|
133
|
+
|
|
134
|
+
**Read `.open-knowledge/config.yml` at the start of every session that involves writing to the knowledge base.** It is the single source of truth for:
|
|
135
|
+
|
|
136
|
+
- **Folder structure intent** — the `folders:` block tells you which folders exist, what each one contains, and what tags its files should carry. Every `exec("ls <folder>")` / `read_document` / `search` call merges these defaults with per-file frontmatter automatically, but you should also read config.yml directly when orienting so you can *place new docs in the right folder* and *write them in the voice + shape the project expects*.
|
|
137
|
+
- **Per-folder instructions** — each `folders:` entry's `description:` field is the canonical place for "what does this folder contain + how should agents work inside it." Treat the description as a binding instruction, not flavor text. If a folder's description says "preserve verbatim, no analysis" (e.g. `external-sources/`), don't synthesize into those files; takeaways belong elsewhere.
|
|
138
|
+
- **Content scope** — `content.dir` / `content.include` / `content.exclude` define which files count as knowledge-base documents. Anything outside those globs is regular source code, not a wiki doc.
|
|
139
|
+
|
|
140
|
+
If a project uses `ok seed` to scaffold the Karpathy three-layer layout (`external-sources/` → `research/` → `articles/`), each folder's description in `config.yml` encodes the layer's rules. Projects with custom layouts put their own discipline in their own descriptions. Either way: **follow what config.yml says.**
|
|
141
|
+
|
|
142
|
+
## Folder structure + metadata — edit `.open-knowledge/config.yml`
|
|
143
|
+
|
|
144
|
+
When you create or restructure folders, you SHOULD add a matching entry to the `folders:` key in `.open-knowledge/config.yml` with a glob + frontmatter defaults. This is how per-folder title/description/tags land without duplicating frontmatter on every child file.
|
|
145
|
+
|
|
146
|
+
Example:
|
|
147
|
+
|
|
148
|
+
```yaml
|
|
149
|
+
folders:
|
|
150
|
+
- match: 'articles/characters/team-avatar/**'
|
|
151
|
+
frontmatter:
|
|
152
|
+
title: Team Avatar
|
|
153
|
+
description: Core Team Avatar character articles
|
|
154
|
+
tags: [characters, team-avatar]
|
|
155
|
+
- match: 'articles/characters/fire-nation/**'
|
|
156
|
+
frontmatter:
|
|
157
|
+
title: Fire Nation Characters
|
|
158
|
+
description: Antagonists and Fire Nation cast
|
|
159
|
+
tags: [characters, fire-nation]
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Rules:
|
|
163
|
+
- Rules apply in declaration order; later matches override earlier scalars.
|
|
164
|
+
- Tags concat + dedup across all matching rules; first-occurrence preserved.
|
|
165
|
+
- File's own frontmatter always wins per-scalar; folder defaults fill in blanks.
|
|
166
|
+
- Folder metadata lives in `config.yml` only — NOT in an `INDEX.md` / `README.md` hub file inside the folder.
|
|
167
|
+
|
|
168
|
+
Prefer enriching `config.yml` over creating hub files. The merge is computed on every `exec("ls <folder>")` / `read_document` / `search` call and is never written back to disk.
|
|
169
|
+
|
|
170
|
+
## Organization
|
|
171
|
+
|
|
172
|
+
- **Folders are the organizational unit.** Group related docs in a shared folder.
|
|
173
|
+
- **Folder-level metadata lives in `config.yml`** under `folders:` (see section above).
|
|
174
|
+
- **Don't create `INDEX.md` / `README.md` hub files** solely to catalog children — `exec("ls <folder>")` returns the same view live, with per-file frontmatter + backlink counts.
|
|
175
|
+
- If a hub doc exists from prior work, keep it updated as children change — but don't create new ones.
|
|
176
|
+
|
|
177
|
+
## Cadence
|
|
178
|
+
|
|
179
|
+
When you make a multi-step change (batch of new docs, folder restructure), pause between steps to let the browser preview catch up. The CRDT edit streams live; the preview follows your edit cadence. Don't batch 10 writes in a row — interleave the writes so the user watching the browser sees the narrative progress.
|
|
180
|
+
|
|
181
|
+
If a hub doc exists in a folder, update it as you change children. Don't batch five child edits and then update the hub — write child → update hub → write next child.
|
|
182
|
+
|
|
183
|
+
This is primarily a human-watchability concern — the user watches edits land in the preview; interleaved cadence makes the narrative legible.
|
|
184
|
+
|
|
185
|
+
## Anti-patterns — at a glance
|
|
186
|
+
|
|
187
|
+
| Task | Don't | Do |
|
|
188
|
+
| --------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------ |
|
|
189
|
+
| List a markdown-heavy dir | `Bash: ls specs/` | `exec("ls specs/")` |
|
|
190
|
+
| Find all SPEC.md files | `Glob: **/SPEC.md` | `exec("find specs -name SPEC.md")` |
|
|
191
|
+
| Search a phrase across markdown | `Grep: "pattern" *.md` | `search({ query: "pattern" })` |
|
|
192
|
+
| Read an individual doc | `Read: specs/foo/SPEC.md` | `exec("cat specs/foo/SPEC.md")` or `read_document(...)` |
|
|
193
|
+
| Explore a markdown-heavy dir | `Agent(Explore): "..."` | Do `exec`-based exploration yourself |
|
|
194
|
+
| Edit without preview | `write_document(...)` direct | `get_preview_url` → open browser → `write_document` |
|
|
195
|
+
| Reference another doc | `` `[text](./page.md)` `` (backticked) or HTML `<a>` | `[text](./page.md)` (raw markdown) |
|
|
196
|
+
| Embed an image | `<img src="...">` (HTML) or hot-linked external URL | Fetch + save locally + `` |
|
|
197
|
+
| Write a factual claim | plausible prose without citation | prose with `[source](URL)` per Grounding rule |
|
|
198
|
+
| Add an image | empty alt `` or generic alt `` | meaningful alt + source caption below |
|
|
199
|
+
| Catalog folder contents | create `INDEX.md` hub file | add `folders:` entry in `.open-knowledge/config.yml` |
|
|
200
|
+
| Fork a skill and expect no stomp | Edit installed SKILL.md | `npx skills remove` before CLI upgrade |
|
|
201
|
+
|
|
202
|
+
## Workflow tools — when to invoke them
|
|
203
|
+
|
|
204
|
+
Three MCP tools build on the primitives above and correspond to [Karpathy's three-layer knowledge-base pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f):
|
|
205
|
+
|
|
206
|
+
| Tool | Layer | When to invoke |
|
|
207
|
+
| --- | --- | --- |
|
|
208
|
+
| `ingest` | Raw sources (immutable) | User shares a URL, PDF, or file to preserve verbatim. No analysis in the file itself — takeaways go back to the user in chat. |
|
|
209
|
+
| `research` | Wiki, 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. |
|
|
210
|
+
| `consolidate` | Wiki, 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. |
|
|
211
|
+
|
|
212
|
+
Each tool returns a multi-step instructional body when invoked. The bodies enforce their own gates — follow the numbered steps in order, don't skip the STOP gates.
|
|
213
|
+
|
|
214
|
+
Typical day-2 flow: user shares a URL → `ingest` (preserve) → user asks "now research this" → `research` (provisional article + `ingest`s more sources as needed) → decision lands → `consolidate` (canonical article, supersedes the research).
|
|
215
|
+
|
|
216
|
+
**Do not chain silently.** After `ingest`, ask the user whether to proceed to `research`. After `research`, let the user decide whether the findings are ready to `consolidate`. Each tool completes on its own terms — the user drives the transitions.
|
|
217
|
+
|
|
218
|
+
**Project scaffolding is a CLI operation (optional).** Users who want the Karpathy three-layer layout as their folder structure can run `ok seed` once from a terminal. That command scaffolds `external-sources/` + `research/` + `articles/`, seeds an append-only `log.md` at the project root, and writes matching `config.yml` `folders:` entries so agents see layer descriptions at every `exec("ls <folder>")` call. It is **not required**: the three workflow tools above work against any folder structure the project already uses (`specs/`, `docs/`, `reports/`, or anything else). Only mention `ok seed` if the user explicitly asks for a starter layout or wants the Karpathy pattern specifically.
|
|
219
|
+
|
|
220
|
+
## Server lifecycle
|
|
221
|
+
|
|
222
|
+
If `write_document` or `edit_document` returns a "Hocuspocus server is not running" error, start it with `ok start` (via Bash) and retry. Never fall back to native `Edit` / `Write` for in-scope markdown — always route through the MCP write tools so edits go through the CRDT with proper attribution.
|
|
223
|
+
|
|
224
|
+
## Scope recap
|
|
225
|
+
|
|
226
|
+
When MCP is connected, the server's `instructions` echo the **resolved** `dir` / `include` / `exclude` for this session — treat that table and `.open-knowledge/config.yml` as two views of the same rules. `.gitignore` still applies.
|
|
227
|
+
|
|
228
|
+
Default mental model (no jargon): unless this project narrowed `content.include`, **every `.md` and `.mdx` under `content.dir`** is an Open Knowledge document — including under `specs/`, `reports/`, `docs/`, etc. If `content.include` is non-default, read `config.yml` once per turn so you do not mis-classify paths.
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as e,i as t,n,t as r}from"./colors-
|
|
1
|
+
import{a as e,i as t,n,t as r}from"./colors-Cmha5EZJ.mjs";import i from"cli-boxes";const a=i.round;function o(i){let o=[],s=`${i.name} v${i.version}`;o.push({plain:s,colored:r(s)}),o.push({plain:``,colored:``});let c=i.apiUrl?`Editor: `:`Local: `;if(o.push({plain:`${c}${i.localUrl}`,colored:`${c}${e(t(i.localUrl),i.localUrl)}`}),i.apiUrl){let t=`API: `;o.push({plain:`${t}${i.apiUrl}`,colored:`${t}${n(e(i.apiUrl,i.apiUrl))}`})}if(i.networkUrl){let n=`Network: `;o.push({plain:`${n}${i.networkUrl}`,colored:`${n}${e(t(i.networkUrl),i.networkUrl)}`})}o.push({plain:``,colored:``});let l=`Press Ctrl+C to stop`;o.push({plain:l,colored:n(l)});let u=Math.max(...o.map(e=>e.plain.length)),d=u+4,f=` ${a.topLeft}${a.top.repeat(d)}${a.topRight}`,p=` ${a.bottomLeft}${a.bottom.repeat(d)}${a.bottomRight}`;return[``,f,...o.map(e=>{let t=u-e.plain.length;return` ${a.left}${` `.repeat(2)}${e.colored}${` `.repeat(t+2)}${a.right}`}),p,``].join(`
|
|
2
2
|
`)}export{o as renderBanner};
|
|
3
|
-
//# sourceMappingURL=banner-
|
|
3
|
+
//# sourceMappingURL=banner-CI3--er0.mjs.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import{stat as e,unwatchFile as t,watch as n,watchFile as r}from"node:fs";import{type as i}from"node:os";import*as a from"node:path";import{join as o,relative as s,resolve as c,sep as l}from"node:path";import{EventEmitter as u}from"node:events";import{Readable as d}from"node:stream";import{lstat as f,open as ee,readdir as p,realpath as m,stat as h}from"node:fs/promises";const g={FILE_TYPE:`files`,DIR_TYPE:`directories`,FILE_DIR_TYPE:`files_directories`,EVERYTHING_TYPE:`all`},_={root:`.`,fileFilter:e=>!0,directoryFilter:e=>!0,type:g.FILE_TYPE,lstat:!1,depth:2147483648,alwaysStat:!1,highWaterMark:4096};Object.freeze(_);const v=`READDIRP_RECURSIVE_ERROR`,y=new Set([`ENOENT`,`EPERM`,`EACCES`,`ELOOP`,v]),b=[g.DIR_TYPE,g.EVERYTHING_TYPE,g.FILE_DIR_TYPE,g.FILE_TYPE],te=new Set([g.DIR_TYPE,g.EVERYTHING_TYPE,g.FILE_DIR_TYPE]),ne=new Set([g.EVERYTHING_TYPE,g.FILE_DIR_TYPE,g.FILE_TYPE]),re=e=>y.has(e.code),ie=process.platform===`win32`,x=e=>!0,S=e=>{if(e===void 0)return x;if(typeof e==`function`)return e;if(typeof e==`string`){let t=e.trim();return e=>e.basename===t}if(Array.isArray(e)){let t=e.map(e=>e.trim());return e=>t.some(t=>e.basename===t)}return x};var C=class extends d{parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;constructor(e={}){super({objectMode:!0,autoDestroy:!0,highWaterMark:e.highWaterMark});let t={..._,...e},{root:n,type:r}=t;this._fileFilter=S(t.fileFilter),this._directoryFilter=S(t.directoryFilter);let i=t.lstat?f:h;ie?this._stat=e=>i(e,{bigint:!0}):this._stat=i,this._maxDepth=t.depth!=null&&Number.isSafeInteger(t.depth)?t.depth:_.depth,this._wantsDir=r?te.has(r):!1,this._wantsFile=r?ne.has(r):!1,this._wantsEverything=r===g.EVERYTHING_TYPE,this._root=c(n),this._isDirent=!t.alwaysStat,this._statsProp=this._isDirent?`dirent`:`stats`,this._rdOptions={encoding:`utf8`,withFileTypes:this._isDirent},this.parents=[this._exploreDir(n,1)],this.reading=!1,this.parent=void 0}async _read(e){if(!this.reading){this.reading=!0;try{for(;!this.destroyed&&e>0;){let t=this.parent,n=t&&t.files;if(n&&n.length>0){let{path:r,depth:i}=t,a=n.splice(0,e).map(e=>this._formatEntry(e,r)),o=await Promise.all(a);for(let t of o){if(!t)continue;if(this.destroyed)return;let n=await this._getEntryType(t);n===`directory`&&this._directoryFilter(t)?(i<=this._maxDepth&&this.parents.push(this._exploreDir(t.fullPath,i+1)),this._wantsDir&&(this.push(t),e--)):(n===`file`||this._includeAsFile(t))&&this._fileFilter(t)&&this._wantsFile&&(this.push(t),e--)}}else{let e=this.parents.pop();if(!e){this.push(null);break}if(this.parent=await e,this.destroyed)return}}}catch(e){this.destroy(e)}finally{this.reading=!1}}}async _exploreDir(e,t){let n;try{n=await p(e,this._rdOptions)}catch(e){this._onError(e)}return{files:n,depth:t,path:e}}async _formatEntry(e,t){let n,r=this._isDirent?e.name:e;try{let i=c(o(t,r));n={path:s(this._root,i),fullPath:i,basename:r},n[this._statsProp]=this._isDirent?e:await this._stat(i)}catch(e){this._onError(e);return}return n}_onError(e){re(e)&&!this.destroyed?this.emit(`warn`,e):this.destroy(e)}async _getEntryType(e){if(!e&&this._statsProp in e)return``;let t=e[this._statsProp];if(t.isFile())return`file`;if(t.isDirectory())return`directory`;if(t&&t.isSymbolicLink()){let t=e.fullPath;try{let e=await m(t),n=await f(e);if(n.isFile())return`file`;if(n.isDirectory()){let n=e.length;if(t.startsWith(e)&&t.substr(n,1)===l){let n=Error(`Circular symlink detected: "${t}" points to "${e}"`);return n.code=v,this._onError(n)}return`directory`}}catch(e){return this._onError(e),``}}}_includeAsFile(e){let t=e&&e[this._statsProp];return t&&this._wantsEverything&&!t.isDirectory()}};function ae(e,t={}){let n=t.entryType||t.type;if(n===`both`&&(n=g.FILE_DIR_TYPE),n&&(t.type=n),!e)throw Error(`readdirp: root argument is required. Usage: readdirp(root, options)`);if(typeof e!=`string`)throw TypeError(`readdirp: root argument must be a string. Usage: readdirp(root, options)`);if(n&&!b.includes(n))throw Error(`readdirp: Invalid type passed. Use one of ${b.join(`, `)}`);return t.root=e,new C(t)}const w=()=>{},T=process.platform,E=T===`win32`,D=T===`darwin`,O=T===`linux`,k=T===`freebsd`,A=i()===`OS400`,j={ALL:`all`,READY:`ready`,ADD:`add`,CHANGE:`change`,ADD_DIR:`addDir`,UNLINK:`unlink`,UNLINK_DIR:`unlinkDir`,RAW:`raw`,ERROR:`error`},M=j,N={lstat:f,stat:h},P=`listeners`,F=`errHandlers`,I=`rawEmitters`,oe=[P,F,I],se=new Set(`3dm.3ds.3g2.3gp.7z.a.aac.adp.afdesign.afphoto.afpub.ai.aif.aiff.alz.ape.apk.appimage.ar.arj.asf.au.avi.bak.baml.bh.bin.bk.bmp.btif.bz2.bzip2.cab.caf.cgm.class.cmx.cpio.cr2.cur.dat.dcm.deb.dex.djvu.dll.dmg.dng.doc.docm.docx.dot.dotm.dra.DS_Store.dsk.dts.dtshd.dvb.dwg.dxf.ecelp4800.ecelp7470.ecelp9600.egg.eol.eot.epub.exe.f4v.fbs.fh.fla.flac.flatpak.fli.flv.fpx.fst.fvt.g3.gh.gif.graffle.gz.gzip.h261.h263.h264.icns.ico.ief.img.ipa.iso.jar.jpeg.jpg.jpgv.jpm.jxr.key.ktx.lha.lib.lvp.lz.lzh.lzma.lzo.m3u.m4a.m4v.mar.mdi.mht.mid.midi.mj2.mka.mkv.mmr.mng.mobi.mov.movie.mp3.mp4.mp4a.mpeg.mpg.mpga.mxu.nef.npx.numbers.nupkg.o.odp.ods.odt.oga.ogg.ogv.otf.ott.pages.pbm.pcx.pdb.pdf.pea.pgm.pic.png.pnm.pot.potm.potx.ppa.ppam.ppm.pps.ppsm.ppsx.ppt.pptm.pptx.psd.pya.pyc.pyo.pyv.qt.rar.ras.raw.resources.rgb.rip.rlc.rmf.rmvb.rpm.rtf.rz.s3m.s7z.scpt.sgi.shar.snap.sil.sketch.slk.smv.snk.so.stl.suo.sub.swf.tar.tbz.tbz2.tga.tgz.thmx.tif.tiff.tlz.ttc.ttf.txz.udf.uvh.uvi.uvm.uvp.uvs.uvu.viv.vob.war.wav.wax.wbmp.wdp.weba.webm.webp.whl.wim.wm.wma.wmv.wmx.woff.woff2.wrm.wvx.xbm.xif.xla.xlam.xls.xlsb.xlsm.xlsx.xlt.xltm.xltx.xm.xmind.xpi.xpm.xwd.xz.z.zip.zipx`.split(`.`)),ce=e=>se.has(a.extname(e).slice(1).toLowerCase()),L=(e,t)=>{e instanceof Set?e.forEach(t):t(e)},R=(e,t,n)=>{let r=e[t];r instanceof Set||(e[t]=r=new Set([r])),r.add(n)},z=e=>t=>{let n=e[t];n instanceof Set?n.clear():delete e[t]},B=(e,t,n)=>{let r=e[t];r instanceof Set?r.delete(n):r===n&&delete e[t]},V=e=>e instanceof Set?e.size===0:!e,H=new Map;function U(e,t,r,i,o){let s=(t,n)=>{r(e),o(t,n,{watchedPath:e}),n&&e!==n&&W(a.resolve(e,n),P,a.join(e,n))};try{return n(e,{persistent:t.persistent},s)}catch(e){i(e);return}}const W=(e,t,n,r,i)=>{let a=H.get(e);a&&L(a[t],e=>{e(n,r,i)})},le=(e,t,n,r)=>{let{listener:i,errHandler:a,rawEmitter:o}=r,s=H.get(t),c;if(!n.persistent)return c=U(e,n,i,a,o),c?c.close.bind(c):void 0;if(s)R(s,P,i),R(s,F,a),R(s,I,o);else{if(c=U(e,n,W.bind(null,t,P),a,W.bind(null,t,I)),!c)return;c.on(M.ERROR,async n=>{let r=W.bind(null,t,F);if(s&&(s.watcherUnusable=!0),E&&n.code===`EPERM`)try{await(await ee(e,`r`)).close(),r(n)}catch{}else r(n)}),s={listeners:i,errHandlers:a,rawEmitters:o,watcher:c},H.set(t,s)}return()=>{B(s,P,i),B(s,F,a),B(s,I,o),V(s.listeners)&&(s.watcher.close(),H.delete(t),oe.forEach(z(s)),s.watcher=void 0,Object.freeze(s))}},G=new Map,ue=(e,n,i,a)=>{let{listener:o,rawEmitter:s}=a,c=G.get(n),l=c&&c.options;return l&&(l.persistent<i.persistent||l.interval>i.interval)&&(t(n),c=void 0),c?(R(c,P,o),R(c,I,s)):(c={listeners:o,rawEmitters:s,options:i,watcher:r(n,i,(t,r)=>{L(c.rawEmitters,e=>{e(M.CHANGE,n,{curr:t,prev:r})});let i=t.mtimeMs;(t.size!==r.size||i>r.mtimeMs||i===0)&&L(c.listeners,n=>n(e,t))})},G.set(n,c)),()=>{B(c,P,o),B(c,I,s),V(c.listeners)&&(G.delete(n),t(n),c.options=c.watcher=void 0,Object.freeze(c))}};var de=class{fsw;_boundHandleError;constructor(e){this.fsw=e,this._boundHandleError=t=>e._handleError(t)}_watchWithNodeFs(e,t){let n=this.fsw.options,r=a.dirname(e),i=a.basename(e);this.fsw._getWatchedDir(r).add(i);let o=a.resolve(e),s={persistent:n.persistent};t||=w;let c;return n.usePolling?(s.interval=n.interval!==n.binaryInterval&&ce(i)?n.binaryInterval:n.interval,c=ue(e,o,s,{listener:t,rawEmitter:this.fsw._emitRaw})):c=le(e,o,s,{listener:t,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw}),c}_handleFile(e,t,n){if(this.fsw.closed)return;let r=a.dirname(e),i=a.basename(e),o=this.fsw._getWatchedDir(r),s=t;if(o.has(i))return;let c=async(t,n)=>{if(this.fsw._throttle(`watch`,e,5)){if(!n||n.mtimeMs===0)try{let n=await h(e);if(this.fsw.closed)return;let r=n.atimeMs,i=n.mtimeMs;if((!r||r<=i||i!==s.mtimeMs)&&this.fsw._emit(M.CHANGE,e,n),(D||O||k)&&s.ino!==n.ino){this.fsw._closeFile(t),s=n;let r=this._watchWithNodeFs(e,c);r&&this.fsw._addPathCloser(t,r)}else s=n}catch{this.fsw._remove(r,i)}else if(o.has(i)){let t=n.atimeMs,r=n.mtimeMs;(!t||t<=r||r!==s.mtimeMs)&&this.fsw._emit(M.CHANGE,e,n),s=n}}},l=this._watchWithNodeFs(e,c);if(!(n&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(e)){if(!this.fsw._throttle(M.ADD,e,0))return;this.fsw._emit(M.ADD,e,t)}return l}async _handleSymlink(e,t,n,r){if(this.fsw.closed)return;let i=e.fullPath,a=this.fsw._getWatchedDir(t);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let t;try{t=await m(n)}catch{return this.fsw._emitReady(),!0}return this.fsw.closed?void 0:(a.has(r)?this.fsw._symlinkPaths.get(i)!==t&&(this.fsw._symlinkPaths.set(i,t),this.fsw._emit(M.CHANGE,n,e.stats)):(a.add(r),this.fsw._symlinkPaths.set(i,t),this.fsw._emit(M.ADD,n,e.stats)),this.fsw._emitReady(),!0)}if(this.fsw._symlinkPaths.has(i))return!0;this.fsw._symlinkPaths.set(i,!0)}_handleRead(e,t,n,r,i,o,s){e=a.join(e,``);let c=r?`${e}:${r}`:e;if(s=this.fsw._throttle(`readdir`,c,1e3),!s)return;let l=this.fsw._getWatchedDir(n.path),u=new Set,d=this.fsw._readdirp(e,{fileFilter:e=>n.filterPath(e),directoryFilter:e=>n.filterDir(e)});if(d)return d.on(`data`,async s=>{if(this.fsw.closed){d=void 0;return}let c=s.path,f=a.join(e,c);if(u.add(c),!(s.stats.isSymbolicLink()&&await this._handleSymlink(s,e,f,c))){if(this.fsw.closed){d=void 0;return}(c===r||!r&&!l.has(c))&&(this.fsw._incrReadyCount(),f=a.join(i,a.relative(i,f)),this._addToNodeFs(f,t,n,o+1))}}).on(M.ERROR,this._boundHandleError),new Promise((t,a)=>{if(!d)return a();d.once(`end`,()=>{if(this.fsw.closed){d=void 0;return}let a=s?s.clear():!1;t(void 0),l.getChildren().filter(t=>t!==e&&!u.has(t)).forEach(t=>{this.fsw._remove(e,t)}),d=void 0,a&&this._handleRead(e,!1,n,r,i,o,s)})})}async _handleDir(e,t,n,r,i,o,s){let c=this.fsw._getWatchedDir(a.dirname(e)),l=c.has(a.basename(e));!(n&&this.fsw.options.ignoreInitial)&&!i&&!l&&this.fsw._emit(M.ADD_DIR,e,t),c.add(a.basename(e)),this.fsw._getWatchedDir(e);let u,d=this.fsw.options.depth;if((d==null||r<=d)&&!this.fsw._symlinkPaths.has(s)){if(!i&&(await this._handleRead(e,n,o,i,e,r,void 0),this.fsw.closed))return;u=this._watchWithNodeFs(e,(t,n)=>{n&&n.mtimeMs===0||this._handleRead(t,!1,o,i,e,r,void 0)})}return u}async _addToNodeFs(e,t,n,r,i){let o=this.fsw._emitReady;if(this.fsw._isIgnored(e)||this.fsw.closed)return o(),!1;let s=this.fsw._getWatchHelpers(e);n&&(s.filterPath=e=>n.filterPath(e),s.filterDir=e=>n.filterDir(e));try{let n=await N[s.statMethod](s.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(s.watchPath,n))return o(),!1;let c=this.fsw.options.followSymlinks,l;if(n.isDirectory()){let o=a.resolve(e),u=c?await m(e):e;if(this.fsw.closed||(l=await this._handleDir(s.watchPath,n,t,r,i,s,u),this.fsw.closed))return;o!==u&&u!==void 0&&this.fsw._symlinkPaths.set(o,u)}else if(n.isSymbolicLink()){let i=c?await m(e):e;if(this.fsw.closed)return;let o=a.dirname(s.watchPath);if(this.fsw._getWatchedDir(o).add(s.watchPath),this.fsw._emit(M.ADD,s.watchPath,n),l=await this._handleDir(o,n,t,r,e,s,i),this.fsw.closed)return;i!==void 0&&this.fsw._symlinkPaths.set(a.resolve(e),i)}else l=this._handleFile(s.watchPath,n,t);return o(),l&&this.fsw._addPathCloser(e,l),!1}catch(t){if(this.fsw._handleError(t))return o(),e}}};
|
|
2
2
|
/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
|
|
3
3
|
const fe=/\\/g,K=/\/\//g,pe=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,me=/^\.[/\\]/;function q(e){return Array.isArray(e)?e:[e]}const J=e=>typeof e==`object`&&!!e&&!(e instanceof RegExp);function he(e){return typeof e==`function`?e:typeof e==`string`?t=>e===t:e instanceof RegExp?t=>e.test(t):typeof e==`object`&&e?t=>{if(e.path===t)return!0;if(e.recursive){let n=a.relative(e.path,t);return n?!n.startsWith(`..`)&&!a.isAbsolute(n):!1}return!1}:()=>!1}function ge(e){if(typeof e!=`string`)throw Error(`string expected`);e=a.normalize(e),e=e.replace(/\\/g,`/`);let t=!1;return e.startsWith(`//`)&&(t=!0),e=e.replace(K,`/`),t&&(e=`/`+e),e}function Y(e,t,n){let r=ge(t);for(let t=0;t<e.length;t++){let i=e[t];if(i(r,n))return!0}return!1}function _e(e,t){if(e==null)throw TypeError(`anymatch: specify first argument`);let n=q(e).map(e=>he(e));return t==null?(e,t)=>Y(n,e,t):Y(n,t)}const X=e=>{let t=q(e).flat();if(!t.every(e=>typeof e==`string`))throw TypeError(`Non-string provided as watch path: ${t}`);return t.map(Q)},Z=e=>{let t=e.replace(fe,`/`),n=!1;return t.startsWith(`//`)&&(n=!0),t=t.replace(K,`/`),n&&(t=`/`+t),t},Q=e=>Z(a.normalize(Z(e))),$=(e=``)=>t=>typeof t==`string`?Q(a.isAbsolute(t)?t:a.join(e,t)):t,ve=(e,t)=>a.isAbsolute(e)?e:a.join(t,e),ye=Object.freeze(new Set);var be=class{path;_removeWatcher;items;constructor(e,t){this.path=e,this._removeWatcher=t,this.items=new Set}add(e){let{items:t}=this;t&&e!==`.`&&e!==`..`&&t.add(e)}async remove(e){let{items:t}=this;if(!t||(t.delete(e),t.size>0))return;let n=this.path;try{await p(n)}catch{this._removeWatcher&&this._removeWatcher(a.dirname(n),a.basename(n))}}has(e){let{items:t}=this;if(t)return t.has(e)}getChildren(){let{items:e}=this;return e?[...e.values()]:[]}dispose(){this.items.clear(),this.path=``,this._removeWatcher=w,this.items=ye,Object.freeze(this)}},xe=class{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(e,t,n){this.fsw=n;let r=e;this.path=e=e.replace(me,``),this.watchPath=r,this.fullWatchPath=a.resolve(r),this.dirParts=[],this.dirParts.forEach(e=>{e.length>1&&e.pop()}),this.followSymlinks=t,this.statMethod=t?`stat`:`lstat`}entryPath(e){return a.join(this.watchPath,a.relative(this.watchPath,e.fullPath))}filterPath(e){let{stats:t}=e;if(t&&t.isSymbolicLink())return this.filterDir(e);let n=this.entryPath(e);return this.fsw._isntIgnored(n,t)&&this.fsw._hasReadPermissions(t)}filterDir(e){return this.fsw._isntIgnored(this.entryPath(e),e.stats)}},Se=class extends u{closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(e={}){super(),this.closed=!1,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=!1;let t=e.awaitWriteFinish,n={stabilityThreshold:2e3,pollInterval:100},r={persistent:!0,ignoreInitial:!1,ignorePermissionErrors:!1,interval:100,binaryInterval:300,followSymlinks:!0,usePolling:!1,atomic:!0,...e,ignored:e.ignored?q(e.ignored):q([]),awaitWriteFinish:t===!0?n:typeof t==`object`?{...n,...t}:!1};A&&(r.usePolling=!0),r.atomic===void 0&&(r.atomic=!r.usePolling);let i=process.env.CHOKIDAR_USEPOLLING;if(i!==void 0){let e=i.toLowerCase();e===`false`||e===`0`?r.usePolling=!1:e===`true`||e===`1`?r.usePolling=!0:r.usePolling=!!e}let a=process.env.CHOKIDAR_INTERVAL;a&&(r.interval=Number.parseInt(a,10));let o=0;this._emitReady=()=>{o++,o>=this._readyCount&&(this._emitReady=w,this._readyEmitted=!0,process.nextTick(()=>this.emit(j.READY)))},this._emitRaw=(...e)=>this.emit(j.RAW,...e),this._boundRemove=this._remove.bind(this),this.options=r,this._nodeFsHandler=new de(this),Object.freeze(r)}_addIgnoredPath(e){if(J(e)){for(let t of this._ignoredPaths)if(J(t)&&t.path===e.path&&t.recursive===e.recursive)return}this._ignoredPaths.add(e)}_removeIgnoredPath(e){if(this._ignoredPaths.delete(e),typeof e==`string`)for(let t of this._ignoredPaths)J(t)&&t.path===e&&this._ignoredPaths.delete(t)}add(e,t,n){let{cwd:r}=this.options;this.closed=!1,this._closePromise=void 0;let i=X(e);return r&&(i=i.map(e=>ve(e,r))),i.forEach(e=>{this._removeIgnoredPath(e)}),this._userIgnored=void 0,this._readyCount||=0,this._readyCount+=i.length,Promise.all(i.map(async e=>{let r=await this._nodeFsHandler._addToNodeFs(e,!n,void 0,0,t);return r&&this._emitReady(),r})).then(e=>{this.closed||e.forEach(e=>{e&&this.add(a.dirname(e),a.basename(t||e))})}),this}unwatch(e){if(this.closed)return this;let t=X(e),{cwd:n}=this.options;return t.forEach(e=>{!a.isAbsolute(e)&&!this._closers.has(e)&&(n&&(e=a.join(n,e)),e=a.resolve(e)),this._closePath(e),this._addIgnoredPath(e),this._watched.has(e)&&this._addIgnoredPath({path:e,recursive:!0}),this._userIgnored=void 0}),this}close(){if(this._closePromise)return this._closePromise;this.closed=!0,this.removeAllListeners();let e=[];return this._closers.forEach(t=>t.forEach(t=>{let n=t();n instanceof Promise&&e.push(n)})),this._streams.forEach(e=>e.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=!1,this._watched.forEach(e=>e.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=e.length?Promise.all(e).then(()=>void 0):Promise.resolve(),this._closePromise}getWatched(){let e={};return this._watched.forEach((t,n)=>{let r=(this.options.cwd?a.relative(this.options.cwd,n):n)||`.`;e[r]=t.getChildren().sort()}),e}emitWithAll(e,t){this.emit(e,...t),e!==j.ERROR&&this.emit(j.ALL,e,...t)}async _emit(e,t,n){if(this.closed)return;let r=this.options;E&&(t=a.normalize(t)),r.cwd&&(t=a.relative(r.cwd,t));let i=[t];n!=null&&i.push(n);let o=r.awaitWriteFinish,s;if(o&&(s=this._pendingWrites.get(t)))return s.lastChange=new Date,this;if(r.atomic){if(e===j.UNLINK)return this._pendingUnlinks.set(t,[e,...i]),setTimeout(()=>{this._pendingUnlinks.forEach((e,t)=>{this.emit(...e),this.emit(j.ALL,...e),this._pendingUnlinks.delete(t)})},typeof r.atomic==`number`?r.atomic:100),this;e===j.ADD&&this._pendingUnlinks.has(t)&&(e=j.CHANGE,this._pendingUnlinks.delete(t))}if(o&&(e===j.ADD||e===j.CHANGE)&&this._readyEmitted)return this._awaitWriteFinish(t,o.stabilityThreshold,e,(t,n)=>{t?(e=j.ERROR,i[0]=t,this.emitWithAll(e,i)):n&&(i.length>1?i[1]=n:i.push(n),this.emitWithAll(e,i))}),this;if(e===j.CHANGE&&!this._throttle(j.CHANGE,t,50))return this;if(r.alwaysStat&&n===void 0&&(e===j.ADD||e===j.ADD_DIR||e===j.CHANGE)){let e=r.cwd?a.join(r.cwd,t):t,n;try{n=await h(e)}catch{}if(!n||this.closed)return;i.push(n)}return this.emitWithAll(e,i),this}_handleError(e){let t=e&&e.code;return e&&t!==`ENOENT`&&t!==`ENOTDIR`&&(!this.options.ignorePermissionErrors||t!==`EPERM`&&t!==`EACCES`)&&this.emit(j.ERROR,e),e||this.closed}_throttle(e,t,n){this._throttled.has(e)||this._throttled.set(e,new Map);let r=this._throttled.get(e);if(!r)throw Error(`invalid throttle`);let i=r.get(t);if(i)return i.count++,!1;let a,o=()=>{let e=r.get(t),n=e?e.count:0;return r.delete(t),clearTimeout(a),e&&clearTimeout(e.timeoutObject),n};a=setTimeout(o,n);let s={timeoutObject:a,clear:o,count:0};return r.set(t,s),s}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(t,n,r,i){let o=this.options.awaitWriteFinish;if(typeof o!=`object`)return;let s=o.pollInterval,c,l=t;this.options.cwd&&!a.isAbsolute(t)&&(l=a.join(this.options.cwd,t));let u=new Date,d=this._pendingWrites;function f(r){e(l,(e,a)=>{if(e||!d.has(t)){e&&e.code!==`ENOENT`&&i(e);return}let o=Number(new Date);r&&a.size!==r.size&&(d.get(t).lastChange=o),o-d.get(t).lastChange>=n?(d.delete(t),i(void 0,a)):c=setTimeout(f,s,a)})}d.has(t)||(d.set(t,{lastChange:u,cancelWait:()=>(d.delete(t),clearTimeout(c),r)}),c=setTimeout(f,s))}_isIgnored(e,t){if(this.options.atomic&&pe.test(e))return!0;if(!this._userIgnored){let{cwd:e}=this.options,t=(this.options.ignored||[]).map($(e));this._userIgnored=_e([...[...this._ignoredPaths].map($(e)),...t],void 0)}return this._userIgnored(e,t)}_isntIgnored(e,t){return!this._isIgnored(e,t)}_getWatchHelpers(e){return new xe(e,this.options.followSymlinks,this)}_getWatchedDir(e){let t=a.resolve(e);return this._watched.has(t)||this._watched.set(t,new be(t,this._boundRemove)),this._watched.get(t)}_hasReadPermissions(e){return this.options.ignorePermissionErrors?!0:!!(Number(e.mode)&256)}_remove(e,t,n){let r=a.join(e,t),i=a.resolve(r);if(n??=this._watched.has(r)||this._watched.has(i),!this._throttle(`remove`,r,100))return;!n&&this._watched.size===1&&this.add(e,t,!0),this._getWatchedDir(r).getChildren().forEach(e=>this._remove(r,e));let o=this._getWatchedDir(e),s=o.has(t);o.remove(t),this._symlinkPaths.has(i)&&this._symlinkPaths.delete(i);let c=r;if(this.options.cwd&&(c=a.relative(this.options.cwd,r)),this.options.awaitWriteFinish&&this._pendingWrites.has(c)&&this._pendingWrites.get(c).cancelWait()===j.ADD)return;this._watched.delete(r),this._watched.delete(i);let l=n?j.UNLINK_DIR:j.UNLINK;s&&!this._isIgnored(r)&&this._emit(l,r),this._closePath(r)}_closePath(e){this._closeFile(e);let t=a.dirname(e);this._getWatchedDir(t).remove(a.basename(e))}_closeFile(e){let t=this._closers.get(e);t&&(t.forEach(e=>e()),this._closers.delete(e))}_addPathCloser(e,t){if(!t)return;let n=this._closers.get(e);n||(n=[],this._closers.set(e,n)),n.push(t)}_readdirp(e,t){if(this.closed)return;let n=ae(e,{type:j.ALL,alwaysStat:!0,lstat:!0,...t,depth:0});return this._streams.add(n),n.once(`close`,()=>{n=void 0}),n.once(`end`,()=>{n&&=(this._streams.delete(n),void 0)}),n}};function Ce(e,t={}){let n=new Se(t);return n.add(e),n}export{Ce as watch};
|
|
4
|
-
//# sourceMappingURL=chokidar-
|
|
4
|
+
//# sourceMappingURL=chokidar-Z9-8o-jG.mjs.map
|