@gmickel/gno 1.46.0 → 2.1.0
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 +17 -5
- package/THIRD_PARTY_NOTICES.md +46 -0
- package/assets/skill/SKILL.md +7 -6
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.1.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.1.0.zip.sha256 +1 -0
- package/browser-extension/dist/chunk-4tc9v0ja.js +74 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/browser-extension/dist/preview.html +1 -1
- package/browser-extension/dist/service-worker.js +32 -33
- package/bunfig.toml +2 -0
- package/package.json +40 -26
- package/spec/cli.md +29 -4
- package/spec/db/schema.sql +146 -1
- package/spec/mcp.md +26 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +2 -0
- package/src/cli/commands/ask.ts +6 -1
- package/src/cli/commands/daemon.ts +21 -8
- package/src/cli/commands/embed.ts +77 -41
- package/src/cli/detach.ts +3 -2
- package/src/config/types.ts +3 -3
- package/src/converters/adapters/markitdownTs/adapter.ts +1 -2
- package/src/converters/adapters/officeparser/adapter.ts +1 -2
- package/src/converters/versions.ts +6 -8
- package/src/core/context-evidence.ts +8 -4
- package/src/core/job-manager.ts +95 -13
- package/src/core/network-boundary-inventory.ts +10 -0
- package/src/core/shutdown-budget.ts +45 -0
- package/src/embed/backlog.ts +107 -4
- package/src/embed/batch.ts +42 -2
- package/src/embed/fingerprint.ts +16 -0
- package/src/embed/retry.ts +113 -5
- package/src/embed/variant-backlog.ts +105 -0
- package/src/embed/variant-plan.ts +62 -0
- package/src/embed/variant-retry.ts +113 -0
- package/src/ingestion/graph-reconciliation.ts +327 -0
- package/src/ingestion/sync.ts +9 -272
- package/src/llm/http-inference.ts +6 -0
- package/src/llm/httpEmbedding.ts +37 -6
- package/src/llm/httpGeneration.ts +18 -3
- package/src/llm/httpRerank.ts +23 -5
- package/src/llm/inference-cancellation.ts +168 -0
- package/src/llm/inference-scope.ts +202 -0
- package/src/llm/lazy-ports.ts +115 -0
- package/src/llm/native-worker/client.ts +541 -0
- package/src/llm/native-worker/dispatcher.ts +228 -0
- package/src/llm/native-worker/embedding-identity.ts +33 -0
- package/src/llm/native-worker/entry.ts +173 -0
- package/src/llm/native-worker/errors.ts +32 -0
- package/src/llm/native-worker/evaluation.ts +16 -0
- package/src/llm/native-worker/owned-exit.ts +108 -0
- package/src/llm/native-worker/owner.ts +141 -0
- package/src/llm/native-worker/ports.ts +317 -0
- package/src/llm/native-worker/protocol.ts +442 -0
- package/src/llm/native-worker/runtime-config.ts +92 -0
- package/src/llm/nodeLlamaCpp/adapter.ts +77 -20
- package/src/llm/nodeLlamaCpp/embedding.ts +130 -46
- package/src/llm/nodeLlamaCpp/generation.ts +34 -5
- package/src/llm/nodeLlamaCpp/lifecycle-options.ts +99 -0
- package/src/llm/nodeLlamaCpp/lifecycle.ts +209 -204
- package/src/llm/nodeLlamaCpp/rerank-capacity.ts +111 -0
- package/src/llm/nodeLlamaCpp/rerank.ts +118 -27
- package/src/llm/nodeLlamaCpp/simulator-handle.ts +73 -0
- package/src/llm/nodeLlamaCpp/simulator-install.ts +124 -0
- package/src/llm/nodeLlamaCpp/simulator-session.ts +240 -0
- package/src/llm/nodeLlamaCpp/simulator-types.ts +80 -0
- package/src/llm/types.ts +35 -5
- package/src/mcp/context.ts +27 -0
- package/src/mcp/http-transport.ts +12 -10
- package/src/mcp/server.ts +3 -0
- package/src/mcp/tool-profile.ts +30 -8
- package/src/mcp/tools/context.ts +8 -11
- package/src/mcp/tools/embed.ts +1 -1
- package/src/mcp/tools/index-cmd.ts +1 -1
- package/src/mcp/tools/index.ts +10 -8
- package/src/mcp/tools/query.ts +14 -30
- package/src/mcp/tools/vsearch.ts +1 -1
- package/src/pipeline/answer.ts +23 -3
- package/src/pipeline/claim-verifier.ts +6 -0
- package/src/pipeline/expansion.ts +43 -40
- package/src/pipeline/explain.ts +6 -2
- package/src/pipeline/filters.ts +63 -0
- package/src/pipeline/fusion.ts +29 -9
- package/src/pipeline/graph-retrieval.ts +29 -9
- package/src/pipeline/hybrid.ts +198 -55
- package/src/pipeline/hydration.ts +161 -0
- package/src/pipeline/owner-fusion.ts +87 -0
- package/src/pipeline/rerank.ts +35 -11
- package/src/pipeline/search.ts +13 -2
- package/src/pipeline/types.ts +5 -3
- package/src/pipeline/vsearch.ts +87 -7
- package/src/sdk/client.ts +47 -3
- package/src/sdk/embed.ts +63 -39
- package/src/serve/background-runtime.ts +1 -1
- package/src/serve/context.ts +41 -56
- package/src/serve/embed-scheduler.ts +58 -35
- package/src/serve/public/components/IndexingProgress.tsx +46 -60
- package/src/serve/public/components/PublishExportDialog.tsx +266 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/globals.css +35 -0
- package/src/serve/public/lib/publish-export.ts +81 -1
- package/src/serve/public/lib/shiki-language-ids.ts +14 -0
- package/src/serve/public/pages/Collections.tsx +12 -46
- package/src/serve/public/pages/DocView.tsx +14 -52
- package/src/serve/resident-admission.ts +36 -36
- package/src/serve/resident-background-work.ts +20 -2
- package/src/serve/resident-request.ts +11 -5
- package/src/serve/resident-runtime.ts +97 -61
- package/src/serve/resident-shutdown.ts +153 -0
- package/src/serve/routes/api.ts +3 -1
- package/src/serve/server.ts +47 -26
- package/src/store/migrations/028-vector-variants.ts +54 -0
- package/src/store/migrations/029-graph-reference-state.ts +77 -0
- package/src/store/migrations/index.ts +4 -0
- package/src/store/sqlite/adapter.ts +251 -183
- package/src/store/sqlite/eligibility.ts +174 -0
- package/src/store/sqlite/graph-edge-application.ts +66 -0
- package/src/store/sqlite/graph-reference-state.ts +194 -0
- package/src/store/sqlite/legacy-vector-ownership.ts +79 -0
- package/src/store/types.ts +80 -12
- package/src/store/vector/eligibility.ts +36 -0
- package/src/store/vector/freshness.ts +33 -6
- package/src/store/vector/lazy.ts +81 -0
- package/src/store/vector/sqlite-vec.ts +106 -54
- package/src/store/vector/stats.ts +14 -3
- package/src/store/vector/types.ts +35 -2
- package/src/store/vector/variant-search.ts +192 -0
- package/src/store/vector/variants.ts +451 -0
- package/vendor/converters/markitdown-ts/LICENSE +21 -0
- package/vendor/converters/markitdown-ts/dist/index.cjs +1180 -0
- package/vendor/converters/markitdown-ts/dist/index.d.cts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.mts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.d.ts +46 -0
- package/vendor/converters/markitdown-ts/dist/index.mjs +1152 -0
- package/vendor/converters/markitdown-ts/package.json +77 -0
- package/vendor/converters/officeparser/LICENSE +21 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.d.ts +47 -0
- package/vendor/converters/officeparser/dist/OfficeConverter.js +76 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.d.ts +23 -0
- package/vendor/converters/officeparser/dist/OfficeGenerator.js +73 -0
- package/vendor/converters/officeparser/dist/OfficeParser.d.ts +106 -0
- package/vendor/converters/officeparser/dist/OfficeParser.js +332 -0
- package/vendor/converters/officeparser/dist/cli.d.ts +28 -0
- package/vendor/converters/officeparser/dist/cli.js +381 -0
- package/vendor/converters/officeparser/dist/defaults.d.ts +41 -0
- package/vendor/converters/officeparser/dist/defaults.js +218 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.d.ts +107 -0
- package/vendor/converters/officeparser/dist/generators/BaseGenerator.js +248 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.d.ts +82 -0
- package/vendor/converters/officeparser/dist/generators/ChunkingGenerator.js +797 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.d.ts +38 -0
- package/vendor/converters/officeparser/dist/generators/CsvGenerator.js +245 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.d.ts +43 -0
- package/vendor/converters/officeparser/dist/generators/EpubGenerator.js +315 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.d.ts +59 -0
- package/vendor/converters/officeparser/dist/generators/HtmlGenerator.js +1942 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.d.ts +96 -0
- package/vendor/converters/officeparser/dist/generators/MarkdownGenerator.js +1175 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.d.ts +22 -0
- package/vendor/converters/officeparser/dist/generators/PdfGenerator.js +194 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.d.ts +29 -0
- package/vendor/converters/officeparser/dist/generators/RtfGenerator.js +316 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.d.ts +13 -0
- package/vendor/converters/officeparser/dist/generators/TextGenerator.js +201 -0
- package/vendor/converters/officeparser/dist/index.d.ts +60 -0
- package/vendor/converters/officeparser/dist/index.js +72 -0
- package/vendor/converters/officeparser/dist/index.mjs +18 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.mjs +1335 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.d.ts +2621 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.iife.js +1336 -0
- package/vendor/converters/officeparser/dist/officeparser.browser.slim.mjs +1335 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.d.ts +9 -0
- package/vendor/converters/officeparser/dist/parsers/CsvParser.js +115 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.d.ts +8 -0
- package/vendor/converters/officeparser/dist/parsers/EpubParser.js +217 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/ExcelParser.js +736 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/HtmlParser.js +1287 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.d.ts +2 -0
- package/vendor/converters/officeparser/dist/parsers/MarkdownParser.js +1272 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.d.ts +31 -0
- package/vendor/converters/officeparser/dist/parsers/OpenOfficeParser.js +1819 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.d.ts +67 -0
- package/vendor/converters/officeparser/dist/parsers/PdfParser.js +848 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.d.ts +32 -0
- package/vendor/converters/officeparser/dist/parsers/PowerPointParser.js +950 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.d.ts +187 -0
- package/vendor/converters/officeparser/dist/parsers/RtfParser.js +1801 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.d.ts +79 -0
- package/vendor/converters/officeparser/dist/parsers/WordParser.js +1177 -0
- package/vendor/converters/officeparser/dist/sbom.cdx.json +1763 -0
- package/vendor/converters/officeparser/dist/types.d.ts +2507 -0
- package/vendor/converters/officeparser/dist/types.js +107 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.d.ts +16 -0
- package/vendor/converters/officeparser/dist/utils/astUtils.js +33 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.d.ts +6 -0
- package/vendor/converters/officeparser/dist/utils/chartUtils.js +257 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.d.ts +44 -0
- package/vendor/converters/officeparser/dist/utils/configUtils.js +315 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.d.ts +17 -0
- package/vendor/converters/officeparser/dist/utils/dateUtils.js +69 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.d.ts +29 -0
- package/vendor/converters/officeparser/dist/utils/envUtils.js +152 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.d.ts +72 -0
- package/vendor/converters/officeparser/dist/utils/errorUtils.js +245 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.d.ts +66 -0
- package/vendor/converters/officeparser/dist/utils/imageUtils.js +133 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/mathUtils.js +385 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.d.ts +18 -0
- package/vendor/converters/officeparser/dist/utils/moduleLoader.js +106 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.d.ts +42 -0
- package/vendor/converters/officeparser/dist/utils/ocrUtils.js +428 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.d.ts +148 -0
- package/vendor/converters/officeparser/dist/utils/sanitize.js +344 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.d.ts +7 -0
- package/vendor/converters/officeparser/dist/utils/sheetUtils.js +35 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.d.ts +36 -0
- package/vendor/converters/officeparser/dist/utils/styleMapper.js +224 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.d.ts +163 -0
- package/vendor/converters/officeparser/dist/utils/xmlUtils.js +461 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.d.ts +134 -0
- package/vendor/converters/officeparser/dist/utils/zipUtils.js +337 -0
- package/vendor/converters/officeparser/package.json +147 -0
- package/vendor/converters/upstream-manifest.json +124 -0
- package/vendor/dependency-fixes/README.md +77 -0
- package/vendor/dependency-fixes/vendor-converters.py +83 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v1.46.0.zip.sha256 +0 -1
- package/browser-extension/dist/chunk-627emwpj.js +0 -75
- /package/browser-extension/dist/{chunk-ydfx5d7p.css → chunk-z74y8n8c.css} +0 -0
package/src/mcp/tools/index.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/server";
|
|
1
2
|
/**
|
|
2
3
|
* MCP tool registration and shared utilities.
|
|
3
4
|
*
|
|
4
5
|
* @module src/mcp/tools
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
|
-
import type { McpServer } from "@modelcontextprotocol/server";
|
|
8
|
-
|
|
9
8
|
import { z } from "zod";
|
|
10
9
|
|
|
11
10
|
import type { ToolContext } from "../server";
|
|
@@ -18,6 +17,10 @@ import { CAPTURE_MAX_TEXT_BYTES } from "../../core/capture";
|
|
|
18
17
|
import { NOTE_PRESETS, type NotePresetId } from "../../core/note-presets";
|
|
19
18
|
import { RETRIEVAL_TRACE_METADATA } from "../../core/retrieval-trace-session";
|
|
20
19
|
import { normalizeTag } from "../../core/tags";
|
|
20
|
+
import {
|
|
21
|
+
assertInferenceActive,
|
|
22
|
+
acquireInferencePermit,
|
|
23
|
+
} from "../../llm/inference-scope";
|
|
21
24
|
import { profileToolDescription } from "../tool-descriptions-core";
|
|
22
25
|
import {
|
|
23
26
|
createProfileToolRegistrar,
|
|
@@ -940,10 +943,11 @@ export async function runTool<T>(
|
|
|
940
943
|
}
|
|
941
944
|
|
|
942
945
|
// Sequential execution via mutex
|
|
943
|
-
const release = await ctx.toolMutex.acquire();
|
|
944
|
-
const modelLease = ctx.acquireModelLease?.();
|
|
946
|
+
const release = await acquireInferencePermit(() => ctx.toolMutex.acquire());
|
|
945
947
|
try {
|
|
948
|
+
assertInferenceActive();
|
|
946
949
|
const data = await (ctx.runWithSnapshot?.(fn) ?? fn());
|
|
950
|
+
assertInferenceActive();
|
|
947
951
|
const traceMetadata =
|
|
948
952
|
data !== null && typeof data === "object"
|
|
949
953
|
? (data as Record<PropertyKey, unknown>)[RETRIEVAL_TRACE_METADATA]
|
|
@@ -966,7 +970,6 @@ export async function runTool<T>(
|
|
|
966
970
|
structuredContent: parsedError,
|
|
967
971
|
};
|
|
968
972
|
} finally {
|
|
969
|
-
modelLease?.release();
|
|
970
973
|
release();
|
|
971
974
|
}
|
|
972
975
|
}
|
|
@@ -990,9 +993,10 @@ export async function runToolNoMutex<T>(
|
|
|
990
993
|
};
|
|
991
994
|
}
|
|
992
995
|
|
|
993
|
-
const modelLease = ctx.acquireModelLease?.();
|
|
994
996
|
try {
|
|
997
|
+
assertInferenceActive();
|
|
995
998
|
const data = await (ctx.runWithSnapshot?.(fn) ?? fn());
|
|
999
|
+
assertInferenceActive();
|
|
996
1000
|
return {
|
|
997
1001
|
content: [{ type: "text", text: formatText(data) }],
|
|
998
1002
|
structuredContent: data as { [x: string]: unknown },
|
|
@@ -1007,8 +1011,6 @@ export async function runToolNoMutex<T>(
|
|
|
1007
1011
|
content: [{ type: "text", text: `Error: ${message}` }],
|
|
1008
1012
|
structuredContent: parsedError,
|
|
1009
1013
|
};
|
|
1010
|
-
} finally {
|
|
1011
|
-
modelLease?.release();
|
|
1012
1014
|
}
|
|
1013
1015
|
}
|
|
1014
1016
|
|
package/src/mcp/tools/query.ts
CHANGED
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
SearchResult,
|
|
18
18
|
SearchResults,
|
|
19
19
|
} from "../../pipeline/types";
|
|
20
|
+
import type { VectorIndexPort } from "../../store/vector";
|
|
20
21
|
import type { ToolContext } from "../server";
|
|
21
22
|
|
|
22
23
|
import { decorateUriForIndex, parseUri } from "../../app/constants";
|
|
@@ -42,10 +43,7 @@ import { resolveDownloadPolicy } from "../../llm/policy";
|
|
|
42
43
|
import { getActivePreset, resolveModelUri } from "../../llm/registry";
|
|
43
44
|
import { diagnoseQueryTarget } from "../../pipeline/diagnose";
|
|
44
45
|
import { type HybridSearchDeps, searchHybrid } from "../../pipeline/hybrid";
|
|
45
|
-
import {
|
|
46
|
-
createVectorIndexPort,
|
|
47
|
-
type VectorIndexPort,
|
|
48
|
-
} from "../../store/vector";
|
|
46
|
+
import { createLazyVectorIndex } from "../../store/vector/lazy";
|
|
49
47
|
import { normalizeTagFilters, runTool, type ToolResult } from "./index";
|
|
50
48
|
|
|
51
49
|
interface QueryInput {
|
|
@@ -278,7 +276,7 @@ export function handleQuery(
|
|
|
278
276
|
});
|
|
279
277
|
if (!traceStart.ok) throw new Error(traceStart.error.message);
|
|
280
278
|
traceSession = traceStart.value ?? undefined;
|
|
281
|
-
const llm = new LlmAdapter(ctx.config);
|
|
279
|
+
const llm = ctx.getModelAdapter?.() ?? new LlmAdapter(ctx.config);
|
|
282
280
|
const egressCollections = args.collection
|
|
283
281
|
? [args.collection]
|
|
284
282
|
: ("all" as const);
|
|
@@ -325,18 +323,11 @@ export function handleQuery(
|
|
|
325
323
|
|
|
326
324
|
// Create vector index (optional)
|
|
327
325
|
if (embedPort) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
model: embedUri,
|
|
334
|
-
dimensions,
|
|
335
|
-
});
|
|
336
|
-
if (vectorResult.ok) {
|
|
337
|
-
vectorIndex = vectorResult.value;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
326
|
+
vectorIndex = await createLazyVectorIndex(
|
|
327
|
+
ctx.store.getRawDb(),
|
|
328
|
+
embedUri,
|
|
329
|
+
embedPort
|
|
330
|
+
);
|
|
340
331
|
}
|
|
341
332
|
|
|
342
333
|
const deps: HybridSearchDeps = {
|
|
@@ -428,7 +419,7 @@ export function handleQueryDiagnose(
|
|
|
428
419
|
: undefined;
|
|
429
420
|
|
|
430
421
|
const preset = getActivePreset(ctx.config);
|
|
431
|
-
const llm = new LlmAdapter(ctx.config);
|
|
422
|
+
const llm = ctx.getModelAdapter?.() ?? new LlmAdapter(ctx.config);
|
|
432
423
|
const policy = resolveDownloadPolicy(process.env, {});
|
|
433
424
|
const downloadProgress = createNonTtyProgressRenderer();
|
|
434
425
|
const egressCollections = collection ? [collection] : ("all" as const);
|
|
@@ -501,18 +492,11 @@ export function handleQueryDiagnose(
|
|
|
501
492
|
}
|
|
502
493
|
|
|
503
494
|
if (embedPort) {
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
model: embedUri,
|
|
510
|
-
dimensions,
|
|
511
|
-
});
|
|
512
|
-
if (vectorResult.ok) {
|
|
513
|
-
vectorIndex = vectorResult.value;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
495
|
+
vectorIndex = await createLazyVectorIndex(
|
|
496
|
+
ctx.store.getRawDb(),
|
|
497
|
+
embedUri,
|
|
498
|
+
embedPort
|
|
499
|
+
);
|
|
516
500
|
}
|
|
517
501
|
|
|
518
502
|
const deps: HybridSearchDeps = {
|
package/src/mcp/tools/vsearch.ts
CHANGED
|
@@ -178,7 +178,7 @@ export function handleVsearch(
|
|
|
178
178
|
const downloadProgress = createNonTtyProgressRenderer();
|
|
179
179
|
|
|
180
180
|
// Create LLM adapter for embeddings
|
|
181
|
-
const llm = new LlmAdapter(ctx.config);
|
|
181
|
+
const llm = ctx.getModelAdapter?.() ?? new LlmAdapter(ctx.config);
|
|
182
182
|
const embedResult = await llm.createEmbeddingPort(modelUri, {
|
|
183
183
|
egressCollections: args.collection ? [args.collection] : "all",
|
|
184
184
|
policy,
|
package/src/pipeline/answer.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import type { RetrievalTraceSession } from "../core/retrieval-trace-session";
|
|
1
2
|
/**
|
|
2
3
|
* Grounded answer generation.
|
|
3
4
|
* Shared between CLI ask command and web API.
|
|
4
5
|
*
|
|
5
6
|
* @module src/pipeline/answer
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
import type { RetrievalTraceSession } from "../core/retrieval-trace-session";
|
|
9
8
|
import type { GenerationPort } from "../llm/types";
|
|
10
9
|
import type { StorePort } from "../store/types";
|
|
10
|
+
import type { RequestHydration } from "./hydration";
|
|
11
11
|
import type {
|
|
12
12
|
AnswerContextEntry,
|
|
13
13
|
AnswerContextExplain,
|
|
@@ -15,6 +15,10 @@ import type {
|
|
|
15
15
|
SearchResult,
|
|
16
16
|
} from "./types";
|
|
17
17
|
|
|
18
|
+
import {
|
|
19
|
+
assertInferenceActive,
|
|
20
|
+
assertInferenceResult,
|
|
21
|
+
} from "../llm/inference-scope";
|
|
18
22
|
import { buildAnswerPrompt, type AnswerPromptSource } from "./answer-prompt";
|
|
19
23
|
import { attachCitationTraceMetadata } from "./trace-metadata";
|
|
20
24
|
import {
|
|
@@ -117,6 +121,7 @@ const completeLinePrefix = (
|
|
|
117
121
|
const selected: string[] = [];
|
|
118
122
|
let characters = 0;
|
|
119
123
|
for (const line of lines) {
|
|
124
|
+
assertInferenceActive();
|
|
120
125
|
const addition = selected.length === 0 ? line.length : line.length + 1;
|
|
121
126
|
if (characters + addition > maxChars) break;
|
|
122
127
|
selected.push(line);
|
|
@@ -172,6 +177,7 @@ export function extractValidCitationNumbers(
|
|
|
172
177
|
const re = /\[(\d+)\]/g;
|
|
173
178
|
const matches = answer.matchAll(re);
|
|
174
179
|
for (const match of matches) {
|
|
180
|
+
assertInferenceActive();
|
|
175
181
|
const n = Number(match[1]);
|
|
176
182
|
if (Number.isInteger(n) && n >= 1 && n <= maxCitation) {
|
|
177
183
|
nums.add(n);
|
|
@@ -231,6 +237,8 @@ export interface AnswerGenerationResult {
|
|
|
231
237
|
export interface AnswerGenerationDeps {
|
|
232
238
|
genPort: GenerationPort;
|
|
233
239
|
store: StorePort | null;
|
|
240
|
+
/** Raw request-owned content only; passage/hash validation still runs. */
|
|
241
|
+
hydration?: Pick<RequestHydration, "getContent">;
|
|
234
242
|
}
|
|
235
243
|
|
|
236
244
|
function normalizeScore(score: number): number {
|
|
@@ -273,6 +281,7 @@ function buildCandidates(
|
|
|
273
281
|
|
|
274
282
|
const matchedQueryTokens = new Set<string>();
|
|
275
283
|
for (const token of queryTokenSet) {
|
|
284
|
+
assertInferenceActive();
|
|
276
285
|
if (signalTokenSet.has(token)) {
|
|
277
286
|
matchedQueryTokens.add(token);
|
|
278
287
|
}
|
|
@@ -280,7 +289,9 @@ function buildCandidates(
|
|
|
280
289
|
|
|
281
290
|
const matchedFacetIndexes = new Set<number>();
|
|
282
291
|
for (const [index, facetTokenSet] of facetTokenSets.entries()) {
|
|
292
|
+
assertInferenceActive();
|
|
283
293
|
for (const token of facetTokenSet) {
|
|
294
|
+
assertInferenceActive();
|
|
284
295
|
if (signalTokenSet.has(token)) {
|
|
285
296
|
matchedFacetIndexes.add(index);
|
|
286
297
|
break;
|
|
@@ -301,6 +312,7 @@ function dedupeByDocidBestScore(results: SearchResult[]): SearchResult[] {
|
|
|
301
312
|
const bestByDocid = new Map<string, SearchResult>();
|
|
302
313
|
|
|
303
314
|
for (const result of results) {
|
|
315
|
+
assertInferenceActive();
|
|
304
316
|
const existing = bestByDocid.get(result.docid);
|
|
305
317
|
if (!existing || result.score > existing.score) {
|
|
306
318
|
bestByDocid.set(result.docid, result);
|
|
@@ -358,6 +370,7 @@ function selectAdaptiveSources(
|
|
|
358
370
|
let bestReason = "relevance";
|
|
359
371
|
|
|
360
372
|
for (const candidate of candidates) {
|
|
373
|
+
assertInferenceActive();
|
|
361
374
|
const docid = candidate.result.docid;
|
|
362
375
|
if (selectedDocids.has(docid)) {
|
|
363
376
|
continue;
|
|
@@ -418,15 +431,18 @@ function selectAdaptiveSources(
|
|
|
418
431
|
selected.push({ candidate: bestCandidate, reason: bestReason });
|
|
419
432
|
selectedDocids.add(bestCandidate.result.docid);
|
|
420
433
|
for (const token of bestCandidate.matchedQueryTokens) {
|
|
434
|
+
assertInferenceActive();
|
|
421
435
|
coveredTokens.add(token);
|
|
422
436
|
}
|
|
423
437
|
for (const index of bestCandidate.matchedFacetIndexes) {
|
|
438
|
+
assertInferenceActive();
|
|
424
439
|
coveredFacets.add(index);
|
|
425
440
|
}
|
|
426
441
|
}
|
|
427
442
|
|
|
428
443
|
if (comparisonIntent && selected.length < 2) {
|
|
429
444
|
for (const candidate of candidates) {
|
|
445
|
+
assertInferenceActive();
|
|
430
446
|
if (selectedDocids.has(candidate.result.docid)) {
|
|
431
447
|
continue;
|
|
432
448
|
}
|
|
@@ -501,6 +517,7 @@ export async function generateGroundedAnswer(
|
|
|
501
517
|
let citationIndex = 0;
|
|
502
518
|
|
|
503
519
|
for (const r of sourceSelection.selected) {
|
|
520
|
+
assertInferenceActive();
|
|
504
521
|
let passage: ExactAnswerPassage | null = null;
|
|
505
522
|
const plannerMetadata = r[SEARCH_RESULT_PLANNER_METADATA];
|
|
506
523
|
const sourceHash = r.source.sourceHash;
|
|
@@ -508,7 +525,9 @@ export async function generateGroundedAnswer(
|
|
|
508
525
|
|
|
509
526
|
// Try to fetch full document content if store available
|
|
510
527
|
if (store && mirrorHash) {
|
|
511
|
-
const contentResult = await store.getContent(
|
|
528
|
+
const contentResult = await (deps.hydration ?? store).getContent(
|
|
529
|
+
mirrorHash
|
|
530
|
+
);
|
|
512
531
|
if (contentResult.ok && contentResult.value) {
|
|
513
532
|
if (sha256(contentResult.value) === mirrorHash) {
|
|
514
533
|
passage =
|
|
@@ -578,6 +597,7 @@ export async function generateGroundedAnswer(
|
|
|
578
597
|
maxTokens,
|
|
579
598
|
});
|
|
580
599
|
|
|
600
|
+
assertInferenceResult(result);
|
|
581
601
|
if (!result.ok) {
|
|
582
602
|
return null;
|
|
583
603
|
}
|
|
@@ -8,6 +8,10 @@ import type {
|
|
|
8
8
|
} from "./claim-verification";
|
|
9
9
|
|
|
10
10
|
import { sha256Text } from "../core/context-capsule-validation";
|
|
11
|
+
import {
|
|
12
|
+
assertInferenceActive,
|
|
13
|
+
assertInferenceResult,
|
|
14
|
+
} from "../llm/inference-scope";
|
|
11
15
|
import {
|
|
12
16
|
semanticClaimJudgmentSchema,
|
|
13
17
|
verifyClaimsDeterministically,
|
|
@@ -251,6 +255,7 @@ const parseEnvelope = (
|
|
|
251
255
|
}
|
|
252
256
|
const judgments: SemanticClaimJudgment[] = [];
|
|
253
257
|
for (const rawJudgment of parsed.data.judgments) {
|
|
258
|
+
assertInferenceActive();
|
|
254
259
|
const candidate = candidatesById.get(rawJudgment.claimId);
|
|
255
260
|
const allowed = new Set(
|
|
256
261
|
candidate?.evidence.map((item) => item.evidenceId) ?? []
|
|
@@ -416,6 +421,7 @@ export const verifyClaimsSemantically = async (
|
|
|
416
421
|
maxTokens: MAX_OUTPUT_TOKENS,
|
|
417
422
|
jsonSchema: schema,
|
|
418
423
|
});
|
|
424
|
+
assertInferenceResult(generated);
|
|
419
425
|
if (!generated.ok) {
|
|
420
426
|
return failedResult(
|
|
421
427
|
deterministic,
|
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
import { createHash } from "node:crypto"; // No Bun alternative for hashing
|
|
2
|
+
|
|
3
|
+
import type { InferenceOptions } from "../llm/types";
|
|
1
4
|
/**
|
|
2
5
|
* Query expansion for hybrid search.
|
|
3
6
|
* Uses GenerationPort to generate query variants.
|
|
4
7
|
*
|
|
5
8
|
* @module src/pipeline/expansion
|
|
6
9
|
*/
|
|
7
|
-
|
|
8
|
-
import { createHash } from "node:crypto"; // No Bun alternative for hashing
|
|
9
|
-
|
|
10
10
|
import type { GenerationPort } from "../llm/types";
|
|
11
11
|
import type { StoreResult } from "../store/types";
|
|
12
12
|
import type { ExpansionResult } from "./types";
|
|
13
13
|
|
|
14
|
+
import {
|
|
15
|
+
assertInferenceActive,
|
|
16
|
+
assertInferenceResult,
|
|
17
|
+
inferenceOptions,
|
|
18
|
+
} from "../llm/inference-scope";
|
|
14
19
|
import { ok } from "../store/types";
|
|
15
20
|
|
|
16
21
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -449,7 +454,7 @@ export function parseExpansionOutput(
|
|
|
449
454
|
// Expansion Function
|
|
450
455
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
451
456
|
|
|
452
|
-
export interface ExpansionOptions {
|
|
457
|
+
export interface ExpansionOptions extends InferenceOptions {
|
|
453
458
|
/** Language hint for prompt selection */
|
|
454
459
|
lang?: string;
|
|
455
460
|
/** Timeout in milliseconds */
|
|
@@ -474,49 +479,47 @@ export async function expandQuery(
|
|
|
474
479
|
// Build prompt
|
|
475
480
|
const prompt = buildExpansionPrompt(query, options);
|
|
476
481
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
482
|
+
assertInferenceActive(options);
|
|
483
|
+
const operational = inferenceOptions(options);
|
|
484
|
+
const budget = new AbortController();
|
|
485
|
+
const expiresAt = performance.now() + timeout;
|
|
486
|
+
const timer = setTimeout(() => budget.abort(), timeout);
|
|
483
487
|
try {
|
|
484
|
-
const result = await
|
|
485
|
-
|
|
488
|
+
const result = await genPort.generate(
|
|
489
|
+
prompt,
|
|
490
|
+
{
|
|
486
491
|
temperature: 0,
|
|
487
492
|
seed: 42,
|
|
488
493
|
maxTokens: 512,
|
|
489
494
|
contextSize: options.contextSize,
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
//
|
|
500
|
-
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
...operational,
|
|
498
|
+
signal: operational.signal
|
|
499
|
+
? AbortSignal.any([operational.signal, budget.signal])
|
|
500
|
+
: budget.signal,
|
|
501
|
+
}
|
|
502
|
+
);
|
|
503
|
+
// The independent expansion budget preserves its existing fallback. Caller
|
|
504
|
+
// cancellation/deadline always wins and cannot become a lexical success.
|
|
505
|
+
assertInferenceActive(options);
|
|
506
|
+
if (budget.signal.aborted || performance.now() >= expiresAt)
|
|
501
507
|
return ok(null);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
// Parse result
|
|
510
|
-
const parsed = parseExpansionOutput(result.value, query);
|
|
511
|
-
if (!parsed) {
|
|
508
|
+
assertInferenceResult(result);
|
|
509
|
+
if (!result.ok) return ok(null);
|
|
510
|
+
return ok(parseExpansionOutput(result.value, query));
|
|
511
|
+
} catch (cause) {
|
|
512
|
+
assertInferenceActive(options);
|
|
513
|
+
if (budget.signal.aborted || performance.now() >= expiresAt)
|
|
512
514
|
return ok(null);
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
515
|
+
if (
|
|
516
|
+
cause instanceof Error &&
|
|
517
|
+
["AbortError", "TimeoutError"].includes(cause.name)
|
|
518
|
+
)
|
|
519
|
+
throw cause;
|
|
520
|
+
return ok(null);
|
|
521
|
+
} finally {
|
|
522
|
+
clearTimeout(timer);
|
|
520
523
|
}
|
|
521
524
|
}
|
|
522
525
|
|
package/src/pipeline/explain.ts
CHANGED
|
@@ -234,7 +234,11 @@ export function buildExplainResults(
|
|
|
234
234
|
const candidate = candidates.find(
|
|
235
235
|
(entry) =>
|
|
236
236
|
entry.mirrorHash === result.conversion?.mirrorHash &&
|
|
237
|
-
entry.seq === (planner?.retrievalSeq ?? planner?.seq)
|
|
237
|
+
entry.seq === (planner?.retrievalSeq ?? planner?.seq) &&
|
|
238
|
+
(entry.documentId === undefined ||
|
|
239
|
+
docidMap.get(
|
|
240
|
+
`${entry.mirrorHash}:${entry.seq}:${entry.documentId}`
|
|
241
|
+
) === result.docid)
|
|
238
242
|
);
|
|
239
243
|
return {
|
|
240
244
|
...buildExplainResult(result.docid, result.score, index, candidate),
|
|
@@ -244,7 +248,7 @@ export function buildExplainResults(
|
|
|
244
248
|
});
|
|
245
249
|
}
|
|
246
250
|
return candidates.slice(0, 20).map((candidate, index) => {
|
|
247
|
-
const key = `${candidate.mirrorHash}:${candidate.seq}`;
|
|
251
|
+
const key = `${candidate.mirrorHash}:${candidate.seq}${candidate.documentId === undefined ? "" : `:${candidate.documentId}`}`;
|
|
248
252
|
return buildExplainResult(
|
|
249
253
|
docidMap.get(key) ?? "#unknown",
|
|
250
254
|
candidate.blendedScore,
|
package/src/pipeline/filters.ts
CHANGED
|
@@ -15,6 +15,69 @@ export interface QueryFilterEvaluation {
|
|
|
15
15
|
reasons: string[];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
/** Internal pre-budget contract. Undefined metadata is a failed lookup, never
|
|
19
|
+
* an unrestricted candidate. Owners must be evaluated separately; this does
|
|
20
|
+
* not replace complete ownership lineage or change ranking/deduplication.
|
|
21
|
+
* Managed-memory scopes/supersession must already be enforced by the store.
|
|
22
|
+
*/
|
|
23
|
+
export async function evaluateRetrievalEligibility(
|
|
24
|
+
store: StorePort,
|
|
25
|
+
query: string,
|
|
26
|
+
doc: DocumentRow | undefined,
|
|
27
|
+
chunks: ChunkRow[] | undefined,
|
|
28
|
+
options: HybridSearchOptions,
|
|
29
|
+
callerScope?: Pick<HybridSearchOptions, "collection" | "retrievalScope">
|
|
30
|
+
): Promise<QueryFilterEvaluation & { chunks: ChunkRow[] }> {
|
|
31
|
+
if (!doc || !chunks || !doc.mirrorHash) {
|
|
32
|
+
return { matches: false, reasons: ["metadata"], chunks: [] };
|
|
33
|
+
}
|
|
34
|
+
const reasons: string[] = [];
|
|
35
|
+
if (!doc.active) reasons.push("inactive");
|
|
36
|
+
const sourcePath = doc.recordSourcePath ?? doc.relPath;
|
|
37
|
+
for (const scope of [callerScope, options]) {
|
|
38
|
+
if (scope?.collection && doc.collection !== scope.collection) {
|
|
39
|
+
reasons.push("collection");
|
|
40
|
+
}
|
|
41
|
+
if (scope?.retrievalScope) {
|
|
42
|
+
if (!scope.retrievalScope.allowedMirrorHashes.includes(doc.mirrorHash)) {
|
|
43
|
+
reasons.push("scope");
|
|
44
|
+
}
|
|
45
|
+
const prefix = scope.retrievalScope.relPathPrefix;
|
|
46
|
+
if (
|
|
47
|
+
prefix !== undefined &&
|
|
48
|
+
sourcePath !== prefix &&
|
|
49
|
+
!sourcePath.startsWith(`${prefix}/`)
|
|
50
|
+
) {
|
|
51
|
+
reasons.push("path");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Whole-document exclusions inspect every chunk before language selection.
|
|
56
|
+
// A mismatched hash is incomplete/corrupt metadata, not a usable owner.
|
|
57
|
+
if (chunks.some((chunk) => chunk.mirrorHash !== doc.mirrorHash)) {
|
|
58
|
+
reasons.push("metadata");
|
|
59
|
+
}
|
|
60
|
+
if (reasons.length === 0) {
|
|
61
|
+
try {
|
|
62
|
+
reasons.push(
|
|
63
|
+
...(
|
|
64
|
+
await evaluateQueryTargetFilters(store, query, doc, chunks, options)
|
|
65
|
+
).reasons
|
|
66
|
+
);
|
|
67
|
+
} catch {
|
|
68
|
+
reasons.push("metadata");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const eligibleChunks = chunks.filter(
|
|
72
|
+
(chunk) => !options.lang || chunk.language === options.lang
|
|
73
|
+
);
|
|
74
|
+
return {
|
|
75
|
+
matches: reasons.length === 0,
|
|
76
|
+
reasons,
|
|
77
|
+
chunks: reasons.length === 0 ? eligibleChunks : [],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
18
81
|
export function evaluateDocumentChunkFilters(
|
|
19
82
|
query: string,
|
|
20
83
|
doc: DocumentRow,
|
package/src/pipeline/fusion.ts
CHANGED
|
@@ -15,6 +15,8 @@ import type { FusionCandidate, FusionSource, RrfConfig } from "./types";
|
|
|
15
15
|
export interface RankedInput {
|
|
16
16
|
source: FusionSource;
|
|
17
17
|
results: Array<{
|
|
18
|
+
sourceDocid?: string;
|
|
19
|
+
documentId?: number;
|
|
18
20
|
mirrorHash: string;
|
|
19
21
|
seq: number;
|
|
20
22
|
rank: number; // 1-based rank
|
|
@@ -73,11 +75,14 @@ export function rrfFuse(
|
|
|
73
75
|
: config.bm25Weight * 0.5;
|
|
74
76
|
|
|
75
77
|
for (const result of input.results) {
|
|
76
|
-
const key = `${result.mirrorHash}:${result.seq}`;
|
|
78
|
+
const key = `${result.mirrorHash}:${result.seq}:${result.documentId ?? ""}`;
|
|
77
79
|
let candidate = candidates.get(key);
|
|
78
80
|
|
|
79
81
|
if (!candidate) {
|
|
80
82
|
candidate = {
|
|
83
|
+
...(result.documentId === undefined
|
|
84
|
+
? {}
|
|
85
|
+
: { documentId: result.documentId }),
|
|
81
86
|
mirrorHash: result.mirrorHash,
|
|
82
87
|
seq: result.seq,
|
|
83
88
|
bm25Rank: null,
|
|
@@ -112,11 +117,14 @@ export function rrfFuse(
|
|
|
112
117
|
}
|
|
113
118
|
|
|
114
119
|
for (const result of input.results) {
|
|
115
|
-
const key = `${result.mirrorHash}:${result.seq}`;
|
|
120
|
+
const key = `${result.mirrorHash}:${result.seq}:${result.documentId ?? ""}`;
|
|
116
121
|
let candidate = candidates.get(key);
|
|
117
122
|
|
|
118
123
|
if (!candidate) {
|
|
119
124
|
candidate = {
|
|
125
|
+
...(result.documentId === undefined
|
|
126
|
+
? {}
|
|
127
|
+
: { documentId: result.documentId }),
|
|
120
128
|
mirrorHash: result.mirrorHash,
|
|
121
129
|
seq: result.seq,
|
|
122
130
|
bm25Rank: null,
|
|
@@ -145,11 +153,14 @@ export function rrfFuse(
|
|
|
145
153
|
const weight = config.bm25Weight * 0.8;
|
|
146
154
|
|
|
147
155
|
for (const result of input.results) {
|
|
148
|
-
const key = `${result.mirrorHash}:${result.seq}`;
|
|
156
|
+
const key = `${result.mirrorHash}:${result.seq}:${result.documentId ?? ""}`;
|
|
149
157
|
let candidate = candidates.get(key);
|
|
150
158
|
|
|
151
159
|
if (!candidate) {
|
|
152
160
|
candidate = {
|
|
161
|
+
...(result.documentId === undefined
|
|
162
|
+
? {}
|
|
163
|
+
: { documentId: result.documentId }),
|
|
153
164
|
mirrorHash: result.mirrorHash,
|
|
154
165
|
seq: result.seq,
|
|
155
166
|
bm25Rank: null,
|
|
@@ -211,14 +222,23 @@ export function rrfFuse(
|
|
|
211
222
|
*/
|
|
212
223
|
export function toRankedInput(
|
|
213
224
|
source: FusionSource,
|
|
214
|
-
results: Array<{
|
|
225
|
+
results: Array<{
|
|
226
|
+
mirrorHash: string;
|
|
227
|
+
seq: number;
|
|
228
|
+
documentIds?: number[];
|
|
229
|
+
sourceDocid?: string;
|
|
230
|
+
}>
|
|
215
231
|
): RankedInput {
|
|
216
232
|
return {
|
|
217
233
|
source,
|
|
218
|
-
results: results.
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
234
|
+
results: results.flatMap((r, i) =>
|
|
235
|
+
(r.documentIds ?? [undefined]).map((documentId) => ({
|
|
236
|
+
...(documentId === undefined ? {} : { documentId }),
|
|
237
|
+
...(r.sourceDocid === undefined ? {} : { sourceDocid: r.sourceDocid }),
|
|
238
|
+
mirrorHash: r.mirrorHash,
|
|
239
|
+
seq: r.seq,
|
|
240
|
+
rank: i + 1,
|
|
241
|
+
}))
|
|
242
|
+
),
|
|
223
243
|
};
|
|
224
244
|
}
|