gitnexus 1.6.12-rc.28 → 1.6.12-rc.29
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/cli/i18n/en.d.ts +1 -2
- package/dist/cli/i18n/en.js +1 -2
- package/dist/cli/i18n/resources.d.ts +1 -3
- package/dist/cli/i18n/zh-CN.d.ts +0 -1
- package/dist/cli/i18n/zh-CN.js +1 -2
- package/dist/cli/index.js +5 -9
- package/dist/core/embeddings/http-client.js +13 -45
- package/package.json +1 -1
- package/dist/cli/embeddings-sync.d.ts +0 -2
- package/dist/cli/embeddings-sync.js +0 -127
package/dist/cli/i18n/en.d.ts
CHANGED
|
@@ -140,7 +140,6 @@ export declare const en: {
|
|
|
140
140
|
readonly 'help.watch.details': "\n`gitnexus watch` does not start a watcher.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n";
|
|
141
141
|
readonly 'error.watch.ambiguous': "`gitnexus watch` is ambiguous.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n";
|
|
142
142
|
readonly 'help.command.analyze.description': "Index a repository (full analysis)";
|
|
143
|
-
readonly 'help.command.embeddings.sync.description': "Add missing embeddings to an existing index, checkpointing periodically for safe resume";
|
|
144
143
|
readonly 'help.command.index.description': "Register an existing .gitnexus/ folder into the global registry (no re-analysis needed)";
|
|
145
144
|
readonly 'help.command.serve.description': "Start local HTTP server for web UI connection";
|
|
146
145
|
readonly 'help.command.mcp.description': "Start MCP server. Default: stdio. Use --http for a remote HTTP server (Streamable HTTP at POST /mcp + legacy SSE at GET /sse, POST /messages).";
|
|
@@ -278,5 +277,5 @@ export declare const en: {
|
|
|
278
277
|
readonly 'help.option.group.contracts.repo': "Filter by repo";
|
|
279
278
|
readonly 'help.option.group.contracts.unmatched': "Show only unmatched contracts";
|
|
280
279
|
readonly 'help.identityCache.environment': "\nAnalyzer identity cache:\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir\n Operator-trusted persistent cache for warm cross-process status. The directory must pre-exist, be outside the GitNexus package/build roots, and contain no symlink or junction components. Defaults remain fail-closed on platforms without POSIX ownership APIs.";
|
|
281
|
-
readonly 'help.analyze.environment': "\nEnvironment variables:\n GITNEXUS_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir Operator-trusted persistent analyzer identity cache; must pre-exist, be outside package/build roots, and contain no symlink/junction components.\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker idle timeout in milliseconds. Default 30000.\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL auto-checkpoint threshold in bytes (default 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB).\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker job byte budget. Default 8388608.\n GITNEXUS_WORKER_POOL_SIZE=N Parse worker count override. Default cores-1 capped at 16.\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N Concurrent in-flight parse chunks. Default 2.\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N Max replacement spawns per slot before drop. Default 3.\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N Total retry wall-time per job. Default 5x sub-batch timeout.\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N Per-slot deaths to trip circuit breaker. Default max(3, poolSize).\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N Max wait at pool shutdown for a retired worker still inside native code (terminated at its next safe point instead of aborting the process). Default 30000.\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning. Default 20000.\n GITNEXUS_EMBEDDING_THREADS=N Limit local ONNX CPU threads for --embeddings.\n
|
|
280
|
+
readonly 'help.analyze.environment': "\nEnvironment variables:\n GITNEXUS_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir Operator-trusted persistent analyzer identity cache; must pre-exist, be outside package/build roots, and contain no symlink/junction components.\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker idle timeout in milliseconds. Default 30000.\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL auto-checkpoint threshold in bytes (default 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB).\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker job byte budget. Default 8388608.\n GITNEXUS_WORKER_POOL_SIZE=N Parse worker count override. Default cores-1 capped at 16.\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N Concurrent in-flight parse chunks. Default 2.\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N Max replacement spawns per slot before drop. Default 3.\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N Total retry wall-time per job. Default 5x sub-batch timeout.\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N Per-slot deaths to trip circuit breaker. Default max(3, poolSize).\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N Max wait at pool shutdown for a retired worker still inside native code (terminated at its next safe point instead of aborting the process). Default 30000.\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning. Default 20000.\n GITNEXUS_EMBEDDING_THREADS=N Limit local ONNX CPU threads for --embeddings.\n GITNEXUS_SEMANTIC_EXACT_SCAN_LIMIT=N Max embedding chunks for exact-scan fallback. Default 10000.\n GITNEXUS_VECTOR_MAX_DISTANCE=N Max accepted semantic/vector cosine distance (0 < N <= 2; higher values clamp to 2). Default 0.6 for MCP, 0.5 elsewhere.\n\nFlags override the corresponding env vars when both are provided.\n\nTip: `.gitnexusignore` supports `.gitignore`-style negation. Add e.g.\n `!__tests__/` to index a directory that is auto-filtered by default (#771).";
|
|
282
281
|
};
|
package/dist/cli/i18n/en.js
CHANGED
|
@@ -142,7 +142,6 @@ export const en = {
|
|
|
142
142
|
'help.watch.details': '\n`gitnexus watch` does not start a watcher.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n',
|
|
143
143
|
'error.watch.ambiguous': '`gitnexus watch` is ambiguous.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n',
|
|
144
144
|
'help.command.analyze.description': 'Index a repository (full analysis)',
|
|
145
|
-
'help.command.embeddings.sync.description': 'Add missing embeddings to an existing index, checkpointing periodically for safe resume',
|
|
146
145
|
'help.command.index.description': 'Register an existing .gitnexus/ folder into the global registry (no re-analysis needed)',
|
|
147
146
|
'help.command.serve.description': 'Start local HTTP server for web UI connection',
|
|
148
147
|
'help.command.mcp.description': 'Start MCP server. Default: stdio. Use --http for a remote HTTP server (Streamable HTTP at POST /mcp + legacy SSE at GET /sse, POST /messages).',
|
|
@@ -280,5 +279,5 @@ export const en = {
|
|
|
280
279
|
'help.option.group.contracts.repo': 'Filter by repo',
|
|
281
280
|
'help.option.group.contracts.unmatched': 'Show only unmatched contracts',
|
|
282
281
|
'help.identityCache.environment': '\nAnalyzer identity cache:\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir\n Operator-trusted persistent cache for warm cross-process status. The directory must pre-exist, be outside the GitNexus package/build roots, and contain no symlink or junction components. Defaults remain fail-closed on platforms without POSIX ownership APIs.',
|
|
283
|
-
'help.analyze.environment': '\nEnvironment variables:\n GITNEXUS_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir Operator-trusted persistent analyzer identity cache; must pre-exist, be outside package/build roots, and contain no symlink/junction components.\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker idle timeout in milliseconds. Default 30000.\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL auto-checkpoint threshold in bytes (default 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB).\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker job byte budget. Default 8388608.\n GITNEXUS_WORKER_POOL_SIZE=N Parse worker count override. Default cores-1 capped at 16.\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N Concurrent in-flight parse chunks. Default 2.\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N Max replacement spawns per slot before drop. Default 3.\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N Total retry wall-time per job. Default 5x sub-batch timeout.\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N Per-slot deaths to trip circuit breaker. Default max(3, poolSize).\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N Max wait at pool shutdown for a retired worker still inside native code (terminated at its next safe point instead of aborting the process). Default 30000.\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning. Default 20000.\n GITNEXUS_EMBEDDING_THREADS=N Limit local ONNX CPU threads for --embeddings.\n
|
|
282
|
+
'help.analyze.environment': '\nEnvironment variables:\n GITNEXUS_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir Operator-trusted persistent analyzer identity cache; must pre-exist, be outside package/build roots, and contain no symlink/junction components.\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker idle timeout in milliseconds. Default 30000.\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL auto-checkpoint threshold in bytes (default 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB).\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker job byte budget. Default 8388608.\n GITNEXUS_WORKER_POOL_SIZE=N Parse worker count override. Default cores-1 capped at 16.\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N Concurrent in-flight parse chunks. Default 2.\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N Max replacement spawns per slot before drop. Default 3.\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N Total retry wall-time per job. Default 5x sub-batch timeout.\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N Per-slot deaths to trip circuit breaker. Default max(3, poolSize).\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N Max wait at pool shutdown for a retired worker still inside native code (terminated at its next safe point instead of aborting the process). Default 30000.\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning. Default 20000.\n GITNEXUS_EMBEDDING_THREADS=N Limit local ONNX CPU threads for --embeddings.\n GITNEXUS_SEMANTIC_EXACT_SCAN_LIMIT=N Max embedding chunks for exact-scan fallback. Default 10000.\n GITNEXUS_VECTOR_MAX_DISTANCE=N Max accepted semantic/vector cosine distance (0 < N <= 2; higher values clamp to 2). Default 0.6 for MCP, 0.5 elsewhere.\n\nFlags override the corresponding env vars when both are provided.\n\nTip: `.gitnexusignore` supports `.gitignore`-style negation. Add e.g.\n `!__tests__/` to index a directory that is auto-filtered by default (#771).',
|
|
284
283
|
};
|
|
@@ -141,7 +141,6 @@ export declare const cliResources: {
|
|
|
141
141
|
readonly 'help.watch.details': "\n`gitnexus watch` does not start a watcher.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n";
|
|
142
142
|
readonly 'error.watch.ambiguous': "`gitnexus watch` is ambiguous.\n Local working-tree incremental index: gitnexus analyze --watch\n Scheduled remote clone/pull + analyze: gitnexus auto-sync start\n";
|
|
143
143
|
readonly 'help.command.analyze.description': "Index a repository (full analysis)";
|
|
144
|
-
readonly 'help.command.embeddings.sync.description': "Add missing embeddings to an existing index, checkpointing periodically for safe resume";
|
|
145
144
|
readonly 'help.command.index.description': "Register an existing .gitnexus/ folder into the global registry (no re-analysis needed)";
|
|
146
145
|
readonly 'help.command.serve.description': "Start local HTTP server for web UI connection";
|
|
147
146
|
readonly 'help.command.mcp.description': "Start MCP server. Default: stdio. Use --http for a remote HTTP server (Streamable HTTP at POST /mcp + legacy SSE at GET /sse, POST /messages).";
|
|
@@ -279,7 +278,7 @@ export declare const cliResources: {
|
|
|
279
278
|
readonly 'help.option.group.contracts.repo': "Filter by repo";
|
|
280
279
|
readonly 'help.option.group.contracts.unmatched': "Show only unmatched contracts";
|
|
281
280
|
readonly 'help.identityCache.environment': "\nAnalyzer identity cache:\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir\n Operator-trusted persistent cache for warm cross-process status. The directory must pre-exist, be outside the GitNexus package/build roots, and contain no symlink or junction components. Defaults remain fail-closed on platforms without POSIX ownership APIs.";
|
|
282
|
-
readonly 'help.analyze.environment': "\nEnvironment variables:\n GITNEXUS_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir Operator-trusted persistent analyzer identity cache; must pre-exist, be outside package/build roots, and contain no symlink/junction components.\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker idle timeout in milliseconds. Default 30000.\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL auto-checkpoint threshold in bytes (default 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB).\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker job byte budget. Default 8388608.\n GITNEXUS_WORKER_POOL_SIZE=N Parse worker count override. Default cores-1 capped at 16.\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N Concurrent in-flight parse chunks. Default 2.\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N Max replacement spawns per slot before drop. Default 3.\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N Total retry wall-time per job. Default 5x sub-batch timeout.\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N Per-slot deaths to trip circuit breaker. Default max(3, poolSize).\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N Max wait at pool shutdown for a retired worker still inside native code (terminated at its next safe point instead of aborting the process). Default 30000.\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning. Default 20000.\n GITNEXUS_EMBEDDING_THREADS=N Limit local ONNX CPU threads for --embeddings.\n
|
|
281
|
+
readonly 'help.analyze.environment': "\nEnvironment variables:\n GITNEXUS_NO_GITIGNORE=1 Skip .gitignore parsing (still reads .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N Override large-file skip threshold (KB). Default 512, max 32768.\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir Operator-trusted persistent analyzer identity cache; must pre-exist, be outside package/build roots, and contain no symlink/junction components.\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker idle timeout in milliseconds. Default 30000.\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL auto-checkpoint threshold in bytes (default 67108864 = 64 MiB; -1 keeps Ladybug stock ~16 MiB).\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker job byte budget. Default 8388608.\n GITNEXUS_WORKER_POOL_SIZE=N Parse worker count override. Default cores-1 capped at 16.\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N Concurrent in-flight parse chunks. Default 2.\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N Max replacement spawns per slot before drop. Default 3.\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N Total retry wall-time per job. Default 5x sub-batch timeout.\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N Per-slot deaths to trip circuit breaker. Default max(3, poolSize).\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N Max wait at pool shutdown for a retired worker still inside native code (terminated at its next safe point instead of aborting the process). Default 30000.\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N Per-file wall-clock budget for C++ capture extraction; on breach the file keeps partial captures with a warning. Default 20000.\n GITNEXUS_EMBEDDING_THREADS=N Limit local ONNX CPU threads for --embeddings.\n GITNEXUS_SEMANTIC_EXACT_SCAN_LIMIT=N Max embedding chunks for exact-scan fallback. Default 10000.\n GITNEXUS_VECTOR_MAX_DISTANCE=N Max accepted semantic/vector cosine distance (0 < N <= 2; higher values clamp to 2). Default 0.6 for MCP, 0.5 elsewhere.\n\nFlags override the corresponding env vars when both are provided.\n\nTip: `.gitnexusignore` supports `.gitignore`-style negation. Add e.g.\n `!__tests__/` to index a directory that is auto-filtered by default (#771).";
|
|
283
282
|
};
|
|
284
283
|
readonly 'zh-CN': {
|
|
285
284
|
'common.notIndexed': string;
|
|
@@ -423,7 +422,6 @@ export declare const cliResources: {
|
|
|
423
422
|
'help.watch.details': string;
|
|
424
423
|
'error.watch.ambiguous': string;
|
|
425
424
|
'help.command.analyze.description': string;
|
|
426
|
-
'help.command.embeddings.sync.description': string;
|
|
427
425
|
'help.command.index.description': string;
|
|
428
426
|
'help.command.serve.description': string;
|
|
429
427
|
'help.command.mcp.description': string;
|
package/dist/cli/i18n/zh-CN.d.ts
CHANGED
|
@@ -140,7 +140,6 @@ export declare const zhCN: {
|
|
|
140
140
|
'help.watch.details': string;
|
|
141
141
|
'error.watch.ambiguous': string;
|
|
142
142
|
'help.command.analyze.description': string;
|
|
143
|
-
'help.command.embeddings.sync.description': string;
|
|
144
143
|
'help.command.index.description': string;
|
|
145
144
|
'help.command.serve.description': string;
|
|
146
145
|
'help.command.mcp.description': string;
|
package/dist/cli/i18n/zh-CN.js
CHANGED
|
@@ -140,7 +140,6 @@ export const zhCN = {
|
|
|
140
140
|
'help.watch.details': '\n`gitnexus watch` 不会启动监视器。\n 本地工作区增量索引:gitnexus analyze --watch\n 定时远程 clone/pull 并分析:gitnexus auto-sync start\n',
|
|
141
141
|
'error.watch.ambiguous': '`gitnexus watch` 含义不明确。\n 本地工作区增量索引:gitnexus analyze --watch\n 定时远程 clone/pull 并分析:gitnexus auto-sync start\n',
|
|
142
142
|
'help.command.analyze.description': '索引仓库(完整分析)',
|
|
143
|
-
'help.command.embeddings.sync.description': '向现有索引添加缺失的嵌入,并定期保存检查点以安全续跑',
|
|
144
143
|
'help.command.index.description': '将现有 .gitnexus/ 文件夹注册到全局注册表(无需重新分析)',
|
|
145
144
|
'help.command.serve.description': '启动供 Web UI 连接的本地 HTTP 服务器',
|
|
146
145
|
'help.command.mcp.description': '启动 MCP 服务器。默认为 stdio。使用 --http 启动远程 HTTP 服务器(Streamable HTTP: POST /mcp + 遗留 SSE: GET /sse, POST /messages)。',
|
|
@@ -278,5 +277,5 @@ export const zhCN = {
|
|
|
278
277
|
'help.option.group.contracts.repo': '按仓库过滤',
|
|
279
278
|
'help.option.group.contracts.unmatched': '仅显示未匹配契约',
|
|
280
279
|
'help.identityCache.environment': '\n分析器身份缓存:\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir\n 由操作员明确信任的持久缓存,用于跨进程快速查询状态。目录必须预先存在、位于 GitNexus 包/构建根目录之外,且路径中不得包含符号链接或 junction。缺少 POSIX 所有权 API 的平台默认保持故障关闭。',
|
|
281
|
-
'help.analyze.environment': '\n环境变量:\n GITNEXUS_NO_GITIGNORE=1 跳过 .gitignore 解析(仍读取 .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N 覆盖大文件跳过阈值(KB)。默认 512,最大 32768。\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir 由操作员明确信任的持久分析器身份缓存;目录必须预先存在、位于包/构建根目录之外,且路径中不得包含符号链接或 junction。\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker 空闲超时(毫秒)。默认 30000。\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL 自动 checkpoint 阈值(字节,默认 67108864 = 64 MiB;-1 保持 Ladybug 默认约 16 MiB)。\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker 作业字节预算。默认 8388608。\n GITNEXUS_WORKER_POOL_SIZE=N 解析 worker 数量覆盖值。默认 cores-1,最多 16。\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N 并发进行中的解析分块数。默认 2。\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N 每个 slot 丢弃前允许的最大替换进程数。默认 3。\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N 每个作业的总重试墙钟时间。默认 5 倍子批次超时。\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N 每个 slot 触发熔断的死亡次数。默认 max(3, poolSize)。\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N 线程池关闭时等待仍在原生代码中的已退役 worker 的最长时间(到达安全点后再终止,避免进程级 abort)。默认 30000。\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N C++ 捕获提取的每文件墙钟预算;超出后该文件保留部分捕获并输出警告。默认 20000。\n GITNEXUS_EMBEDDING_THREADS=N 限制 --embeddings 的本地 ONNX CPU 线程数。\n
|
|
280
|
+
'help.analyze.environment': '\n环境变量:\n GITNEXUS_NO_GITIGNORE=1 跳过 .gitignore 解析(仍读取 .gitnexusignore)\n GITNEXUS_MAX_FILE_SIZE=N 覆盖大文件跳过阈值(KB)。默认 512,最大 32768。\n GITNEXUS_ANALYZER_IDENTITY_CACHE_DIR=/absolute/protected/dir 由操作员明确信任的持久分析器身份缓存;目录必须预先存在、位于包/构建根目录之外,且路径中不得包含符号链接或 junction。\n GITNEXUS_WORKER_SUB_BATCH_TIMEOUT_MS=N Worker 空闲超时(毫秒)。默认 30000。\n GITNEXUS_WAL_CHECKPOINT_THRESHOLD=N LadybugDB WAL 自动 checkpoint 阈值(字节,默认 67108864 = 64 MiB;-1 保持 Ladybug 默认约 16 MiB)。\n GITNEXUS_WORKER_SUB_BATCH_MAX_BYTES=N Worker 作业字节预算。默认 8388608。\n GITNEXUS_WORKER_POOL_SIZE=N 解析 worker 数量覆盖值。默认 cores-1,最多 16。\n GITNEXUS_PARSE_CHUNK_CONCURRENCY=N 并发进行中的解析分块数。默认 2。\n GITNEXUS_WORKER_MAX_RESPAWNS_PER_SLOT=N 每个 slot 丢弃前允许的最大替换进程数。默认 3。\n GITNEXUS_WORKER_MAX_CUMULATIVE_TIMEOUT_MS=N 每个作业的总重试墙钟时间。默认 5 倍子批次超时。\n GITNEXUS_WORKER_CONSECUTIVE_FAILURE_THRESHOLD=N 每个 slot 触发熔断的死亡次数。默认 max(3, poolSize)。\n GITNEXUS_WORKER_SHUTDOWN_DRAIN_MS=N 线程池关闭时等待仍在原生代码中的已退役 worker 的最长时间(到达安全点后再终止,避免进程级 abort)。默认 30000。\n GITNEXUS_CPP_CAPTURE_BUDGET_MS=N C++ 捕获提取的每文件墙钟预算;超出后该文件保留部分捕获并输出警告。默认 20000。\n GITNEXUS_EMBEDDING_THREADS=N 限制 --embeddings 的本地 ONNX CPU 线程数。\n GITNEXUS_SEMANTIC_EXACT_SCAN_LIMIT=N exact-scan 回退的最大嵌入分块数。默认 10000。\n GITNEXUS_VECTOR_MAX_DISTANCE=N 语义/向量搜索接受的最大余弦距离(0 < N <= 2;超出则钳制为 2)。MCP 默认 0.6,其他路径默认 0.5。\n\n当参数和对应环境变量同时提供时,参数优先。\n\n提示:`.gitnexusignore` 支持 `.gitignore` 风格的取反。比如添加\n `!__tests__/` 可以索引默认自动过滤的目录(#771)。',
|
|
282
281
|
};
|
package/dist/cli/index.js
CHANGED
|
@@ -184,21 +184,17 @@ program
|
|
|
184
184
|
.command('update')
|
|
185
185
|
.description('Install the latest published GitNexus globally (`npm i -g gitnexus@<x.y.z>`).')
|
|
186
186
|
.action(createLazyAction(() => import('./update.js'), 'updateCommand'));
|
|
187
|
-
|
|
187
|
+
program
|
|
188
188
|
.command('embeddings')
|
|
189
|
-
.description(
|
|
190
|
-
embeddings
|
|
189
|
+
.description('Manage the on-demand local embedding runtime')
|
|
191
190
|
.command('install')
|
|
192
|
-
.description(
|
|
191
|
+
.description('Install the local embedding stack (@huggingface/transformers + onnxruntime-node) on demand. ' +
|
|
192
|
+
'Heals installs where npm skipped the optional packages (e.g. behind an HTTP proxy, #2370). ' +
|
|
193
|
+
'Downloads only from your configured npm registry — mirrors and proxies apply.')
|
|
193
194
|
.option('--cuda', "Also download the CUDA GPU binaries (runs onnxruntime-node's NuGet postinstall; " +
|
|
194
195
|
'set GLOBAL_AGENT_HTTPS_PROXY behind a proxy)')
|
|
195
196
|
.option('--force', 'Install into the runtime prefix even when the stack already resolves')
|
|
196
197
|
.action(createLazyAction(() => import('./embeddings.js'), 'embeddingsInstallCommand'));
|
|
197
|
-
embeddings
|
|
198
|
-
.command('sync [path]')
|
|
199
|
-
.description(t('help.command.embeddings.sync.description'))
|
|
200
|
-
.addHelpText('after', () => t('help.analyze.environment'))
|
|
201
|
-
.action(createLbugLazyAction(() => import('./embeddings-sync.js'), 'embeddingsSyncCommand'));
|
|
202
198
|
program
|
|
203
199
|
.command('clean')
|
|
204
200
|
.description('Delete GitNexus index for current repo')
|
|
@@ -157,7 +157,6 @@ const readConfig = () => {
|
|
|
157
157
|
retryCapMs: parsePositiveIntegerEnv('GITNEXUS_EMBEDDING_RETRY_CAP_MS', HTTP_RETRY_CAP_MS, 300_000),
|
|
158
158
|
minIntervalMs: parseNonNegativeIntegerEnv('GITNEXUS_EMBEDDING_MIN_INTERVAL_MS', 0, 300_000),
|
|
159
159
|
timeoutMs: parsePositiveIntegerEnv(HTTP_TIMEOUT_ENV, DEFAULT_HTTP_TIMEOUT_MS, MAX_HTTP_TIMEOUT_MS),
|
|
160
|
-
retryTimeouts: parseNonNegativeIntegerEnv('GITNEXUS_EMBEDDING_RETRY_TIMEOUTS', 0, 1) === 1,
|
|
161
160
|
requestDimensions,
|
|
162
161
|
};
|
|
163
162
|
};
|
|
@@ -278,23 +277,6 @@ class RetryableEmbeddingBodyError extends Error {
|
|
|
278
277
|
this.name = 'RetryableEmbeddingBodyError';
|
|
279
278
|
}
|
|
280
279
|
}
|
|
281
|
-
class RetryableEmbeddingTimeoutError extends Error {
|
|
282
|
-
timeoutMs;
|
|
283
|
-
constructor(timeoutMs, options) {
|
|
284
|
-
super(`Embedding request timed out after ${timeoutMs}ms`, options?.cause !== undefined ? { cause: options.cause } : undefined);
|
|
285
|
-
this.timeoutMs = timeoutMs;
|
|
286
|
-
this.name = 'RetryableEmbeddingTimeoutError';
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
/** Re-wrap an opt-in TimeoutError so `resilientFetch` retries it. Abort stays terminal. */
|
|
290
|
-
const throwIfRetryableTimeout = (err, retryTimeouts, callerAborted, timeoutMs) => {
|
|
291
|
-
if (retryTimeouts &&
|
|
292
|
-
!callerAborted &&
|
|
293
|
-
isTerminalNetworkError(err) &&
|
|
294
|
-
err.name === 'TimeoutError') {
|
|
295
|
-
throw new RetryableEmbeddingTimeoutError(timeoutMs, { cause: err });
|
|
296
|
-
}
|
|
297
|
-
};
|
|
298
280
|
/**
|
|
299
281
|
* Build the message for a 2xx body carrying the wrong number of vectors.
|
|
300
282
|
*
|
|
@@ -322,7 +304,7 @@ const countMismatchMessage = (received, expected, safeEndpoint, batchIndex) => `
|
|
|
322
304
|
* `GITNEXUS_EMBEDDING_REQUEST_DIMS=omit` for strict backends while keeping
|
|
323
305
|
* `GITNEXUS_EMBEDDING_DIMS` set to the returned vector size.
|
|
324
306
|
*/
|
|
325
|
-
const httpEmbedBatch = async (url, batch, model, apiKey, batchIndex = 0, dimensions, requestOptions = {}, maxAttempts = HTTP_MAX_RETRIES + 1, retryCapMs = HTTP_RETRY_CAP_MS, minIntervalMs = 0, timeoutMs = DEFAULT_HTTP_TIMEOUT_MS
|
|
307
|
+
const httpEmbedBatch = async (url, batch, model, apiKey, batchIndex = 0, dimensions, requestOptions = {}, maxAttempts = HTTP_MAX_RETRIES + 1, retryCapMs = HTTP_RETRY_CAP_MS, minIntervalMs = 0, timeoutMs = DEFAULT_HTTP_TIMEOUT_MS) => {
|
|
326
308
|
const requestBody = {
|
|
327
309
|
input: batch,
|
|
328
310
|
model,
|
|
@@ -359,14 +341,7 @@ const httpEmbedBatch = async (url, batch, model, apiKey, batchIndex = 0, dimensi
|
|
|
359
341
|
const signal = requestOptions.signal
|
|
360
342
|
? AbortSignal.any([requestOptions.signal, timeoutSignal])
|
|
361
343
|
: timeoutSignal;
|
|
362
|
-
|
|
363
|
-
try {
|
|
364
|
-
attemptResp = await globalThis.fetch(input, { ...init, signal });
|
|
365
|
-
}
|
|
366
|
-
catch (err) {
|
|
367
|
-
throwIfRetryableTimeout(err, retryTimeouts, requestOptions.signal?.aborted, timeoutMs);
|
|
368
|
-
throw err;
|
|
369
|
-
}
|
|
344
|
+
const attemptResp = await globalThis.fetch(input, { ...init, signal });
|
|
370
345
|
// Non-OK bodies are none of our business: hand the response straight
|
|
371
346
|
// back so `resilientFetch` keeps classifying 4xx/5xx/429 unchanged.
|
|
372
347
|
if (!attemptResp.ok)
|
|
@@ -386,19 +361,15 @@ const httpEmbedBatch = async (url, batch, model, apiKey, batchIndex = 0, dimensi
|
|
|
386
361
|
// Not every `.json()` rejection is a parse error: the per-attempt
|
|
387
362
|
// signal (`AbortSignal.any([caller, AbortSignal.timeout(...)])`) is
|
|
388
363
|
// wired to the body stream, so a stalled body rejects with the abort
|
|
389
|
-
// reason. Re-raise
|
|
390
|
-
//
|
|
391
|
-
//
|
|
392
|
-
//
|
|
393
|
-
//
|
|
394
|
-
//
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
// response" so they never reach for the timeout knob.
|
|
399
|
-
// Opt-in `GITNEXUS_EMBEDDING_RETRY_TIMEOUTS=1` is the exception:
|
|
400
|
-
// TimeoutError is re-wrapped so the existing retry loop can retry it.
|
|
401
|
-
throwIfRetryableTimeout(err, retryTimeouts, requestOptions.signal?.aborted, timeoutMs);
|
|
364
|
+
// reason. Re-raise those untouched — `isTerminalNetworkError` is
|
|
365
|
+
// `resilientFetch`'s own predicate, so this test agrees with
|
|
366
|
+
// `classifyOutcome` by construction. Wrapping one would flip its
|
|
367
|
+
// verdict from `terminal-network` (returned without retry AND
|
|
368
|
+
// without touching the breaker, via `recordNeutral()`) to
|
|
369
|
+
// `retryable-network` (retried, then `breaker.recordFailure()`): the
|
|
370
|
+
// same timeout would take 3 attempts instead of 1, count toward the
|
|
371
|
+
// process-global `embeddings-http` breaker, and reach the operator as
|
|
372
|
+
// "unparseable response" so they never reach for the timeout knob.
|
|
402
373
|
if (isTerminalNetworkError(err))
|
|
403
374
|
throw err;
|
|
404
375
|
throw new RetryableEmbeddingBodyError(unparseableMessage(), { cause: err });
|
|
@@ -440,9 +411,6 @@ const httpEmbedBatch = async (url, batch, model, apiKey, batchIndex = 0, dimensi
|
|
|
440
411
|
if (err instanceof RetryableEmbeddingBodyError) {
|
|
441
412
|
throw new HttpEmbeddingError(err.terminalMessage, { cause: err.cause });
|
|
442
413
|
}
|
|
443
|
-
if (err instanceof RetryableEmbeddingTimeoutError) {
|
|
444
|
-
throw new HttpEmbeddingError(`${err.message} after ${maxAttempts} attempt(s) (${safeUrl(url)}, batch ${batchIndex})`, { cause: err.cause });
|
|
445
|
-
}
|
|
446
414
|
if (err instanceof CircuitOpenError) {
|
|
447
415
|
throw new HttpEmbeddingError(`Embedding endpoint circuit open (${safeUrl(url)}, batch ${batchIndex}): retry in ${Math.ceil(err.retryAfterMs / 1000)}s`, { cause: err });
|
|
448
416
|
}
|
|
@@ -487,7 +455,7 @@ export const httpEmbed = async (texts, requestOptions = {}) => {
|
|
|
487
455
|
const url = `${config.baseUrl}/embeddings`;
|
|
488
456
|
const allVectors = [];
|
|
489
457
|
for (const [batchIndex, batch] of chunk(texts, HTTP_BATCH_SIZE).entries()) {
|
|
490
|
-
const items = await httpEmbedBatch(url, batch, config.model, config.apiKey, batchIndex, config.requestDimensions, requestOptions, config.maxAttempts, config.retryCapMs, config.minIntervalMs, config.timeoutMs
|
|
458
|
+
const items = await httpEmbedBatch(url, batch, config.model, config.apiKey, batchIndex, config.requestDimensions, requestOptions, config.maxAttempts, config.retryCapMs, config.minIntervalMs, config.timeoutMs);
|
|
491
459
|
// Defensive backstop, deliberately kept: `httpEmbedBatch` now rejects a
|
|
492
460
|
// short body from *inside* the retry loop (through the same
|
|
493
461
|
// `countMismatchMessage`), so in practice this branch is unreachable. It
|
|
@@ -538,7 +506,7 @@ export const httpEmbedQuery = async (text, requestOptions = {}) => {
|
|
|
538
506
|
if (!config)
|
|
539
507
|
throw new Error('HTTP embedding not configured');
|
|
540
508
|
const url = `${config.baseUrl}/embeddings`;
|
|
541
|
-
const items = await httpEmbedBatch(url, [text], config.model, config.apiKey, 0, config.requestDimensions, requestOptions, config.maxAttempts, config.retryCapMs, config.minIntervalMs, config.timeoutMs
|
|
509
|
+
const items = await httpEmbedBatch(url, [text], config.model, config.apiKey, 0, config.requestDimensions, requestOptions, config.maxAttempts, config.retryCapMs, config.minIntervalMs, config.timeoutMs);
|
|
542
510
|
// Defensive backstop like the `httpEmbed` one above: an empty `data` array is
|
|
543
511
|
// now a cardinality mismatch (0 vectors for 1 text) rejected and retried
|
|
544
512
|
// inside `httpEmbedBatch`, so this branch is unreachable in practice.
|
package/package.json
CHANGED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { lstat } from 'node:fs/promises';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { cliInfo } from './cli-message.js';
|
|
4
|
-
import { getGitRoot } from '../storage/git.js';
|
|
5
|
-
import { acquireIndexLock } from '../storage/index-lock.js';
|
|
6
|
-
import { getStoragePaths, loadMeta, saveMeta } from '../storage/repo-manager.js';
|
|
7
|
-
import { closeLbug, executeQuery, executeWithReusedStatement, fetchExistingEmbeddingHashes, initLbug, } from '../core/lbug/lbug-adapter.js';
|
|
8
|
-
import { runEmbeddingPipeline } from '../core/embeddings/embedding-pipeline.js';
|
|
9
|
-
import { resolveEmbeddingIdentity } from '../core/embeddings/embedding-identity.js';
|
|
10
|
-
import { checkpointKind, decideEmbeddingResume, mintInterruptedCheckpoint, mintPartialCheckpoint, mintUnverifiedCountCheckpoint, } from '../core/embedding-checkpoint.js';
|
|
11
|
-
import { measurePersistedEmbeddingCount, persistedEmbeddingCountOrUndefined, } from '../core/embedding-count.js';
|
|
12
|
-
/** Add missing embeddings directly to a healthy index, checkpointing periodically. */
|
|
13
|
-
export const embeddingsSyncCommand = async (inputPath) => {
|
|
14
|
-
const repoPath = inputPath ? path.resolve(inputPath) : getGitRoot(process.cwd());
|
|
15
|
-
if (!repoPath)
|
|
16
|
-
throw new Error('Not inside a git repository. Pass a repository path.');
|
|
17
|
-
const { lbugPath, metaPath } = getStoragePaths(repoPath);
|
|
18
|
-
const metaDir = path.dirname(metaPath);
|
|
19
|
-
const lock = await acquireIndexLock(metaDir);
|
|
20
|
-
try {
|
|
21
|
-
const meta = await loadMeta(metaDir);
|
|
22
|
-
if (!meta)
|
|
23
|
-
throw new Error(`No GitNexus index found for ${repoPath}. Run gitnexus analyze first.`);
|
|
24
|
-
if (meta.incrementalInProgress) {
|
|
25
|
-
throw new Error('The structural index is incomplete. Run gitnexus analyze --force first.');
|
|
26
|
-
}
|
|
27
|
-
let lbugStat;
|
|
28
|
-
try {
|
|
29
|
-
lbugStat = await lstat(lbugPath);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
throw new Error(`The LadybugDB graph store at ${lbugPath} is missing. Run gitnexus analyze first.`);
|
|
33
|
-
}
|
|
34
|
-
if (!lbugStat.isFile()) {
|
|
35
|
-
throw new Error(`The LadybugDB graph store at ${lbugPath} is not a usable database file. Run gitnexus analyze first.`);
|
|
36
|
-
}
|
|
37
|
-
const identity = resolveEmbeddingIdentity();
|
|
38
|
-
let forceReembedNodeIds;
|
|
39
|
-
let resumedFrom;
|
|
40
|
-
if (meta.embeddingCheckpoint) {
|
|
41
|
-
const checkpoint = meta.embeddingCheckpoint;
|
|
42
|
-
const decision = decideEmbeddingResume(checkpoint, identity);
|
|
43
|
-
if (decision.action === 'abort')
|
|
44
|
-
throw new Error(decision.error);
|
|
45
|
-
const identityDiffers = checkpoint.provider !== identity.provider ||
|
|
46
|
-
checkpoint.model !== identity.model ||
|
|
47
|
-
checkpoint.dimensions !== identity.dimensions;
|
|
48
|
-
// `abandon` on a non-interrupted foreign identity drops the pending set
|
|
49
|
-
// only. Existing rows stay; sync would then embed the holes under the new
|
|
50
|
-
// identity and mix vector spaces. Fail closed — rebuild via analyze.
|
|
51
|
-
if (identityDiffers && checkpointKind(checkpoint) !== 'unverified-count') {
|
|
52
|
-
throw new Error(`Cannot sync embeddings: the index checkpoint was written by ${checkpoint.model} ` +
|
|
53
|
-
`(${checkpoint.provider}) at ${checkpoint.dimensions} dimensions, but this run ` +
|
|
54
|
-
`resolves ${identity.model} (${identity.provider}) at ${identity.dimensions}. ` +
|
|
55
|
-
'Run `gitnexus analyze --embeddings --force` to rebuild under the new identity.');
|
|
56
|
-
}
|
|
57
|
-
cliInfo(decision.log);
|
|
58
|
-
if (decision.action === 'resume') {
|
|
59
|
-
forceReembedNodeIds = decision.pendingNodeIds;
|
|
60
|
-
resumedFrom = decision.resumedFrom;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
await initLbug(lbugPath);
|
|
64
|
-
try {
|
|
65
|
-
const existing = await fetchExistingEmbeddingHashes(executeQuery);
|
|
66
|
-
let lastPercent = -1;
|
|
67
|
-
const countEmbeddings = async () => persistedEmbeddingCountOrUndefined(await measurePersistedEmbeddingCount(executeQuery));
|
|
68
|
-
const saveCheckpoint = async (checkpoint, pendingNodeIds, embeddings) => {
|
|
69
|
-
const latest = (await loadMeta(metaDir)) ?? meta;
|
|
70
|
-
await saveMeta(metaDir, {
|
|
71
|
-
...latest,
|
|
72
|
-
...(embeddings === undefined ? {} : { stats: { ...latest.stats, embeddings } }),
|
|
73
|
-
embeddingCheckpoint: mintInterruptedCheckpoint(identity, checkpoint, pendingNodeIds),
|
|
74
|
-
});
|
|
75
|
-
};
|
|
76
|
-
cliInfo(`Embedding ${repoPath}`);
|
|
77
|
-
cliInfo(`Checkpointed nodes already present: ${existing?.size ?? 0}`);
|
|
78
|
-
const result = await runEmbeddingPipeline(executeQuery, executeWithReusedStatement, (progress) => {
|
|
79
|
-
const percent = Math.floor(progress.percent);
|
|
80
|
-
if (percent !== lastPercent && (percent % 5 === 0 || percent === 100)) {
|
|
81
|
-
lastPercent = percent;
|
|
82
|
-
cliInfo(` ${percent}% — ${progress.nodesProcessed ?? 0}/${progress.totalNodes ?? '?'} nodes`);
|
|
83
|
-
}
|
|
84
|
-
}, {}, undefined, existing && existing.size ? existing : undefined, {
|
|
85
|
-
forceReembedNodeIds,
|
|
86
|
-
onCheckpointWindowStart: async ({ nodeIds, ...checkpoint }) => {
|
|
87
|
-
await saveCheckpoint(checkpoint, nodeIds);
|
|
88
|
-
},
|
|
89
|
-
onCheckpoint: async (checkpoint) => {
|
|
90
|
-
await saveCheckpoint(checkpoint, [], await countEmbeddings());
|
|
91
|
-
},
|
|
92
|
-
});
|
|
93
|
-
const embeddings = await countEmbeddings();
|
|
94
|
-
const latest = (await loadMeta(metaDir)) ?? meta;
|
|
95
|
-
if (embeddings === undefined) {
|
|
96
|
-
// Keep last-known stats.embeddings. An interrupted window marker would
|
|
97
|
-
// fail the identity gate on the next run even though this run finished;
|
|
98
|
-
// unverified-count is the recovery kind that forces a recount (#2790).
|
|
99
|
-
await saveMeta(metaDir, {
|
|
100
|
-
...latest,
|
|
101
|
-
embeddingCheckpoint: result.failedNodeIds.length
|
|
102
|
-
? mintPartialCheckpoint(identity, result, resumedFrom)
|
|
103
|
-
: mintUnverifiedCountCheckpoint(identity, {
|
|
104
|
-
nodesProcessed: result.nodesProcessed,
|
|
105
|
-
totalNodes: result.nodesProcessed,
|
|
106
|
-
chunksProcessed: result.chunksProcessed,
|
|
107
|
-
}),
|
|
108
|
-
});
|
|
109
|
-
throw new Error('Could not verify persisted embedding count.');
|
|
110
|
-
}
|
|
111
|
-
await saveMeta(metaDir, {
|
|
112
|
-
...latest,
|
|
113
|
-
stats: { ...latest.stats, embeddings },
|
|
114
|
-
embeddingCheckpoint: result.failedNodeIds.length
|
|
115
|
-
? mintPartialCheckpoint(identity, result, resumedFrom)
|
|
116
|
-
: undefined,
|
|
117
|
-
});
|
|
118
|
-
cliInfo(`Embeddings ready: ${embeddings}`);
|
|
119
|
-
}
|
|
120
|
-
finally {
|
|
121
|
-
await closeLbug().catch(() => { });
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
finally {
|
|
125
|
-
lock.release();
|
|
126
|
-
}
|
|
127
|
-
};
|