@nusoft/nuos-build-catalogue 0.20.0 → 0.20.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/dist/commands/init.js +6 -9
- package/dist/setup/auto-index.d.ts +14 -9
- package/dist/setup/auto-index.js +39 -17
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -296,16 +296,13 @@ export async function cmdInstallProtocols(prompt, options = {}) {
|
|
|
296
296
|
prompt.print('');
|
|
297
297
|
prompt.print('Checking local semantic search (Ollama + qwen3-embedding:0.6b):');
|
|
298
298
|
await reportLlmStatus((msg) => prompt.print(` ${msg}`));
|
|
299
|
-
// Auto-build the search index when the LLM is ready
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
//
|
|
303
|
-
//
|
|
299
|
+
// Auto-build/refresh the search index when the LLM is ready. The
|
|
300
|
+
// indexer is incremental via per-file SHA hashes: a no-change project
|
|
301
|
+
// takes ~1s, a project with N changed files takes O(N) embed calls.
|
|
302
|
+
// When the LLM stack isn't ready the helper skips silently — the
|
|
303
|
+
// status was already reported above by reportLlmStatus.
|
|
304
304
|
const { ensureIndexBuilt } = await import('../setup/auto-index.js');
|
|
305
|
-
|
|
306
|
-
if (indexResult.kind === 'just_built') {
|
|
307
|
-
prompt.print(` ✓ Built search index (${indexResult.indexed} files, ${indexResult.chunks} chunks).`);
|
|
308
|
-
}
|
|
305
|
+
await ensureIndexBuilt({ cwd });
|
|
309
306
|
return { output: '', exitCode: 0 };
|
|
310
307
|
}
|
|
311
308
|
/**
|
|
@@ -15,13 +15,17 @@
|
|
|
15
15
|
* @module setup/auto-index
|
|
16
16
|
*/
|
|
17
17
|
/** Outcome of an auto-index attempt. */
|
|
18
|
-
export type AutoIndexResult =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
export type AutoIndexResult =
|
|
19
|
+
/**
|
|
20
|
+
* The indexer ran. `indexed` includes both freshly-embedded files and
|
|
21
|
+
* re-embedded changed ones. `unchanged` is non-zero on subsequent
|
|
22
|
+
* runs — those files were SHA-matched and skipped without embedding.
|
|
23
|
+
*/
|
|
24
|
+
{
|
|
25
|
+
kind: 'ran';
|
|
23
26
|
indexPath: string;
|
|
24
27
|
indexed: number;
|
|
28
|
+
unchanged: number;
|
|
25
29
|
chunks: number;
|
|
26
30
|
durationMs: number;
|
|
27
31
|
} | {
|
|
@@ -43,10 +47,11 @@ export interface AutoIndexOptions {
|
|
|
43
47
|
force?: boolean;
|
|
44
48
|
}
|
|
45
49
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
+
* Run the indexer when conditions allow. Always runs (the indexer is
|
|
51
|
+
* incremental — unchanged files are SHA-skipped without embedding work),
|
|
52
|
+
* so this both *creates* the index on first call and *refreshes* it on
|
|
53
|
+
* subsequent calls. Returns `skipped_llm_not_ready` with a hint when
|
|
54
|
+
* the Ollama probe fails — the caller prints the hint and the user runs
|
|
50
55
|
* `setup-llm` to fix things.
|
|
51
56
|
*
|
|
52
57
|
* Never throws on user-facing failures.
|
package/dist/setup/auto-index.js
CHANGED
|
@@ -19,10 +19,11 @@ import { resolveBuildRoot, resolveCatalogueRoot, resolveHashPath, resolveIndexPa
|
|
|
19
19
|
import { DEFAULT_OLLAMA_HOST, detectModelPresent, detectOllamaApi } from './ollama-detect.js';
|
|
20
20
|
import { DEFAULT_EMBEDDING_MODEL } from './run-llm-setup.js';
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
22
|
+
* Run the indexer when conditions allow. Always runs (the indexer is
|
|
23
|
+
* incremental — unchanged files are SHA-skipped without embedding work),
|
|
24
|
+
* so this both *creates* the index on first call and *refreshes* it on
|
|
25
|
+
* subsequent calls. Returns `skipped_llm_not_ready` with a hint when
|
|
26
|
+
* the Ollama probe fails — the caller prints the hint and the user runs
|
|
26
27
|
* `setup-llm` to fix things.
|
|
27
28
|
*
|
|
28
29
|
* Never throws on user-facing failures.
|
|
@@ -49,10 +50,13 @@ export async function ensureIndexBuilt(opts = {}) {
|
|
|
49
50
|
catch {
|
|
50
51
|
return { kind: 'skipped_no_catalogue' };
|
|
51
52
|
}
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
// We do not short-circuit on `existsSync(indexPath)` — the indexer is
|
|
54
|
+
// already incremental via the per-file SHA hash store, so running it
|
|
55
|
+
// when the index is up-to-date is cheap (~1s on a 270-file catalogue
|
|
56
|
+
// with no changes). Short-circuiting here would leave newer files
|
|
57
|
+
// un-embedded until the user ran `nuos-catalogue index` manually,
|
|
58
|
+
// which is exactly the discoverability gap the auto-index is meant to
|
|
59
|
+
// close.
|
|
56
60
|
// Probe the LLM stack — index requires Ollama + the model. If either
|
|
57
61
|
// is missing, skip with a hint pointing at setup-llm.
|
|
58
62
|
const apiHost = process.env.NUOS_CATALOGUE_OLLAMA_HOST ?? DEFAULT_OLLAMA_HOST;
|
|
@@ -73,10 +77,17 @@ export async function ensureIndexBuilt(opts = {}) {
|
|
|
73
77
|
hint: 'Run `nuos-catalogue setup-llm` to pull the embedding model (~600 MB), then re-run `nuos-catalogue index`.',
|
|
74
78
|
};
|
|
75
79
|
}
|
|
76
|
-
// LLM is ready.
|
|
77
|
-
//
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
+
// LLM is ready. Run the indexer. The first run on a fresh project is
|
|
81
|
+
// ~30s of starter-kit content; subsequent runs are fast — the
|
|
82
|
+
// per-file SHA hashes mean unchanged files are skipped without
|
|
83
|
+
// embedding.
|
|
84
|
+
const isFirstRun = !existsSync(indexPath);
|
|
85
|
+
if (isFirstRun) {
|
|
86
|
+
out('Building search index for docs/build/ … (first run may take ~30 seconds)\n');
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
out('Refreshing search index (incremental — only changed files are re-embedded)…\n');
|
|
90
|
+
}
|
|
80
91
|
try {
|
|
81
92
|
const { selectEmbedderFromEnv } = await import('../embedder/select.js');
|
|
82
93
|
const { openStore } = await import('../store/open.js');
|
|
@@ -92,12 +103,23 @@ export async function ensureIndexBuilt(opts = {}) {
|
|
|
92
103
|
force: Boolean(opts.force),
|
|
93
104
|
dryRun: false,
|
|
94
105
|
});
|
|
95
|
-
|
|
96
|
-
|
|
106
|
+
const changed = report.indexed + report.updated;
|
|
107
|
+
const secs = (report.durationMs / 1000).toFixed(1);
|
|
108
|
+
if (isFirstRun) {
|
|
109
|
+
out(`✓ Indexed ${report.indexed} file(s), ${report.chunks} chunks embedded in ${secs}s\n`);
|
|
110
|
+
}
|
|
111
|
+
else if (changed === 0) {
|
|
112
|
+
out(`✓ Index up-to-date (${report.unchanged} files checked, none changed) in ${secs}s\n`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
out(`✓ Re-indexed ${changed} changed file(s) (${report.unchanged} unchanged), ` +
|
|
116
|
+
`${report.chunks} chunks embedded in ${secs}s\n`);
|
|
117
|
+
}
|
|
97
118
|
return {
|
|
98
|
-
kind: '
|
|
119
|
+
kind: 'ran',
|
|
99
120
|
indexPath,
|
|
100
|
-
indexed:
|
|
121
|
+
indexed: changed,
|
|
122
|
+
unchanged: report.unchanged,
|
|
101
123
|
chunks: report.chunks,
|
|
102
124
|
durationMs: report.durationMs,
|
|
103
125
|
};
|
|
@@ -109,7 +131,7 @@ export async function ensureIndexBuilt(opts = {}) {
|
|
|
109
131
|
}
|
|
110
132
|
catch (err) {
|
|
111
133
|
const message = err instanceof Error ? err.message : String(err);
|
|
112
|
-
out(`\n✗ Index
|
|
134
|
+
out(`\n✗ Index refresh failed: ${message}\n`);
|
|
113
135
|
out('Re-run `nuos-catalogue index` manually to retry.\n');
|
|
114
136
|
return { kind: 'failed', error: message };
|
|
115
137
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nusoft/nuos-build-catalogue",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "NuOS build-catalogue tooling: semantic search (WU 110) + migration runner that lifts markdown artefacts into JSON-backed workflow records (WU 111, Phase G).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|