@dikolab/kbdb 0.1.5 → 0.2.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 +30 -9
- package/dist/cli.cjs +181 -50
- package/dist/cli.cjs.map +3 -3
- package/dist/cli.mjs +181 -50
- package/dist/cli.mjs.map +3 -3
- package/dist/kbdb-worker.cjs +283 -29
- package/dist/kbdb-worker.cjs.map +4 -4
- package/dist/mod.cjs +13 -2
- package/dist/mod.cjs.map +2 -2
- package/dist/mod.mjs +13 -2
- package/dist/mod.mjs.map +2 -2
- package/dist/src/shared/cli/functions/format-output.function.d.ts +7 -7
- package/dist/src/shared/cli/functions/run-search.function.d.ts +25 -16
- package/dist/src/shared/cli/index.d.ts +1 -1
- package/dist/src/shared/cli/typings/cli-options.interface.d.ts +2 -0
- package/dist/src/shared/cli/typings/search-display.model.d.ts +25 -7
- package/dist/src/shared/mcp/functions/handle-recall.function.d.ts +29 -0
- package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +30 -11
- package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
- package/dist/src/shared/wasm-codec/functions/decode-recall-result.function.d.ts +28 -0
- package/dist/src/shared/wasm-codec/functions/decode-scored-results.function.d.ts +14 -7
- package/dist/src/shared/wasm-codec/functions/encode-recall-params.function.d.ts +21 -0
- package/dist/src/shared/wasm-codec/functions/encode-search-params.function.d.ts +1 -1
- package/dist/src/shared/wasm-codec/index.d.ts +5 -2
- package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +13 -3
- package/dist/src/shared/worker-client/index.d.ts +2 -1
- package/dist/src/shared/worker-client/typings/recall-result.model.d.ts +94 -0
- package/dist/src/shared/worker-client/typings/search-params.model.d.ts +2 -0
- package/dist/src/shared/worker-client/typings/search-result.model.d.ts +23 -7
- package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +1 -0
- package/dist/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
- package/dist/wasm/fs-database/kbdb_fs_database.js +30 -0
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
- package/dist/wasm/kb-worker/kbdb_worker.d.ts +38 -0
- package/dist/wasm/kb-worker/kbdb_worker.js +56 -0
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/dist/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
- package/dist/worker.mjs +283 -29
- package/dist/worker.mjs.map +4 -4
- package/docs/details/README.md +26 -0
- package/docs/details/cli.md +608 -0
- package/docs/details/library-api.md +406 -0
- package/docs/details/mcp-server.md +430 -0
- package/docs/details/search-and-ranking.md +457 -0
- package/docs/details/storage.md +529 -0
- package/docs/goals/agents.md +751 -0
- package/docs/goals/architecture.svg +198 -0
- package/docs/goals/cli.md +2308 -0
- package/docs/goals/content-composer.md +609 -0
- package/docs/goals/content-parser.md +279 -0
- package/docs/goals/database.md +1452 -0
- package/docs/goals/document.md +368 -0
- package/docs/goals/mcp.md +1467 -0
- package/docs/goals/overview.md +124 -0
- package/docs/goals/query-parser.md +271 -0
- package/docs/goals/query-result.md +693 -0
- package/docs/goals/skills.md +738 -0
- package/docs/goals/worker-client.md +944 -0
- package/docs/goals/worker-daemon.md +1447 -0
- package/docs/modules/overview.md +298 -0
- package/docs/modules/rust/fs-database/functions/document.md +48 -0
- package/docs/modules/rust/fs-database/functions/integrity.md +68 -0
- package/docs/modules/rust/fs-database/functions/io.md +87 -0
- package/docs/modules/rust/fs-database/functions/module.md +22 -0
- package/docs/modules/rust/fs-database/functions/query-exec.md +44 -0
- package/docs/modules/rust/fs-database/functions/section.md +59 -0
- package/docs/modules/rust/fs-database/indexes/btree.md +35 -0
- package/docs/modules/rust/fs-database/indexes/corpus.md +61 -0
- package/docs/modules/rust/fs-database/indexes/inverted.md +60 -0
- package/docs/modules/rust/fs-database/indexes/module.md +64 -0
- package/docs/modules/rust/fs-database/indexes/positional.md +39 -0
- package/docs/modules/rust/fs-database/module.md +149 -0
- package/docs/modules/rust/fs-database/types/catalog.md +53 -0
- package/docs/modules/rust/fs-database/types/module.md +12 -0
- package/docs/modules/rust/fs-database/types/section.md +101 -0
- package/docs/modules/rust/kb-worker/functions/compose.md +57 -0
- package/docs/modules/rust/kb-worker/functions/module.md +20 -0
- package/docs/modules/rust/kb-worker/functions/retrieve.md +194 -0
- package/docs/modules/rust/kb-worker/functions/search.md +173 -0
- package/docs/modules/rust/kb-worker/functions/write.md +172 -0
- package/docs/modules/rust/kb-worker/module.md +171 -0
- package/docs/modules/rust/kb-worker/types/cache.md +90 -0
- package/docs/modules/rust/kb-worker/types/context.md +26 -0
- package/docs/modules/rust/kb-worker/types/module.md +16 -0
- package/docs/modules/rust/kb-worker/types/status.md +29 -0
- package/docs/modules/rust/kb-worker/types/token.md +50 -0
- package/docs/modules/rust/overview.md +495 -0
- package/docs/modules/rust/query-parser/functions/extract.md +56 -0
- package/docs/modules/rust/query-parser/functions/module.md +16 -0
- package/docs/modules/rust/query-parser/functions/parse.md +33 -0
- package/docs/modules/rust/query-parser/functions/pipeline.md +103 -0
- package/docs/modules/rust/query-parser/functions/rank.md +85 -0
- package/docs/modules/rust/query-parser/module.md +136 -0
- package/docs/modules/rust/query-parser/types/cache.md +39 -0
- package/docs/modules/rust/query-parser/types/keyphrase.md +60 -0
- package/docs/modules/rust/query-parser/types/module.md +17 -0
- package/docs/modules/rust/query-parser/types/token.md +42 -0
- package/docs/modules/rust/shared/content-composer/functions.md +114 -0
- package/docs/modules/rust/shared/content-composer/module.md +147 -0
- package/docs/modules/rust/shared/content-composer/types.md +93 -0
- package/docs/modules/rust/shared/content-parser/functions.md +72 -0
- package/docs/modules/rust/shared/content-parser/module.md +99 -0
- package/docs/modules/rust/shared/content-parser/types.md +71 -0
- package/docs/modules/rust/shared/corpus/module.md +24 -0
- package/docs/modules/rust/shared/corpus/types.md +141 -0
- package/docs/modules/rust/shared/document/module.md +25 -0
- package/docs/modules/rust/shared/document/types.md +154 -0
- package/docs/modules/rust/shared/encode/module.md +22 -0
- package/docs/modules/rust/shared/encode/traits.md +304 -0
- package/docs/modules/rust/shared/error/module.md +28 -0
- package/docs/modules/rust/shared/error/types.md +302 -0
- package/docs/modules/rust/shared/kbid/module.md +24 -0
- package/docs/modules/rust/shared/kbid/types.md +147 -0
- package/docs/modules/rust/shared/memory/functions.md +209 -0
- package/docs/modules/rust/shared/memory/module.md +24 -0
- package/docs/modules/rust/shared/module.md +168 -0
- package/docs/modules/rust/shared/query/module.md +27 -0
- package/docs/modules/rust/shared/query/types.md +236 -0
- package/docs/modules/rust/shared/section/module.md +25 -0
- package/docs/modules/rust/shared/section/types.md +294 -0
- package/docs/modules/rust/shared/term/module.md +25 -0
- package/docs/modules/rust/shared/term/types.md +139 -0
- package/docs/modules/typescript/cli.md +129 -0
- package/docs/modules/typescript/kbdb-worker.md +135 -0
- package/docs/modules/typescript/overview.md +378 -0
- package/docs/modules/typescript/shared/cli/constants.md +23 -0
- package/docs/modules/typescript/shared/cli/functions.md +630 -0
- package/docs/modules/typescript/shared/cli/module.md +125 -0
- package/docs/modules/typescript/shared/cli/typings.md +172 -0
- package/docs/modules/typescript/shared/hash/functions.md +20 -0
- package/docs/modules/typescript/shared/hash/module.md +21 -0
- package/docs/modules/typescript/shared/mcp/classes.md +179 -0
- package/docs/modules/typescript/shared/mcp/functions.md +386 -0
- package/docs/modules/typescript/shared/mcp/module.md +160 -0
- package/docs/modules/typescript/shared/mcp/typings.md +522 -0
- package/docs/modules/typescript/shared/module.md +94 -0
- package/docs/modules/typescript/shared/platform/functions.md +42 -0
- package/docs/modules/typescript/shared/platform/module.md +25 -0
- package/docs/modules/typescript/shared/runtime/functions.md +26 -0
- package/docs/modules/typescript/shared/runtime/module.md +27 -0
- package/docs/modules/typescript/shared/runtime/typings.md +13 -0
- package/docs/modules/typescript/shared/version/module.md +27 -0
- package/docs/modules/typescript/shared/wasm-codec/functions.md +391 -0
- package/docs/modules/typescript/shared/wasm-codec/module.md +98 -0
- package/docs/modules/typescript/shared/worker-client/classes.md +264 -0
- package/docs/modules/typescript/shared/worker-client/functions.md +175 -0
- package/docs/modules/typescript/shared/worker-client/module.md +84 -0
- package/docs/modules/typescript/shared/worker-client/typings.md +508 -0
- package/docs/modules/typescript/shared/worker-daemon/classes.md +239 -0
- package/docs/modules/typescript/shared/worker-daemon/constants.md +37 -0
- package/docs/modules/typescript/shared/worker-daemon/functions.md +221 -0
- package/docs/modules/typescript/shared/worker-daemon/module.md +112 -0
- package/docs/modules/typescript/shared/worker-daemon/typings.md +126 -0
- package/docs/overview.md +188 -0
- package/docs/release-notes/0.1.0.md +189 -0
- package/docs/release-notes/0.1.1.md +46 -0
- package/docs/release-notes/0.1.2.md +38 -0
- package/docs/release-notes/0.1.3.md +42 -0
- package/docs/release-notes/0.2.0.md +147 -0
- package/docs/release-notes/README.md +9 -0
- package/package.json +8 -2
- package/src/shared/cli/functions/dispatch-command.function.ts +3 -3
- package/src/shared/cli/functions/format-output.function.ts +41 -34
- package/src/shared/cli/functions/parse-args.function.ts +7 -0
- package/src/shared/cli/functions/run-search.function.ts +53 -27
- package/src/shared/cli/index.ts +4 -1
- package/src/shared/cli/typings/cli-options.interface.ts +2 -0
- package/src/shared/cli/typings/search-display.model.ts +26 -7
- package/src/shared/mcp/functions/create-tool-definitions.function.ts +64 -4
- package/src/shared/mcp/functions/handle-recall.function.ts +66 -0
- package/src/shared/mcp/functions/handle-tool-call.function.ts +11 -1
- package/src/shared/mcp/typings/mcp-client.interface.ts +33 -15
- package/src/shared/version/constants/version.constant.ts +1 -1
- package/src/shared/wasm-codec/functions/decode-recall-result.function.ts +267 -0
- package/src/shared/wasm-codec/functions/decode-scored-results.function.ts +81 -27
- package/src/shared/wasm-codec/functions/encode-recall-params.function.ts +68 -0
- package/src/shared/wasm-codec/functions/encode-search-params.function.ts +4 -1
- package/src/shared/wasm-codec/index.ts +11 -3
- package/src/shared/worker-client/classes/worker-client.class.ts +24 -4
- package/src/shared/worker-client/index.ts +11 -1
- package/src/shared/worker-client/typings/recall-result.model.ts +98 -0
- package/src/shared/worker-client/typings/search-params.model.ts +2 -0
- package/src/shared/worker-client/typings/search-result.model.ts +24 -7
- package/src/shared/worker-daemon/classes/worker-daemon.class.ts +25 -4
- package/src/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
- package/src/wasm/fs-database/kbdb_fs_database.js +30 -0
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
- package/src/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
- package/src/wasm/kb-worker/kbdb_worker.d.ts +38 -0
- package/src/wasm/kb-worker/kbdb_worker.js +56 -0
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
- package/src/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# 0.2.0
|
|
2
|
+
|
|
3
|
+
*Minor release -- 2026-06-21*
|
|
4
|
+
|
|
5
|
+
Adds progressive context recall, paginated search
|
|
6
|
+
results with rich metadata, and a bidirectional
|
|
7
|
+
reference graph. These features give AI agents
|
|
8
|
+
the ability to explore related content across
|
|
9
|
+
sections and documents without loading everything
|
|
10
|
+
at once.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## New Features
|
|
15
|
+
|
|
16
|
+
- **Recall with layered context (depths 0--3)** --
|
|
17
|
+
New `recall` command (CLI), MCP tool, and IPC
|
|
18
|
+
method. Accepts a `kbid` (or `kbids` for batch)
|
|
19
|
+
and a `depth` parameter that controls how much
|
|
20
|
+
context is returned:
|
|
21
|
+
- Depth 0: section content, heading, type, docids
|
|
22
|
+
- Depth 1: adds parent documents and
|
|
23
|
+
back-references
|
|
24
|
+
- Depth 2: adds sibling sections and forward
|
|
25
|
+
references
|
|
26
|
+
- Depth 3: referenced sections include full
|
|
27
|
+
content
|
|
28
|
+
|
|
29
|
+
- **Paginated search results** -- Search now
|
|
30
|
+
returns a `PagedSearchResult` envelope:
|
|
31
|
+
`{ items, total, offset, limit, has_more }`.
|
|
32
|
+
New `--offset` / `-o` CLI flag. The `offset`
|
|
33
|
+
parameter is available in MCP and IPC as well.
|
|
34
|
+
|
|
35
|
+
- **Rich search result metadata** -- Each search
|
|
36
|
+
result item now includes `heading`, `type`,
|
|
37
|
+
`snippet` (KWIC ~150 chars around matched terms),
|
|
38
|
+
`matched_terms`, and `docids`. Replaces the
|
|
39
|
+
previous `matches: [{term, frequency}]` format.
|
|
40
|
+
|
|
41
|
+
- **Bidirectional reference graph** -- New
|
|
42
|
+
`references.idx` tracks content-marker references
|
|
43
|
+
(`$(link: ...)`, `$(doclink: ...)`, etc.) between
|
|
44
|
+
sections. New WASM exports `db_get_forward_refs`
|
|
45
|
+
and `db_get_back_refs`. Built automatically on
|
|
46
|
+
`learn`/`update`, cleaned on `unlearn`,
|
|
47
|
+
regenerated on `rebuild`.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Improvements
|
|
52
|
+
|
|
53
|
+
- **KWIC snippet generation** -- New
|
|
54
|
+
`extract_kwic_snippet()` in the Rust engine
|
|
55
|
+
produces ~150-character context windows around
|
|
56
|
+
matched terms with case-insensitive matching,
|
|
57
|
+
Unicode-safe boundaries, and ellipsis markers.
|
|
58
|
+
|
|
59
|
+
- **MCP search strips score** -- The MCP layer
|
|
60
|
+
omits the `score` field from search results.
|
|
61
|
+
Rank order is the signal for AI agents; raw
|
|
62
|
+
scores are kept in CLI and IPC output for
|
|
63
|
+
debugging.
|
|
64
|
+
|
|
65
|
+
- **Tool annotations** -- All 18 MCP tool
|
|
66
|
+
definitions now include `openWorldHint: false`,
|
|
67
|
+
`readOnlyHint`, `destructiveHint`, and
|
|
68
|
+
`idempotentHint` annotations per the MCP spec.
|
|
69
|
+
|
|
70
|
+
- **Text format paging** -- CLI text output now
|
|
71
|
+
shows a paging footer:
|
|
72
|
+
`Showing 1--20 of 42 results. Use --offset 20 to see more.`
|
|
73
|
+
|
|
74
|
+
- **MCP tool descriptions** -- `search` guides
|
|
75
|
+
agents to use `recall` for full content.
|
|
76
|
+
`retrieve` updated to prefer `recall`.
|
|
77
|
+
|
|
78
|
+
- **Documentation included in package** -- Both
|
|
79
|
+
npm and JSR packages now ship `docs/details/`,
|
|
80
|
+
`docs/goals/`, `docs/modules/`,
|
|
81
|
+
`docs/release-notes/`, and `docs/overview.md`.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Testing
|
|
86
|
+
|
|
87
|
+
- **383 e2e assertions (Node.js), 378 (Deno)** --
|
|
88
|
+
up from ~300. All pass with 0 failures.
|
|
89
|
+
|
|
90
|
+
- **Recall depth testing** -- Cross-referenced
|
|
91
|
+
test data (sections with `$(link: ...)` markers)
|
|
92
|
+
validates depth 0--3 field presence across CLI,
|
|
93
|
+
MCP, and worker IPC.
|
|
94
|
+
|
|
95
|
+
- **Response shape validation** -- Every field in
|
|
96
|
+
the public API is asserted: paged search envelope,
|
|
97
|
+
search item metadata, recall depth fields, skill
|
|
98
|
+
and agent CRUD responses, MCP prompts protocol,
|
|
99
|
+
resource templates, and completions.
|
|
100
|
+
|
|
101
|
+
- **Rust unit tests** -- 21+ new tests for KWIC
|
|
102
|
+
snippet extraction, matched-terms ordering,
|
|
103
|
+
paged result pagination, and section matching.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Breaking Changes
|
|
108
|
+
|
|
109
|
+
- **Search result shape changed** -- Results are
|
|
110
|
+
now wrapped in a `PagedSearchResult` envelope.
|
|
111
|
+
Code that expected a flat array of results must
|
|
112
|
+
read `result.items` instead. Each item's
|
|
113
|
+
`matches` array is replaced by `snippet`,
|
|
114
|
+
`matched_terms`, `heading`, `type`, and `docids`.
|
|
115
|
+
|
|
116
|
+
- **Codec exports renamed** -- `decodeScoredResults`
|
|
117
|
+
is now `decodePagedSearchResult`. `ScoredResult`
|
|
118
|
+
is now `SectionMatch`.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Internal
|
|
123
|
+
|
|
124
|
+
- Rust engine: reference tracking wired into
|
|
125
|
+
`db_add_section`, `db_update_section`, and
|
|
126
|
+
`db_remove_section`. `worker_search` parses
|
|
127
|
+
4-part format (query/mode/limit/offset).
|
|
128
|
+
`worker_recall` WASM export added.
|
|
129
|
+
- `content-creator` renamed to `content-composer`
|
|
130
|
+
across all code and docs.
|
|
131
|
+
- WASM binaries rebuilt (~8KB and ~35KB larger).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Upgrade
|
|
136
|
+
|
|
137
|
+
```sh
|
|
138
|
+
# Node.js
|
|
139
|
+
npm install -g @dikolab/kbdb@0.2.0
|
|
140
|
+
|
|
141
|
+
# Deno
|
|
142
|
+
deno install -Agf jsr:@dikolab/kbdb/cli
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Review the **Breaking Changes** section above if
|
|
146
|
+
you use the library API or parse search results
|
|
147
|
+
programmatically.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Release Notes
|
|
2
|
+
|
|
3
|
+
## Releases
|
|
4
|
+
|
|
5
|
+
- [0.2.0](0.2.0.md) -- Recall, paginated search, reference graph
|
|
6
|
+
- [0.1.3](0.1.3.md) -- Include WASM binaries in JSR package
|
|
7
|
+
- [0.1.2](0.1.2.md) -- Fix WASM loading from JSR
|
|
8
|
+
- [0.1.1](0.1.1.md) -- Deno type fix, build pipeline cleanup
|
|
9
|
+
- [0.1.0](0.1.0.md) -- Initial release
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dikolab/kbdb",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI tool and MCP server for a file-based knowledge base database",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -24,7 +24,13 @@
|
|
|
24
24
|
"mod.ts",
|
|
25
25
|
"src/**/*",
|
|
26
26
|
"!src/**/*.spec.ts",
|
|
27
|
-
"LICENSE"
|
|
27
|
+
"LICENSE",
|
|
28
|
+
"README.md",
|
|
29
|
+
"docs/details/**/*.md",
|
|
30
|
+
"docs/goals/**",
|
|
31
|
+
"docs/modules/**/*.md",
|
|
32
|
+
"docs/release-notes/**/*.md",
|
|
33
|
+
"docs/overview.md"
|
|
28
34
|
],
|
|
29
35
|
"type": "module",
|
|
30
36
|
"main": "./dist/mod.cjs",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CliOptions } from '../typings/cli-options.interface.ts';
|
|
2
2
|
import type { CommandResult } from '../typings/command-result.model.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { PagedSearchDisplay } from '../typings/search-display.model.ts';
|
|
4
4
|
import type { LearnIO } from './run-learn.function.ts';
|
|
5
5
|
import type { SearchClient } from './run-search.function.ts';
|
|
6
6
|
import type { LearnClient } from './run-learn.function.ts';
|
|
@@ -323,10 +323,10 @@ async function handleDbMigrate(
|
|
|
323
323
|
*/
|
|
324
324
|
async function hydrateSearchPreviews(
|
|
325
325
|
client: ContentClient,
|
|
326
|
-
|
|
326
|
+
paged: PagedSearchDisplay,
|
|
327
327
|
): Promise<void> {
|
|
328
328
|
await Promise.all(
|
|
329
|
-
|
|
329
|
+
paged.items.map(async (result) => {
|
|
330
330
|
try {
|
|
331
331
|
const contentResult = await client.content([result.kbid]);
|
|
332
332
|
result.preview = contentResult.data;
|
|
@@ -1,63 +1,70 @@
|
|
|
1
1
|
import type { OutputFormat } from '../typings/cli-options.interface.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PagedSearchDisplay } from '../typings/search-display.model.ts';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Serialises
|
|
5
|
+
* Serialises a paged search result into the requested output
|
|
6
6
|
* format string.
|
|
7
7
|
*
|
|
8
|
-
* - `'json'` -- pretty-printed JSON
|
|
9
|
-
* - `'text'` -- numbered human-readable list
|
|
10
|
-
* - `'mcp'` -- JSON envelope compatible with MCP protocol
|
|
8
|
+
* - `'json'` -- pretty-printed JSON envelope
|
|
9
|
+
* - `'text'` -- numbered human-readable list with paging footer
|
|
10
|
+
* - `'mcp'` -- JSON envelope compatible with MCP protocol
|
|
11
11
|
*
|
|
12
|
-
* @param
|
|
12
|
+
* @param paged - paginated search results to format
|
|
13
13
|
* @param format - target output format
|
|
14
14
|
* @returns formatted string ready for stdout
|
|
15
15
|
*/
|
|
16
16
|
export function formatOutput(
|
|
17
|
-
|
|
17
|
+
paged: PagedSearchDisplay,
|
|
18
18
|
format: OutputFormat,
|
|
19
19
|
): string {
|
|
20
20
|
switch (format) {
|
|
21
21
|
case 'json':
|
|
22
|
-
return JSON.stringify(
|
|
22
|
+
return JSON.stringify(paged, null, 2);
|
|
23
23
|
case 'text':
|
|
24
|
-
return formatText(
|
|
24
|
+
return formatText(paged);
|
|
25
25
|
case 'mcp':
|
|
26
|
-
return formatMcp(
|
|
26
|
+
return formatMcp(paged);
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
`
|
|
43
|
-
`
|
|
44
|
-
|
|
30
|
+
function formatText(paged: PagedSearchDisplay): string {
|
|
31
|
+
if (paged.items.length === 0) return 'No results found.';
|
|
32
|
+
const start = paged.offset + 1;
|
|
33
|
+
const end = paged.offset + paged.items.length;
|
|
34
|
+
|
|
35
|
+
const lines = paged.items
|
|
36
|
+
.map((r, i) => {
|
|
37
|
+
const num = paged.offset + i + 1;
|
|
38
|
+
const heading = r.heading ?? '(untitled)';
|
|
39
|
+
const terms = r.matched_terms.join(', ');
|
|
40
|
+
return (
|
|
41
|
+
`${String(num)}. [${r.kbid}] ${heading}` +
|
|
42
|
+
` (score: ${r.score.toFixed(4)})\n` +
|
|
43
|
+
` ${r.snippet || r.preview || '(no snippet)'}\n` +
|
|
44
|
+
` type: ${r.type}` +
|
|
45
|
+
` terms: ${terms}`
|
|
46
|
+
);
|
|
47
|
+
})
|
|
45
48
|
.join('\n\n');
|
|
49
|
+
|
|
50
|
+
const footer =
|
|
51
|
+
`\nShowing ${String(start)}-${String(end)}` +
|
|
52
|
+
` of ${String(paged.total)} results`;
|
|
53
|
+
const hint = paged.has_more
|
|
54
|
+
? `\nUse --offset ${String(end)} to see more`
|
|
55
|
+
: '';
|
|
56
|
+
|
|
57
|
+
return lines + footer + hint;
|
|
46
58
|
}
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
* Renders results as a JSON envelope for MCP protocol consumers.
|
|
50
|
-
*
|
|
51
|
-
* @param results - search results to render
|
|
52
|
-
*/
|
|
53
|
-
function formatMcp(results: SearchDisplay[]): string {
|
|
60
|
+
function formatMcp(paged: PagedSearchDisplay): string {
|
|
54
61
|
return JSON.stringify({
|
|
55
62
|
type: 'text',
|
|
56
|
-
text:
|
|
63
|
+
text: paged.items
|
|
57
64
|
.map(
|
|
58
65
|
(r) =>
|
|
59
|
-
`[${r.kbid}]
|
|
60
|
-
` — ${r.preview}`,
|
|
66
|
+
`[${r.kbid}] ${r.heading ?? '(untitled)'}` +
|
|
67
|
+
` — ${r.snippet || r.preview}`,
|
|
61
68
|
)
|
|
62
69
|
.join('\n'),
|
|
63
70
|
});
|
|
@@ -87,6 +87,13 @@ export function parseArgs(argv: string[]): CliOptions {
|
|
|
87
87
|
options.limit =
|
|
88
88
|
parseInt(argv[++i] ?? '', 10) || DEFAULT_LIMIT;
|
|
89
89
|
break;
|
|
90
|
+
case '--offset':
|
|
91
|
+
case '-o':
|
|
92
|
+
options.offset = Math.max(
|
|
93
|
+
0,
|
|
94
|
+
parseInt(argv[++i] ?? '', 10) || 0,
|
|
95
|
+
);
|
|
96
|
+
break;
|
|
90
97
|
case '--title':
|
|
91
98
|
options.title = argv[++i];
|
|
92
99
|
break;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CliOptions } from '../typings/cli-options.interface.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PagedSearchDisplay } from '../typings/search-display.model.ts';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Minimal client interface required by `runSearch`.
|
|
@@ -9,54 +9,80 @@ import type { SearchDisplay } from '../typings/search-display.model.ts';
|
|
|
9
9
|
*/
|
|
10
10
|
export interface SearchClient {
|
|
11
11
|
/**
|
|
12
|
-
* Searches the knowledge base and returns
|
|
12
|
+
* Searches the knowledge base and returns paginated results.
|
|
13
13
|
*
|
|
14
|
-
* @param params - query, mode, and
|
|
14
|
+
* @param params - query, mode, limit, and offset
|
|
15
15
|
*/
|
|
16
16
|
search(params: {
|
|
17
17
|
query: string;
|
|
18
18
|
mode?: string;
|
|
19
19
|
limit?: number;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
readonly
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
offset?: number;
|
|
21
|
+
}): Promise<{
|
|
22
|
+
readonly items: readonly {
|
|
23
|
+
readonly kbid: string;
|
|
24
|
+
readonly heading: string | null;
|
|
25
|
+
readonly type: string;
|
|
26
|
+
readonly docids: readonly string[];
|
|
27
|
+
readonly score: number;
|
|
28
|
+
readonly snippet: string;
|
|
29
|
+
readonly matched_terms: readonly string[];
|
|
30
|
+
}[];
|
|
31
|
+
readonly total: number;
|
|
32
|
+
readonly offset: number;
|
|
33
|
+
readonly limit: number;
|
|
34
|
+
readonly has_more: boolean;
|
|
35
|
+
}>;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
|
-
* Executes a search query via the provided client and maps the
|
|
34
|
-
* daemon results to the `
|
|
39
|
+
* Executes a search query via the provided client and maps the
|
|
40
|
+
* daemon results to the `PagedSearchDisplay` format used by the
|
|
41
|
+
* CLI.
|
|
35
42
|
*
|
|
36
|
-
* Returns an empty
|
|
37
|
-
* contains no query terms.
|
|
43
|
+
* Returns an empty paged result without calling the client when
|
|
44
|
+
* `options.args` contains no query terms.
|
|
38
45
|
*
|
|
39
46
|
* @param client - search client to delegate to
|
|
40
|
-
* @param options - parsed CLI options supplying query args and
|
|
41
|
-
* parameters
|
|
47
|
+
* @param options - parsed CLI options supplying query args and
|
|
48
|
+
* search parameters
|
|
42
49
|
*/
|
|
43
50
|
export async function runSearch(
|
|
44
51
|
client: SearchClient,
|
|
45
52
|
options: CliOptions,
|
|
46
|
-
): Promise<
|
|
53
|
+
): Promise<PagedSearchDisplay> {
|
|
47
54
|
const query = options.args.join(' ').trim();
|
|
48
|
-
if (!query)
|
|
55
|
+
if (!query) {
|
|
56
|
+
return {
|
|
57
|
+
items: [],
|
|
58
|
+
total: 0,
|
|
59
|
+
offset: 0,
|
|
60
|
+
limit: options.limit,
|
|
61
|
+
has_more: false,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
49
64
|
|
|
50
65
|
const results = await client.search({
|
|
51
66
|
query,
|
|
52
67
|
mode: options.mode,
|
|
53
68
|
limit: options.limit,
|
|
69
|
+
offset: options.offset,
|
|
54
70
|
});
|
|
55
71
|
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
72
|
+
return {
|
|
73
|
+
items: results.items.map((r) => ({
|
|
74
|
+
kbid: r.kbid,
|
|
75
|
+
heading: r.heading,
|
|
76
|
+
type: r.type,
|
|
77
|
+
docids: r.docids,
|
|
78
|
+
score: r.score,
|
|
79
|
+
snippet: r.snippet,
|
|
80
|
+
matched_terms: r.matched_terms,
|
|
81
|
+
preview: '',
|
|
82
|
+
})),
|
|
83
|
+
total: results.total,
|
|
84
|
+
offset: results.offset,
|
|
85
|
+
limit: results.limit,
|
|
86
|
+
has_more: results.has_more,
|
|
87
|
+
};
|
|
62
88
|
}
|
package/src/shared/cli/index.ts
CHANGED
|
@@ -23,7 +23,10 @@ export type {
|
|
|
23
23
|
SearchMode,
|
|
24
24
|
} from './typings/cli-options.interface.ts';
|
|
25
25
|
export type { LearnResult } from './typings/learn-result.model.ts';
|
|
26
|
-
export type {
|
|
26
|
+
export type {
|
|
27
|
+
SearchDisplay,
|
|
28
|
+
PagedSearchDisplay,
|
|
29
|
+
} from './typings/search-display.model.ts';
|
|
27
30
|
export type { SearchClient } from './functions/run-search.function.ts';
|
|
28
31
|
export type { LearnClient } from './functions/run-learn.function.ts';
|
|
29
32
|
export type {
|
|
@@ -31,6 +31,8 @@ export interface CliOptions {
|
|
|
31
31
|
mode: SearchMode;
|
|
32
32
|
/** Maximum number of results to return. Defaults to 20. */
|
|
33
33
|
limit: number;
|
|
34
|
+
/** Number of results to skip for pagination. */
|
|
35
|
+
offset?: number;
|
|
34
36
|
/** Section title for learn command. */
|
|
35
37
|
title?: string;
|
|
36
38
|
/** Section description for learn command. */
|
|
@@ -2,16 +2,35 @@
|
|
|
2
2
|
export interface SearchDisplay {
|
|
3
3
|
/** Knowledge-base identifier of the matched section. */
|
|
4
4
|
kbid: string;
|
|
5
|
+
/** Section heading, or null when untitled. */
|
|
6
|
+
heading: string | null;
|
|
7
|
+
/** MIME type of the section content. */
|
|
8
|
+
type: string;
|
|
9
|
+
/** Document IDs this section belongs to. */
|
|
10
|
+
docids: readonly string[];
|
|
5
11
|
/** Relevance score assigned by the ranking engine. */
|
|
6
12
|
score: number;
|
|
13
|
+
/** KWIC snippet from the WASM engine (~150 chars). */
|
|
14
|
+
snippet: string;
|
|
15
|
+
/** Query terms that matched within this section. */
|
|
16
|
+
matched_terms: readonly string[];
|
|
7
17
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
18
|
+
* CLI-side truncated content preview for terminal display.
|
|
19
|
+
* Populated when `--content` / `-c` is used.
|
|
10
20
|
*/
|
|
11
21
|
preview: string;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Paginated search display envelope for CLI output. */
|
|
25
|
+
export interface PagedSearchDisplay {
|
|
26
|
+
/** Search results for the current page. */
|
|
27
|
+
items: SearchDisplay[];
|
|
28
|
+
/** Total number of matches across all pages. */
|
|
29
|
+
total: number;
|
|
30
|
+
/** Number of results skipped. */
|
|
31
|
+
offset: number;
|
|
32
|
+
/** Maximum results per page. */
|
|
33
|
+
limit: number;
|
|
34
|
+
/** Whether more results exist beyond this page. */
|
|
35
|
+
has_more: boolean;
|
|
17
36
|
}
|