opencode-rag-plugin 1.15.1 → 1.17.2
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 +52 -9
- package/dist/api.js +44 -24
- package/dist/chunker/base.d.ts +34 -3
- package/dist/chunker/base.js +70 -21
- package/dist/chunker/factory.d.ts +4 -1
- package/dist/chunker/factory.js +12 -1
- package/dist/chunker/grammar.js +3 -0
- package/dist/chunker/image.js +8 -8
- package/dist/chunker/pdf.js +11 -13
- package/dist/chunker/xml.d.ts +2 -0
- package/dist/chunker/xml.js +2 -0
- package/dist/cli/commands/index-command.js +0 -4
- package/dist/cli/commands/index.d.ts +1 -0
- package/dist/cli/commands/index.js +1 -0
- package/dist/cli/commands/init-helpers.d.ts +12 -0
- package/dist/cli/commands/init-helpers.js +87 -2
- package/dist/cli/commands/init.js +20 -2
- package/dist/cli/commands/query.js +1 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/commands/setup.js +113 -0
- package/dist/cli/commands/status.js +64 -2
- package/dist/cli/commands/update.d.ts +4 -6
- package/dist/cli/commands/update.js +44 -58
- package/dist/cli/index.js +2 -1
- package/dist/content/image.js +24 -3
- package/dist/content/reader.d.ts +6 -1
- package/dist/content/reader.js +49 -4
- package/dist/core/config.d.ts +29 -1
- package/dist/core/config.js +105 -8
- package/dist/core/desc-cache.d.ts +31 -0
- package/dist/core/desc-cache.js +124 -0
- package/dist/core/interfaces.d.ts +58 -3
- package/dist/core/manifest.d.ts +24 -1
- package/dist/core/manifest.js +34 -3
- package/dist/core/resolve-api-key.js +4 -2
- package/dist/core/runtime-overrides.js +12 -8
- package/dist/core/setup-runtime.d.ts +23 -0
- package/dist/core/setup-runtime.js +231 -0
- package/dist/core/version-check.d.ts +85 -0
- package/dist/core/version-check.js +160 -0
- package/dist/describer/anthropic.d.ts +2 -2
- package/dist/describer/anthropic.js +5 -7
- package/dist/describer/describer.d.ts +2 -2
- package/dist/describer/describer.js +6 -8
- package/dist/describer/gemini.d.ts +2 -2
- package/dist/describer/gemini.js +5 -7
- package/dist/embedder/cohere.d.ts +1 -1
- package/dist/embedder/cohere.js +2 -2
- package/dist/embedder/factory.d.ts +3 -1
- package/dist/embedder/factory.js +8 -2
- package/dist/embedder/health.js +5 -1
- package/dist/embedder/http.d.ts +1 -1
- package/dist/embedder/http.js +74 -43
- package/dist/embedder/ollama.d.ts +1 -1
- package/dist/embedder/ollama.js +2 -2
- package/dist/embedder/openai.d.ts +1 -1
- package/dist/embedder/openai.js +2 -2
- package/dist/eval/compare-merge.d.ts +10 -0
- package/dist/eval/compare-merge.js +537 -0
- package/dist/eval/compare-rankings.d.ts +10 -0
- package/dist/eval/compare-rankings.js +245 -0
- package/dist/eval/dump-descriptions.d.ts +7 -0
- package/dist/eval/dump-descriptions.js +58 -0
- package/dist/eval/fast-index.d.ts +8 -0
- package/dist/eval/fast-index.js +283 -0
- package/dist/eval/run-branch-compare.d.ts +7 -0
- package/dist/eval/run-branch-compare.js +220 -0
- package/dist/eval/run-token-test.js +1 -0
- package/dist/eval/test-kw.d.ts +1 -0
- package/dist/eval/test-kw.js +22 -0
- package/dist/eval/update-descriptions.d.ts +7 -0
- package/dist/eval/update-descriptions.js +84 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/indexer/embed-stage.js +2 -1
- package/dist/indexer/git-diff.js +21 -9
- package/dist/indexer/pipeline.d.ts +6 -0
- package/dist/indexer/pipeline.js +304 -40
- package/dist/indexer/watch.js +1 -3
- package/dist/indexer/worker.d.ts +15 -2
- package/dist/indexer/worker.js +25 -12
- package/dist/mcp/handlers.d.ts +9 -0
- package/dist/mcp/handlers.js +23 -6
- package/dist/mcp/server.js +2 -0
- package/dist/opencode/create-read-tool.d.ts +2 -0
- package/dist/opencode/create-read-tool.js +8 -2
- package/dist/opencode/read-fallback.d.ts +1 -5
- package/dist/opencode/read-fallback.js +1 -18
- package/dist/opencode/read-format.js +5 -3
- package/dist/opencode/tools.js +5 -7
- package/dist/plugin.js +223 -71
- package/dist/retriever/keyword-index.d.ts +3 -2
- package/dist/retriever/keyword-index.js +25 -1
- package/dist/retriever/retriever.d.ts +4 -1
- package/dist/retriever/retriever.js +34 -56
- package/dist/tui.js +18 -1
- package/dist/vectorstore/lancedb.d.ts +35 -4
- package/dist/vectorstore/lancedb.js +146 -23
- package/dist/vectorstore/memory.d.ts +6 -1
- package/dist/vectorstore/memory.js +58 -0
- package/dist/watcher.d.ts +2 -0
- package/dist/watcher.js +5 -1
- package/dist/web/api.js +10 -2
- package/dist/web/server.js +18 -3
- package/package.json +8 -9
- package/scripts/postinstall-setup.js +82 -0
- package/dist/api.js.map +0 -1
- package/dist/chunker/base.js.map +0 -1
- package/dist/chunker/bash.js.map +0 -1
- package/dist/chunker/c.js.map +0 -1
- package/dist/chunker/cpp.js.map +0 -1
- package/dist/chunker/csharp.js.map +0 -1
- package/dist/chunker/css.js.map +0 -1
- package/dist/chunker/doc.js.map +0 -1
- package/dist/chunker/dockerfile.js.map +0 -1
- package/dist/chunker/docx.js.map +0 -1
- package/dist/chunker/excel.js.map +0 -1
- package/dist/chunker/factory.js.map +0 -1
- package/dist/chunker/fallback.js.map +0 -1
- package/dist/chunker/go.js.map +0 -1
- package/dist/chunker/grammar.js.map +0 -1
- package/dist/chunker/html.js.map +0 -1
- package/dist/chunker/image.js.map +0 -1
- package/dist/chunker/ini.js.map +0 -1
- package/dist/chunker/java.js.map +0 -1
- package/dist/chunker/javascript.js.map +0 -1
- package/dist/chunker/json.js.map +0 -1
- package/dist/chunker/kotlin.js.map +0 -1
- package/dist/chunker/loader.js.map +0 -1
- package/dist/chunker/markdown.js.map +0 -1
- package/dist/chunker/pdf.js.map +0 -1
- package/dist/chunker/php.js.map +0 -1
- package/dist/chunker/powershell.js.map +0 -1
- package/dist/chunker/python.js.map +0 -1
- package/dist/chunker/razor.js.map +0 -1
- package/dist/chunker/ruby.js.map +0 -1
- package/dist/chunker/rust.js.map +0 -1
- package/dist/chunker/sln.js.map +0 -1
- package/dist/chunker/sql.js.map +0 -1
- package/dist/chunker/ssl.js.map +0 -1
- package/dist/chunker/swift.js.map +0 -1
- package/dist/chunker/tex.js.map +0 -1
- package/dist/chunker/toml.js.map +0 -1
- package/dist/chunker/typescript.js.map +0 -1
- package/dist/chunker/uuid.js.map +0 -1
- package/dist/chunker/xml.js.map +0 -1
- package/dist/chunker/yaml.js.map +0 -1
- package/dist/cli/commands/clear.js.map +0 -1
- package/dist/cli/commands/describe-image.js.map +0 -1
- package/dist/cli/commands/dump.js.map +0 -1
- package/dist/cli/commands/eval.js.map +0 -1
- package/dist/cli/commands/index-command.js.map +0 -1
- package/dist/cli/commands/index.js.map +0 -1
- package/dist/cli/commands/init-helpers.js.map +0 -1
- package/dist/cli/commands/init.js.map +0 -1
- package/dist/cli/commands/list.js.map +0 -1
- package/dist/cli/commands/mcp.js.map +0 -1
- package/dist/cli/commands/query.js.map +0 -1
- package/dist/cli/commands/show.js.map +0 -1
- package/dist/cli/commands/status.js.map +0 -1
- package/dist/cli/commands/ui.js.map +0 -1
- package/dist/cli/commands/update.js.map +0 -1
- package/dist/cli/format.js.map +0 -1
- package/dist/cli/helpers.js.map +0 -1
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/progress.d.ts +0 -42
- package/dist/cli/progress.js +0 -137
- package/dist/cli/progress.js.map +0 -1
- package/dist/cli/types.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/content/doc.js.map +0 -1
- package/dist/content/docx.js.map +0 -1
- package/dist/content/excel.js.map +0 -1
- package/dist/content/image.js.map +0 -1
- package/dist/content/pdf.js.map +0 -1
- package/dist/content/reader.js.map +0 -1
- package/dist/content/types.js.map +0 -1
- package/dist/core/bootstrap.js.map +0 -1
- package/dist/core/config.js.map +0 -1
- package/dist/core/doc-progress.js.map +0 -1
- package/dist/core/fileLogger.js.map +0 -1
- package/dist/core/interfaces.js.map +0 -1
- package/dist/core/manifest.js.map +0 -1
- package/dist/core/provider-defaults.js.map +0 -1
- package/dist/core/rag-injection-flag.js.map +0 -1
- package/dist/core/resolve-api-key.js.map +0 -1
- package/dist/core/runtime-overrides.js.map +0 -1
- package/dist/describer/anthropic.js.map +0 -1
- package/dist/describer/describer.js.map +0 -1
- package/dist/describer/factory.js.map +0 -1
- package/dist/describer/gemini.js.map +0 -1
- package/dist/describer/shared.js.map +0 -1
- package/dist/embedder/cohere.js.map +0 -1
- package/dist/embedder/factory.js.map +0 -1
- package/dist/embedder/health.js.map +0 -1
- package/dist/embedder/http.js.map +0 -1
- package/dist/embedder/ollama.js.map +0 -1
- package/dist/embedder/openai.js.map +0 -1
- package/dist/eval/index.js.map +0 -1
- package/dist/eval/run-token-test.js.map +0 -1
- package/dist/eval/session-logger.js.map +0 -1
- package/dist/eval/storage.js.map +0 -1
- package/dist/eval/token-analysis.js.map +0 -1
- package/dist/eval/token-counter.js.map +0 -1
- package/dist/eval/types.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/indexer/description-stage.js.map +0 -1
- package/dist/indexer/embed-stage.js.map +0 -1
- package/dist/indexer/git-diff.js.map +0 -1
- package/dist/indexer/metadata.js.map +0 -1
- package/dist/indexer/pipeline.js.map +0 -1
- package/dist/indexer/stats.js.map +0 -1
- package/dist/indexer/watch.js.map +0 -1
- package/dist/indexer/worker.js.map +0 -1
- package/dist/indexer.js.map +0 -1
- package/dist/mcp/cli.js.map +0 -1
- package/dist/mcp/handlers.js.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/opencode/create-read-tool.js.map +0 -1
- package/dist/opencode/read-fallback.js.map +0 -1
- package/dist/opencode/read-format.js.map +0 -1
- package/dist/opencode/read-query.js.map +0 -1
- package/dist/opencode/tool-args.js.map +0 -1
- package/dist/opencode/tools.js.map +0 -1
- package/dist/plugin-entry.js.map +0 -1
- package/dist/plugin.js.map +0 -1
- package/dist/retriever/context-optimizer.js.map +0 -1
- package/dist/retriever/keyword-index.js.map +0 -1
- package/dist/retriever/retriever.js.map +0 -1
- package/dist/tui.js.map +0 -1
- package/dist/updater.d.ts +0 -45
- package/dist/updater.js +0 -175
- package/dist/updater.js.map +0 -1
- package/dist/vectorstore/factory.js.map +0 -1
- package/dist/vectorstore/lancedb.js.map +0 -1
- package/dist/vectorstore/memory.js.map +0 -1
- package/dist/watcher.js.map +0 -1
- package/dist/web/api.js.map +0 -1
- package/dist/web/server.js.map +0 -1
- package/dist/web/static.js.map +0 -1
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import os from "node:os";
|
|
10
10
|
import { existsSync, mkdirSync, rmSync, symlinkSync, } from "node:fs";
|
|
11
|
+
import { execSync } from "node:child_process";
|
|
11
12
|
import { DEFAULT_CONFIG } from "../../core/config.js";
|
|
12
13
|
import { c } from "../format.js";
|
|
13
14
|
import { getStringRecord, readJsonObject, writeJsonFile, } from "../helpers.js";
|
|
@@ -61,7 +62,7 @@ export function buildOpencodeConfig(existing) {
|
|
|
61
62
|
// Plugin is loaded via .opencode/plugins/rag-plugin.js auto-discovery,
|
|
62
63
|
// not via npm package resolution. Stale "plugin" entries from older
|
|
63
64
|
// init versions would trigger npm install (which fails due to native
|
|
64
|
-
// dependencies like
|
|
65
|
+
// dependencies like sharp) and produce "Plugin export is not a function".
|
|
65
66
|
delete next.plugin;
|
|
66
67
|
return next;
|
|
67
68
|
}
|
|
@@ -247,6 +248,48 @@ export function mergeGitignoreContent(existingContent) {
|
|
|
247
248
|
merged.push("# OpenCodeRAG workspace state", ...missing, "");
|
|
248
249
|
return merged.join("\n");
|
|
249
250
|
}
|
|
251
|
+
const BEGIN_MARKER = "<!-- BEGIN opencode-rag -->";
|
|
252
|
+
const END_MARKER = "<!-- END opencode-rag -->";
|
|
253
|
+
const AGENTS_MD_SECTION = [
|
|
254
|
+
BEGIN_MARKER,
|
|
255
|
+
"## Code Navigation",
|
|
256
|
+
"",
|
|
257
|
+
"ALWAYS use OpenCodeRAG tools before reading or editing:",
|
|
258
|
+
"- **Search first** — `search_semantic(query)` instead of grep/glob",
|
|
259
|
+
"- **Skeleton before read** — `get_file_skeleton(filePath)` then read specific lines",
|
|
260
|
+
"- **Usages before edit** — `find_usages(symbolName)` before modifying any symbol",
|
|
261
|
+
"- **Images via describe** — `describe_image(filePath)` — never read raw bytes",
|
|
262
|
+
"",
|
|
263
|
+
"If no results, run `opencode-rag index`.",
|
|
264
|
+
END_MARKER,
|
|
265
|
+
].join("\n");
|
|
266
|
+
/**
|
|
267
|
+
* Merge the OpenCodeRAG directive section into an existing `AGENTS.md`.
|
|
268
|
+
*
|
|
269
|
+
* The directive is wrapped in sentinel markers so re-runs replace the
|
|
270
|
+
* section in place rather than appending duplicates. Existing content
|
|
271
|
+
* outside the markers is always preserved. If no existing content is
|
|
272
|
+
* provided, the section alone is returned as a new file.
|
|
273
|
+
*
|
|
274
|
+
* @param existingContent - The current `AGENTS.md` content, or `undefined` if absent.
|
|
275
|
+
* @returns The merged `AGENTS.md` content with a trailing newline.
|
|
276
|
+
*/
|
|
277
|
+
export function mergeAgentsMdContent(existingContent) {
|
|
278
|
+
if (!existingContent) {
|
|
279
|
+
return `${AGENTS_MD_SECTION}\n`;
|
|
280
|
+
}
|
|
281
|
+
const beginIdx = existingContent.indexOf(BEGIN_MARKER);
|
|
282
|
+
const endIdx = existingContent.indexOf(END_MARKER);
|
|
283
|
+
if (beginIdx !== -1 && endIdx !== -1 && endIdx > beginIdx) {
|
|
284
|
+
const before = existingContent.slice(0, beginIdx);
|
|
285
|
+
const after = existingContent.slice(endIdx + END_MARKER.length);
|
|
286
|
+
const merged = `${before}${AGENTS_MD_SECTION}${after}`;
|
|
287
|
+
return merged.endsWith("\n") ? merged : `${merged}\n`;
|
|
288
|
+
}
|
|
289
|
+
const trimmed = existingContent.trimEnd();
|
|
290
|
+
const separator = trimmed.endsWith(BEGIN_MARKER) ? "" : "\n\n";
|
|
291
|
+
return `${trimmed}${separator}${AGENTS_MD_SECTION}\n`;
|
|
292
|
+
}
|
|
250
293
|
/**
|
|
251
294
|
* Get the runtime directory path (`~/.opencode`).
|
|
252
295
|
*
|
|
@@ -290,8 +333,47 @@ export async function installPluginFromGlobal(opencodeDir, packageName, skipInst
|
|
|
290
333
|
const globalPluginDir = path.join(runtimeDir, "node_modules", packageName);
|
|
291
334
|
const workspaceTarget = path.join(opencodeDir, "node_modules", packageName);
|
|
292
335
|
if (!existsSync(globalPluginDir)) {
|
|
336
|
+
// Fallback: try the global npm prefix
|
|
337
|
+
let globalRoot;
|
|
338
|
+
try {
|
|
339
|
+
globalRoot = execSync("npm root -g", { encoding: "utf-8", timeout: 10_000 }).trim();
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
throw new Error(`Global plugin cache not found at ${globalPluginDir}. ` +
|
|
343
|
+
"Run 'opencode-rag setup' or install globally with 'npm install -g opencode-rag-plugin' first.");
|
|
344
|
+
}
|
|
345
|
+
const globalNpmPluginDir = path.join(globalRoot, packageName);
|
|
346
|
+
if (existsSync(globalNpmPluginDir) && existsSync(path.join(globalNpmPluginDir, "dist", "cli.js"))) {
|
|
347
|
+
console.log(` ${c.created("Found:")} ${packageName} in global npm prefix, linking...`);
|
|
348
|
+
if (existsSync(workspaceTarget)) {
|
|
349
|
+
rmSync(workspaceTarget, { recursive: true, force: true });
|
|
350
|
+
}
|
|
351
|
+
mkdirSync(path.dirname(workspaceTarget), { recursive: true });
|
|
352
|
+
createJunction(globalNpmPluginDir, workspaceTarget);
|
|
353
|
+
const cliEntry = path.join(workspaceTarget, "dist", "cli.js");
|
|
354
|
+
if (existsSync(cliEntry)) {
|
|
355
|
+
console.log(` ${c.success("Linked:")} ${packageName} from global npm`);
|
|
356
|
+
// Also link @opencode-ai/plugin from global npm
|
|
357
|
+
const globalSdkDir = path.join(globalRoot, "@opencode-ai", "plugin");
|
|
358
|
+
const workspaceSdkDir = path.join(opencodeDir, "node_modules", "@opencode-ai", "plugin");
|
|
359
|
+
if (existsSync(globalSdkDir) && !existsSync(workspaceSdkDir)) {
|
|
360
|
+
mkdirSync(path.dirname(workspaceSdkDir), { recursive: true });
|
|
361
|
+
try {
|
|
362
|
+
createJunction(globalSdkDir, workspaceSdkDir);
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
const { cpSync } = await import("node:fs");
|
|
366
|
+
cpSync(globalSdkDir, workspaceSdkDir, { recursive: true });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
console.log(` ${c.success("Linked:")} @opencode-ai/plugin from global npm`);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
// Junction failed or incomplete — fall through to error
|
|
373
|
+
rmSync(workspaceTarget, { recursive: true, force: true });
|
|
374
|
+
}
|
|
293
375
|
throw new Error(`Global plugin cache not found at ${globalPluginDir}. ` +
|
|
294
|
-
"Run '
|
|
376
|
+
"Run 'opencode-rag setup' or install globally with 'npm install -g opencode-rag-plugin' first.");
|
|
295
377
|
}
|
|
296
378
|
// Remove any stale copy (e.g. from a previous 'npm install' run)
|
|
297
379
|
if (existsSync(workspaceTarget)) {
|
|
@@ -378,6 +460,9 @@ export function generateDefaultConfigJson() {
|
|
|
378
460
|
timeoutMs: DEFAULT_CONFIG.description.timeoutMs,
|
|
379
461
|
maxContentChars: DEFAULT_CONFIG.description.maxContentChars,
|
|
380
462
|
},
|
|
463
|
+
wikiMode: {
|
|
464
|
+
enabled: DEFAULT_CONFIG.wikiMode.enabled,
|
|
465
|
+
},
|
|
381
466
|
mcp: {
|
|
382
467
|
enabled: DEFAULT_CONFIG.mcp.enabled,
|
|
383
468
|
},
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
* installation.
|
|
11
11
|
*/
|
|
12
12
|
import path from "node:path";
|
|
13
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from "node:fs";
|
|
14
14
|
import { loadConfig } from "../../core/config.js";
|
|
15
15
|
import { checkProviderHealth, pullOllamaModels } from "../../embedder/health.js";
|
|
16
16
|
import { destroyAllPooledConnections } from "../../embedder/http.js";
|
|
17
17
|
import { c } from "../format.js";
|
|
18
18
|
import { getPackageMetadata, readJsonObject, writeJsonFile } from "../helpers.js";
|
|
19
|
-
import { buildOpencodeConfig, buildWorkspacePackageJson, generateDefaultConfigJson, generateSkillFile, generateWorkspacePluginFile, generateWorkspaceTuiPluginFile, installPluginFromGlobal, mergeGitignoreContent, } from "./init-helpers.js";
|
|
19
|
+
import { buildOpencodeConfig, buildWorkspacePackageJson, generateDefaultConfigJson, generateSkillFile, generateWorkspacePluginFile, generateWorkspaceTuiPluginFile, installPluginFromGlobal, mergeAgentsMdContent, mergeGitignoreContent, } from "./init-helpers.js";
|
|
20
20
|
/**
|
|
21
21
|
* Register the `init` command on the given Commander program.
|
|
22
22
|
*
|
|
@@ -142,6 +142,20 @@ export function registerInitCommand(program) {
|
|
|
142
142
|
else {
|
|
143
143
|
console.log(` ${c.exists("Exists:")} .opencode/skills/opencode-rag/SKILL.md`);
|
|
144
144
|
}
|
|
145
|
+
const agentsMdPath = path.join(cwd, "AGENTS.md");
|
|
146
|
+
const agentsMdExists = existsSync(agentsMdPath);
|
|
147
|
+
const nextAgentsMd = mergeAgentsMdContent(agentsMdExists ? readFileSync(agentsMdPath, "utf-8") : undefined);
|
|
148
|
+
if (!agentsMdExists || options.force) {
|
|
149
|
+
writeFileSync(agentsMdPath, nextAgentsMd, "utf-8");
|
|
150
|
+
console.log(` ${agentsMdExists ? c.updated("Updated:") : c.created("Created:")} AGENTS.md`);
|
|
151
|
+
}
|
|
152
|
+
else if (readFileSync(agentsMdPath, "utf-8") !== nextAgentsMd) {
|
|
153
|
+
writeFileSync(agentsMdPath, nextAgentsMd, "utf-8");
|
|
154
|
+
console.log(` ${c.updated("Updated:")} AGENTS.md`);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
console.log(` ${c.exists("Exists:")} AGENTS.md`);
|
|
158
|
+
}
|
|
145
159
|
const workspacePackageExists = existsSync(opencodePackagePath);
|
|
146
160
|
const nextWorkspacePackage = buildWorkspacePackageJson(readJsonObject(opencodePackagePath), packageMetadata);
|
|
147
161
|
if (!workspacePackageExists || options.force) {
|
|
@@ -157,6 +171,10 @@ export function registerInitCommand(program) {
|
|
|
157
171
|
}
|
|
158
172
|
const configExists = existsSync(configPath);
|
|
159
173
|
if (!configExists || options.force) {
|
|
174
|
+
if (configExists && options.force) {
|
|
175
|
+
copyFileSync(configPath, configPath + ".bak");
|
|
176
|
+
console.log(` ${c.dim("Backup:")} ${configPath}.bak`);
|
|
177
|
+
}
|
|
160
178
|
writeFileSync(configPath, generateDefaultConfigJson(), "utf-8");
|
|
161
179
|
console.log(` ${configExists ? c.updated("Updated:") : c.created("Created:")} opencode-rag.json`);
|
|
162
180
|
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { existsSync, lstatSync, rmSync } from "node:fs";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { c } from "../format.js";
|
|
5
|
+
import { getPackageMetadata } from "../helpers.js";
|
|
6
|
+
import { getRuntimeDir, getVersionFile, readVersionFile, setupRuntime, } from "../../core/setup-runtime.js";
|
|
7
|
+
const PLUGIN_NAME = "opencode-rag-plugin";
|
|
8
|
+
function removeIfExists(targetPath) {
|
|
9
|
+
if (existsSync(targetPath)) {
|
|
10
|
+
rmSync(targetPath, { recursive: true, force: true });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function checkOpenCodeRunning() {
|
|
14
|
+
try {
|
|
15
|
+
const pids = execSync("pgrep -x opencode 2>/dev/null || (Get-Process -Name opencode -ErrorAction SilentlyContinue 2>nul | ForEach-Object { $_.Id })", {
|
|
16
|
+
encoding: "utf-8",
|
|
17
|
+
timeout: 3_000,
|
|
18
|
+
}).trim();
|
|
19
|
+
if (pids) {
|
|
20
|
+
console.log(`\n ${c.warn("OpenCode is currently running.")} Restart it to load the updated plugin.`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// pgrep/Get-Process aren't available or succeeded silently
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function registerSetupCommand(program) {
|
|
28
|
+
program
|
|
29
|
+
.command("setup")
|
|
30
|
+
.description("Set up the OpenCodeRAG runtime (~/.opencode/) for OpenCode plugin discovery")
|
|
31
|
+
.option("--uninstall", "remove the runtime and cleanup")
|
|
32
|
+
.option("-f, --force", "force re-setup even if up-to-date")
|
|
33
|
+
.option("--check", "check whether the runtime is correctly installed")
|
|
34
|
+
.action(async (options) => {
|
|
35
|
+
const pkg = getPackageMetadata();
|
|
36
|
+
const pluginVersion = pkg.version;
|
|
37
|
+
const runtimeDir = getRuntimeDir();
|
|
38
|
+
const versionFile = getVersionFile(runtimeDir);
|
|
39
|
+
const runtimePluginDir = path.join(runtimeDir, "node_modules", PLUGIN_NAME);
|
|
40
|
+
const runtimeSdkDir = path.join(runtimeDir, "node_modules", "@opencode-ai");
|
|
41
|
+
const runtimeSdkPluginDir = path.join(runtimeSdkDir, "plugin");
|
|
42
|
+
// --- check status ---
|
|
43
|
+
if (options.check) {
|
|
44
|
+
console.log(`\n${c.heading("OpenCodeRAG Runtime Status")}\n`);
|
|
45
|
+
const runtimeDist = path.join(runtimePluginDir, "dist");
|
|
46
|
+
if (existsSync(runtimeDist)) {
|
|
47
|
+
console.log(` ${c.label("Runtime:")} ${c.success("installed")} at ${c.file(runtimeDir)}`);
|
|
48
|
+
const installedVersion = readVersionFile(versionFile);
|
|
49
|
+
console.log(` ${c.label("Installed:")} ${c.value(installedVersion ?? "?")}`);
|
|
50
|
+
if (installedVersion !== pluginVersion) {
|
|
51
|
+
console.log(` ${c.label("Published:")} ${c.value(pluginVersion)} ${c.warn("(update available — run `opencode-rag setup` to sync)")}`);
|
|
52
|
+
}
|
|
53
|
+
console.log(` ${c.label("Plugin:")} ${existsSync(runtimePluginDir) ? (() => {
|
|
54
|
+
try {
|
|
55
|
+
const stat = lstatSync(runtimePluginDir);
|
|
56
|
+
return stat.isSymbolicLink() ? "junction" : "directory";
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return "?";
|
|
60
|
+
}
|
|
61
|
+
})() : "missing"}`);
|
|
62
|
+
console.log(` ${c.label("SDK:")} ${existsSync(runtimeSdkPluginDir) ? "present" : "missing"}`);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
console.log(` ${c.label("Runtime:")} ${c.warn("not installed")}`);
|
|
66
|
+
console.log(` ${c.label("Run:")} ${c.file("opencode-rag setup")} to install`);
|
|
67
|
+
}
|
|
68
|
+
console.log();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// --- uninstall ---
|
|
72
|
+
if (options.uninstall) {
|
|
73
|
+
console.log(`\n${c.heading("Removing OpenCodeRAG runtime...")}\n`);
|
|
74
|
+
removeIfExists(runtimePluginDir);
|
|
75
|
+
removeIfExists(runtimeSdkDir);
|
|
76
|
+
removeIfExists(versionFile);
|
|
77
|
+
console.log(` ${c.updated("Removed:")} ${c.file(runtimeDir)}`);
|
|
78
|
+
console.log(`\n ${c.success("Done.")} Run ${c.file("npm uninstall -g opencode-rag-plugin")} to remove the global package.\n`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// --- install ---
|
|
82
|
+
console.log(`\n${c.heading("Setting up OpenCodeRAG runtime...")}\n`);
|
|
83
|
+
// Check if already installed and up-to-date
|
|
84
|
+
const installedVersion = readVersionFile(versionFile);
|
|
85
|
+
const runtimeDist = path.join(runtimePluginDir, "dist");
|
|
86
|
+
const alreadyInstalled = existsSync(runtimeDist);
|
|
87
|
+
if (alreadyInstalled && installedVersion === pluginVersion && !options.force) {
|
|
88
|
+
console.log(` ${c.success("Already up-to-date.")} (${c.value(pluginVersion)}) at ${c.file(runtimeDir)}\n`);
|
|
89
|
+
console.log(` ${c.dim("Run `opencode-rag setup --force` to re-install.")}\n`);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const result = await setupRuntime({ force: options.force, version: pluginVersion });
|
|
93
|
+
if (result.success) {
|
|
94
|
+
console.log(` ${c.created("Updated:")} runtime at ${c.file(runtimeDir)}`);
|
|
95
|
+
console.log(` ${c.created("Version:")} ${c.value(pluginVersion)}`);
|
|
96
|
+
console.log(`\n${c.success("Setup complete.")}`);
|
|
97
|
+
console.log(`\n ${c.dim("Next steps:")}`);
|
|
98
|
+
console.log(` ${c.dim(" 1. Restart OpenCode if it is running")}`);
|
|
99
|
+
console.log(` ${c.dim(" 2. Run `opencode-rag init` in each workspace")}`);
|
|
100
|
+
console.log(` ${c.dim(" 3. Run `opencode-rag index` to build the search index")}`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
for (const err of result.errors) {
|
|
104
|
+
console.error(` ${c.error("✗")} ${err}`);
|
|
105
|
+
}
|
|
106
|
+
console.error(`\n ${c.error("Setup failed. Please check the errors above or run with --force.\n")}`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
checkOpenCodeRunning();
|
|
110
|
+
console.log();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
* `status` command — shows index statistics, store health, and configuration summary.
|
|
6
6
|
*/
|
|
7
7
|
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
8
9
|
import fs from "node:fs";
|
|
9
10
|
import { c, resolveCliContext, cleanupContext, logCliError, logCliInfo, formatTimestamp } from "../format.js";
|
|
10
11
|
import { getIndexStatusSummary } from "../../indexer.js";
|
|
12
|
+
import { getPackageMetadata } from "../helpers.js";
|
|
13
|
+
import { checkForUpdate } from "../../core/version-check.js";
|
|
11
14
|
/**
|
|
12
15
|
* Check for a stale index.lock file and clean it up if the owning process is dead.
|
|
13
16
|
*
|
|
@@ -62,7 +65,7 @@ export function registerStatusCommand(program) {
|
|
|
62
65
|
try {
|
|
63
66
|
const cwd = process.cwd();
|
|
64
67
|
let logFilePath = path.resolve(cwd, ".opencode", "opencode-rag.log");
|
|
65
|
-
const ctx = await resolveCliContext(options, logFilePath, { skipProbe: true
|
|
68
|
+
const ctx = await resolveCliContext(options, logFilePath, { skipProbe: true });
|
|
66
69
|
const { config, store, storePath, keywordIndex } = ctx;
|
|
67
70
|
logFilePath = ctx.logFilePath;
|
|
68
71
|
checkStaleLock(storePath, logFilePath);
|
|
@@ -83,7 +86,34 @@ export function registerStatusCommand(program) {
|
|
|
83
86
|
logCliInfo(logFilePath, "status", `${c.label("Pending files:")} ${c.num(summary.pendingFiles)}`);
|
|
84
87
|
logCliInfo(logFilePath, "status", `${c.label("Indexed chunks:")} ${c.num(summary.storeChunkCount)}`);
|
|
85
88
|
logCliInfo(logFilePath, "status", `${c.label("Expected chunks:")} ${c.num(summary.manifestExpectedChunks)}`);
|
|
86
|
-
|
|
89
|
+
// Read watcher status from the background auto-indexer
|
|
90
|
+
const watcherStatusPath = path.join(storePath, "watcher-status.json");
|
|
91
|
+
let watchModeDisplay;
|
|
92
|
+
if (fs.existsSync(watcherStatusPath)) {
|
|
93
|
+
try {
|
|
94
|
+
const raw = fs.readFileSync(watcherStatusPath, "utf-8");
|
|
95
|
+
const ws = JSON.parse(raw);
|
|
96
|
+
if (ws.lastRunAt) {
|
|
97
|
+
const lastRun = formatTimestamp(ws.lastRunAt);
|
|
98
|
+
watchModeDisplay = ws.running
|
|
99
|
+
? c.enabled("active") + c.dim(" (last run: " + lastRun + ")")
|
|
100
|
+
: c.enabled("on") + c.dim(" (last run: " + lastRun + ")");
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
watchModeDisplay = c.enabled("on");
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
watchModeDisplay = c.enabled("on") + c.dim(" (status unknown)");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else if (config.openCode.autoIndex?.enabled) {
|
|
111
|
+
watchModeDisplay = c.enabled("enabled (config)");
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
watchModeDisplay = c.dim("off");
|
|
115
|
+
}
|
|
116
|
+
logCliInfo(logFilePath, "status", `${c.label("Watch mode:")} ${watchModeDisplay}`);
|
|
87
117
|
const kiCount = config.retrieval.hybridSearch?.enabled
|
|
88
118
|
? keywordIndex?.count() ?? 0
|
|
89
119
|
: 0;
|
|
@@ -94,6 +124,38 @@ export function registerStatusCommand(program) {
|
|
|
94
124
|
if (summary.storeChunkCount > 0 && summary.manifestExpectedChunks > 0 && summary.storeChunkCount < summary.manifestExpectedChunks * 0.5) {
|
|
95
125
|
logCliInfo(logFilePath, "status", `${c.label("Data loss detected:")} ${c.warn("yes")} — store has fewer chunks than expected. Run 'opencode-rag index' to rebuild.`);
|
|
96
126
|
}
|
|
127
|
+
// Version & runtime status
|
|
128
|
+
const pkg = getPackageMetadata();
|
|
129
|
+
logCliInfo(logFilePath, "status", `${c.label("Plugin version:")} ${c.value(pkg.version)}`);
|
|
130
|
+
const versionFilePath = path.join(os.homedir(), ".opencode", ".bundle-version");
|
|
131
|
+
const runtimeDir = path.join(os.homedir(), ".opencode", "node_modules", "opencode-rag-plugin", "dist");
|
|
132
|
+
const runtimeOk = fs.existsSync(runtimeDir);
|
|
133
|
+
if (!runtimeOk) {
|
|
134
|
+
logCliInfo(logFilePath, "status", `${c.label("Runtime:")} ${c.warn("not set up — run `opencode-rag setup`")}`);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
try {
|
|
138
|
+
const installedVersion = fs.readFileSync(versionFilePath, "utf-8").trim();
|
|
139
|
+
if (installedVersion !== pkg.version) {
|
|
140
|
+
logCliInfo(logFilePath, "status", `${c.label("Runtime version:")} ${c.warn(installedVersion)} ${c.dim("(sync with `opencode-rag setup`)")}`);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
logCliInfo(logFilePath, "status", `${c.label("Runtime:")} ${c.success("up-to-date")}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
logCliInfo(logFilePath, "status", `${c.label("Runtime:")} ${c.warn("version unknown — run `opencode-rag setup`")}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Async GitHub update check (fire-and-forget, 5s timeout).
|
|
151
|
+
// Runs unless autoUpdate is explicitly disabled.
|
|
152
|
+
if (config.autoUpdate?.enabled) {
|
|
153
|
+
checkForUpdate(pkg.version).then((info) => {
|
|
154
|
+
if (info.updateAvailable) {
|
|
155
|
+
process.stdout.write(` ${c.label("Update:")} ${c.warn(`v${info.latestVersion} available — run \`opencode-rag update\` to install`)}\n`);
|
|
156
|
+
}
|
|
157
|
+
}).catch(() => { });
|
|
158
|
+
}
|
|
97
159
|
await cleanupContext(ctx);
|
|
98
160
|
}
|
|
99
161
|
catch (err) {
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview `update` command — checks GitHub for a newer OpenCodeRAG release and installs it.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* `update` command — checks for
|
|
5
|
+
* `update` command — checks for a newer published version of OpenCodeRAG and,
|
|
6
|
+
* by default, installs it (via `npm install -g ...@latest`) then re-syncs the
|
|
7
|
+
* OpenCode runtime junctions so the new build is picked up on next restart.
|
|
6
8
|
*/
|
|
7
9
|
import type { Command } from "commander";
|
|
8
10
|
/**
|
|
9
11
|
* Register the `update` command on the given Commander program.
|
|
10
12
|
*
|
|
11
|
-
* Checks the GitHub repository for a newer release, displays the current
|
|
12
|
-
* and latest versions, and optionally applies the update by pulling
|
|
13
|
-
* the latest code and rebuilding.
|
|
14
|
-
*
|
|
15
13
|
* @param program - The Commander `Command` instance to register on.
|
|
16
14
|
*/
|
|
17
15
|
export declare function registerUpdateCommand(program: Command): void;
|
|
@@ -1,77 +1,63 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview `update` command — checks GitHub for a newer OpenCodeRAG release and installs it.
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
|
-
* `update` command — checks for
|
|
5
|
+
* `update` command — checks for a newer published version of OpenCodeRAG and,
|
|
6
|
+
* by default, installs it (via `npm install -g ...@latest`) then re-syncs the
|
|
7
|
+
* OpenCode runtime junctions so the new build is picked up on next restart.
|
|
6
8
|
*/
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import { getCurrentVersion, checkForUpdate, applyUpdate } from "../../updater.js";
|
|
9
9
|
import { c } from "../format.js";
|
|
10
|
-
import {
|
|
10
|
+
import { checkForUpdate, getCurrentVersion, installLatestUpdate } from "../../core/version-check.js";
|
|
11
11
|
/**
|
|
12
12
|
* Register the `update` command on the given Commander program.
|
|
13
13
|
*
|
|
14
|
-
* Checks the GitHub repository for a newer release, displays the current
|
|
15
|
-
* and latest versions, and optionally applies the update by pulling
|
|
16
|
-
* the latest code and rebuilding.
|
|
17
|
-
*
|
|
18
14
|
* @param program - The Commander `Command` instance to register on.
|
|
19
15
|
*/
|
|
20
16
|
export function registerUpdateCommand(program) {
|
|
21
17
|
program
|
|
22
18
|
.command("update")
|
|
23
|
-
.description("Check for and install
|
|
24
|
-
.option("--check", "only check
|
|
25
|
-
.option("-
|
|
26
|
-
.option("-v, --verbose", "show build/install output")
|
|
19
|
+
.description("Check for and install the newest published version of OpenCodeRAG")
|
|
20
|
+
.option("--check", "only check whether an update is available; do not install")
|
|
21
|
+
.option("-v, --verbose", "stream npm/setup output to the console")
|
|
27
22
|
.action(async (options) => {
|
|
23
|
+
const currentVersion = getCurrentVersion();
|
|
24
|
+
console.log(`\n${c.heading("OpenCodeRAG Update")}\n`);
|
|
25
|
+
console.log(` ${c.label("Current version:")} ${c.value(currentVersion)}`);
|
|
26
|
+
console.log(` ${c.label("Checking...")} `);
|
|
27
|
+
let info;
|
|
28
28
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
console.log(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
console.log();
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
console.log(` ${c.label("Applying update...")}\n`);
|
|
60
|
-
const result = applyUpdate({
|
|
61
|
-
repoRoot: path.resolve(getPackageRoot()),
|
|
62
|
-
verbose: options.verbose ?? false,
|
|
63
|
-
});
|
|
64
|
-
if (result.success) {
|
|
65
|
-
console.log(` ${c.success(result.message)}\n`);
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
console.error(` ${c.error(result.message)}\n`);
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
29
|
+
info = await checkForUpdate(currentVersion);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
console.log(`\n ${c.warn("Could not reach the update server. Check your network and try again.")}\n`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!info.updateAvailable) {
|
|
37
|
+
console.log(`\n ${c.success("Already up-to-date.")} (${c.value(info.latestVersion || currentVersion)})\n`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
console.log(` ${c.label("Latest version:")} ${c.value(info.latestVersion)}`);
|
|
41
|
+
if (info.publishedAt) {
|
|
42
|
+
console.log(` ${c.label("Published:")} ${c.dim(info.publishedAt)}`);
|
|
43
|
+
}
|
|
44
|
+
if (info.releaseUrl) {
|
|
45
|
+
console.log(` ${c.label("Release notes:")} ${c.file(info.releaseUrl)}`);
|
|
46
|
+
}
|
|
47
|
+
if (options.check) {
|
|
48
|
+
console.log(`\n ${c.warn("Update available.")} Run ${c.file("opencode-rag update")} to install.\n`);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
console.log(`\n ${c.dim("Installing newest version...")}\n`);
|
|
52
|
+
const result = await installLatestUpdate({ verbose: options.verbose });
|
|
53
|
+
if (result.success) {
|
|
54
|
+
console.log(` ${c.success("✓")} ${result.message}`);
|
|
55
|
+
console.log(`\n ${c.dim("Restart OpenCode if it is running to load the new version.")}\n`);
|
|
71
56
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
console.error(c.error(
|
|
57
|
+
else {
|
|
58
|
+
console.error(` ${c.error("✗")} ${result.message}`);
|
|
59
|
+
console.error(`\n ${c.error("Update failed. You can retry with `opencode-rag update` or install manually:")}\n`);
|
|
60
|
+
console.error(` ${c.dim(" npm install -g opencode-rag-plugin@latest && opencode-rag setup")}\n`);
|
|
75
61
|
process.exit(1);
|
|
76
62
|
}
|
|
77
63
|
});
|
package/dist/cli/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { realpathSync } from "node:fs";
|
|
|
14
14
|
import { basename, dirname } from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { getPackageMetadata } from "./helpers.js";
|
|
17
|
-
import { registerIndexCommand, registerQueryCommand, registerClearCommand, registerStatusCommand, registerListCommand, registerShowCommand, registerDumpCommand, registerInitCommand, registerUiCommand, registerMcpCommand, registerUpdateCommand, registerEvalSessionsCommand, registerEvalAnalyzeCommand, registerEvalCompareCommand, registerDescribeImageCommand, } from "./commands/index.js";
|
|
17
|
+
import { registerIndexCommand, registerQueryCommand, registerClearCommand, registerStatusCommand, registerListCommand, registerShowCommand, registerDumpCommand, registerInitCommand, registerUiCommand, registerMcpCommand, registerSetupCommand, registerUpdateCommand, registerEvalSessionsCommand, registerEvalAnalyzeCommand, registerEvalCompareCommand, registerDescribeImageCommand, } from "./commands/index.js";
|
|
18
18
|
/**
|
|
19
19
|
* The top-level Commander program instance that defines the `opencode-rag` CLI.
|
|
20
20
|
*
|
|
@@ -38,6 +38,7 @@ registerDumpCommand(program);
|
|
|
38
38
|
registerDescribeImageCommand(program);
|
|
39
39
|
registerUiCommand(program);
|
|
40
40
|
registerMcpCommand(program);
|
|
41
|
+
registerSetupCommand(program);
|
|
41
42
|
registerUpdateCommand(program);
|
|
42
43
|
registerEvalSessionsCommand(program);
|
|
43
44
|
registerEvalAnalyzeCommand(program);
|
package/dist/content/image.js
CHANGED
|
@@ -19,14 +19,22 @@ export function isImageFile(fp) {
|
|
|
19
19
|
function isBmpFile(fp) {
|
|
20
20
|
return fp.toLowerCase().endsWith(".bmp");
|
|
21
21
|
}
|
|
22
|
+
const MAX_BMP_DIMENSION = 10_000;
|
|
23
|
+
const MAX_BMP_ALLOC = 500 * 1024 * 1024; // 500 MB
|
|
22
24
|
function decodeBmp(buffer) {
|
|
23
25
|
const signature = buffer.toString("ascii", 0, 2);
|
|
24
26
|
if (signature !== "BM")
|
|
25
27
|
throw new Error("Not a BMP file");
|
|
28
|
+
if (buffer.length < 54)
|
|
29
|
+
throw new Error("Truncated BMP header");
|
|
26
30
|
const dibSize = buffer.readUInt32LE(14);
|
|
27
31
|
const width = buffer.readInt32LE(18);
|
|
28
32
|
const rawHeight = buffer.readInt32LE(22);
|
|
29
33
|
const bitsPerPixel = buffer.readUInt16LE(28);
|
|
34
|
+
if (width <= 0 || Math.abs(rawHeight) <= 0)
|
|
35
|
+
throw new Error("Invalid BMP dimensions");
|
|
36
|
+
if (width > MAX_BMP_DIMENSION || Math.abs(rawHeight) > MAX_BMP_DIMENSION)
|
|
37
|
+
throw new Error(`BMP dimensions (${width}x${rawHeight}) exceed ${MAX_BMP_DIMENSION}x${MAX_BMP_DIMENSION} limit`);
|
|
30
38
|
if (bitsPerPixel !== 24 && bitsPerPixel !== 32)
|
|
31
39
|
throw new Error(`Unsupported BMP bit depth: ${bitsPerPixel}. Only 24 and 32 bit are supported.`);
|
|
32
40
|
if (dibSize < 40)
|
|
@@ -38,8 +46,17 @@ function decodeBmp(buffer) {
|
|
|
38
46
|
const rowSize = Math.floor((bitsPerPixel * width + 31) / 32) * 4;
|
|
39
47
|
const topDown = rawHeight < 0;
|
|
40
48
|
const absHeight = Math.abs(rawHeight);
|
|
49
|
+
const allocSize = width * absHeight * channels;
|
|
50
|
+
if (allocSize > MAX_BMP_ALLOC)
|
|
51
|
+
throw new Error(`BMP allocation (${allocSize} bytes) exceeds ${MAX_BMP_ALLOC} byte limit`);
|
|
41
52
|
const pixelOffset = buffer.readUInt32LE(10);
|
|
42
|
-
|
|
53
|
+
// Clamp dimensions to prevent OOM from crafted BMP headers.
|
|
54
|
+
const MAX_BMP_DIM = 16384;
|
|
55
|
+
if (width > MAX_BMP_DIM || absHeight > MAX_BMP_DIM) {
|
|
56
|
+
throw new Error(`BMP dimensions too large: ${width}x${absHeight} (max ${MAX_BMP_DIM})`);
|
|
57
|
+
}
|
|
58
|
+
const pixels = Buffer.alloc(allocSize);
|
|
59
|
+
const lastValidSrc = buffer.length - 1;
|
|
43
60
|
for (let y = 0; y < absHeight; y++) {
|
|
44
61
|
const srcY = topDown ? y : absHeight - 1 - y;
|
|
45
62
|
const srcRow = pixelOffset + srcY * rowSize;
|
|
@@ -47,6 +64,10 @@ function decodeBmp(buffer) {
|
|
|
47
64
|
for (let x = 0; x < width; x++) {
|
|
48
65
|
const srcPx = srcRow + x * (bitsPerPixel / 8);
|
|
49
66
|
const dstPx = dstRow + x * channels;
|
|
67
|
+
if (srcPx + 3 > lastValidSrc) {
|
|
68
|
+
pixels.fill(0, dstPx, dstPx + channels);
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
50
71
|
if (channels === 4) {
|
|
51
72
|
pixels[dstPx] = buffer[srcPx + 2];
|
|
52
73
|
pixels[dstPx + 1] = buffer[srcPx + 1];
|
|
@@ -94,8 +115,8 @@ export async function resizeImage(buffer, filePath, maxDimension) {
|
|
|
94
115
|
.jpeg({ quality: 80 })
|
|
95
116
|
.toBuffer();
|
|
96
117
|
}
|
|
97
|
-
catch {
|
|
98
|
-
|
|
118
|
+
catch (err) {
|
|
119
|
+
throw new Error(`Image resize failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
99
120
|
}
|
|
100
121
|
}
|
|
101
122
|
/**
|
package/dist/content/reader.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { RagConfig } from "../core/config.js";
|
|
5
5
|
import { type FileManifest } from "../core/manifest.js";
|
|
6
|
+
import { DescriptionCache } from "../core/desc-cache.js";
|
|
7
|
+
import { type ImageVisionProvider } from "../chunker/image.js";
|
|
6
8
|
/** Metadata and extracted content for a single workspace file discovered during scanning. */
|
|
7
9
|
export interface WorkspaceFile {
|
|
8
10
|
filePath: string;
|
|
@@ -32,6 +34,9 @@ export declare function walkFiles(dir: string, extensions: Set<string>, excludeD
|
|
|
32
34
|
* Scan the workspace directory for indexable files, reading content or dispatching
|
|
33
35
|
* binary extraction (PDF, DOCX, DOC, Excel, images). Respects the file manifest
|
|
34
36
|
* for incremental re-indexing by skipping unchanged files.
|
|
37
|
+
*
|
|
38
|
+
* @param descCache - Optional persistent description cache. When set, image
|
|
39
|
+
* descriptions are cached and reused across sessions (survives aborted runs).
|
|
35
40
|
*/
|
|
36
|
-
export declare function scanWorkspaceFiles(cwd: string, config: RagConfig, logger?: Logger, manifest?: FileManifest, filterPaths?: string[]): Promise<WorkspaceFile[]>;
|
|
41
|
+
export declare function scanWorkspaceFiles(cwd: string, config: RagConfig, logger?: Logger, manifest?: FileManifest, filterPaths?: string[], injectedVisionProvider?: ImageVisionProvider, descCache?: DescriptionCache): Promise<WorkspaceFile[]>;
|
|
37
42
|
export {};
|