claude-memory-layer 1.0.26 → 1.0.28
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/.env.example +7 -0
- package/AGENTS.md +11 -0
- package/README.md +184 -41
- package/benchmarks/replay/anonymized-real-sessions.json +48 -0
- package/dist/cli/index.js +10097 -6003
- package/dist/cli/index.js.map +4 -4
- package/dist/core/index.js +9745 -5587
- package/dist/core/index.js.map +4 -4
- package/dist/hooks/post-tool-use.js +6545 -5270
- package/dist/hooks/post-tool-use.js.map +4 -4
- package/dist/hooks/semantic-daemon.js +6646 -5354
- package/dist/hooks/semantic-daemon.js.map +4 -4
- package/dist/hooks/session-end.js +6618 -5347
- package/dist/hooks/session-end.js.map +4 -4
- package/dist/hooks/session-start.js +6619 -5354
- package/dist/hooks/session-start.js.map +4 -4
- package/dist/hooks/stop.js +6614 -5325
- package/dist/hooks/stop.js.map +4 -4
- package/dist/hooks/user-prompt-submit.js +6702 -5356
- package/dist/hooks/user-prompt-submit.js.map +4 -4
- package/dist/index.js +13537 -0
- package/dist/index.js.map +7 -0
- package/dist/mcp/index.js +20770 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/server/api/index.js +6632 -5319
- package/dist/server/api/index.js.map +4 -4
- package/dist/server/index.js +6667 -5340
- package/dist/server/index.js.map +4 -4
- package/dist/services/memory-service.js +6568 -5350
- package/dist/services/memory-service.js.map +4 -4
- package/dist/ui/assets/js/bootstrap.js +244 -0
- package/dist/ui/assets/js/chat.js +373 -0
- package/dist/ui/assets/js/disclosure.js +232 -0
- package/dist/ui/assets/js/modals.js +298 -0
- package/dist/ui/assets/js/overview.js +655 -0
- package/dist/ui/assets/js/state.js +72 -0
- package/dist/ui/assets/js/views.js +468 -0
- package/dist/ui/index.html +43 -1
- package/dist/ui/index.ts +3 -0
- package/dist/ui/style.css +222 -0
- package/docs/ARCHITECTURE_COMPARISON_AND_RECOMMENDATIONS.md +627 -0
- package/docs/HERMES_MEMORY_INGESTION_ANALYSIS.md +440 -0
- package/docs/MEMORY_USEFULNESS_AUDIT.md +371 -0
- package/docs/MEMORY_USEFULNESS_AUDIT_RAW.json +80 -0
- package/docs/MEMSEARCH_PROJECT_STRUCTURE_ANALYSIS.md +333 -0
- package/docs/PRODUCT_VALIDATION_MATRIX.md +82 -0
- package/docs/PROJECT_STRUCTURE_ANALYSIS.md +421 -0
- package/docs/REFACTORING_MILESTONES_AND_ISSUES.md +501 -0
- package/docs/REFACTORING_PLAN_THIN_CORE.md +414 -0
- package/docs/REFERENCE_PROJECT_ANALYSES.md +25 -0
- package/docs/SUPERLOCALMEMORY_PROJECT_STRUCTURE_ANALYSIS.md +452 -0
- package/docs/TARGET_ARCHITECTURE_AND_FOLDER_STRUCTURE.md +446 -0
- package/docs/architecture/comparison-index.md +47 -0
- package/docs/reports/codex-real-data-validation-20260505T040447Z.md +46 -0
- package/package.json +9 -5
- package/scripts/build.ts +25 -8
- package/scripts/generate-session-qrels.ts +126 -0
- package/scripts/replay-retrieval-benchmark.ts +69 -0
- package/specs/thin-core-refactor/context.md +275 -0
- package/specs/thin-core-refactor/plan.md +536 -0
- package/specs/thin-core-refactor/spec.md +465 -0
- package/src/adapters/claude/capture/index.ts +3 -0
- package/src/adapters/claude/context/index.ts +3 -0
- package/src/adapters/claude/hooks/index.ts +21 -0
- package/src/adapters/claude/hooks/post-tool-use.ts +239 -0
- package/src/adapters/claude/hooks/prompt-injection-policy.ts +104 -0
- package/src/adapters/claude/hooks/semantic-daemon-client.ts +209 -0
- package/src/adapters/claude/hooks/semantic-daemon.ts +283 -0
- package/src/adapters/claude/hooks/session-end.ts +59 -0
- package/src/adapters/claude/hooks/session-start.ts +73 -0
- package/src/adapters/claude/hooks/stop.ts +128 -0
- package/src/adapters/claude/hooks/user-prompt-submit.ts +361 -0
- package/src/adapters/claude/index.ts +4 -0
- package/src/adapters/claude/transcript/index.ts +4 -0
- package/src/adapters/claude/transcript/transcript-reader.ts +57 -0
- package/src/adapters/claude/transcript/turn-reconstructor.ts +65 -0
- package/src/apps/cli/claude-settings-hooks.ts +138 -0
- package/src/apps/cli/codex-import-runner.ts +125 -0
- package/src/apps/cli/codex-validation-output.ts +95 -0
- package/src/apps/cli/hermes-import-runner.ts +130 -0
- package/src/apps/cli/hermes-validation-output.ts +91 -0
- package/src/apps/cli/index.ts +1731 -0
- package/src/apps/cli/mcp-install.ts +106 -0
- package/src/apps/cli/retrieval-disclosure-output.ts +196 -0
- package/src/apps/dashboard/assets/js/bootstrap.js +244 -0
- package/src/apps/dashboard/assets/js/chat.js +373 -0
- package/src/apps/dashboard/assets/js/disclosure.js +232 -0
- package/src/apps/dashboard/assets/js/modals.js +298 -0
- package/src/apps/dashboard/assets/js/overview.js +655 -0
- package/src/apps/dashboard/assets/js/state.js +72 -0
- package/src/apps/dashboard/assets/js/views.js +468 -0
- package/src/{ui → apps/dashboard}/index.html +43 -1
- package/src/apps/dashboard/index.ts +3 -0
- package/src/{ui → apps/dashboard}/style.css +222 -0
- package/src/apps/index.ts +5 -0
- package/src/apps/server/api/chat.ts +244 -0
- package/src/apps/server/api/citations.ts +105 -0
- package/src/apps/server/api/events.ts +137 -0
- package/src/apps/server/api/health.ts +53 -0
- package/src/apps/server/api/index.ts +26 -0
- package/src/apps/server/api/projects.ts +74 -0
- package/src/apps/server/api/search.ts +184 -0
- package/src/apps/server/api/sessions.ts +115 -0
- package/src/apps/server/api/stats.ts +723 -0
- package/src/apps/server/api/turns.ts +143 -0
- package/src/apps/server/api/utils.ts +65 -0
- package/src/apps/server/index.ts +111 -0
- package/src/cli/index.ts +2 -1311
- package/src/cli/retrieval-disclosure-output.ts +2 -0
- package/src/compat/index.ts +5 -0
- package/src/core/derive/fact-deriver.ts +170 -0
- package/src/core/derive/index.ts +2 -0
- package/src/core/derive/summary-deriver.ts +76 -0
- package/src/core/embedder.ts +4 -152
- package/src/core/engine/embedding-maintenance-service.ts +187 -0
- package/src/core/engine/endless-memory-services.ts +4 -0
- package/src/core/engine/index.ts +19 -0
- package/src/core/engine/memory-engine-services.ts +170 -0
- package/src/core/engine/memory-ingest-service.ts +317 -0
- package/src/core/engine/memory-query-service.ts +173 -0
- package/src/core/engine/memory-runtime-service.ts +162 -0
- package/src/core/engine/memory-service-composition.ts +231 -0
- package/src/core/engine/retrieval-analytics-service.ts +181 -0
- package/src/core/engine/retrieval-disclosure-service.ts +420 -0
- package/src/core/engine/retrieval-orchestrator.ts +377 -0
- package/src/core/engine/retrieval-services.ts +176 -0
- package/src/core/engine/shared-memory-services.ts +4 -0
- package/src/core/entity-repo.ts +1 -3
- package/src/core/event-store.ts +3 -3
- package/src/core/evidence-aligner.ts +2 -2
- package/src/core/external-market-context.ts +582 -0
- package/src/core/graduation.ts +2 -3
- package/src/core/index.ts +21 -0
- package/src/core/matcher.ts +2 -4
- package/src/core/model/memory-fact.ts +30 -0
- package/src/core/model/memory-rule.ts +14 -0
- package/src/core/model/memory-summary.ts +21 -0
- package/src/core/model/raw-event.ts +28 -0
- package/src/core/model/retrieval-result.ts +35 -0
- package/src/core/privacy/filter.ts +21 -10
- package/src/core/product-validation-matrix.ts +314 -0
- package/src/core/progressive-retriever.ts +1 -2
- package/src/core/registry/project-path.ts +54 -0
- package/src/core/registry/session-registry.ts +69 -0
- package/src/core/replay-evaluator.ts +625 -0
- package/src/core/retrieval-benchmark.ts +117 -0
- package/src/core/retrieval-quality.ts +109 -0
- package/src/core/retriever.ts +53 -15
- package/src/core/session-qrels.ts +360 -0
- package/src/core/shared-event-store.ts +1 -1
- package/src/core/sqlite-event-store.ts +35 -11
- package/src/core/task/blocker-resolver.ts +2 -2
- package/src/core/task/task-resolver.ts +0 -1
- package/src/core/vector-outbox.ts +1 -10
- package/src/core/vector-worker.ts +1 -1
- package/src/extensions/endless-memory/endless-memory-services.ts +350 -0
- package/src/extensions/endless-memory/index.ts +1 -0
- package/src/extensions/index.ts +5 -0
- package/src/extensions/mcp/handlers.ts +960 -0
- package/src/extensions/mcp/index.ts +48 -0
- package/src/extensions/mcp/tools.ts +252 -0
- package/src/extensions/shared-memory/index.ts +1 -0
- package/src/extensions/shared-memory/shared-memory-services.ts +211 -0
- package/src/extensions/vector/embedder.ts +197 -0
- package/src/extensions/vector/index.ts +1 -0
- package/src/hooks/post-tool-use.ts +3 -236
- package/src/hooks/semantic-daemon-client.ts +1 -208
- package/src/hooks/semantic-daemon.ts +6 -271
- package/src/hooks/session-end.ts +4 -79
- package/src/hooks/session-start.ts +4 -73
- package/src/hooks/stop.ts +3 -173
- package/src/hooks/user-prompt-submit.ts +3 -338
- package/src/index.ts +13 -0
- package/src/mcp/handlers.ts +2 -212
- package/src/mcp/index.ts +3 -46
- package/src/mcp/tools.ts +2 -78
- package/src/server/api/chat.ts +2 -244
- package/src/server/api/citations.ts +2 -105
- package/src/server/api/events.ts +2 -137
- package/src/server/api/health.ts +2 -53
- package/src/server/api/index.ts +2 -26
- package/src/server/api/projects.ts +2 -74
- package/src/server/api/search.ts +2 -102
- package/src/server/api/sessions.ts +2 -115
- package/src/server/api/stats.ts +2 -724
- package/src/server/api/turns.ts +2 -143
- package/src/server/api/utils.ts +2 -46
- package/src/server/index.ts +2 -100
- package/src/services/bootstrap-organizer.ts +46 -26
- package/src/services/codex-session-history-importer.ts +521 -29
- package/src/services/hermes-session-history-importer.ts +733 -0
- package/src/services/memory-service-config.ts +36 -0
- package/src/services/memory-service-registry.ts +150 -0
- package/src/services/memory-service.ts +211 -1325
- package/src/services/session-history-importer.ts +58 -14
- package/tests/README.md +23 -0
- package/tests/adapters/claude/claude-semantic-daemon-adapter.test.ts +54 -0
- package/tests/adapters/claude/claude-transcript-reconstructor.test.ts +98 -0
- package/tests/adapters/claude-hook-prompt-injection-policy.test.ts +99 -0
- package/tests/apps/app-layer-boundary.test.ts +48 -0
- package/tests/apps/claude-settings-hooks.test.ts +107 -0
- package/tests/apps/cli-disclosure-output.test.ts +212 -0
- package/tests/apps/codex-import-runner.test.ts +99 -0
- package/tests/apps/codex-validation-output.test.ts +100 -0
- package/tests/apps/hermes-import-runner.test.ts +99 -0
- package/tests/apps/mcp-install-command.test.ts +59 -0
- package/tests/apps/package-build-entrypoints.test.ts +30 -0
- package/tests/apps/search-api-disclosure.test.ts +162 -0
- package/tests/apps/stats-api-lightweight.test.ts +67 -0
- package/tests/apps/ui-disclosure-output.test.ts +140 -0
- package/tests/{bootstrap-organizer.test.ts → core/bootstrap-organizer.test.ts} +1 -1
- package/tests/{canonical-key.test.ts → core/canonical-key.test.ts} +1 -1
- package/tests/core/codex-session-history-importer-validation.test.ts +185 -0
- package/tests/{consolidation-worker.test.ts → core/consolidation-worker.test.ts} +2 -2
- package/tests/core/embedding-maintenance-service.test.ts +282 -0
- package/tests/{evidence-aligner.test.ts → core/evidence-aligner.test.ts} +1 -1
- package/tests/core/external-market-context.test.ts +209 -0
- package/tests/core/fact-deriver.test.ts +79 -0
- package/tests/core/hermes-session-history-importer-validation.test.ts +609 -0
- package/tests/{ingest-interceptor.test.ts → core/ingest-interceptor.test.ts} +1 -1
- package/tests/{markdown-mirror.test.ts → core/markdown-mirror.test.ts} +2 -2
- package/tests/{matcher.test.ts → core/matcher.test.ts} +1 -1
- package/tests/{md-mirror.test.ts → core/md-mirror.test.ts} +2 -2
- package/tests/core/memory-engine-services.test.ts +240 -0
- package/tests/core/memory-ingest-service.test.ts +296 -0
- package/tests/core/memory-query-service.test.ts +129 -0
- package/tests/core/memory-runtime-service.test.ts +201 -0
- package/tests/core/memory-service-composition.test.ts +192 -0
- package/tests/core/memory-service-config.test.ts +41 -0
- package/tests/core/memory-service-facade.test.ts +30 -0
- package/tests/core/memory-service-registry.test.ts +206 -0
- package/tests/core/product-validation-matrix.test.ts +61 -0
- package/tests/core/project-registry.test.ts +78 -0
- package/tests/core/replay-evaluator.test.ts +181 -0
- package/tests/core/retrieval-analytics-service.test.ts +210 -0
- package/tests/core/retrieval-benchmark.test.ts +93 -0
- package/tests/core/retrieval-disclosure-service.test.ts +264 -0
- package/tests/core/retrieval-orchestrator.test.ts +403 -0
- package/tests/core/retrieval-quality.test.ts +31 -0
- package/tests/core/retrieval-services.test.ts +185 -0
- package/tests/{retriever-fallback-chain.test.ts → core/retriever-fallback-chain.test.ts} +3 -3
- package/tests/{retriever-strategy-scope.test.ts → core/retriever-strategy-scope.test.ts} +70 -3
- package/tests/{retriever.memu-adoption.test.ts → core/retriever.memu-adoption.test.ts} +3 -3
- package/tests/core/session-history-importer-filter.test.ts +78 -0
- package/tests/core/session-qrels.test.ts +250 -0
- package/tests/{sqlite-event-store-replication.test.ts → core/sqlite-event-store-replication.test.ts} +36 -1
- package/tests/core/summary-deriver.test.ts +66 -0
- package/tests/extensions/embedder-warning-suppression.test.ts +53 -0
- package/tests/extensions/endless-memory-extension-boundary.test.ts +17 -0
- package/tests/extensions/endless-memory-services.test.ts +325 -0
- package/tests/extensions/mcp-context-tools.test.ts +905 -0
- package/tests/extensions/mcp-extension-boundary.test.ts +21 -0
- package/tests/extensions/mcp-package-build.test.ts +22 -0
- package/tests/extensions/mcp-project-aware-tools.test.ts +102 -0
- package/tests/extensions/shared-memory-extension-boundary.test.ts +24 -0
- package/tests/extensions/shared-memory-services.test.ts +309 -0
- package/tests/extensions/vector-extension-boundary.test.ts +21 -0
- package/.claude/settings.local.json +0 -25
- package/.npm-cache/_cacache/content-v2/sha512/04/76/c098f88dfe584a2b80870bff7421b05d17d3d9ee1027f77772332a22d3f93a9a57101a2855107f6ad82077a818bba912b2bc317f2361b5ddb09ad284d9ce +0 -0
- package/.npm-cache/_cacache/content-v2/sha512/60/25/d2ecd39cfc7cab58351162814be77f935c6d6491c10c3745d456da7ddb2117ffd90c10e53fe3c0f1ed16b403307841543634504398b16ee4e6b6dd8e0c45 +0 -0
- package/.npm-cache/_cacache/index-v5/2b/9a/7f8f40206ed8a2e0a84efaa953ccaed1f5d001e14b931083f2e7a0738007 +0 -2
- package/.npm-cache/_cacache/index-v5/2e/d9/fcfa5c6a6abdc2a3644ab84a95936047298c465a2f47ee03db8f7fe1e946 +0 -3
- package/.npm-cache/_cacache/index-v5/a9/42/e519633356d12d3d2f19da66a8301016d496c8f5c3e0554124aaa62dc043 +0 -2
- package/.npm-cache/_logs/2026-02-26T12_04_52_729Z-debug-0.log +0 -256
- package/.npm-cache/_logs/2026-02-26T12_05_36_835Z-debug-0.log +0 -18
- package/.npm-cache/_logs/2026-02-26T12_05_45_982Z-debug-0.log +0 -32
- package/.npm-cache/_logs/2026-02-26T12_05_48_515Z-debug-0.log +0 -260
- package/.npm-cache/_logs/2026-02-26T12_05_53_567Z-debug-0.log +0 -69
- package/.npm-cache/_update-notifier-last-checked +0 -0
- package/bootstrap-kb/decisions/decisions.md +0 -244
- package/bootstrap-kb/glossary/glossary.md +0 -46
- package/bootstrap-kb/modules/.claude-plugin.md +0 -22
- package/bootstrap-kb/modules/agents.md.md +0 -15
- package/bootstrap-kb/modules/claude.md.md +0 -15
- package/bootstrap-kb/modules/context.md.md +0 -15
- package/bootstrap-kb/modules/docs.md +0 -18
- package/bootstrap-kb/modules/handoff.md.md +0 -15
- package/bootstrap-kb/modules/package-lock.json.md +0 -15
- package/bootstrap-kb/modules/package.json.md +0 -15
- package/bootstrap-kb/modules/plan.md.md +0 -15
- package/bootstrap-kb/modules/readme.md.md +0 -15
- package/bootstrap-kb/modules/scripts.md +0 -26
- package/bootstrap-kb/modules/spec.md.md +0 -15
- package/bootstrap-kb/modules/specs.md +0 -20
- package/bootstrap-kb/modules/src.md +0 -51
- package/bootstrap-kb/modules/tests.md +0 -42
- package/bootstrap-kb/modules/tsconfig.json.md +0 -15
- package/bootstrap-kb/modules/vitest.config.ts.md +0 -15
- package/bootstrap-kb/overview/overview.md +0 -40
- package/bootstrap-kb/sources/manifest.json +0 -950
- package/bootstrap-kb/sources/manifest.md +0 -227
- package/bootstrap-kb/timeline/timeline.md +0 -57
- package/claude-memory-layer-1.0.14.tgz +0 -0
- package/d.sh +0 -3
- package/deploy.sh +0 -3
- package/dist/ui/app.js +0 -2101
- package/memory/.claude-plugin/commands/2026-02-25.md +0 -263
- package/memory/_index.md +0 -418
- package/memory/agent_response/uncategorized/2026-02-26.md +0 -176
- package/memory/agent_response/uncategorized/2026-03-03.md +0 -14
- package/memory/agent_response/uncategorized/2026-03-04.md +0 -1421
- package/memory/agent_response/uncategorized/2026-03-05.md +0 -48
- package/memory/default/uncategorized/2026-02-25.md +0 -4839
- package/memory/session_summary/uncategorized/2026-02-26.md +0 -13
- package/memory/session_summary/uncategorized/2026-03-03.md +0 -5
- package/memory/session_summary/uncategorized/2026-03-04.md +0 -50
- package/memory/specs/20260207-dashboard-upgrade/2026-02-25.md +0 -142
- package/memory/specs/citations-system/2026-02-25.md +0 -1121
- package/memory/specs/endless-mode/2026-02-25.md +0 -1392
- package/memory/specs/entity-edge-model/2026-02-25.md +0 -1263
- package/memory/specs/evidence-aligner-v2/2026-02-25.md +0 -1028
- package/memory/specs/mcp-desktop-integration/2026-02-25.md +0 -1334
- package/memory/specs/post-tool-use-hook/2026-02-25.md +0 -1164
- package/memory/specs/private-tags/2026-02-25.md +0 -1057
- package/memory/specs/progressive-disclosure/2026-02-25.md +0 -1436
- package/memory/specs/task-entity-system/2026-02-25.md +0 -924
- package/memory/specs/vector-outbox-v2/2026-02-25.md +0 -1510
- package/memory/specs/web-viewer-ui/2026-02-25.md +0 -1709
- package/memory/tool_observation/uncategorized/2026-02-26.md +0 -209
- package/memory/tool_observation/uncategorized/2026-03-03.md +0 -21
- package/memory/tool_observation/uncategorized/2026-03-04.md +0 -1033
- package/memory/tool_observation/uncategorized/2026-03-05.md +0 -29
- package/memory/user_prompt/uncategorized/2026-02-26.md +0 -25
- package/memory/user_prompt/uncategorized/2026-03-04.md +0 -634
- package/specs/optional-duckdb/context.md +0 -77
- package/specs/optional-duckdb/plan.md +0 -142
- package/specs/optional-duckdb/spec.md +0 -35
- package/src/ui/app.js +0 -2101
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
|
|
4
|
+
export interface SessionQrelsMemory {
|
|
5
|
+
id: string;
|
|
6
|
+
content: string;
|
|
7
|
+
sourceSessionId: string;
|
|
8
|
+
sourceTurnIndex: number;
|
|
9
|
+
timestamp?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type SessionQrelsExpectation = 'match' | 'no_match';
|
|
13
|
+
|
|
14
|
+
export interface SessionQrelsQuery {
|
|
15
|
+
queryId: string;
|
|
16
|
+
query: string;
|
|
17
|
+
expectedIds: string[];
|
|
18
|
+
expectedRelevance: Record<string, number>;
|
|
19
|
+
sourceSessionId: string;
|
|
20
|
+
sourceTurnIndex: number;
|
|
21
|
+
expectation?: SessionQrelsExpectation;
|
|
22
|
+
forbiddenIds?: string[];
|
|
23
|
+
knownAnswer?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface SessionQrelsFixtureMetadata {
|
|
27
|
+
sourceFileCount?: number;
|
|
28
|
+
rawContentIncluded: boolean;
|
|
29
|
+
generatedAt?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface SessionQrelsFixture {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
ks: number[];
|
|
36
|
+
queries: SessionQrelsQuery[];
|
|
37
|
+
memories: SessionQrelsMemory[];
|
|
38
|
+
metadata?: SessionQrelsFixtureMetadata;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SessionQrelsNoMatchQueryInput {
|
|
42
|
+
queryId?: string;
|
|
43
|
+
query: string;
|
|
44
|
+
forbiddenIds?: string[];
|
|
45
|
+
sourceSessionId?: string;
|
|
46
|
+
sourceTurnIndex?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface SessionQrelsOptions {
|
|
50
|
+
name?: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
ks?: number[];
|
|
53
|
+
maxQueries?: number;
|
|
54
|
+
redactContent?: boolean;
|
|
55
|
+
sourceFileCount?: number;
|
|
56
|
+
rawContentIncluded?: boolean;
|
|
57
|
+
generatedAt?: string;
|
|
58
|
+
noMatchQueries?: SessionQrelsNoMatchQueryInput[];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface SessionQrelsFileCollectionOptions {
|
|
62
|
+
includeSubagents?: boolean;
|
|
63
|
+
maxFiles?: number;
|
|
64
|
+
minBytes?: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface SessionQrelsPerSessionSummary {
|
|
68
|
+
sourceSessionId: string;
|
|
69
|
+
queryCount: number;
|
|
70
|
+
memoryCount: number;
|
|
71
|
+
firstTurnIndex: number;
|
|
72
|
+
lastTurnIndex: number;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface SessionQrelsSummary {
|
|
76
|
+
name: string;
|
|
77
|
+
description: string;
|
|
78
|
+
ks: number[];
|
|
79
|
+
queryCount: number;
|
|
80
|
+
positiveQueryCount: number;
|
|
81
|
+
noMatchQueryCount: number;
|
|
82
|
+
knownAnswerCount: number;
|
|
83
|
+
memoryCount: number;
|
|
84
|
+
sourceSessionCount: number;
|
|
85
|
+
sourceFileCount?: number;
|
|
86
|
+
rawContentIncluded: boolean;
|
|
87
|
+
perSession: SessionQrelsPerSessionSummary[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface ClaudeContentBlock {
|
|
91
|
+
type: string;
|
|
92
|
+
text?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
type ClaudeMessageContent = string | ClaudeContentBlock[];
|
|
96
|
+
|
|
97
|
+
interface ClaudeJsonlEntry {
|
|
98
|
+
type?: string;
|
|
99
|
+
sessionId?: string;
|
|
100
|
+
timestamp?: string;
|
|
101
|
+
message?: {
|
|
102
|
+
role?: string;
|
|
103
|
+
content?: ClaudeMessageContent;
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
interface PendingPrompt {
|
|
108
|
+
sessionId: string;
|
|
109
|
+
text: string;
|
|
110
|
+
turnIndex: number;
|
|
111
|
+
timestamp?: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function buildSessionQrelsFixtureFromJsonl(
|
|
115
|
+
jsonl: string | string[],
|
|
116
|
+
options: SessionQrelsOptions = {}
|
|
117
|
+
): SessionQrelsFixture {
|
|
118
|
+
const lines = Array.isArray(jsonl) ? jsonl : jsonl.split(/\r?\n/);
|
|
119
|
+
const queries: SessionQrelsQuery[] = [];
|
|
120
|
+
const memories: SessionQrelsMemory[] = [];
|
|
121
|
+
const sessionCounters = new Map<string, number>();
|
|
122
|
+
const pendingBySession = new Map<string, PendingPrompt>();
|
|
123
|
+
|
|
124
|
+
for (const line of lines) {
|
|
125
|
+
if (options.maxQueries !== undefined && queries.length >= options.maxQueries) break;
|
|
126
|
+
const entry = parseEntry(line);
|
|
127
|
+
if (!entry) continue;
|
|
128
|
+
|
|
129
|
+
const sessionId = entry.sessionId || 'unknown-session';
|
|
130
|
+
const content = extractTextContent(entry.message?.content);
|
|
131
|
+
if (!content) continue;
|
|
132
|
+
|
|
133
|
+
if (entry.type === 'user') {
|
|
134
|
+
if (isWorthBenchmarkingPrompt(content)) {
|
|
135
|
+
const turnIndex = nextSessionCounter(sessionCounters, sessionId);
|
|
136
|
+
pendingBySession.set(sessionId, { sessionId, text: content, turnIndex, timestamp: entry.timestamp });
|
|
137
|
+
} else {
|
|
138
|
+
pendingBySession.delete(sessionId);
|
|
139
|
+
}
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (entry.type === 'assistant') {
|
|
144
|
+
const pending = pendingBySession.get(sessionId);
|
|
145
|
+
if (!pending) continue;
|
|
146
|
+
|
|
147
|
+
const answer = content.trim();
|
|
148
|
+
if (answer.length === 0) continue;
|
|
149
|
+
const idSuffix = `${pending.sessionId}-${pending.turnIndex}`;
|
|
150
|
+
const memoryId = `m-${idSuffix}`;
|
|
151
|
+
const queryId = `q-${idSuffix}`;
|
|
152
|
+
const memoryContent = options.redactContent ? `[redacted memory ${memoryId}]` : answer;
|
|
153
|
+
memories.push({
|
|
154
|
+
id: memoryId,
|
|
155
|
+
content: memoryContent,
|
|
156
|
+
sourceSessionId: pending.sessionId,
|
|
157
|
+
sourceTurnIndex: pending.turnIndex,
|
|
158
|
+
timestamp: entry.timestamp ?? pending.timestamp
|
|
159
|
+
});
|
|
160
|
+
queries.push({
|
|
161
|
+
queryId,
|
|
162
|
+
query: options.redactContent ? `[redacted query ${queryId}]` : pending.text,
|
|
163
|
+
expectedIds: [memoryId],
|
|
164
|
+
expectedRelevance: { [memoryId]: 2 },
|
|
165
|
+
sourceSessionId: pending.sessionId,
|
|
166
|
+
sourceTurnIndex: pending.turnIndex,
|
|
167
|
+
expectation: 'match',
|
|
168
|
+
knownAnswer: memoryContent
|
|
169
|
+
});
|
|
170
|
+
pendingBySession.delete(sessionId);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
appendExplicitNoMatchQueries(queries, options);
|
|
175
|
+
|
|
176
|
+
const redactContent = options.redactContent === true;
|
|
177
|
+
const rawContentIncluded = options.rawContentIncluded ?? !redactContent;
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
name: options.name ?? 'session-qrels-fixture',
|
|
181
|
+
description: options.description ?? 'Session-derived qrels fixture generated from Claude JSONL user/assistant turns.',
|
|
182
|
+
ks: options.ks ?? [1, 3, 5],
|
|
183
|
+
queries,
|
|
184
|
+
memories,
|
|
185
|
+
metadata: {
|
|
186
|
+
sourceFileCount: options.sourceFileCount,
|
|
187
|
+
rawContentIncluded,
|
|
188
|
+
generatedAt: options.generatedAt
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export async function collectClaudeSessionJsonlFiles(
|
|
194
|
+
rootDir: string,
|
|
195
|
+
options: SessionQrelsFileCollectionOptions = {}
|
|
196
|
+
): Promise<string[]> {
|
|
197
|
+
const maxFiles = options.maxFiles ?? Number.POSITIVE_INFINITY;
|
|
198
|
+
const minBytes = options.minBytes ?? 0;
|
|
199
|
+
const files: string[] = [];
|
|
200
|
+
|
|
201
|
+
async function walk(dir: string): Promise<void> {
|
|
202
|
+
if (files.length >= maxFiles) return;
|
|
203
|
+
|
|
204
|
+
let entries;
|
|
205
|
+
try {
|
|
206
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
207
|
+
} catch {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
212
|
+
|
|
213
|
+
for (const entry of entries) {
|
|
214
|
+
if (files.length >= maxFiles) return;
|
|
215
|
+
const fullPath = path.join(dir, entry.name);
|
|
216
|
+
if (entry.isDirectory()) {
|
|
217
|
+
if (!options.includeSubagents && entry.name.toLowerCase() === 'subagents') continue;
|
|
218
|
+
await walk(fullPath);
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
if (!entry.isFile() || !entry.name.endsWith('.jsonl')) continue;
|
|
223
|
+
if (minBytes > 0) {
|
|
224
|
+
try {
|
|
225
|
+
const info = await stat(fullPath);
|
|
226
|
+
if (info.size < minBytes) continue;
|
|
227
|
+
} catch {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
files.push(fullPath);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
await walk(rootDir);
|
|
236
|
+
return files;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function summarizeSessionQrelsFixture(fixture: SessionQrelsFixture): SessionQrelsSummary {
|
|
240
|
+
const bySession = new Map<string, SessionQrelsPerSessionSummary>();
|
|
241
|
+
|
|
242
|
+
function ensureSession(sourceSessionId: string, turnIndex: number): SessionQrelsPerSessionSummary {
|
|
243
|
+
const existing = bySession.get(sourceSessionId);
|
|
244
|
+
if (existing) {
|
|
245
|
+
existing.firstTurnIndex = Math.min(existing.firstTurnIndex, turnIndex);
|
|
246
|
+
existing.lastTurnIndex = Math.max(existing.lastTurnIndex, turnIndex);
|
|
247
|
+
return existing;
|
|
248
|
+
}
|
|
249
|
+
const created: SessionQrelsPerSessionSummary = {
|
|
250
|
+
sourceSessionId,
|
|
251
|
+
queryCount: 0,
|
|
252
|
+
memoryCount: 0,
|
|
253
|
+
firstTurnIndex: turnIndex,
|
|
254
|
+
lastTurnIndex: turnIndex
|
|
255
|
+
};
|
|
256
|
+
bySession.set(sourceSessionId, created);
|
|
257
|
+
return created;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
for (const query of fixture.queries) {
|
|
261
|
+
ensureSession(query.sourceSessionId, query.sourceTurnIndex).queryCount += 1;
|
|
262
|
+
}
|
|
263
|
+
for (const memory of fixture.memories) {
|
|
264
|
+
ensureSession(memory.sourceSessionId, memory.sourceTurnIndex).memoryCount += 1;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const perSession = Array.from(bySession.values()).sort((a, b) => a.sourceSessionId.localeCompare(b.sourceSessionId));
|
|
268
|
+
|
|
269
|
+
const positiveQueryCount = fixture.queries.filter((query) => getQueryExpectation(query) === 'match').length;
|
|
270
|
+
const noMatchQueryCount = fixture.queries.filter((query) => getQueryExpectation(query) === 'no_match').length;
|
|
271
|
+
const knownAnswerCount = fixture.queries.filter((query) => typeof query.knownAnswer === 'string' && query.knownAnswer.length > 0).length;
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
name: fixture.name,
|
|
275
|
+
description: fixture.description,
|
|
276
|
+
ks: fixture.ks,
|
|
277
|
+
queryCount: fixture.queries.length,
|
|
278
|
+
positiveQueryCount,
|
|
279
|
+
noMatchQueryCount,
|
|
280
|
+
knownAnswerCount,
|
|
281
|
+
memoryCount: fixture.memories.length,
|
|
282
|
+
sourceSessionCount: perSession.length,
|
|
283
|
+
sourceFileCount: fixture.metadata?.sourceFileCount,
|
|
284
|
+
rawContentIncluded: fixture.metadata?.rawContentIncluded ?? true,
|
|
285
|
+
perSession
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function appendExplicitNoMatchQueries(
|
|
290
|
+
queries: SessionQrelsQuery[],
|
|
291
|
+
options: SessionQrelsOptions
|
|
292
|
+
): void {
|
|
293
|
+
const inputs = options.noMatchQueries ?? [];
|
|
294
|
+
if (inputs.length === 0) return;
|
|
295
|
+
|
|
296
|
+
const remaining = options.maxQueries === undefined
|
|
297
|
+
? Number.POSITIVE_INFINITY
|
|
298
|
+
: Math.max(0, options.maxQueries - queries.length);
|
|
299
|
+
|
|
300
|
+
const startIndex = queries.length;
|
|
301
|
+
inputs.slice(0, remaining).forEach((input, index) => {
|
|
302
|
+
const queryId = input.queryId ?? `q-no-match-${startIndex + index + 1}`;
|
|
303
|
+
queries.push({
|
|
304
|
+
queryId,
|
|
305
|
+
query: options.redactContent ? `[redacted query ${queryId}]` : input.query,
|
|
306
|
+
expectedIds: [],
|
|
307
|
+
expectedRelevance: {},
|
|
308
|
+
sourceSessionId: input.sourceSessionId ?? 'no-match',
|
|
309
|
+
sourceTurnIndex: input.sourceTurnIndex ?? 0,
|
|
310
|
+
expectation: 'no_match',
|
|
311
|
+
forbiddenIds: [...(input.forbiddenIds ?? [])]
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function getQueryExpectation(query: SessionQrelsQuery): SessionQrelsExpectation {
|
|
317
|
+
return query.expectation ?? (query.expectedIds.length === 0 ? 'no_match' : 'match');
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function parseEntry(line: string): ClaudeJsonlEntry | null {
|
|
321
|
+
const trimmed = line.trim();
|
|
322
|
+
if (!trimmed) return null;
|
|
323
|
+
try {
|
|
324
|
+
return JSON.parse(trimmed) as ClaudeJsonlEntry;
|
|
325
|
+
} catch {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function extractTextContent(content: ClaudeMessageContent | undefined): string | null {
|
|
331
|
+
if (!content) return null;
|
|
332
|
+
if (typeof content === 'string') return content.trim();
|
|
333
|
+
const texts = content
|
|
334
|
+
.filter((block) => block.type === 'text' && block.text)
|
|
335
|
+
.map((block) => block.text?.trim() ?? '')
|
|
336
|
+
.filter(Boolean);
|
|
337
|
+
return texts.length > 0 ? texts.join('\n') : null;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function isWorthBenchmarkingPrompt(content: string): boolean {
|
|
341
|
+
const trimmed = content.trim();
|
|
342
|
+
if (isClaudeLocalCommandArtifact(trimmed)) return false;
|
|
343
|
+
if (trimmed.startsWith('/')) return false;
|
|
344
|
+
if (trimmed.length < 15) return false;
|
|
345
|
+
return /[a-zA-Z가-힣]{2,}/.test(trimmed);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function isClaudeLocalCommandArtifact(content: string): boolean {
|
|
349
|
+
return (
|
|
350
|
+
/^<local-command-(stdout|stderr)>/.test(content) ||
|
|
351
|
+
/^<command-(name|message)>/.test(content) ||
|
|
352
|
+
(content.includes('<command-name>') && content.includes('<local-command-stdout>'))
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function nextSessionCounter(counters: Map<string, number>, sessionId: string): number {
|
|
357
|
+
const next = (counters.get(sessionId) ?? 0) + 1;
|
|
358
|
+
counters.set(sessionId, next);
|
|
359
|
+
return next;
|
|
360
|
+
}
|
|
@@ -36,7 +36,7 @@ export class SQLiteEventStore {
|
|
|
36
36
|
private readonly readOnly: boolean;
|
|
37
37
|
private readonly markdownMirror: MarkdownMirror | null;
|
|
38
38
|
|
|
39
|
-
constructor(
|
|
39
|
+
constructor(dbPath: string, options?: SQLiteEventStoreOptions) {
|
|
40
40
|
this.readOnly = options?.readonly ?? false;
|
|
41
41
|
this.db = createSQLiteDatabase(dbPath, {
|
|
42
42
|
readonly: this.readOnly,
|
|
@@ -346,8 +346,7 @@ export class SQLiteEventStore {
|
|
|
346
346
|
CREATE VIRTUAL TABLE IF NOT EXISTS events_fts USING fts5(
|
|
347
347
|
content,
|
|
348
348
|
event_id UNINDEXED,
|
|
349
|
-
|
|
350
|
-
content_rowid='rowid'
|
|
349
|
+
tokenize='porter unicode61'
|
|
351
350
|
);
|
|
352
351
|
|
|
353
352
|
-- Triggers to keep FTS in sync with events table
|
|
@@ -356,11 +355,11 @@ export class SQLiteEventStore {
|
|
|
356
355
|
END;
|
|
357
356
|
|
|
358
357
|
CREATE TRIGGER IF NOT EXISTS events_fts_delete AFTER DELETE ON events BEGIN
|
|
359
|
-
|
|
358
|
+
DELETE FROM events_fts WHERE rowid = OLD.rowid;
|
|
360
359
|
END;
|
|
361
360
|
|
|
362
361
|
CREATE TRIGGER IF NOT EXISTS events_fts_update AFTER UPDATE ON events BEGIN
|
|
363
|
-
|
|
362
|
+
DELETE FROM events_fts WHERE rowid = OLD.rowid;
|
|
364
363
|
INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
|
|
365
364
|
END;
|
|
366
365
|
`);
|
|
@@ -1422,11 +1421,36 @@ export class SQLiteEventStore {
|
|
|
1422
1421
|
const countRow = sqliteGet<{count: number}>(this.db, 'SELECT COUNT(*) as count FROM events', []);
|
|
1423
1422
|
const totalEvents = countRow?.count ?? 0;
|
|
1424
1423
|
|
|
1425
|
-
// Clear and rebuild FTS index
|
|
1424
|
+
// Clear and rebuild FTS index. Recreate the virtual table instead of
|
|
1425
|
+
// issuing DELETE against it: older migrated FTS5 tables/triggers can fail
|
|
1426
|
+
// with `no such column: T.event_id` when processing synthetic deletes.
|
|
1426
1427
|
sqliteExec(this.db, `
|
|
1427
|
-
|
|
1428
|
+
DROP TRIGGER IF EXISTS events_fts_insert;
|
|
1429
|
+
DROP TRIGGER IF EXISTS events_fts_delete;
|
|
1430
|
+
DROP TRIGGER IF EXISTS events_fts_update;
|
|
1431
|
+
DROP TABLE IF EXISTS events_fts;
|
|
1432
|
+
|
|
1433
|
+
CREATE VIRTUAL TABLE events_fts USING fts5(
|
|
1434
|
+
content,
|
|
1435
|
+
event_id UNINDEXED,
|
|
1436
|
+
tokenize='porter unicode61'
|
|
1437
|
+
);
|
|
1438
|
+
|
|
1428
1439
|
INSERT INTO events_fts(rowid, content, event_id)
|
|
1429
1440
|
SELECT rowid, content, id FROM events;
|
|
1441
|
+
|
|
1442
|
+
CREATE TRIGGER events_fts_insert AFTER INSERT ON events BEGIN
|
|
1443
|
+
INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
|
|
1444
|
+
END;
|
|
1445
|
+
|
|
1446
|
+
CREATE TRIGGER events_fts_delete AFTER DELETE ON events BEGIN
|
|
1447
|
+
DELETE FROM events_fts WHERE rowid = OLD.rowid;
|
|
1448
|
+
END;
|
|
1449
|
+
|
|
1450
|
+
CREATE TRIGGER events_fts_update AFTER UPDATE ON events BEGIN
|
|
1451
|
+
DELETE FROM events_fts WHERE rowid = OLD.rowid;
|
|
1452
|
+
INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
|
|
1453
|
+
END;
|
|
1430
1454
|
`);
|
|
1431
1455
|
|
|
1432
1456
|
return totalEvents;
|
|
@@ -1773,14 +1797,14 @@ export class SQLiteEventStore {
|
|
|
1773
1797
|
|
|
1774
1798
|
// Recreate triggers
|
|
1775
1799
|
sqliteRun(this.db, `CREATE TRIGGER IF NOT EXISTS events_fts_insert AFTER INSERT ON events BEGIN
|
|
1776
|
-
INSERT INTO events_fts(rowid, content) VALUES (NEW.rowid, NEW.content);
|
|
1800
|
+
INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
|
|
1777
1801
|
END`);
|
|
1778
1802
|
sqliteRun(this.db, `CREATE TRIGGER IF NOT EXISTS events_fts_delete AFTER DELETE ON events BEGIN
|
|
1779
|
-
|
|
1803
|
+
DELETE FROM events_fts WHERE rowid = OLD.rowid;
|
|
1780
1804
|
END`);
|
|
1781
1805
|
sqliteRun(this.db, `CREATE TRIGGER IF NOT EXISTS events_fts_update AFTER UPDATE ON events BEGIN
|
|
1782
|
-
|
|
1783
|
-
INSERT INTO events_fts(rowid, content) VALUES (NEW.rowid, NEW.content);
|
|
1806
|
+
DELETE FROM events_fts WHERE rowid = OLD.rowid;
|
|
1807
|
+
INSERT INTO events_fts(rowid, content, event_id) VALUES (NEW.rowid, NEW.content, NEW.id);
|
|
1784
1808
|
END`);
|
|
1785
1809
|
} catch {
|
|
1786
1810
|
// FTS rebuild failed - non-critical, will be rebuilt on next initialize
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { dbRun, dbAll, type Database } from '../db-wrapper.js';
|
|
7
7
|
import { randomUUID } from 'crypto';
|
|
8
|
-
import type { BlockerRef,
|
|
8
|
+
import type { BlockerRef, Entity } from '../types.js';
|
|
9
9
|
import { makeEntityCanonicalKey, makeArtifactKey } from '../canonical-key.js';
|
|
10
10
|
import { TaskMatcher } from './task-matcher.js';
|
|
11
11
|
|
|
@@ -39,7 +39,7 @@ export class BlockerResolver {
|
|
|
39
39
|
*/
|
|
40
40
|
async resolveBlocker(
|
|
41
41
|
text: string,
|
|
42
|
-
|
|
42
|
+
_sourceEntryId?: string
|
|
43
43
|
): Promise<BlockerRef> {
|
|
44
44
|
const trimmedText = text.trim();
|
|
45
45
|
|
|
@@ -8,8 +8,7 @@ import { randomUUID } from 'crypto';
|
|
|
8
8
|
import type {
|
|
9
9
|
OutboxJob,
|
|
10
10
|
OutboxStatus,
|
|
11
|
-
OutboxItemKind
|
|
12
|
-
VALID_OUTBOX_TRANSITIONS
|
|
11
|
+
OutboxItemKind
|
|
13
12
|
} from './types.js';
|
|
14
13
|
|
|
15
14
|
export interface OutboxConfig {
|
|
@@ -191,14 +190,6 @@ export class VectorOutbox {
|
|
|
191
190
|
[now.toISOString(), this.config.maxRetries]
|
|
192
191
|
);
|
|
193
192
|
|
|
194
|
-
// Get counts (DuckDB doesn't return affected rows easily)
|
|
195
|
-
const recoveredRows = await dbAll<{ count: number }>(
|
|
196
|
-
this.db,
|
|
197
|
-
`SELECT COUNT(*) as count FROM vector_outbox
|
|
198
|
-
WHERE status = 'pending' AND updated_at = ?`,
|
|
199
|
-
[now.toISOString()]
|
|
200
|
-
);
|
|
201
|
-
|
|
202
193
|
return {
|
|
203
194
|
recovered: 0, // Approximate
|
|
204
195
|
retried: 0 // Approximate
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { EventStore } from './event-store.js';
|
|
7
7
|
import { VectorStore } from './vector-store.js';
|
|
8
8
|
import { Embedder } from './embedder.js';
|
|
9
|
-
import type {
|
|
9
|
+
import type { VectorRecord } from './types.js';
|
|
10
10
|
|
|
11
11
|
export interface WorkerConfig {
|
|
12
12
|
batchSize: number;
|