@zvec/zvec-grep 0.1.5 → 0.1.6
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 +88 -249
- package/README_CN.md +82 -246
- package/dist/authorization/index.d.ts +7 -0
- package/dist/authorization/index.js +7 -0
- package/dist/authorization/index.js.map +1 -0
- package/dist/authorization/manager.d.ts +8 -0
- package/dist/authorization/manager.js +19 -0
- package/dist/authorization/manager.js.map +1 -0
- package/dist/authorization/operation.d.ts +7 -0
- package/dist/authorization/operation.js +50 -0
- package/dist/authorization/operation.js.map +1 -0
- package/dist/authorization/planner.d.ts +21 -0
- package/dist/authorization/planner.js +97 -0
- package/dist/authorization/planner.js.map +1 -0
- package/dist/authorization/prompt.d.ts +11 -0
- package/dist/authorization/prompt.js +62 -0
- package/dist/authorization/prompt.js.map +1 -0
- package/dist/authorization/store.d.ts +20 -0
- package/dist/authorization/store.js +251 -0
- package/dist/authorization/store.js.map +1 -0
- package/dist/authorization/target.d.ts +15 -0
- package/dist/authorization/target.js +49 -0
- package/dist/authorization/target.js.map +1 -0
- package/dist/authorization/types.d.ts +61 -0
- package/dist/authorization/types.js +2 -0
- package/dist/authorization/types.js.map +1 -0
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.js +304 -54
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth.d.ts +21 -0
- package/dist/cli/auth.js +212 -0
- package/dist/cli/auth.js.map +1 -0
- package/dist/cli/commands.js +433 -618
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/errors.js +2 -2
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/format/context.d.ts +1 -0
- package/dist/cli/format/context.js +241 -45
- package/dist/cli/format/context.js.map +1 -1
- package/dist/cli/format/debug.js +2 -2
- package/dist/cli/format/debug.js.map +1 -1
- package/dist/cli/format/progress.d.ts +4 -0
- package/dist/cli/format/progress.js +219 -46
- package/dist/cli/format/progress.js.map +1 -1
- package/dist/cli/format/status.d.ts +77 -6
- package/dist/cli/format/status.js +302 -106
- package/dist/cli/format/status.js.map +1 -1
- package/dist/cli/help.js +258 -59
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/cli/install.d.ts +4 -0
- package/dist/cli/install.js +845 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/managed-rg.d.ts +10 -0
- package/dist/cli/managed-rg.js +329 -0
- package/dist/cli/managed-rg.js.map +1 -0
- package/dist/cli/types.d.ts +20 -6
- package/dist/cli/types.js.map +1 -1
- package/dist/client/daemon-client.d.ts +19 -0
- package/dist/client/daemon-client.js +180 -0
- package/dist/client/daemon-client.js.map +1 -0
- package/dist/client/mode-router.d.ts +9 -0
- package/dist/client/mode-router.js +28 -0
- package/dist/client/mode-router.js.map +1 -0
- package/dist/client/search-policy.d.ts +11 -0
- package/dist/client/search-policy.js +15 -0
- package/dist/client/search-policy.js.map +1 -0
- package/dist/daemon/backend.d.ts +76 -0
- package/dist/daemon/backend.js +1049 -0
- package/dist/daemon/backend.js.map +1 -0
- package/dist/daemon/change-set.d.ts +25 -0
- package/dist/daemon/change-set.js +101 -0
- package/dist/daemon/change-set.js.map +1 -0
- package/dist/daemon/config.d.ts +24 -0
- package/dist/daemon/config.js +88 -0
- package/dist/daemon/config.js.map +1 -0
- package/dist/daemon/errors.d.ts +5 -0
- package/dist/daemon/errors.js +11 -0
- package/dist/daemon/errors.js.map +1 -0
- package/dist/daemon/http-server.d.ts +30 -0
- package/dist/daemon/http-server.js +287 -0
- package/dist/daemon/http-server.js.map +1 -0
- package/dist/daemon/index-coordinator.d.ts +23 -0
- package/dist/daemon/index-coordinator.js +68 -0
- package/dist/daemon/index-coordinator.js.map +1 -0
- package/dist/daemon/job-scheduler.d.ts +70 -0
- package/dist/daemon/job-scheduler.js +366 -0
- package/dist/daemon/job-scheduler.js.map +1 -0
- package/dist/daemon/logger.d.ts +9 -0
- package/dist/daemon/logger.js +53 -0
- package/dist/daemon/logger.js.map +1 -0
- package/dist/daemon/model-pool.d.ts +45 -0
- package/dist/daemon/model-pool.js +187 -0
- package/dist/daemon/model-pool.js.map +1 -0
- package/dist/daemon/root-lease.d.ts +14 -0
- package/dist/daemon/root-lease.js +188 -0
- package/dist/daemon/root-lease.js.map +1 -0
- package/dist/daemon/root-runtime.d.ts +78 -0
- package/dist/daemon/root-runtime.js +333 -0
- package/dist/daemon/root-runtime.js.map +1 -0
- package/dist/daemon/runtime-manager.d.ts +45 -0
- package/dist/daemon/runtime-manager.js +243 -0
- package/dist/daemon/runtime-manager.js.map +1 -0
- package/dist/daemon/runtime.d.ts +12 -0
- package/dist/daemon/runtime.js +102 -0
- package/dist/daemon/runtime.js.map +1 -0
- package/dist/daemon/server-controller.d.ts +39 -0
- package/dist/daemon/server-controller.js +203 -0
- package/dist/daemon/server-controller.js.map +1 -0
- package/dist/daemon/watch-manager.d.ts +50 -0
- package/dist/daemon/watch-manager.js +293 -0
- package/dist/daemon/watch-manager.js.map +1 -0
- package/dist/daemon/workspace-read-session-cache.d.ts +31 -0
- package/dist/daemon/workspace-read-session-cache.js +115 -0
- package/dist/daemon/workspace-read-session-cache.js.map +1 -0
- package/dist/engine/config.d.ts +30 -8
- package/dist/engine/config.js +171 -45
- package/dist/engine/config.js.map +1 -1
- package/dist/engine/{errors/index.d.ts → errors.d.ts} +6 -1
- package/dist/engine/{errors/details.js → errors.js} +17 -4
- package/dist/engine/errors.js.map +1 -0
- package/dist/engine/extraction/code/adapter.d.ts +1 -1
- package/dist/engine/extraction/code/extractor.d.ts +5 -11
- package/dist/engine/extraction/code/extractor.js +105 -44
- package/dist/engine/extraction/code/extractor.js.map +1 -1
- package/dist/engine/extraction/code/families/c-family.js +1 -1
- package/dist/engine/extraction/code/families/c-family.js.map +1 -1
- package/dist/engine/extraction/code/families/js-ts.d.ts +1 -1
- package/dist/engine/extraction/code/families/metadata.d.ts +1 -1
- package/dist/engine/extraction/code/tree-sitter/grammar.js.map +1 -0
- package/dist/engine/extraction/code/tree-sitter/nodes.js.map +1 -0
- package/dist/engine/extraction/code/tree-sitter/parser.js.map +1 -0
- package/dist/engine/extraction/image/extractor.d.ts +5 -0
- package/dist/engine/extraction/image/extractor.js +35 -0
- package/dist/engine/extraction/image/extractor.js.map +1 -0
- package/dist/engine/extraction/index.d.ts +3 -44
- package/dist/engine/extraction/index.js +1 -280
- package/dist/engine/extraction/index.js.map +1 -1
- package/dist/engine/extraction/markdown/extractor.d.ts +5 -11
- package/dist/engine/extraction/markdown/extractor.js +35 -16
- package/dist/engine/extraction/markdown/extractor.js.map +1 -1
- package/dist/engine/extraction/runtime.d.ts +4 -0
- package/dist/engine/extraction/runtime.js +26 -0
- package/dist/engine/extraction/runtime.js.map +1 -0
- package/dist/engine/extraction/source.d.ts +18 -0
- package/dist/engine/extraction/source.js +22 -0
- package/dist/engine/extraction/source.js.map +1 -0
- package/dist/engine/extraction/text/extractor.d.ts +7 -0
- package/dist/engine/extraction/text/extractor.js +168 -0
- package/dist/engine/extraction/text/extractor.js.map +1 -0
- package/dist/engine/extraction/types.d.ts +4 -0
- package/dist/engine/{models → extraction}/types.js.map +1 -1
- package/dist/engine/{files/file-type.d.ts → file-type.d.ts} +1 -1
- package/dist/engine/file-type.js.map +1 -0
- package/dist/engine/index-status.d.ts +9 -0
- package/dist/engine/index-status.js +38 -0
- package/dist/engine/index-status.js.map +1 -0
- package/dist/engine/manifest.d.ts +12 -0
- package/dist/engine/manifest.js +120 -0
- package/dist/engine/manifest.js.map +1 -0
- package/dist/engine/models/{providers/llama-cpp/embedding.d.ts → backends/llama-cpp.d.ts} +25 -20
- package/dist/engine/models/{providers/llama-cpp/embedding.js → backends/llama-cpp.js} +127 -106
- package/dist/engine/models/backends/llama-cpp.js.map +1 -0
- package/dist/engine/models/backends/model2vec.d.ts +57 -0
- package/dist/engine/models/backends/model2vec.js +332 -0
- package/dist/engine/models/backends/model2vec.js.map +1 -0
- package/dist/engine/models/backends/qwen.d.ts +44 -0
- package/dist/engine/models/{providers/qwen/embedding.js → backends/qwen.js} +155 -94
- package/dist/engine/models/backends/qwen.js.map +1 -0
- package/dist/engine/models/backends/transformers-js.d.ts +87 -0
- package/dist/engine/models/backends/transformers-js.js +316 -0
- package/dist/engine/models/backends/transformers-js.js.map +1 -0
- package/dist/engine/models/catalog.d.ts +188 -23
- package/dist/engine/models/catalog.js +172 -25
- package/dist/engine/models/catalog.js.map +1 -1
- package/dist/engine/models/download-progress.d.ts +15 -0
- package/dist/engine/models/download-progress.js +48 -0
- package/dist/engine/models/download-progress.js.map +1 -0
- package/dist/engine/models/embeddings.d.ts +58 -18
- package/dist/engine/models/embeddings.js +52 -28
- package/dist/engine/models/embeddings.js.map +1 -1
- package/dist/engine/models/factory.d.ts +2 -5
- package/dist/engine/models/factory.js +41 -56
- package/dist/engine/models/factory.js.map +1 -1
- package/dist/engine/models/index.d.ts +4 -6
- package/dist/engine/models/index.js +4 -4
- package/dist/engine/models/index.js.map +1 -1
- package/dist/engine/models/ranking.d.ts +7 -3
- package/dist/engine/models/resolution.d.ts +8 -0
- package/dist/engine/models/resolution.js +22 -0
- package/dist/engine/models/resolution.js.map +1 -0
- package/dist/engine/pipeline/indexing/index.d.ts +9 -7
- package/dist/engine/pipeline/indexing/index.js +360 -121
- package/dist/engine/pipeline/indexing/index.js.map +1 -1
- package/dist/engine/pipeline/indexing/root-paths.js +6 -6
- package/dist/engine/pipeline/indexing/root-paths.js.map +1 -1
- package/dist/engine/pipeline/indexing/scanner/index.d.ts +6 -1
- package/dist/engine/pipeline/indexing/scanner/index.js +233 -29
- package/dist/engine/pipeline/indexing/scanner/index.js.map +1 -1
- package/dist/engine/pipeline/search/index.d.ts +6 -6
- package/dist/engine/pipeline/search/index.js +8 -10
- package/dist/engine/pipeline/search/index.js.map +1 -1
- package/dist/engine/service/index.d.ts +3 -2
- package/dist/engine/service/index.js +1 -1
- package/dist/engine/service/index.js.map +1 -1
- package/dist/engine/service/root.d.ts +13 -12
- package/dist/engine/service/root.js +35 -24
- package/dist/engine/service/root.js.map +1 -1
- package/dist/engine/service/structure-enrichment.js +12 -14
- package/dist/engine/service/structure-enrichment.js.map +1 -1
- package/dist/engine/service/types.d.ts +32 -37
- package/dist/engine/service/workspace-index.d.ts +24 -0
- package/dist/engine/service/workspace-index.js +151 -0
- package/dist/engine/service/workspace-index.js.map +1 -0
- package/dist/engine/service/zvec-grep.d.ts +12 -1
- package/dist/engine/service/zvec-grep.js +677 -486
- package/dist/engine/service/zvec-grep.js.map +1 -1
- package/dist/engine/storage/index.d.ts +8 -4
- package/dist/engine/storage/index.js +1 -1
- package/dist/engine/storage/index.js.map +1 -1
- package/dist/engine/storage/zvec.d.ts +10 -33
- package/dist/engine/storage/zvec.js +95 -38
- package/dist/engine/storage/zvec.js.map +1 -1
- package/dist/engine/types.d.ts +15 -23
- package/dist/engine/types.js +1 -1
- package/dist/engine/types.js.map +1 -1
- package/dist/engine/utils/daemon-lease.d.ts +17 -0
- package/dist/engine/utils/daemon-lease.js +175 -0
- package/dist/engine/utils/daemon-lease.js.map +1 -0
- package/dist/engine/utils/file-selection.js +38 -1
- package/dist/engine/utils/file-selection.js.map +1 -1
- package/dist/engine/utils/lock.js +1 -1
- package/dist/engine/utils/lock.js.map +1 -1
- package/dist/index-progress.d.ts +10 -0
- package/dist/index-progress.js +159 -0
- package/dist/index-progress.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/http-transport.d.ts +27 -0
- package/dist/mcp/http-transport.js +182 -0
- package/dist/mcp/http-transport.js.map +1 -0
- package/dist/mcp/input-normalization.d.ts +38 -0
- package/dist/mcp/input-normalization.js +95 -0
- package/dist/mcp/input-normalization.js.map +1 -0
- package/dist/mcp/progress-heartbeat.d.ts +17 -0
- package/dist/mcp/progress-heartbeat.js +46 -0
- package/dist/mcp/progress-heartbeat.js.map +1 -0
- package/dist/mcp/request-metadata.d.ts +2 -0
- package/dist/mcp/request-metadata.js +11 -0
- package/dist/mcp/request-metadata.js.map +1 -0
- package/dist/mcp/request-state.d.ts +40 -0
- package/dist/mcp/request-state.js +210 -0
- package/dist/mcp/request-state.js.map +1 -0
- package/dist/mcp/result-format.d.ts +13 -0
- package/dist/mcp/result-format.js +75 -0
- package/dist/mcp/result-format.js.map +1 -0
- package/dist/mcp/schemas.d.ts +430 -0
- package/dist/mcp/schemas.js +447 -0
- package/dist/mcp/schemas.js.map +1 -0
- package/dist/mcp/tools.d.ts +150 -0
- package/dist/mcp/tools.js +448 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/toolset.d.ts +5 -0
- package/dist/mcp/toolset.js +12 -0
- package/dist/mcp/toolset.js.map +1 -0
- package/dist/observability/trace-context.d.ts +11 -0
- package/dist/observability/trace-context.js +138 -0
- package/dist/observability/trace-context.js.map +1 -0
- package/docs/01-agents.md +111 -0
- package/docs/02-cli.md +229 -0
- package/docs/03-mcp.md +167 -0
- package/docs/04-pipeline.md +218 -0
- package/docs/05-architecture.md +86 -0
- package/docs/06-server.md +210 -0
- package/docs/07-embedding.md +179 -0
- package/docs/08-roadmap.md +85 -0
- package/docs/README.md +53 -0
- package/package.json +17 -8
- package/skills/zvec-grep/SKILL.md +43 -133
- package/skills/zvec-grep/agents/openai.yaml +2 -2
- package/skills/zvec-grep/references/cli-fallback.md +85 -0
- package/dist/cli/mcp.d.ts +0 -2
- package/dist/cli/mcp.js +0 -354
- package/dist/cli/mcp.js.map +0 -1
- package/dist/engine/collection/index.d.ts +0 -55
- package/dist/engine/collection/index.js +0 -710
- package/dist/engine/collection/index.js.map +0 -1
- package/dist/engine/errors/details.d.ts +0 -6
- package/dist/engine/errors/details.js.map +0 -1
- package/dist/engine/errors/index.js +0 -16
- package/dist/engine/errors/index.js.map +0 -1
- package/dist/engine/extraction/tree-sitter/grammar.js.map +0 -1
- package/dist/engine/extraction/tree-sitter/nodes.js.map +0 -1
- package/dist/engine/extraction/tree-sitter/parser.js.map +0 -1
- package/dist/engine/files/file-type.js.map +0 -1
- package/dist/engine/models/providers/index.d.ts +0 -2
- package/dist/engine/models/providers/index.js +0 -3
- package/dist/engine/models/providers/index.js.map +0 -1
- package/dist/engine/models/providers/llama-cpp/embedding.js.map +0 -1
- package/dist/engine/models/providers/llama-cpp/index.d.ts +0 -1
- package/dist/engine/models/providers/llama-cpp/index.js +0 -2
- package/dist/engine/models/providers/llama-cpp/index.js.map +0 -1
- package/dist/engine/models/providers/qwen/embedding.d.ts +0 -42
- package/dist/engine/models/providers/qwen/embedding.js.map +0 -1
- package/dist/engine/models/providers/qwen/index.d.ts +0 -1
- package/dist/engine/models/providers/qwen/index.js +0 -2
- package/dist/engine/models/providers/qwen/index.js.map +0 -1
- package/dist/engine/models/types.d.ts +0 -30
- /package/dist/engine/extraction/{tree-sitter → code/tree-sitter}/grammar.d.ts +0 -0
- /package/dist/engine/extraction/{tree-sitter → code/tree-sitter}/grammar.js +0 -0
- /package/dist/engine/extraction/{tree-sitter → code/tree-sitter}/nodes.d.ts +0 -0
- /package/dist/engine/extraction/{tree-sitter → code/tree-sitter}/nodes.js +0 -0
- /package/dist/engine/extraction/{tree-sitter → code/tree-sitter}/parser.d.ts +0 -0
- /package/dist/engine/extraction/{tree-sitter → code/tree-sitter}/parser.js +0 -0
- /package/dist/engine/{models → extraction}/types.js +0 -0
- /package/dist/engine/{files/file-type.js → file-type.js} +0 -0
package/dist/cli/commands.js
CHANGED
|
@@ -1,29 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { chmod, lstat, mkdir, open, readFile, readlink, rename, stat, unlink, } from "node:fs/promises";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, resolve } from "node:path";
|
|
1
|
+
import { resolve } from "node:path";
|
|
5
2
|
import { createInterface } from "node:readline/promises";
|
|
6
3
|
import { createZvecGrep, } from "../index.js";
|
|
7
|
-
import { globalConfigPath,
|
|
8
|
-
import {
|
|
4
|
+
import { globalConfigPath, updateGlobalConfig } from "../engine/config.js";
|
|
5
|
+
import { listEmbeddingModels } from "../engine/models/index.js";
|
|
6
|
+
import { DaemonClient } from "../client/daemon-client.js";
|
|
7
|
+
import { resolveDirectSearchPolicy, resolveServerSearchPolicy, } from "../client/search-policy.js";
|
|
8
|
+
import { resolveClientMode, resolveServerUrl, routeByMode, } from "../client/mode-router.js";
|
|
9
|
+
import { serverStatus } from "../daemon/server-controller.js";
|
|
10
|
+
import { findNearestWorkspace } from "../engine/service/root.js";
|
|
9
11
|
import { contextWarningLines, printAgentContextResult, printHumanContextResult, } from "./format/context.js";
|
|
12
|
+
import { createHighlighter, shouldUseColor } from "./format/highlight.js";
|
|
10
13
|
import { printDebug } from "./format/debug.js";
|
|
11
14
|
import { createIndexProgressReporter } from "./format/progress.js";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
uninstall: uninstallCodexIntegration,
|
|
20
|
-
},
|
|
21
|
-
];
|
|
22
|
-
const ZVEC_GREP_CONFIG_START = "# ZVEC_GREP_START";
|
|
23
|
-
const ZVEC_GREP_CONFIG_END = "# ZVEC_GREP_END";
|
|
24
|
-
const ZVEC_GREP_AGENTS_START = "<!-- ZVEC_GREP_START -->";
|
|
25
|
-
const ZVEC_GREP_AGENTS_END = "<!-- ZVEC_GREP_END -->";
|
|
26
|
-
const DEFAULT_MCP_TOOL_TIMEOUT_SECONDS = 600;
|
|
15
|
+
import { printWorkspaceInfo, printIndexPathFilterTip, printIndexResult, printServerIndexInfo, } from "./format/status.js";
|
|
16
|
+
import { planRemoteIndexAuthorization, planRemoteSearchAuthorization, } from "../authorization/index.js";
|
|
17
|
+
import { indexCompletionFromStatus, indexStatusNeedsRefresh, } from "../engine/index-status.js";
|
|
18
|
+
import { indexProgressFromMessage } from "../index-progress.js";
|
|
19
|
+
import { normalizeManagedRgInput } from "./managed-rg.js";
|
|
20
|
+
import { runInstall, runUninstall } from "./install.js";
|
|
21
|
+
import { runAuth, authorizationStore, authorizeCliPlan, resolveAuthorizationSchema, embeddingModelInfo, configuredEmbeddingReference, workspaceRuntimeFromInfo, assertEmbeddingModelCompatible, assertRequestedEndpointCompatible, requireEmbeddingModelCatalogEntry, unsupportedRemoteEmbeddingProvider, withRemoteEmbeddingOperationPermit, } from "./auth.js";
|
|
27
22
|
export async function runParsedCommand(parsed) {
|
|
28
23
|
switch (parsed.command) {
|
|
29
24
|
case "query":
|
|
@@ -35,174 +30,107 @@ export async function runParsedCommand(parsed) {
|
|
|
35
30
|
case "status":
|
|
36
31
|
await runStatus(parsed);
|
|
37
32
|
return;
|
|
38
|
-
case "collections":
|
|
39
|
-
await runCollections(parsed);
|
|
40
|
-
return;
|
|
41
33
|
case "install":
|
|
42
34
|
await runInstall(parsed);
|
|
43
35
|
return;
|
|
44
36
|
case "uninstall":
|
|
45
37
|
await runUninstall(parsed);
|
|
46
38
|
return;
|
|
47
|
-
case "
|
|
48
|
-
await
|
|
39
|
+
case "config":
|
|
40
|
+
await runConfig(parsed);
|
|
41
|
+
return;
|
|
42
|
+
case "auth":
|
|
43
|
+
await runAuth(parsed);
|
|
44
|
+
return;
|
|
45
|
+
case "server":
|
|
46
|
+
await runServer(parsed);
|
|
49
47
|
return;
|
|
50
48
|
case "help":
|
|
51
49
|
case "version":
|
|
52
50
|
throw new Error(`${parsed.command} must be handled before dispatch`);
|
|
53
51
|
}
|
|
54
52
|
}
|
|
55
|
-
async function
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
console.log("No agents selected.");
|
|
59
|
-
return;
|
|
53
|
+
async function runConfig(parsed) {
|
|
54
|
+
if (parsed.positionals.length !== 1) {
|
|
55
|
+
throw new Error(`zg config ${parsed.options.configAction === "provider-set" ? "provider" : "model"} set requires exactly one reference`);
|
|
60
56
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
mcpToolTimeoutSeconds: parsed.options.installMcpToolTimeoutSeconds ??
|
|
66
|
-
DEFAULT_MCP_TOOL_TIMEOUT_SECONDS,
|
|
67
|
-
});
|
|
68
|
-
console.log(`Installed ${installer.label}:`);
|
|
69
|
-
for (const file of result.files) {
|
|
70
|
-
console.log(` ${file}`);
|
|
57
|
+
const reference = parsed.positionals[0];
|
|
58
|
+
if (parsed.options.configAction === "provider-set") {
|
|
59
|
+
if (!/^[a-z][a-z0-9_-]*$/.test(reference)) {
|
|
60
|
+
throw unsupportedRemoteEmbeddingProvider(reference, "Invalid embedding provider");
|
|
71
61
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
async function runUninstall(parsed) {
|
|
79
|
-
const installers = await resolveInstallers(parsed, "uninstall");
|
|
80
|
-
if (installers.length === 0) {
|
|
81
|
-
console.log("No agents selected.");
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
console.log(`Removing zvec-grep from: ${installers.map((installer) => installer.label).join(", ")}`);
|
|
85
|
-
for (const installer of installers) {
|
|
86
|
-
const result = await installer.uninstall();
|
|
87
|
-
console.log(`Removed ${installer.label} integration:`);
|
|
88
|
-
for (const file of result.files) {
|
|
89
|
-
console.log(` ${file}`);
|
|
62
|
+
if (reference === "local" ||
|
|
63
|
+
!listEmbeddingModels().some((entry) => entry.provider === reference)) {
|
|
64
|
+
throw unsupportedRemoteEmbeddingProvider(reference);
|
|
65
|
+
}
|
|
66
|
+
if (parsed.options.apiKey === undefined) {
|
|
67
|
+
throw new Error("zg config provider set requires --api-key");
|
|
90
68
|
}
|
|
69
|
+
updateGlobalConfig({
|
|
70
|
+
providers: {
|
|
71
|
+
[reference]: {
|
|
72
|
+
apiKey: parsed.options.apiKey,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
console.log(`Provider config: ${reference}`);
|
|
77
|
+
console.log(`Global config: ${globalConfigPath()}`);
|
|
78
|
+
return;
|
|
91
79
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
80
|
+
if (parsed.options.configAction !== "model-set") {
|
|
81
|
+
throw new Error("zg config requires provider set or model set");
|
|
82
|
+
}
|
|
83
|
+
const catalogEntry = requireEmbeddingModelCatalogEntry(reference);
|
|
84
|
+
if (parsed.options.endpoint === undefined &&
|
|
85
|
+
parsed.options.device === undefined &&
|
|
86
|
+
!parsed.options.defaultModel) {
|
|
87
|
+
throw new Error("zg config model set requires --endpoint, --device, or --default");
|
|
88
|
+
}
|
|
89
|
+
if (catalogEntry.provider === "local" &&
|
|
90
|
+
parsed.options.endpoint !== undefined) {
|
|
91
|
+
throw new Error("--endpoint is only supported for remote embedding models");
|
|
92
|
+
}
|
|
93
|
+
if (catalogEntry.provider !== "local" &&
|
|
94
|
+
parsed.options.device !== undefined) {
|
|
95
|
+
throw new Error("--device is only supported for local embedding models");
|
|
96
|
+
}
|
|
97
|
+
if (parsed.options.endpoint !== undefined) {
|
|
98
|
+
assertHttpEndpoint(parsed.options.endpoint);
|
|
99
|
+
}
|
|
100
|
+
updateGlobalConfig({
|
|
101
|
+
...(parsed.options.endpoint !== undefined ||
|
|
102
|
+
parsed.options.device !== undefined
|
|
103
|
+
? {
|
|
104
|
+
models: {
|
|
105
|
+
[reference]: {
|
|
106
|
+
...(parsed.options.endpoint !== undefined
|
|
107
|
+
? { endpoint: parsed.options.endpoint }
|
|
108
|
+
: {}),
|
|
109
|
+
...(parsed.options.device !== undefined
|
|
110
|
+
? { device: parsed.options.device }
|
|
111
|
+
: {}),
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
: {}),
|
|
116
|
+
...(parsed.options.defaultModel
|
|
117
|
+
? { defaults: { embedding: reference } }
|
|
118
|
+
: {}),
|
|
130
119
|
});
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
async function resolveInstallers(parsed, action) {
|
|
134
|
-
const targetTokens = [
|
|
135
|
-
...(parsed.options.installTargets ?? []),
|
|
136
|
-
...parsed.positionals,
|
|
137
|
-
];
|
|
138
|
-
if (targetTokens.length > 0) {
|
|
139
|
-
return installersFromTokens(targetTokens);
|
|
140
|
-
}
|
|
141
|
-
if (parsed.options.yes === true ||
|
|
142
|
-
!process.stdin.isTTY ||
|
|
143
|
-
!process.stdout.isTTY) {
|
|
144
|
-
return installersFromTokens(["auto"]);
|
|
145
|
-
}
|
|
146
|
-
return promptInstallers(action);
|
|
120
|
+
console.log(`Model config: ${reference}`);
|
|
121
|
+
console.log(`Global config: ${globalConfigPath()}`);
|
|
147
122
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
AGENT_INSTALLERS.forEach((installer, index) => {
|
|
151
|
-
console.log(` ${index + 1}. ${installer.label} - ${installer.description}`);
|
|
152
|
-
});
|
|
153
|
-
console.log(" all. All supported agents");
|
|
154
|
-
console.log(" none. Cancel");
|
|
155
|
-
const readline = createInterface({
|
|
156
|
-
input: process.stdin,
|
|
157
|
-
output: process.stdout,
|
|
158
|
-
});
|
|
123
|
+
function assertHttpEndpoint(endpoint) {
|
|
124
|
+
let parsed;
|
|
159
125
|
try {
|
|
160
|
-
|
|
161
|
-
const normalized = answer.trim();
|
|
162
|
-
return installersFromTokens(normalized.length > 0 ? splitTargetTokens(normalized) : ["codex"]);
|
|
126
|
+
parsed = new URL(endpoint);
|
|
163
127
|
}
|
|
164
|
-
|
|
165
|
-
|
|
128
|
+
catch {
|
|
129
|
+
throw new Error("--endpoint must be a valid HTTP(S) URL");
|
|
166
130
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const normalized = tokens.flatMap(splitTargetTokens);
|
|
170
|
-
if (normalized.length === 0) {
|
|
171
|
-
return installersFromTokens(["auto"]);
|
|
172
|
-
}
|
|
173
|
-
const selected = new Map();
|
|
174
|
-
for (const token of normalized) {
|
|
175
|
-
const lower = token.toLowerCase();
|
|
176
|
-
if (lower === "none") {
|
|
177
|
-
return [];
|
|
178
|
-
}
|
|
179
|
-
if (lower === "auto" || lower === "all") {
|
|
180
|
-
for (const installer of AGENT_INSTALLERS) {
|
|
181
|
-
selected.set(installer.id, installer);
|
|
182
|
-
}
|
|
183
|
-
continue;
|
|
184
|
-
}
|
|
185
|
-
const numbered = /^\d+$/.test(lower) ? Number(lower) : Number.NaN;
|
|
186
|
-
if (Number.isInteger(numbered) &&
|
|
187
|
-
numbered >= 1 &&
|
|
188
|
-
numbered <= AGENT_INSTALLERS.length) {
|
|
189
|
-
const installer = AGENT_INSTALLERS[numbered - 1];
|
|
190
|
-
selected.set(installer.id, installer);
|
|
191
|
-
continue;
|
|
192
|
-
}
|
|
193
|
-
const installer = AGENT_INSTALLERS.find((candidate) => candidate.id === lower || candidate.label.toLowerCase() === lower);
|
|
194
|
-
if (!installer) {
|
|
195
|
-
throw new Error(`Unknown install target: ${token}`);
|
|
196
|
-
}
|
|
197
|
-
selected.set(installer.id, installer);
|
|
131
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
132
|
+
throw new Error("--endpoint must be a valid HTTP(S) URL");
|
|
198
133
|
}
|
|
199
|
-
return [...selected.values()];
|
|
200
|
-
}
|
|
201
|
-
function splitTargetTokens(value) {
|
|
202
|
-
return value
|
|
203
|
-
.split(/[,\s]+/)
|
|
204
|
-
.map((target) => target.trim())
|
|
205
|
-
.filter((target) => target.length > 0);
|
|
206
134
|
}
|
|
207
135
|
async function runIndex(parsed) {
|
|
208
136
|
const explicitRoot = parsed.positionals.length > 0;
|
|
@@ -215,11 +143,110 @@ async function runIndex(parsed) {
|
|
|
215
143
|
await runDropIndex(parsed, rootPath.absolutePath);
|
|
216
144
|
return;
|
|
217
145
|
}
|
|
218
|
-
|
|
219
|
-
|
|
146
|
+
if (parsed.options.embedding) {
|
|
147
|
+
requireEmbeddingModelCatalogEntry(parsed.options.embedding);
|
|
148
|
+
}
|
|
149
|
+
const mode = resolveClientMode(parsed.options.mode);
|
|
150
|
+
await routeByMode({
|
|
151
|
+
mode,
|
|
152
|
+
serverAvailable: () => daemonIsReady(parsed.options.home),
|
|
153
|
+
server: async () => {
|
|
154
|
+
const progress = createIndexProgressReporter({
|
|
155
|
+
color: parsed.options.color,
|
|
156
|
+
});
|
|
157
|
+
let result;
|
|
158
|
+
try {
|
|
159
|
+
result = await daemonClient(parsed.options).callTool("zvec_grep_index", {
|
|
160
|
+
root: rootPath.absolutePath,
|
|
161
|
+
embedding: parsed.options.embedding,
|
|
162
|
+
apiKey: parsed.options.apiKey,
|
|
163
|
+
endpoint: parsed.options.endpoint,
|
|
164
|
+
device: parsed.options.device,
|
|
165
|
+
rebuild: parsed.options.rebuild,
|
|
166
|
+
resetPaths: parsed.options.resetPaths,
|
|
167
|
+
globs: parsed.options.globs,
|
|
168
|
+
insensitiveGlobs: parsed.options.insensitiveGlobs,
|
|
169
|
+
fileTypes: parsed.options.fileTypes,
|
|
170
|
+
excludedFileTypes: parsed.options.excludedFileTypes,
|
|
171
|
+
hidden: parsed.options.hidden,
|
|
172
|
+
noIgnore: parsed.options.noIgnore,
|
|
173
|
+
ignoreFiles: parsed.options.ignoreFiles,
|
|
174
|
+
maxDepth: parsed.options.maxDepth,
|
|
175
|
+
maxFileSizeBytes: parsed.options.maxFileSizeBytes,
|
|
176
|
+
follow: parsed.options.follow,
|
|
177
|
+
embeddingConcurrency: parsed.options.embeddingConcurrency,
|
|
178
|
+
wait: true,
|
|
179
|
+
}, {
|
|
180
|
+
onProgress: (event) => {
|
|
181
|
+
const update = indexProgressFromMessage(event.message);
|
|
182
|
+
if (update) {
|
|
183
|
+
progress.report(update.progress);
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
embeddingEnvironment: process.env.ZVEC_GREP_EMBEDDING?.trim(),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
progress.finish();
|
|
191
|
+
}
|
|
192
|
+
console.log(`Workspace index: ${String(result.state ?? "submitted")}`);
|
|
193
|
+
console.log(`Root: ${String(result.root ?? rootPath.absolutePath)}`);
|
|
194
|
+
console.log(`Job: ${String(result.job_id ?? "unknown")}`);
|
|
195
|
+
if (result.state === "failed") {
|
|
196
|
+
throw new Error(serverIndexFailureMessage(result));
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
direct: () => runDirectIndex(parsed, rootPath, explicitRoot),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function serverIndexFailureMessage(result) {
|
|
203
|
+
const error = result.error;
|
|
204
|
+
if (error && typeof error === "object") {
|
|
205
|
+
const code = error.code;
|
|
206
|
+
const message = error.message;
|
|
207
|
+
if (typeof message === "string" && message.length > 0) {
|
|
208
|
+
if (typeof code !== "string" ||
|
|
209
|
+
code.length === 0 ||
|
|
210
|
+
message.includes(`[${code}]`)) {
|
|
211
|
+
return message;
|
|
212
|
+
}
|
|
213
|
+
return `[${code}] ${message}`;
|
|
214
|
+
}
|
|
215
|
+
if (typeof code === "string" && code.length > 0) {
|
|
216
|
+
return `[${code}] Index job failed.`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return `Index job ${String(result.job_id ?? "unknown")} failed. Run zg status --mode server for details.`;
|
|
220
|
+
}
|
|
221
|
+
async function runDirectIndex(parsed, rootPath, explicitRoot) {
|
|
222
|
+
const serviceOptions = createServiceOptions(parsed.options, rootPath.absolutePath);
|
|
223
|
+
const zvecGrep = await createZvecGrep(serviceOptions);
|
|
224
|
+
const progress = createIndexProgressReporter({ color: parsed.options.color });
|
|
220
225
|
try {
|
|
226
|
+
const infoBefore = await zvecGrep.info({
|
|
227
|
+
root: rootPath.absolutePath,
|
|
228
|
+
includeStatus: parsed.options.rebuild !== true,
|
|
229
|
+
});
|
|
230
|
+
const schema = resolveAuthorizationSchema(configuredEmbeddingReference(parsed.options, infoBefore.workspaceIndex?.embedding), infoBefore.workspaceIndex?.embedding);
|
|
231
|
+
assertEmbeddingModelCompatible(infoBefore.workspaceIndex?.embedding, schema, parsed.options.rebuild === true);
|
|
232
|
+
const workspaceRuntime = workspaceRuntimeFromInfo(infoBefore);
|
|
233
|
+
assertRequestedEndpointCompatible(infoBefore, workspaceRuntime, parsed.options.endpoint, parsed.options.rebuild === true);
|
|
234
|
+
const modelInfo = schema?.provider === "qwen"
|
|
235
|
+
? await embeddingModelInfo(schema, serviceOptions, workspaceRuntime)
|
|
236
|
+
: undefined;
|
|
237
|
+
const plan = modelInfo
|
|
238
|
+
? await planRemoteIndexAuthorization({
|
|
239
|
+
info: infoBefore,
|
|
240
|
+
model: modelInfo,
|
|
241
|
+
rebuild: parsed.options.rebuild,
|
|
242
|
+
store: authorizationStore(parsed.options),
|
|
243
|
+
})
|
|
244
|
+
: undefined;
|
|
245
|
+
const authorizationResolution = plan
|
|
246
|
+
? await authorizeCliPlan(plan, parsed.options)
|
|
247
|
+
: {};
|
|
221
248
|
printIndexPathFilterTip(parsed.options);
|
|
222
|
-
const result = await zvecGrep.index({
|
|
249
|
+
const result = await withRemoteEmbeddingOperationPermit(authorizationResolution.authorization, () => zvecGrep.index({
|
|
223
250
|
root: rootPath.absolutePath,
|
|
224
251
|
rootPaths: explicitRoot ? [rootPath] : undefined,
|
|
225
252
|
rebuild: parsed.options.rebuild,
|
|
@@ -236,11 +263,10 @@ async function runIndex(parsed) {
|
|
|
236
263
|
follow: parsed.options.follow,
|
|
237
264
|
embeddingConcurrency: parsed.options.embeddingConcurrency,
|
|
238
265
|
onProgress: progress.report,
|
|
239
|
-
});
|
|
266
|
+
}));
|
|
240
267
|
progress.finish();
|
|
241
268
|
const info = await zvecGrep.info({ root: rootPath.absolutePath });
|
|
242
|
-
printIndexResult("
|
|
243
|
-
persistExplicitGlobalConfig(parsed.options, info.collection?.embedding?.provider);
|
|
269
|
+
printIndexResult("Workspace index", result, parsed.options, info.workspaceIndex?.rootPaths);
|
|
244
270
|
}
|
|
245
271
|
catch (error) {
|
|
246
272
|
progress.finish();
|
|
@@ -255,14 +281,26 @@ async function runDropIndex(parsed, root) {
|
|
|
255
281
|
console.log("Index drop cancelled.");
|
|
256
282
|
return;
|
|
257
283
|
}
|
|
258
|
-
const
|
|
259
|
-
try {
|
|
260
|
-
const removed = await zvecGrep.dropIndex({ root });
|
|
284
|
+
const printResult = (removed) => {
|
|
261
285
|
console.log(removed ? `Dropped index for ${root}` : `No index found for ${root}`);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
286
|
+
};
|
|
287
|
+
await routeByMode({
|
|
288
|
+
mode: resolveClientMode(parsed.options.mode),
|
|
289
|
+
serverAvailable: () => daemonIsReady(parsed.options.home),
|
|
290
|
+
server: async () => {
|
|
291
|
+
const result = await daemonClient(parsed.options).callTool("zvec_grep_index_drop", { root });
|
|
292
|
+
printResult(result.removed === true);
|
|
293
|
+
},
|
|
294
|
+
direct: async () => {
|
|
295
|
+
const zvecGrep = await createZvecGrep(createServiceOptions(parsed.options, root));
|
|
296
|
+
try {
|
|
297
|
+
printResult(await zvecGrep.dropIndex({ root }));
|
|
298
|
+
}
|
|
299
|
+
finally {
|
|
300
|
+
await zvecGrep.close();
|
|
301
|
+
}
|
|
302
|
+
},
|
|
303
|
+
});
|
|
266
304
|
}
|
|
267
305
|
async function confirmIndexDrop(root, accepted) {
|
|
268
306
|
if (accepted) {
|
|
@@ -283,163 +321,77 @@ async function confirmIndexDrop(root, accepted) {
|
|
|
283
321
|
readline.close();
|
|
284
322
|
}
|
|
285
323
|
}
|
|
286
|
-
async function
|
|
324
|
+
async function runServer(parsed) {
|
|
287
325
|
if (parsed.positionals.length > 0) {
|
|
288
|
-
throw new Error(
|
|
326
|
+
throw new Error(`zg server ${parsed.options.serverAction} does not accept positional arguments`);
|
|
327
|
+
}
|
|
328
|
+
const { readPackageVersion } = await import("./version.js");
|
|
329
|
+
if (parsed.options.serverAction === "on") {
|
|
330
|
+
const { startServer } = await import("../daemon/server-controller.js");
|
|
331
|
+
const status = await startServer({
|
|
332
|
+
cliPath: process.argv[1],
|
|
333
|
+
listen: parsed.options.listen,
|
|
334
|
+
tokenFile: parsed.options.serverTokenFile,
|
|
335
|
+
home: parsed.options.home,
|
|
336
|
+
mcpToolset: parsed.options.mcpToolset,
|
|
337
|
+
});
|
|
338
|
+
printServerControlStatus(status);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (parsed.options.serverAction === "off") {
|
|
342
|
+
const { stopServer } = await import("../daemon/server-controller.js");
|
|
343
|
+
printServerControlStatus(await stopServer(parsed.options.home, 30_000, parsed.options.serverTokenFile));
|
|
344
|
+
return;
|
|
289
345
|
}
|
|
290
|
-
|
|
291
|
-
|
|
346
|
+
if (parsed.options.serverAction === "status") {
|
|
347
|
+
const status = await serverStatus(parsed.options.home);
|
|
348
|
+
printServerControlStatus(status);
|
|
349
|
+
if (parsed.options.checkReady && !status.ready) {
|
|
350
|
+
throw new Error("zvec-grep server is not ready");
|
|
351
|
+
}
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const { runDaemonForeground } = await import("../daemon/runtime.js");
|
|
355
|
+
await runDaemonForeground({
|
|
356
|
+
version: readPackageVersion(),
|
|
357
|
+
listen: parsed.options.listen,
|
|
358
|
+
tokenFile: parsed.options.serverTokenFile,
|
|
359
|
+
home: parsed.options.home,
|
|
360
|
+
mcpToolset: parsed.options.mcpToolset,
|
|
361
|
+
serviceOptions: createServiceOptions(parsed.options, process.cwd()),
|
|
362
|
+
});
|
|
292
363
|
}
|
|
293
364
|
async function runStatus(parsed) {
|
|
294
365
|
const root = parsed.positionals[0] ?? process.cwd();
|
|
295
366
|
if (parsed.positionals.length > 1) {
|
|
296
367
|
throw new Error("zg status accepts at most one root path");
|
|
297
368
|
}
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const [action = "list", name, root] = parsed.positionals;
|
|
309
|
-
validateCollectionArguments(action, parsed.positionals);
|
|
310
|
-
const indexOption = collectionIndexOption(parsed.options);
|
|
311
|
-
if (action !== "index" && indexOption) {
|
|
312
|
-
throw new Error(`${indexOption} can only be used with zg collections index`);
|
|
313
|
-
}
|
|
314
|
-
const zvecGrep = await createZvecGrep(createServiceOptions(parsed.options, undefined));
|
|
315
|
-
try {
|
|
316
|
-
if (action === "list") {
|
|
317
|
-
if (parsed.options.resetPaths) {
|
|
318
|
-
throw new Error("--reset-paths can only be used with zg collections index");
|
|
319
|
-
}
|
|
320
|
-
printCollectionList(await zvecGrep.collections.list(), parsed.options);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
if (action === "info") {
|
|
324
|
-
if (parsed.options.resetPaths) {
|
|
325
|
-
throw new Error("--reset-paths can only be used with zg collections index");
|
|
326
|
-
}
|
|
327
|
-
if (!name) {
|
|
328
|
-
throw new Error("zg collections info requires <name>");
|
|
329
|
-
}
|
|
330
|
-
const [info, status] = await Promise.all([
|
|
331
|
-
zvecGrep.collections.info(name),
|
|
332
|
-
zvecGrep.collections.status(name),
|
|
333
|
-
]);
|
|
334
|
-
if (!info) {
|
|
335
|
-
throw new Error(`Collection not found: ${name}`);
|
|
336
|
-
}
|
|
337
|
-
printCollectionInfo(info, status, parsed.options);
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
if (action === "index") {
|
|
341
|
-
if (!name) {
|
|
342
|
-
throw new Error("zg collections index requires <name>");
|
|
343
|
-
}
|
|
344
|
-
const explicitRoot = root !== undefined;
|
|
345
|
-
const rootPath = indexRootPath(root ?? process.cwd(), parsed.options);
|
|
346
|
-
const rootPaths = explicitRoot ? rootPath : undefined;
|
|
347
|
-
const progress = createIndexProgressReporter();
|
|
369
|
+
const mode = resolveClientMode(parsed.options.mode);
|
|
370
|
+
const state = await routeByMode({
|
|
371
|
+
mode,
|
|
372
|
+
serverAvailable: () => daemonIsReady(parsed.options.home),
|
|
373
|
+
server: async () => {
|
|
374
|
+
const result = await daemonClient(parsed.options).callTool("zvec_grep_index_status", { root: resolve(root) });
|
|
375
|
+
return printServerIndexInfo(result, parsed.options);
|
|
376
|
+
},
|
|
377
|
+
direct: async () => {
|
|
378
|
+
const zvecGrep = await createZvecGrep(createServiceOptions(parsed.options, root));
|
|
348
379
|
try {
|
|
349
|
-
|
|
350
|
-
rebuild: parsed.options.rebuild,
|
|
351
|
-
resetPaths: parsed.options.resetPaths,
|
|
352
|
-
globs: parsed.options.globs,
|
|
353
|
-
insensitiveGlobs: parsed.options.insensitiveGlobs,
|
|
354
|
-
fileTypes: parsed.options.fileTypes,
|
|
355
|
-
excludedFileTypes: parsed.options.excludedFileTypes,
|
|
356
|
-
hidden: parsed.options.hidden,
|
|
357
|
-
noIgnore: parsed.options.noIgnore,
|
|
358
|
-
ignoreFiles: parsed.options.ignoreFiles,
|
|
359
|
-
maxDepth: parsed.options.maxDepth,
|
|
360
|
-
maxFileSizeBytes: parsed.options.maxFileSizeBytes,
|
|
361
|
-
follow: parsed.options.follow,
|
|
362
|
-
embeddingConcurrency: parsed.options.embeddingConcurrency,
|
|
363
|
-
onProgress: progress.report,
|
|
364
|
-
});
|
|
365
|
-
progress.finish();
|
|
366
|
-
const info = await zvecGrep.collections.info(name);
|
|
367
|
-
printIndexResult(`Indexed collection ${name}`, result, parsed.options, info?.rootPaths);
|
|
368
|
-
persistExplicitGlobalConfig(parsed.options, info?.embedding?.provider);
|
|
369
|
-
}
|
|
370
|
-
catch (error) {
|
|
371
|
-
progress.finish();
|
|
372
|
-
throw error;
|
|
373
|
-
}
|
|
374
|
-
return;
|
|
375
|
-
}
|
|
376
|
-
if (action === "remove") {
|
|
377
|
-
if (parsed.options.resetPaths) {
|
|
378
|
-
throw new Error("--reset-paths can only be used with zg collections index");
|
|
380
|
+
return printWorkspaceInfo(await zvecGrep.info({ root }), parsed.options);
|
|
379
381
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
+
finally {
|
|
383
|
+
await zvecGrep.close();
|
|
382
384
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
if (parsed.options.resetPaths) {
|
|
388
|
-
throw new Error("--reset-paths can only be used with zg collections index");
|
|
389
|
-
}
|
|
390
|
-
throw new Error(`Unknown collections action: ${action}`);
|
|
391
|
-
}
|
|
392
|
-
finally {
|
|
393
|
-
await zvecGrep.close();
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
function validateCollectionArguments(action, positionals) {
|
|
397
|
-
if (action === "list") {
|
|
398
|
-
if (positionals.length > 1) {
|
|
399
|
-
throw new Error("zg collections list does not accept arguments");
|
|
400
|
-
}
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
if (action === "info" || action === "remove") {
|
|
404
|
-
if (positionals.length > 2) {
|
|
405
|
-
throw new Error(`zg collections ${action} accepts only <name>`);
|
|
406
|
-
}
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
if (action === "index") {
|
|
410
|
-
if (positionals.length > 3) {
|
|
411
|
-
throw new Error("zg collections index accepts only <name> and [root]");
|
|
412
|
-
}
|
|
413
|
-
return;
|
|
385
|
+
},
|
|
386
|
+
});
|
|
387
|
+
if (parsed.options.checkReady && state !== "ready") {
|
|
388
|
+
throw new Error(`Workspace index is not ready (state: ${state})`);
|
|
414
389
|
}
|
|
415
|
-
throw new Error(`Unknown collections action: ${action}`);
|
|
416
|
-
}
|
|
417
|
-
function collectionIndexOption(options) {
|
|
418
|
-
const candidates = [
|
|
419
|
-
[options.rebuild, "--rebuild"],
|
|
420
|
-
[options.resetPaths, "--reset-paths"],
|
|
421
|
-
[options.embedding, "--embedding"],
|
|
422
|
-
[options.modelCacheDir, "--model-cache"],
|
|
423
|
-
[options.llamaGpu, "--llama-gpu"],
|
|
424
|
-
[options.embeddingParallelism, "--embedding-parallelism"],
|
|
425
|
-
[options.apiKey, "--api-key"],
|
|
426
|
-
[options.endpoint, "--endpoint"],
|
|
427
|
-
[options.embeddingConcurrency, "--embedding-concurrency"],
|
|
428
|
-
[options.globs?.length, "--glob"],
|
|
429
|
-
[options.insensitiveGlobs?.length, "--iglob"],
|
|
430
|
-
[options.fileTypes?.length, "--type"],
|
|
431
|
-
[options.excludedFileTypes?.length, "--type-not"],
|
|
432
|
-
[options.hidden, "--hidden"],
|
|
433
|
-
[options.noIgnore, "--no-ignore"],
|
|
434
|
-
[options.ignoreFiles?.length, "--ignore-file"],
|
|
435
|
-
[options.maxDepth, "--max-depth"],
|
|
436
|
-
[options.maxFileSizeBytes, "--max-filesize"],
|
|
437
|
-
[options.follow, "--follow"],
|
|
438
|
-
];
|
|
439
|
-
return candidates.find(([value]) => Array.isArray(value) ? value.length > 0 : value !== undefined)?.[1];
|
|
440
390
|
}
|
|
441
391
|
async function runQuery(parsed) {
|
|
442
|
-
const rgInput = parsed.options.rg
|
|
392
|
+
const rgInput = parsed.options.rg
|
|
393
|
+
? normalizeManagedRgInput(parsed)
|
|
394
|
+
: undefined;
|
|
443
395
|
const commandOptions = rgInput?.options ?? parsed.options;
|
|
444
396
|
const queries = (rgInput?.queries ?? [
|
|
445
397
|
...parsed.positionals,
|
|
@@ -455,14 +407,55 @@ async function runQuery(parsed) {
|
|
|
455
407
|
? "zg query --rg requires a pattern. Use zg help query for examples."
|
|
456
408
|
: "zg query requires text or --hybrid/--fts/--vector routes. Use zg help query for examples.");
|
|
457
409
|
}
|
|
458
|
-
|
|
459
|
-
|
|
410
|
+
if (!commandOptions.rg) {
|
|
411
|
+
const mode = resolveClientMode(commandOptions.mode);
|
|
412
|
+
if (mode !== "direct") {
|
|
413
|
+
await routeByMode({
|
|
414
|
+
mode,
|
|
415
|
+
serverAvailable: () => daemonIsReady(commandOptions.home),
|
|
416
|
+
server: () => runServerQuery(commandOptions, queries, routes),
|
|
417
|
+
direct: () => runDirectQuery(commandOptions, queries),
|
|
418
|
+
});
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
await runDirectQuery(commandOptions, queries);
|
|
423
|
+
}
|
|
424
|
+
async function runDirectQuery(commandOptions, queries) {
|
|
425
|
+
if (commandOptions.refresh === "background") {
|
|
426
|
+
console.error("warning: --refresh background requires Server mode; Direct mode uses --refresh off");
|
|
427
|
+
}
|
|
428
|
+
const serviceOptions = createServiceOptions(commandOptions, undefined);
|
|
429
|
+
const zvecGrep = await createZvecGrep(serviceOptions);
|
|
430
|
+
const progress = createIndexProgressReporter({
|
|
431
|
+
color: commandOptions.color,
|
|
432
|
+
});
|
|
460
433
|
try {
|
|
461
|
-
const
|
|
462
|
-
if (progressEvent.phase !== "done")
|
|
434
|
+
const contextRequest = contextOptions(commandOptions, queries, (progressEvent) => {
|
|
435
|
+
if (progressEvent.phase !== "done")
|
|
463
436
|
progress.report(progressEvent);
|
|
464
|
-
|
|
465
|
-
|
|
437
|
+
});
|
|
438
|
+
const info = await directQueryInfo(zvecGrep);
|
|
439
|
+
const schema = info.workspaceIndex?.embedding;
|
|
440
|
+
const workspaceRuntime = workspaceRuntimeFromInfo(info);
|
|
441
|
+
const modelInfo = !commandOptions.rg && schema?.provider === "qwen"
|
|
442
|
+
? await embeddingModelInfo(schema, createServiceOptions(commandOptions, info.root), workspaceRuntime)
|
|
443
|
+
: undefined;
|
|
444
|
+
const plan = modelInfo
|
|
445
|
+
? await planRemoteSearchAuthorization({
|
|
446
|
+
info,
|
|
447
|
+
model: modelInfo,
|
|
448
|
+
search: normalizedDirectSearchInput(commandOptions, queries, info.root),
|
|
449
|
+
store: authorizationStore(commandOptions),
|
|
450
|
+
})
|
|
451
|
+
: undefined;
|
|
452
|
+
const authorizationResolution = plan
|
|
453
|
+
? await authorizeCliPlan(plan, commandOptions, "local_search")
|
|
454
|
+
: {};
|
|
455
|
+
const effectiveContextRequest = authorizationResolution.alternative === "local_search"
|
|
456
|
+
? ftsFallbackContextRequest(contextRequest)
|
|
457
|
+
: contextRequest;
|
|
458
|
+
const result = await withRemoteEmbeddingOperationPermit(authorizationResolution.authorization, () => zvecGrep.context(effectiveContextRequest));
|
|
466
459
|
progress.finish();
|
|
467
460
|
if (commandOptions.human) {
|
|
468
461
|
printHumanContextResult(result, commandOptions);
|
|
@@ -473,6 +466,10 @@ async function runQuery(parsed) {
|
|
|
473
466
|
for (const line of contextWarningLines(result)) {
|
|
474
467
|
console.error(line);
|
|
475
468
|
}
|
|
469
|
+
if (effectiveContextRequest.autoUpdate !== true &&
|
|
470
|
+
indexStatusNeedsRefresh(info.status)) {
|
|
471
|
+
printStaleIndexStatus("idle", indexCompletionFromStatus(info.status));
|
|
472
|
+
}
|
|
476
473
|
if (commandOptions.debug) {
|
|
477
474
|
printDebug(result, {
|
|
478
475
|
trace: commandOptions.trace === true,
|
|
@@ -487,7 +484,106 @@ async function runQuery(parsed) {
|
|
|
487
484
|
await zvecGrep.close();
|
|
488
485
|
}
|
|
489
486
|
}
|
|
487
|
+
async function runServerQuery(options, queries, routes) {
|
|
488
|
+
const searchPolicy = resolveServerSearchPolicy(options);
|
|
489
|
+
const fts = routes
|
|
490
|
+
.filter((route) => route.mode === "fts")
|
|
491
|
+
.map((route) => route.query);
|
|
492
|
+
const vector = routes
|
|
493
|
+
.filter((route) => route.mode === "vector")
|
|
494
|
+
.map((route) => route.query);
|
|
495
|
+
const response = await daemonClient(options).callTextTool("zvec_grep_search", {
|
|
496
|
+
root: resolve(process.cwd()),
|
|
497
|
+
apiKey: options.apiKey,
|
|
498
|
+
device: options.device,
|
|
499
|
+
queries: queries.length ? queries : undefined,
|
|
500
|
+
fts: fts.length ? fts : undefined,
|
|
501
|
+
vector: vector.length ? vector : undefined,
|
|
502
|
+
fuse: options.fuse,
|
|
503
|
+
limit: options.limit,
|
|
504
|
+
trace: options.trace,
|
|
505
|
+
preferSymbol: options.preferSymbol,
|
|
506
|
+
symbolTypes: options.symbolTypes,
|
|
507
|
+
globs: options.globs,
|
|
508
|
+
insensitiveGlobs: options.insensitiveGlobs,
|
|
509
|
+
fileTypes: options.fileTypes,
|
|
510
|
+
excludedFileTypes: options.excludedFileTypes,
|
|
511
|
+
hidden: options.hidden,
|
|
512
|
+
noIgnore: options.noIgnore,
|
|
513
|
+
ignoreFiles: options.ignoreFiles,
|
|
514
|
+
maxDepth: options.maxDepth,
|
|
515
|
+
maxFileSizeBytes: options.maxFileSizeBytes,
|
|
516
|
+
follow: options.follow,
|
|
517
|
+
embeddingConcurrency: options.embeddingConcurrency,
|
|
518
|
+
modifiedAfter: options.modifiedAfter,
|
|
519
|
+
modifiedBefore: options.modifiedBefore,
|
|
520
|
+
freshness: searchPolicy.freshness,
|
|
521
|
+
autoUpdate: searchPolicy.autoUpdate,
|
|
522
|
+
});
|
|
523
|
+
const highlighter = createHighlighter([...queries, ...fts, ...vector].join(" "), shouldUseColor(options));
|
|
524
|
+
for (const line of response.split("\n")) {
|
|
525
|
+
console.log(highlighter(line));
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
function printStaleIndexStatus(state, completion) {
|
|
529
|
+
console.error("status: possibly_stale");
|
|
530
|
+
if (!state)
|
|
531
|
+
return;
|
|
532
|
+
const progress = completion?.completed === undefined || completion.total === undefined
|
|
533
|
+
? ""
|
|
534
|
+
: ` (${completion.completed}/${completion.total})`;
|
|
535
|
+
console.error(`indexing: ${state}${progress}`);
|
|
536
|
+
}
|
|
537
|
+
function daemonClient(options) {
|
|
538
|
+
return new DaemonClient({
|
|
539
|
+
serverUrl: resolveServerUrl(),
|
|
540
|
+
home: options.home,
|
|
541
|
+
tokenFile: options.serverTokenFile,
|
|
542
|
+
allowRemote: options.allowRemote,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
function ftsFallbackContextRequest(request) {
|
|
546
|
+
const queries = [
|
|
547
|
+
...(request.queries ?? []),
|
|
548
|
+
...(request.query ? [request.query] : []),
|
|
549
|
+
...(request.routes ?? []).map((route) => route.query),
|
|
550
|
+
];
|
|
551
|
+
return {
|
|
552
|
+
...request,
|
|
553
|
+
query: undefined,
|
|
554
|
+
queries: undefined,
|
|
555
|
+
routes: queries.map((query) => ({ mode: "fts", query })),
|
|
556
|
+
autoUpdate: false,
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
async function directQueryInfo(service) {
|
|
560
|
+
return await service.info({ root: process.cwd() });
|
|
561
|
+
}
|
|
562
|
+
function normalizedDirectSearchInput(options, queries, root) {
|
|
563
|
+
const policy = resolveDirectSearchPolicy(options);
|
|
564
|
+
return {
|
|
565
|
+
root,
|
|
566
|
+
apiKey: options.apiKey,
|
|
567
|
+
device: options.device,
|
|
568
|
+
queries: !options.rg && queries.length > 0 ? [...queries] : undefined,
|
|
569
|
+
routes: [...(options.routes ?? [])],
|
|
570
|
+
...policy,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
async function daemonIsReady(home) {
|
|
574
|
+
return (await serverStatus(home)).ready;
|
|
575
|
+
}
|
|
576
|
+
function printServerControlStatus(status) {
|
|
577
|
+
console.log(`Server: ${status.running ? (status.ready ? "ready" : "starting") : "stopped"}`);
|
|
578
|
+
if (status.pid)
|
|
579
|
+
console.log(`PID: ${status.pid}`);
|
|
580
|
+
if (status.serverUrl)
|
|
581
|
+
console.log(`URL: ${status.serverUrl}`);
|
|
582
|
+
if (status.mcpToolset)
|
|
583
|
+
console.log(`MCP toolset: ${status.mcpToolset}`);
|
|
584
|
+
}
|
|
490
585
|
function contextOptions(options, queries, onAutoUpdateProgress) {
|
|
586
|
+
const policy = resolveDirectSearchPolicy(options);
|
|
491
587
|
return {
|
|
492
588
|
queries: queries.length > 0 ? queries : undefined,
|
|
493
589
|
rg: options.rg,
|
|
@@ -495,9 +591,8 @@ function contextOptions(options, queries, onAutoUpdateProgress) {
|
|
|
495
591
|
rgPaths: options.rgPaths,
|
|
496
592
|
routes: options.routes,
|
|
497
593
|
fuse: options.fuse,
|
|
498
|
-
collection: options.collection,
|
|
499
594
|
limit: options.limit,
|
|
500
|
-
autoUpdate:
|
|
595
|
+
autoUpdate: policy.autoUpdate,
|
|
501
596
|
onAutoUpdateProgress,
|
|
502
597
|
trace: options.trace,
|
|
503
598
|
preferSymbol: options.preferSymbol,
|
|
@@ -517,303 +612,23 @@ function contextOptions(options, queries, onAutoUpdateProgress) {
|
|
|
517
612
|
embeddingConcurrency: options.embeddingConcurrency,
|
|
518
613
|
};
|
|
519
614
|
}
|
|
520
|
-
function normalizeRgInput(parsed) {
|
|
521
|
-
const explicitPatterns = parsed.options.rgOptions?.patterns ?? [];
|
|
522
|
-
const hasPatternFiles = (parsed.options.rgOptions?.patternFiles?.length ?? 0) > 0;
|
|
523
|
-
const queries = explicitPatterns.length > 0 || hasPatternFiles
|
|
524
|
-
? explicitPatterns
|
|
525
|
-
: parsed.positionals.slice(0, 1);
|
|
526
|
-
const paths = explicitPatterns.length > 0 || hasPatternFiles
|
|
527
|
-
? parsed.positionals
|
|
528
|
-
: parsed.positionals.slice(1);
|
|
529
|
-
return {
|
|
530
|
-
queries,
|
|
531
|
-
options: {
|
|
532
|
-
...parsed.options,
|
|
533
|
-
rgPaths: paths.length > 0 ? paths : undefined,
|
|
534
|
-
},
|
|
535
|
-
};
|
|
536
|
-
}
|
|
537
615
|
export function createServiceOptions(options, root) {
|
|
538
|
-
const embedding = options.embedding ?? process.env.ZVEC_GREP_EMBEDDING;
|
|
539
|
-
const apiKey = options.apiKey ??
|
|
540
|
-
process.env.ZVEC_GREP_API_KEY ??
|
|
541
|
-
process.env.DASHSCOPE_API_KEY ??
|
|
542
|
-
process.env.QWEN_API_KEY;
|
|
543
|
-
const endpoint = options.endpoint ?? process.env.ZVEC_GREP_ENDPOINT;
|
|
544
616
|
return {
|
|
545
617
|
root,
|
|
546
618
|
home: options.home ?? process.env.ZVEC_GREP_HOME,
|
|
547
|
-
embedding,
|
|
548
|
-
apiKey,
|
|
549
|
-
endpoint,
|
|
550
|
-
modelCacheDir: options.modelCacheDir
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
parseEnvPositiveInteger(process.env.ZVEC_GREP_EMBED_PARALLELISM),
|
|
619
|
+
embedding: options.embedding,
|
|
620
|
+
apiKey: options.apiKey,
|
|
621
|
+
endpoint: options.endpoint,
|
|
622
|
+
modelCacheDir: options.modelCacheDir,
|
|
623
|
+
device: options.device,
|
|
624
|
+
authorizationSigningKeyPath: process.env.ZVEC_GREP_AUTHORIZATION_KEY_FILE,
|
|
554
625
|
};
|
|
555
626
|
}
|
|
556
|
-
function persistExplicitGlobalConfig(options, indexedProvider) {
|
|
557
|
-
if (!updateGlobalConfigFromExplicitOptions(options, indexedProvider)) {
|
|
558
|
-
return;
|
|
559
|
-
}
|
|
560
|
-
console.log(`Global config: ${globalConfigPath()}`);
|
|
561
|
-
}
|
|
562
|
-
function parseEnvLlamaGpu(value) {
|
|
563
|
-
const normalized = value?.trim().toLowerCase() ?? "";
|
|
564
|
-
if (!normalized) {
|
|
565
|
-
return undefined;
|
|
566
|
-
}
|
|
567
|
-
if (normalized === "auto" ||
|
|
568
|
-
normalized === "metal" ||
|
|
569
|
-
normalized === "vulkan" ||
|
|
570
|
-
normalized === "cuda") {
|
|
571
|
-
return normalized;
|
|
572
|
-
}
|
|
573
|
-
if (["false", "off", "none", "disable", "disabled", "0"].includes(normalized)) {
|
|
574
|
-
return false;
|
|
575
|
-
}
|
|
576
|
-
return undefined;
|
|
577
|
-
}
|
|
578
|
-
function parseEnvPositiveInteger(value) {
|
|
579
|
-
const normalized = value?.trim() ?? "";
|
|
580
|
-
if (!/^\d+$/.test(normalized)) {
|
|
581
|
-
return undefined;
|
|
582
|
-
}
|
|
583
|
-
const parsed = Number(normalized);
|
|
584
|
-
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
|
|
585
|
-
}
|
|
586
|
-
function resolveCodexHome() {
|
|
587
|
-
return resolve(process.env.CODEX_HOME ?? resolve(homedir(), ".codex"));
|
|
588
|
-
}
|
|
589
|
-
async function writeMarkedFile(options) {
|
|
590
|
-
let existing = await readTextFileIfExists(options.path);
|
|
591
|
-
const next = replaceMarkedBlock(existing, options.startMarker, options.endMarker, options.block);
|
|
592
|
-
if (next === null) {
|
|
593
|
-
existing = removeOrphanedMarkers(existing, options.startMarker, options.endMarker);
|
|
594
|
-
}
|
|
595
|
-
if (next === null && options.hasConflict?.(existing)) {
|
|
596
|
-
if (!options.force) {
|
|
597
|
-
throw new Error(options.conflictMessage ??
|
|
598
|
-
`Existing unmanaged configuration found in ${options.path}`);
|
|
599
|
-
}
|
|
600
|
-
existing = options.removeConflict
|
|
601
|
-
? options.removeConflict(existing)
|
|
602
|
-
: existing;
|
|
603
|
-
}
|
|
604
|
-
await writeTextFileAtomic(options.path, next ?? appendMarkedBlock(existing, options.block));
|
|
605
|
-
}
|
|
606
|
-
async function removeMarkedFile(options) {
|
|
607
|
-
const existing = await readTextFileIfExists(options.path);
|
|
608
|
-
if (!existing) {
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
const next = replaceMarkedBlock(existing, options.startMarker, options.endMarker, "") ??
|
|
612
|
-
removeOrphanedMarkers(existing, options.startMarker, options.endMarker);
|
|
613
|
-
if (next === existing) {
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
await writeTextFileAtomic(options.path, next);
|
|
617
|
-
}
|
|
618
|
-
async function writeTextFileAtomic(path, content) {
|
|
619
|
-
const targetPath = await resolveAtomicWriteTarget(path);
|
|
620
|
-
await mkdir(dirname(targetPath), { recursive: true });
|
|
621
|
-
const mode = await fileModeIfExists(targetPath);
|
|
622
|
-
const temporaryPath = `${targetPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
623
|
-
let temporaryFile;
|
|
624
|
-
try {
|
|
625
|
-
temporaryFile = await open(temporaryPath, "wx", mode);
|
|
626
|
-
await temporaryFile.writeFile(content, "utf8");
|
|
627
|
-
await temporaryFile.sync();
|
|
628
|
-
await temporaryFile.close();
|
|
629
|
-
temporaryFile = undefined;
|
|
630
|
-
if (mode !== undefined) {
|
|
631
|
-
await chmod(temporaryPath, mode);
|
|
632
|
-
}
|
|
633
|
-
await rename(temporaryPath, targetPath);
|
|
634
|
-
}
|
|
635
|
-
catch (error) {
|
|
636
|
-
await temporaryFile?.close().catch(() => undefined);
|
|
637
|
-
await unlink(temporaryPath).catch(() => undefined);
|
|
638
|
-
throw error;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
async function resolveAtomicWriteTarget(path, visited = new Set()) {
|
|
642
|
-
const absolutePath = resolve(path);
|
|
643
|
-
if (visited.has(absolutePath)) {
|
|
644
|
-
throw new Error(`Cannot atomically write through circular symbolic link: ${path}`);
|
|
645
|
-
}
|
|
646
|
-
try {
|
|
647
|
-
const file = await lstat(absolutePath);
|
|
648
|
-
if (!file.isSymbolicLink()) {
|
|
649
|
-
return absolutePath;
|
|
650
|
-
}
|
|
651
|
-
visited.add(absolutePath);
|
|
652
|
-
const link = await readlink(absolutePath);
|
|
653
|
-
return resolveAtomicWriteTarget(resolve(dirname(absolutePath), link), visited);
|
|
654
|
-
}
|
|
655
|
-
catch (error) {
|
|
656
|
-
if (isNodeError(error) && error.code === "ENOENT") {
|
|
657
|
-
return absolutePath;
|
|
658
|
-
}
|
|
659
|
-
throw error;
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
async function fileModeIfExists(path) {
|
|
663
|
-
try {
|
|
664
|
-
return (await stat(path)).mode & 0o777;
|
|
665
|
-
}
|
|
666
|
-
catch (error) {
|
|
667
|
-
if (isNodeError(error) && error.code === "ENOENT") {
|
|
668
|
-
return undefined;
|
|
669
|
-
}
|
|
670
|
-
throw error;
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
async function readTextFileIfExists(path) {
|
|
674
|
-
try {
|
|
675
|
-
return await readFile(path, "utf8");
|
|
676
|
-
}
|
|
677
|
-
catch (error) {
|
|
678
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
679
|
-
return "";
|
|
680
|
-
}
|
|
681
|
-
throw error;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
function isNodeError(error) {
|
|
685
|
-
return typeof error === "object" && error !== null && "code" in error;
|
|
686
|
-
}
|
|
687
|
-
function replaceMarkedBlock(existing, startMarker, endMarker, block) {
|
|
688
|
-
const lines = existing.split(/\r?\n/);
|
|
689
|
-
const markerLines = new Set();
|
|
690
|
-
const ranges = [];
|
|
691
|
-
let pendingStart;
|
|
692
|
-
for (const [index, line] of lines.entries()) {
|
|
693
|
-
const trimmed = line.trim();
|
|
694
|
-
if (trimmed === startMarker) {
|
|
695
|
-
markerLines.add(index);
|
|
696
|
-
pendingStart = index;
|
|
697
|
-
continue;
|
|
698
|
-
}
|
|
699
|
-
if (trimmed === endMarker) {
|
|
700
|
-
markerLines.add(index);
|
|
701
|
-
if (pendingStart !== undefined) {
|
|
702
|
-
ranges.push({ start: pendingStart, end: index });
|
|
703
|
-
pendingStart = undefined;
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
const first = ranges[0];
|
|
708
|
-
if (!first) {
|
|
709
|
-
return null;
|
|
710
|
-
}
|
|
711
|
-
const before = retainedMarkedLines(lines, 0, first.start, markerLines, [])
|
|
712
|
-
.join("\n")
|
|
713
|
-
.trimEnd();
|
|
714
|
-
const after = retainedMarkedLines(lines, first.end + 1, lines.length, markerLines, ranges.slice(1))
|
|
715
|
-
.join("\n")
|
|
716
|
-
.trim();
|
|
717
|
-
return ([before, block.trim(), after.trim()]
|
|
718
|
-
.filter((part) => part.length > 0)
|
|
719
|
-
.join("\n\n") + "\n");
|
|
720
|
-
}
|
|
721
|
-
function retainedMarkedLines(lines, start, end, markerLines, removedRanges) {
|
|
722
|
-
const retained = [];
|
|
723
|
-
for (let index = start; index < end; index += 1) {
|
|
724
|
-
if (markerLines.has(index)) {
|
|
725
|
-
continue;
|
|
726
|
-
}
|
|
727
|
-
if (removedRanges.some((range) => index >= range.start && index <= range.end)) {
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
retained.push(lines[index]);
|
|
731
|
-
}
|
|
732
|
-
return retained;
|
|
733
|
-
}
|
|
734
|
-
function removeOrphanedMarkers(existing, startMarker, endMarker) {
|
|
735
|
-
return (existing
|
|
736
|
-
.split(/\r?\n/)
|
|
737
|
-
.filter((line) => {
|
|
738
|
-
const trimmed = line.trim();
|
|
739
|
-
return trimmed !== startMarker && trimmed !== endMarker;
|
|
740
|
-
})
|
|
741
|
-
.join("\n")
|
|
742
|
-
.trimEnd() + "\n");
|
|
743
|
-
}
|
|
744
|
-
function appendMarkedBlock(existing, block) {
|
|
745
|
-
const prefix = existing.trimEnd();
|
|
746
|
-
return `${prefix.length > 0 ? `${prefix}\n\n` : ""}${block.trim()}\n`;
|
|
747
|
-
}
|
|
748
|
-
function hasCodexMcpServerConfig(existing) {
|
|
749
|
-
return existing.split(/\r?\n/).some((line) => {
|
|
750
|
-
const tableName = tomlTableName(line);
|
|
751
|
-
return tableName !== undefined && isCodexMcpServerTableName(tableName);
|
|
752
|
-
});
|
|
753
|
-
}
|
|
754
|
-
function removeCodexMcpServerConfig(existing) {
|
|
755
|
-
const lines = existing.split(/\r?\n/);
|
|
756
|
-
const kept = [];
|
|
757
|
-
let skipping = false;
|
|
758
|
-
for (const line of lines) {
|
|
759
|
-
const tableName = tomlTableName(line);
|
|
760
|
-
if (tableName !== undefined) {
|
|
761
|
-
skipping = isCodexMcpServerTableName(tableName);
|
|
762
|
-
}
|
|
763
|
-
if (!skipping) {
|
|
764
|
-
kept.push(line);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
return kept.join("\n").trimEnd() + "\n";
|
|
768
|
-
}
|
|
769
|
-
function tomlTableName(line) {
|
|
770
|
-
return line.match(/^\s*\[([^\]]+)\]\s*(?:#.*)?$/)?.[1]?.trim();
|
|
771
|
-
}
|
|
772
|
-
function isCodexMcpServerTableName(tableName) {
|
|
773
|
-
return /^(?:mcp_servers|"mcp_servers"|'mcp_servers')\s*\.\s*(?:zvec_grep|"zvec_grep"|'zvec_grep')(?:\s*\.|$)/.test(tableName);
|
|
774
|
-
}
|
|
775
|
-
function codexConfigBlock(mcpToolTimeoutSeconds) {
|
|
776
|
-
return `${ZVEC_GREP_CONFIG_START}
|
|
777
|
-
[mcp_servers.zvec_grep]
|
|
778
|
-
command = "zg"
|
|
779
|
-
args = ["serve", "--mcp"]
|
|
780
|
-
env_vars = [
|
|
781
|
-
"DASHSCOPE_API_KEY",
|
|
782
|
-
"QWEN_API_KEY",
|
|
783
|
-
"ZVEC_GREP_API_KEY",
|
|
784
|
-
"ZVEC_GREP_EMBEDDING",
|
|
785
|
-
"ZVEC_GREP_ENDPOINT",
|
|
786
|
-
"ZVEC_GREP_HOME",
|
|
787
|
-
"ZVEC_GREP_MODEL_CACHE",
|
|
788
|
-
"ZVEC_GREP_LLAMA_GPU",
|
|
789
|
-
"ZVEC_GREP_EMBED_PARALLELISM",
|
|
790
|
-
"NODE_LLAMA_CPP_CMAKE_OPTION_GGML_OPENMP",
|
|
791
|
-
"NODE_LLAMA_CPP_CMAKE_OPTION_GGML_NATIVE",
|
|
792
|
-
"NODE_LLAMA_CPP_CMAKE_OPTION_GGML_CPU_ARM_ARCH"
|
|
793
|
-
]
|
|
794
|
-
startup_timeout_sec = 20
|
|
795
|
-
tool_timeout_sec = ${mcpToolTimeoutSeconds}
|
|
796
|
-
default_tools_approval_mode = "auto"
|
|
797
|
-
${ZVEC_GREP_CONFIG_END}`;
|
|
798
|
-
}
|
|
799
|
-
function codexAgentsBlock() {
|
|
800
|
-
return `${ZVEC_GREP_AGENTS_START}
|
|
801
|
-
## zvec-grep
|
|
802
|
-
|
|
803
|
-
Use zvec-grep before grep, rg, or broad file reads when you need to understand or locate code.
|
|
804
|
-
|
|
805
|
-
- **MCP tools**: Use \`zvec_grep_search\` for indexed semantic/lexical code search and \`zvec_grep_rg\` for explicit no-index lexical search.
|
|
806
|
-
- **Indexing and status**: These are CLI-only operations. If an index is missing, use \`zvec_grep_rg\` and mention \`zg index\` as the opt-in setup path; use \`zg status\` when status inspection is needed.
|
|
807
|
-
- **Shell fallback**: If the MCP server is unavailable, use \`zg status\`, \`zg query "<query>"\`, and \`zg query --rg "<pattern>"\`.
|
|
808
|
-
|
|
809
|
-
Prefer focused -g/--glob and -t/--type filters, and exclude dependencies, generated output, caches, build artifacts, and logs unless the task is about those files.
|
|
810
|
-
${ZVEC_GREP_AGENTS_END}`;
|
|
811
|
-
}
|
|
812
627
|
function resolveIndexRoot(root) {
|
|
813
628
|
if (root !== undefined) {
|
|
814
629
|
return root;
|
|
815
630
|
}
|
|
816
|
-
return
|
|
631
|
+
return findNearestWorkspace(process.cwd())?.root ?? process.cwd();
|
|
817
632
|
}
|
|
818
633
|
function indexRootPath(path, options) {
|
|
819
634
|
return {
|