@gmickel/gno 1.18.0 → 1.19.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 +5 -3
- package/assets/skill/SKILL.md +27 -0
- package/package.json +2 -1
- package/spec/AGENTS.md +83 -0
- package/spec/CLAUDE.md +83 -0
- package/spec/bench-fixture.schema.json +137 -0
- package/spec/cli.md +2894 -0
- package/spec/db/schema.sql +442 -0
- package/spec/evals-agentic.md +510 -0
- package/spec/evals.md +1106 -0
- package/spec/mcp.md +2229 -0
- package/spec/output-schemas/activation-verification.schema.json +515 -0
- package/spec/output-schemas/ask.schema.json +366 -0
- package/spec/output-schemas/backlinks.schema.json +131 -0
- package/spec/output-schemas/bench-result.schema.json +120 -0
- package/spec/output-schemas/capture-receipt.schema.json +143 -0
- package/spec/output-schemas/collection-list.schema.json +45 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +691 -0
- package/spec/output-schemas/context-capsule-verification.schema.json +1338 -0
- package/spec/output-schemas/context-list.schema.json +21 -0
- package/spec/output-schemas/doctor.schema.json +313 -0
- package/spec/output-schemas/error.schema.json +30 -0
- package/spec/output-schemas/expansion.schema.json +37 -0
- package/spec/output-schemas/get.schema.json +140 -0
- package/spec/output-schemas/graph-query.schema.json +99 -0
- package/spec/output-schemas/graph.schema.json +371 -0
- package/spec/output-schemas/links-list.schema.json +186 -0
- package/spec/output-schemas/mcp-add-collection-result.schema.json +23 -0
- package/spec/output-schemas/mcp-capture-result.schema.json +152 -0
- package/spec/output-schemas/mcp-http-error.schema.json +30 -0
- package/spec/output-schemas/mcp-job-list.schema.json +58 -0
- package/spec/output-schemas/mcp-job-status.schema.json +224 -0
- package/spec/output-schemas/mcp-remove-result.schema.json +39 -0
- package/spec/output-schemas/mcp-sync-result.schema.json +41 -0
- package/spec/output-schemas/mcp-tag-result.schema.json +33 -0
- package/spec/output-schemas/models-list.schema.json +93 -0
- package/spec/output-schemas/multi-get.schema.json +103 -0
- package/spec/output-schemas/process-status.schema.json +119 -0
- package/spec/output-schemas/query-diagnose.schema.json +123 -0
- package/spec/output-schemas/resident-status.schema.json +154 -0
- package/spec/output-schemas/retrieval-trace-common.schema.json +492 -0
- package/spec/output-schemas/retrieval-trace-delete.schema.json +16 -0
- package/spec/output-schemas/retrieval-trace-export.schema.json +61 -0
- package/spec/output-schemas/retrieval-trace-filters.schema.json +139 -0
- package/spec/output-schemas/retrieval-trace-judgment.schema.json +15 -0
- package/spec/output-schemas/retrieval-trace-list.schema.json +18 -0
- package/spec/output-schemas/retrieval-trace-payloads.schema.json +178 -0
- package/spec/output-schemas/retrieval-trace-purge.schema.json +31 -0
- package/spec/output-schemas/retrieval-trace-qrels.schema.json +303 -0
- package/spec/output-schemas/retrieval-trace-replay.schema.json +286 -0
- package/spec/output-schemas/retrieval-trace-show.schema.json +69 -0
- package/spec/output-schemas/retrieval-trace-summary.schema.json +65 -0
- package/spec/output-schemas/search-result.schema.json +154 -0
- package/spec/output-schemas/search-results.schema.json +338 -0
- package/spec/output-schemas/similar.schema.json +84 -0
- package/spec/output-schemas/status.schema.json +676 -0
- package/spec/output-schemas/tags-list.schema.json +48 -0
- package/src/app/context-runtime-types.ts +3 -0
- package/src/app/context-runtime.ts +15 -1
- package/src/cli/commands/ask.ts +106 -36
- package/src/cli/commands/context-build.ts +56 -9
- package/src/cli/commands/get.ts +64 -3
- package/src/cli/commands/query.ts +62 -23
- package/src/cli/commands/replay.ts +140 -0
- package/src/cli/commands/search.ts +48 -3
- package/src/cli/commands/shared.ts +3 -1
- package/src/cli/commands/trace.ts +200 -0
- package/src/cli/commands/vsearch.ts +75 -53
- package/src/cli/program.ts +255 -0
- package/src/config/index.ts +9 -0
- package/src/config/retrieval-traces.ts +56 -0
- package/src/config/types.ts +4 -0
- package/src/core/context-compiler.ts +11 -4
- package/src/core/retrieval-qrels.ts +405 -0
- package/src/core/retrieval-replay-candidate.ts +368 -0
- package/src/core/retrieval-replay-types.ts +109 -0
- package/src/core/retrieval-replay-validation.ts +89 -0
- package/src/core/retrieval-replay.ts +441 -0
- package/src/core/retrieval-trace-evidence-origin.ts +175 -0
- package/src/core/retrieval-trace-export.ts +113 -0
- package/src/core/retrieval-trace-filter-normalization.ts +27 -0
- package/src/core/retrieval-trace-filters.ts +19 -0
- package/src/core/retrieval-trace-management-helpers.ts +247 -0
- package/src/core/retrieval-trace-management-types.ts +132 -0
- package/src/core/retrieval-trace-management.ts +422 -0
- package/src/core/retrieval-trace-request.ts +141 -0
- package/src/core/retrieval-trace-session.ts +494 -0
- package/src/core/retrieval-trace.ts +472 -0
- package/src/mcp/tools/context.ts +59 -8
- package/src/mcp/tools/get.ts +35 -1
- package/src/mcp/tools/index.ts +74 -0
- package/src/mcp/tools/query.ts +95 -64
- package/src/mcp/tools/search.ts +36 -13
- package/src/mcp/tools/trace.ts +143 -0
- package/src/mcp/tools/vsearch.ts +71 -38
- package/src/pipeline/answer.ts +167 -26
- package/src/pipeline/graph-retrieval.ts +15 -1
- package/src/pipeline/hybrid.ts +151 -43
- package/src/pipeline/search.ts +36 -3
- package/src/pipeline/trace-metadata.ts +47 -0
- package/src/pipeline/types.ts +43 -0
- package/src/pipeline/vsearch.ts +101 -38
- package/src/sdk/client.ts +380 -71
- package/src/sdk/documents.ts +48 -1
- package/src/sdk/index.ts +17 -0
- package/src/sdk/types.ts +28 -0
- package/src/serve/context-capsule.ts +67 -8
- package/src/serve/public/app.tsx +12 -1
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/workspace-tabs.ts +2 -0
- package/src/serve/public/pages/Dashboard.tsx +10 -0
- package/src/serve/public/pages/TraceHistory.tsx +478 -0
- package/src/serve/public/pages/trace-history-detail.tsx +224 -0
- package/src/serve/retrieval-trace.ts +28 -0
- package/src/serve/routes/api.ts +366 -72
- package/src/serve/routes/traces.ts +156 -0
- package/src/serve/server.ts +87 -2
- package/src/store/index.ts +31 -0
- package/src/store/migrations/014-retrieval-traces.ts +303 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/retrieval-trace-codec.ts +384 -0
- package/src/store/sqlite/adapter.ts +153 -1
- package/src/store/sqlite/retrieval-trace-management-store.ts +341 -0
- package/src/store/sqlite/retrieval-trace-retention.ts +349 -0
- package/src/store/sqlite/retrieval-trace-rows.ts +267 -0
- package/src/store/sqlite/retrieval-trace-store.ts +515 -0
- package/src/store/types.ts +297 -0
- package/src/store/vector/sqlite-vec.ts +76 -1
- package/src/store/vector/types.ts +1 -1
package/src/store/types.ts
CHANGED
|
@@ -346,6 +346,8 @@ export interface FtsSearchOptions {
|
|
|
346
346
|
limit?: number;
|
|
347
347
|
/** Filter by collection */
|
|
348
348
|
collection?: string;
|
|
349
|
+
/** Internal exact relative-path boundary applied before ranking and LIMIT. */
|
|
350
|
+
relPathPrefix?: string;
|
|
349
351
|
/**
|
|
350
352
|
* Language hint (reserved for future use).
|
|
351
353
|
* Note: FTS5 snowball tokenizer is language-aware at index time,
|
|
@@ -816,6 +818,220 @@ export interface ActivationIndexSnapshot {
|
|
|
816
818
|
documents: ActivationIndexDocument[];
|
|
817
819
|
}
|
|
818
820
|
|
|
821
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
822
|
+
// Private Retrieval Trace Receipts
|
|
823
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
824
|
+
|
|
825
|
+
export type RetrievalTraceRedactionMode = "metadata" | "replay";
|
|
826
|
+
export type RetrievalTraceTerminalStatus =
|
|
827
|
+
| "completed"
|
|
828
|
+
| "partial"
|
|
829
|
+
| "failed"
|
|
830
|
+
| "cancelled";
|
|
831
|
+
export type RetrievalTraceStatus = "open" | RetrievalTraceTerminalStatus;
|
|
832
|
+
export type RetrievalTraceJudgmentLabel =
|
|
833
|
+
| "relevant"
|
|
834
|
+
| "irrelevant"
|
|
835
|
+
| "missing_expected";
|
|
836
|
+
export type RetrievalTraceJudgmentTargetKind =
|
|
837
|
+
| "document"
|
|
838
|
+
| "chunk"
|
|
839
|
+
| "span"
|
|
840
|
+
| "query";
|
|
841
|
+
export type RetrievalTraceAppendResult = "inserted" | "duplicate";
|
|
842
|
+
export type RetrievalTraceRunKind = "retrieval" | "context" | "get";
|
|
843
|
+
export type RetrievalTraceEventKind =
|
|
844
|
+
| "query"
|
|
845
|
+
| "retrieval"
|
|
846
|
+
| "context"
|
|
847
|
+
| "get"
|
|
848
|
+
| "open"
|
|
849
|
+
| "cite"
|
|
850
|
+
| "pin"
|
|
851
|
+
| "capability"
|
|
852
|
+
| "complete";
|
|
853
|
+
export type RetrievalTraceExportFormat = "agentic-receipt" | "qrels";
|
|
854
|
+
|
|
855
|
+
export interface RetrievalTraceFingerprints {
|
|
856
|
+
pipeline: string;
|
|
857
|
+
model: string;
|
|
858
|
+
config: string;
|
|
859
|
+
index: string;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/** Already-redacted trace header persisted by StorePort implementations. */
|
|
863
|
+
export interface RetrievalTraceInput {
|
|
864
|
+
traceId: string;
|
|
865
|
+
schemaVersion: "1.0";
|
|
866
|
+
redactionMode: RetrievalTraceRedactionMode;
|
|
867
|
+
replayCapable: boolean;
|
|
868
|
+
queryText: string | null;
|
|
869
|
+
queryDigest: string | null;
|
|
870
|
+
queryShape: {
|
|
871
|
+
characters: number;
|
|
872
|
+
terms: number;
|
|
873
|
+
};
|
|
874
|
+
goalText: string | null;
|
|
875
|
+
goalDigest: string | null;
|
|
876
|
+
goalShape: {
|
|
877
|
+
characters: number;
|
|
878
|
+
terms: number;
|
|
879
|
+
};
|
|
880
|
+
filters: Record<string, unknown>;
|
|
881
|
+
fingerprints: RetrievalTraceFingerprints;
|
|
882
|
+
status: "open";
|
|
883
|
+
createdAtMs: number;
|
|
884
|
+
updatedAtMs: number;
|
|
885
|
+
expiresAtMs: number;
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
export type RetrievalTraceRow = Omit<
|
|
889
|
+
RetrievalTraceInput,
|
|
890
|
+
"status" | "updatedAtMs"
|
|
891
|
+
> & {
|
|
892
|
+
status: RetrievalTraceStatus;
|
|
893
|
+
updatedAtMs: number;
|
|
894
|
+
byteSize: number;
|
|
895
|
+
/** Digest of immutable creation fields; terminal status/time are excluded. */
|
|
896
|
+
creationDigest: string;
|
|
897
|
+
};
|
|
898
|
+
|
|
899
|
+
export interface RetrievalTraceRunInput {
|
|
900
|
+
runId: string;
|
|
901
|
+
traceId: string;
|
|
902
|
+
idempotencyKey: string;
|
|
903
|
+
kind: RetrievalTraceRunKind;
|
|
904
|
+
payload: Record<string, unknown>;
|
|
905
|
+
createdAtMs: number;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
export type RetrievalTraceRunRow = RetrievalTraceRunInput & {
|
|
909
|
+
payloadBytes: number;
|
|
910
|
+
canonicalDigest: string;
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
export interface RetrievalTraceEventInput {
|
|
914
|
+
eventId: string;
|
|
915
|
+
traceId: string;
|
|
916
|
+
runId: string | null;
|
|
917
|
+
idempotencyKey: string;
|
|
918
|
+
kind: RetrievalTraceEventKind;
|
|
919
|
+
payload: Record<string, unknown>;
|
|
920
|
+
createdAtMs: number;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
export type RetrievalTraceEventRow = RetrievalTraceEventInput & {
|
|
924
|
+
payloadBytes: number;
|
|
925
|
+
canonicalDigest: string;
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
export interface RetrievalTraceJudgmentInput {
|
|
929
|
+
judgmentId: string;
|
|
930
|
+
traceId: string;
|
|
931
|
+
runId: string | null;
|
|
932
|
+
idempotencyKey: string;
|
|
933
|
+
label: RetrievalTraceJudgmentLabel;
|
|
934
|
+
targetKind: RetrievalTraceJudgmentTargetKind;
|
|
935
|
+
targetRef: string;
|
|
936
|
+
target: Record<string, unknown>;
|
|
937
|
+
createdAtMs: number;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
export type RetrievalTraceJudgmentRow = RetrievalTraceJudgmentInput & {
|
|
941
|
+
targetBytes: number;
|
|
942
|
+
canonicalDigest: string;
|
|
943
|
+
};
|
|
944
|
+
|
|
945
|
+
export interface RetrievalTraceExportInput {
|
|
946
|
+
exportId: string;
|
|
947
|
+
traceId: string;
|
|
948
|
+
format: RetrievalTraceExportFormat;
|
|
949
|
+
artifactHash: string;
|
|
950
|
+
createdAtMs: number;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
export interface RetrievalTraceExportRow extends RetrievalTraceExportInput {}
|
|
954
|
+
|
|
955
|
+
export interface RetrievalTraceCursor {
|
|
956
|
+
createdAtMs: number;
|
|
957
|
+
traceId: string;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
export interface RetrievalTraceExportManifestInput {
|
|
961
|
+
exportId: string;
|
|
962
|
+
traceIds: string[];
|
|
963
|
+
format: RetrievalTraceExportFormat;
|
|
964
|
+
artifactHash: string;
|
|
965
|
+
createdAtMs: number;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
export interface RetrievalTraceExportManifestRow extends Omit<
|
|
969
|
+
RetrievalTraceExportManifestInput,
|
|
970
|
+
"traceIds"
|
|
971
|
+
> {
|
|
972
|
+
traceIds: string[];
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
export interface RetrievalTraceBundle {
|
|
976
|
+
trace: RetrievalTraceRow;
|
|
977
|
+
runs: RetrievalTraceRunRow[];
|
|
978
|
+
events: RetrievalTraceEventRow[];
|
|
979
|
+
judgments: RetrievalTraceJudgmentRow[];
|
|
980
|
+
exports: RetrievalTraceExportRow[];
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/** One aggregate export identity and every complete linked trace bundle. */
|
|
984
|
+
export interface RetrievalTraceExportBundle {
|
|
985
|
+
manifest: RetrievalTraceExportManifestRow;
|
|
986
|
+
traces: RetrievalTraceBundle[];
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
export interface RetrievalTraceBundleTotals {
|
|
990
|
+
runs: number;
|
|
991
|
+
events: number;
|
|
992
|
+
judgments: number;
|
|
993
|
+
exports: number;
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
export interface RetrievalTraceBoundedBundle {
|
|
997
|
+
bundle: RetrievalTraceBundle;
|
|
998
|
+
totals: RetrievalTraceBundleTotals;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
export interface RetrievalTraceRetentionPolicy {
|
|
1002
|
+
maxAgeDays: number;
|
|
1003
|
+
maxTraces: number;
|
|
1004
|
+
maxRecordsPerTrace: number;
|
|
1005
|
+
maxBytes: number;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
export interface RetrievalTraceDeleteCounts {
|
|
1009
|
+
traces: number;
|
|
1010
|
+
runs: number;
|
|
1011
|
+
events: number;
|
|
1012
|
+
judgments: number;
|
|
1013
|
+
exports: number;
|
|
1014
|
+
exportLinks: number;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
export interface RetrievalTraceRetentionResult {
|
|
1018
|
+
deleted: RetrievalTraceDeleteCounts;
|
|
1019
|
+
deletedTraceIds: string[];
|
|
1020
|
+
remainingTraces: number;
|
|
1021
|
+
remainingBytes: number;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
export type RetrievalTracePhysicalCleanupStatus =
|
|
1025
|
+
| "completed"
|
|
1026
|
+
| "wal_busy"
|
|
1027
|
+
| "failed";
|
|
1028
|
+
|
|
1029
|
+
export interface RetrievalTracePurgeResult extends RetrievalTraceDeleteCounts {
|
|
1030
|
+
physicalCleanup: RetrievalTracePhysicalCleanupStatus;
|
|
1031
|
+
checkpointedFrames: number;
|
|
1032
|
+
remainingWalFrames: number;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
819
1035
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
820
1036
|
// Transaction Types
|
|
821
1037
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -925,6 +1141,87 @@ export interface StorePort {
|
|
|
925
1141
|
receipt: ActivationVerificationReceipt
|
|
926
1142
|
): Promise<StoreResult<void>>;
|
|
927
1143
|
|
|
1144
|
+
/** Persist an already-redacted, versioned retrieval trace header. */
|
|
1145
|
+
createRetrievalTrace(
|
|
1146
|
+
trace: RetrievalTraceInput
|
|
1147
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1148
|
+
|
|
1149
|
+
/** Return a trace and all of its locally stored subordinate records. */
|
|
1150
|
+
getRetrievalTrace(
|
|
1151
|
+
traceId: string
|
|
1152
|
+
): Promise<StoreResult<RetrievalTraceBundle | null>>;
|
|
1153
|
+
|
|
1154
|
+
/** Read bounded subordinate detail while returning exact aggregate counts. */
|
|
1155
|
+
getBoundedRetrievalTrace(
|
|
1156
|
+
traceId: string,
|
|
1157
|
+
detailLimit: number
|
|
1158
|
+
): Promise<StoreResult<RetrievalTraceBoundedBundle | null>>;
|
|
1159
|
+
|
|
1160
|
+
/** List trace headers newest-first with a bounded caller-selected limit. */
|
|
1161
|
+
listRetrievalTraces(
|
|
1162
|
+
limit: number,
|
|
1163
|
+
cursor?: RetrievalTraceCursor
|
|
1164
|
+
): Promise<StoreResult<RetrievalTraceRow[]>>;
|
|
1165
|
+
|
|
1166
|
+
/** Transition an open trace to one explicit terminal outcome idempotently. */
|
|
1167
|
+
finalizeRetrievalTrace(
|
|
1168
|
+
traceId: string,
|
|
1169
|
+
status: RetrievalTraceTerminalStatus,
|
|
1170
|
+
updatedAtMs: number
|
|
1171
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1172
|
+
|
|
1173
|
+
/** Append a run once per trace-scoped idempotency key. */
|
|
1174
|
+
appendRetrievalTraceRun(
|
|
1175
|
+
run: RetrievalTraceRunInput
|
|
1176
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1177
|
+
|
|
1178
|
+
/** Append an event once per trace-scoped idempotency key. */
|
|
1179
|
+
appendRetrievalTraceEvent(
|
|
1180
|
+
event: RetrievalTraceEventInput
|
|
1181
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1182
|
+
|
|
1183
|
+
/** Append an explicit judgment once per trace-scoped idempotency key. */
|
|
1184
|
+
appendRetrievalTraceJudgment(
|
|
1185
|
+
judgment: RetrievalTraceJudgmentInput
|
|
1186
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1187
|
+
|
|
1188
|
+
/** Record a locally produced explicit export receipt idempotently. */
|
|
1189
|
+
appendRetrievalTraceExport(
|
|
1190
|
+
traceExport: RetrievalTraceExportInput
|
|
1191
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1192
|
+
|
|
1193
|
+
/** Record one export manifest and all sorted trace memberships atomically. */
|
|
1194
|
+
appendRetrievalTraceExportManifest(
|
|
1195
|
+
manifest: RetrievalTraceExportManifestInput
|
|
1196
|
+
): Promise<StoreResult<RetrievalTraceAppendResult>>;
|
|
1197
|
+
|
|
1198
|
+
/** Read one aggregate export manifest with stable sorted membership. */
|
|
1199
|
+
getRetrievalTraceExportManifest(
|
|
1200
|
+
exportId: string
|
|
1201
|
+
): Promise<StoreResult<RetrievalTraceExportManifestRow | null>>;
|
|
1202
|
+
|
|
1203
|
+
/** Read one export and all linked traces without bounded-detail truncation. */
|
|
1204
|
+
getRetrievalTraceExportBundle(
|
|
1205
|
+
exportId: string
|
|
1206
|
+
): Promise<StoreResult<RetrievalTraceExportBundle | null>>;
|
|
1207
|
+
|
|
1208
|
+
/** Durable random index-local secret used only to redact metadata labels. */
|
|
1209
|
+
getOrCreateRetrievalTraceRedactionSecret(): Promise<StoreResult<string>>;
|
|
1210
|
+
|
|
1211
|
+
/** Delete one trace and report exact cascade counts. */
|
|
1212
|
+
deleteRetrievalTrace(
|
|
1213
|
+
traceId: string
|
|
1214
|
+
): Promise<StoreResult<RetrievalTraceDeleteCounts>>;
|
|
1215
|
+
|
|
1216
|
+
/** Delete every trace and subordinate record in one transaction. */
|
|
1217
|
+
purgeRetrievalTraces(): Promise<StoreResult<RetrievalTracePurgeResult>>;
|
|
1218
|
+
|
|
1219
|
+
/** Apply deterministic time, row, and byte retention limits. */
|
|
1220
|
+
enforceRetrievalTraceRetention(
|
|
1221
|
+
policy: RetrievalTraceRetentionPolicy,
|
|
1222
|
+
nowMs: number
|
|
1223
|
+
): Promise<StoreResult<RetrievalTraceRetentionResult>>;
|
|
1224
|
+
|
|
928
1225
|
// ─────────────────────────────────────────────────────────────────────────
|
|
929
1226
|
// Documents
|
|
930
1227
|
// ─────────────────────────────────────────────────────────────────────────
|
|
@@ -74,6 +74,16 @@ function formatUnavailableMessage(loadError?: string): string {
|
|
|
74
74
|
return `Vector search requires sqlite-vec. Embeddings are stored, but KNN search is disabled.${reason} ${SQLITE_VEC_GUIDANCE}`;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
const ALLOWED_HASH_BATCH_SIZE = 800;
|
|
78
|
+
|
|
79
|
+
const compareVectorResults = (
|
|
80
|
+
left: VectorSearchResult,
|
|
81
|
+
right: VectorSearchResult
|
|
82
|
+
): number =>
|
|
83
|
+
left.distance - right.distance ||
|
|
84
|
+
left.mirrorHash.localeCompare(right.mirrorHash) ||
|
|
85
|
+
left.seq - right.seq;
|
|
86
|
+
|
|
77
87
|
/**
|
|
78
88
|
* Create a VectorIndexPort for a specific model.
|
|
79
89
|
* sqlite-vec is optional - storage works without it, search disabled.
|
|
@@ -243,15 +253,80 @@ export async function createVectorIndexPort(
|
|
|
243
253
|
searchNearest(
|
|
244
254
|
embedding: Float32Array,
|
|
245
255
|
k: number,
|
|
246
|
-
searchOptions?: {
|
|
256
|
+
searchOptions?: {
|
|
257
|
+
minScore?: number;
|
|
258
|
+
allowedMirrorHashes?: string[];
|
|
259
|
+
}
|
|
247
260
|
): Promise<StoreResult<VectorSearchResult[]>> {
|
|
248
261
|
if (!(searchAvailable && searchStmt)) {
|
|
249
262
|
return Promise.resolve(
|
|
250
263
|
err("VEC_SEARCH_UNAVAILABLE", formatUnavailableMessage(loadError))
|
|
251
264
|
);
|
|
252
265
|
}
|
|
266
|
+
if (!Number.isSafeInteger(k) || k < 1) {
|
|
267
|
+
return Promise.resolve(
|
|
268
|
+
err("INVALID_INPUT", "Vector search limit must be a positive integer")
|
|
269
|
+
);
|
|
270
|
+
}
|
|
253
271
|
|
|
254
272
|
try {
|
|
273
|
+
const allowed = searchOptions?.allowedMirrorHashes;
|
|
274
|
+
if (allowed) {
|
|
275
|
+
const hashes = [
|
|
276
|
+
...new Set(allowed.filter((hash) => hash.length > 0)),
|
|
277
|
+
].sort();
|
|
278
|
+
if (hashes.length === 0) return Promise.resolve(ok([]));
|
|
279
|
+
const distanceFunction =
|
|
280
|
+
distanceMetric === "cosine"
|
|
281
|
+
? "vec_distance_cosine"
|
|
282
|
+
: "vec_distance_L2";
|
|
283
|
+
const scoped: VectorSearchResult[] = [];
|
|
284
|
+
for (
|
|
285
|
+
let index = 0;
|
|
286
|
+
index < hashes.length;
|
|
287
|
+
index += ALLOWED_HASH_BATCH_SIZE
|
|
288
|
+
) {
|
|
289
|
+
const batch = hashes.slice(index, index + ALLOWED_HASH_BATCH_SIZE);
|
|
290
|
+
const placeholders = batch.map(() => "?").join(",");
|
|
291
|
+
const rows = db
|
|
292
|
+
.query<
|
|
293
|
+
{
|
|
294
|
+
mirror_hash: string;
|
|
295
|
+
seq: number;
|
|
296
|
+
distance: number;
|
|
297
|
+
},
|
|
298
|
+
(Uint8Array | string | number)[]
|
|
299
|
+
>(
|
|
300
|
+
`SELECT mirror_hash, seq,
|
|
301
|
+
${distanceFunction}(embedding, ?) AS distance
|
|
302
|
+
FROM content_vectors
|
|
303
|
+
WHERE model = ?
|
|
304
|
+
AND mirror_hash IN (${placeholders})
|
|
305
|
+
ORDER BY distance, mirror_hash, seq
|
|
306
|
+
LIMIT ?`
|
|
307
|
+
)
|
|
308
|
+
.all(encodeEmbedding(embedding), model, ...batch, k);
|
|
309
|
+
scoped.push(
|
|
310
|
+
...rows.map((row) => ({
|
|
311
|
+
mirrorHash: row.mirror_hash,
|
|
312
|
+
seq: row.seq,
|
|
313
|
+
distance: row.distance,
|
|
314
|
+
}))
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
const minScore = searchOptions.minScore;
|
|
318
|
+
return Promise.resolve(
|
|
319
|
+
ok(
|
|
320
|
+
scoped
|
|
321
|
+
.sort(compareVectorResults)
|
|
322
|
+
.filter(
|
|
323
|
+
(row) =>
|
|
324
|
+
minScore === undefined || 1 - row.distance >= minScore
|
|
325
|
+
)
|
|
326
|
+
.slice(0, k)
|
|
327
|
+
)
|
|
328
|
+
);
|
|
329
|
+
}
|
|
255
330
|
const results = searchStmt.all(encodeEmbedding(embedding), k) as {
|
|
256
331
|
chunk_id: string;
|
|
257
332
|
distance: number;
|
|
@@ -84,7 +84,7 @@ export interface VectorIndexPort {
|
|
|
84
84
|
searchNearest(
|
|
85
85
|
embedding: Float32Array,
|
|
86
86
|
k: number,
|
|
87
|
-
options?: { minScore?: number }
|
|
87
|
+
options?: { minScore?: number; allowedMirrorHashes?: string[] }
|
|
88
88
|
): Promise<StoreResult<VectorSearchResult[]>>;
|
|
89
89
|
|
|
90
90
|
// ─────────────────────────────────────────────────────────────────────────
|