ricord 1.0.0
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/LICENSE +21 -0
- package/README.md +213 -0
- package/commands/ricord-flush.md +29 -0
- package/commands/ricord-init.md +129 -0
- package/commands/ricord-lint.md +64 -0
- package/commands/ricord-query.md +71 -0
- package/dist/cli/auth.d.ts +16 -0
- package/dist/cli/auth.js +42 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/bundle.d.ts +25 -0
- package/dist/cli/bundle.js +179 -0
- package/dist/cli/bundle.js.map +1 -0
- package/dist/cli/cache.d.ts +18 -0
- package/dist/cli/cache.js +39 -0
- package/dist/cli/cache.js.map +1 -0
- package/dist/cli/cli.d.ts +21 -0
- package/dist/cli/cli.js +355 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/client.d.ts +12 -0
- package/dist/cli/client.js +35 -0
- package/dist/cli/client.js.map +1 -0
- package/dist/cli/commands/build.d.ts +44 -0
- package/dist/cli/commands/build.js +437 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/curate.d.ts +32 -0
- package/dist/cli/commands/curate.js +154 -0
- package/dist/cli/commands/curate.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +16 -0
- package/dist/cli/commands/doctor.js +92 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/ingest.d.ts +25 -0
- package/dist/cli/commands/ingest.js +121 -0
- package/dist/cli/commands/ingest.js.map +1 -0
- package/dist/cli/commands/install.d.ts +16 -0
- package/dist/cli/commands/install.js +82 -0
- package/dist/cli/commands/install.js.map +1 -0
- package/dist/cli/commands/pull.d.ts +24 -0
- package/dist/cli/commands/pull.js +104 -0
- package/dist/cli/commands/pull.js.map +1 -0
- package/dist/cli/commands/push.d.ts +28 -0
- package/dist/cli/commands/push.js +164 -0
- package/dist/cli/commands/push.js.map +1 -0
- package/dist/cli/commands/rollup.d.ts +21 -0
- package/dist/cli/commands/rollup.js +118 -0
- package/dist/cli/commands/rollup.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +7 -0
- package/dist/cli/commands/setup.js +43 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +15 -0
- package/dist/cli/commands/sync.js +63 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +17 -0
- package/dist/cli/commands/watch.js +87 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/config.d.ts +29 -0
- package/dist/cli/config.js +52 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/extract.d.ts +101 -0
- package/dist/cli/extract.js +216 -0
- package/dist/cli/extract.js.map +1 -0
- package/dist/cli/ingest.d.ts +48 -0
- package/dist/cli/ingest.js +74 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/ledger.d.ts +44 -0
- package/dist/cli/ledger.js +67 -0
- package/dist/cli/ledger.js.map +1 -0
- package/dist/cli/llm.d.ts +21 -0
- package/dist/cli/llm.js +138 -0
- package/dist/cli/llm.js.map +1 -0
- package/dist/cli/parse.d.ts +13 -0
- package/dist/cli/parse.js +188 -0
- package/dist/cli/parse.js.map +1 -0
- package/dist/cli/run-explore.d.ts +56 -0
- package/dist/cli/run-explore.js +229 -0
- package/dist/cli/run-explore.js.map +1 -0
- package/dist/cli/summarize.d.ts +15 -0
- package/dist/cli/summarize.js +49 -0
- package/dist/cli/summarize.js.map +1 -0
- package/dist/cli/uninstall.d.ts +6 -0
- package/dist/cli/uninstall.js +277 -0
- package/dist/cli/uninstall.js.map +1 -0
- package/dist/cli/walk.d.ts +13 -0
- package/dist/cli/walk.js +62 -0
- package/dist/cli/walk.js.map +1 -0
- package/dist/cli/walker.d.ts +14 -0
- package/dist/cli/walker.js +120 -0
- package/dist/cli/walker.js.map +1 -0
- package/dist/hooks/pre-compact.d.ts +15 -0
- package/dist/hooks/pre-compact.js +127 -0
- package/dist/hooks/pre-compact.js.map +1 -0
- package/dist/hooks/pre-tool-use.d.ts +15 -0
- package/dist/hooks/pre-tool-use.js +25 -0
- package/dist/hooks/pre-tool-use.js.map +1 -0
- package/dist/hooks/session-end.d.ts +21 -0
- package/dist/hooks/session-end.js +186 -0
- package/dist/hooks/session-end.js.map +1 -0
- package/dist/hooks/session-start.d.ts +15 -0
- package/dist/hooks/session-start.js +233 -0
- package/dist/hooks/session-start.js.map +1 -0
- package/dist/hooks/turn-end-post.d.ts +17 -0
- package/dist/hooks/turn-end-post.js +66 -0
- package/dist/hooks/turn-end-post.js.map +1 -0
- package/dist/hooks/turn-end.d.ts +29 -0
- package/dist/hooks/turn-end.js +295 -0
- package/dist/hooks/turn-end.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +1547 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +45 -0
- package/dist/init.js +839 -0
- package/dist/init.js.map +1 -0
- package/dist/lib/active-project.d.ts +14 -0
- package/dist/lib/active-project.js +65 -0
- package/dist/lib/active-project.js.map +1 -0
- package/dist/lib/buffer.d.ts +34 -0
- package/dist/lib/buffer.js +79 -0
- package/dist/lib/buffer.js.map +1 -0
- package/dist/scripts/compile.d.ts +25 -0
- package/dist/scripts/compile.js +185 -0
- package/dist/scripts/compile.js.map +1 -0
- package/dist/scripts/config.d.ts +30 -0
- package/dist/scripts/config.js +68 -0
- package/dist/scripts/config.js.map +1 -0
- package/dist/scripts/flush.d.ts +23 -0
- package/dist/scripts/flush.js +230 -0
- package/dist/scripts/flush.js.map +1 -0
- package/dist/scripts/lint.d.ts +21 -0
- package/dist/scripts/lint.js +242 -0
- package/dist/scripts/lint.js.map +1 -0
- package/dist/scripts/utils.d.ts +43 -0
- package/dist/scripts/utils.js +165 -0
- package/dist/scripts/utils.js.map +1 -0
- package/package.json +74 -0
- package/scripts/postinstall.mjs +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ricord AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# ricord-mcp
|
|
2
|
+
|
|
3
|
+
Persistent memory for AI coding assistants. Ricord gives your AI tools long-term knowledge, episodic memory, a knowledge graph, integrations, and more — all via the [Model Context Protocol](https://modelcontextprotocol.io).
|
|
4
|
+
|
|
5
|
+
This package ships **two binaries**:
|
|
6
|
+
|
|
7
|
+
- **`ricord-mcp`** — the MCP server, for Claude Code / Cursor / Windsurf / VS Code
|
|
8
|
+
- **`ricord`** — a CLI for repo ingestion (`ricord init`), auth (`ricord login`), and account info (`ricord whoami`)
|
|
9
|
+
|
|
10
|
+
Both share `~/.ricord/credentials.json`, so logging in once authorizes everything.
|
|
11
|
+
|
|
12
|
+
## Quick Start (One Command)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx ricord-mcp --setup --client claude --api-key YOUR_API_KEY
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Supported clients: `claude-code`, `claude-desktop`, `cursor`, `windsurf`, `vscode`
|
|
19
|
+
|
|
20
|
+
This auto-writes the correct config file for your editor. Get your API key at [ricord.ai/dashboard/api-keys](https://ricord.ai/dashboard/api-keys).
|
|
21
|
+
|
|
22
|
+
### Manual Setup
|
|
23
|
+
|
|
24
|
+
<details>
|
|
25
|
+
<summary>Claude Code</summary>
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
claude mcp add ricord -- npx ricord-mcp --api-key YOUR_API_KEY
|
|
29
|
+
```
|
|
30
|
+
</details>
|
|
31
|
+
|
|
32
|
+
<details>
|
|
33
|
+
<summary>Claude Desktop</summary>
|
|
34
|
+
|
|
35
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"mcpServers": {
|
|
40
|
+
"ricord": {
|
|
41
|
+
"command": "npx",
|
|
42
|
+
"args": ["ricord-mcp", "--api-key", "YOUR_API_KEY"]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
</details>
|
|
48
|
+
|
|
49
|
+
<details>
|
|
50
|
+
<summary>Cursor</summary>
|
|
51
|
+
|
|
52
|
+
Add to `.cursor/mcp.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"ricord": {
|
|
58
|
+
"command": "npx",
|
|
59
|
+
"args": ["ricord-mcp", "--api-key", "YOUR_API_KEY"]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
</details>
|
|
65
|
+
|
|
66
|
+
<details>
|
|
67
|
+
<summary>Windsurf</summary>
|
|
68
|
+
|
|
69
|
+
Add to `~/.codeium/windsurf/mcp_config.json`:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"ricord": {
|
|
75
|
+
"command": "npx",
|
|
76
|
+
"args": ["ricord-mcp", "--api-key", "YOUR_API_KEY"]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
</details>
|
|
82
|
+
|
|
83
|
+
<details>
|
|
84
|
+
<summary>VS Code (Copilot)</summary>
|
|
85
|
+
|
|
86
|
+
Add to `.vscode/mcp.json`:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"servers": {
|
|
91
|
+
"ricord": {
|
|
92
|
+
"command": "npx",
|
|
93
|
+
"args": ["ricord-mcp", "--api-key", "YOUR_API_KEY"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
</details>
|
|
99
|
+
|
|
100
|
+
## Options
|
|
101
|
+
|
|
102
|
+
| Flag | Env Var | Default | Description |
|
|
103
|
+
|------|---------|---------|-------------|
|
|
104
|
+
| `--api-key` | `RICORD_API_KEY` | required | Your Ricord API key |
|
|
105
|
+
| `--api-base` | `RICORD_API_BASE` | `https://api.ricord.ai` | API endpoint |
|
|
106
|
+
| `--mode` | — | `auto` | `auto`, `manual`, or `hybrid` |
|
|
107
|
+
| `--project` | `RICORD_PROJECT` | — | Project namespace |
|
|
108
|
+
|
|
109
|
+
### Modes
|
|
110
|
+
|
|
111
|
+
- **auto** (default) — AI automatically saves knowledge when you make decisions, state preferences, or discuss architecture
|
|
112
|
+
- **manual** — Only saves when explicitly asked
|
|
113
|
+
- **hybrid** — Auto-extracts knowledge but marks it as draft for your review
|
|
114
|
+
|
|
115
|
+
## Tools (9)
|
|
116
|
+
|
|
117
|
+
| Tool | Description | Credits |
|
|
118
|
+
|------|-------------|---------|
|
|
119
|
+
| `ricord_remember` | Save facts, preferences, decisions, procedures, references, playbooks, anti-patterns, episodes | 3 |
|
|
120
|
+
| `ricord_recall` | Retrieve relevant knowledge (hybrid vector + graph search) | 1 |
|
|
121
|
+
| `ricord_correct` | Update existing knowledge by ID | 3 |
|
|
122
|
+
| `ricord_forget` | Delete knowledge items by ID | 0 |
|
|
123
|
+
| `ricord_list` | Browse stored items with optional type filter | 0 |
|
|
124
|
+
| `ricord_profile` | Get or update aggregated user profile | 0 |
|
|
125
|
+
| `ricord_graph` | Explore knowledge graph: entities, neighborhoods, stats, communities | 0 |
|
|
126
|
+
| `ricord_usage` | Check credit balance, tier, and usage stats | 0 |
|
|
127
|
+
|
|
128
|
+
## Prompts
|
|
129
|
+
|
|
130
|
+
Setup prompts are included for each supported client:
|
|
131
|
+
- `setup-claude-code`
|
|
132
|
+
- `setup-claude-desktop`
|
|
133
|
+
- `setup-cursor`
|
|
134
|
+
- `setup-windsurf`
|
|
135
|
+
- `setup-vscode`
|
|
136
|
+
|
|
137
|
+
## Repo ingestion (`ricord init` + `/ricord-init` slash command)
|
|
138
|
+
|
|
139
|
+
Two paths, one mental model — both follow Karpathy's [LLM Wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) pattern: the agent (LLM) does the bookkeeping, Ricord stores the persistent wiki, and the schema (the slash command markdown) is the protocol.
|
|
140
|
+
|
|
141
|
+
### Path A — inside Claude Code / Codex / OpenCode (preferred)
|
|
142
|
+
|
|
143
|
+
The host agent IS the LLM. Zero external API spend.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# In Claude Code
|
|
147
|
+
/ricord-init . # walks repo, agent extracts each bundle
|
|
148
|
+
/ricord-lint # Karpathy lint: contradictions, orphans, stale claims
|
|
149
|
+
/ricord-query "<question>" # ask the wiki, optionally file the answer back
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Under the hood, `/ricord-init` runs `ricord init --emit-bundles` to stage `.ricord-cache/bundles/*.md` + `manifest.json`, then iterates the manifest: the agent reads each bundle, applies Ricord's canonical extraction prompt (fetched from `/v1/extraction/prompt`) in-context, and POSTs the structured result to `/v1/ingest/extracted`. The agent also maintains `index.md` (catalog) and `log.md` (chronological) per Karpathy's pattern.
|
|
153
|
+
|
|
154
|
+
### Path B — headless CLI (for CI, scripts, no host agent)
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
ricord login # one-time OAuth
|
|
158
|
+
ricord init # uses OPENAI_API_KEY (or ANTHROPIC_API_KEY)
|
|
159
|
+
ricord init --dry-run # walk + parse, no POST
|
|
160
|
+
ricord init --no-ingest # also write summaries to disk for review
|
|
161
|
+
ricord init --llm-model claude-sonnet-4-6 # override LLM
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
In Path B the CLI fetches the same `/v1/extraction/prompt`, runs it through your LLM (~$0.05–0.15 for a small-medium repo with gpt-4o), and POSTs to `/v1/ingest/extracted`. Ricord ships zero generative LLM calls — the only thing the server does is embed bundle text for hybrid search (Vertex, ~$0.025 / 1M chars).
|
|
165
|
+
|
|
166
|
+
Both paths cache by content hash at `<root>/.ricord-cache/`, so re-runs only touch changed directories.
|
|
167
|
+
|
|
168
|
+
After ingest, query your graph:
|
|
169
|
+
- `ricord_search` (MCP tool, or `POST /v1/search`) for hybrid recall
|
|
170
|
+
- `POST /v1/kb/global-query` for GraphRAG map-reduce questions ("What's the architecture?")
|
|
171
|
+
- The Ricord dashboard at [ricord.ai/dashboard](https://ricord.ai/dashboard) for the visual graph
|
|
172
|
+
|
|
173
|
+
## Hooks (opt-in)
|
|
174
|
+
|
|
175
|
+
Ricord ships two Claude Code hook scripts in `dist/hooks/`. Hooks are opt-in — installing the npm package does not activate them. You wire them into your project's `.claude/settings.json` yourself.
|
|
176
|
+
|
|
177
|
+
### Available hooks
|
|
178
|
+
|
|
179
|
+
**SessionStart** — injects a compact memory digest at the start of every Claude session. Adds top SOPs, preferences, recent activity, and open tasks to the system prompt.
|
|
180
|
+
|
|
181
|
+
**PreToolUse** — blocks any Write, Edit, or MultiEdit call whose `file_path` targets `MEMORY.md` or the Claude auto-memory paths (`.claude/projects/*/memory/*`, `.ricord/memory/*`). Prevents the AI from silently overwriting your memory files instead of saving knowledge through the Ricord API.
|
|
182
|
+
|
|
183
|
+
### Wiring hooks into Claude Code
|
|
184
|
+
|
|
185
|
+
Add this to your project's `.claude/settings.json`:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"hooks": {
|
|
190
|
+
"SessionStart": [
|
|
191
|
+
{
|
|
192
|
+
"type": "command",
|
|
193
|
+
"command": "node node_modules/ricord-mcp/dist/hooks/session-start.js"
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
"PreToolUse": [
|
|
197
|
+
{
|
|
198
|
+
"type": "command",
|
|
199
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
200
|
+
"command": "node node_modules/ricord-mcp/dist/hooks/pre-tool-use.js"
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Or, if you installed globally (`npm install -g ricord-mcp`), replace the `node node_modules/...` path with the global install path (e.g. `$(npm root -g)/ricord-mcp/dist/hooks/session-start.js`).
|
|
208
|
+
|
|
209
|
+
**Note:** both hooks require that `RICORD_API_KEY` is set in your environment (or that `~/.ricord/credentials.json` exists from `ricord login`).
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Flush this conversation to Ricord — extract anchors + connections, write graph, and roll up affected pages
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Run the Ricord client-extraction flush flow on the **current conversation**:
|
|
6
|
+
|
|
7
|
+
1. Call `ricord_extract` with `action="fetch_prompt"`. Save the returned `prompt`, `output_schema`, and `schema_version`.
|
|
8
|
+
|
|
9
|
+
2. Build the message list to extract from:
|
|
10
|
+
- All `role=user` messages from this conversation.
|
|
11
|
+
- The **final** `role=assistant` message only (the one followed by Stop, not the intermediate tool-using turns).
|
|
12
|
+
- Skip every other assistant turn, every tool-result block, every system message.
|
|
13
|
+
|
|
14
|
+
3. Apply the prompt locally (do the extraction yourself). Substitute `{TEXT}` with the message list joined by `\n\n` lines of `<role>: <content>`. Emit a JSON object exactly matching `output_schema`: `{ anchors: [...], connections: [...], tasks: [...] }`. Do not invent facts not stated in the messages.
|
|
15
|
+
|
|
16
|
+
4. Call `ricord_extract` with `action="flush"`, passing:
|
|
17
|
+
- `messages`: the same filtered list from step 2
|
|
18
|
+
- `extracted`: your JSON from step 3
|
|
19
|
+
- `extraction_meta`: `{ model: "<your model id>", client: "claude-code", schema_version: <from step 1> }`
|
|
20
|
+
|
|
21
|
+
5. The response includes `pages_written` and any `pages_needing_rollup` ids. For each page id in `pages_needing_rollup`:
|
|
22
|
+
- `GET /v1/kb/pages/<id>/rollup-prompt` (use Bash + curl with the API key from `~/.ricord/credentials.json`)
|
|
23
|
+
- Apply the returned `prompt` locally, emit JSON matching its `output_schema`
|
|
24
|
+
- `POST /v1/kb/pages/<id>/body` with that JSON
|
|
25
|
+
|
|
26
|
+
6. Report a one-line summary:
|
|
27
|
+
`Flushed: <pages_written> pages, <links_written> edges, <rolled_up> rollups, <tasks_written> tasks.`
|
|
28
|
+
|
|
29
|
+
Do not narrate intermediate steps. Just do the work and produce the summary line.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Build / refresh a Ricord knowledge wiki from a repo, URL, file, or conversation — the host LLM (you) is the worker.
|
|
3
|
+
argument-hint: [. | repo | <url> | <file path> | (omit for conversation)]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the worker. Ricord is the **wiki store** and the **schema** (extraction prompt + ingest endpoints). This command is the **protocol** — Karpathy's "LLM Wiki" pattern: the agent (you) reads sources, extracts structured knowledge, and the wiki compounds over time. You never call an external LLM API — *you* are the LLM.
|
|
7
|
+
|
|
8
|
+
Target: `$ARGUMENTS` (default: this conversation).
|
|
9
|
+
|
|
10
|
+
## Source modes
|
|
11
|
+
|
|
12
|
+
- **No argument** → use this conversation. Build a single bundle from `role=user` messages plus the final `role=assistant` message. Skip to "Single-bundle flow" below.
|
|
13
|
+
- **`.` or `repo`** → walk the cwd repo. Use "Multi-bundle flow" below.
|
|
14
|
+
- **URL** (starts with `http://` / `https://`) → `WebFetch` the URL → single bundle.
|
|
15
|
+
- **File path** (anything else) → `Read` it. If it's a directory, treat as repo (multi-bundle).
|
|
16
|
+
|
|
17
|
+
## Multi-bundle flow (repo mode)
|
|
18
|
+
|
|
19
|
+
This is the Karpathy pattern: the wiki is the agent's persistent artifact, refreshed incrementally.
|
|
20
|
+
|
|
21
|
+
### Step 1 — Stage bundles
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ricord init --emit-bundles
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This walks the repo with no LLM, no POST. It writes:
|
|
28
|
+
- `.ricord-cache/bundles/<slug>.md` — one structural summary per meaningful directory
|
|
29
|
+
- `.ricord-cache/manifest.json` — `{root, repo, api_base, bundles:[{rel, slug, bundlePath, chars, hash}]}`
|
|
30
|
+
|
|
31
|
+
If `.ricord-cache/manifest.json` already exists and the user hasn't said "re-walk", reuse it.
|
|
32
|
+
|
|
33
|
+
### Step 2 — Fetch the extraction prompt (once)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
TOKEN=$(jq -r .api_key ~/.ricord/credentials.json)
|
|
37
|
+
API=$(jq -r .api_base ~/.ricord/credentials.json 2>/dev/null || echo https://api.ricord.ai)
|
|
38
|
+
curl -sS -H "Authorization: Bearer $TOKEN" "$API/v1/extraction/prompt" > .ricord-cache/extraction-prompt.json
|
|
39
|
+
SCHEMA_VERSION=$(jq -r .schema_version .ricord-cache/extraction-prompt.json)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Read `.ricord-cache/extraction-prompt.json` once. Hold the `prompt`, `output_schema`, and `caps` in mind for every bundle.
|
|
43
|
+
|
|
44
|
+
### Step 3 — Per bundle, extract + POST
|
|
45
|
+
|
|
46
|
+
For each bundle in the manifest (iterate, don't parallelize with the Task tool — sequential is fine and keeps the log linear):
|
|
47
|
+
|
|
48
|
+
1. `Read` the bundle file at `bundlePath`.
|
|
49
|
+
2. Mentally apply the extraction prompt to the bundle text. Substitute `{TEXT}` with the bundle. Emit JSON matching `output_schema`: `{ anchors: [...], connections: [...], tasks: [...] }`.
|
|
50
|
+
- **Quality bar**: every anchor must be a named concept a human would recognize as a wiki article title (Karpathy: "you are a writer, not a filing clerk").
|
|
51
|
+
- **Type discipline**: `type` must be exactly `"entity"`, `"topic"`, or `"epoch"`. Put finer-grained classification into `subtype` (`"person"`, `"company"`, `"library"`, `"decision"`, `"pattern"`, etc.).
|
|
52
|
+
- **Caps**: max 10 anchors, 30 connections, 5 tasks per bundle. The server rejects more.
|
|
53
|
+
- Skip bundles where there is genuinely nothing to extract (e.g. a 50-char README stub). Note the skip in `log.md` (step 4).
|
|
54
|
+
3. POST via curl. Build the payload as a JSON file first so quoting in the bundle text doesn't corrupt the call:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Write payload to a temp file, then POST it
|
|
58
|
+
Write /tmp/ricord-payload.json with the JSON body
|
|
59
|
+
curl -sS -X POST "$API/v1/ingest/extracted" \
|
|
60
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
61
|
+
-H "Content-Type: application/json" \
|
|
62
|
+
--data-binary @/tmp/ricord-payload.json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The JSON body:
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"messages": [{"role": "user", "content": "<full bundle text>"}],
|
|
69
|
+
"extracted": { "anchors": [...], "connections": [...], "tasks": [...] },
|
|
70
|
+
"extraction_meta": { "model": "<your model id, e.g. claude-opus-4-7>", "client": "claude-code", "schema_version": <from step 2> },
|
|
71
|
+
"tags": ["repo:<repo>", "dir:<rel>", "kind:dir-summary"]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
4. Parse the response. Track `pages_written`, `links_written`, `tasks_written`, and `pages_needing_rollup: [<page_id>, …]`.
|
|
76
|
+
|
|
77
|
+
5. For each `page_id` in `pages_needing_rollup`, do the rollup pair (Karpathy: "the LLM owns the wiki layer entirely"):
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
curl -sS -H "Authorization: Bearer $TOKEN" "$API/v1/kb/pages/$PAGE_ID/rollup-prompt"
|
|
81
|
+
```
|
|
82
|
+
Read the prompt, mentally produce the rollup body (markdown, citing source bundles), write the body JSON to a temp file, then:
|
|
83
|
+
```bash
|
|
84
|
+
curl -sS -X POST "$API/v1/kb/pages/$PAGE_ID/body" \
|
|
85
|
+
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
86
|
+
--data-binary @/tmp/ricord-rollup.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Step 4 — Maintain `index.md` and `log.md`
|
|
90
|
+
|
|
91
|
+
Karpathy's two special files. They live at `.ricord-cache/wiki/`:
|
|
92
|
+
|
|
93
|
+
- **`index.md`** — catalog. After all bundles are POSTed, write a markdown index: heading per anchor type (Entities, Topics, Epochs), bullet list with a one-line description per anchor. If this is a re-run, *update* the existing file: merge new anchors in, drop ones the new ingest didn't see.
|
|
94
|
+
- **`log.md`** — chronological. Append a single block:
|
|
95
|
+
```
|
|
96
|
+
## [<YYYY-MM-DD HH:MM>] ingest | <mode> | <repo or url or file>
|
|
97
|
+
bundles: <N>, anchors: <A>, connections: <C>, tasks: <T>, rollups: <R>, skipped: <S>
|
|
98
|
+
```
|
|
99
|
+
Karpathy's tip: the consistent `## [date]` prefix makes this greppable (`grep "^## \[" log.md | tail -5`).
|
|
100
|
+
|
|
101
|
+
### Step 5 — Final summary
|
|
102
|
+
|
|
103
|
+
Emit one line. Nothing more, no intermediate narration:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
Init repo: <N> bundles → <A> anchors, <C> connections, <T> tasks, <R> rollups. (skipped: <S>)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Single-bundle flow (URL / file / conversation)
|
|
110
|
+
|
|
111
|
+
Skip steps 1, 4-style index. Do:
|
|
112
|
+
|
|
113
|
+
1. Build one bundle text. Cap at ~30 KB.
|
|
114
|
+
2. Fetch the extraction prompt (step 2 above).
|
|
115
|
+
3. Mentally apply prompt → emit JSON → POST `/v1/ingest/extracted` with appropriate tags (`source:url`, `source:file`, or `source:conversation`).
|
|
116
|
+
4. Handle any `pages_needing_rollup`.
|
|
117
|
+
5. Append to `log.md` (in `~/.ricord/log.md` for non-repo modes — there's no repo cwd to anchor to).
|
|
118
|
+
6. Emit a one-line summary.
|
|
119
|
+
|
|
120
|
+
## Hard rules
|
|
121
|
+
|
|
122
|
+
- Do not call any external LLM API. You are the LLM. The whole point is that the agent does the work and Ricord stores it.
|
|
123
|
+
- Do not invent facts the source doesn't state. Skip bundles where there's nothing real to extract; log the skip.
|
|
124
|
+
- Stay within caps (10 anchors / 30 connections / 5 tasks per call). The server enforces them.
|
|
125
|
+
- Do not narrate intermediate work. The user sees the final summary line only. Errors get reported; progress doesn't.
|
|
126
|
+
|
|
127
|
+
## Why this design
|
|
128
|
+
|
|
129
|
+
This is Karpathy's "LLM Wiki" applied to Ricord. The repo is the **raw source** (immutable). Ricord stores the **wiki** (KG pages, edges, tasks). This file is the **schema** — the protocol that turns you from a generic chatbot into a disciplined wiki maintainer. The CLI (`ricord init --emit-bundles`) is just the walker; you do the thinking.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Karpathy lint pass over the Ricord wiki — surface contradictions, orphans, stale claims, missing cross-refs.
|
|
3
|
+
argument-hint: [(optional) topic or anchor name to focus on]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the worker. This is the **Lint** operation from Karpathy's "LLM Wiki": periodically health-check the wiki and surface what's wrong, so it stays useful as it grows.
|
|
7
|
+
|
|
8
|
+
Scope: `$ARGUMENTS` (optional — if given, focus the lint pass on pages mentioning this anchor / topic; if empty, do a full pass).
|
|
9
|
+
|
|
10
|
+
## Sources to read
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
TOKEN=$(jq -r .api_key ~/.ricord/credentials.json)
|
|
14
|
+
API=$(jq -r .api_base ~/.ricord/credentials.json 2>/dev/null || echo https://api.ricord.ai)
|
|
15
|
+
|
|
16
|
+
# Wiki shape
|
|
17
|
+
curl -sS -H "Authorization: Bearer $TOKEN" "$API/v1/kb/pages" > /tmp/ricord-pages.json
|
|
18
|
+
curl -sS -H "Authorization: Bearer $TOKEN" "$API/v1/kb/graph" > /tmp/ricord-graph.json
|
|
19
|
+
|
|
20
|
+
# Recent ingest log (last 10 entries if local file exists)
|
|
21
|
+
[ -f .ricord-cache/wiki/log.md ] && grep "^## \[" .ricord-cache/wiki/log.md | tail -10
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
If a focus argument was given, additionally:
|
|
25
|
+
```bash
|
|
26
|
+
curl -sS -H "Authorization: Bearer $TOKEN" \
|
|
27
|
+
"$API/v1/search?q=$(jq -nr --arg q "$ARGUMENTS" '$q|@uri')&k=20" > /tmp/ricord-focus.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## What to look for
|
|
31
|
+
|
|
32
|
+
Walk the page list + graph and produce a report under five headings. Be specific — cite page titles and ids. Don't pad. If a category is empty, say "(none)" and move on.
|
|
33
|
+
|
|
34
|
+
### 1. Contradictions
|
|
35
|
+
Pages that state mutually exclusive facts about the same anchor. E.g. one page says project X uses Postgres, another says SQLite. List the conflict + both citations.
|
|
36
|
+
|
|
37
|
+
### 2. Stale claims
|
|
38
|
+
Pages whose claims are likely outdated based on more recent ingests. Look at `last_updated` and `mentioned_in_log_since` to spot pages that haven't been touched in a long time but cover anchors that have appeared in recent log entries.
|
|
39
|
+
|
|
40
|
+
### 3. Orphans
|
|
41
|
+
Pages with zero inbound edges in the graph. Either they should be deleted, merged into a broader topic, or new cross-references should be added.
|
|
42
|
+
|
|
43
|
+
### 4. Missing pages
|
|
44
|
+
Concepts mentioned >= 3 times across the wiki (look at anchor mentions in page bodies) that don't yet have their own page. Karpathy: "important concepts mentioned but lacking their own page."
|
|
45
|
+
|
|
46
|
+
### 5. Suggested next steps
|
|
47
|
+
A short list of:
|
|
48
|
+
- Questions worth investigating (gaps in the wiki where the user would benefit from a new source)
|
|
49
|
+
- Sources worth ingesting (URLs / docs / files the wiki keeps pointing at but hasn't absorbed)
|
|
50
|
+
- Cross-references worth adding (page pairs that should link but don't)
|
|
51
|
+
|
|
52
|
+
## Output format
|
|
53
|
+
|
|
54
|
+
A single markdown report. Save it to `.ricord-cache/wiki/lint-<YYYY-MM-DD>.md` and print it. Append a one-liner to `log.md`:
|
|
55
|
+
```
|
|
56
|
+
## [<YYYY-MM-DD HH:MM>] lint | scope: <focus or "full">
|
|
57
|
+
contradictions: <X>, stale: <Y>, orphans: <Z>, missing: <W>, suggestions: <N>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Hard rules
|
|
61
|
+
|
|
62
|
+
- Do not modify wiki pages in a lint pass. Lint surfaces problems; the user decides which to fix.
|
|
63
|
+
- Do not invent contradictions. Two pages saying different things about *different* aspects of an anchor is not a contradiction.
|
|
64
|
+
- Do not narrate. Output the report.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Ask the Ricord wiki a question — search, synthesize an answer with citations, optionally file it back as a new page.
|
|
3
|
+
argument-hint: <your question>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the worker. This is the **Query** operation from Karpathy's "LLM Wiki": ask the wiki a question, get an answer synthesized from the relevant pages, and (optionally) file the answer back into the wiki so explorations compound.
|
|
7
|
+
|
|
8
|
+
Question: `$ARGUMENTS`
|
|
9
|
+
|
|
10
|
+
If `$ARGUMENTS` is empty, ask the user what they want to know.
|
|
11
|
+
|
|
12
|
+
## Search → Read → Synthesize
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
TOKEN=$(jq -r .api_key ~/.ricord/credentials.json)
|
|
16
|
+
API=$(jq -r .api_base ~/.ricord/credentials.json 2>/dev/null || echo https://api.ricord.ai)
|
|
17
|
+
|
|
18
|
+
# Hybrid search: semantic + graph + memory
|
|
19
|
+
Q=$(jq -nr --arg q "$ARGUMENTS" '$q|@uri')
|
|
20
|
+
curl -sS -H "Authorization: Bearer $TOKEN" "$API/v1/search?q=$Q&k=12" > /tmp/ricord-search.json
|
|
21
|
+
|
|
22
|
+
# For each top hit, fetch the full page body if it's a KB page
|
|
23
|
+
# (search results return excerpts; full body lives at /v1/kb/pages/<id>)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For each top-ranked result:
|
|
27
|
+
1. If it's a memory excerpt, use it directly.
|
|
28
|
+
2. If it's a KB page id, fetch the body: `curl -sS -H "Authorization: Bearer $TOKEN" "$API/v1/kb/pages/<id>"`.
|
|
29
|
+
|
|
30
|
+
Synthesize an answer. **Cite every claim** with the source memory id or KB page title in brackets, e.g. `[mem:abc123]` or `[kb: Vertex migration]`. If the wiki doesn't have enough to answer well, say so — don't fabricate.
|
|
31
|
+
|
|
32
|
+
## Output
|
|
33
|
+
|
|
34
|
+
Print the answer as markdown:
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
## <one-line restatement of the question>
|
|
38
|
+
|
|
39
|
+
<2-5 paragraphs of synthesis with inline citations>
|
|
40
|
+
|
|
41
|
+
### Sources
|
|
42
|
+
- [page or memory title 1] (<id>)
|
|
43
|
+
- [page or memory title 2] (<id>)
|
|
44
|
+
- …
|
|
45
|
+
|
|
46
|
+
### Gaps
|
|
47
|
+
- <what the wiki doesn't yet know that would improve this answer, if anything>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## File the answer back? (optional)
|
|
51
|
+
|
|
52
|
+
Karpathy: "good answers can be filed back into the wiki as new pages."
|
|
53
|
+
|
|
54
|
+
After printing, ask the user one short question: **"File this answer back into the wiki as a page? (y/n)"**
|
|
55
|
+
|
|
56
|
+
If yes:
|
|
57
|
+
1. POST to `/v1/ingest/extracted` with the answer text as a single message, treating it as a synthesis source. Tag it `kind:synthesis`, `source:query`, and include the original question in metadata.
|
|
58
|
+
2. Append to `log.md`:
|
|
59
|
+
```
|
|
60
|
+
## [<YYYY-MM-DD HH:MM>] query | filed-back
|
|
61
|
+
question: <the question>
|
|
62
|
+
sources_used: <N>, gaps_noted: <Y/N>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If no, just append the query log entry without the filed-back bit.
|
|
66
|
+
|
|
67
|
+
## Hard rules
|
|
68
|
+
|
|
69
|
+
- Cite everything. Uncited claims are worse than no answer.
|
|
70
|
+
- If the wiki has nothing relevant, say "The wiki doesn't have material on this yet." Suggest sources to ingest.
|
|
71
|
+
- Do not call external search engines or LLM APIs. The only ground truth is the Ricord wiki.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface Credentials {
|
|
2
|
+
api_key: string;
|
|
3
|
+
api_base?: string;
|
|
4
|
+
created_at: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the Ricord token in this order:
|
|
8
|
+
* 1. explicit `--token` flag
|
|
9
|
+
* 2. RICORD_TOKEN env var
|
|
10
|
+
* 3. RICORD_API_KEY env var (matches what `ricord-mcp` reads)
|
|
11
|
+
* 4. ~/.ricord/credentials.json (written by `ricord login`)
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveToken(explicit?: string): string | undefined;
|
|
14
|
+
export declare function resolveApiBase(explicit?: string): string;
|
|
15
|
+
export declare function loadCredentials(): Credentials | null;
|
|
16
|
+
export declare function maskKey(key: string): string;
|
package/dist/cli/auth.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
const CREDENTIALS_FILE = join(homedir(), ".ricord", "credentials.json");
|
|
5
|
+
/**
|
|
6
|
+
* Resolve the Ricord token in this order:
|
|
7
|
+
* 1. explicit `--token` flag
|
|
8
|
+
* 2. RICORD_TOKEN env var
|
|
9
|
+
* 3. RICORD_API_KEY env var (matches what `ricord-mcp` reads)
|
|
10
|
+
* 4. ~/.ricord/credentials.json (written by `ricord login`)
|
|
11
|
+
*/
|
|
12
|
+
export function resolveToken(explicit) {
|
|
13
|
+
if (explicit && explicit.length > 0)
|
|
14
|
+
return explicit;
|
|
15
|
+
if (process.env.RICORD_TOKEN)
|
|
16
|
+
return process.env.RICORD_TOKEN;
|
|
17
|
+
if (process.env.RICORD_API_KEY)
|
|
18
|
+
return process.env.RICORD_API_KEY;
|
|
19
|
+
return loadCredentials()?.api_key;
|
|
20
|
+
}
|
|
21
|
+
export function resolveApiBase(explicit) {
|
|
22
|
+
if (explicit)
|
|
23
|
+
return explicit;
|
|
24
|
+
if (process.env.RICORD_API_BASE)
|
|
25
|
+
return process.env.RICORD_API_BASE;
|
|
26
|
+
return loadCredentials()?.api_base ?? "https://api.ricord.ai";
|
|
27
|
+
}
|
|
28
|
+
export function loadCredentials() {
|
|
29
|
+
try {
|
|
30
|
+
if (existsSync(CREDENTIALS_FILE)) {
|
|
31
|
+
return JSON.parse(readFileSync(CREDENTIALS_FILE, "utf8"));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
export function maskKey(key) {
|
|
38
|
+
if (key.length <= 16)
|
|
39
|
+
return "***";
|
|
40
|
+
return `${key.slice(0, 12)}...${key.slice(-4)}`;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/cli/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQjC,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,kBAAkB,CAAC,CAAC;AAExE;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,QAAiB;IAC5C,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrD,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IAC9D,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAClE,OAAO,eAAe,EAAE,EAAE,OAAO,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAiB;IAC9C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACpE,OAAO,eAAe,EAAE,EAAE,QAAQ,IAAI,uBAAuB,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { DirGroup } from "./walker.js";
|
|
2
|
+
import { ParsedFile } from "./parse.js";
|
|
3
|
+
export interface DirBundle {
|
|
4
|
+
rel: string;
|
|
5
|
+
fileTree: string;
|
|
6
|
+
readme?: string;
|
|
7
|
+
parsedFiles: ParsedFile[];
|
|
8
|
+
externalDeps: string[];
|
|
9
|
+
internalImports: string[];
|
|
10
|
+
usedBy: string[];
|
|
11
|
+
}
|
|
12
|
+
export declare function buildBundle(group: DirGroup, root: string): Promise<DirBundle>;
|
|
13
|
+
/**
|
|
14
|
+
* After all bundles are built, populate `usedBy` on each by inverting the
|
|
15
|
+
* `internalImports` maps. This is the magic that gives the LLM ground-truth
|
|
16
|
+
* "Used by" instead of forcing it to guess.
|
|
17
|
+
*/
|
|
18
|
+
export declare function invertUsedBy(bundles: DirBundle[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Render a bundle to the prompt-ready text the summarizer LLM will see.
|
|
21
|
+
* This is the contract that defines summary quality — keep it tight.
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderBundleForPrompt(b: DirBundle, opts?: {
|
|
24
|
+
maxChars?: number;
|
|
25
|
+
}): string;
|