@jungjaehoon/mama-core 2.4.1 → 4.0.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/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 +1968 -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/commitments.d.ts +188 -0
- package/dist/knowledge/commitments.js +370 -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/judgments.d.ts +118 -0
- package/dist/knowledge/judgments.js +808 -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 +155 -0
- package/dist/runtime/drivers/claude-cli-wrapper.js +392 -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 +424 -0
- package/dist/runtime/drivers/persistent-cli-process.js +1543 -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
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectSourceLocatorKind = detectSourceLocatorKind;
|
|
4
|
-
function detectSourceLocatorKind(locator) {
|
|
5
|
-
if (typeof locator !== 'string' || locator.trim().length === 0) {
|
|
6
|
-
return 'unknown';
|
|
7
|
-
}
|
|
8
|
-
const trimmed = locator.trim();
|
|
9
|
-
const normalized = trimmed.toLowerCase();
|
|
10
|
-
if (normalized.startsWith('http://') || normalized.startsWith('https://')) {
|
|
11
|
-
return 'url';
|
|
12
|
-
}
|
|
13
|
-
if (normalized.startsWith('file://')) {
|
|
14
|
-
return 'file';
|
|
15
|
-
}
|
|
16
|
-
if (normalized.startsWith('drive://') ||
|
|
17
|
-
normalized.startsWith('gmail://') ||
|
|
18
|
-
normalized.startsWith('calendar://') ||
|
|
19
|
-
normalized.startsWith('sheets://')) {
|
|
20
|
-
return 'connector';
|
|
21
|
-
}
|
|
22
|
-
if (normalized.endsWith('.db') ||
|
|
23
|
-
normalized.includes('/raw.db') ||
|
|
24
|
-
normalized.includes('\\raw.db')) {
|
|
25
|
-
return 'db';
|
|
26
|
-
}
|
|
27
|
-
if (trimmed.startsWith('/') || trimmed.startsWith('~/') || /^[A-Za-z]:[\\/]/.test(trimmed)) {
|
|
28
|
-
return 'file';
|
|
29
|
-
}
|
|
30
|
-
return 'unknown';
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=source-locator.js.map
|
package/dist/entities/store.d.ts
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { type EntityAlias, type EntityNode, type EntityObservation } from './types.js';
|
|
2
|
-
export interface EntityStoreAdapter {
|
|
3
|
-
prepare(sql: string): {
|
|
4
|
-
run(...params: unknown[]): {
|
|
5
|
-
changes: number;
|
|
6
|
-
lastInsertRowid: number | bigint;
|
|
7
|
-
};
|
|
8
|
-
get(...params: unknown[]): unknown;
|
|
9
|
-
all(...params: unknown[]): unknown[];
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
export declare class EntityMergeError extends Error {
|
|
13
|
-
readonly code: string;
|
|
14
|
-
constructor(code: string, message: string);
|
|
15
|
-
}
|
|
16
|
-
declare const OBSERVATION_CONTEXT_KEY_COLUMNS: readonly ["workspace_context_key", "channel_context_key", "thread_context_key", "actor_context_key"];
|
|
17
|
-
type CreateEntityNodeInput = Omit<EntityNode, 'created_at' | 'updated_at'>;
|
|
18
|
-
type AttachEntityAliasInput = Omit<EntityAlias, 'created_at'>;
|
|
19
|
-
type ObservationContextKeyColumn = (typeof OBSERVATION_CONTEXT_KEY_COLUMNS)[number];
|
|
20
|
-
type UpsertEntityObservationInput = Omit<EntityObservation, 'created_at'> & Partial<Record<ObservationContextKeyColumn, string | null>>;
|
|
21
|
-
export interface UpsertEntityObservationResult {
|
|
22
|
-
id: string;
|
|
23
|
-
created: boolean;
|
|
24
|
-
}
|
|
25
|
-
export declare function clearEntityTableColumnCache(adapter: EntityStoreAdapter): void;
|
|
26
|
-
export declare function parseObservationRow(row: Record<string, unknown>): EntityObservation;
|
|
27
|
-
export declare function createEntityNode(input: CreateEntityNodeInput): Promise<EntityNode>;
|
|
28
|
-
export declare function getEntityNode(id: string, adapter?: EntityStoreAdapter): EntityNode | null;
|
|
29
|
-
export declare function attachEntityAlias(input: AttachEntityAliasInput): Promise<EntityAlias>;
|
|
30
|
-
export declare function listEntityAliases(entityId: string, adapter?: EntityStoreAdapter): EntityAlias[];
|
|
31
|
-
export declare function upsertEntityObservation(input: UpsertEntityObservationInput): Promise<EntityObservation>;
|
|
32
|
-
export declare function upsertEntityObservations(inputs: UpsertEntityObservationInput[]): Promise<UpsertEntityObservationResult[]>;
|
|
33
|
-
/**
|
|
34
|
-
* Walks the `entity_nodes.merged_into` chain from the given id and returns the
|
|
35
|
-
* terminal (unmerged) entity id. Detects cycles and caps depth. Read-only.
|
|
36
|
-
*
|
|
37
|
-
* Matches the read-time chain-walking approach described in the canonical
|
|
38
|
-
* entity ontology implementation plan.
|
|
39
|
-
*/
|
|
40
|
-
export declare function resolveCanonicalEntityId(adapter: EntityStoreAdapter, id: string): string;
|
|
41
|
-
export interface MergeEntityNodesInput {
|
|
42
|
-
adapter: EntityStoreAdapter;
|
|
43
|
-
source_id: string;
|
|
44
|
-
target_id: string;
|
|
45
|
-
actor_type: 'system' | 'user' | 'agent';
|
|
46
|
-
actor_id: string;
|
|
47
|
-
reason: string;
|
|
48
|
-
candidate_id: string | null;
|
|
49
|
-
evidence_json: string;
|
|
50
|
-
}
|
|
51
|
-
export interface MergeEntityNodesResult {
|
|
52
|
-
merge_action_id: string;
|
|
53
|
-
timeline_event_id: string;
|
|
54
|
-
merged_at: number;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Marks `source_id` as merged into `target_id`, emits a timeline event, and
|
|
58
|
-
* inserts the entity_merge_actions audit row with both entity IDs populated.
|
|
59
|
-
*
|
|
60
|
-
* Intentionally NOT wrapped in its own transaction — the caller is expected
|
|
61
|
-
* to wrap the call in `adapter.transaction(...)` so the candidate status
|
|
62
|
-
* update and this merge land atomically (Policy B1, hard transaction).
|
|
63
|
-
*
|
|
64
|
-
* Validates: source != target, both exist, both active/unmerged, same kind,
|
|
65
|
-
* same scope. Throws `EntityMergeError` with a stable `code` on any violation.
|
|
66
|
-
*/
|
|
67
|
-
export declare function mergeEntityNodes(input: MergeEntityNodesInput): MergeEntityNodesResult;
|
|
68
|
-
export {};
|
|
69
|
-
//# sourceMappingURL=store.d.ts.map
|
package/dist/entities/store.js
DELETED
|
@@ -1,544 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EntityMergeError = void 0;
|
|
4
|
-
exports.clearEntityTableColumnCache = clearEntityTableColumnCache;
|
|
5
|
-
exports.parseObservationRow = parseObservationRow;
|
|
6
|
-
exports.createEntityNode = createEntityNode;
|
|
7
|
-
exports.getEntityNode = getEntityNode;
|
|
8
|
-
exports.attachEntityAlias = attachEntityAlias;
|
|
9
|
-
exports.listEntityAliases = listEntityAliases;
|
|
10
|
-
exports.upsertEntityObservation = upsertEntityObservation;
|
|
11
|
-
exports.upsertEntityObservations = upsertEntityObservations;
|
|
12
|
-
exports.resolveCanonicalEntityId = resolveCanonicalEntityId;
|
|
13
|
-
exports.mergeEntityNodes = mergeEntityNodes;
|
|
14
|
-
const node_crypto_1 = require("node:crypto");
|
|
15
|
-
const db_manager_js_1 = require("../db-manager.js");
|
|
16
|
-
const types_js_1 = require("./types.js");
|
|
17
|
-
class EntityMergeError extends Error {
|
|
18
|
-
code;
|
|
19
|
-
constructor(code, message) {
|
|
20
|
-
super(message);
|
|
21
|
-
this.code = code;
|
|
22
|
-
this.name = 'EntityMergeError';
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
exports.EntityMergeError = EntityMergeError;
|
|
26
|
-
const MAX_MERGE_CHAIN_DEPTH = 8;
|
|
27
|
-
const OBSERVATION_CONTEXT_KEY_COLUMNS = [
|
|
28
|
-
'workspace_context_key',
|
|
29
|
-
'channel_context_key',
|
|
30
|
-
'thread_context_key',
|
|
31
|
-
'actor_context_key',
|
|
32
|
-
];
|
|
33
|
-
const tableColumnCache = new WeakMap();
|
|
34
|
-
function now() {
|
|
35
|
-
return Date.now();
|
|
36
|
-
}
|
|
37
|
-
function normalizeSourceLocator(value) {
|
|
38
|
-
// Write empty-string as the null sentinel so SQLite UNIQUE can collapse null-like locators; parseObservationRow maps it back to null on read.
|
|
39
|
-
return value ?? '';
|
|
40
|
-
}
|
|
41
|
-
function normalizeContextKey(value) {
|
|
42
|
-
return value ?? '';
|
|
43
|
-
}
|
|
44
|
-
function sourceLocatorForInput(input) {
|
|
45
|
-
return normalizeSourceLocator(input.source_locator);
|
|
46
|
-
}
|
|
47
|
-
function channelContextKey(input) {
|
|
48
|
-
if (input.channel_context_key !== undefined) {
|
|
49
|
-
return normalizeContextKey(input.channel_context_key);
|
|
50
|
-
}
|
|
51
|
-
if (input.scope_kind !== 'channel' || !input.scope_id) {
|
|
52
|
-
return '';
|
|
53
|
-
}
|
|
54
|
-
return input.scope_id.startsWith(`${input.source_connector}:`)
|
|
55
|
-
? input.scope_id
|
|
56
|
-
: `${input.source_connector}:${input.scope_id}`;
|
|
57
|
-
}
|
|
58
|
-
function actorContextKey(input) {
|
|
59
|
-
if (input.actor_context_key !== undefined) {
|
|
60
|
-
return normalizeContextKey(input.actor_context_key);
|
|
61
|
-
}
|
|
62
|
-
if (input.observation_type === 'author') {
|
|
63
|
-
return input.surface_form;
|
|
64
|
-
}
|
|
65
|
-
return input.related_surface_forms.find((value) => value.trim().length > 0) ?? '';
|
|
66
|
-
}
|
|
67
|
-
function observationContextKeys(input) {
|
|
68
|
-
return {
|
|
69
|
-
workspace_context_key: normalizeContextKey(input.workspace_context_key ?? input.source_connector),
|
|
70
|
-
channel_context_key: channelContextKey(input),
|
|
71
|
-
thread_context_key: normalizeContextKey(input.thread_context_key),
|
|
72
|
-
actor_context_key: actorContextKey(input),
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
function tableColumnNames(adapter, tableName) {
|
|
76
|
-
let adapterCache = tableColumnCache.get(adapter);
|
|
77
|
-
if (!adapterCache) {
|
|
78
|
-
adapterCache = new Map();
|
|
79
|
-
tableColumnCache.set(adapter, adapterCache);
|
|
80
|
-
}
|
|
81
|
-
const cached = adapterCache.get(tableName);
|
|
82
|
-
if (cached) {
|
|
83
|
-
return cached;
|
|
84
|
-
}
|
|
85
|
-
const rows = adapter.prepare(`PRAGMA table_info(${tableName})`).all();
|
|
86
|
-
const columns = new Set(rows.map((row) => row.name));
|
|
87
|
-
adapterCache.set(tableName, columns);
|
|
88
|
-
return columns;
|
|
89
|
-
}
|
|
90
|
-
function clearEntityTableColumnCache(adapter) {
|
|
91
|
-
tableColumnCache.delete(adapter);
|
|
92
|
-
}
|
|
93
|
-
function requireStringField(row, field) {
|
|
94
|
-
if (typeof row[field] !== 'string' || row[field].length === 0) {
|
|
95
|
-
throw new Error(`Invalid entity observation row: ${field} must be a non-empty string`);
|
|
96
|
-
}
|
|
97
|
-
return row[field];
|
|
98
|
-
}
|
|
99
|
-
function optionalStringField(row, field) {
|
|
100
|
-
if (!Object.prototype.hasOwnProperty.call(row, field)) {
|
|
101
|
-
throw new Error(`Invalid entity observation row: ${field} must be present`);
|
|
102
|
-
}
|
|
103
|
-
if (row[field] === null) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
if (typeof row[field] !== 'string') {
|
|
107
|
-
throw new Error(`Invalid entity observation row: ${field} must be a string or null`);
|
|
108
|
-
}
|
|
109
|
-
return row[field];
|
|
110
|
-
}
|
|
111
|
-
function optionalStringFieldIfPresent(row, field) {
|
|
112
|
-
if (!Object.prototype.hasOwnProperty.call(row, field)) {
|
|
113
|
-
return undefined;
|
|
114
|
-
}
|
|
115
|
-
if (row[field] === null) {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
if (typeof row[field] !== 'string') {
|
|
119
|
-
throw new Error(`Invalid entity observation row: ${field} must be a string or null`);
|
|
120
|
-
}
|
|
121
|
-
return row[field];
|
|
122
|
-
}
|
|
123
|
-
function optionalNumberField(row, field) {
|
|
124
|
-
if (!Object.prototype.hasOwnProperty.call(row, field)) {
|
|
125
|
-
throw new Error(`Invalid entity observation row: ${field} must be present`);
|
|
126
|
-
}
|
|
127
|
-
if (row[field] === null) {
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
if (typeof row[field] !== 'number') {
|
|
131
|
-
throw new Error(`Invalid entity observation row: ${field} must be a number or null`);
|
|
132
|
-
}
|
|
133
|
-
return row[field];
|
|
134
|
-
}
|
|
135
|
-
function parseObservationRow(row) {
|
|
136
|
-
const id = requireStringField(row, 'id');
|
|
137
|
-
const observationType = requireStringField(row, 'observation_type');
|
|
138
|
-
if (!types_js_1.ENTITY_OBSERVATION_TYPES.includes(observationType)) {
|
|
139
|
-
throw new Error(`Invalid entity observation row: observation_type=${observationType}`);
|
|
140
|
-
}
|
|
141
|
-
const entityKindHint = optionalStringField(row, 'entity_kind_hint');
|
|
142
|
-
if (entityKindHint !== null &&
|
|
143
|
-
!types_js_1.ENTITY_KINDS.includes(entityKindHint)) {
|
|
144
|
-
throw new Error(`Invalid entity observation row: entity_kind_hint=${entityKindHint}`);
|
|
145
|
-
}
|
|
146
|
-
const scopeKind = optionalStringField(row, 'scope_kind');
|
|
147
|
-
if (scopeKind === null) {
|
|
148
|
-
throw new Error('Invalid entity observation row: scope_kind must not be null');
|
|
149
|
-
}
|
|
150
|
-
if (!types_js_1.ENTITY_SCOPE_KINDS.includes(scopeKind)) {
|
|
151
|
-
throw new Error(`Invalid entity observation row: scope_kind=${scopeKind}`);
|
|
152
|
-
}
|
|
153
|
-
const createdAt = row.created_at;
|
|
154
|
-
if (typeof createdAt !== 'number') {
|
|
155
|
-
throw new Error('Invalid entity observation row: created_at must be a number');
|
|
156
|
-
}
|
|
157
|
-
let relatedSurfaceForms = [];
|
|
158
|
-
if (typeof row.related_surface_forms === 'string') {
|
|
159
|
-
try {
|
|
160
|
-
const parsed = JSON.parse(row.related_surface_forms);
|
|
161
|
-
if (!Array.isArray(parsed) || parsed.some((value) => typeof value !== 'string')) {
|
|
162
|
-
throw new Error('parsed value is not a string[]');
|
|
163
|
-
}
|
|
164
|
-
relatedSurfaceForms = parsed;
|
|
165
|
-
}
|
|
166
|
-
catch (error) {
|
|
167
|
-
throw new Error(`Invalid entity observation row: related_surface_forms must be valid JSON string[] (${error instanceof Error ? error.message : String(error)})`);
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
else if (row.related_surface_forms !== undefined && row.related_surface_forms !== null) {
|
|
171
|
-
throw new Error('Invalid entity observation row: related_surface_forms must be a JSON string or null');
|
|
172
|
-
}
|
|
173
|
-
const sourceLocator = optionalStringFieldIfPresent(row, 'source_locator');
|
|
174
|
-
if (sourceLocator === undefined) {
|
|
175
|
-
throw new Error('Invalid entity observation row: source_locator must be present');
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
id,
|
|
179
|
-
observation_type: observationType,
|
|
180
|
-
entity_kind_hint: entityKindHint,
|
|
181
|
-
surface_form: requireStringField(row, 'surface_form'),
|
|
182
|
-
normalized_form: requireStringField(row, 'normalized_form'),
|
|
183
|
-
lang: optionalStringField(row, 'lang'),
|
|
184
|
-
script: optionalStringField(row, 'script'),
|
|
185
|
-
context_summary: optionalStringField(row, 'context_summary'),
|
|
186
|
-
related_surface_forms: relatedSurfaceForms,
|
|
187
|
-
timestamp_observed: optionalNumberField(row, 'timestamp_observed'),
|
|
188
|
-
scope_kind: scopeKind,
|
|
189
|
-
scope_id: optionalStringField(row, 'scope_id'),
|
|
190
|
-
extractor_version: requireStringField(row, 'extractor_version'),
|
|
191
|
-
embedding_model_version: optionalStringField(row, 'embedding_model_version'),
|
|
192
|
-
source_connector: requireStringField(row, 'source_connector'),
|
|
193
|
-
source_locator: sourceLocator && sourceLocator.length > 0 ? sourceLocator : null,
|
|
194
|
-
source_raw_record_id: requireStringField(row, 'source_raw_record_id'),
|
|
195
|
-
workspace_context_key: optionalStringFieldIfPresent(row, 'workspace_context_key'),
|
|
196
|
-
channel_context_key: optionalStringFieldIfPresent(row, 'channel_context_key'),
|
|
197
|
-
thread_context_key: optionalStringFieldIfPresent(row, 'thread_context_key'),
|
|
198
|
-
actor_context_key: optionalStringFieldIfPresent(row, 'actor_context_key'),
|
|
199
|
-
created_at: createdAt,
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
async function createEntityNode(input) {
|
|
203
|
-
await (0, db_manager_js_1.initDB)();
|
|
204
|
-
const adapter = (0, db_manager_js_1.getAdapter)();
|
|
205
|
-
const createdAt = now();
|
|
206
|
-
adapter
|
|
207
|
-
.prepare(`
|
|
208
|
-
INSERT INTO entity_nodes (
|
|
209
|
-
id, kind, preferred_label, status, scope_kind, scope_id, merged_into, created_at, updated_at
|
|
210
|
-
)
|
|
211
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
212
|
-
`)
|
|
213
|
-
.run(input.id, input.kind, input.preferred_label, input.status, input.scope_kind, input.scope_id, input.merged_into, createdAt, createdAt);
|
|
214
|
-
return {
|
|
215
|
-
...input,
|
|
216
|
-
created_at: createdAt,
|
|
217
|
-
updated_at: createdAt,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
function getEntityNode(id, adapter = (0, db_manager_js_1.getAdapter)()) {
|
|
221
|
-
const row = adapter.prepare('SELECT * FROM entity_nodes WHERE id = ?').get(id);
|
|
222
|
-
if (!row) {
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
return {
|
|
226
|
-
id: String(row.id),
|
|
227
|
-
kind: row.kind,
|
|
228
|
-
preferred_label: String(row.preferred_label),
|
|
229
|
-
status: row.status,
|
|
230
|
-
scope_kind: typeof row.scope_kind === 'string' ? row.scope_kind : null,
|
|
231
|
-
scope_id: typeof row.scope_id === 'string' ? row.scope_id : null,
|
|
232
|
-
merged_into: typeof row.merged_into === 'string' ? row.merged_into : null,
|
|
233
|
-
created_at: Number(row.created_at),
|
|
234
|
-
updated_at: Number(row.updated_at),
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
async function attachEntityAlias(input) {
|
|
238
|
-
await (0, db_manager_js_1.initDB)();
|
|
239
|
-
const adapter = (0, db_manager_js_1.getAdapter)();
|
|
240
|
-
const createdAt = now();
|
|
241
|
-
adapter
|
|
242
|
-
.prepare(`
|
|
243
|
-
INSERT INTO entity_aliases (
|
|
244
|
-
id, entity_id, label, normalized_label, lang, script, label_type,
|
|
245
|
-
source_type, source_ref, confidence, status, created_at
|
|
246
|
-
)
|
|
247
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
248
|
-
`)
|
|
249
|
-
.run(input.id, input.entity_id, input.label, input.normalized_label, input.lang, input.script, input.label_type, input.source_type, input.source_ref, input.confidence, input.status, createdAt);
|
|
250
|
-
return {
|
|
251
|
-
...input,
|
|
252
|
-
created_at: createdAt,
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
function listEntityAliases(entityId, adapter = (0, db_manager_js_1.getAdapter)()) {
|
|
256
|
-
const rows = adapter
|
|
257
|
-
.prepare('SELECT * FROM entity_aliases WHERE entity_id = ? ORDER BY created_at ASC')
|
|
258
|
-
.all(entityId);
|
|
259
|
-
return rows.map((row) => ({
|
|
260
|
-
id: String(row.id),
|
|
261
|
-
entity_id: String(row.entity_id),
|
|
262
|
-
label: String(row.label),
|
|
263
|
-
normalized_label: String(row.normalized_label),
|
|
264
|
-
lang: typeof row.lang === 'string' ? row.lang : null,
|
|
265
|
-
script: typeof row.script === 'string' ? row.script : null,
|
|
266
|
-
label_type: row.label_type,
|
|
267
|
-
source_type: String(row.source_type),
|
|
268
|
-
source_ref: typeof row.source_ref === 'string' ? row.source_ref : null,
|
|
269
|
-
confidence: typeof row.confidence === 'number' ? row.confidence : null,
|
|
270
|
-
status: row.status,
|
|
271
|
-
created_at: Number(row.created_at),
|
|
272
|
-
}));
|
|
273
|
-
}
|
|
274
|
-
function observationContextColumns(columns) {
|
|
275
|
-
return OBSERVATION_CONTEXT_KEY_COLUMNS.filter((column) => columns.has(column));
|
|
276
|
-
}
|
|
277
|
-
function observationInsertValues(input, normalizedSourceLocator, contextColumns, contextKeys, createdAt) {
|
|
278
|
-
const columns = [
|
|
279
|
-
'id',
|
|
280
|
-
'observation_type',
|
|
281
|
-
'entity_kind_hint',
|
|
282
|
-
'surface_form',
|
|
283
|
-
'normalized_form',
|
|
284
|
-
'lang',
|
|
285
|
-
'script',
|
|
286
|
-
'context_summary',
|
|
287
|
-
'related_surface_forms',
|
|
288
|
-
'timestamp_observed',
|
|
289
|
-
'scope_kind',
|
|
290
|
-
'scope_id',
|
|
291
|
-
'extractor_version',
|
|
292
|
-
'embedding_model_version',
|
|
293
|
-
'source_connector',
|
|
294
|
-
'source_locator',
|
|
295
|
-
'source_raw_record_id',
|
|
296
|
-
...contextColumns,
|
|
297
|
-
'created_at',
|
|
298
|
-
];
|
|
299
|
-
const values = [
|
|
300
|
-
input.id,
|
|
301
|
-
input.observation_type,
|
|
302
|
-
input.entity_kind_hint,
|
|
303
|
-
input.surface_form,
|
|
304
|
-
input.normalized_form,
|
|
305
|
-
input.lang,
|
|
306
|
-
input.script,
|
|
307
|
-
input.context_summary,
|
|
308
|
-
JSON.stringify(input.related_surface_forms),
|
|
309
|
-
input.timestamp_observed,
|
|
310
|
-
input.scope_kind,
|
|
311
|
-
input.scope_id,
|
|
312
|
-
input.extractor_version,
|
|
313
|
-
input.embedding_model_version,
|
|
314
|
-
input.source_connector,
|
|
315
|
-
normalizedSourceLocator,
|
|
316
|
-
input.source_raw_record_id,
|
|
317
|
-
...contextColumns.map((column) => contextKeys[column]),
|
|
318
|
-
createdAt,
|
|
319
|
-
];
|
|
320
|
-
return { columns, values };
|
|
321
|
-
}
|
|
322
|
-
function findExistingObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys) {
|
|
323
|
-
const conditions = [
|
|
324
|
-
'source_connector = ?',
|
|
325
|
-
'source_locator = ?',
|
|
326
|
-
'source_raw_record_id = ?',
|
|
327
|
-
'observation_type = ?',
|
|
328
|
-
...contextColumns.map((column) => `COALESCE(${column}, '') = ?`),
|
|
329
|
-
];
|
|
330
|
-
const params = [
|
|
331
|
-
input.source_connector,
|
|
332
|
-
normalizedSourceLocator,
|
|
333
|
-
input.source_raw_record_id,
|
|
334
|
-
input.observation_type,
|
|
335
|
-
...contextColumns.map((column) => contextKeys[column]),
|
|
336
|
-
];
|
|
337
|
-
return adapter
|
|
338
|
-
.prepare(`
|
|
339
|
-
SELECT id FROM entity_observations
|
|
340
|
-
WHERE ${conditions.join(' AND ')}
|
|
341
|
-
ORDER BY created_at ASC, id ASC
|
|
342
|
-
LIMIT 1
|
|
343
|
-
`)
|
|
344
|
-
.get(...params);
|
|
345
|
-
}
|
|
346
|
-
function insertObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys, createdAt) {
|
|
347
|
-
const insert = observationInsertValues(input, normalizedSourceLocator, contextColumns, contextKeys, createdAt);
|
|
348
|
-
const placeholders = insert.columns.map(() => '?').join(', ');
|
|
349
|
-
adapter
|
|
350
|
-
.prepare(`
|
|
351
|
-
INSERT INTO entity_observations (${insert.columns.join(', ')})
|
|
352
|
-
VALUES (${placeholders})
|
|
353
|
-
`)
|
|
354
|
-
.run(...insert.values);
|
|
355
|
-
}
|
|
356
|
-
function updateObservation(adapter, id, input, normalizedSourceLocator, contextColumns, contextKeys) {
|
|
357
|
-
const assignments = [
|
|
358
|
-
'entity_kind_hint = ?',
|
|
359
|
-
'surface_form = ?',
|
|
360
|
-
'normalized_form = ?',
|
|
361
|
-
'lang = ?',
|
|
362
|
-
'script = ?',
|
|
363
|
-
'context_summary = ?',
|
|
364
|
-
'related_surface_forms = ?',
|
|
365
|
-
'timestamp_observed = ?',
|
|
366
|
-
'scope_kind = ?',
|
|
367
|
-
'scope_id = ?',
|
|
368
|
-
'extractor_version = ?',
|
|
369
|
-
'embedding_model_version = ?',
|
|
370
|
-
'source_locator = ?',
|
|
371
|
-
...contextColumns.map((column) => `${column} = ?`),
|
|
372
|
-
];
|
|
373
|
-
const values = [
|
|
374
|
-
input.entity_kind_hint,
|
|
375
|
-
input.surface_form,
|
|
376
|
-
input.normalized_form,
|
|
377
|
-
input.lang,
|
|
378
|
-
input.script,
|
|
379
|
-
input.context_summary,
|
|
380
|
-
JSON.stringify(input.related_surface_forms),
|
|
381
|
-
input.timestamp_observed,
|
|
382
|
-
input.scope_kind,
|
|
383
|
-
input.scope_id,
|
|
384
|
-
input.extractor_version,
|
|
385
|
-
input.embedding_model_version,
|
|
386
|
-
normalizedSourceLocator,
|
|
387
|
-
...contextColumns.map((column) => contextKeys[column]),
|
|
388
|
-
id,
|
|
389
|
-
];
|
|
390
|
-
adapter
|
|
391
|
-
.prepare(`
|
|
392
|
-
UPDATE entity_observations
|
|
393
|
-
SET ${assignments.join(', ')}
|
|
394
|
-
WHERE id = ?
|
|
395
|
-
`)
|
|
396
|
-
.run(...values);
|
|
397
|
-
}
|
|
398
|
-
function saveObservation(adapter, input) {
|
|
399
|
-
const columns = tableColumnNames(adapter, 'entity_observations');
|
|
400
|
-
const contextColumns = observationContextColumns(columns);
|
|
401
|
-
const contextKeys = observationContextKeys(input);
|
|
402
|
-
const normalizedSourceLocator = sourceLocatorForInput(input);
|
|
403
|
-
const existing = findExistingObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys);
|
|
404
|
-
if (existing) {
|
|
405
|
-
const id = requireStringField(existing, 'id');
|
|
406
|
-
updateObservation(adapter, id, input, normalizedSourceLocator, contextColumns, contextKeys);
|
|
407
|
-
return { id, created: false };
|
|
408
|
-
}
|
|
409
|
-
insertObservation(adapter, input, normalizedSourceLocator, contextColumns, contextKeys, now());
|
|
410
|
-
return { id: input.id, created: true };
|
|
411
|
-
}
|
|
412
|
-
async function upsertEntityObservation(input) {
|
|
413
|
-
await (0, db_manager_js_1.initDB)();
|
|
414
|
-
const adapter = (0, db_manager_js_1.getAdapter)();
|
|
415
|
-
const result = saveObservation(adapter, input);
|
|
416
|
-
const saved = adapter.prepare('SELECT * FROM entity_observations WHERE id = ?').get(result.id);
|
|
417
|
-
if (!saved) {
|
|
418
|
-
throw new Error(`Failed to load saved entity observation ${result.id}`);
|
|
419
|
-
}
|
|
420
|
-
return parseObservationRow(saved);
|
|
421
|
-
}
|
|
422
|
-
async function upsertEntityObservations(inputs) {
|
|
423
|
-
await (0, db_manager_js_1.initDB)();
|
|
424
|
-
const adapter = (0, db_manager_js_1.getAdapter)();
|
|
425
|
-
const observations = [];
|
|
426
|
-
const upsertOne = (input) => {
|
|
427
|
-
observations.push(saveObservation(adapter, input));
|
|
428
|
-
};
|
|
429
|
-
if ('transaction' in adapter && typeof adapter.transaction === 'function') {
|
|
430
|
-
const txResult = adapter.transaction(() => {
|
|
431
|
-
for (const input of inputs) {
|
|
432
|
-
upsertOne(input);
|
|
433
|
-
}
|
|
434
|
-
});
|
|
435
|
-
if (typeof txResult === 'function') {
|
|
436
|
-
txResult();
|
|
437
|
-
}
|
|
438
|
-
return observations;
|
|
439
|
-
}
|
|
440
|
-
for (const input of inputs) {
|
|
441
|
-
upsertOne(input);
|
|
442
|
-
}
|
|
443
|
-
return observations;
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* Walks the `entity_nodes.merged_into` chain from the given id and returns the
|
|
447
|
-
* terminal (unmerged) entity id. Detects cycles and caps depth. Read-only.
|
|
448
|
-
*
|
|
449
|
-
* Matches the read-time chain-walking approach described in the canonical
|
|
450
|
-
* entity ontology implementation plan.
|
|
451
|
-
*/
|
|
452
|
-
function resolveCanonicalEntityId(adapter, id) {
|
|
453
|
-
const seen = new Set();
|
|
454
|
-
let current = id;
|
|
455
|
-
for (let depth = 0; depth < MAX_MERGE_CHAIN_DEPTH; depth++) {
|
|
456
|
-
if (seen.has(current)) {
|
|
457
|
-
throw new EntityMergeError('entity.merge_chain_cycle', `Cycle detected in merged_into chain starting at ${id}`);
|
|
458
|
-
}
|
|
459
|
-
seen.add(current);
|
|
460
|
-
const row = adapter
|
|
461
|
-
.prepare('SELECT merged_into FROM entity_nodes WHERE id = ?')
|
|
462
|
-
.get(current);
|
|
463
|
-
if (!row) {
|
|
464
|
-
throw new EntityMergeError('entity.node_not_found', `Entity node ${current} not found while resolving canonical id for ${id}`);
|
|
465
|
-
}
|
|
466
|
-
if (!row.merged_into) {
|
|
467
|
-
return current;
|
|
468
|
-
}
|
|
469
|
-
current = row.merged_into;
|
|
470
|
-
}
|
|
471
|
-
throw new EntityMergeError('entity.merge_chain_too_deep', `merged_into chain exceeds depth ${MAX_MERGE_CHAIN_DEPTH} starting at ${id}`);
|
|
472
|
-
}
|
|
473
|
-
/**
|
|
474
|
-
* Marks `source_id` as merged into `target_id`, emits a timeline event, and
|
|
475
|
-
* inserts the entity_merge_actions audit row with both entity IDs populated.
|
|
476
|
-
*
|
|
477
|
-
* Intentionally NOT wrapped in its own transaction — the caller is expected
|
|
478
|
-
* to wrap the call in `adapter.transaction(...)` so the candidate status
|
|
479
|
-
* update and this merge land atomically (Policy B1, hard transaction).
|
|
480
|
-
*
|
|
481
|
-
* Validates: source != target, both exist, both active/unmerged, same kind,
|
|
482
|
-
* same scope. Throws `EntityMergeError` with a stable `code` on any violation.
|
|
483
|
-
*/
|
|
484
|
-
function mergeEntityNodes(input) {
|
|
485
|
-
const { adapter, source_id, target_id, actor_type, actor_id, reason, candidate_id, evidence_json, } = input;
|
|
486
|
-
if (!source_id || !target_id) {
|
|
487
|
-
throw new EntityMergeError('entity.merge_invalid_args', 'source_id and target_id are required');
|
|
488
|
-
}
|
|
489
|
-
if (source_id === target_id) {
|
|
490
|
-
throw new EntityMergeError('entity.merge_self', 'Cannot merge an entity into itself');
|
|
491
|
-
}
|
|
492
|
-
const source = adapter.prepare('SELECT * FROM entity_nodes WHERE id = ?').get(source_id);
|
|
493
|
-
if (!source) {
|
|
494
|
-
throw new EntityMergeError('entity.merge_source_not_found', `Source entity ${source_id} not found`);
|
|
495
|
-
}
|
|
496
|
-
const target = adapter.prepare('SELECT * FROM entity_nodes WHERE id = ?').get(target_id);
|
|
497
|
-
if (!target) {
|
|
498
|
-
throw new EntityMergeError('entity.merge_target_not_found', `Target entity ${target_id} not found`);
|
|
499
|
-
}
|
|
500
|
-
if (source.status === 'merged' || source.merged_into) {
|
|
501
|
-
throw new EntityMergeError('entity.merge_source_already_merged', `Source entity ${source_id} is already merged`);
|
|
502
|
-
}
|
|
503
|
-
if (target.status === 'merged' || target.merged_into) {
|
|
504
|
-
throw new EntityMergeError('entity.merge_target_already_merged', `Target entity ${target_id} is already merged`);
|
|
505
|
-
}
|
|
506
|
-
if (source.status === 'archived' || target.status === 'archived') {
|
|
507
|
-
throw new EntityMergeError('entity.merge_archived', 'Cannot merge archived entities');
|
|
508
|
-
}
|
|
509
|
-
if (source.kind !== target.kind) {
|
|
510
|
-
throw new EntityMergeError('entity.merge_kind_mismatch', `Cannot merge ${source.kind} into ${target.kind}`);
|
|
511
|
-
}
|
|
512
|
-
if (source.scope_kind !== target.scope_kind || source.scope_id !== target.scope_id) {
|
|
513
|
-
throw new EntityMergeError('entity.merge_scope_mismatch', `Cannot merge across scopes: ${source.scope_kind}/${source.scope_id ?? 'null'} vs ${target.scope_kind}/${target.scope_id ?? 'null'}`);
|
|
514
|
-
}
|
|
515
|
-
const mergedAt = now();
|
|
516
|
-
const mergeActionId = `mact_${(0, node_crypto_1.randomUUID)()}`;
|
|
517
|
-
const timelineEventId = `et_${(0, node_crypto_1.randomUUID)()}`;
|
|
518
|
-
adapter
|
|
519
|
-
.prepare(`UPDATE entity_nodes SET merged_into = ?, status = 'merged', updated_at = ? WHERE id = ?`)
|
|
520
|
-
.run(target_id, mergedAt, source_id);
|
|
521
|
-
adapter
|
|
522
|
-
.prepare(`
|
|
523
|
-
INSERT INTO entity_timeline_events (
|
|
524
|
-
id, entity_id, event_type, role, observed_at, source_ref, summary, details, created_at
|
|
525
|
-
)
|
|
526
|
-
VALUES (?, ?, 'merged', NULL, ?, ?, ?, ?, ?)
|
|
527
|
-
`)
|
|
528
|
-
.run(timelineEventId, source_id, mergedAt, candidate_id, `Merged into ${target_id}`, JSON.stringify({ target_entity_id: target_id, reason, actor_id, actor_type }), mergedAt);
|
|
529
|
-
adapter
|
|
530
|
-
.prepare(`
|
|
531
|
-
INSERT INTO entity_merge_actions (
|
|
532
|
-
id, action_type, source_entity_id, target_entity_id, candidate_id,
|
|
533
|
-
actor_type, actor_id, reason, evidence_json, created_at
|
|
534
|
-
)
|
|
535
|
-
VALUES (?, 'merge', ?, ?, ?, ?, ?, ?, ?, ?)
|
|
536
|
-
`)
|
|
537
|
-
.run(mergeActionId, source_id, target_id, candidate_id, actor_type, actor_id, reason, evidence_json, mergedAt);
|
|
538
|
-
return {
|
|
539
|
-
merge_action_id: mergeActionId,
|
|
540
|
-
timeline_event_id: timelineEventId,
|
|
541
|
-
merged_at: mergedAt,
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
//# sourceMappingURL=store.js.map
|