@hevmind/ask 0.1.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/README.md +116 -0
- package/bin/ask-launcher.mjs +110 -0
- package/bin/ask.mjs +4 -0
- package/openapi.yaml +363 -0
- package/package.json +61 -0
- package/skills/build-digest/SKILL.md +164 -0
- package/src/components/SearchOverlay.astro +1375 -0
- package/src/components/markdown.ts +107 -0
- package/src/digest/build.ts +432 -0
- package/src/digest/cli.ts +148 -0
- package/src/digest/expand.ts +24 -0
- package/src/digest/facts.ts +77 -0
- package/src/digest/frontmatter.ts +41 -0
- package/src/digest/read.ts +63 -0
- package/src/digest/schema.ts +185 -0
- package/src/digest/verify.ts +116 -0
- package/src/endpoint.ts +247 -0
- package/src/index.ts +2 -0
- package/src/integration.ts +146 -0
- package/src/llm.ts +239 -0
- package/src/observability.ts +213 -0
- package/src/search/chunk.ts +137 -0
- package/src/search/index.ts +44 -0
- package/src/search/loop.ts +525 -0
- package/src/search/prefilter.ts +93 -0
- package/src/types.ts +99 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-digest
|
|
3
|
+
description: >-
|
|
4
|
+
Build the @hevmind/ask ask digest (.hev-ask/digest.json) for an Astro docs site
|
|
5
|
+
using your Claude Code subscription instead of an ANTHROPIC_API_KEY. Use when
|
|
6
|
+
the user asks to build, rebuild, or refresh the hev ask digest, knowledge
|
|
7
|
+
graph, KG, or search index, or after docs content changes. Runs `ask digest
|
|
8
|
+
corpus --shards-dir`, distils each shard in a fresh context, and runs
|
|
9
|
+
`ask digest assemble --input-dir`.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Build the hev ask digest
|
|
13
|
+
|
|
14
|
+
`@hevmind/ask` searches an Astro docs site. Its agentic loop, keyword ranking, and
|
|
15
|
+
suggested questions are powered by a committed ask digest at
|
|
16
|
+
`.hev-ask/digest.json`. Only the **distillation** needs a model — the node
|
|
17
|
+
structure, verbatim facts, overview map, and content hash are computed
|
|
18
|
+
deterministically by the CLI. This skill performs that distillation here, in
|
|
19
|
+
the user's subscription, so it costs **no API tokens on their own key**.
|
|
20
|
+
|
|
21
|
+
The corpus is split into **shards** (~200KB of text each, along slug-prefix
|
|
22
|
+
boundaries) and each shard is distilled in its own fresh context. Corpus size
|
|
23
|
+
is therefore never a context-limit problem — a bigger site just means more
|
|
24
|
+
shards. All state lives on disk in `.hev-ask/shards/`, so the build can be
|
|
25
|
+
stopped, resumed, and incrementally refreshed: after content edits, only the
|
|
26
|
+
shards whose content changed need re-distilling.
|
|
27
|
+
|
|
28
|
+
Run every command from the **site root** (the directory whose `astro.config.*`
|
|
29
|
+
registers `hevAsk()`). Prefer `pnpm exec ask digest …`; fall back to
|
|
30
|
+
`npx -p @hevmind/ask ask digest …` if pnpm isn't used. Pass the same content flags
|
|
31
|
+
the site's integration uses if they differ from the defaults (`--collection`,
|
|
32
|
+
`--base-path`, `--chunk-heading-depth`, `--content-glob`, `--digest-path`);
|
|
33
|
+
they must match across `corpus` and `assemble`.
|
|
34
|
+
|
|
35
|
+
**Never read a shard input file into the orchestrating context** (they hold
|
|
36
|
+
the full corpus text). The orchestrator works only from command output,
|
|
37
|
+
`manifest.json`, and `status`; shard contents are read by the per-shard
|
|
38
|
+
distillation agents.
|
|
39
|
+
|
|
40
|
+
## Steps
|
|
41
|
+
|
|
42
|
+
1. **Shard the corpus.**
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pnpm exec ask digest corpus --shards-dir .hev-ask/shards
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Deterministic and keyless. Writes one `input-<shard-id>.json` per shard
|
|
49
|
+
plus `manifest.json`, and reports `(N sections, M shards, P pending,
|
|
50
|
+
up-to-date|needs-rebuild)`. Re-running after content edits is safe and is
|
|
51
|
+
the refresh mechanism: unchanged shards keep their distillations; changed
|
|
52
|
+
ones are marked pending again.
|
|
53
|
+
|
|
54
|
+
2. **Check state.** If the corpus reported `up-to-date` AND `0 pending`, the
|
|
55
|
+
committed digest already matches the content — **stop here** and tell the
|
|
56
|
+
user nothing needs rebuilding. Otherwise:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
pnpm exec ask digest status --shards-dir .hev-ask/shards
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
lists which shards are `pending` or `stale` (distilled against older
|
|
63
|
+
content). Both need distilling.
|
|
64
|
+
|
|
65
|
+
3. **Distil each pending/stale shard in a fresh context.** Spawn one agent per
|
|
66
|
+
shard (run a few in parallel; don't read shard contents yourself). Each
|
|
67
|
+
agent gets this prompt, with `<id>` filled in:
|
|
68
|
+
|
|
69
|
+
> Read ONLY `.hev-ask/shards/input-<id>.json` (from the site root). It has
|
|
70
|
+
> `shardId`, `shardHash`, and a `sections` array of `{ id, url, title,
|
|
71
|
+
> text }`. Write `.hev-ask/shards/distill-<id>.json` with exactly this
|
|
72
|
+
> shape:
|
|
73
|
+
>
|
|
74
|
+
> ```json
|
|
75
|
+
> {
|
|
76
|
+
> "shardHash": "<copy the shardHash from the input file verbatim>",
|
|
77
|
+
> "notes": "5-10 lines: what this shard covers, its key concepts, and how users talk about them.",
|
|
78
|
+
> "glossary": [
|
|
79
|
+
> { "term": "ask digest", "aliases": ["digest", "kg"], "definition": "One-line definition." }
|
|
80
|
+
> ],
|
|
81
|
+
> "summaries": [
|
|
82
|
+
> { "id": "<exact section id from sections>", "summary": "1-3 sentence distillation." }
|
|
83
|
+
> ]
|
|
84
|
+
> }
|
|
85
|
+
> ```
|
|
86
|
+
>
|
|
87
|
+
> Rules:
|
|
88
|
+
> - Emit **one `summaries` entry for every `id`** in `sections` — no more,
|
|
89
|
+
> no fewer. Use the exact id strings.
|
|
90
|
+
> - Summaries are what the search agent reasons from: faithful,
|
|
91
|
+
> self-contained, 1-3 sentences. **Paraphrase prose, but never restate
|
|
92
|
+
> code, flags, commands, or exact identifiers** — those are extracted
|
|
93
|
+
> verbatim by the CLI and would only drift if you retyped them.
|
|
94
|
+
> - `glossary`: at most the ~10 terms from this shard a real user would
|
|
95
|
+
> type (aliases like `k8s` for `kubernetes`); one-line definitions. The
|
|
96
|
+
> CLI dedupes and caps the merged glossary.
|
|
97
|
+
> - `notes` is NOT user-facing — it feeds a later site-wide synthesis pass.
|
|
98
|
+
> - Your final message: just the shard id and how many summaries you wrote.
|
|
99
|
+
|
|
100
|
+
If the run is interrupted, just re-run from step 1 — disk state is the
|
|
101
|
+
source of truth and `status` shows what's left.
|
|
102
|
+
|
|
103
|
+
4. **Synthesize the global context.** Once every shard is distilled, extract
|
|
104
|
+
only the `notes` fields (small) — never the full distill files:
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
python3 -c "import json,glob; [print('##', f.split('distill-')[1].removesuffix('.json'), '\n' + json.load(open(f)).get('notes','')) for f in sorted(glob.glob('.hev-ask/shards/distill-*.json'))]"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
From those notes, write `.hev-ask/shards/global.json`:
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"context": "Compact markdown orientation: what the product/site is, its core concepts and feature areas, and how users talk about them.",
|
|
115
|
+
"suggestions": [
|
|
116
|
+
"A natural question a reader might type that these docs answer."
|
|
117
|
+
],
|
|
118
|
+
"glossary": []
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`suggestions`: 3-5 questions phrased the way a user would ask them, each
|
|
123
|
+
genuinely answerable from these docs (they show in the overlay on open).
|
|
124
|
+
|
|
125
|
+
5. **Assemble.**
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
pnpm exec ask digest assemble --input-dir .hev-ask/shards
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Merges every current shard distillation with the global synthesis, derives
|
|
132
|
+
the deterministic parts, and writes `.hev-ask/digest.json`. Sections from
|
|
133
|
+
undistilled shards fall back to plain excerpts and are reported — the
|
|
134
|
+
digest stays usable mid-wave, but aim for 0 pending before committing.
|
|
135
|
+
|
|
136
|
+
6. **Verify.**
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
pnpm exec ask digest verify
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Anchor drift is fatal; coverage/fidelity warnings are informational.
|
|
143
|
+
|
|
144
|
+
7. **Clean up and commit.** The shards directory is a local cache — it is the
|
|
145
|
+
resume/refresh state, so keep it on disk but out of git, and drop the bulky
|
|
146
|
+
input files (regenerated by `corpus` any time):
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
rm -f .hev-ask/shards/input-*.json
|
|
150
|
+
git check-ignore -q .hev-ask/shards || echo ".hev-ask/shards/" >> .gitignore
|
|
151
|
+
git add .gitignore .hev-ask/digest.json
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Only `.hev-ask/digest.json` is committed.
|
|
155
|
+
|
|
156
|
+
## Notes
|
|
157
|
+
|
|
158
|
+
- A small site may produce a single shard; the flow is the same (you can
|
|
159
|
+
distil it yourself instead of spawning an agent — a single shard's input is
|
|
160
|
+
small enough to read directly).
|
|
161
|
+
- `--shard-bytes` (default 200000) tunes shard size if a site's sections are
|
|
162
|
+
unusually dense.
|
|
163
|
+
- If `corpus` fails because no content is found, you're likely not in the
|
|
164
|
+
site root, or the collection name isn't `docs` — pass `--collection <name>`.
|