@gmickel/gno 2.6.0 → 2.7.1
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 +25 -30
- package/assets/skill/SKILL.md +5 -3
- package/assets/skill/cli-reference.md +9 -2
- package/assets/skill/mcp-reference.md +2 -1
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v2.6.0.zip → gno-browser-clipper-v2.7.1.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.7.1.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +2 -1
- package/spec/cli.md +109 -18
- package/spec/mcp.md +36 -2
- package/spec/output-schemas/ask.schema.json +1 -1
- package/spec/output-schemas/capture-receipt.schema.json +1 -1
- package/spec/output-schemas/collection-list.schema.json +2 -2
- package/spec/output-schemas/doctor.schema.json +88 -0
- package/spec/output-schemas/error.schema.json +11 -2
- package/spec/output-schemas/get.schema.json +1 -1
- package/spec/output-schemas/mcp-capture-result.schema.json +1 -2
- package/spec/output-schemas/memory-remember.schema.json +2 -2
- package/spec/output-schemas/multi-get.schema.json +4 -1
- package/spec/output-schemas/peek.schema.json +2 -9
- package/spec/output-schemas/resident-status.schema.json +22 -0
- package/spec/output-schemas/search-result.schema.json +1 -1
- package/spec/output-schemas/search-results.schema.json +1 -1
- package/spec/output-schemas/status.schema.json +110 -16
- package/src/cli/commands/ask.ts +31 -12
- package/src/cli/commands/doctor.ts +54 -20
- package/src/cli/commands/embed.ts +41 -3
- package/src/cli/commands/ls.ts +6 -1
- package/src/cli/commands/query.ts +5 -0
- package/src/cli/commands/status.ts +63 -5
- package/src/cli/commands/vec.ts +54 -0
- package/src/cli/detach.ts +29 -1
- package/src/cli/errors.ts +13 -9
- package/src/cli/program.ts +53 -1
- package/src/core/capture-sync.ts +9 -2
- package/src/core/host-paths.ts +49 -0
- package/src/core/memory-remember.ts +4 -3
- package/src/core/request-receipts.ts +63 -9
- package/src/core/shutdown-budget.ts +6 -0
- package/src/core/vector-partition-status.ts +52 -0
- package/src/core/windows-private-path.ts +136 -1
- package/src/embed/backlog.ts +145 -27
- package/src/embed/fingerprint.ts +6 -3
- package/src/embed/retry.ts +66 -27
- package/src/embed/variant-backlog.ts +48 -18
- package/src/embed/variant-retry.ts +31 -22
- package/src/index.ts +21 -2
- package/src/llm/inference-scope.ts +18 -0
- package/src/llm/native-worker/dispatcher.ts +2 -0
- package/src/llm/native-worker/embedding-identity.ts +42 -0
- package/src/llm/native-worker/protocol.ts +1 -0
- package/src/llm/types.ts +3 -0
- package/src/mcp/context.ts +9 -0
- package/src/mcp/resources/index.ts +6 -5
- package/src/mcp/tool-descriptions-core.ts +1 -1
- package/src/mcp/tools/capture.ts +1 -3
- package/src/mcp/tools/index.ts +11 -4
- package/src/mcp/tools/memory-remember.ts +1 -1
- package/src/mcp/tools/status.ts +23 -6
- package/src/pipeline/hybrid.ts +37 -7
- package/src/pipeline/vsearch.ts +14 -2
- package/src/serve/embed-scheduler.ts +133 -19
- package/src/serve/host-path-redaction.ts +116 -0
- package/src/serve/public/components/BootstrapStatus.tsx +5 -3
- package/src/serve/public/components/CaptureModal.tsx +1 -1
- package/src/serve/public/components/CollectionModelDialog.tsx +16 -13
- package/src/serve/public/components/CollectionsEmptyState.tsx +5 -3
- package/src/serve/public/components/FirstRunWizard.tsx +4 -2
- package/src/serve/public/components/sessions/SessionSearch.tsx +2 -2
- package/src/serve/public/components/sessions/SourcesPanel.tsx +77 -60
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/hooks/use-api.ts +17 -2
- package/src/serve/public/lib/request-intent.ts +8 -0
- package/src/serve/public/{components/sessions → lib}/snippet.tsx +2 -3
- package/src/serve/public/pages/Collections.tsx +16 -13
- package/src/serve/public/pages/Connectors.tsx +7 -4
- package/src/serve/public/pages/Dashboard.tsx +16 -11
- package/src/serve/public/pages/DocView.tsx +10 -5
- package/src/serve/public/pages/DocumentEditor.tsx +91 -14
- package/src/serve/public/pages/Search.tsx +1 -41
- package/src/serve/resident-runtime.ts +33 -1
- package/src/serve/resident-status.ts +13 -1
- package/src/serve/routes/sessions.ts +61 -5
- package/src/serve/server.ts +15 -12
- package/src/serve/status-model.ts +26 -6
- package/src/serve/status.ts +4 -7
- package/src/serve/watch-reconciliation-shared.ts +3 -0
- package/src/serve/watch-service-events.ts +3 -2
- package/src/serve/watch-service-run-flush.ts +35 -2
- package/src/serve/watch-service.ts +5 -0
- package/src/store/migrations/031-runtime-independent-vectors.ts +29 -0
- package/src/store/migrations/032-vector-runtime-callers.ts +17 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +24 -3
- package/src/store/sqlite/change-journal-store.ts +1 -1
- package/src/store/sqlite/legacy-vector-ownership.ts +2 -1
- package/src/store/types.ts +11 -1
- package/src/store/vector/lazy.ts +46 -43
- package/src/store/vector/runtime-compat.ts +651 -0
- package/src/store/vector/sqlite-vec.ts +20 -2
- package/src/store/vector/status.ts +276 -35
- package/src/store/vector/types.ts +2 -0
- package/src/store/vector/variant-search.ts +71 -23
- package/src/store/vector/variants.ts +49 -14
- package/browser-extension/artifacts/gno-browser-clipper-v2.6.0.zip.sha256 +0 -1
|
@@ -12,8 +12,17 @@
|
|
|
12
12
|
"properties": {
|
|
13
13
|
"code": {
|
|
14
14
|
"type": "string",
|
|
15
|
-
"description": "
|
|
16
|
-
"enum": [
|
|
15
|
+
"description": "CLI error code; each maps to one exit code (see spec/cli.md Error Output)",
|
|
16
|
+
"enum": [
|
|
17
|
+
"VALIDATION",
|
|
18
|
+
"RUNTIME",
|
|
19
|
+
"NOT_RUNNING",
|
|
20
|
+
"BUSY",
|
|
21
|
+
"AUDIT_FINDINGS",
|
|
22
|
+
"AUDIT_PARTIAL",
|
|
23
|
+
"CONTEXT_STALE",
|
|
24
|
+
"CONTEXT_CONFLICT"
|
|
25
|
+
]
|
|
17
26
|
},
|
|
18
27
|
"message": {
|
|
19
28
|
"type": "string",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"properties": {
|
|
63
63
|
"absPath": {
|
|
64
64
|
"type": "string",
|
|
65
|
-
"description": "Absolute path to source file"
|
|
65
|
+
"description": "Absolute path to source file. Host path: local callers only (CLI, stdio MCP, same-host Web UI/REST); omitted for remote REST and HTTP MCP callers, which identify the document by uri + relPath."
|
|
66
66
|
},
|
|
67
67
|
"relPath": {
|
|
68
68
|
"type": "string",
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
"required": [
|
|
8
8
|
"docid",
|
|
9
9
|
"uri",
|
|
10
|
-
"absPath",
|
|
11
10
|
"collection",
|
|
12
11
|
"relPath",
|
|
13
12
|
"created",
|
|
@@ -34,7 +33,7 @@
|
|
|
34
33
|
},
|
|
35
34
|
"absPath": {
|
|
36
35
|
"type": "string",
|
|
37
|
-
"description": "Absolute path to the created file"
|
|
36
|
+
"description": "Absolute path to the created file. Stdio callers only; omitted for HTTP MCP callers, which identify the file by uri + relPath."
|
|
38
37
|
},
|
|
39
38
|
"collection": {
|
|
40
39
|
"type": "string",
|
|
@@ -34,13 +34,13 @@
|
|
|
34
34
|
{
|
|
35
35
|
"type": "object",
|
|
36
36
|
"additionalProperties": false,
|
|
37
|
-
"required": ["outcome", "record", "
|
|
37
|
+
"required": ["outcome", "record", "sync", "matching"],
|
|
38
38
|
"properties": {
|
|
39
39
|
"outcome": { "enum": ["added", "superseded"] },
|
|
40
40
|
"record": { "$ref": "#/$defs/fact" },
|
|
41
41
|
"absPath": {
|
|
42
42
|
"type": "string",
|
|
43
|
-
"description": "Absolute path of the fact file that was written."
|
|
43
|
+
"description": "Absolute path of the fact file that was written. Host path: local callers only (CLI, stdio MCP, same-host Web UI/REST); omitted for remote REST and HTTP MCP callers, which identify the document by uri + relPath."
|
|
44
44
|
},
|
|
45
45
|
"sync": { "$ref": "#/$defs/sync" },
|
|
46
46
|
"matching": { "$ref": "#/$defs/matching" },
|
|
@@ -40,7 +40,10 @@
|
|
|
40
40
|
"type": "object",
|
|
41
41
|
"required": ["relPath", "mime", "ext"],
|
|
42
42
|
"properties": {
|
|
43
|
-
"absPath": {
|
|
43
|
+
"absPath": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "Absolute path to source file. Host path: local callers only (CLI, stdio MCP, same-host Web UI/REST); omitted for remote REST and HTTP MCP callers, which identify the document by uri + relPath."
|
|
46
|
+
},
|
|
44
47
|
"relPath": { "type": "string" },
|
|
45
48
|
"mime": { "type": "string" },
|
|
46
49
|
"ext": { "type": "string", "pattern": "^\\.[a-zA-Z0-9]+$" }
|
|
@@ -99,14 +99,7 @@
|
|
|
99
99
|
"items": {
|
|
100
100
|
"type": "object",
|
|
101
101
|
"additionalProperties": false,
|
|
102
|
-
"required": [
|
|
103
|
-
"docid",
|
|
104
|
-
"uri",
|
|
105
|
-
"title",
|
|
106
|
-
"collection",
|
|
107
|
-
"absPath",
|
|
108
|
-
"modifiedAt"
|
|
109
|
-
],
|
|
102
|
+
"required": ["docid", "uri", "title", "collection", "modifiedAt"],
|
|
110
103
|
"properties": {
|
|
111
104
|
"docid": {
|
|
112
105
|
"type": "string",
|
|
@@ -129,7 +122,7 @@
|
|
|
129
122
|
"absPath": {
|
|
130
123
|
"type": "string",
|
|
131
124
|
"minLength": 1,
|
|
132
|
-
"description": "Absolute source path (collection root + relative path)"
|
|
125
|
+
"description": "Absolute source path (collection root + relative path). CLI and stdio MCP only; omitted for HTTP MCP callers."
|
|
133
126
|
},
|
|
134
127
|
"modifiedAt": {
|
|
135
128
|
"type": "string",
|
|
@@ -128,6 +128,28 @@
|
|
|
128
128
|
"content": { "type": "integer", "minimum": 0 },
|
|
129
129
|
"index": { "type": "integer", "minimum": 0 }
|
|
130
130
|
}
|
|
131
|
+
},
|
|
132
|
+
"backgroundIssues": {
|
|
133
|
+
"description": "Present only while a background job is in trouble: failing passes, retries parked, a pass overrunning, or (client-side) a resident that did not answer its status request",
|
|
134
|
+
"type": "array",
|
|
135
|
+
"minItems": 1,
|
|
136
|
+
"items": { "$ref": "#/definitions/backgroundIssue" }
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"definitions": {
|
|
140
|
+
"backgroundIssue": {
|
|
141
|
+
"type": "object",
|
|
142
|
+
"additionalProperties": false,
|
|
143
|
+
"required": ["job", "state", "consecutiveFailures", "runningSeconds"],
|
|
144
|
+
"properties": {
|
|
145
|
+
"job": { "type": "string", "enum": ["embed", "resident"] },
|
|
146
|
+
"state": {
|
|
147
|
+
"type": "string",
|
|
148
|
+
"enum": ["failing", "parked", "overrunning", "unresponsive"]
|
|
149
|
+
},
|
|
150
|
+
"consecutiveFailures": { "type": "integer", "minimum": 0 },
|
|
151
|
+
"runningSeconds": { "type": ["integer", "null"], "minimum": 0 }
|
|
152
|
+
}
|
|
131
153
|
}
|
|
132
154
|
},
|
|
133
155
|
"allOf": [
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"properties": {
|
|
79
79
|
"absPath": {
|
|
80
80
|
"type": "string",
|
|
81
|
-
"description": "Absolute path (
|
|
81
|
+
"description": "Absolute source path. Host path: local callers only (CLI, stdio MCP, same-host Web UI/REST); omitted for remote REST and HTTP MCP callers, which identify the document by uri + relPath."
|
|
82
82
|
},
|
|
83
83
|
"relPath": {
|
|
84
84
|
"type": "string",
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
"properties": {
|
|
238
238
|
"absPath": {
|
|
239
239
|
"type": "string",
|
|
240
|
-
"description": "Absolute filesystem path when resolvable from collection root + relPath. Default field on gno search --json (no --source flag). Omitted when unresolvable; consumers fall back to
|
|
240
|
+
"description": "Absolute filesystem path when resolvable from collection root + relPath. Default field on gno search --json (no --source flag). Omitted when unresolvable, and always omitted for remote REST and HTTP MCP callers (host paths reach only CLI, stdio MCP and same-host Web UI/REST callers); consumers fall back to uri + relPath for display and disable file-open."
|
|
241
241
|
},
|
|
242
242
|
"relPath": {
|
|
243
243
|
"type": "string",
|
|
@@ -90,24 +90,18 @@
|
|
|
90
90
|
},
|
|
91
91
|
"configPath": {
|
|
92
92
|
"type": "string",
|
|
93
|
-
"description": "Path to config file"
|
|
93
|
+
"description": "Path to config file. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
94
94
|
},
|
|
95
95
|
"dbPath": {
|
|
96
96
|
"type": "string",
|
|
97
|
-
"description": "Path to SQLite database"
|
|
97
|
+
"description": "Path to SQLite database. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
98
98
|
},
|
|
99
99
|
"collections": {
|
|
100
100
|
"type": "array",
|
|
101
101
|
"description": "Collection statistics",
|
|
102
102
|
"items": {
|
|
103
103
|
"type": "object",
|
|
104
|
-
"required": [
|
|
105
|
-
"name",
|
|
106
|
-
"path",
|
|
107
|
-
"documentCount",
|
|
108
|
-
"chunkCount",
|
|
109
|
-
"embeddedCount"
|
|
110
|
-
],
|
|
104
|
+
"required": ["name", "documentCount", "chunkCount", "embeddedCount"],
|
|
111
105
|
"properties": {
|
|
112
106
|
"name": {
|
|
113
107
|
"type": "string",
|
|
@@ -115,7 +109,7 @@
|
|
|
115
109
|
},
|
|
116
110
|
"path": {
|
|
117
111
|
"type": "string",
|
|
118
|
-
"description": "Collection root path"
|
|
112
|
+
"description": "Collection root path. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
119
113
|
},
|
|
120
114
|
"documentCount": {
|
|
121
115
|
"type": "integer",
|
|
@@ -150,6 +144,104 @@
|
|
|
150
144
|
"description": "Chunks awaiting embedding",
|
|
151
145
|
"minimum": 0
|
|
152
146
|
},
|
|
147
|
+
"vectorPartitions": {
|
|
148
|
+
"type": "array",
|
|
149
|
+
"description": "Vector partitions of the embedding model; omitted when none exist",
|
|
150
|
+
"items": {
|
|
151
|
+
"type": "object",
|
|
152
|
+
"additionalProperties": false,
|
|
153
|
+
"required": [
|
|
154
|
+
"id",
|
|
155
|
+
"model",
|
|
156
|
+
"dimensions",
|
|
157
|
+
"state",
|
|
158
|
+
"legacy",
|
|
159
|
+
"retrieval",
|
|
160
|
+
"droppable",
|
|
161
|
+
"owners",
|
|
162
|
+
"provenance",
|
|
163
|
+
"compatibleRuntimes",
|
|
164
|
+
"incompatibleRuntimes"
|
|
165
|
+
],
|
|
166
|
+
"properties": {
|
|
167
|
+
"id": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"description": "Partition id (drop with `gno vec drop <id-prefix>`)"
|
|
170
|
+
},
|
|
171
|
+
"model": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"description": "Embedding model URI"
|
|
174
|
+
},
|
|
175
|
+
"dimensions": {
|
|
176
|
+
"type": "integer",
|
|
177
|
+
"minimum": 1
|
|
178
|
+
},
|
|
179
|
+
"state": {
|
|
180
|
+
"type": "string",
|
|
181
|
+
"enum": ["active", "shadow"],
|
|
182
|
+
"description": "active = activated for retrieval; shadow = incomplete or abandoned"
|
|
183
|
+
},
|
|
184
|
+
"legacy": {
|
|
185
|
+
"type": "boolean",
|
|
186
|
+
"description": "Pre-runtime-independent key, awaiting measured re-keying"
|
|
187
|
+
},
|
|
188
|
+
"retrieval": {
|
|
189
|
+
"type": "boolean",
|
|
190
|
+
"description": "Status counts use this partition: the activated runtime-independent partition every compatible runtime reads"
|
|
191
|
+
},
|
|
192
|
+
"droppable": {
|
|
193
|
+
"type": "boolean",
|
|
194
|
+
"description": "`gno vec drop` accepts it; never the partition this runtime's retrieval uses"
|
|
195
|
+
},
|
|
196
|
+
"owners": {
|
|
197
|
+
"type": "integer",
|
|
198
|
+
"minimum": 0,
|
|
199
|
+
"description": "Current chunks bound to this partition"
|
|
200
|
+
},
|
|
201
|
+
"provenance": {
|
|
202
|
+
"type": "string",
|
|
203
|
+
"description": "Runtime that built the partition, e.g. \"CUDA, Bun 1.4.2\""
|
|
204
|
+
},
|
|
205
|
+
"compatibleRuntimes": {
|
|
206
|
+
"type": "array",
|
|
207
|
+
"items": {
|
|
208
|
+
"type": "string"
|
|
209
|
+
},
|
|
210
|
+
"description": "Runtimes measured (or recorded as the builder) to read this partition"
|
|
211
|
+
},
|
|
212
|
+
"incompatibleRuntimes": {
|
|
213
|
+
"type": "array",
|
|
214
|
+
"items": {
|
|
215
|
+
"type": "string"
|
|
216
|
+
},
|
|
217
|
+
"description": "Runtimes measured incompatible; they read another partition or use lexical retrieval only"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"vectorRuntime": {
|
|
223
|
+
"type": "object",
|
|
224
|
+
"additionalProperties": false,
|
|
225
|
+
"required": ["label", "state", "partition"],
|
|
226
|
+
"description": "This process's runtime, resolved by the same selection rule its queries use",
|
|
227
|
+
"properties": {
|
|
228
|
+
"label": {
|
|
229
|
+
"type": ["string", "null"],
|
|
230
|
+
"description": "Runtime recorded by this caller's last query or embed"
|
|
231
|
+
},
|
|
232
|
+
"state": {
|
|
233
|
+
"type": "string",
|
|
234
|
+
"enum": ["vectors", "unavailable", "unresolved"],
|
|
235
|
+
"description": "vectors: queries read `partition`; unavailable: lexical retrieval only; unresolved: no query or embed has resolved this caller yet"
|
|
236
|
+
},
|
|
237
|
+
"partition": {
|
|
238
|
+
"type": ["string", "null"]
|
|
239
|
+
},
|
|
240
|
+
"reason": {
|
|
241
|
+
"type": "string"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
153
245
|
"recentErrors": {
|
|
154
246
|
"type": "integer",
|
|
155
247
|
"description": "Recent ingest errors in the last 24 hours",
|
|
@@ -497,13 +589,14 @@
|
|
|
497
589
|
"type": "array",
|
|
498
590
|
"items": {
|
|
499
591
|
"type": "object",
|
|
500
|
-
"required": ["label", "
|
|
592
|
+
"required": ["label", "reason"],
|
|
501
593
|
"properties": {
|
|
502
594
|
"label": {
|
|
503
595
|
"type": "string"
|
|
504
596
|
},
|
|
505
597
|
"path": {
|
|
506
|
-
"type": "string"
|
|
598
|
+
"type": "string",
|
|
599
|
+
"description": "Suggested folder path. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
507
600
|
},
|
|
508
601
|
"reason": {
|
|
509
602
|
"type": "string"
|
|
@@ -785,10 +878,11 @@
|
|
|
785
878
|
},
|
|
786
879
|
"cache": {
|
|
787
880
|
"type": "object",
|
|
788
|
-
"required": ["
|
|
881
|
+
"required": ["totalSizeBytes", "totalSizeLabel"],
|
|
789
882
|
"properties": {
|
|
790
883
|
"path": {
|
|
791
|
-
"type": "string"
|
|
884
|
+
"type": "string",
|
|
885
|
+
"description": "Model cache directory. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
792
886
|
},
|
|
793
887
|
"totalSizeBytes": {
|
|
794
888
|
"type": "integer",
|
|
@@ -843,7 +937,6 @@
|
|
|
843
937
|
"role",
|
|
844
938
|
"uri",
|
|
845
939
|
"cached",
|
|
846
|
-
"path",
|
|
847
940
|
"sizeBytes",
|
|
848
941
|
"statusLabel"
|
|
849
942
|
],
|
|
@@ -859,7 +952,8 @@
|
|
|
859
952
|
"type": "boolean"
|
|
860
953
|
},
|
|
861
954
|
"path": {
|
|
862
|
-
"type": ["string", "null"]
|
|
955
|
+
"type": ["string", "null"],
|
|
956
|
+
"description": "Cached model file, or null when not cached. Same-host callers only: omitted for a remote REST or HTTP MCP caller."
|
|
863
957
|
},
|
|
864
958
|
"sizeBytes": {
|
|
865
959
|
"type": ["integer", "null"],
|
package/src/cli/commands/ask.ts
CHANGED
|
@@ -81,6 +81,36 @@ export type AskCommandResult =
|
|
|
81
81
|
}
|
|
82
82
|
| { success: false; error: string };
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Give every document URI `?index=` on a named index, like search and
|
|
86
|
+
* Capsule results: results, citations and the answer-context selection.
|
|
87
|
+
*/
|
|
88
|
+
export function decorateAskUris(
|
|
89
|
+
result: AskResult,
|
|
90
|
+
indexName: string | undefined
|
|
91
|
+
): AskResult {
|
|
92
|
+
const decorate = <T extends { uri: string }>(item: T): T => ({
|
|
93
|
+
...item,
|
|
94
|
+
uri: decorateUriForIndex(item.uri, indexName),
|
|
95
|
+
});
|
|
96
|
+
const answerContext = result.meta.answerContext;
|
|
97
|
+
return {
|
|
98
|
+
...result,
|
|
99
|
+
results: result.results.map(decorate),
|
|
100
|
+
citations: result.citations?.map(decorate),
|
|
101
|
+
meta: answerContext
|
|
102
|
+
? {
|
|
103
|
+
...result.meta,
|
|
104
|
+
answerContext: {
|
|
105
|
+
...answerContext,
|
|
106
|
+
selected: answerContext.selected.map(decorate),
|
|
107
|
+
dropped: answerContext.dropped.map(decorate),
|
|
108
|
+
},
|
|
109
|
+
}
|
|
110
|
+
: result.meta,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
84
114
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
85
115
|
// Command Implementation
|
|
86
116
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -435,20 +465,9 @@ export async function ask(
|
|
|
435
465
|
return { success: false, error: finalized.error.message };
|
|
436
466
|
}
|
|
437
467
|
}
|
|
438
|
-
// URIs carry `?index=` like search and Capsule results on a named index.
|
|
439
468
|
return {
|
|
440
469
|
success: true,
|
|
441
|
-
data:
|
|
442
|
-
...askResult,
|
|
443
|
-
results: askResult.results.map((result) => ({
|
|
444
|
-
...result,
|
|
445
|
-
uri: decorateUriForIndex(result.uri, globals.index),
|
|
446
|
-
})),
|
|
447
|
-
citations: askResult.citations?.map((citation) => ({
|
|
448
|
-
...citation,
|
|
449
|
-
uri: decorateUriForIndex(citation.uri, globals.index),
|
|
450
|
-
})),
|
|
451
|
-
},
|
|
470
|
+
data: decorateAskUris(askResult, globals.index),
|
|
452
471
|
metadata: traceSession?.metadata(),
|
|
453
472
|
};
|
|
454
473
|
} catch (cause) {
|
|
@@ -12,6 +12,10 @@ import { arch, platform } from "node:os";
|
|
|
12
12
|
|
|
13
13
|
import type { Config } from "../../config/types";
|
|
14
14
|
import type { ActivationStatus } from "../../core/activation-status";
|
|
15
|
+
import type {
|
|
16
|
+
VectorPartitionStatus,
|
|
17
|
+
VectorRuntimeStatus,
|
|
18
|
+
} from "../../store/vector/status";
|
|
15
19
|
|
|
16
20
|
import { getIndexDbPath, getModelsCachePath } from "../../app/constants";
|
|
17
21
|
import {
|
|
@@ -26,6 +30,7 @@ import {
|
|
|
26
30
|
readFindingsRunStatus,
|
|
27
31
|
resolveFindingsSchedule,
|
|
28
32
|
} from "../../core/findings-run-state";
|
|
33
|
+
import { formatVectorPartitionLines } from "../../core/vector-partition-status";
|
|
29
34
|
import { getCodeChunkingStatus } from "../../ingestion/chunker";
|
|
30
35
|
import { ModelCache } from "../../llm/cache";
|
|
31
36
|
import { getActivePreset, resolveModelUri } from "../../llm/registry";
|
|
@@ -57,6 +62,9 @@ export interface DoctorCheck {
|
|
|
57
62
|
details?: string[];
|
|
58
63
|
/** Embedding fingerprint diagnostics for machine consumers */
|
|
59
64
|
embeddingFingerprint?: EmbeddingFingerprintHealth;
|
|
65
|
+
/** Vector partitions; `retrieval` marks the one status and search use */
|
|
66
|
+
vectorPartitions?: VectorPartitionStatus[];
|
|
67
|
+
vectorRuntime?: VectorRuntimeStatus;
|
|
60
68
|
}
|
|
61
69
|
|
|
62
70
|
export interface EmbeddingFingerprintGroup {
|
|
@@ -261,16 +269,18 @@ function describeFingerprintGroup(group: EmbeddingFingerprintGroup): string {
|
|
|
261
269
|
async function checkEmbeddingFingerprints(
|
|
262
270
|
config: Config,
|
|
263
271
|
indexName?: string
|
|
264
|
-
): Promise<DoctorCheck> {
|
|
272
|
+
): Promise<DoctorCheck[]> {
|
|
265
273
|
const dbPath = getIndexDbPath(indexName);
|
|
266
274
|
try {
|
|
267
275
|
await stat(dbPath);
|
|
268
276
|
} catch {
|
|
269
|
-
return
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
277
|
+
return [
|
|
278
|
+
{
|
|
279
|
+
name: "embedding-fingerprint",
|
|
280
|
+
status: "warn",
|
|
281
|
+
message: "Database not found. Run: gno init",
|
|
282
|
+
},
|
|
283
|
+
];
|
|
274
284
|
}
|
|
275
285
|
|
|
276
286
|
const store = new SqliteAdapter();
|
|
@@ -283,12 +293,14 @@ async function checkEmbeddingFingerprints(
|
|
|
283
293
|
config.busyTimeoutMs ?? DEFAULT_BUSY_TIMEOUT_MS
|
|
284
294
|
);
|
|
285
295
|
if (!openResult.ok) {
|
|
286
|
-
return
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
296
|
+
return [
|
|
297
|
+
{
|
|
298
|
+
name: "embedding-fingerprint",
|
|
299
|
+
status: "warn",
|
|
300
|
+
message: `Fingerprint health unavailable: ${openResult.error.message}`,
|
|
301
|
+
details: ["Run: gno doctor --json", "Then run: gno embed"],
|
|
302
|
+
},
|
|
303
|
+
];
|
|
292
304
|
}
|
|
293
305
|
|
|
294
306
|
try {
|
|
@@ -297,12 +309,14 @@ async function checkEmbeddingFingerprints(
|
|
|
297
309
|
const currentFingerprint = getStoredEmbeddingFingerprint(db, model);
|
|
298
310
|
const statusResult = await store.getStatus({ embedModel: model });
|
|
299
311
|
if (!statusResult.ok) {
|
|
300
|
-
return
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
312
|
+
return [
|
|
313
|
+
{
|
|
314
|
+
name: "embedding-fingerprint",
|
|
315
|
+
status: "warn",
|
|
316
|
+
message: `Fingerprint health unavailable: ${statusResult.error.message}`,
|
|
317
|
+
details: ["Run: gno embed"],
|
|
318
|
+
},
|
|
319
|
+
];
|
|
306
320
|
}
|
|
307
321
|
|
|
308
322
|
const legacyChunks =
|
|
@@ -389,13 +403,33 @@ async function checkEmbeddingFingerprints(
|
|
|
389
403
|
}
|
|
390
404
|
}
|
|
391
405
|
|
|
392
|
-
|
|
406
|
+
const fingerprintCheck: DoctorCheck = {
|
|
393
407
|
name: "embedding-fingerprint",
|
|
394
408
|
status: hasWarnings ? "warn" : "ok",
|
|
395
409
|
message,
|
|
396
410
|
details: details.length > 0 ? details : undefined,
|
|
397
411
|
embeddingFingerprint: health,
|
|
398
412
|
};
|
|
413
|
+
const partitions = statusResult.value.vectorPartitions;
|
|
414
|
+
if (!partitions) return [fingerprintCheck];
|
|
415
|
+
const runtime = statusResult.value.vectorRuntime;
|
|
416
|
+
const partitionLines = formatVectorPartitionLines(partitions, runtime);
|
|
417
|
+
const retrieval = partitions.find((p) => p.retrieval);
|
|
418
|
+
return [
|
|
419
|
+
fingerprintCheck,
|
|
420
|
+
{
|
|
421
|
+
name: "vector-partitions",
|
|
422
|
+
status: partitionLines.length ? "warn" : "ok",
|
|
423
|
+
message: retrieval
|
|
424
|
+
? `this runtime's retrieval uses ${retrieval.id.slice(0, 12)} (${retrieval.state}, ${retrieval.owners} chunks, ${retrieval.provenance}); ${partitions.length - 1} other partition(s)`
|
|
425
|
+
: runtime?.state === "unavailable"
|
|
426
|
+
? `this runtime uses lexical retrieval only: ${runtime.reason}`
|
|
427
|
+
: `this runtime has not resolved a partition yet; ${partitions.length} partition(s)`,
|
|
428
|
+
details: partitionLines.length ? partitionLines.slice(1) : undefined,
|
|
429
|
+
vectorPartitions: partitions,
|
|
430
|
+
vectorRuntime: runtime,
|
|
431
|
+
},
|
|
432
|
+
];
|
|
399
433
|
} finally {
|
|
400
434
|
await store.close();
|
|
401
435
|
}
|
|
@@ -669,7 +703,7 @@ export async function doctor(
|
|
|
669
703
|
checks.push(checkCodeChunking());
|
|
670
704
|
|
|
671
705
|
// Embedding fingerprint freshness
|
|
672
|
-
checks.push(await checkEmbeddingFingerprints(config, options.indexName));
|
|
706
|
+
checks.push(...(await checkEmbeddingFingerprints(config, options.indexName)));
|
|
673
707
|
|
|
674
708
|
// Scheduled findings pass (daemon-only, opt-in)
|
|
675
709
|
checks.push(await checkFindingsPass(config, options.indexName));
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
import type { Database } from "bun:sqlite";
|
|
9
9
|
|
|
10
|
+
// node:readline/promises is the platform line-input API; Bun has no equivalent
|
|
11
|
+
import { createInterface } from "node:readline/promises";
|
|
12
|
+
|
|
10
13
|
import type { EmbeddingPort } from "../../llm/types";
|
|
11
14
|
import type { StoreResult } from "../../store/types";
|
|
12
15
|
|
|
@@ -77,8 +80,10 @@ export interface EmbedOptions extends CliWriteLeaseOptions {
|
|
|
77
80
|
force?: boolean;
|
|
78
81
|
/** Show what would be done without embedding */
|
|
79
82
|
dryRun?: boolean;
|
|
80
|
-
/** Skip confirmation prompts */
|
|
83
|
+
/** Skip confirmation prompts (never confirms a separate vector partition) */
|
|
81
84
|
yes?: boolean;
|
|
85
|
+
/** Explicitly confirm building a separate vector partition */
|
|
86
|
+
newPartition?: boolean;
|
|
82
87
|
/** Output as JSON */
|
|
83
88
|
json?: boolean;
|
|
84
89
|
/** Verbose error logging */
|
|
@@ -450,6 +455,24 @@ async function initEmbedContext(
|
|
|
450
455
|
return { ok: true, config, modelUri, store };
|
|
451
456
|
}
|
|
452
457
|
|
|
458
|
+
async function confirmSeparatePartition(message: string): Promise<boolean> {
|
|
459
|
+
process.stderr.write(`${message}\n`);
|
|
460
|
+
const prompt = createInterface({
|
|
461
|
+
input: process.stdin,
|
|
462
|
+
output: process.stderr,
|
|
463
|
+
});
|
|
464
|
+
try {
|
|
465
|
+
const answer = await prompt.question(
|
|
466
|
+
"Build the separate partition? [y/N] "
|
|
467
|
+
);
|
|
468
|
+
return /^(?:y|yes)$/i.test(answer.trim());
|
|
469
|
+
} catch {
|
|
470
|
+
return false;
|
|
471
|
+
} finally {
|
|
472
|
+
prompt.close();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
453
476
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
454
477
|
// Main Command
|
|
455
478
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -574,7 +597,7 @@ export async function embed(options: EmbedOptions = {}): Promise<EmbedResult> {
|
|
|
574
597
|
}
|
|
575
598
|
vectorIndex = vectorResult.value;
|
|
576
599
|
|
|
577
|
-
const
|
|
600
|
+
const backlogDeps = {
|
|
578
601
|
statsPort: stats,
|
|
579
602
|
embedPort,
|
|
580
603
|
vectorIndex,
|
|
@@ -582,7 +605,22 @@ export async function embed(options: EmbedOptions = {}): Promise<EmbedResult> {
|
|
|
582
605
|
collection: options.collection,
|
|
583
606
|
batchSize,
|
|
584
607
|
force,
|
|
585
|
-
|
|
608
|
+
allowNewPartition: options.newPartition,
|
|
609
|
+
};
|
|
610
|
+
let prepared = await prepareEmbeddingBacklog(backlogDeps);
|
|
611
|
+
if (
|
|
612
|
+
!prepared.ok &&
|
|
613
|
+
prepared.error.code === "VECTOR_PARTITION_FORK" &&
|
|
614
|
+
!dryRun &&
|
|
615
|
+
!options.json &&
|
|
616
|
+
!options.yes &&
|
|
617
|
+
process.stdin.isTTY &&
|
|
618
|
+
(await confirmSeparatePartition(prepared.error.message))
|
|
619
|
+
)
|
|
620
|
+
prepared = await prepareEmbeddingBacklog({
|
|
621
|
+
...backlogDeps,
|
|
622
|
+
allowNewPartition: true,
|
|
623
|
+
});
|
|
586
624
|
if (!prepared.ok)
|
|
587
625
|
return { success: false, error: prepared.error.message };
|
|
588
626
|
if (prepared.value.variantStore) {
|
package/src/cli/commands/ls.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import type { DocumentRow, StorePort, StoreResult } from "../../store/types";
|
|
9
9
|
|
|
10
|
+
import { decorateUriForIndex } from "../../app/constants";
|
|
10
11
|
import { initStore } from "./shared";
|
|
11
12
|
|
|
12
13
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -145,7 +146,11 @@ export async function ls(
|
|
|
145
146
|
// Apply offset and limit
|
|
146
147
|
const offset = options.offset ?? 0;
|
|
147
148
|
const limit = options.limit ?? 20;
|
|
148
|
-
|
|
149
|
+
// Sorted on canonical URIs; the output URIs carry `?index=` like search.
|
|
150
|
+
const paged = allActive.slice(offset, offset + limit).map((doc) => ({
|
|
151
|
+
...doc,
|
|
152
|
+
uri: decorateUriForIndex(doc.uri, options.indexName),
|
|
153
|
+
}));
|
|
149
154
|
|
|
150
155
|
return {
|
|
151
156
|
success: true,
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
createVectorIndexPort,
|
|
38
38
|
type VectorIndexPort,
|
|
39
39
|
} from "../../store/vector";
|
|
40
|
+
import { VECTOR_RUNTIME_INCOMPATIBLE } from "../../store/vector/variant-search";
|
|
40
41
|
import { getGlobals } from "../program";
|
|
41
42
|
import {
|
|
42
43
|
createProgressRenderer,
|
|
@@ -517,6 +518,10 @@ export function formatQuery(
|
|
|
517
518
|
}
|
|
518
519
|
// Output explain to stderr if present (async but best-effort)
|
|
519
520
|
outputExplainToStderr(result.data);
|
|
521
|
+
if (options.format !== "json")
|
|
522
|
+
for (const warning of result.data.meta.warnings ?? [])
|
|
523
|
+
if (warning.code === VECTOR_RUNTIME_INCOMPATIBLE)
|
|
524
|
+
process.stderr.write(`Warning: ${warning.message}\n`);
|
|
520
525
|
|
|
521
526
|
// Use shared formatter for consistent output
|
|
522
527
|
// Dynamic import to keep module loading fast
|