@gmickel/gno 0.7.0 → 0.8.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/LICENSE +21 -0
- package/README.md +90 -50
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/assets/screenshots/webui-ask-answer.png +0 -0
- package/assets/screenshots/webui-collections.png +0 -0
- package/assets/screenshots/webui-editor.png +0 -0
- package/assets/screenshots/webui-home.png +0 -0
- package/assets/skill/SKILL.md +12 -12
- package/assets/skill/cli-reference.md +59 -57
- package/assets/skill/examples.md +8 -7
- package/assets/skill/mcp-reference.md +8 -4
- package/package.json +31 -24
- package/src/app/constants.ts +43 -42
- package/src/cli/colors.ts +1 -1
- package/src/cli/commands/ask.ts +44 -43
- package/src/cli/commands/cleanup.ts +9 -8
- package/src/cli/commands/collection/add.ts +12 -12
- package/src/cli/commands/collection/index.ts +4 -4
- package/src/cli/commands/collection/list.ts +26 -25
- package/src/cli/commands/collection/remove.ts +10 -10
- package/src/cli/commands/collection/rename.ts +10 -10
- package/src/cli/commands/context/add.ts +1 -1
- package/src/cli/commands/context/check.ts +17 -17
- package/src/cli/commands/context/index.ts +4 -4
- package/src/cli/commands/context/list.ts +11 -11
- package/src/cli/commands/context/rm.ts +1 -1
- package/src/cli/commands/doctor.ts +86 -84
- package/src/cli/commands/embed.ts +30 -28
- package/src/cli/commands/get.ts +27 -26
- package/src/cli/commands/index-cmd.ts +9 -9
- package/src/cli/commands/index.ts +16 -16
- package/src/cli/commands/init.ts +13 -12
- package/src/cli/commands/ls.ts +20 -19
- package/src/cli/commands/mcp/config.ts +30 -28
- package/src/cli/commands/mcp/index.ts +4 -4
- package/src/cli/commands/mcp/install.ts +17 -17
- package/src/cli/commands/mcp/paths.ts +133 -133
- package/src/cli/commands/mcp/status.ts +21 -21
- package/src/cli/commands/mcp/uninstall.ts +13 -13
- package/src/cli/commands/mcp.ts +2 -2
- package/src/cli/commands/models/clear.ts +12 -11
- package/src/cli/commands/models/index.ts +5 -5
- package/src/cli/commands/models/list.ts +31 -30
- package/src/cli/commands/models/path.ts +1 -1
- package/src/cli/commands/models/pull.ts +19 -18
- package/src/cli/commands/models/use.ts +4 -4
- package/src/cli/commands/multi-get.ts +38 -36
- package/src/cli/commands/query.ts +21 -20
- package/src/cli/commands/ref-parser.ts +10 -10
- package/src/cli/commands/reset.ts +40 -39
- package/src/cli/commands/search.ts +14 -13
- package/src/cli/commands/serve.ts +4 -4
- package/src/cli/commands/shared.ts +11 -10
- package/src/cli/commands/skill/index.ts +5 -5
- package/src/cli/commands/skill/install.ts +18 -17
- package/src/cli/commands/skill/paths-cmd.ts +11 -10
- package/src/cli/commands/skill/paths.ts +23 -23
- package/src/cli/commands/skill/show.ts +13 -12
- package/src/cli/commands/skill/uninstall.ts +16 -15
- package/src/cli/commands/status.ts +25 -24
- package/src/cli/commands/update.ts +3 -3
- package/src/cli/commands/vsearch.ts +17 -16
- package/src/cli/context.ts +5 -5
- package/src/cli/errors.ts +3 -3
- package/src/cli/format/search-results.ts +37 -37
- package/src/cli/options.ts +43 -43
- package/src/cli/program.ts +455 -459
- package/src/cli/progress.ts +1 -1
- package/src/cli/run.ts +24 -23
- package/src/collection/add.ts +9 -8
- package/src/collection/index.ts +3 -3
- package/src/collection/remove.ts +7 -6
- package/src/collection/types.ts +6 -6
- package/src/config/defaults.ts +1 -1
- package/src/config/index.ts +5 -5
- package/src/config/loader.ts +19 -18
- package/src/config/paths.ts +9 -8
- package/src/config/saver.ts +14 -13
- package/src/config/types.ts +53 -52
- package/src/converters/adapters/markitdownTs/adapter.ts +21 -19
- package/src/converters/adapters/officeparser/adapter.ts +18 -16
- package/src/converters/canonicalize.ts +12 -12
- package/src/converters/errors.ts +26 -22
- package/src/converters/index.ts +8 -8
- package/src/converters/mime.ts +25 -25
- package/src/converters/native/markdown.ts +10 -9
- package/src/converters/native/plaintext.ts +8 -7
- package/src/converters/path.ts +2 -2
- package/src/converters/pipeline.ts +11 -10
- package/src/converters/registry.ts +8 -8
- package/src/converters/types.ts +14 -14
- package/src/converters/versions.ts +4 -4
- package/src/index.ts +4 -4
- package/src/ingestion/chunker.ts +10 -9
- package/src/ingestion/index.ts +6 -6
- package/src/ingestion/language.ts +62 -62
- package/src/ingestion/sync.ts +50 -49
- package/src/ingestion/types.ts +10 -10
- package/src/ingestion/walker.ts +14 -13
- package/src/llm/cache.ts +51 -49
- package/src/llm/errors.ts +40 -36
- package/src/llm/index.ts +9 -9
- package/src/llm/lockfile.ts +6 -6
- package/src/llm/nodeLlamaCpp/adapter.ts +13 -12
- package/src/llm/nodeLlamaCpp/embedding.ts +9 -8
- package/src/llm/nodeLlamaCpp/generation.ts +7 -6
- package/src/llm/nodeLlamaCpp/lifecycle.ts +11 -10
- package/src/llm/nodeLlamaCpp/rerank.ts +6 -5
- package/src/llm/policy.ts +5 -5
- package/src/llm/registry.ts +6 -5
- package/src/llm/types.ts +2 -2
- package/src/mcp/resources/index.ts +15 -13
- package/src/mcp/server.ts +25 -23
- package/src/mcp/tools/get.ts +25 -23
- package/src/mcp/tools/index.ts +32 -29
- package/src/mcp/tools/multi-get.ts +34 -32
- package/src/mcp/tools/query.ts +29 -27
- package/src/mcp/tools/search.ts +14 -12
- package/src/mcp/tools/status.ts +12 -11
- package/src/mcp/tools/vsearch.ts +26 -24
- package/src/pipeline/answer.ts +9 -9
- package/src/pipeline/chunk-lookup.ts +1 -1
- package/src/pipeline/contextual.ts +4 -4
- package/src/pipeline/expansion.ts +23 -21
- package/src/pipeline/explain.ts +21 -21
- package/src/pipeline/fusion.ts +9 -9
- package/src/pipeline/hybrid.ts +41 -42
- package/src/pipeline/index.ts +10 -10
- package/src/pipeline/query-language.ts +39 -39
- package/src/pipeline/rerank.ts +8 -7
- package/src/pipeline/search.ts +22 -22
- package/src/pipeline/types.ts +8 -8
- package/src/pipeline/vsearch.ts +21 -24
- package/src/serve/CLAUDE.md +21 -15
- package/src/serve/config-sync.ts +9 -8
- package/src/serve/context.ts +19 -18
- package/src/serve/index.ts +1 -1
- package/src/serve/jobs.ts +7 -7
- package/src/serve/public/app.tsx +79 -25
- package/src/serve/public/components/AddCollectionDialog.tsx +382 -0
- package/src/serve/public/components/CaptureButton.tsx +60 -0
- package/src/serve/public/components/CaptureModal.tsx +365 -0
- package/src/serve/public/components/IndexingProgress.tsx +333 -0
- package/src/serve/public/components/ShortcutHelpModal.tsx +106 -0
- package/src/serve/public/components/ai-elements/code-block.tsx +42 -32
- package/src/serve/public/components/ai-elements/conversation.tsx +16 -14
- package/src/serve/public/components/ai-elements/inline-citation.tsx +33 -32
- package/src/serve/public/components/ai-elements/loader.tsx +5 -4
- package/src/serve/public/components/ai-elements/message.tsx +39 -37
- package/src/serve/public/components/ai-elements/prompt-input.tsx +97 -95
- package/src/serve/public/components/ai-elements/sources.tsx +12 -10
- package/src/serve/public/components/ai-elements/suggestion.tsx +10 -9
- package/src/serve/public/components/editor/CodeMirrorEditor.tsx +142 -0
- package/src/serve/public/components/editor/MarkdownPreview.tsx +311 -0
- package/src/serve/public/components/editor/index.ts +6 -0
- package/src/serve/public/components/preset-selector.tsx +29 -28
- package/src/serve/public/components/ui/badge.tsx +13 -12
- package/src/serve/public/components/ui/button-group.tsx +13 -12
- package/src/serve/public/components/ui/button.tsx +23 -22
- package/src/serve/public/components/ui/card.tsx +16 -16
- package/src/serve/public/components/ui/carousel.tsx +36 -35
- package/src/serve/public/components/ui/collapsible.tsx +1 -1
- package/src/serve/public/components/ui/command.tsx +17 -15
- package/src/serve/public/components/ui/dialog.tsx +13 -12
- package/src/serve/public/components/ui/dropdown-menu.tsx +13 -12
- package/src/serve/public/components/ui/hover-card.tsx +6 -5
- package/src/serve/public/components/ui/input-group.tsx +45 -43
- package/src/serve/public/components/ui/input.tsx +6 -6
- package/src/serve/public/components/ui/progress.tsx +5 -4
- package/src/serve/public/components/ui/scroll-area.tsx +11 -10
- package/src/serve/public/components/ui/select.tsx +19 -18
- package/src/serve/public/components/ui/separator.tsx +6 -5
- package/src/serve/public/components/ui/table.tsx +18 -18
- package/src/serve/public/components/ui/textarea.tsx +4 -4
- package/src/serve/public/components/ui/tooltip.tsx +5 -4
- package/src/serve/public/globals.css +27 -4
- package/src/serve/public/hooks/use-api.ts +8 -8
- package/src/serve/public/hooks/useCaptureModal.tsx +83 -0
- package/src/serve/public/hooks/useKeyboardShortcuts.ts +85 -0
- package/src/serve/public/index.html +4 -4
- package/src/serve/public/lib/utils.ts +6 -0
- package/src/serve/public/pages/Ask.tsx +27 -26
- package/src/serve/public/pages/Browse.tsx +28 -27
- package/src/serve/public/pages/Collections.tsx +439 -0
- package/src/serve/public/pages/Dashboard.tsx +166 -40
- package/src/serve/public/pages/DocView.tsx +258 -73
- package/src/serve/public/pages/DocumentEditor.tsx +510 -0
- package/src/serve/public/pages/Search.tsx +80 -58
- package/src/serve/routes/api.ts +272 -155
- package/src/serve/security.ts +4 -4
- package/src/serve/server.ts +66 -48
- package/src/store/index.ts +5 -5
- package/src/store/migrations/001-initial.ts +24 -23
- package/src/store/migrations/002-documents-fts.ts +7 -6
- package/src/store/migrations/index.ts +4 -4
- package/src/store/migrations/runner.ts +17 -15
- package/src/store/sqlite/adapter.ts +123 -121
- package/src/store/sqlite/fts5-snowball.ts +24 -23
- package/src/store/sqlite/index.ts +1 -1
- package/src/store/sqlite/setup.ts +12 -12
- package/src/store/sqlite/types.ts +4 -4
- package/src/store/types.ts +19 -19
- package/src/store/vector/index.ts +3 -3
- package/src/store/vector/sqlite-vec.ts +23 -20
- package/src/store/vector/stats.ts +10 -8
- package/src/store/vector/types.ts +2 -2
- package/vendor/fts5-snowball/README.md +6 -6
- package/assets/screenshots/webui-ask-answer.jpg +0 -0
- package/assets/screenshots/webui-home.jpg +0 -0
|
@@ -5,26 +5,28 @@
|
|
|
5
5
|
* @module src/cli/commands/doctor
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { Database } from
|
|
9
|
-
import { stat } from
|
|
8
|
+
import { Database } from "bun:sqlite";
|
|
9
|
+
import { stat } from "node:fs/promises";
|
|
10
10
|
// node:os: arch/platform detection (no Bun equivalent)
|
|
11
|
-
import { arch, platform } from
|
|
12
|
-
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
11
|
+
import { arch, platform } from "node:os";
|
|
12
|
+
|
|
13
|
+
import type { Config } from "../../config/types";
|
|
14
|
+
|
|
15
|
+
import { getIndexDbPath, getModelsCachePath } from "../../app/constants";
|
|
16
|
+
import { getConfigPaths, isInitialized, loadConfig } from "../../config";
|
|
17
|
+
import { ModelCache } from "../../llm/cache";
|
|
18
|
+
import { getActivePreset } from "../../llm/registry";
|
|
17
19
|
import {
|
|
18
20
|
getCustomSqlitePath,
|
|
19
21
|
getExtensionLoadingMode,
|
|
20
22
|
getLoadAttempts,
|
|
21
|
-
} from
|
|
23
|
+
} from "../../store/sqlite/setup";
|
|
22
24
|
|
|
23
25
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
24
26
|
// Types
|
|
25
27
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
26
28
|
|
|
27
|
-
export type DoctorCheckStatus =
|
|
29
|
+
export type DoctorCheckStatus = "ok" | "warn" | "error";
|
|
28
30
|
|
|
29
31
|
export interface DoctorCheck {
|
|
30
32
|
name: string;
|
|
@@ -56,25 +58,25 @@ async function checkConfig(configPath?: string): Promise<DoctorCheck> {
|
|
|
56
58
|
const initialized = await isInitialized(configPath);
|
|
57
59
|
if (!initialized) {
|
|
58
60
|
return {
|
|
59
|
-
name:
|
|
60
|
-
status:
|
|
61
|
-
message:
|
|
61
|
+
name: "config",
|
|
62
|
+
status: "error",
|
|
63
|
+
message: "Config not found. Run: gno init",
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
const configResult = await loadConfig(configPath);
|
|
66
68
|
if (!configResult.ok) {
|
|
67
69
|
return {
|
|
68
|
-
name:
|
|
69
|
-
status:
|
|
70
|
+
name: "config",
|
|
71
|
+
status: "error",
|
|
70
72
|
message: `Config invalid: ${configResult.error.message}`,
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
const paths = getConfigPaths();
|
|
75
77
|
return {
|
|
76
|
-
name:
|
|
77
|
-
status:
|
|
78
|
+
name: "config",
|
|
79
|
+
status: "ok",
|
|
78
80
|
message: `Config loaded: ${paths.configFile}`,
|
|
79
81
|
};
|
|
80
82
|
}
|
|
@@ -85,15 +87,15 @@ async function checkDatabase(): Promise<DoctorCheck> {
|
|
|
85
87
|
try {
|
|
86
88
|
await stat(dbPath);
|
|
87
89
|
return {
|
|
88
|
-
name:
|
|
89
|
-
status:
|
|
90
|
+
name: "database",
|
|
91
|
+
status: "ok",
|
|
90
92
|
message: `Database found: ${dbPath}`,
|
|
91
93
|
};
|
|
92
94
|
} catch {
|
|
93
95
|
return {
|
|
94
|
-
name:
|
|
95
|
-
status:
|
|
96
|
-
message:
|
|
96
|
+
name: "database",
|
|
97
|
+
status: "warn",
|
|
98
|
+
message: "Database not found. Run: gno init",
|
|
97
99
|
};
|
|
98
100
|
}
|
|
99
101
|
}
|
|
@@ -103,13 +105,13 @@ async function checkModels(config: Config): Promise<DoctorCheck[]> {
|
|
|
103
105
|
const cache = new ModelCache(getModelsCachePath());
|
|
104
106
|
const preset = getActivePreset(config);
|
|
105
107
|
|
|
106
|
-
for (const type of [
|
|
108
|
+
for (const type of ["embed", "rerank", "gen"] as const) {
|
|
107
109
|
const uri = preset[type];
|
|
108
110
|
const cached = await cache.isCached(uri);
|
|
109
111
|
|
|
110
112
|
checks.push({
|
|
111
113
|
name: `${type}-model`,
|
|
112
|
-
status: cached ?
|
|
114
|
+
status: cached ? "ok" : "warn",
|
|
113
115
|
message: cached
|
|
114
116
|
? `${type} model cached`
|
|
115
117
|
: `${type} model not cached. Run: gno models pull --${type}`,
|
|
@@ -121,19 +123,19 @@ async function checkModels(config: Config): Promise<DoctorCheck[]> {
|
|
|
121
123
|
|
|
122
124
|
async function checkNodeLlamaCpp(): Promise<DoctorCheck> {
|
|
123
125
|
try {
|
|
124
|
-
const { getLlama } = await import(
|
|
126
|
+
const { getLlama } = await import("node-llama-cpp");
|
|
125
127
|
// Just check that we can get the llama instance
|
|
126
128
|
await getLlama();
|
|
127
129
|
return {
|
|
128
|
-
name:
|
|
129
|
-
status:
|
|
130
|
-
message:
|
|
130
|
+
name: "node-llama-cpp",
|
|
131
|
+
status: "ok",
|
|
132
|
+
message: "node-llama-cpp loaded successfully",
|
|
131
133
|
};
|
|
132
134
|
} catch (e) {
|
|
133
135
|
const message = e instanceof Error ? e.message : String(e);
|
|
134
136
|
return {
|
|
135
|
-
name:
|
|
136
|
-
status:
|
|
137
|
+
name: "node-llama-cpp",
|
|
138
|
+
status: "error",
|
|
137
139
|
message: `node-llama-cpp failed: ${message}`,
|
|
138
140
|
};
|
|
139
141
|
}
|
|
@@ -143,7 +145,7 @@ async function checkNodeLlamaCpp(): Promise<DoctorCheck> {
|
|
|
143
145
|
* Check SQLite extension support (FTS5, sqlite-vec).
|
|
144
146
|
* Uses runtime capability probes instead of compile_options strings.
|
|
145
147
|
*/
|
|
146
|
-
//
|
|
148
|
+
// oxlint-disable-next-line max-lines-per-function -- diagnostic checks with platform-specific handling
|
|
147
149
|
async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
148
150
|
const checks: DoctorCheck[] = [];
|
|
149
151
|
const plat = platform();
|
|
@@ -153,10 +155,10 @@ async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
|
153
155
|
const attempts = getLoadAttempts();
|
|
154
156
|
|
|
155
157
|
// Platform/mode info
|
|
156
|
-
let modeDesc =
|
|
157
|
-
if (mode ===
|
|
158
|
-
modeDesc =
|
|
159
|
-
} else if (mode ===
|
|
158
|
+
let modeDesc = "unavailable";
|
|
159
|
+
if (mode === "native") {
|
|
160
|
+
modeDesc = "native (bundled SQLite supports extensions)";
|
|
161
|
+
} else if (mode === "custom") {
|
|
160
162
|
modeDesc = `custom (${customPath})`;
|
|
161
163
|
}
|
|
162
164
|
|
|
@@ -167,18 +169,18 @@ async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
|
167
169
|
|
|
168
170
|
// Add load attempt details if there were failures
|
|
169
171
|
if (attempts.length > 0) {
|
|
170
|
-
details.push(
|
|
172
|
+
details.push("Load attempts:");
|
|
171
173
|
for (const attempt of attempts) {
|
|
172
174
|
details.push(` ${attempt.path}: ${attempt.error}`);
|
|
173
175
|
}
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
// Create in-memory DB for probes
|
|
177
|
-
const db = new Database(
|
|
178
|
-
let version =
|
|
179
|
+
const db = new Database(":memory:");
|
|
180
|
+
let version = "unknown";
|
|
179
181
|
|
|
180
182
|
try {
|
|
181
|
-
const row = db.query(
|
|
183
|
+
const row = db.query("SELECT sqlite_version() as v").get() as { v: string };
|
|
182
184
|
version = row.v;
|
|
183
185
|
details.push(`SQLite version: ${version}`);
|
|
184
186
|
} catch {
|
|
@@ -188,20 +190,20 @@ async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
|
188
190
|
// Probe FTS5 capability
|
|
189
191
|
let fts5Available = false;
|
|
190
192
|
try {
|
|
191
|
-
db.exec(
|
|
192
|
-
db.exec(
|
|
193
|
+
db.exec("CREATE VIRTUAL TABLE _fts5_probe USING fts5(x)");
|
|
194
|
+
db.exec("DROP TABLE _fts5_probe");
|
|
193
195
|
fts5Available = true;
|
|
194
196
|
} catch {
|
|
195
197
|
// FTS5 not available
|
|
196
198
|
}
|
|
197
199
|
|
|
198
200
|
checks.push({
|
|
199
|
-
name:
|
|
200
|
-
status: fts5Available ?
|
|
201
|
-
message: fts5Available ?
|
|
201
|
+
name: "sqlite-fts5",
|
|
202
|
+
status: fts5Available ? "ok" : "error",
|
|
203
|
+
message: fts5Available ? "FTS5 available" : "FTS5 not available (required)",
|
|
202
204
|
details: fts5Available
|
|
203
205
|
? undefined
|
|
204
|
-
: [
|
|
206
|
+
: ["Full-text search requires FTS5 support"],
|
|
205
207
|
});
|
|
206
208
|
|
|
207
209
|
// Probe JSON capability
|
|
@@ -214,22 +216,22 @@ async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
|
214
216
|
}
|
|
215
217
|
|
|
216
218
|
checks.push({
|
|
217
|
-
name:
|
|
218
|
-
status: jsonAvailable ?
|
|
219
|
-
message: jsonAvailable ?
|
|
219
|
+
name: "sqlite-json",
|
|
220
|
+
status: jsonAvailable ? "ok" : "warn",
|
|
221
|
+
message: jsonAvailable ? "JSON1 available" : "JSON1 not available",
|
|
220
222
|
});
|
|
221
223
|
|
|
222
224
|
// Probe sqlite-vec extension
|
|
223
225
|
let sqliteVecAvailable = false;
|
|
224
|
-
let sqliteVecVersion =
|
|
225
|
-
let sqliteVecError =
|
|
226
|
+
let sqliteVecVersion = "";
|
|
227
|
+
let sqliteVecError = "";
|
|
226
228
|
try {
|
|
227
|
-
const sqliteVec = await import(
|
|
229
|
+
const sqliteVec = await import("sqlite-vec");
|
|
228
230
|
sqliteVec.load(db);
|
|
229
231
|
sqliteVecAvailable = true;
|
|
230
232
|
// Try to get version
|
|
231
233
|
try {
|
|
232
|
-
const vrow = db.query(
|
|
234
|
+
const vrow = db.query("SELECT vec_version() as v").get() as { v: string };
|
|
233
235
|
sqliteVecVersion = vrow.v;
|
|
234
236
|
} catch {
|
|
235
237
|
// No version available
|
|
@@ -242,27 +244,27 @@ async function checkSqliteExtensions(): Promise<DoctorCheck[]> {
|
|
|
242
244
|
if (sqliteVecAvailable) {
|
|
243
245
|
vecMessage = sqliteVecVersion
|
|
244
246
|
? `sqlite-vec loaded (v${sqliteVecVersion})`
|
|
245
|
-
:
|
|
246
|
-
} else if (mode ===
|
|
247
|
+
: "sqlite-vec loaded";
|
|
248
|
+
} else if (mode === "unavailable") {
|
|
247
249
|
vecMessage =
|
|
248
|
-
|
|
250
|
+
"sqlite-vec unavailable (no extension support on macOS without Homebrew)";
|
|
249
251
|
} else {
|
|
250
252
|
vecMessage = sqliteVecError
|
|
251
253
|
? `sqlite-vec failed: ${sqliteVecError}`
|
|
252
|
-
:
|
|
254
|
+
: "sqlite-vec failed to load";
|
|
253
255
|
}
|
|
254
256
|
|
|
255
257
|
const vecDetails = [...details];
|
|
256
|
-
if (!sqliteVecAvailable && plat ===
|
|
257
|
-
vecDetails.push(
|
|
258
|
+
if (!sqliteVecAvailable && plat === "darwin" && mode === "unavailable") {
|
|
259
|
+
vecDetails.push("Install Homebrew SQLite: brew install sqlite3");
|
|
258
260
|
}
|
|
259
261
|
if (sqliteVecError) {
|
|
260
262
|
vecDetails.push(`Load error: ${sqliteVecError}`);
|
|
261
263
|
}
|
|
262
264
|
|
|
263
265
|
checks.push({
|
|
264
|
-
name:
|
|
265
|
-
status: sqliteVecAvailable ?
|
|
266
|
+
name: "sqlite-vec",
|
|
267
|
+
status: sqliteVecAvailable ? "ok" : "warn",
|
|
266
268
|
message: vecMessage,
|
|
267
269
|
details: vecDetails,
|
|
268
270
|
});
|
|
@@ -290,7 +292,7 @@ export async function doctor(
|
|
|
290
292
|
checks.push(await checkDatabase());
|
|
291
293
|
|
|
292
294
|
// Load config for model checks (if available)
|
|
293
|
-
const { createDefaultConfig } = await import(
|
|
295
|
+
const { createDefaultConfig } = await import("../../config");
|
|
294
296
|
const configResult = await loadConfig(options.configPath);
|
|
295
297
|
const config = configResult.ok ? configResult.value : createDefaultConfig();
|
|
296
298
|
|
|
@@ -306,7 +308,7 @@ export async function doctor(
|
|
|
306
308
|
checks.push(...sqliteChecks);
|
|
307
309
|
|
|
308
310
|
// Determine overall health
|
|
309
|
-
const hasErrors = checks.some((c) => c.status ===
|
|
311
|
+
const hasErrors = checks.some((c) => c.status === "error");
|
|
310
312
|
|
|
311
313
|
return {
|
|
312
314
|
healthy: !hasErrors,
|
|
@@ -320,50 +322,50 @@ export async function doctor(
|
|
|
320
322
|
|
|
321
323
|
function statusIcon(status: DoctorCheckStatus): string {
|
|
322
324
|
switch (status) {
|
|
323
|
-
case
|
|
324
|
-
return
|
|
325
|
-
case
|
|
326
|
-
return
|
|
327
|
-
case
|
|
328
|
-
return
|
|
325
|
+
case "ok":
|
|
326
|
+
return "✓";
|
|
327
|
+
case "warn":
|
|
328
|
+
return "!";
|
|
329
|
+
case "error":
|
|
330
|
+
return "✗";
|
|
329
331
|
default:
|
|
330
|
-
return
|
|
332
|
+
return "?";
|
|
331
333
|
}
|
|
332
334
|
}
|
|
333
335
|
|
|
334
336
|
function formatTerminal(result: DoctorResult): string {
|
|
335
337
|
const lines: string[] = [];
|
|
336
338
|
|
|
337
|
-
lines.push(
|
|
338
|
-
lines.push(
|
|
339
|
+
lines.push("GNO Health Check");
|
|
340
|
+
lines.push("");
|
|
339
341
|
|
|
340
342
|
for (const check of result.checks) {
|
|
341
343
|
lines.push(` ${statusIcon(check.status)} ${check.name}: ${check.message}`);
|
|
342
344
|
// Show details for non-ok checks
|
|
343
|
-
if (check.details && check.status !==
|
|
345
|
+
if (check.details && check.status !== "ok") {
|
|
344
346
|
for (const detail of check.details) {
|
|
345
347
|
lines.push(` ${detail}`);
|
|
346
348
|
}
|
|
347
349
|
}
|
|
348
350
|
}
|
|
349
351
|
|
|
350
|
-
lines.push(
|
|
351
|
-
lines.push(`Overall: ${result.healthy ?
|
|
352
|
+
lines.push("");
|
|
353
|
+
lines.push(`Overall: ${result.healthy ? "HEALTHY" : "UNHEALTHY"}`);
|
|
352
354
|
|
|
353
|
-
return lines.join(
|
|
355
|
+
return lines.join("\n");
|
|
354
356
|
}
|
|
355
357
|
|
|
356
358
|
function formatMarkdown(result: DoctorResult): string {
|
|
357
359
|
const lines: string[] = [];
|
|
358
360
|
|
|
359
|
-
lines.push(
|
|
360
|
-
lines.push(
|
|
361
|
-
lines.push(`**Status**: ${result.healthy ?
|
|
362
|
-
lines.push(
|
|
363
|
-
lines.push(
|
|
364
|
-
lines.push(
|
|
365
|
-
lines.push(
|
|
366
|
-
lines.push(
|
|
361
|
+
lines.push("# GNO Health Check");
|
|
362
|
+
lines.push("");
|
|
363
|
+
lines.push(`**Status**: ${result.healthy ? "✓ Healthy" : "✗ Unhealthy"}`);
|
|
364
|
+
lines.push("");
|
|
365
|
+
lines.push("## Checks");
|
|
366
|
+
lines.push("");
|
|
367
|
+
lines.push("| Check | Status | Message |");
|
|
368
|
+
lines.push("|-------|--------|---------|");
|
|
367
369
|
|
|
368
370
|
for (const check of result.checks) {
|
|
369
371
|
lines.push(
|
|
@@ -371,7 +373,7 @@ function formatMarkdown(result: DoctorResult): string {
|
|
|
371
373
|
);
|
|
372
374
|
}
|
|
373
375
|
|
|
374
|
-
return lines.join(
|
|
376
|
+
return lines.join("\n");
|
|
375
377
|
}
|
|
376
378
|
|
|
377
379
|
/**
|
|
@@ -5,22 +5,24 @@
|
|
|
5
5
|
* @module src/cli/commands/embed
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type { Database } from
|
|
9
|
-
|
|
8
|
+
import type { Database } from "bun:sqlite";
|
|
9
|
+
|
|
10
|
+
import type { EmbeddingPort } from "../../llm/types";
|
|
11
|
+
import type { StoreResult } from "../../store/types";
|
|
12
|
+
|
|
13
|
+
import { getIndexDbPath } from "../../app/constants";
|
|
10
14
|
import {
|
|
11
15
|
type Config,
|
|
12
16
|
getConfigPaths,
|
|
13
17
|
isInitialized,
|
|
14
18
|
loadConfig,
|
|
15
|
-
} from
|
|
16
|
-
import { LlmAdapter } from
|
|
17
|
-
import { resolveDownloadPolicy } from
|
|
18
|
-
import { getActivePreset } from
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import type { StoreResult } from '../../store/types';
|
|
23
|
-
import { err, ok } from '../../store/types';
|
|
19
|
+
} from "../../config";
|
|
20
|
+
import { LlmAdapter } from "../../llm/nodeLlamaCpp/adapter";
|
|
21
|
+
import { resolveDownloadPolicy } from "../../llm/policy";
|
|
22
|
+
import { getActivePreset } from "../../llm/registry";
|
|
23
|
+
import { formatDocForEmbedding } from "../../pipeline/contextual";
|
|
24
|
+
import { SqliteAdapter } from "../../store/sqlite/adapter";
|
|
25
|
+
import { err, ok } from "../../store/types";
|
|
24
26
|
import {
|
|
25
27
|
type BacklogItem,
|
|
26
28
|
createVectorIndexPort,
|
|
@@ -28,12 +30,12 @@ import {
|
|
|
28
30
|
type VectorIndexPort,
|
|
29
31
|
type VectorRow,
|
|
30
32
|
type VectorStatsPort,
|
|
31
|
-
} from
|
|
32
|
-
import { getGlobals } from
|
|
33
|
+
} from "../../store/vector";
|
|
34
|
+
import { getGlobals } from "../program";
|
|
33
35
|
import {
|
|
34
36
|
createProgressRenderer,
|
|
35
37
|
createThrottledProgressRenderer,
|
|
36
|
-
} from
|
|
38
|
+
} from "../progress";
|
|
37
39
|
|
|
38
40
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
41
|
// Types
|
|
@@ -81,10 +83,10 @@ function formatDuration(seconds: number): string {
|
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
async function checkVecAvailable(
|
|
84
|
-
db: import(
|
|
86
|
+
db: import("bun:sqlite").Database
|
|
85
87
|
): Promise<boolean> {
|
|
86
88
|
try {
|
|
87
|
-
const sqliteVec = await import(
|
|
89
|
+
const sqliteVec = await import("sqlite-vec");
|
|
88
90
|
sqliteVec.load(db);
|
|
89
91
|
return true;
|
|
90
92
|
} catch {
|
|
@@ -93,7 +95,7 @@ async function checkVecAvailable(
|
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
interface BatchContext {
|
|
96
|
-
db: import(
|
|
98
|
+
db: import("bun:sqlite").Database;
|
|
97
99
|
stats: VectorStatsPort;
|
|
98
100
|
embedPort: EmbeddingPort;
|
|
99
101
|
vectorIndex: VectorIndexPort;
|
|
@@ -190,7 +192,7 @@ async function processBatches(ctx: BatchContext): Promise<BatchResult> {
|
|
|
190
192
|
}
|
|
191
193
|
|
|
192
194
|
if (ctx.showProgress) {
|
|
193
|
-
process.stdout.write(
|
|
195
|
+
process.stdout.write("\n");
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
return {
|
|
@@ -220,7 +222,7 @@ async function initEmbedContext(
|
|
|
220
222
|
): Promise<({ ok: true } & EmbedContext) | { ok: false; error: string }> {
|
|
221
223
|
const initialized = await isInitialized(configPath);
|
|
222
224
|
if (!initialized) {
|
|
223
|
-
return { ok: false, error:
|
|
225
|
+
return { ok: false, error: "GNO not initialized. Run: gno init" };
|
|
224
226
|
}
|
|
225
227
|
|
|
226
228
|
const configResult = await loadConfig(configPath);
|
|
@@ -324,7 +326,7 @@ export async function embed(options: EmbedOptions = {}): Promise<EmbedResult> {
|
|
|
324
326
|
const embedResult = await llm.createEmbeddingPort(modelUri, {
|
|
325
327
|
policy,
|
|
326
328
|
onProgress: downloadProgress
|
|
327
|
-
? (progress) => downloadProgress(
|
|
329
|
+
? (progress) => downloadProgress("embed", progress)
|
|
328
330
|
: undefined,
|
|
329
331
|
});
|
|
330
332
|
if (!embedResult.ok) {
|
|
@@ -334,11 +336,11 @@ export async function embed(options: EmbedOptions = {}): Promise<EmbedResult> {
|
|
|
334
336
|
|
|
335
337
|
// Clear download progress line if shown
|
|
336
338
|
if (showDownloadProgress) {
|
|
337
|
-
process.stderr.write(
|
|
339
|
+
process.stderr.write("\n");
|
|
338
340
|
}
|
|
339
341
|
|
|
340
342
|
// Discover dimensions via probe embedding
|
|
341
|
-
const probeResult = await embedPort.embed(
|
|
343
|
+
const probeResult = await embedPort.embed("dimension probe");
|
|
342
344
|
if (!probeResult.ok) {
|
|
343
345
|
return { success: false, error: probeResult.error.message };
|
|
344
346
|
}
|
|
@@ -408,7 +410,7 @@ function getActiveChunkCount(db: Database): Promise<StoreResult<number>> {
|
|
|
408
410
|
} catch (e) {
|
|
409
411
|
return Promise.resolve(
|
|
410
412
|
err(
|
|
411
|
-
|
|
413
|
+
"QUERY_FAILED",
|
|
412
414
|
`Failed to count chunks: ${e instanceof Error ? e.message : String(e)}`
|
|
413
415
|
)
|
|
414
416
|
);
|
|
@@ -458,7 +460,7 @@ function getActiveChunks(
|
|
|
458
460
|
} catch (e) {
|
|
459
461
|
return Promise.resolve(
|
|
460
462
|
err(
|
|
461
|
-
|
|
463
|
+
"QUERY_FAILED",
|
|
462
464
|
`Failed to get chunks: ${e instanceof Error ? e.message : String(e)}`
|
|
463
465
|
)
|
|
464
466
|
);
|
|
@@ -478,7 +480,7 @@ export function formatEmbed(
|
|
|
478
480
|
): string {
|
|
479
481
|
if (!result.success) {
|
|
480
482
|
return options.json
|
|
481
|
-
? JSON.stringify({ error: { code:
|
|
483
|
+
? JSON.stringify({ error: { code: "RUNTIME", message: result.error } })
|
|
482
484
|
: `Error: ${result.error}`;
|
|
483
485
|
}
|
|
484
486
|
|
|
@@ -501,7 +503,7 @@ export function formatEmbed(
|
|
|
501
503
|
}
|
|
502
504
|
|
|
503
505
|
if (result.embedded === 0 && result.errors === 0) {
|
|
504
|
-
return
|
|
506
|
+
return "No chunks need embedding. All up to date.";
|
|
505
507
|
}
|
|
506
508
|
|
|
507
509
|
const lines: string[] = [];
|
|
@@ -515,9 +517,9 @@ export function formatEmbed(
|
|
|
515
517
|
|
|
516
518
|
if (!result.searchAvailable) {
|
|
517
519
|
lines.push(
|
|
518
|
-
|
|
520
|
+
"Warning: sqlite-vec not available. Embeddings stored but KNN search disabled."
|
|
519
521
|
);
|
|
520
522
|
}
|
|
521
523
|
|
|
522
|
-
return lines.join(
|
|
524
|
+
return lines.join("\n");
|
|
523
525
|
}
|