@gmickel/gno 1.9.0 → 1.10.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/assets/skill/SKILL.md +28 -16
- package/assets/skill/cli-reference.md +30 -0
- package/assets/skill/examples.md +20 -0
- package/assets/skill/mcp-reference.md +7 -1
- package/package.json +1 -1
- package/src/cli/commands/graph.ts +89 -2
- package/src/cli/commands/links.ts +237 -54
- package/src/cli/commands/query.ts +212 -0
- package/src/cli/commands/ref-parser.ts +8 -103
- package/src/cli/options.ts +4 -0
- package/src/cli/program.ts +176 -9
- package/src/config/content-types.ts +14 -0
- package/src/core/graph-query.ts +137 -0
- package/src/core/graph-resolver.ts +117 -0
- package/src/core/ref-parser.ts +145 -0
- package/src/ingestion/frontmatter.ts +95 -2
- package/src/ingestion/sync.ts +281 -1
- package/src/mcp/tools/get.ts +1 -1
- package/src/mcp/tools/index.ts +89 -1
- package/src/mcp/tools/links.ts +83 -1
- package/src/mcp/tools/multi-get.ts +1 -1
- package/src/mcp/tools/query.ts +207 -0
- package/src/pipeline/diagnose.ts +302 -0
- package/src/pipeline/filters.ts +119 -0
- package/src/pipeline/hybrid.ts +90 -17
- package/src/pipeline/types.ts +32 -0
- package/src/publish/export-service.ts +1 -1
- package/src/sdk/documents.ts +2 -2
- package/src/serve/routes/api.ts +194 -0
- package/src/serve/routes/graph.ts +173 -1
- package/src/serve/server.ts +24 -1
- package/src/store/migrations/010-typed-edges.ts +67 -0
- package/src/store/migrations/011-doc-edge-traversal-indexes.ts +30 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +826 -102
- package/src/store/types.ts +141 -0
package/assets/skill/SKILL.md
CHANGED
|
@@ -35,20 +35,20 @@ gno search "your query" # BM25 keyword search
|
|
|
35
35
|
|
|
36
36
|
## Command Overview
|
|
37
37
|
|
|
38
|
-
| Category | Commands | Description
|
|
39
|
-
| ------------ | ---------------------------------------------------------------- |
|
|
40
|
-
| **Search** | `search`, `vsearch`, `query`, `ask` | Find documents by keywords, meaning, or get AI answers
|
|
41
|
-
| **Links** | `links`, `backlinks`, `similar`, `graph`
|
|
42
|
-
| **Retrieve** | `get`, `multi-get`, `ls` | Fetch document content by URI or ID
|
|
43
|
-
| **Index** | `init`, `collection add/list/remove`, `index`, `update`, `embed` | Set up and maintain document index
|
|
44
|
-
| **Tags** | `tags`, `tags add`, `tags rm` | Organize and filter documents
|
|
45
|
-
| **Context** | `context add/list/rm/check` | Add hints to improve search relevance
|
|
46
|
-
| **Models** | `models list/use/pull/clear/path` | Manage local AI models
|
|
47
|
-
| **Serve** | `serve` | Web UI for browsing and searching
|
|
48
|
-
| **Publish** | `publish export` | Export gno.sh publish artifacts
|
|
49
|
-
| **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration
|
|
50
|
-
| **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents
|
|
51
|
-
| **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics
|
|
38
|
+
| Category | Commands | Description |
|
|
39
|
+
| ------------ | ---------------------------------------------------------------- | ------------------------------------------------------ |
|
|
40
|
+
| **Search** | `search`, `vsearch`, `query`, `ask` | Find documents by keywords, meaning, or get AI answers |
|
|
41
|
+
| **Links** | `links`, `backlinks`, `similar`, `graph`, `graph query` | Navigate document relationships and typed connections |
|
|
42
|
+
| **Retrieve** | `get`, `multi-get`, `ls` | Fetch document content by URI or ID |
|
|
43
|
+
| **Index** | `init`, `collection add/list/remove`, `index`, `update`, `embed` | Set up and maintain document index |
|
|
44
|
+
| **Tags** | `tags`, `tags add`, `tags rm` | Organize and filter documents |
|
|
45
|
+
| **Context** | `context add/list/rm/check` | Add hints to improve search relevance |
|
|
46
|
+
| **Models** | `models list/use/pull/clear/path` | Manage local AI models |
|
|
47
|
+
| **Serve** | `serve` | Web UI for browsing and searching |
|
|
48
|
+
| **Publish** | `publish export` | Export gno.sh publish artifacts |
|
|
49
|
+
| **MCP** | `mcp`, `mcp install/uninstall/status` | AI assistant integration |
|
|
50
|
+
| **Skill** | `skill install/uninstall/show/paths` | Install skill for AI agents |
|
|
51
|
+
| **Admin** | `status`, `doctor`, `cleanup`, `reset`, `vec`, `completion` | Maintenance and diagnostics |
|
|
52
52
|
|
|
53
53
|
## Search Modes
|
|
54
54
|
|
|
@@ -137,8 +137,9 @@ When using GNO through MCP, prefer this retrieval order:
|
|
|
137
137
|
|
|
138
138
|
1. Check `gno_status` first when freshness, missing vectors, or stale results are plausible.
|
|
139
139
|
2. Use `gno_query` first for normal content questions. It returns snippets plus `uri`, `docid`, and often `line`; pass `graph: true` only when linked context is worth the extra latency.
|
|
140
|
-
3. Use graph/link expansion for relationship context: `gno_graph_neighbors` for nearby documents, `gno_graph_path` for "how are X and Y connected?", `gno_links`/`gno_backlinks` for one-document link expansion, and `gno_similar` for semantic neighbors. Prefer
|
|
141
|
-
4. Use `
|
|
140
|
+
3. Use graph/link expansion for relationship context: `gno_graph_query` for typed relationship traversal, `gno_graph_neighbors` for nearby documents, `gno_graph_path` for "how are X and Y connected?", `gno_links`/`gno_backlinks` for one-document link expansion, and `gno_similar` for semantic neighbors. Prefer explicit or typed edges over inferred, ambiguous, or similarity edges when confidence matters.
|
|
141
|
+
4. Use `gno_query_diagnose` when a known target document should have appeared but did not; it reports BM25/vector/fusion/graph/rerank stage presence and filter state.
|
|
142
|
+
5. Use `gno_get` with `fromLine`/`lineCount` for targeted reads, or `gno_multi_get` to batch top refs.
|
|
142
143
|
|
|
143
144
|
Use narrower tools when the request tells you to:
|
|
144
145
|
|
|
@@ -146,8 +147,10 @@ Use narrower tools when the request tells you to:
|
|
|
146
147
|
- `gno_vsearch`: conceptual similarity when exact wording differs
|
|
147
148
|
- `gno_status`: stale results, missing embeddings, vector unavailable
|
|
148
149
|
- `gno_graph`: graph report/stats, hubs, isolates, unresolved links, edge confidence/audit, communities, unfamiliar corpus overview
|
|
150
|
+
- `gno_graph_query`: bounded typed-edge traversal from a known document
|
|
149
151
|
- `gno_graph_neighbors`: relationship/corpus-navigation questions around a known document
|
|
150
152
|
- `gno_graph_path`: "how are X and Y connected?" questions
|
|
153
|
+
- `gno_query_diagnose`: why a named target did or did not surface for a query
|
|
151
154
|
|
|
152
155
|
For ambiguous terms, pass `intent` instead of bloating the query text. For typed retrieval, use `queryModes`: `term` for lexical anchors, `intent` for disambiguation, one `hyde` for a hypothetical answer/document.
|
|
153
156
|
|
|
@@ -160,6 +163,15 @@ gno links gno://notes/readme.md
|
|
|
160
163
|
# Find documents linking TO a document (backlinks)
|
|
161
164
|
gno backlinks gno://notes/api-design.md
|
|
162
165
|
|
|
166
|
+
# Traverse typed relationships
|
|
167
|
+
gno graph query gno://notes/people/alice.md --edge-type works_at --max-depth 2
|
|
168
|
+
|
|
169
|
+
# Query semantic edges on link commands
|
|
170
|
+
gno links gno://notes/people/alice.md --edge-type works_at
|
|
171
|
+
|
|
172
|
+
# Diagnose a missing expected result
|
|
173
|
+
gno query diagnose "Alice Acme" --target gno://notes/people/alice.md --json
|
|
174
|
+
|
|
163
175
|
# Find semantically similar documents
|
|
164
176
|
gno similar gno://notes/auth.md
|
|
165
177
|
|
|
@@ -317,6 +317,36 @@ gno backlinks <ref> [options]
|
|
|
317
317
|
| `-n` | Max results (default: 20) |
|
|
318
318
|
| `--json` | JSON output |
|
|
319
319
|
|
|
320
|
+
`gno links` and `gno backlinks` also accept `--edge-type <type>` or
|
|
321
|
+
`--relation <type>` to query semantic typed edges instead of positional
|
|
322
|
+
wiki/markdown links. Do not combine `--type` with `--edge-type`.
|
|
323
|
+
|
|
324
|
+
### gno graph query
|
|
325
|
+
|
|
326
|
+
Bounded typed-edge traversal from a document.
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
gno graph query <ref> [--edge-type <type>] [--max-depth <n>] [--direction out|in|both] [--json]
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Use this when relation meaning matters:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
gno graph query gno://notes/people/alice.md --edge-type works_at --max-depth 2 --json
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
### gno query diagnose
|
|
339
|
+
|
|
340
|
+
Explain why a target document did or did not surface for a query.
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
gno query diagnose "<query>" --target <ref> [--fast|--thorough] [--json]
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
The JSON output reports target status, filters, typed metadata, and per-stage
|
|
347
|
+
presence across BM25, vector, fusion, graph expansion, and rerank. Use `--fast`
|
|
348
|
+
for BM25-only diagnosis without vector/rerank startup.
|
|
349
|
+
|
|
320
350
|
### gno similar
|
|
321
351
|
|
|
322
352
|
Find semantically similar documents.
|
package/assets/skill/examples.md
CHANGED
|
@@ -380,6 +380,26 @@ and raw chronology below it. If `contentTypes` are configured in `index.yml`,
|
|
|
380
380
|
matching frontmatter `type` or path prefixes become `contentType` in JSON search
|
|
381
381
|
results.
|
|
382
382
|
|
|
383
|
+
### Typed relationships and diagnostics
|
|
384
|
+
|
|
385
|
+
```yaml
|
|
386
|
+
relations:
|
|
387
|
+
works_at: [gno://notes/companies/acme.md]
|
|
388
|
+
attended: [gno://notes/meetings/weekly-sync.md]
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
```bash
|
|
392
|
+
# Traverse semantic relationships
|
|
393
|
+
gno graph query gno://notes/people/alice.md --edge-type works_at --max-depth 2 --json
|
|
394
|
+
|
|
395
|
+
# Query the semantic edge layer from link commands
|
|
396
|
+
gno links gno://notes/people/alice.md --edge-type works_at
|
|
397
|
+
gno backlinks gno://notes/meetings/weekly-sync.md --relation attended
|
|
398
|
+
|
|
399
|
+
# Debug why a named target did not rank
|
|
400
|
+
gno query diagnose "Alice Acme" --target gno://notes/people/alice.md --fast --json
|
|
401
|
+
```
|
|
402
|
+
|
|
383
403
|
### Web UI quick capture
|
|
384
404
|
|
|
385
405
|
Press **N** in `gno serve`, write the note, and open **Source** only when you
|
|
@@ -58,16 +58,22 @@ gno mcp status
|
|
|
58
58
|
For normal questions, start with `gno_query`, then read targeted snippets with
|
|
59
59
|
`gno_get` or batch refs with `gno_multi_get`. Pass `graph: true` only when
|
|
60
60
|
linked context is worth the extra latency. Check `gno_status` first when freshness or
|
|
61
|
-
embeddings may be stale.
|
|
61
|
+
embeddings may be stale. Use `gno_query_diagnose` when a known target document
|
|
62
|
+
should have appeared but did not.
|
|
62
63
|
|
|
63
64
|
Use graph tools for relationship context: `gno_graph` for corpus report/stats,
|
|
64
65
|
community summaries,
|
|
66
|
+
`gno_graph_query` for bounded typed-edge traversal,
|
|
65
67
|
`gno_graph_neighbors` for nearby incoming/outgoing graph context, and
|
|
66
68
|
`gno_graph_path` for "how are X and Y connected?" questions. Use
|
|
67
69
|
`gno_links`, `gno_backlinks`, and `gno_similar` for one-document expansion.
|
|
68
70
|
Graph edges include confidence/audit metadata; prefer `explicit` edges when
|
|
69
71
|
answers depend on link certainty.
|
|
70
72
|
|
|
73
|
+
Read-only MCP graph/query diagnostics include `gno_graph_query` and
|
|
74
|
+
`gno_query_diagnose`. In `gno_query_diagnose`, pass `fast: true` for a BM25-only
|
|
75
|
+
diagnosis that avoids embedding/rerank model initialization.
|
|
76
|
+
|
|
71
77
|
## Capture
|
|
72
78
|
|
|
73
79
|
`gno_capture` is available only when MCP starts with `--enable-write` or
|
package/package.json
CHANGED
|
@@ -5,8 +5,15 @@
|
|
|
5
5
|
* @module src/cli/commands/graph
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
9
|
-
|
|
8
|
+
import type {
|
|
9
|
+
GetGraphOptions,
|
|
10
|
+
GraphQueryDirection,
|
|
11
|
+
GraphQueryResult,
|
|
12
|
+
GraphResult,
|
|
13
|
+
} from "../../store/types";
|
|
14
|
+
|
|
15
|
+
import { normalizeContentTypes } from "../../config";
|
|
16
|
+
import { diagnoseGraphQuery } from "../../core/graph-query";
|
|
10
17
|
import { initStore } from "./shared";
|
|
11
18
|
|
|
12
19
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -16,6 +23,8 @@ import { initStore } from "./shared";
|
|
|
16
23
|
export interface GraphOptions {
|
|
17
24
|
/** Override config path */
|
|
18
25
|
configPath?: string;
|
|
26
|
+
/** Override index name */
|
|
27
|
+
indexName?: string;
|
|
19
28
|
/** Filter by collection */
|
|
20
29
|
collection?: string;
|
|
21
30
|
/** Max nodes (default 2000) */
|
|
@@ -44,12 +53,28 @@ export interface GraphOptions {
|
|
|
44
53
|
maxDepth?: number;
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
export interface GraphQueryCliOptions {
|
|
57
|
+
configPath?: string;
|
|
58
|
+
indexName?: string;
|
|
59
|
+
direction?: GraphQueryDirection;
|
|
60
|
+
edgeType?: string;
|
|
61
|
+
maxDepth?: number;
|
|
62
|
+
maxNodes?: number;
|
|
63
|
+
frontierLimit?: number;
|
|
64
|
+
visitedLimit?: number;
|
|
65
|
+
format?: "terminal" | "json";
|
|
66
|
+
}
|
|
67
|
+
|
|
47
68
|
export type GraphCommandResult =
|
|
48
69
|
| { success: true; data: GraphResult }
|
|
49
70
|
| { success: true; data: GraphNeighborsCliResult }
|
|
50
71
|
| { success: true; data: GraphPathCliResult }
|
|
51
72
|
| { success: false; error: string; isValidation?: boolean };
|
|
52
73
|
|
|
74
|
+
export type GraphQueryCommandResult =
|
|
75
|
+
| { success: true; data: GraphQueryResult }
|
|
76
|
+
| { success: false; error: string; isValidation?: boolean };
|
|
77
|
+
|
|
53
78
|
type GraphNode = GraphResult["nodes"][number];
|
|
54
79
|
type GraphLink = GraphResult["links"][number];
|
|
55
80
|
|
|
@@ -94,6 +119,7 @@ export async function graph(
|
|
|
94
119
|
): Promise<GraphCommandResult> {
|
|
95
120
|
const initResult = await initStore({
|
|
96
121
|
configPath: options.configPath,
|
|
122
|
+
indexName: options.indexName,
|
|
97
123
|
syncConfig: false,
|
|
98
124
|
});
|
|
99
125
|
if (!initResult.ok) {
|
|
@@ -185,6 +211,35 @@ export async function graph(
|
|
|
185
211
|
}
|
|
186
212
|
}
|
|
187
213
|
|
|
214
|
+
export async function graphQuery(
|
|
215
|
+
docRef: string,
|
|
216
|
+
options: GraphQueryCliOptions = {}
|
|
217
|
+
): Promise<GraphQueryCommandResult> {
|
|
218
|
+
const initResult = await initStore({
|
|
219
|
+
configPath: options.configPath,
|
|
220
|
+
indexName: options.indexName,
|
|
221
|
+
syncConfig: false,
|
|
222
|
+
});
|
|
223
|
+
if (!initResult.ok) {
|
|
224
|
+
return { success: false, error: initResult.error };
|
|
225
|
+
}
|
|
226
|
+
const { store, config } = initResult;
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
return await diagnoseGraphQuery(store, docRef, {
|
|
230
|
+
direction: options.direction,
|
|
231
|
+
edgeType: options.edgeType,
|
|
232
|
+
maxDepth: options.maxDepth,
|
|
233
|
+
maxNodes: options.maxNodes,
|
|
234
|
+
frontierLimit: options.frontierLimit,
|
|
235
|
+
visitedLimit: options.visitedLimit,
|
|
236
|
+
contentTypeRules: normalizeContentTypes(config.contentTypes ?? []).rules,
|
|
237
|
+
});
|
|
238
|
+
} finally {
|
|
239
|
+
await store.close();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
188
243
|
function resolveGraphNode(
|
|
189
244
|
graphResult: GraphResult,
|
|
190
245
|
ref: string
|
|
@@ -421,3 +476,35 @@ export function formatGraph(
|
|
|
421
476
|
return JSON.stringify(data, null, 2);
|
|
422
477
|
}
|
|
423
478
|
}
|
|
479
|
+
|
|
480
|
+
export function formatGraphQuery(
|
|
481
|
+
result: GraphQueryCommandResult,
|
|
482
|
+
options: GraphQueryCliOptions
|
|
483
|
+
): string {
|
|
484
|
+
if (!result.success) {
|
|
485
|
+
if (options.format === "json") {
|
|
486
|
+
return JSON.stringify({
|
|
487
|
+
error: { code: "GRAPH_QUERY_FAILED", message: result.error },
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
return `Error: ${result.error}`;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (options.format === "json") {
|
|
494
|
+
return JSON.stringify(result.data, null, 2);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const lines = [
|
|
498
|
+
`Graph query from ${result.data.root.uri}`,
|
|
499
|
+
`Nodes: ${result.data.meta.returnedNodes}, edges: ${result.data.meta.returnedEdges}`,
|
|
500
|
+
];
|
|
501
|
+
if (result.data.meta.truncated) {
|
|
502
|
+
lines.push(`Truncated: ${result.data.meta.warnings.join("; ")}`);
|
|
503
|
+
}
|
|
504
|
+
for (const edge of result.data.edges) {
|
|
505
|
+
lines.push(
|
|
506
|
+
`${edge.source} -> ${edge.target} (${edge.edgeType}, ${edge.confidence}, ${edge.edgeSource}, depth ${edge.depth})`
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
return lines.join("\n");
|
|
510
|
+
}
|