@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
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type ZvecGrepInfoResult } from "../engine/service/index.js";
|
|
2
|
+
import type { CreateZvecGrepOptions } from "../engine/service/types.js";
|
|
3
|
+
import type { EmbeddingModelLoadRequest, EmbeddingModelPool } from "./model-pool.js";
|
|
4
|
+
import { RootRuntime } from "./root-runtime.js";
|
|
5
|
+
import { RootLeaseManager } from "./root-lease.js";
|
|
6
|
+
export type RuntimeManagerOptions = {
|
|
7
|
+
modelPool: EmbeddingModelPool;
|
|
8
|
+
serviceOptions?: CreateZvecGrepOptions;
|
|
9
|
+
readSessionIdleTtlMs?: number;
|
|
10
|
+
runtimeIdleTtlMs?: number;
|
|
11
|
+
onRuntimeEvicted?: (canonicalRoot: string) => void | Promise<void>;
|
|
12
|
+
rootLeaseManager?: RootLeaseManager;
|
|
13
|
+
createRuntime?: (input: {
|
|
14
|
+
canonicalRoot: string;
|
|
15
|
+
modelLoadRequest?: EmbeddingModelLoadRequest;
|
|
16
|
+
modelPool: EmbeddingModelPool;
|
|
17
|
+
}) => RootRuntime | Promise<RootRuntime>;
|
|
18
|
+
};
|
|
19
|
+
export type RuntimeManagerSnapshot = {
|
|
20
|
+
activeRuntimes: number;
|
|
21
|
+
};
|
|
22
|
+
export declare class RuntimeManager {
|
|
23
|
+
private readonly options;
|
|
24
|
+
private readonly runtimes;
|
|
25
|
+
private readonly creating;
|
|
26
|
+
private readonly aliases;
|
|
27
|
+
private readonly rootLeaseManager;
|
|
28
|
+
private readonly idleTimers;
|
|
29
|
+
private closed;
|
|
30
|
+
constructor(options: RuntimeManagerOptions);
|
|
31
|
+
get instanceToken(): string;
|
|
32
|
+
activate(requestedRoot: string): Promise<RootRuntime>;
|
|
33
|
+
activateForIndex(requestedRoot: string): Promise<RootRuntime>;
|
|
34
|
+
peek(requestedRoot: string): Promise<RootRuntime | undefined>;
|
|
35
|
+
getByCanonicalRoot(canonicalRoot: string): RootRuntime | undefined;
|
|
36
|
+
snapshot(): RuntimeManagerSnapshot;
|
|
37
|
+
evict(canonicalRoot: string): Promise<boolean>;
|
|
38
|
+
close(): Promise<void>;
|
|
39
|
+
private getOrCreate;
|
|
40
|
+
private createRuntime;
|
|
41
|
+
private touchRuntime;
|
|
42
|
+
private evictIfIdle;
|
|
43
|
+
}
|
|
44
|
+
export declare function inspectRoot(requestedRoot: string, serviceOptions?: CreateZvecGrepOptions, includeStatus?: boolean): Promise<ZvecGrepInfoResult>;
|
|
45
|
+
export declare function resolveRequestedRoot(requestedRoot: string, writable: boolean): Promise<string>;
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { access, realpath, stat } from "node:fs/promises";
|
|
2
|
+
import { constants as fsConstants } from "node:fs";
|
|
3
|
+
import { isAbsolute } from "node:path";
|
|
4
|
+
import { createZvecGrep, } from "../engine/service/index.js";
|
|
5
|
+
import { DaemonError } from "./errors.js";
|
|
6
|
+
import { RootRuntime } from "./root-runtime.js";
|
|
7
|
+
import { RootLeaseManager } from "./root-lease.js";
|
|
8
|
+
export class RuntimeManager {
|
|
9
|
+
options;
|
|
10
|
+
runtimes = new Map();
|
|
11
|
+
creating = new Map();
|
|
12
|
+
aliases = new Map();
|
|
13
|
+
rootLeaseManager;
|
|
14
|
+
idleTimers = new Map();
|
|
15
|
+
closed = false;
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.rootLeaseManager = options.rootLeaseManager ?? new RootLeaseManager();
|
|
19
|
+
}
|
|
20
|
+
get instanceToken() {
|
|
21
|
+
return this.rootLeaseManager.instanceToken;
|
|
22
|
+
}
|
|
23
|
+
async activate(requestedRoot) {
|
|
24
|
+
if (this.closed) {
|
|
25
|
+
throw new DaemonError("DAEMON_SHUTTING_DOWN", "The daemon is shutting down.", true);
|
|
26
|
+
}
|
|
27
|
+
const canonicalRequestedRoot = await resolveRequestedRoot(requestedRoot, false);
|
|
28
|
+
const activeRequestedRoot = this.runtimes.get(this.aliases.get(canonicalRequestedRoot) ?? canonicalRequestedRoot);
|
|
29
|
+
if (activeRequestedRoot &&
|
|
30
|
+
(activeRequestedRoot.snapshot().writerPending ||
|
|
31
|
+
activeRequestedRoot.needsReconciliation())) {
|
|
32
|
+
return activeRequestedRoot;
|
|
33
|
+
}
|
|
34
|
+
const creatingRequestedRoot = this.creating.get(this.aliases.get(canonicalRequestedRoot) ?? canonicalRequestedRoot);
|
|
35
|
+
if (creatingRequestedRoot) {
|
|
36
|
+
return creatingRequestedRoot;
|
|
37
|
+
}
|
|
38
|
+
const info = await inspectRoot(requestedRoot, this.options.serviceOptions, false);
|
|
39
|
+
if (!info.indexed || !info.workspaceIndex?.embedding) {
|
|
40
|
+
throw new DaemonError("INDEX_MISSING", `Indexed search requires a built zvec-grep index for ${info.root}. Use native grep or rg for exhaustive literal or regex search, or call zvec_grep_index only when persistent indexing is authorized.`);
|
|
41
|
+
}
|
|
42
|
+
const canonicalRoot = await realpath(info.root);
|
|
43
|
+
this.aliases.set(canonicalRequestedRoot, canonicalRoot);
|
|
44
|
+
return this.getOrCreate(canonicalRoot, {
|
|
45
|
+
model: {
|
|
46
|
+
provider: info.workspaceIndex.embedding.provider,
|
|
47
|
+
name: info.workspaceIndex.embedding.model,
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async activateForIndex(requestedRoot) {
|
|
52
|
+
if (this.closed) {
|
|
53
|
+
throw new DaemonError("DAEMON_SHUTTING_DOWN", "The daemon is shutting down.", true);
|
|
54
|
+
}
|
|
55
|
+
const canonicalRequestedRoot = await resolveRequestedRoot(requestedRoot, true);
|
|
56
|
+
const activeRequestedRoot = this.runtimes.get(this.aliases.get(canonicalRequestedRoot) ?? canonicalRequestedRoot);
|
|
57
|
+
if (activeRequestedRoot) {
|
|
58
|
+
return activeRequestedRoot;
|
|
59
|
+
}
|
|
60
|
+
const creatingRequestedRoot = this.creating.get(this.aliases.get(canonicalRequestedRoot) ?? canonicalRequestedRoot);
|
|
61
|
+
if (creatingRequestedRoot) {
|
|
62
|
+
return creatingRequestedRoot;
|
|
63
|
+
}
|
|
64
|
+
const info = await inspectRoot(canonicalRequestedRoot, this.options.serviceOptions, false);
|
|
65
|
+
const canonicalRoot = await resolveRequestedRoot(info.root, true);
|
|
66
|
+
this.aliases.set(canonicalRequestedRoot, canonicalRoot);
|
|
67
|
+
return this.getOrCreate(canonicalRoot);
|
|
68
|
+
}
|
|
69
|
+
async peek(requestedRoot) {
|
|
70
|
+
const info = await inspectRoot(requestedRoot, this.options.serviceOptions, false);
|
|
71
|
+
const canonicalRoot = await realpath(info.root);
|
|
72
|
+
return this.runtimes.get(canonicalRoot);
|
|
73
|
+
}
|
|
74
|
+
getByCanonicalRoot(canonicalRoot) {
|
|
75
|
+
return this.runtimes.get(canonicalRoot);
|
|
76
|
+
}
|
|
77
|
+
snapshot() {
|
|
78
|
+
return { activeRuntimes: this.runtimes.size };
|
|
79
|
+
}
|
|
80
|
+
async evict(canonicalRoot) {
|
|
81
|
+
const creating = this.creating.get(canonicalRoot);
|
|
82
|
+
if (creating) {
|
|
83
|
+
await creating;
|
|
84
|
+
}
|
|
85
|
+
const timer = this.idleTimers.get(canonicalRoot);
|
|
86
|
+
if (timer)
|
|
87
|
+
clearTimeout(timer);
|
|
88
|
+
this.idleTimers.delete(canonicalRoot);
|
|
89
|
+
const runtime = this.runtimes.get(canonicalRoot);
|
|
90
|
+
this.runtimes.delete(canonicalRoot);
|
|
91
|
+
for (const [alias, target] of this.aliases) {
|
|
92
|
+
if (alias === canonicalRoot || target === canonicalRoot) {
|
|
93
|
+
this.aliases.delete(alias);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!runtime)
|
|
97
|
+
return false;
|
|
98
|
+
try {
|
|
99
|
+
await this.options.onRuntimeEvicted?.(canonicalRoot);
|
|
100
|
+
}
|
|
101
|
+
finally {
|
|
102
|
+
await runtime.close();
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
async close() {
|
|
107
|
+
if (this.closed) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.closed = true;
|
|
111
|
+
await Promise.allSettled(this.creating.values());
|
|
112
|
+
const runtimes = [...this.runtimes.values()];
|
|
113
|
+
for (const timer of this.idleTimers.values())
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
this.idleTimers.clear();
|
|
116
|
+
this.runtimes.clear();
|
|
117
|
+
this.aliases.clear();
|
|
118
|
+
await Promise.all(runtimes.map((runtime) => runtime.close()));
|
|
119
|
+
await this.rootLeaseManager.close();
|
|
120
|
+
}
|
|
121
|
+
async getOrCreate(canonicalRoot, modelLoadRequest) {
|
|
122
|
+
const existing = this.runtimes.get(canonicalRoot);
|
|
123
|
+
if (existing) {
|
|
124
|
+
if (modelLoadRequest) {
|
|
125
|
+
existing.updateModelLoadRequest(modelLoadRequest);
|
|
126
|
+
}
|
|
127
|
+
this.touchRuntime(canonicalRoot);
|
|
128
|
+
return existing;
|
|
129
|
+
}
|
|
130
|
+
let pending = this.creating.get(canonicalRoot);
|
|
131
|
+
if (!pending) {
|
|
132
|
+
pending = this.createRuntime(canonicalRoot, modelLoadRequest);
|
|
133
|
+
this.creating.set(canonicalRoot, pending);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
const runtime = await pending;
|
|
137
|
+
if (modelLoadRequest) {
|
|
138
|
+
runtime.updateModelLoadRequest(modelLoadRequest);
|
|
139
|
+
}
|
|
140
|
+
this.touchRuntime(canonicalRoot);
|
|
141
|
+
return runtime;
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
this.creating.delete(canonicalRoot);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async createRuntime(canonicalRoot, modelLoadRequest) {
|
|
148
|
+
let runtime;
|
|
149
|
+
if (this.options.createRuntime) {
|
|
150
|
+
runtime = await this.options.createRuntime({
|
|
151
|
+
canonicalRoot,
|
|
152
|
+
modelLoadRequest,
|
|
153
|
+
modelPool: this.options.modelPool,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const rootLease = await this.rootLeaseManager.acquire(canonicalRoot);
|
|
158
|
+
runtime = new RootRuntime({
|
|
159
|
+
canonicalRoot,
|
|
160
|
+
modelPool: this.options.modelPool,
|
|
161
|
+
modelLoadRequest,
|
|
162
|
+
rootLease,
|
|
163
|
+
readSessionIdleTtlMs: this.options.readSessionIdleTtlMs,
|
|
164
|
+
onActivity: () => this.touchRuntime(canonicalRoot),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (this.closed) {
|
|
168
|
+
await runtime.close();
|
|
169
|
+
throw new DaemonError("DAEMON_SHUTTING_DOWN", "The daemon is shutting down.", true);
|
|
170
|
+
}
|
|
171
|
+
this.runtimes.set(canonicalRoot, runtime);
|
|
172
|
+
this.touchRuntime(canonicalRoot);
|
|
173
|
+
return runtime;
|
|
174
|
+
}
|
|
175
|
+
touchRuntime(canonicalRoot) {
|
|
176
|
+
const idleTtlMs = this.options.runtimeIdleTtlMs ?? 30 * 60_000;
|
|
177
|
+
const existing = this.idleTimers.get(canonicalRoot);
|
|
178
|
+
if (existing)
|
|
179
|
+
clearTimeout(existing);
|
|
180
|
+
if (idleTtlMs <= 0 || this.closed) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const timer = setTimeout(() => void this.evictIfIdle(canonicalRoot), idleTtlMs);
|
|
184
|
+
timer.unref?.();
|
|
185
|
+
this.idleTimers.set(canonicalRoot, timer);
|
|
186
|
+
}
|
|
187
|
+
async evictIfIdle(canonicalRoot) {
|
|
188
|
+
this.idleTimers.delete(canonicalRoot);
|
|
189
|
+
const runtime = this.runtimes.get(canonicalRoot);
|
|
190
|
+
if (!runtime) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const snapshot = runtime.snapshot();
|
|
194
|
+
if (snapshot.activeReaders > 0 ||
|
|
195
|
+
snapshot.activeOperations > 0 ||
|
|
196
|
+
snapshot.writerPending ||
|
|
197
|
+
snapshot.watcherPending) {
|
|
198
|
+
this.touchRuntime(canonicalRoot);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
await this.evict(canonicalRoot);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export async function inspectRoot(requestedRoot, serviceOptions = {}, includeStatus = true) {
|
|
205
|
+
const canonicalRequestedRoot = await resolveRequestedRoot(requestedRoot, false);
|
|
206
|
+
const service = await createZvecGrep({
|
|
207
|
+
...serviceOptions,
|
|
208
|
+
root: canonicalRequestedRoot,
|
|
209
|
+
});
|
|
210
|
+
try {
|
|
211
|
+
return await service.info({ root: canonicalRequestedRoot, includeStatus });
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
await service.close();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
export async function resolveRequestedRoot(requestedRoot, writable) {
|
|
218
|
+
if (!isAbsolute(requestedRoot)) {
|
|
219
|
+
throw new DaemonError("ROOT_NOT_ABSOLUTE", "root must be an absolute path.");
|
|
220
|
+
}
|
|
221
|
+
let rootStat;
|
|
222
|
+
try {
|
|
223
|
+
rootStat = await stat(requestedRoot);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
const code = error.code;
|
|
227
|
+
if (code === "EACCES" || code === "EPERM") {
|
|
228
|
+
throw new DaemonError("ROOT_PERMISSION_DENIED", "root is not readable.");
|
|
229
|
+
}
|
|
230
|
+
throw new DaemonError("ROOT_NOT_FOUND", "root does not exist.");
|
|
231
|
+
}
|
|
232
|
+
if (!rootStat.isDirectory()) {
|
|
233
|
+
throw new DaemonError("ROOT_NOT_FOUND", "root is not a directory.");
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
await access(requestedRoot, writable ? fsConstants.R_OK | fsConstants.W_OK : fsConstants.R_OK);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
throw new DaemonError("ROOT_PERMISSION_DENIED", writable ? "root is not writable." : "root is not readable.");
|
|
240
|
+
}
|
|
241
|
+
return realpath(requestedRoot);
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=runtime-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-manager.js","sourceRoot":"","sources":["../../src/daemon/runtime-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,cAAc,GAEf,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAoBnD,MAAM,OAAO,cAAc;IAWI;IAVZ,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC1C,QAAQ,GAAG,IAAI,GAAG,EAAgC,CAAC;IACnD,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,gBAAgB,CAAmB;IACnC,UAAU,GAAG,IAAI,GAAG,EAGlC,CAAC;IACI,MAAM,GAAG,KAAK,CAAC;IAEvB,YAA6B,OAA8B;QAA9B,YAAO,GAAP,OAAO,CAAuB;QACzD,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,gBAAgB,EAAE,CAAC;IAC7E,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,gBAAgB,CAAC,aAAa,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,aAAqB;QAClC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,WAAW,CACnB,sBAAsB,EACtB,8BAA8B,EAC9B,IAAI,CACL,CAAC;QACJ,CAAC;QACD,MAAM,sBAAsB,GAAG,MAAM,oBAAoB,CACvD,aAAa,EACb,KAAK,CACN,CAAC;QACF,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,sBAAsB,CACnE,CAAC;QACF,IACE,mBAAmB;YACnB,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,aAAa;gBAC3C,mBAAmB,CAAC,mBAAmB,EAAE,CAAC,EAC5C,CAAC;YACD,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,MAAM,qBAAqB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,sBAAsB,CACnE,CAAC;QACF,IAAI,qBAAqB,EAAE,CAAC;YAC1B,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,WAAW,CAC5B,aAAa,EACb,IAAI,CAAC,OAAO,CAAC,cAAc,EAC3B,KAAK,CACN,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,SAAS,EAAE,CAAC;YACrD,MAAM,IAAI,WAAW,CACnB,eAAe,EACf,uDAAuD,IAAI,CAAC,IAAI,sIAAsI,CACvM,CAAC;QACJ,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE;YACrC,KAAK,EAAE;gBACL,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ;gBAChD,IAAI,EAAE,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,KAAK;aAC1C;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,aAAqB;QAC1C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,WAAW,CACnB,sBAAsB,EACtB,8BAA8B,EAC9B,IAAI,CACL,CAAC;QACJ,CAAC;QACD,MAAM,sBAAsB,GAAG,MAAM,oBAAoB,CACvD,aAAa,EACb,IAAI,CACL,CAAC;QACF,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAC3C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,sBAAsB,CACnE,CAAC;QACF,IAAI,mBAAmB,EAAE,CAAC;YACxB,OAAO,mBAAmB,CAAC;QAC7B,CAAC;QACD,MAAM,qBAAqB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAC7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,sBAAsB,CACnE,CAAC;QACF,IAAI,qBAAqB,EAAE,CAAC;YAC1B,OAAO,qBAAqB,CAAC;QAC/B,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,WAAW,CAC5B,sBAAsB,EACtB,IAAI,CAAC,OAAO,CAAC,cAAc,EAC3B,KAAK,CACN,CAAC;QACF,MAAM,aAAa,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,aAAa,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,aAAqB;QAC9B,MAAM,IAAI,GAAG,MAAM,WAAW,CAC5B,aAAa,EACb,IAAI,CAAC,OAAO,CAAC,cAAc,EAC3B,KAAK,CACN,CAAC;QACF,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAED,kBAAkB,CAAC,aAAqB;QACtC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1C,CAAC;IAED,QAAQ;QACN,OAAO,EAAE,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,aAAqB;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAClD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,QAAQ,CAAC;QACjB,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,KAAK;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACpC,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,IAAI,KAAK,KAAK,aAAa,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;gBACxD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO;YAAE,OAAO,KAAK,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC,aAAa,CAAC,CAAC;QACvD,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QAC7C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;YAAE,YAAY,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC9D,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,WAAW,CACvB,aAAqB,EACrB,gBAA4C;QAE5C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAClD,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,gBAAgB,EAAE,CAAC;gBACrB,QAAQ,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;YACpD,CAAC;YACD,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YACjC,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;YAC9D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;YAC9B,IAAI,gBAAgB,EAAE,CAAC;gBACrB,OAAO,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YACjC,OAAO,OAAO,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,aAAa,CACzB,aAAqB,EACrB,gBAA4C;QAE5C,IAAI,OAAoB,CAAC;QACzB,IAAI,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;YAC/B,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC;gBACzC,aAAa;gBACb,gBAAgB;gBAChB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;aAClC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YACrE,OAAO,GAAG,IAAI,WAAW,CAAC;gBACxB,aAAa;gBACb,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;gBACjC,gBAAgB;gBAChB,SAAS;gBACT,oBAAoB,EAAE,IAAI,CAAC,OAAO,CAAC,oBAAoB;gBACvD,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC;aACnD,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,WAAW,CACnB,sBAAsB,EACtB,8BAA8B,EAC9B,IAAI,CACL,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC1C,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,YAAY,CAAC,aAAqB;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,GAAG,MAAM,CAAC;QAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACpD,IAAI,QAAQ;YAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,SAAS,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAG,UAAU,CACtB,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,EAC1C,SAAS,CACV,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;QAChB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,aAAqB;QAC7C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QACpC,IACE,QAAQ,CAAC,aAAa,GAAG,CAAC;YAC1B,QAAQ,CAAC,gBAAgB,GAAG,CAAC;YAC7B,QAAQ,CAAC,aAAa;YACtB,QAAQ,CAAC,cAAc,EACvB,CAAC;YACD,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;YACjC,OAAO;QACT,CAAC;QACD,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,aAAqB,EACrB,iBAAwC,EAAE,EAC1C,aAAa,GAAG,IAAI;IAEpB,MAAM,sBAAsB,GAAG,MAAM,oBAAoB,CACvD,aAAa,EACb,KAAK,CACN,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC;QACnC,GAAG,cAAc;QACjB,IAAI,EAAE,sBAAsB;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,aAAa,EAAE,CAAC,CAAC;IAC7E,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,aAAqB,EACrB,QAAiB;IAEjB,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,WAAW,CACnB,mBAAmB,EACnB,gCAAgC,CACjC,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1C,MAAM,IAAI,WAAW,CAAC,wBAAwB,EAAE,uBAAuB,CAAC,CAAC;QAC3E,CAAC;QACD,MAAM,IAAI,WAAW,CAAC,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,WAAW,CAAC,gBAAgB,EAAE,0BAA0B,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,CACV,aAAa,EACb,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAClE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,WAAW,CACnB,wBAAwB,EACxB,QAAQ,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,uBAAuB,CAC7D,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,aAAa,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CreateZvecGrepOptions } from "../engine/service/types.js";
|
|
2
|
+
import { type McpToolset } from "../mcp/toolset.js";
|
|
3
|
+
export type RunDaemonOptions = {
|
|
4
|
+
version: string;
|
|
5
|
+
listen?: string;
|
|
6
|
+
token?: string;
|
|
7
|
+
tokenFile?: string;
|
|
8
|
+
home?: string;
|
|
9
|
+
mcpToolset?: McpToolset;
|
|
10
|
+
serviceOptions?: CreateZvecGrepOptions;
|
|
11
|
+
};
|
|
12
|
+
export declare function runDaemonForeground(options: RunDaemonOptions): Promise<void>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { DaemonBackend } from "./backend.js";
|
|
2
|
+
import { configuredListenAddress, resolveServerToken } from "./config.js";
|
|
3
|
+
import { DaemonHttpServer } from "./http-server.js";
|
|
4
|
+
import { DaemonInstanceLock } from "./server-controller.js";
|
|
5
|
+
import { createDaemonLogger } from "./logger.js";
|
|
6
|
+
import { MCP_TOOLSET_ENV, resolveMcpToolset, } from "../mcp/toolset.js";
|
|
7
|
+
import { loadOrCreateMcpRequestStateKey, PersistentRemoteEmbeddingRequestStateReplayGuard, } from "../mcp/request-state.js";
|
|
8
|
+
export async function runDaemonForeground(options) {
|
|
9
|
+
const mcpToolset = resolveMcpToolset(options.mcpToolset, process.env[MCP_TOOLSET_ENV]);
|
|
10
|
+
const listen = configuredListenAddress(options.listen);
|
|
11
|
+
const displayAddress = `http://${displayHost(listen.host)}:${listen.port}/mcp`;
|
|
12
|
+
const instanceLock = await DaemonInstanceLock.acquire(options.home, displayAddress, mcpToolset);
|
|
13
|
+
const logger = createDaemonLogger(options.home);
|
|
14
|
+
let auth;
|
|
15
|
+
try {
|
|
16
|
+
auth = await resolveServerToken({
|
|
17
|
+
token: options.token,
|
|
18
|
+
tokenFile: options.tokenFile,
|
|
19
|
+
home: options.home,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
await instanceLock.release();
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
let requestStateKey;
|
|
27
|
+
try {
|
|
28
|
+
requestStateKey = await loadOrCreateMcpRequestStateKey(options.home);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
await instanceLock.release();
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
const backend = new DaemonBackend({
|
|
35
|
+
version: options.version,
|
|
36
|
+
serviceOptions: options.serviceOptions,
|
|
37
|
+
logger,
|
|
38
|
+
});
|
|
39
|
+
let requestStop;
|
|
40
|
+
const httpServer = new DaemonHttpServer({
|
|
41
|
+
...listen,
|
|
42
|
+
token: auth.token,
|
|
43
|
+
version: options.version,
|
|
44
|
+
mcpToolset,
|
|
45
|
+
backend,
|
|
46
|
+
requestStateKey,
|
|
47
|
+
requestStateReplayGuard: new PersistentRemoteEmbeddingRequestStateReplayGuard(options.home),
|
|
48
|
+
logger,
|
|
49
|
+
onShutdown: () => requestStop?.(),
|
|
50
|
+
});
|
|
51
|
+
let address;
|
|
52
|
+
try {
|
|
53
|
+
address = await httpServer.start();
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
await backend.close();
|
|
57
|
+
await instanceLock.release();
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
const stopped = new Promise((resolve) => {
|
|
61
|
+
let stopping = false;
|
|
62
|
+
const stop = () => {
|
|
63
|
+
if (stopping)
|
|
64
|
+
return;
|
|
65
|
+
stopping = true;
|
|
66
|
+
void (async () => {
|
|
67
|
+
await backend.close();
|
|
68
|
+
await httpServer.close();
|
|
69
|
+
await instanceLock.release();
|
|
70
|
+
logger.event("server.stopped", { pid: process.pid });
|
|
71
|
+
await logger.flush();
|
|
72
|
+
})().finally(resolve);
|
|
73
|
+
};
|
|
74
|
+
requestStop = stop;
|
|
75
|
+
process.once("SIGINT", stop);
|
|
76
|
+
process.once("SIGTERM", stop);
|
|
77
|
+
});
|
|
78
|
+
try {
|
|
79
|
+
await instanceLock.markReady();
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
requestStop?.();
|
|
83
|
+
await stopped;
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
logger.event("server.ready", {
|
|
87
|
+
host: listen.host,
|
|
88
|
+
port: address.port,
|
|
89
|
+
pid: process.pid,
|
|
90
|
+
mcp_toolset: mcpToolset,
|
|
91
|
+
});
|
|
92
|
+
console.log(`zvec-grep server listening on http://${displayHost(address.address)}:${address.port}/mcp`);
|
|
93
|
+
console.log(`MCP toolset: ${mcpToolset}`);
|
|
94
|
+
if (auth.tokenFile) {
|
|
95
|
+
console.log(`Bearer token file: ${auth.tokenFile}`);
|
|
96
|
+
}
|
|
97
|
+
await stopped;
|
|
98
|
+
}
|
|
99
|
+
function displayHost(host) {
|
|
100
|
+
return host.includes(":") ? `[${host}]` : host;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/daemon/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type McpToolset } from "../mcp/toolset.js";
|
|
2
|
+
export type DaemonInstanceRecord = {
|
|
3
|
+
pid: number;
|
|
4
|
+
hostname: string;
|
|
5
|
+
instanceToken: string;
|
|
6
|
+
startedAt: number;
|
|
7
|
+
updatedAt: number;
|
|
8
|
+
serverUrl: string;
|
|
9
|
+
ready: boolean;
|
|
10
|
+
mcpToolset: McpToolset;
|
|
11
|
+
};
|
|
12
|
+
export type DaemonControlStatus = {
|
|
13
|
+
running: boolean;
|
|
14
|
+
ready: boolean;
|
|
15
|
+
pid?: number;
|
|
16
|
+
serverUrl?: string;
|
|
17
|
+
mcpToolset?: McpToolset;
|
|
18
|
+
};
|
|
19
|
+
export declare class DaemonInstanceLock {
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly record: DaemonInstanceRecord;
|
|
22
|
+
private heartbeat?;
|
|
23
|
+
private constructor();
|
|
24
|
+
static acquire(home: string | undefined, serverUrl: string, mcpToolset?: McpToolset): Promise<DaemonInstanceLock>;
|
|
25
|
+
markReady(): Promise<void>;
|
|
26
|
+
release(): Promise<void>;
|
|
27
|
+
private write;
|
|
28
|
+
}
|
|
29
|
+
export declare function readInstanceRecord(home?: string): Promise<DaemonInstanceRecord | undefined>;
|
|
30
|
+
export declare function serverStatus(home?: string): Promise<DaemonControlStatus>;
|
|
31
|
+
export declare function startServer(options: {
|
|
32
|
+
cliPath: string;
|
|
33
|
+
listen?: string;
|
|
34
|
+
tokenFile?: string;
|
|
35
|
+
home?: string;
|
|
36
|
+
timeoutMs?: number;
|
|
37
|
+
mcpToolset?: McpToolset;
|
|
38
|
+
}): Promise<DaemonControlStatus>;
|
|
39
|
+
export declare function stopServer(home?: string, timeoutMs?: number, tokenFile?: string): Promise<DaemonControlStatus>;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { open, readFile, unlink } from "node:fs/promises";
|
|
4
|
+
import { hostname } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { daemonHome, resolveClientToken } from "./config.js";
|
|
7
|
+
import { processIsAlive } from "../engine/utils/daemon-lease.js";
|
|
8
|
+
import { DEFAULT_MCP_TOOLSET, MCP_TOOLSET_ENV, resolveMcpToolset, } from "../mcp/toolset.js";
|
|
9
|
+
export class DaemonInstanceLock {
|
|
10
|
+
path;
|
|
11
|
+
record;
|
|
12
|
+
heartbeat;
|
|
13
|
+
constructor(path, record) {
|
|
14
|
+
this.path = path;
|
|
15
|
+
this.record = record;
|
|
16
|
+
}
|
|
17
|
+
static async acquire(home, serverUrl, mcpToolset = DEFAULT_MCP_TOOLSET) {
|
|
18
|
+
const path = join(daemonHome(home), "instance.lock");
|
|
19
|
+
const record = {
|
|
20
|
+
pid: process.pid,
|
|
21
|
+
hostname: hostname(),
|
|
22
|
+
instanceToken: randomUUID(),
|
|
23
|
+
startedAt: Date.now(),
|
|
24
|
+
updatedAt: Date.now(),
|
|
25
|
+
serverUrl,
|
|
26
|
+
ready: false,
|
|
27
|
+
mcpToolset,
|
|
28
|
+
};
|
|
29
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
30
|
+
try {
|
|
31
|
+
const handle = await open(path, "wx", 0o600);
|
|
32
|
+
try {
|
|
33
|
+
await handle.writeFile(`${JSON.stringify(record)}\n`);
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
await handle.close();
|
|
37
|
+
}
|
|
38
|
+
return new DaemonInstanceLock(path, record);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (error.code === "ENOENT") {
|
|
42
|
+
const { mkdir } = await import("node:fs/promises");
|
|
43
|
+
await mkdir(daemonHome(home), { recursive: true, mode: 0o700 });
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (error.code !== "EEXIST")
|
|
47
|
+
throw error;
|
|
48
|
+
const existing = await readInstanceRecord(home);
|
|
49
|
+
if (existing &&
|
|
50
|
+
existing.hostname === hostname() &&
|
|
51
|
+
processIsAlive(existing.pid)) {
|
|
52
|
+
throw new Error(`zvec-grep server is already running with PID ${existing.pid}`, {
|
|
53
|
+
cause: error,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
await unlink(path).catch(() => undefined);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
throw new Error("Could not acquire the zvec-grep server instance lock.");
|
|
60
|
+
}
|
|
61
|
+
async markReady() {
|
|
62
|
+
this.record.ready = true;
|
|
63
|
+
await this.write();
|
|
64
|
+
this.heartbeat = setInterval(() => {
|
|
65
|
+
void this.write();
|
|
66
|
+
}, 5_000);
|
|
67
|
+
this.heartbeat.unref?.();
|
|
68
|
+
}
|
|
69
|
+
async release() {
|
|
70
|
+
if (this.heartbeat)
|
|
71
|
+
clearInterval(this.heartbeat);
|
|
72
|
+
const current = await readRecordPath(this.path);
|
|
73
|
+
if (current?.instanceToken === this.record.instanceToken &&
|
|
74
|
+
current.pid === process.pid) {
|
|
75
|
+
await unlink(this.path).catch(() => undefined);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async write() {
|
|
79
|
+
this.record.updatedAt = Date.now();
|
|
80
|
+
const current = await readRecordPath(this.path);
|
|
81
|
+
if (current?.instanceToken !== this.record.instanceToken ||
|
|
82
|
+
current.pid !== process.pid)
|
|
83
|
+
return;
|
|
84
|
+
const { writeFile } = await import("node:fs/promises");
|
|
85
|
+
await writeFile(this.path, `${JSON.stringify(this.record)}\n`, {
|
|
86
|
+
mode: 0o600,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export async function readInstanceRecord(home) {
|
|
91
|
+
return readRecordPath(join(daemonHome(home), "instance.lock"));
|
|
92
|
+
}
|
|
93
|
+
export async function serverStatus(home) {
|
|
94
|
+
const record = await readInstanceRecord(home);
|
|
95
|
+
if (!record ||
|
|
96
|
+
record.hostname !== hostname() ||
|
|
97
|
+
!processIsAlive(record.pid)) {
|
|
98
|
+
return { running: false, ready: false };
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const response = await fetch(new URL("/healthz", record.serverUrl), {
|
|
102
|
+
signal: AbortSignal.timeout(1_000),
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
running: true,
|
|
106
|
+
ready: response.ok && record.ready,
|
|
107
|
+
pid: record.pid,
|
|
108
|
+
serverUrl: record.serverUrl,
|
|
109
|
+
mcpToolset: record.mcpToolset,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return {
|
|
114
|
+
running: true,
|
|
115
|
+
ready: false,
|
|
116
|
+
pid: record.pid,
|
|
117
|
+
serverUrl: record.serverUrl,
|
|
118
|
+
mcpToolset: record.mcpToolset,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export async function startServer(options) {
|
|
123
|
+
const environmentToolset = process.env[MCP_TOOLSET_ENV];
|
|
124
|
+
const requestedToolset = resolveMcpToolset(options.mcpToolset, environmentToolset);
|
|
125
|
+
const toolsetWasExplicit = options.mcpToolset !== undefined || environmentToolset !== undefined;
|
|
126
|
+
const current = await serverStatus(options.home);
|
|
127
|
+
if (current.running) {
|
|
128
|
+
if (toolsetWasExplicit &&
|
|
129
|
+
current.mcpToolset !== undefined &&
|
|
130
|
+
current.mcpToolset !== requestedToolset) {
|
|
131
|
+
throw new Error(`zvec-grep server is already running with MCP toolset "${current.mcpToolset}". Run \`zg server off\`, then restart it with \`zg server on --mcp-toolset ${requestedToolset}\`.`);
|
|
132
|
+
}
|
|
133
|
+
if (current.ready)
|
|
134
|
+
return current;
|
|
135
|
+
throw new Error(`zvec-grep server process ${current.pid} is running but not ready`);
|
|
136
|
+
}
|
|
137
|
+
const args = [options.cliPath, "server", "run"];
|
|
138
|
+
args.push("--mcp-toolset", requestedToolset);
|
|
139
|
+
if (options.listen)
|
|
140
|
+
args.push("--listen", options.listen);
|
|
141
|
+
if (options.tokenFile)
|
|
142
|
+
args.push("--token-file", options.tokenFile);
|
|
143
|
+
if (options.home)
|
|
144
|
+
args.push("--home", options.home);
|
|
145
|
+
const child = spawn(process.execPath, args, {
|
|
146
|
+
detached: true,
|
|
147
|
+
stdio: "ignore",
|
|
148
|
+
windowsHide: true,
|
|
149
|
+
});
|
|
150
|
+
child.unref();
|
|
151
|
+
return waitForStatus(options.home, true, options.timeoutMs ?? 10_000);
|
|
152
|
+
}
|
|
153
|
+
export async function stopServer(home, timeoutMs = 30_000, tokenFile) {
|
|
154
|
+
const status = await serverStatus(home);
|
|
155
|
+
if (!status.running)
|
|
156
|
+
return status;
|
|
157
|
+
const token = await resolveClientToken({ home, tokenFile });
|
|
158
|
+
const response = await fetch(new URL("/control/shutdown", status.serverUrl), {
|
|
159
|
+
method: "POST",
|
|
160
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
161
|
+
signal: AbortSignal.timeout(2_000),
|
|
162
|
+
});
|
|
163
|
+
if (!response.ok)
|
|
164
|
+
throw new Error(`Server shutdown request failed with HTTP ${response.status}`);
|
|
165
|
+
return waitForStatus(home, false, timeoutMs);
|
|
166
|
+
}
|
|
167
|
+
async function waitForStatus(home, running, timeoutMs) {
|
|
168
|
+
const deadline = Date.now() + timeoutMs;
|
|
169
|
+
let last = { running: false, ready: false };
|
|
170
|
+
while (Date.now() < deadline) {
|
|
171
|
+
last = await serverStatus(home);
|
|
172
|
+
if (running ? last.running && last.ready : !last.running)
|
|
173
|
+
return last;
|
|
174
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
175
|
+
}
|
|
176
|
+
throw new Error(`Timed out waiting for zvec-grep server to ${running ? "start" : "stop"}.`);
|
|
177
|
+
}
|
|
178
|
+
async function readRecordPath(path) {
|
|
179
|
+
try {
|
|
180
|
+
const value = JSON.parse(await readFile(path, "utf8"));
|
|
181
|
+
if (typeof value.pid !== "number" ||
|
|
182
|
+
typeof value.hostname !== "string" ||
|
|
183
|
+
typeof value.instanceToken !== "string" ||
|
|
184
|
+
typeof value.startedAt !== "number" ||
|
|
185
|
+
typeof value.updatedAt !== "number" ||
|
|
186
|
+
typeof value.serverUrl !== "string" ||
|
|
187
|
+
typeof value.ready !== "boolean" ||
|
|
188
|
+
(value.mcpToolset !== undefined &&
|
|
189
|
+
value.mcpToolset !== "agent" &&
|
|
190
|
+
value.mcpToolset !== "full"))
|
|
191
|
+
return undefined;
|
|
192
|
+
return {
|
|
193
|
+
...value,
|
|
194
|
+
// Locks written before toolset profiles exposed the full six-tool MCP
|
|
195
|
+
// surface, so preserve that behavior when reporting a live legacy daemon.
|
|
196
|
+
mcpToolset: value.mcpToolset ?? "full",
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=server-controller.js.map
|