@jungjaehoon/mama-core 2.4.1 → 4.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 +76 -239
- package/db/migrations/030-case-first-memory-substrate.sql +13 -98
- package/db/migrations/034-add-connector-event-scope-columns.sql +9 -13
- package/db/migrations/039-add-connector-event-operator-ingest-seq.sql +9 -95
- package/db/migrations/062-refresh-connector-event-sequences.sql +9 -113
- package/db/migrations/063-refresh-legacy-connector-event-updates.sql +9 -32
- package/db/migrations/067-add-connector-event-source-entity-id.sql +9 -13
- package/db/migrations/069-create-registry-nodes.sql +52 -0
- package/db/migrations/070-record-identity.sql +35 -0
- package/db/migrations/071-service-operation-origins.sql +187 -0
- package/db/migrations/072-observation-versions.sql +29 -0
- package/db/migrations/073-registry-corrections.sql +45 -0
- package/db/migrations/074-work-graph-ref-kinds.sql +39 -0
- package/db/migrations/075-agent-judgments.sql +58 -0
- package/db/migrations/076-scoped-checkpoint-bindings.sql +15 -0
- package/db/migrations/077-legacy-record-kind.sql +6 -0
- package/db/migrations/078-source-ingest-commands.sql +18 -0
- package/db/migrations/079-twin-edge-relations.sql +43 -0
- package/db/migrations/080-restore-duration-days.sql +7 -0
- package/db/migrations/081-mailbox.sql +61 -0
- package/db/migrations/082-commitments-row-id.sql +12 -0
- package/db/migrations/083-observation-is-the-evidence.sql +49 -0
- package/db/migrations/084-scope-kind-is-not-the-cores-to-list.sql +34 -0
- package/db/migrations/085-a-migration-has-a-source.sql +37 -0
- package/db/migrations/086-the-mailbox-is-generic.sql +110 -0
- package/db/migrations/087-mailbox-payload.sql +5 -0
- package/db/migrations/088-native-input-journal.sql +14 -0
- package/db/migrations/089-native-turn-receipt-lookup.sql +3 -0
- package/db/migrations/090-model-run-native-inputs.sql +29 -0
- package/db/migrations/091-native-turn-results.sql +11 -0
- package/db/migrations/092-restore-decision-fts.sql +34 -0
- package/db/migrations/093-native-turn-primary-kind.sql +14 -0
- package/db/migrations/094-commitment-run-provenance.sql +9 -0
- package/db/migrations/095-model-run-native-input-identity.sql +39 -0
- package/db/migrations/096-drop-connector-event-index-fts.sql +9 -0
- package/db/migrations/097-native-input-json-validity.sql +37 -0
- package/db/migrations/098-workflow-memory-kind.sql +105 -0
- package/db/migrations/099-commitment-revision-graph.sql +2 -0
- package/dist/action-contracts.d.ts +212 -0
- package/dist/action-contracts.js +10 -0
- package/dist/api/catalog.d.ts +118 -0
- package/dist/api/catalog.js +1756 -0
- package/dist/api/dispatch.d.ts +76 -0
- package/dist/api/dispatch.js +372 -0
- package/dist/canonicalize.d.ts +2 -2
- package/dist/canonicalize.js +3 -3
- package/dist/client/client.d.ts +33 -0
- package/dist/client/client.js +123 -0
- package/dist/client/ipc.d.ts +81 -0
- package/dist/client/ipc.js +314 -0
- package/dist/db-adapter/base-adapter.d.ts +6 -66
- package/dist/db-adapter/base-adapter.js +6 -6
- package/dist/db-adapter/index.d.ts +5 -5
- package/dist/db-adapter/index.js +2 -5
- package/dist/db-adapter/node-sqlite-adapter.d.ts +85 -15
- package/dist/db-adapter/node-sqlite-adapter.js +1985 -570
- package/dist/db-manager.d.ts +53 -97
- package/dist/db-manager.js +121 -603
- package/dist/embedding/embedder.d.ts +132 -0
- package/dist/embedding/embedder.js +299 -0
- package/dist/identity/principal-repository.d.ts +2 -2
- package/dist/index.d.ts +43 -58
- package/dist/index.js +97 -145
- package/dist/{context-compile/channel-grant.d.ts → knowledge/access.d.ts} +12 -17
- package/dist/knowledge/access.js +663 -0
- package/dist/knowledge/case-errors.d.ts +31 -0
- package/dist/knowledge/case-errors.js +40 -0
- package/dist/{cases/search-rollup.d.ts → knowledge/case-search-rollup.d.ts} +5 -4
- package/dist/{cases/search-rollup.js → knowledge/case-search-rollup.js} +6 -8
- package/dist/{cases/store.d.ts → knowledge/case-store.d.ts} +3 -6
- package/dist/{cases/store.js → knowledge/case-store.js} +7 -42
- package/dist/{cases/timeline-range.d.ts → knowledge/case-timeline-range.d.ts} +3 -3
- package/dist/{cases/timeline-range.js → knowledge/case-timeline-range.js} +47 -25
- package/dist/{cases/types.d.ts → knowledge/case-types.d.ts} +8 -2
- package/dist/{cases/types.js → knowledge/case-types.js} +1 -1
- package/dist/knowledge/commitment-revision-migration.d.ts +4 -0
- package/dist/knowledge/commitment-revision-migration.js +50 -0
- package/dist/knowledge/commitments.d.ts +192 -0
- package/dist/knowledge/commitments.js +386 -0
- package/dist/knowledge/decision-edges.d.ts +70 -0
- package/dist/knowledge/decision-edges.js +123 -0
- package/dist/{agent-graph/types.d.ts → knowledge/graph-query.d.ts} +80 -70
- package/dist/knowledge/graph-query.js +1585 -0
- package/dist/knowledge/identity.d.ts +16 -0
- package/dist/knowledge/identity.js +22 -0
- package/dist/knowledge/index.d.ts +47 -0
- package/dist/knowledge/index.js +90 -0
- package/dist/knowledge/judgment-edge.d.ts +6 -0
- package/dist/knowledge/judgment-edge.js +22 -0
- package/dist/knowledge/judgments.d.ts +118 -0
- package/dist/knowledge/judgments.js +802 -0
- package/dist/knowledge/observations.d.ts +160 -0
- package/dist/knowledge/observations.js +449 -0
- package/dist/knowledge/question-type.d.ts +34 -0
- package/dist/knowledge/question-type.js +70 -0
- package/dist/{search → knowledge}/ranker-features.js +1 -1
- package/dist/{search → knowledge}/search-quality.d.ts +0 -1
- package/dist/knowledge/search.d.ts +38 -0
- package/dist/knowledge/search.js +91 -0
- package/dist/knowledge/source-ingest.d.ts +65 -0
- package/dist/knowledge/source-ingest.js +174 -0
- package/dist/{edges/types.d.ts → knowledge/twin-edge-types.d.ts} +31 -4
- package/dist/{edges/types.js → knowledge/twin-edge-types.js} +13 -2
- package/dist/knowledge/work-dates.d.ts +49 -0
- package/dist/knowledge/work-dates.js +120 -0
- package/dist/mama-api.d.ts +114 -778
- package/dist/mama-api.js +313 -2461
- package/dist/memory/api.d.ts +264 -24
- package/dist/memory/api.js +1633 -843
- package/dist/memory/bootstrap-builder.d.ts +2 -1
- package/dist/memory/bootstrap-builder.js +5 -5
- package/dist/memory/channel-summary-state-store.d.ts +3 -2
- package/dist/memory/channel-summary-state-store.js +53 -51
- package/dist/memory/channel-summary-store.d.ts +5 -3
- package/dist/memory/channel-summary-store.js +3 -8
- package/dist/memory/dashboard-read.d.ts +46 -0
- package/dist/memory/dashboard-read.js +94 -0
- package/dist/memory/event-store.d.ts +3 -3
- package/dist/memory/event-store.js +3 -10
- package/dist/memory/finding-store.d.ts +3 -2
- package/dist/memory/finding-store.js +2 -7
- package/dist/memory/graph-read.d.ts +52 -0
- package/dist/memory/graph-read.js +130 -0
- package/dist/memory/judgment-types.d.ts +394 -0
- package/dist/memory/judgment-types.js +16 -0
- package/dist/memory/provenance-audit.d.ts +5 -2
- package/dist/memory/provenance-audit.js +8 -14
- package/dist/memory/provenance-live.d.ts +141 -0
- package/dist/memory/provenance-live.js +409 -0
- package/dist/memory/provenance-query.d.ts +5 -4
- package/dist/memory/provenance-query.js +21 -29
- package/dist/memory/provenance-resolver.d.ts +191 -0
- package/dist/memory/provenance-resolver.js +155 -0
- package/dist/memory/provenance.d.ts +1 -11
- package/dist/memory/provenance.js +2 -33
- package/dist/memory/recall-sanitize.d.ts +55 -0
- package/dist/memory/recall-sanitize.js +144 -0
- package/dist/memory/secret-filter.d.ts +32 -0
- package/dist/memory/secret-filter.js +126 -0
- package/dist/memory/truth-store.d.ts +2 -1
- package/dist/memory/truth-store.js +1 -4
- package/dist/memory/types.d.ts +74 -24
- package/dist/memory/types.js +75 -5
- package/dist/memory/write-adapters.d.ts +98 -0
- package/dist/memory/write-adapters.js +242 -0
- package/dist/operations/owner-action-effects.d.ts +53 -0
- package/dist/operations/owner-action-effects.js +96 -0
- package/dist/provenance/source-ref.d.ts +1 -1
- package/dist/provenance/source-ref.js +0 -2
- package/dist/registry/corrections.d.ts +31 -0
- package/dist/registry/corrections.js +332 -0
- package/dist/registry/record-identity.d.ts +49 -0
- package/dist/registry/record-identity.js +133 -0
- package/dist/registry/store.d.ts +101 -0
- package/dist/registry/store.js +395 -0
- package/dist/registry/types.d.ts +28 -0
- package/dist/registry/types.js +5 -0
- package/dist/relevance-scorer.js +2 -2
- package/dist/runtime/agent-event-bus.d.ts +50 -0
- package/dist/runtime/agent-event-bus.js +101 -0
- package/dist/runtime/drivers/claude-cli-wrapper.d.ts +152 -0
- package/dist/runtime/drivers/claude-cli-wrapper.js +375 -0
- package/dist/runtime/drivers/claude-effort.d.ts +4 -0
- package/dist/runtime/drivers/claude-effort.js +16 -0
- package/dist/runtime/drivers/cli-arg-redaction.d.ts +2 -0
- package/dist/runtime/drivers/cli-arg-redaction.js +18 -0
- package/dist/runtime/drivers/cli-secret-redaction.d.ts +17 -0
- package/dist/runtime/drivers/cli-secret-redaction.js +126 -0
- package/dist/runtime/drivers/codex-app-server-process.d.ts +277 -0
- package/dist/runtime/drivers/codex-app-server-process.js +2342 -0
- package/dist/runtime/drivers/codex-auxiliary-tools.d.ts +17 -0
- package/dist/runtime/drivers/codex-auxiliary-tools.js +267 -0
- package/dist/runtime/drivers/codex-home.d.ts +20 -0
- package/dist/runtime/drivers/codex-home.js +674 -0
- package/dist/runtime/drivers/codex-thread-registry.d.ts +63 -0
- package/dist/runtime/drivers/codex-thread-registry.js +433 -0
- package/dist/runtime/drivers/persistent-cli-adapter.d.ts +160 -0
- package/dist/runtime/drivers/persistent-cli-adapter.js +396 -0
- package/dist/runtime/drivers/persistent-cli-process.d.ts +425 -0
- package/dist/runtime/drivers/persistent-cli-process.js +1529 -0
- package/dist/runtime/drivers/types.d.ts +456 -0
- package/dist/runtime/drivers/types.js +110 -0
- package/dist/runtime/mailbox.d.ts +223 -0
- package/dist/runtime/mailbox.js +582 -0
- package/dist/runtime/model-run-store.d.ts +28 -0
- package/dist/{model-runs/store.js → runtime/model-run-store.js} +81 -41
- package/dist/{model-runs/types.d.ts → runtime/model-run-types.d.ts} +33 -4
- package/dist/{model-runs/types.js → runtime/model-run-types.js} +1 -1
- package/dist/runtime/native-effect-observer.d.ts +22 -0
- package/dist/runtime/native-effect-observer.js +103 -0
- package/dist/runtime/native-input-journal.d.ts +46 -0
- package/dist/runtime/native-input-journal.js +308 -0
- package/dist/runtime/native-prompt.d.ts +118 -0
- package/dist/runtime/native-prompt.js +496 -0
- package/dist/runtime/native-session.d.ts +10 -0
- package/dist/{agent-graph/index.js → runtime/native-session.js} +9 -6
- package/dist/runtime/native-tool-trace-observer.d.ts +5 -0
- package/dist/runtime/native-tool-trace-observer.js +65 -0
- package/dist/runtime/native-turn.d.ts +272 -0
- package/dist/runtime/native-turn.js +1041 -0
- package/dist/runtime/operations.d.ts +236 -0
- package/dist/runtime/operations.js +565 -0
- package/dist/runtime/post-tool-handler.d.ts +74 -0
- package/dist/runtime/post-tool-handler.js +137 -0
- package/dist/runtime/prompt-layers.d.ts +126 -0
- package/dist/runtime/prompt-layers.js +239 -0
- package/dist/runtime/runtime-process.d.ts +102 -0
- package/dist/runtime/runtime-process.js +206 -0
- package/dist/runtime/runtime.d.ts +278 -0
- package/dist/runtime/runtime.js +563 -0
- package/dist/runtime/session-pool.d.ts +176 -0
- package/dist/runtime/session-pool.js +369 -0
- package/dist/runtime/stimulus-payload.d.ts +5 -0
- package/dist/runtime/stimulus-payload.js +50 -0
- package/dist/runtime/subagent-bridge.d.ts +24 -0
- package/dist/{agent-graph/types.js → runtime/subagent-bridge.js} +1 -1
- package/dist/runtime/text-completion.d.ts +22 -0
- package/dist/{agent-situation/types.js → runtime/text-completion.js} +1 -1
- package/dist/runtime/token-estimator.d.ts +25 -0
- package/dist/runtime/token-estimator.js +75 -0
- package/dist/runtime/tool-trace-store.d.ts +22 -0
- package/dist/{model-runs → runtime}/tool-trace-store.js +46 -27
- package/dist/runtime/trace-summary.d.ts +5 -0
- package/dist/runtime/trace-summary.js +74 -0
- package/dist/runtime/turn-text.d.ts +23 -0
- package/dist/runtime/turn-text.js +41 -0
- package/dist/storage/database.d.ts +67 -0
- package/dist/storage/database.js +158 -0
- package/package.json +20 -34
- package/dist/agent-graph/alias-write.d.ts +0 -3
- package/dist/agent-graph/alias-write.js +0 -234
- package/dist/agent-graph/entity-resolve.d.ts +0 -3
- package/dist/agent-graph/entity-resolve.js +0 -271
- package/dist/agent-graph/errors.d.ts +0 -4
- package/dist/agent-graph/errors.js +0 -11
- package/dist/agent-graph/graph-query.d.ts +0 -5
- package/dist/agent-graph/graph-query.js +0 -360
- package/dist/agent-graph/index.d.ts +0 -6
- package/dist/agent-situation/builder.d.ts +0 -8
- package/dist/agent-situation/builder.js +0 -239
- package/dist/agent-situation/cache-key.d.ts +0 -4
- package/dist/agent-situation/cache-key.js +0 -64
- package/dist/agent-situation/index.d.ts +0 -7
- package/dist/agent-situation/index.js +0 -28
- package/dist/agent-situation/packet-store.d.ts +0 -27
- package/dist/agent-situation/packet-store.js +0 -228
- package/dist/agent-situation/ranking-policy.d.ts +0 -18
- package/dist/agent-situation/ranking-policy.js +0 -75
- package/dist/agent-situation/source-readers.d.ts +0 -52
- package/dist/agent-situation/source-readers.js +0 -300
- package/dist/agent-situation/types.d.ts +0 -195
- package/dist/cases/wiki-page-index.d.ts +0 -37
- package/dist/cases/wiki-page-index.js +0 -201
- package/dist/config-loader.d.ts +0 -68
- package/dist/config-loader.js +0 -239
- package/dist/connectors/event-index.d.ts +0 -24
- package/dist/connectors/event-index.js +0 -245
- package/dist/connectors/raw-query.d.ts +0 -40
- package/dist/connectors/raw-query.js +0 -412
- package/dist/connectors/types.d.ts +0 -117
- package/dist/connectors/types.js +0 -3
- package/dist/context-compile/boundary-defaults.d.ts +0 -12
- package/dist/context-compile/boundary-defaults.js +0 -105
- package/dist/context-compile/channel-grant.js +0 -66
- package/dist/context-compile/compiler-policy.d.ts +0 -39
- package/dist/context-compile/compiler-policy.js +0 -147
- package/dist/context-compile/compiler.d.ts +0 -18
- package/dist/context-compile/compiler.js +0 -404
- package/dist/context-compile/index.d.ts +0 -10
- package/dist/context-compile/index.js +0 -26
- package/dist/context-compile/packet-store.d.ts +0 -8
- package/dist/context-compile/packet-store.js +0 -239
- package/dist/context-compile/ref.d.ts +0 -7
- package/dist/context-compile/ref.js +0 -102
- package/dist/context-compile/source-readers.d.ts +0 -70
- package/dist/context-compile/source-readers.js +0 -840
- package/dist/context-compile/types.d.ts +0 -155
- package/dist/context-compile/types.js +0 -11
- package/dist/context-compile/visibility.d.ts +0 -21
- package/dist/context-compile/visibility.js +0 -224
- package/dist/decision-tracker.d.ts +0 -206
- package/dist/decision-tracker.js +0 -481
- package/dist/edges/ref-validation.d.ts +0 -7
- package/dist/edges/ref-validation.js +0 -321
- package/dist/edges/store.d.ts +0 -8
- package/dist/edges/store.js +0 -129
- package/dist/embedding-client.d.ts +0 -28
- package/dist/embedding-client.js +0 -53
- package/dist/embedding-server/index.d.ts +0 -67
- package/dist/embedding-server/index.js +0 -405
- package/dist/embedding-server/mobile/auth.d.ts +0 -44
- package/dist/embedding-server/mobile/auth.js +0 -150
- package/dist/embedding-server/mobile/daemon.d.ts +0 -129
- package/dist/embedding-server/mobile/daemon.js +0 -313
- package/dist/embedding-server/mobile/output-parser.d.ts +0 -115
- package/dist/embedding-server/mobile/output-parser.js +0 -241
- package/dist/embedding-server/mobile/session-api.d.ts +0 -57
- package/dist/embedding-server/mobile/session-api.js +0 -261
- package/dist/embedding-server/mobile/session-manager.d.ts +0 -138
- package/dist/embedding-server/mobile/session-manager.js +0 -378
- package/dist/embedding-server/mobile/websocket-handler.d.ts +0 -137
- package/dist/embedding-server/mobile/websocket-handler.js +0 -486
- package/dist/embeddings.d.ts +0 -68
- package/dist/embeddings.js +0 -244
- package/dist/entities/audit-metrics.d.ts +0 -68
- package/dist/entities/audit-metrics.js +0 -124
- package/dist/entities/candidate-generator.d.ts +0 -8
- package/dist/entities/candidate-generator.js +0 -24
- package/dist/entities/entity-linked-decision-counts.d.ts +0 -2
- package/dist/entities/entity-linked-decision-counts.js +0 -29
- package/dist/entities/entity-list.d.ts +0 -22
- package/dist/entities/entity-list.js +0 -3
- package/dist/entities/entity-orphan-list.d.ts +0 -17
- package/dist/entities/entity-orphan-list.js +0 -3
- package/dist/entities/entity-search.d.ts +0 -20
- package/dist/entities/entity-search.js +0 -3
- package/dist/entities/errors.d.ts +0 -55
- package/dist/entities/errors.js +0 -100
- package/dist/entities/lineage-store.d.ts +0 -28
- package/dist/entities/lineage-store.js +0 -204
- package/dist/entities/normalization.d.ts +0 -14
- package/dist/entities/normalization.js +0 -63
- package/dist/entities/policy-store.d.ts +0 -8
- package/dist/entities/policy-store.js +0 -75
- package/dist/entities/policy-types.d.ts +0 -72
- package/dist/entities/policy-types.js +0 -59
- package/dist/entities/projection.d.ts +0 -8
- package/dist/entities/projection.js +0 -82
- package/dist/entities/provenance-query.d.ts +0 -32
- package/dist/entities/provenance-query.js +0 -3
- package/dist/entities/read-identity.d.ts +0 -31
- package/dist/entities/read-identity.js +0 -264
- package/dist/entities/recall-bridge.d.ts +0 -5
- package/dist/entities/recall-bridge.js +0 -171
- package/dist/entities/resolution-engine.d.ts +0 -8
- package/dist/entities/resolution-engine.js +0 -3
- package/dist/entities/rollback-preview.d.ts +0 -35
- package/dist/entities/rollback-preview.js +0 -3
- package/dist/entities/source-locator.d.ts +0 -3
- package/dist/entities/source-locator.js +0 -32
- package/dist/entities/store.d.ts +0 -69
- package/dist/entities/store.js +0 -544
- package/dist/entities/types.d.ts +0 -166
- package/dist/entities/types.js +0 -30
- package/dist/memory/extraction-prompt.d.ts +0 -4
- package/dist/memory/extraction-prompt.js +0 -89
- package/dist/memory/scope-backfill.d.ts +0 -14
- package/dist/memory/scope-backfill.js +0 -3
- package/dist/memory/scope-store.d.ts +0 -4
- package/dist/memory/scope-store.js +0 -9
- package/dist/memory-store.d.ts +0 -87
- package/dist/memory-store.js +0 -78
- package/dist/model-runs/store.d.ts +0 -13
- package/dist/model-runs/tool-trace-store.d.ts +0 -8
- package/dist/notification-manager.d.ts +0 -7
- package/dist/notification-manager.js +0 -12
- package/dist/outcome-tracker.d.ts +0 -151
- package/dist/outcome-tracker.js +0 -271
- package/dist/query-intent.d.ts +0 -23
- package/dist/query-intent.js +0 -114
- package/dist/runtime/trusted-provenance.d.ts +0 -3
- package/dist/runtime/trusted-provenance.js +0 -6
- package/dist/search/question-type.d.ts +0 -5
- package/dist/search/question-type.js +0 -41
- package/dist/test-utils.d.ts +0 -80
- package/dist/test-utils.js +0 -218
- package/dist/tier-validator.d.ts +0 -43
- package/dist/tier-validator.js +0 -159
- package/dist/time-formatter.d.ts +0 -25
- package/dist/time-formatter.js +0 -93
- /package/dist/{search → knowledge}/feedback-store.d.ts +0 -0
- /package/dist/{search → knowledge}/feedback-store.js +0 -0
- /package/dist/{search → knowledge}/ranker-features.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-rescore.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-rescore.js +0 -0
- /package/dist/{search → knowledge}/ranker-trainer.d.ts +0 -0
- /package/dist/{search → knowledge}/ranker-trainer.js +0 -0
- /package/dist/{search → knowledge}/search-quality.js +0 -0
package/dist/db-manager.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* MAMA Database Manager (SQLite-only)
|
|
4
4
|
*
|
|
5
|
-
* SQLite-exclusive database interface for
|
|
6
|
-
* Uses better-sqlite3 for local storage.
|
|
5
|
+
* SQLite-exclusive database interface. Uses better-sqlite3 for local storage.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
7
|
+
* There is no PostgreSQL path.
|
|
9
8
|
*
|
|
10
9
|
* Features:
|
|
11
10
|
* - WAL mode for better concurrency
|
|
@@ -18,43 +17,36 @@
|
|
|
18
17
|
* @date 2026-02-01
|
|
19
18
|
* @source-of-truth packages/mama-core/src/db-manager.js (mama-core)
|
|
20
19
|
*/
|
|
21
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
-
};
|
|
24
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.openDatabase = exports.isTestMode = exports.declareProductionDatabasePath = exports.clearProductionDatabasePaths = exports.assertTestProcessIsNotUsingRealDb = void 0;
|
|
25
22
|
exports.assertEmbeddingSchemeCurrent = assertEmbeddingSchemeCurrent;
|
|
26
23
|
exports.initDB = initDB;
|
|
27
|
-
exports.assertTestProcessIsNotUsingRealDb = assertTestProcessIsNotUsingRealDb;
|
|
28
24
|
exports.getDB = getDB;
|
|
29
25
|
exports.getAdapter = getAdapter;
|
|
26
|
+
exports.buildMemoryScopeId = buildMemoryScopeId;
|
|
30
27
|
exports.closeDB = closeDB;
|
|
31
28
|
exports.ensureMemoryScope = ensureMemoryScope;
|
|
32
|
-
exports.
|
|
33
|
-
exports.
|
|
34
|
-
exports.insertDecisionWithEmbedding = insertDecisionWithEmbedding;
|
|
35
|
-
exports.queryDecisionGraph = queryDecisionGraph;
|
|
36
|
-
exports.querySemanticEdges = querySemanticEdges;
|
|
37
|
-
exports.queryVectorSearch = queryVectorSearch;
|
|
29
|
+
exports.prepareDecisionEmbedding = prepareDecisionEmbedding;
|
|
30
|
+
exports.insertPreparedDecision = insertPreparedDecision;
|
|
38
31
|
exports.updateDecisionOutcome = updateDecisionOutcome;
|
|
39
|
-
exports.getPreparedStmt = getPreparedStmt;
|
|
40
32
|
exports.getDbPath = getDbPath;
|
|
41
33
|
exports.resetDBState = resetDBState;
|
|
42
|
-
exports.isTestMode = isTestMode;
|
|
43
|
-
exports.fts5Search = fts5Search;
|
|
44
|
-
const path_1 = __importDefault(require("path"));
|
|
45
|
-
const os_1 = __importDefault(require("os"));
|
|
46
34
|
const debug_logger_js_1 = require("./debug-logger.js");
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
35
|
+
const database_js_1 = require("./storage/database.js");
|
|
36
|
+
var database_js_2 = require("./storage/database.js");
|
|
37
|
+
Object.defineProperty(exports, "assertTestProcessIsNotUsingRealDb", { enumerable: true, get: function () { return database_js_2.assertTestProcessIsNotUsingRealDb; } });
|
|
38
|
+
Object.defineProperty(exports, "clearProductionDatabasePaths", { enumerable: true, get: function () { return database_js_2.clearProductionDatabasePaths; } });
|
|
39
|
+
Object.defineProperty(exports, "declareProductionDatabasePath", { enumerable: true, get: function () { return database_js_2.declareProductionDatabasePath; } });
|
|
40
|
+
Object.defineProperty(exports, "isTestMode", { enumerable: true, get: function () { return database_js_2.isTestMode; } });
|
|
41
|
+
var database_js_3 = require("./storage/database.js");
|
|
42
|
+
Object.defineProperty(exports, "openDatabase", { enumerable: true, get: function () { return database_js_3.openDatabase; } });
|
|
43
|
+
const embedder_js_1 = require("./embedding/embedder.js");
|
|
44
|
+
// One process-wide handle for callers that have not been given a database of
|
|
45
|
+
// their own yet. `openDatabase` owns the lifetime; this module only holds the
|
|
46
|
+
// handle and hands its adapter out.
|
|
47
|
+
let handle = null;
|
|
48
|
+
let openingPromise = null; // Single-flight guard for concurrent callers
|
|
55
49
|
// Migration directory (moved to src/db/migrations for M1.2)
|
|
56
|
-
const MIGRATIONS_DIR = path_1.default.join(__dirname, '..', 'db', 'migrations');
|
|
57
|
-
const REAL_USER_DB_PATH = path_1.default.join(os_1.default.homedir(), '.claude', 'mama-memory.db');
|
|
58
50
|
/**
|
|
59
51
|
* Initialize SQLite database adapter and connect
|
|
60
52
|
*
|
|
@@ -96,13 +88,13 @@ function assertEmbeddingSchemeCurrent(adapter) {
|
|
|
96
88
|
// embedding_meta missing (pre-042). runMigrations creates it, so this path
|
|
97
89
|
// only hits if migrations did not run; fall through to the vector check.
|
|
98
90
|
}
|
|
99
|
-
if (scheme ===
|
|
91
|
+
if (scheme === embedder_js_1.EMBEDDING_PREFIX_SCHEME)
|
|
100
92
|
return; // current
|
|
101
93
|
const legacyVectors = countRows(adapter, 'embeddings') + countRows(adapter, 'wiki_page_embeddings');
|
|
102
94
|
if (legacyVectors > 0) {
|
|
103
|
-
const dbPath = resolveAdapterDbPath(adapter) ?? '<db>';
|
|
95
|
+
const dbPath = (0, database_js_1.resolveAdapterDbPath)(adapter) ?? '<db>';
|
|
104
96
|
throw new Error(`[embedding-guard] ${dbPath} holds ${legacyVectors} vectors written WITHOUT the e5 ` +
|
|
105
|
-
`query/passage prefix (scheme='${scheme}', code requires '${
|
|
97
|
+
`query/passage prefix (scheme='${scheme}', code requires '${embedder_js_1.EMBEDDING_PREFIX_SCHEME}'). ` +
|
|
106
98
|
`Cosine search would be non-discriminative. Re-embed before starting:\n` +
|
|
107
99
|
` MAMA_DB_PATH="${dbPath}" node packages/mama-core/scripts/re-embed-migration.mjs`);
|
|
108
100
|
}
|
|
@@ -110,112 +102,48 @@ function assertEmbeddingSchemeCurrent(adapter) {
|
|
|
110
102
|
try {
|
|
111
103
|
adapter
|
|
112
104
|
.prepare("INSERT OR REPLACE INTO embedding_meta (key, value) VALUES ('embedding_prefix_scheme', ?)")
|
|
113
|
-
.run(
|
|
105
|
+
.run(embedder_js_1.EMBEDDING_PREFIX_SCHEME);
|
|
114
106
|
}
|
|
115
107
|
catch {
|
|
116
108
|
// best-effort; if embedding_meta truly missing, nothing to guard yet
|
|
117
109
|
}
|
|
118
110
|
}
|
|
119
|
-
async function initDB() {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await dbAdapter.runMigrations(MIGRATIONS_DIR);
|
|
140
|
-
// Reload vector cache after migrations (new tables/rows may now exist)
|
|
141
|
-
if (typeof dbAdapter.reloadVectorCache === 'function') {
|
|
142
|
-
dbAdapter.reloadVectorCache();
|
|
143
|
-
}
|
|
144
|
-
assertEmbeddingSchemeCurrent(dbAdapter); // fail loud on legacy vectors + new code
|
|
145
|
-
isInitialized = true;
|
|
146
|
-
(0, debug_logger_js_1.info)(`[db-manager] Database initialized (${dbAdapter.constructor.name})`);
|
|
147
|
-
(0, progress_indicator_js_1.logComplete)('Database ready');
|
|
148
|
-
return dbConnection;
|
|
149
|
-
}
|
|
150
|
-
catch (error) {
|
|
151
|
-
// Clear state on failure so retry is possible
|
|
152
|
-
initializingPromise = null;
|
|
153
|
-
dbAdapter = null;
|
|
154
|
-
dbConnection = null;
|
|
155
|
-
isInitialized = false;
|
|
156
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
157
|
-
throw new Error(`Failed to initialize database: ${message}`);
|
|
158
|
-
}
|
|
159
|
-
})();
|
|
160
|
-
return initializingPromise;
|
|
161
|
-
}
|
|
162
|
-
function assertTestProcessIsNotUsingRealDb(effectivePath, effectivePathSource = 'adapter') {
|
|
163
|
-
if (!isDatabaseBoundaryTestMode()) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
const configuredPaths = [
|
|
167
|
-
{ name: 'MAMA_DB_PATH', value: process.env.MAMA_DB_PATH },
|
|
168
|
-
{ name: 'MAMA_DATABASE_PATH', value: process.env.MAMA_DATABASE_PATH },
|
|
169
|
-
];
|
|
170
|
-
if (effectivePath) {
|
|
171
|
-
configuredPaths.push({ name: effectivePathSource, value: effectivePath });
|
|
172
|
-
}
|
|
173
|
-
for (const configuredPath of configuredPaths) {
|
|
174
|
-
if (!configuredPath.value) {
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
const resolvedPath = path_1.default.resolve(expandHomePath(configuredPath.value));
|
|
178
|
-
if (resolvedPath === path_1.default.resolve(REAL_USER_DB_PATH)) {
|
|
179
|
-
throw new Error(`[db-boundary] Refusing to initDB against real DB ${REAL_USER_DB_PATH} ` +
|
|
180
|
-
`from a test process (${configuredPath.name}=${configuredPath.value}). ` +
|
|
181
|
-
'Set MAMA_DB_PATH to a temporary path before initDB.');
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
function resolveAdapterDbPath(adapter) {
|
|
186
|
-
if (typeof adapter.getDbPath === 'function') {
|
|
187
|
-
return adapter.getDbPath();
|
|
188
|
-
}
|
|
189
|
-
return adapter.dbPath;
|
|
190
|
-
}
|
|
191
|
-
function isDatabaseBoundaryTestMode() {
|
|
192
|
-
return isTestMode();
|
|
193
|
-
}
|
|
194
|
-
function expandHomePath(value) {
|
|
195
|
-
const home = os_1.default.homedir();
|
|
196
|
-
if (value === '~') {
|
|
197
|
-
return home;
|
|
198
|
-
}
|
|
199
|
-
if (value.startsWith('~/')) {
|
|
200
|
-
return path_1.default.join(home, value.slice(2));
|
|
201
|
-
}
|
|
202
|
-
return value.replaceAll('${HOME}', home);
|
|
111
|
+
async function initDB(options = {}) {
|
|
112
|
+
if (handle) {
|
|
113
|
+
return handle.connection;
|
|
114
|
+
}
|
|
115
|
+
if (openingPromise) {
|
|
116
|
+
return (await openingPromise).connection;
|
|
117
|
+
}
|
|
118
|
+
// The handle is stored inside the chain, before `openingPromise` is cleared.
|
|
119
|
+
// Assigning it after the await left one microtask in which both guards read
|
|
120
|
+
// null, and a concurrent caller landing there would open a second adapter and
|
|
121
|
+
// run migrations again on the same file.
|
|
122
|
+
openingPromise = (0, database_js_1.openDatabase)(options.migrations ? { migrations: options.migrations } : {})
|
|
123
|
+
.then((opened) => {
|
|
124
|
+
handle = opened;
|
|
125
|
+
return opened;
|
|
126
|
+
})
|
|
127
|
+
.finally(() => {
|
|
128
|
+
openingPromise = null;
|
|
129
|
+
});
|
|
130
|
+
return (await openingPromise).connection;
|
|
203
131
|
}
|
|
204
132
|
/**
|
|
205
133
|
* Get database connection (singleton pattern)
|
|
206
134
|
*
|
|
207
135
|
* Returns better-sqlite3 Database instance
|
|
208
136
|
*
|
|
209
|
-
* Note: Synchronous
|
|
137
|
+
* Note: Synchronous because callers assume a resolved adapter, not a promise.
|
|
210
138
|
* Will throw if database not initialized
|
|
211
139
|
*
|
|
212
140
|
* @returns SQLite database connection
|
|
213
141
|
*/
|
|
214
142
|
function getDB() {
|
|
215
|
-
if (!
|
|
143
|
+
if (!handle) {
|
|
216
144
|
throw new Error('Database not initialized. Call await initDB() first.');
|
|
217
145
|
}
|
|
218
|
-
return
|
|
146
|
+
return handle.connection;
|
|
219
147
|
}
|
|
220
148
|
/**
|
|
221
149
|
* Get database adapter instance
|
|
@@ -225,10 +153,10 @@ function getDB() {
|
|
|
225
153
|
* @returns Adapter instance
|
|
226
154
|
*/
|
|
227
155
|
function getAdapter() {
|
|
228
|
-
if (!
|
|
156
|
+
if (!handle) {
|
|
229
157
|
throw new Error('Database adapter not initialized. Call await initDB() first.');
|
|
230
158
|
}
|
|
231
|
-
return
|
|
159
|
+
return handle.adapter;
|
|
232
160
|
}
|
|
233
161
|
function buildMemoryScopeId(kind, externalId) {
|
|
234
162
|
return `scope_${kind}_${Buffer.from(externalId).toString('base64url')}`;
|
|
@@ -239,17 +167,19 @@ function buildMemoryScopeId(kind, externalId) {
|
|
|
239
167
|
* Call this on process exit
|
|
240
168
|
*/
|
|
241
169
|
async function closeDB() {
|
|
242
|
-
if (
|
|
243
|
-
await
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
isInitialized = false;
|
|
247
|
-
initializingPromise = null; // Clear to allow re-initialization
|
|
170
|
+
if (handle) {
|
|
171
|
+
await handle.close();
|
|
172
|
+
handle = null;
|
|
173
|
+
openingPromise = null; // Clear to allow re-initialization
|
|
248
174
|
(0, debug_logger_js_1.info)('[db-manager] Database connection closed');
|
|
249
175
|
}
|
|
250
176
|
}
|
|
251
|
-
|
|
252
|
-
|
|
177
|
+
/**
|
|
178
|
+
* The single write boundary for memory_scopes. Callers inside a transaction
|
|
179
|
+
* pass their adapter through; the public wrapper resolves the global adapter
|
|
180
|
+
* for the call sites that predate the adapter-taking boundary.
|
|
181
|
+
*/
|
|
182
|
+
function ensureMemoryScope(adapter, kind, externalId) {
|
|
253
183
|
const id = buildMemoryScopeId(kind, externalId);
|
|
254
184
|
adapter
|
|
255
185
|
.prepare(`
|
|
@@ -259,388 +189,54 @@ async function ensureMemoryScope(kind, externalId) {
|
|
|
259
189
|
.run(id, kind, externalId);
|
|
260
190
|
return id;
|
|
261
191
|
}
|
|
262
|
-
/**
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
adapter.insertEmbedding(decisionRowid, embedding);
|
|
274
|
-
}
|
|
275
|
-
catch (error) {
|
|
276
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
277
|
-
// Graceful degradation: Log warning but don't fail
|
|
278
|
-
(0, debug_logger_js_1.error)(`[db-manager] Failed to insert embedding (vector search unavailable): ${message}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Perform vector similarity search
|
|
283
|
-
*
|
|
284
|
-
* Returns empty array if vector search not available (no keyword fallback)
|
|
285
|
-
*
|
|
286
|
-
* @param queryEmbedding - Query embedding (1024-dim)
|
|
287
|
-
* @param limit - Max results to return (default: 5)
|
|
288
|
-
* @param threshold - Minimum similarity threshold (default: 0.7)
|
|
289
|
-
* @returns Array of decisions with similarity scores, or empty array
|
|
290
|
-
*/
|
|
291
|
-
async function vectorSearch(queryEmbedding, limit = 5, threshold = 0.7, topicPrefix, excludeStatuses) {
|
|
292
|
-
const adapter = getAdapter();
|
|
293
|
-
try {
|
|
294
|
-
// Brute-force cosine similarity over all embeddings (with optional topic/status pre-filter)
|
|
295
|
-
const results = await adapter.vectorSearch(queryEmbedding, limit * 3, topicPrefix, excludeStatuses);
|
|
296
|
-
if (!results || results.length === 0) {
|
|
297
|
-
return []; // No keyword fallback - fast fail
|
|
298
|
-
}
|
|
299
|
-
const stmt = adapter.prepare(`SELECT * FROM decisions WHERE rowid = ?`);
|
|
300
|
-
const decisions = [];
|
|
301
|
-
for (const row of results) {
|
|
302
|
-
const decision = stmt.get(row.rowid);
|
|
303
|
-
if (!decision) {
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
const similarity = row.similarity ?? Math.max(0, 1.0 - (row.distance ?? 1));
|
|
307
|
-
const distance = row.distance ?? Math.max(0, 1.0 - similarity);
|
|
308
|
-
if (similarity >= threshold) {
|
|
309
|
-
decisions.push({
|
|
310
|
-
...decision,
|
|
311
|
-
distance,
|
|
312
|
-
similarity,
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
if (decisions.length >= limit) {
|
|
316
|
-
break;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
return decisions;
|
|
320
|
-
}
|
|
321
|
-
catch (error) {
|
|
322
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
323
|
-
(0, debug_logger_js_1.error)(`[db-manager] Vector search failed: ${message}`);
|
|
324
|
-
return []; // No keyword fallback - fast fail
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Insert decision with embedding
|
|
329
|
-
*
|
|
330
|
-
* Combined operation: Insert decision + Generate embedding + Insert embedding
|
|
331
|
-
* SQLite-only implementation
|
|
332
|
-
*
|
|
333
|
-
* @param decision - Decision object
|
|
334
|
-
* @returns Decision ID
|
|
335
|
-
*/
|
|
336
|
-
async function insertDecisionWithEmbedding(decision) {
|
|
337
|
-
const adapter = getAdapter();
|
|
338
|
-
const { generateEnhancedEmbedding } = await import('./embeddings.js');
|
|
339
|
-
// Validate event_date before any DB operations
|
|
340
|
-
if (decision.event_date !== null && decision.event_date !== undefined) {
|
|
341
|
-
const d = decision.event_date;
|
|
342
|
-
if (!/^\d{4}-\d{2}-\d{2}$/.test(d) || isNaN(new Date(d).getTime())) {
|
|
343
|
-
throw new Error(`Invalid event_date: must be ISO 8601 YYYY-MM-DD (got: ${d})`);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
if (decision.event_datetime !== null && decision.event_datetime !== undefined) {
|
|
347
|
-
if (typeof decision.event_datetime !== 'number' ||
|
|
192
|
+
/** Generate the optional vector before opening a synchronous SQLite transaction. */
|
|
193
|
+
async function prepareDecisionEmbedding(decision) {
|
|
194
|
+
if (decision.event_date !== null &&
|
|
195
|
+
decision.event_date !== undefined &&
|
|
196
|
+
(!/^\d{4}-\d{2}-\d{2}$/.test(decision.event_date) ||
|
|
197
|
+
Number.isNaN(new Date(decision.event_date).getTime()))) {
|
|
198
|
+
throw new Error(`Invalid event_date: must be ISO 8601 YYYY-MM-DD (got: ${decision.event_date})`);
|
|
199
|
+
}
|
|
200
|
+
if (decision.event_datetime !== null &&
|
|
201
|
+
decision.event_datetime !== undefined &&
|
|
202
|
+
(typeof decision.event_datetime !== 'number' ||
|
|
348
203
|
!Number.isFinite(decision.event_datetime) ||
|
|
349
|
-
decision.event_datetime <= 0) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
});
|
|
367
|
-
(0, debug_logger_js_1.info)(`[db-manager] Embedding generated: ${embedding ? embedding.length : 'null'} dimensions`);
|
|
368
|
-
}
|
|
369
|
-
catch (embGenErr) {
|
|
370
|
-
// Non-fatal: save decision without embedding (e.g. ONNX model unavailable on CI)
|
|
371
|
-
const message = embGenErr instanceof Error ? embGenErr.message : String(embGenErr);
|
|
372
|
-
(0, debug_logger_js_1.error)(`[db-manager] ⚠️ Embedding generation failed, saving without vector: ${message}`);
|
|
373
|
-
}
|
|
374
|
-
// SQLite: Synchronous transaction including embedding
|
|
375
|
-
adapter.transaction(() => {
|
|
376
|
-
// Prepare INSERT statement
|
|
377
|
-
const stmt = adapter.prepare(`
|
|
378
|
-
INSERT INTO decisions (
|
|
379
|
-
id, topic, decision, reasoning,
|
|
380
|
-
outcome, failure_reason, limitation,
|
|
381
|
-
user_involvement, session_id,
|
|
382
|
-
supersedes, superseded_by, refined_from,
|
|
383
|
-
confidence, created_at, updated_at,
|
|
384
|
-
needs_validation, validation_attempts, last_validated_at, usage_count,
|
|
385
|
-
trust_context, usage_success, usage_failure, time_saved,
|
|
386
|
-
evidence, alternatives, risks, event_date, event_datetime,
|
|
387
|
-
agent_id, model_run_id, envelope_hash, gateway_call_id, source_refs_json, provenance_json
|
|
388
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
389
|
-
`);
|
|
390
|
-
const insertResult = stmt.run(decision.id, decision.topic, decision.decision, decision.reasoning || null, decision.outcome || null, decision.failure_reason || null, decision.limitation || null, decision.user_involvement || null, decision.session_id || null, decision.supersedes || null, decision.superseded_by || null, decision.refined_from ? JSON.stringify(decision.refined_from) : null, decision.confidence !== undefined ? decision.confidence : 0.5,
|
|
391
|
-
// IMPORTANT: All timestamps are stored in milliseconds (Date.now()).
|
|
392
|
-
// The schema DEFAULT uses unixepoch() (seconds) but is never used
|
|
393
|
-
// since all inserts go through this function which always provides ms.
|
|
394
|
-
decision.created_at || Date.now(), decision.updated_at || Date.now(), decision.needs_validation !== undefined ? decision.needs_validation : 0, decision.validation_attempts || 0, decision.last_validated_at || null, decision.usage_count || 0, decision.trust_context || null, decision.usage_success || 0, decision.usage_failure || 0, decision.time_saved || 0, decision.evidence || null, decision.alternatives || null, decision.risks || null, decision.event_date || null, decision.event_datetime ?? null, decision.agent_id ?? null, decision.model_run_id ?? null, decision.envelope_hash ?? null, decision.gateway_call_id ?? null, decision.source_refs_json ?? null, decision.provenance_json ?? null);
|
|
395
|
-
const rowid = Number(insertResult.lastInsertRowid);
|
|
396
|
-
// Insert embedding in same transaction to ensure rowid matching
|
|
397
|
-
(0, debug_logger_js_1.info)(`[db-manager] Vector search enabled: ${adapter.vectorSearchEnabled}`);
|
|
398
|
-
if (adapter.vectorSearchEnabled && embedding) {
|
|
399
|
-
try {
|
|
400
|
-
(0, debug_logger_js_1.info)(`[db-manager] Inserting embedding for rowid: ${rowid}`);
|
|
401
|
-
adapter.insertEmbedding(rowid, embedding);
|
|
402
|
-
(0, debug_logger_js_1.info)(`[db-manager] ✅ Embedding inserted successfully`);
|
|
403
|
-
}
|
|
404
|
-
catch (embErr) {
|
|
405
|
-
const message = embErr instanceof Error ? embErr.message : String(embErr);
|
|
406
|
-
// Log but don't fail transaction if embedding fails
|
|
407
|
-
(0, debug_logger_js_1.error)(`[db-manager] ❌ Embedding insert failed: ${message}`);
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
else {
|
|
411
|
-
(0, debug_logger_js_1.info)(`[db-manager] ⚠️ Vector search disabled, skipping embedding`);
|
|
412
|
-
}
|
|
413
|
-
return rowid;
|
|
414
|
-
});
|
|
415
|
-
if (process.env.MAMA_DEBUG) {
|
|
416
|
-
(0, debug_logger_js_1.info)(`[db-manager] Decision stored: ${decision.id}`);
|
|
417
|
-
}
|
|
418
|
-
return decision.id;
|
|
419
|
-
}
|
|
420
|
-
catch (error) {
|
|
421
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
422
|
-
throw new Error(`Failed to insert decision with embedding: ${message}`);
|
|
423
|
-
}
|
|
204
|
+
decision.event_datetime <= 0)) {
|
|
205
|
+
throw new Error(`Invalid event_datetime: must be a positive millisecond timestamp (got: ${decision.event_datetime})`);
|
|
206
|
+
}
|
|
207
|
+
const { generateEnhancedEmbedding, isForceTier3Enabled } = await import('./embedding/embedder.js');
|
|
208
|
+
if (isForceTier3Enabled()) {
|
|
209
|
+
// Tier-3 is an explicit no-vector mode, not an embedder failure.
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
// Failure-first: an embedder error aborts the write instead of committing a
|
|
213
|
+
// decision row without its required vector.
|
|
214
|
+
return await generateEnhancedEmbedding({
|
|
215
|
+
topic: decision.topic,
|
|
216
|
+
decision: decision.decision,
|
|
217
|
+
reasoning: decision.reasoning || undefined,
|
|
218
|
+
outcome: decision.outcome || undefined,
|
|
219
|
+
confidence: decision.confidence,
|
|
220
|
+
});
|
|
424
221
|
}
|
|
425
|
-
/**
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
WITH RECURSIVE decision_chain AS (
|
|
442
|
-
-- Base case: Get current decision (not superseded)
|
|
443
|
-
SELECT * FROM decisions
|
|
444
|
-
WHERE topic = ? AND superseded_by IS NULL
|
|
445
|
-
|
|
446
|
-
UNION ALL
|
|
447
|
-
|
|
448
|
-
-- Recursive case: Get previous decisions
|
|
449
|
-
SELECT d.* FROM decisions d
|
|
450
|
-
JOIN decision_chain dc ON d.id = dc.supersedes
|
|
451
|
-
)
|
|
452
|
-
SELECT * FROM decision_chain
|
|
453
|
-
ORDER BY created_at DESC
|
|
454
|
-
`);
|
|
455
|
-
let decisions = stmt.all(topic);
|
|
456
|
-
// If no exact match, try fuzzy matching as fallback
|
|
457
|
-
if (decisions.length === 0) {
|
|
458
|
-
const topicKeyword = topic.split('_')[0];
|
|
459
|
-
stmt = adapter.prepare(`
|
|
460
|
-
WITH RECURSIVE decision_chain AS (
|
|
461
|
-
-- Base case: Get current decision (not superseded)
|
|
462
|
-
SELECT * FROM decisions
|
|
463
|
-
WHERE topic LIKE ? || '%' AND superseded_by IS NULL
|
|
464
|
-
|
|
465
|
-
UNION ALL
|
|
466
|
-
|
|
467
|
-
-- Recursive case: Get previous decisions
|
|
468
|
-
SELECT d.* FROM decisions d
|
|
469
|
-
JOIN decision_chain dc ON d.id = dc.supersedes
|
|
470
|
-
)
|
|
471
|
-
SELECT * FROM decision_chain
|
|
472
|
-
ORDER BY created_at DESC
|
|
473
|
-
`);
|
|
474
|
-
decisions = stmt.all(topicKeyword);
|
|
475
|
-
}
|
|
476
|
-
// Join with decision_edges to include relationships
|
|
477
|
-
// Prepare statement once outside loop for performance
|
|
478
|
-
const edgesStmt = adapter.prepare(`
|
|
479
|
-
SELECT * FROM decision_edges
|
|
480
|
-
WHERE from_id = ?
|
|
481
|
-
AND (approved_by_user = 1 OR approved_by_user IS NULL)
|
|
482
|
-
`);
|
|
483
|
-
for (const decision of decisions) {
|
|
484
|
-
decision.edges = edgesStmt.all(decision.id);
|
|
485
|
-
// Parse refined_from JSON if exists
|
|
486
|
-
if (decision.refined_from) {
|
|
487
|
-
try {
|
|
488
|
-
decision.refined_from =
|
|
489
|
-
typeof decision.refined_from === 'string'
|
|
490
|
-
? JSON.parse(decision.refined_from)
|
|
491
|
-
: decision.refined_from;
|
|
492
|
-
}
|
|
493
|
-
catch {
|
|
494
|
-
decision.refined_from = [];
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
return decisions;
|
|
499
|
-
}
|
|
500
|
-
catch (error) {
|
|
501
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
502
|
-
throw new Error(`Decision graph query failed: ${message}`);
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Query semantic edges for a list of decisions
|
|
507
|
-
*
|
|
508
|
-
* Returns both outgoing (from_id) and incoming (to_id) edges
|
|
509
|
-
* for refines and contradicts relationships
|
|
510
|
-
*
|
|
511
|
-
* @param decisionIds - Decision IDs to query edges for
|
|
512
|
-
* @returns Categorized edges
|
|
513
|
-
*/
|
|
514
|
-
async function querySemanticEdges(decisionIds) {
|
|
515
|
-
const adapter = getAdapter();
|
|
516
|
-
if (!decisionIds || decisionIds.length === 0) {
|
|
517
|
-
return {
|
|
518
|
-
refines: [],
|
|
519
|
-
refined_by: [],
|
|
520
|
-
contradicts: [],
|
|
521
|
-
contradicted_by: [],
|
|
522
|
-
// Story 2.1: Extended edge types
|
|
523
|
-
builds_on: [],
|
|
524
|
-
built_on_by: [],
|
|
525
|
-
debates: [],
|
|
526
|
-
debated_by: [],
|
|
527
|
-
synthesizes: [],
|
|
528
|
-
synthesized_by: [],
|
|
529
|
-
};
|
|
530
|
-
}
|
|
531
|
-
try {
|
|
532
|
-
// Build placeholders for IN clause
|
|
533
|
-
const placeholders = decisionIds.map(() => '?').join(',');
|
|
534
|
-
// Story 2.1: Include new edge types in query
|
|
535
|
-
const edgeTypes = ['refines', 'contradicts', 'builds_on', 'debates', 'synthesizes'];
|
|
536
|
-
const edgeTypePlaceholders = edgeTypes.map(() => '?').join(',');
|
|
537
|
-
// Query outgoing edges (from_id = decision)
|
|
538
|
-
const outgoingStmt = adapter.prepare(`
|
|
539
|
-
SELECT e.*, d.topic, d.decision, d.confidence, d.created_at
|
|
540
|
-
FROM decision_edges e
|
|
541
|
-
JOIN decisions d ON e.to_id = d.id
|
|
542
|
-
WHERE e.from_id IN (${placeholders})
|
|
543
|
-
AND e.relationship IN (${edgeTypePlaceholders})
|
|
544
|
-
AND (e.approved_by_user = 1 OR e.approved_by_user IS NULL)
|
|
545
|
-
ORDER BY e.created_at DESC
|
|
546
|
-
`);
|
|
547
|
-
const outgoingEdges = outgoingStmt.all(...decisionIds, ...edgeTypes);
|
|
548
|
-
// Query incoming edges (to_id = decision)
|
|
549
|
-
const incomingStmt = adapter.prepare(`
|
|
550
|
-
SELECT e.*, d.topic, d.decision, d.confidence, d.created_at
|
|
551
|
-
FROM decision_edges e
|
|
552
|
-
JOIN decisions d ON e.from_id = d.id
|
|
553
|
-
WHERE e.to_id IN (${placeholders})
|
|
554
|
-
AND e.relationship IN (${edgeTypePlaceholders})
|
|
555
|
-
AND (e.approved_by_user = 1 OR e.approved_by_user IS NULL)
|
|
556
|
-
ORDER BY e.created_at DESC
|
|
557
|
-
`);
|
|
558
|
-
const incomingEdges = incomingStmt.all(...decisionIds, ...edgeTypes);
|
|
559
|
-
// Categorize edges (original + v1.3 extended)
|
|
560
|
-
const refines = outgoingEdges.filter((e) => e.relationship === 'refines');
|
|
561
|
-
const refined_by = incomingEdges.filter((e) => e.relationship === 'refines');
|
|
562
|
-
const contradicts = outgoingEdges.filter((e) => e.relationship === 'contradicts');
|
|
563
|
-
const contradicted_by = incomingEdges.filter((e) => e.relationship === 'contradicts');
|
|
564
|
-
// Story 2.1: New edge type categories
|
|
565
|
-
const builds_on = outgoingEdges.filter((e) => e.relationship === 'builds_on');
|
|
566
|
-
const built_on_by = incomingEdges.filter((e) => e.relationship === 'builds_on');
|
|
567
|
-
const debates = outgoingEdges.filter((e) => e.relationship === 'debates');
|
|
568
|
-
const debated_by = incomingEdges.filter((e) => e.relationship === 'debates');
|
|
569
|
-
const synthesizes = outgoingEdges.filter((e) => e.relationship === 'synthesizes');
|
|
570
|
-
const synthesized_by = incomingEdges.filter((e) => e.relationship === 'synthesizes');
|
|
571
|
-
return {
|
|
572
|
-
refines,
|
|
573
|
-
refined_by,
|
|
574
|
-
contradicts,
|
|
575
|
-
contradicted_by,
|
|
576
|
-
builds_on,
|
|
577
|
-
built_on_by,
|
|
578
|
-
debates,
|
|
579
|
-
debated_by,
|
|
580
|
-
synthesizes,
|
|
581
|
-
synthesized_by,
|
|
582
|
-
};
|
|
583
|
-
}
|
|
584
|
-
catch (error) {
|
|
585
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
586
|
-
throw new Error(`Semantic edges query failed: ${message}`);
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Query vector search with time window and threshold
|
|
591
|
-
*
|
|
592
|
-
* Story 014.14: AC #1 - Vector Search for Related Decisions
|
|
593
|
-
*
|
|
594
|
-
* @param params - Search parameters
|
|
595
|
-
* @returns Results with similarity scores and decision data
|
|
596
|
-
*/
|
|
597
|
-
async function queryVectorSearch(params) {
|
|
598
|
-
const { query, limit = 10, threshold = 0.75, timeWindow = 90 * 24 * 60 * 60 * 1000 } = params;
|
|
599
|
-
const adapter = getAdapter();
|
|
600
|
-
const { generateEmbedding } = await import('./embeddings.js');
|
|
601
|
-
try {
|
|
602
|
-
// Generate embedding for query
|
|
603
|
-
const embedding = await generateEmbedding(query, 'query');
|
|
604
|
-
const cutoffTime = Date.now() - timeWindow;
|
|
605
|
-
const candidates = await adapter.vectorSearch(embedding, limit * 5);
|
|
606
|
-
if (!candidates || candidates.length === 0) {
|
|
607
|
-
return [];
|
|
608
|
-
}
|
|
609
|
-
const stmt = adapter.prepare(`SELECT * FROM decisions WHERE rowid = ?`);
|
|
610
|
-
const results = [];
|
|
611
|
-
for (const candidate of candidates) {
|
|
612
|
-
const decision = stmt.get(candidate.rowid);
|
|
613
|
-
if (!decision) {
|
|
614
|
-
continue;
|
|
615
|
-
}
|
|
616
|
-
if (decision.created_at < cutoffTime) {
|
|
617
|
-
continue;
|
|
618
|
-
}
|
|
619
|
-
const similarity = candidate.similarity ?? Math.max(0, 1 - (candidate.distance ?? 1));
|
|
620
|
-
const distance = candidate.distance ?? Math.max(0, 1 - similarity);
|
|
621
|
-
if (similarity < threshold) {
|
|
622
|
-
continue;
|
|
623
|
-
}
|
|
624
|
-
// Filter out superseded decisions unless explicitly requested
|
|
625
|
-
if (!params.includeSuperseded && decision.superseded_by) {
|
|
626
|
-
continue;
|
|
627
|
-
}
|
|
628
|
-
results.push({
|
|
629
|
-
...decision,
|
|
630
|
-
similarity,
|
|
631
|
-
distance,
|
|
632
|
-
});
|
|
633
|
-
if (results.length >= limit) {
|
|
634
|
-
break;
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
return results;
|
|
638
|
-
}
|
|
639
|
-
catch (error) {
|
|
640
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
641
|
-
(0, debug_logger_js_1.error)(`[db-manager] queryVectorSearch failed: ${message}`);
|
|
642
|
-
return []; // Return empty array on error (graceful degradation)
|
|
222
|
+
/** Insert one decision and its already-prepared vector inside the caller's transaction. */
|
|
223
|
+
function insertPreparedDecision(adapter, decision, embedding) {
|
|
224
|
+
const stmt = adapter.prepare(`
|
|
225
|
+
INSERT INTO decisions (
|
|
226
|
+
id, topic, decision, reasoning, outcome, failure_reason, limitation,
|
|
227
|
+
user_involvement, session_id, supersedes, superseded_by, refined_from,
|
|
228
|
+
confidence, created_at, updated_at, needs_validation, validation_attempts,
|
|
229
|
+
last_validated_at, usage_count, trust_context, usage_success, usage_failure,
|
|
230
|
+
time_saved, evidence, alternatives, risks, event_date, event_datetime,
|
|
231
|
+
agent_id, model_run_id, envelope_hash, gateway_call_id, source_refs_json, provenance_json
|
|
232
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
233
|
+
`);
|
|
234
|
+
const result = stmt.run(decision.id, decision.topic, decision.decision, decision.reasoning || null, decision.outcome || null, decision.failure_reason || null, decision.limitation || null, decision.user_involvement || null, decision.session_id || null, decision.supersedes || null, decision.superseded_by || null, decision.refined_from ? JSON.stringify(decision.refined_from) : null, decision.confidence ?? 0.5, decision.created_at || Date.now(), decision.updated_at || Date.now(), decision.needs_validation ?? 0, decision.validation_attempts || 0, decision.last_validated_at || null, decision.usage_count || 0, decision.trust_context || null, decision.usage_success || 0, decision.usage_failure || 0, decision.time_saved || 0, decision.evidence || null, decision.alternatives || null, decision.risks || null, decision.event_date || null, decision.event_datetime ?? null, decision.agent_id ?? null, decision.model_run_id ?? null, decision.envelope_hash ?? null, decision.gateway_call_id ?? null, decision.source_refs_json ?? null, decision.provenance_json ?? null);
|
|
235
|
+
const rowid = Number(result.lastInsertRowid);
|
|
236
|
+
if (embedding) {
|
|
237
|
+
adapter.insertEmbedding(rowid, embedding);
|
|
643
238
|
}
|
|
239
|
+
return rowid;
|
|
644
240
|
}
|
|
645
241
|
/**
|
|
646
242
|
* Update decision outcome
|
|
@@ -649,20 +245,18 @@ async function queryVectorSearch(params) {
|
|
|
649
245
|
* @param outcomeData - Outcome data
|
|
650
246
|
*/
|
|
651
247
|
async function updateDecisionOutcome(decisionId, outcomeData) {
|
|
652
|
-
const adapter = getAdapter();
|
|
653
248
|
try {
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
stmt.run(outcomeData.outcome ?? null, outcomeData.failure_reason ?? null, outcomeData.limitation ?? null, outcomeData.duration_days ?? null, outcomeData.confidence !== undefined ? outcomeData.confidence : null, Date.now(), decisionId);
|
|
249
|
+
// Append-only: the outcome change is an authored judgment record; the
|
|
250
|
+
// maintained decisions projection columns move in the same transaction.
|
|
251
|
+
// Dynamic import avoids a module cycle with memory/write-adapters.
|
|
252
|
+
const { appendOutcomeAmendment } = await import('./memory/write-adapters.js');
|
|
253
|
+
await appendOutcomeAmendment(decisionId, {
|
|
254
|
+
outcome: outcomeData.outcome ?? null,
|
|
255
|
+
failureReason: outcomeData.failure_reason ?? null,
|
|
256
|
+
limitation: outcomeData.limitation ?? null,
|
|
257
|
+
confidence: outcomeData.confidence ?? null,
|
|
258
|
+
durationDays: outcomeData.duration_days ?? null,
|
|
259
|
+
}, { adapter: getAdapter() });
|
|
666
260
|
(0, debug_logger_js_1.info)(`[db-manager] Decision outcome updated: ${decisionId} → ${outcomeData.outcome}`);
|
|
667
261
|
}
|
|
668
262
|
catch (error) {
|
|
@@ -670,58 +264,16 @@ async function updateDecisionOutcome(decisionId, outcomeData) {
|
|
|
670
264
|
throw new Error(`Failed to update decision outcome: ${message}`);
|
|
671
265
|
}
|
|
672
266
|
}
|
|
673
|
-
/**
|
|
674
|
-
* Get prepared statement
|
|
675
|
-
*
|
|
676
|
-
* For backward compatibility with memory-store.js
|
|
677
|
-
* Returns a compatibility shim that proxies to adapter.prepare()
|
|
678
|
-
*
|
|
679
|
-
* @param sql - SQL statement
|
|
680
|
-
* @returns Statement-like object with run/get/all methods
|
|
681
|
-
*/
|
|
682
|
-
function getPreparedStmt(sql) {
|
|
683
|
-
if (!dbAdapter) {
|
|
684
|
-
(0, debug_logger_js_1.warn)('[db-manager] getPreparedStmt() called before initialization');
|
|
685
|
-
// Return no-op object for feature detection (won't throw)
|
|
686
|
-
return {
|
|
687
|
-
run: () => ({ changes: 0, lastInsertRowid: 0 }),
|
|
688
|
-
get: () => null,
|
|
689
|
-
all: () => [],
|
|
690
|
-
};
|
|
691
|
-
}
|
|
692
|
-
// Proxy to adapter.prepare() for actual usage
|
|
693
|
-
try {
|
|
694
|
-
return dbAdapter.prepare(sql);
|
|
695
|
-
}
|
|
696
|
-
catch (error) {
|
|
697
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
698
|
-
(0, debug_logger_js_1.warn)(`[db-manager] getPreparedStmt() failed: ${message}`);
|
|
699
|
-
// Return no-op object on error (graceful degradation)
|
|
700
|
-
return {
|
|
701
|
-
run: () => ({ changes: 0, lastInsertRowid: 0 }),
|
|
702
|
-
get: () => null,
|
|
703
|
-
all: () => [],
|
|
704
|
-
};
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
267
|
/**
|
|
708
268
|
* Get database file path
|
|
709
269
|
*
|
|
710
270
|
* @returns Actual database path or 'Not initialized'
|
|
711
271
|
*/
|
|
712
272
|
function getDbPath() {
|
|
713
|
-
if (!
|
|
273
|
+
if (!handle) {
|
|
714
274
|
return 'Not initialized';
|
|
715
275
|
}
|
|
716
|
-
|
|
717
|
-
if (typeof dbAdapter.getDbPath === 'function') {
|
|
718
|
-
return dbAdapter.getDbPath();
|
|
719
|
-
}
|
|
720
|
-
// Fallback: try to get path from adapter properties
|
|
721
|
-
if (dbAdapter.dbPath) {
|
|
722
|
-
return dbAdapter.dbPath;
|
|
723
|
-
}
|
|
724
|
-
return `${dbAdapter.constructor.name} (path unavailable)`;
|
|
276
|
+
return handle.dbPath;
|
|
725
277
|
}
|
|
726
278
|
// Note: Removed auto-registered SIGINT/SIGTERM handlers that called process.exit(0)
|
|
727
279
|
// This was causing issues with host cleanup in parent processes.
|
|
@@ -737,54 +289,20 @@ function getDbPath() {
|
|
|
737
289
|
*/
|
|
738
290
|
function resetDBState(options = {}) {
|
|
739
291
|
const { disconnect = true } = options;
|
|
740
|
-
if (disconnect &&
|
|
292
|
+
if (disconnect && handle) {
|
|
741
293
|
try {
|
|
742
|
-
|
|
294
|
+
handle.adapter.disconnect();
|
|
743
295
|
}
|
|
744
296
|
catch {
|
|
745
297
|
// Ignore disconnect errors during reset
|
|
746
298
|
}
|
|
747
299
|
}
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
isInitialized = false;
|
|
751
|
-
initializingPromise = null;
|
|
300
|
+
handle = null;
|
|
301
|
+
openingPromise = null;
|
|
752
302
|
}
|
|
753
303
|
/**
|
|
754
304
|
* Check if running in test mode
|
|
755
305
|
*
|
|
756
306
|
* Returns true if MAMA_TEST_MODE, VITEST, or NODE_ENV=test env vars are set
|
|
757
307
|
*/
|
|
758
|
-
function isTestMode() {
|
|
759
|
-
return Boolean(process.env.MAMA_TEST_MODE || process.env.VITEST || process.env.NODE_ENV === 'test');
|
|
760
|
-
}
|
|
761
|
-
/**
|
|
762
|
-
* FTS5 keyword search on decisions table.
|
|
763
|
-
* Returns matching decision IDs with BM25 rank scores.
|
|
764
|
-
*/
|
|
765
|
-
async function fts5Search(query, limit = 10) {
|
|
766
|
-
const adapter = getAdapter();
|
|
767
|
-
// Check if FTS5 table exists (swallow errors — table may not exist yet)
|
|
768
|
-
let tableCheck;
|
|
769
|
-
try {
|
|
770
|
-
tableCheck = adapter
|
|
771
|
-
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='decisions_fts'")
|
|
772
|
-
.get();
|
|
773
|
-
}
|
|
774
|
-
catch {
|
|
775
|
-
return [];
|
|
776
|
-
}
|
|
777
|
-
if (!tableCheck)
|
|
778
|
-
return [];
|
|
779
|
-
// Query execution — let errors propagate to the caller
|
|
780
|
-
const stmt = adapter.prepare(`
|
|
781
|
-
SELECT d.id, rank
|
|
782
|
-
FROM decisions_fts
|
|
783
|
-
JOIN decisions d ON decisions_fts.rowid = d.rowid
|
|
784
|
-
WHERE decisions_fts MATCH ?
|
|
785
|
-
ORDER BY rank
|
|
786
|
-
LIMIT ?
|
|
787
|
-
`);
|
|
788
|
-
return stmt.all(query, limit);
|
|
789
|
-
}
|
|
790
308
|
//# sourceMappingURL=db-manager.js.map
|