nlm-memory 0.20.1 → 0.21.12
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 +69 -12
- package/assets/replay-eval-dark.svg +26 -0
- package/assets/replay-eval-light.svg +26 -0
- package/dist/cli/digest.js +69 -4
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/nlm.d.ts +14 -0
- package/dist/cli/nlm.js +556 -71
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/reprocess-job-adapters.d.ts +35 -0
- package/dist/cli/reprocess-job-adapters.js +80 -0
- package/dist/cli/reprocess-job-adapters.js.map +1 -0
- package/dist/cli/scope-backfill.d.ts +34 -0
- package/dist/cli/scope-backfill.js +237 -0
- package/dist/cli/scope-backfill.js.map +1 -0
- package/dist/cli/scope-coverage.d.ts +44 -0
- package/dist/cli/scope-coverage.js +208 -0
- package/dist/cli/scope-coverage.js.map +1 -0
- package/dist/cli/supersede.js +8 -7
- package/dist/cli/supersede.js.map +1 -1
- package/dist/core/actions/actions-log.d.ts +65 -8
- package/dist/core/actions/actions-log.js +134 -17
- package/dist/core/actions/actions-log.js.map +1 -1
- package/dist/core/actions/overlay.d.ts +11 -2
- package/dist/core/actions/overlay.js +18 -6
- package/dist/core/actions/overlay.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts +14 -0
- package/dist/core/adapters/claude-code.js +30 -0
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/adapters/from-source.js +11 -3
- package/dist/core/adapters/from-source.js.map +1 -1
- package/dist/core/adapters/fs-wiki-writer.d.ts +44 -0
- package/dist/core/adapters/fs-wiki-writer.js +132 -0
- package/dist/core/adapters/fs-wiki-writer.js.map +1 -0
- package/dist/core/adapters/hermes-agent.d.ts +15 -2
- package/dist/core/adapters/hermes-agent.js +57 -11
- package/dist/core/adapters/hermes-agent.js.map +1 -1
- package/dist/core/adapters/memory-wiki-writer.d.ts +8 -0
- package/dist/core/adapters/memory-wiki-writer.js +16 -0
- package/dist/core/adapters/memory-wiki-writer.js.map +1 -0
- package/dist/core/adapters/muse.d.ts +51 -0
- package/dist/core/adapters/muse.js +271 -0
- package/dist/core/adapters/muse.js.map +1 -0
- package/dist/core/adapters/opencode.d.ts +11 -4
- package/dist/core/adapters/opencode.js +41 -7
- package/dist/core/adapters/opencode.js.map +1 -1
- package/dist/core/alerts/alert-state.d.ts +17 -0
- package/dist/core/alerts/alert-state.js +45 -0
- package/dist/core/alerts/alert-state.js.map +1 -0
- package/dist/core/alerts/check-and-alert.d.ts +28 -0
- package/dist/core/alerts/check-and-alert.js +53 -0
- package/dist/core/alerts/check-and-alert.js.map +1 -0
- package/dist/core/alerts/drift-transition.d.ts +27 -0
- package/dist/core/alerts/drift-transition.js +56 -0
- package/dist/core/alerts/drift-transition.js.map +1 -0
- package/dist/core/alerts/embedder-transition.d.ts +23 -0
- package/dist/core/alerts/embedder-transition.js +40 -0
- package/dist/core/alerts/embedder-transition.js.map +1 -0
- package/dist/core/alerts/fire-alert.d.ts +24 -0
- package/dist/core/alerts/fire-alert.js +72 -0
- package/dist/core/alerts/fire-alert.js.map +1 -0
- package/dist/core/alerts/job-alert.d.ts +12 -0
- package/dist/core/alerts/job-alert.js +37 -0
- package/dist/core/alerts/job-alert.js.map +1 -0
- package/dist/core/alerts/types.d.ts +104 -0
- package/dist/core/alerts/types.js +11 -0
- package/dist/core/alerts/types.js.map +1 -0
- package/dist/core/alerts/wiki-alert.d.ts +15 -0
- package/dist/core/alerts/wiki-alert.js +31 -0
- package/dist/core/alerts/wiki-alert.js.map +1 -0
- package/dist/core/classifier/prompt.d.ts +13 -0
- package/dist/core/classifier/prompt.js +52 -2
- package/dist/core/classifier/prompt.js.map +1 -1
- package/dist/core/dataset/build-dataset.d.ts +16 -1
- package/dist/core/dataset/build-dataset.js +46 -13
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +11 -3
- package/dist/core/digest/compose.js +70 -17
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/digest/hook-injection.d.ts +43 -0
- package/dist/core/digest/hook-injection.js +87 -0
- package/dist/core/digest/hook-injection.js.map +1 -0
- package/dist/core/digest/hook-version-parity.d.ts +31 -0
- package/dist/core/digest/hook-version-parity.js +56 -0
- package/dist/core/digest/hook-version-parity.js.map +1 -0
- package/dist/core/embedding/pg-embed-backfill.js +1 -1
- package/dist/core/embedding/pg-embed-backfill.js.map +1 -1
- package/dist/core/exemplars/capture-from-session.d.ts +2 -1
- package/dist/core/exemplars/capture-from-session.js +4 -4
- package/dist/core/exemplars/capture-from-session.js.map +1 -1
- package/dist/core/exemplars/embed-backfill.d.ts +9 -0
- package/dist/core/exemplars/embed-backfill.js +9 -1
- package/dist/core/exemplars/embed-backfill.js.map +1 -1
- package/dist/core/exemplars/extract-exemplar.d.ts +2 -0
- package/dist/core/exemplars/extract-exemplar.js +7 -1
- package/dist/core/exemplars/extract-exemplar.js.map +1 -1
- package/dist/core/exemplars/ingest-exemplar.d.ts +1 -0
- package/dist/core/exemplars/ingest-exemplar.js +1 -0
- package/dist/core/exemplars/ingest-exemplar.js.map +1 -1
- package/dist/core/exemplars/recall-code.d.ts +1 -1
- package/dist/core/exemplars/recall-code.js +2 -2
- package/dist/core/exemplars/recall-code.js.map +1 -1
- package/dist/core/facts/backfill-facts.d.ts +1 -1
- package/dist/core/facts/backfill-facts.js +4 -4
- package/dist/core/facts/backfill-facts.js.map +1 -1
- package/dist/core/facts/embed-backfill.d.ts +54 -0
- package/dist/core/facts/embed-backfill.js +109 -0
- package/dist/core/facts/embed-backfill.js.map +1 -0
- package/dist/core/facts/reconcile-facts.d.ts +42 -0
- package/dist/core/facts/reconcile-facts.js +133 -0
- package/dist/core/facts/reconcile-facts.js.map +1 -0
- package/dist/core/health/embed-failure-state.d.ts +4 -0
- package/dist/core/health/embed-failure-state.js +12 -0
- package/dist/core/health/embed-failure-state.js.map +1 -0
- package/dist/core/health/warmup-retry.d.ts +27 -0
- package/dist/core/health/warmup-retry.js +53 -0
- package/dist/core/health/warmup-retry.js.map +1 -0
- package/dist/core/health/warmup-state.d.ts +15 -0
- package/dist/core/health/warmup-state.js +15 -1
- package/dist/core/health/warmup-state.js.map +1 -1
- package/dist/core/hook/cite-memo.d.ts +11 -7
- package/dist/core/hook/cite-memo.js +25 -17
- package/dist/core/hook/cite-memo.js.map +1 -1
- package/dist/core/hook/claude-settings.d.ts +1 -1
- package/dist/core/hook/claude-settings.js +0 -1
- package/dist/core/hook/claude-settings.js.map +1 -1
- package/dist/core/hook/hook-log.d.ts +13 -2
- package/dist/core/hook/hook-log.js +16 -8
- package/dist/core/hook/hook-log.js.map +1 -1
- package/dist/core/hook/memo.d.ts +10 -6
- package/dist/core/hook/memo.js +25 -17
- package/dist/core/hook/memo.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +8 -1
- package/dist/core/hook/pointer-block.js +17 -4
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/resolve-conversation-by-query.d.ts +6 -5
- package/dist/core/hook/resolve-conversation-by-query.js +24 -12
- package/dist/core/hook/resolve-conversation-by-query.js.map +1 -1
- package/dist/core/ingest/backfill-derivables.d.ts +92 -0
- package/dist/core/ingest/backfill-derivables.js +175 -0
- package/dist/core/ingest/backfill-derivables.js.map +1 -0
- package/dist/core/ingest/ingest-session.d.ts +1 -1
- package/dist/core/ingest/ingest-session.js +23 -3
- package/dist/core/ingest/ingest-session.js.map +1 -1
- package/dist/core/ingest/reclassify-oversized.d.ts +1 -1
- package/dist/core/ingest/reclassify-oversized.js +8 -2
- package/dist/core/ingest/reclassify-oversized.js.map +1 -1
- package/dist/core/ingest/reprocess.d.ts +1 -1
- package/dist/core/ingest/reprocess.js +7 -2
- package/dist/core/ingest/reprocess.js.map +1 -1
- package/dist/core/ingest/transcript-derivables.d.ts +27 -0
- package/dist/core/ingest/transcript-derivables.js +138 -0
- package/dist/core/ingest/transcript-derivables.js.map +1 -0
- package/dist/core/jobs/job-supervisor.d.ts +168 -0
- package/dist/core/jobs/job-supervisor.js +335 -0
- package/dist/core/jobs/job-supervisor.js.map +1 -0
- package/dist/core/learner/model.d.ts +63 -0
- package/dist/core/learner/model.js +30 -0
- package/dist/core/learner/model.js.map +1 -0
- package/dist/core/learner/service.d.ts +42 -0
- package/dist/core/learner/service.js +74 -0
- package/dist/core/learner/service.js.map +1 -0
- package/dist/core/learner/summary.d.ts +28 -0
- package/dist/core/learner/summary.js +70 -0
- package/dist/core/learner/summary.js.map +1 -0
- package/dist/core/learner/validate.d.ts +18 -0
- package/dist/core/learner/validate.js +95 -0
- package/dist/core/learner/validate.js.map +1 -0
- package/dist/core/metrics/re-derivation.d.ts +31 -2
- package/dist/core/metrics/re-derivation.js +36 -4
- package/dist/core/metrics/re-derivation.js.map +1 -1
- package/dist/core/outcome/coverage.d.ts +33 -0
- package/dist/core/outcome/coverage.js +46 -0
- package/dist/core/outcome/coverage.js.map +1 -0
- package/dist/core/outcome/rollup.d.ts +33 -0
- package/dist/core/outcome/rollup.js +113 -0
- package/dist/core/outcome/rollup.js.map +1 -0
- package/dist/core/providers/provider-registry.d.ts +40 -23
- package/dist/core/providers/provider-registry.js +99 -81
- package/dist/core/providers/provider-registry.js.map +1 -1
- package/dist/core/recall/citation-log.d.ts +10 -5
- package/dist/core/recall/citation-log.js +21 -10
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/hook-recall-log.d.ts +7 -4
- package/dist/core/recall/hook-recall-log.js +14 -8
- package/dist/core/recall/hook-recall-log.js.map +1 -1
- package/dist/core/recall/miss-log.d.ts +7 -4
- package/dist/core/recall/miss-log.js +18 -11
- package/dist/core/recall/miss-log.js.map +1 -1
- package/dist/core/recall/query-log.d.ts +8 -5
- package/dist/core/recall/query-log.js +16 -9
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.d.ts +10 -1
- package/dist/core/recall/recall-service.js +31 -12
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/recent-log.d.ts +6 -1
- package/dist/core/recall/recent-log.js +13 -5
- package/dist/core/recall/recent-log.js.map +1 -1
- package/dist/core/recall/related-concepts.d.ts +29 -0
- package/dist/core/recall/related-concepts.js +67 -0
- package/dist/core/recall/related-concepts.js.map +1 -0
- package/dist/core/recall/related-exemplars.d.ts +1 -1
- package/dist/core/recall/related-exemplars.js +2 -2
- package/dist/core/recall/related-exemplars.js.map +1 -1
- package/dist/core/recall/related-facts.d.ts +1 -1
- package/dist/core/recall/related-facts.js +3 -3
- package/dist/core/recall/related-facts.js.map +1 -1
- package/dist/core/recall-facts/fact-query-log.d.ts +8 -4
- package/dist/core/recall-facts/fact-query-log.js +16 -8
- package/dist/core/recall-facts/fact-query-log.js.map +1 -1
- package/dist/core/recall-facts/fact-recall-service.d.ts +2 -2
- package/dist/core/recall-facts/fact-recall-service.js +13 -12
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.js +15 -12
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.d.ts +3 -0
- package/dist/core/scheduler/scheduler.js +45 -10
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/scope/alias-map.d.ts +10 -0
- package/dist/core/scope/alias-map.js +41 -0
- package/dist/core/scope/alias-map.js.map +1 -0
- package/dist/core/scope/derive-scope.d.ts +8 -0
- package/dist/core/scope/derive-scope.js +54 -0
- package/dist/core/scope/derive-scope.js.map +1 -0
- package/dist/core/scope/scope-clause.d.ts +16 -0
- package/dist/core/scope/scope-clause.js +21 -0
- package/dist/core/scope/scope-clause.js.map +1 -0
- package/dist/core/scope/stamp-flag.d.ts +1 -0
- package/dist/core/scope/stamp-flag.js +4 -0
- package/dist/core/scope/stamp-flag.js.map +1 -0
- package/dist/core/signals/code-signal.d.ts +1 -0
- package/dist/core/signals/code-signal.js +1 -0
- package/dist/core/signals/code-signal.js.map +1 -1
- package/dist/core/signals/failure-mode-recall.d.ts +1 -1
- package/dist/core/signals/failure-mode-recall.js +2 -2
- package/dist/core/signals/failure-mode-recall.js.map +1 -1
- package/dist/core/signals/ingest-signal.d.ts +1 -1
- package/dist/core/signals/ingest-signal.js +3 -1
- package/dist/core/signals/ingest-signal.js.map +1 -1
- package/dist/core/signals/stamp-scope.d.ts +18 -0
- package/dist/core/signals/stamp-scope.js +28 -0
- package/dist/core/signals/stamp-scope.js.map +1 -0
- package/dist/core/sources/source-registry.d.ts +49 -28
- package/dist/core/sources/source-registry.js +113 -70
- package/dist/core/sources/source-registry.js.map +1 -1
- package/dist/core/storage/pg-code-exemplar-store.d.ts +19 -10
- package/dist/core/storage/pg-code-exemplar-store.js +62 -27
- package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/pg-entity-store.d.ts +6 -1
- package/dist/core/storage/pg-entity-store.js +33 -18
- package/dist/core/storage/pg-entity-store.js.map +1 -1
- package/dist/core/storage/pg-fact-ingest.d.ts +1 -1
- package/dist/core/storage/pg-fact-ingest.js +10 -7
- package/dist/core/storage/pg-fact-ingest.js.map +1 -1
- package/dist/core/storage/pg-fact-store.d.ts +29 -17
- package/dist/core/storage/pg-fact-store.js +99 -46
- package/dist/core/storage/pg-fact-store.js.map +1 -1
- package/dist/core/storage/pg-learner-store.d.ts +27 -0
- package/dist/core/storage/pg-learner-store.js +174 -0
- package/dist/core/storage/pg-learner-store.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +25 -21
- package/dist/core/storage/pg-session-store.js +186 -114
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/pg-signal-store.d.ts +10 -5
- package/dist/core/storage/pg-signal-store.js +26 -13
- package/dist/core/storage/pg-signal-store.js.map +1 -1
- package/dist/core/storage/pg-storage.d.ts +4 -0
- package/dist/core/storage/pg-storage.js +6 -0
- package/dist/core/storage/pg-storage.js.map +1 -1
- package/dist/core/storage/pg-workstream-store.d.ts +17 -11
- package/dist/core/storage/pg-workstream-store.js +47 -29
- package/dist/core/storage/pg-workstream-store.js.map +1 -1
- package/dist/core/storage/sqlite-code-exemplar-store.d.ts +24 -10
- package/dist/core/storage/sqlite-code-exemplar-store.js +86 -40
- package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/sqlite-entity-store.d.ts +8 -1
- package/dist/core/storage/sqlite-entity-store.js +46 -27
- package/dist/core/storage/sqlite-entity-store.js.map +1 -1
- package/dist/core/storage/sqlite-fact-store.d.ts +45 -19
- package/dist/core/storage/sqlite-fact-store.js +175 -64
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-learner-store.d.ts +33 -0
- package/dist/core/storage/sqlite-learner-store.js +178 -0
- package/dist/core/storage/sqlite-learner-store.js.map +1 -0
- package/dist/core/storage/sqlite-outcome-store.d.ts +104 -0
- package/dist/core/storage/sqlite-outcome-store.js +211 -0
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -0
- package/dist/core/storage/sqlite-session-store.d.ts +50 -21
- package/dist/core/storage/sqlite-session-store.js +233 -149
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-signal-store.d.ts +12 -5
- package/dist/core/storage/sqlite-signal-store.js +29 -15
- package/dist/core/storage/sqlite-signal-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +4 -0
- package/dist/core/storage/sqlite-storage.js +10 -2
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/sqlite-workstream-store.d.ts +17 -11
- package/dist/core/storage/sqlite-workstream-store.js +53 -31
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -1
- package/dist/core/storage/supersedence-log.d.ts +10 -7
- package/dist/core/storage/supersedence-log.js +21 -14
- package/dist/core/storage/supersedence-log.js.map +1 -1
- package/dist/core/telemetry/probe-filter.d.ts +35 -0
- package/dist/core/telemetry/probe-filter.js +56 -0
- package/dist/core/telemetry/probe-filter.js.map +1 -0
- package/dist/core/tenancy/default-team.d.ts +6 -0
- package/dist/core/tenancy/default-team.js +7 -0
- package/dist/core/tenancy/default-team.js.map +1 -0
- package/dist/core/tenancy/hosted-mode.d.ts +9 -0
- package/dist/core/tenancy/hosted-mode.js +12 -0
- package/dist/core/tenancy/hosted-mode.js.map +1 -0
- package/dist/core/tenancy/team-auth.d.ts +16 -0
- package/dist/core/tenancy/team-auth.js +22 -0
- package/dist/core/tenancy/team-auth.js.map +1 -0
- package/dist/core/tenancy/team-token-store.d.ts +45 -0
- package/dist/core/tenancy/team-token-store.js +52 -0
- package/dist/core/tenancy/team-token-store.js.map +1 -0
- package/dist/core/tenancy/tenant-clause.d.ts +37 -0
- package/dist/core/tenancy/tenant-clause.js +11 -0
- package/dist/core/tenancy/tenant-clause.js.map +1 -0
- package/dist/core/tenancy/tenant-state-path.d.ts +28 -0
- package/dist/core/tenancy/tenant-state-path.js +49 -0
- package/dist/core/tenancy/tenant-state-path.js.map +1 -0
- package/dist/core/update-check/check.d.ts +6 -0
- package/dist/core/update-check/check.js +35 -0
- package/dist/core/update-check/check.js.map +1 -1
- package/dist/core/wiki/project.d.ts +17 -0
- package/dist/core/wiki/project.js +37 -0
- package/dist/core/wiki/project.js.map +1 -0
- package/dist/core/wiki/reconcile.d.ts +15 -0
- package/dist/core/wiki/reconcile.js +14 -0
- package/dist/core/wiki/reconcile.js.map +1 -0
- package/dist/core/wiki/render.d.ts +5 -0
- package/dist/core/wiki/render.js +84 -0
- package/dist/core/wiki/render.js.map +1 -0
- package/dist/core/wiki/rollup.d.ts +28 -0
- package/dist/core/wiki/rollup.js +91 -0
- package/dist/core/wiki/rollup.js.map +1 -0
- package/dist/core/wiki/select.d.ts +8 -0
- package/dist/core/wiki/select.js +7 -0
- package/dist/core/wiki/select.js.map +1 -0
- package/dist/core/wiki/slug.d.ts +36 -0
- package/dist/core/wiki/slug.js +71 -0
- package/dist/core/wiki/slug.js.map +1 -0
- package/dist/core/wiki/types.d.ts +37 -0
- package/dist/core/wiki/types.js +2 -0
- package/dist/core/wiki/types.js.map +1 -0
- package/dist/core/work-digest/build-work-digest.d.ts +1 -1
- package/dist/core/work-digest/build-work-digest.js +3 -3
- package/dist/core/work-digest/build-work-digest.js.map +1 -1
- package/dist/core/workstream/bind.d.ts +3 -2
- package/dist/core/workstream/bind.js +29 -10
- package/dist/core/workstream/bind.js.map +1 -1
- package/dist/core/workstream/model.d.ts +1 -0
- package/dist/core/workstream/model.js.map +1 -1
- package/dist/core/workstream/rollup.d.ts +1 -1
- package/dist/core/workstream/rollup.js +6 -6
- package/dist/core/workstream/rollup.js.map +1 -1
- package/dist/hook/hook-helpers.d.ts +14 -0
- package/dist/hook/hook-helpers.js +29 -2
- package/dist/hook/hook-helpers.js.map +1 -1
- package/dist/hook/pre-compact-hook.js +8 -5
- package/dist/hook/pre-compact-hook.js.map +1 -1
- package/dist/hook/prompt-recall-hook.d.ts +7 -3
- package/dist/hook/prompt-recall-hook.js +35 -20
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-over-http.d.ts +28 -3
- package/dist/hook/recall-over-http.js +58 -12
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/session-end-hook.js +7 -5
- package/dist/hook/session-end-hook.js.map +1 -1
- package/dist/hook/session-start-hook.d.ts +14 -1
- package/dist/hook/session-start-hook.js +57 -16
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +11 -8
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +47 -3
- package/dist/http/app.js +379 -132
- package/dist/http/app.js.map +1 -1
- package/dist/install/claude-code.d.ts +17 -0
- package/dist/install/claude-code.js +44 -5
- package/dist/install/claude-code.js.map +1 -1
- package/dist/install/codex.d.ts +23 -2
- package/dist/install/codex.js +111 -14
- package/dist/install/codex.js.map +1 -1
- package/dist/install/cursor.d.ts +2 -2
- package/dist/install/cursor.js +7 -7
- package/dist/install/cursor.js.map +1 -1
- package/dist/install/hermes.d.ts +8 -0
- package/dist/install/hermes.js +28 -5
- package/dist/install/hermes.js.map +1 -1
- package/dist/install/local-source.d.ts +20 -0
- package/dist/install/local-source.js +28 -0
- package/dist/install/local-source.js.map +1 -0
- package/dist/install/mcp-block.d.ts +77 -0
- package/dist/install/mcp-block.js +99 -0
- package/dist/install/mcp-block.js.map +1 -0
- package/dist/install/pi.d.ts +26 -0
- package/dist/install/pi.js +43 -0
- package/dist/install/pi.js.map +1 -1
- package/dist/install/setup.js +6 -0
- package/dist/install/setup.js.map +1 -1
- package/dist/install/windsurf.d.ts +2 -2
- package/dist/install/windsurf.js +7 -7
- package/dist/install/windsurf.js.map +1 -1
- package/dist/llm/classifier-box.d.ts +5 -0
- package/dist/llm/classifier-box.js +5 -0
- package/dist/llm/classifier-box.js.map +1 -1
- package/dist/mcp/server.d.ts +94 -15
- package/dist/mcp/server.js +402 -79
- package/dist/mcp/server.js.map +1 -1
- package/dist/ports/clock.d.ts +12 -0
- package/dist/ports/clock.js +10 -0
- package/dist/ports/clock.js.map +1 -0
- package/dist/ports/code-exemplar-store.d.ts +13 -13
- package/dist/ports/entity-store.d.ts +5 -1
- package/dist/ports/fact-store.d.ts +0 -0
- package/dist/ports/fact-store.js +0 -0
- package/dist/ports/fact-store.js.map +1 -1
- package/dist/ports/learner-store.d.ts +80 -0
- package/dist/ports/learner-store.js +19 -0
- package/dist/ports/learner-store.js.map +1 -0
- package/dist/ports/outcome.d.ts +85 -0
- package/dist/ports/outcome.js +11 -0
- package/dist/ports/outcome.js.map +1 -0
- package/dist/ports/session-store.d.ts +20 -20
- package/dist/ports/session-store.js +5 -0
- package/dist/ports/session-store.js.map +1 -1
- package/dist/ports/signal-store.d.ts +12 -8
- package/dist/ports/spawn-child.d.ts +14 -0
- package/dist/ports/spawn-child.js +10 -0
- package/dist/ports/spawn-child.js.map +1 -0
- package/dist/ports/storage.d.ts +6 -0
- package/dist/ports/transcript-adapter.d.ts +11 -0
- package/dist/ports/wiki-writer.d.ts +19 -0
- package/dist/ports/wiki-writer.js +12 -0
- package/dist/ports/wiki-writer.js.map +1 -0
- package/dist/ports/workstream-store.d.ts +20 -12
- package/dist/shared/net.d.ts +3 -0
- package/dist/shared/net.js +4 -0
- package/dist/shared/net.js.map +1 -0
- package/dist/shared/types.d.ts +55 -0
- package/dist/shared/types.js +4 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/shared/version.d.ts +9 -0
- package/dist/shared/version.js +11 -0
- package/dist/shared/version.js.map +1 -0
- package/dist/ui/assets/index-D6F3xAis.js +11 -0
- package/dist/ui/index.html +1 -1
- package/migrations/029_project_scope.sql +21 -0
- package/migrations/032_session_derivables.sql +11 -0
- package/migrations/033_actions_kind_check.sql +58 -0
- package/migrations/034_tenancy_teams_and_stamps.sql +40 -0
- package/migrations/035_tenancy_entity_rekey.sql +75 -0
- package/migrations/036_tenant_name_uniqueness.sql +59 -0
- package/migrations/037_sessions_covering_index.sql +25 -0
- package/migrations/038_sources_muse.sql +33 -0
- package/migrations/039_learner_evidence.sql +51 -0
- package/migrations/pg/030_project_scope.sql +23 -0
- package/migrations/pg/031_widen_session_edges_kind.sql +11 -0
- package/migrations/pg/032_session_derivables.sql +17 -0
- package/migrations/pg/033_actions_kind_check.sql +17 -0
- package/migrations/pg/034_tenancy.sql +77 -0
- package/migrations/pg/035_tenant_name_uniqueness.sql +15 -0
- package/migrations/pg/036_sources_muse.sql +12 -0
- package/migrations/pg/037_learner_evidence.sql +55 -0
- package/nlm/index.js +258 -59
- package/package.json +10 -5
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/scripts/prompt-recall-hook.mjs +256 -58
- package/plugin/scripts/session-start-hook.mjs +283 -55
- package/plugin/scripts/stop-hook.mjs +199 -38
- package/dist/hook/subagent-start-hook.d.ts +0 -28
- package/dist/hook/subagent-start-hook.js +0 -81
- package/dist/hook/subagent-start-hook.js.map +0 -1
- package/dist/ui/assets/index-CMpQkbQy.js +0 -11
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* Constructor takes the Pool from PgStorage. Also exposes recentWrites()
|
|
5
5
|
* and recentMarkers() for the /live HTTP endpoints, and insertSession() +
|
|
6
6
|
* insertSessionForTest() for ingest and test seeding.
|
|
7
|
+
*
|
|
8
|
+
* Tenancy: mirrors SqliteSessionStore — every method takes `tenantId` as its
|
|
9
|
+
* non-optional first parameter and routes STAMP-table WHERE fragments
|
|
10
|
+
* through `tenantClausePg`. See that file's header comment for the full
|
|
11
|
+
* per-table rationale.
|
|
7
12
|
*/
|
|
8
13
|
import { tokenize } from "../recall/tokenize.js";
|
|
9
14
|
import { ingestSessionFactsOnClient } from "./pg-fact-ingest.js";
|
|
@@ -11,28 +16,39 @@ import { chunkSessionText } from "../embedding/chunk-body.js";
|
|
|
11
16
|
import { batchWinners } from "./fact-batch.js";
|
|
12
17
|
import { loadActionOverlayPg, openQuestionId } from "../actions/overlay.js";
|
|
13
18
|
import { liveSessionStatus } from "./live-status.js";
|
|
19
|
+
import { tenantClausePg } from "../tenancy/tenant-clause.js";
|
|
20
|
+
import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
|
|
21
|
+
import { recordEmbedFailure } from "../health/embed-failure-state.js";
|
|
14
22
|
/**
|
|
15
23
|
* PG mirror of SQLite findContinuesPredecessor: the most recent prior session
|
|
16
24
|
* whose distinct entity-set is identical to the new session's. Runs on the
|
|
17
25
|
* ingest transaction's own client. Returns null when there is no entity-set or
|
|
18
26
|
* no exact-set match, leaving the pair unlinked for the re_derivation_rate metric.
|
|
27
|
+
* Scoped to the same tenant as the new session.
|
|
19
28
|
*/
|
|
20
|
-
async function findContinuesPredecessorPg(client, newId, rawEntities) {
|
|
29
|
+
async function findContinuesPredecessorPg(client, tenantId, newId, rawEntities) {
|
|
21
30
|
const entities = [...new Set(rawEntities.map((e) => e.trim()).filter(Boolean))];
|
|
22
31
|
if (entities.length === 0)
|
|
23
32
|
return null;
|
|
24
|
-
const placeholders = entities.map((_, i) => `$${i +
|
|
33
|
+
const placeholders = entities.map((_, i) => `$${i + 3}`).join(",");
|
|
34
|
+
// session_entities rows are always written with the same tenant_id as their
|
|
35
|
+
// owning session (every write site stamps both together), so scoping the
|
|
36
|
+
// outer `sessions` row by tenant is already sufficient. The `se.tenant_id =
|
|
37
|
+
// s.tenant_id` join condition below is defense in depth (guard test C4
|
|
38
|
+
// explicitly permits column-to-column tenant equality as a join form).
|
|
39
|
+
const tc = tenantClausePg(tenantId, 2, "s.tenant_id");
|
|
25
40
|
const res = await client.query(`SELECT s.id AS id
|
|
26
41
|
FROM sessions s
|
|
27
|
-
JOIN session_entities se ON se.session_id = s.id
|
|
42
|
+
JOIN session_entities se ON se.session_id = s.id AND se.tenant_id = s.tenant_id
|
|
28
43
|
WHERE s.id != $1
|
|
44
|
+
AND ${tc.sql}
|
|
29
45
|
AND se.entity_canonical IN (${placeholders})
|
|
30
46
|
GROUP BY s.id
|
|
31
|
-
HAVING COUNT(DISTINCT se.entity_canonical) = $${entities.length +
|
|
47
|
+
HAVING COUNT(DISTINCT se.entity_canonical) = $${entities.length + 3}
|
|
32
48
|
AND COUNT(DISTINCT se.entity_canonical)
|
|
33
49
|
= (SELECT COUNT(*) FROM session_entities x WHERE x.session_id = s.id)
|
|
34
50
|
ORDER BY s.started_at DESC, s.id DESC
|
|
35
|
-
LIMIT 1`, [newId, ...entities, entities.length]);
|
|
51
|
+
LIMIT 1`, [newId, tc.param, ...entities, entities.length]);
|
|
36
52
|
return res.rows[0]?.id ?? null;
|
|
37
53
|
}
|
|
38
54
|
export class PgSessionStore {
|
|
@@ -42,98 +58,79 @@ export class PgSessionStore {
|
|
|
42
58
|
constructor(pool) {
|
|
43
59
|
this.pool = pool;
|
|
44
60
|
}
|
|
45
|
-
|
|
46
|
-
|
|
61
|
+
// Keyed by tenantId — see SqliteSessionStore's identical cache for the
|
|
62
|
+
// tenancy rationale (program spec §4.6 hardening 1).
|
|
63
|
+
overlayCache = new Map();
|
|
47
64
|
invalidateOverlayCache() {
|
|
48
|
-
this.overlayCache
|
|
65
|
+
this.overlayCache.clear();
|
|
49
66
|
}
|
|
50
|
-
async overlay() {
|
|
67
|
+
async overlay(tenantId) {
|
|
51
68
|
// TTL backstop: explicit invalidation covers the daemon's own writers; the
|
|
52
69
|
// 30s expiry bounds staleness if another process ever writes actions to
|
|
53
70
|
// this database.
|
|
54
|
-
|
|
55
|
-
|
|
71
|
+
const cached = this.overlayCache.get(tenantId);
|
|
72
|
+
if (cached !== undefined && Date.now() - cached.at < 30_000) {
|
|
73
|
+
return cached.overlay;
|
|
56
74
|
}
|
|
57
|
-
|
|
58
|
-
this.
|
|
59
|
-
return
|
|
75
|
+
const overlay = await loadActionOverlayPg(this.pool, tenantId);
|
|
76
|
+
this.overlayCache.set(tenantId, { overlay, at: Date.now() });
|
|
77
|
+
return overlay;
|
|
60
78
|
}
|
|
61
|
-
async
|
|
79
|
+
async getById(tenantId, sessionId) {
|
|
80
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
62
81
|
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
63
82
|
label, summary, status, transcript_kind, transcript_path, body,
|
|
64
|
-
classifier_provider, classifier_model, classifier_confidence
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const ids = result.rows.map((r) => r.id);
|
|
69
|
-
const [entitiesMap, markersMap, overlay] = await Promise.all([
|
|
70
|
-
this.loadEntities(ids),
|
|
71
|
-
this.loadMarkers(ids),
|
|
72
|
-
this.overlay(),
|
|
73
|
-
]);
|
|
74
|
-
const sessions = result.rows.map((r) => rowToSession(r, entitiesMap, markersMap, overlay));
|
|
75
|
-
if (!filter)
|
|
76
|
-
return sessions;
|
|
77
|
-
return sessions.filter((s) => {
|
|
78
|
-
if (filter.entity !== undefined && !s.entities.includes(filter.entity))
|
|
79
|
-
return false;
|
|
80
|
-
if (filter.hasDecisions === true && s.decisions.length === 0)
|
|
81
|
-
return false;
|
|
82
|
-
if (filter.hasOpenQuestions === true && s.open.length === 0)
|
|
83
|
-
return false;
|
|
84
|
-
return true;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
async getById(sessionId) {
|
|
88
|
-
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
89
|
-
label, summary, status, transcript_kind, transcript_path, body,
|
|
90
|
-
classifier_provider, classifier_model, classifier_confidence
|
|
91
|
-
FROM sessions WHERE id = $1`, [sessionId]);
|
|
83
|
+
classifier_provider, classifier_model, classifier_confidence,
|
|
84
|
+
agent_persona, parent_session_id,
|
|
85
|
+
primary_model, total_tokens, skill
|
|
86
|
+
FROM sessions WHERE id = $1 AND ${tc.sql}`, [sessionId, tc.param]);
|
|
92
87
|
if (!result.rows[0])
|
|
93
88
|
return null;
|
|
94
89
|
const [entitiesMap, markersMap, edgesMap, overlay] = await Promise.all([
|
|
95
|
-
this.loadEntities([sessionId]),
|
|
90
|
+
this.loadEntities(tenantId, [sessionId]),
|
|
96
91
|
this.loadMarkers([sessionId]),
|
|
97
92
|
this.loadEdges([sessionId]),
|
|
98
|
-
this.overlay(),
|
|
93
|
+
this.overlay(tenantId),
|
|
99
94
|
]);
|
|
100
95
|
const edges = edgesMap.get(sessionId);
|
|
101
96
|
return rowToSession(result.rows[0], entitiesMap, markersMap, overlay, edges);
|
|
102
97
|
}
|
|
103
|
-
async getByIds(ids) {
|
|
98
|
+
async getByIds(tenantId, ids) {
|
|
104
99
|
if (ids.length === 0)
|
|
105
100
|
return [];
|
|
106
101
|
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
102
|
+
const tc = tenantClausePg(tenantId, ids.length + 1);
|
|
107
103
|
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
108
104
|
label, summary, status, transcript_kind, transcript_path
|
|
109
|
-
FROM sessions WHERE id IN (${placeholders})`, [...ids]);
|
|
105
|
+
FROM sessions WHERE id IN (${placeholders}) AND ${tc.sql}`, [...ids, tc.param]);
|
|
110
106
|
if (result.rows.length === 0)
|
|
111
107
|
return [];
|
|
112
108
|
const foundIds = result.rows.map((r) => r.id);
|
|
113
109
|
const [entitiesMap, markersMap, overlay] = await Promise.all([
|
|
114
|
-
this.loadEntities(foundIds),
|
|
110
|
+
this.loadEntities(tenantId, foundIds),
|
|
115
111
|
this.loadMarkers(foundIds),
|
|
116
|
-
this.overlay(),
|
|
112
|
+
this.overlay(tenantId),
|
|
117
113
|
]);
|
|
118
114
|
return result.rows.map((r) => rowToSession({ ...r, body: null }, entitiesMap, markersMap, overlay));
|
|
119
115
|
}
|
|
120
|
-
async listByDateRange(fromIso, toIso) {
|
|
116
|
+
async listByDateRange(tenantId, fromIso, toIso) {
|
|
117
|
+
const tc = tenantClausePg(tenantId, 3);
|
|
121
118
|
const result = await this.pool.query(`SELECT id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
122
119
|
label, summary, status, transcript_kind, transcript_path, workstream_id
|
|
123
120
|
FROM sessions
|
|
124
|
-
WHERE started_at < $1 AND (ended_at IS NULL OR ended_at >= $2)
|
|
125
|
-
ORDER BY started_at ASC`, [toIso, fromIso]);
|
|
121
|
+
WHERE started_at < $1 AND (ended_at IS NULL OR ended_at >= $2) AND ${tc.sql}
|
|
122
|
+
ORDER BY started_at ASC`, [toIso, fromIso, tc.param]);
|
|
126
123
|
if (result.rows.length === 0)
|
|
127
124
|
return [];
|
|
128
125
|
const ids = result.rows.map((r) => r.id);
|
|
129
126
|
const [entitiesMap, markersMap, overlay] = await Promise.all([
|
|
130
|
-
this.loadEntities(ids),
|
|
127
|
+
this.loadEntities(tenantId, ids),
|
|
131
128
|
this.loadMarkers(ids),
|
|
132
|
-
this.overlay(),
|
|
129
|
+
this.overlay(tenantId),
|
|
133
130
|
]);
|
|
134
131
|
return result.rows.map((r) => rowToSession({ ...r, body: null }, entitiesMap, markersMap, overlay));
|
|
135
132
|
}
|
|
136
|
-
async semanticSearch(queryVector, limit, opts) {
|
|
133
|
+
async semanticSearch(tenantId, queryVector, limit, opts) {
|
|
137
134
|
const wsIds = opts?.workstreamIds;
|
|
138
135
|
if (wsIds !== undefined && wsIds.length === 0)
|
|
139
136
|
return [];
|
|
@@ -148,19 +145,24 @@ export class PgSessionStore {
|
|
|
148
145
|
params.push(wsIds);
|
|
149
146
|
wsClause = `AND s.workstream_id = ANY($${params.length}::text[])`;
|
|
150
147
|
}
|
|
148
|
+
// Tenant filter is applied in the id-resolution join against `sessions`
|
|
149
|
+
// (program spec §4.3, vector-path rule) — the `<->` KNN scan over
|
|
150
|
+
// session_embedding_chunks has no tenant column of its own.
|
|
151
|
+
const tc = tenantClausePg(tenantId, params.length + 1, "s.tenant_id");
|
|
152
|
+
params.push(tc.param);
|
|
153
|
+
const limitParam = `$${params.length + 1}`;
|
|
151
154
|
params.push(k);
|
|
152
|
-
const limitParam = `$${params.length}`;
|
|
153
155
|
const result = await this.pool.query(`SELECT sec.session_id, MIN(sec.embedding <-> $1::vector) AS distance, s.status
|
|
154
156
|
FROM session_embedding_chunks sec
|
|
155
157
|
JOIN sessions s ON s.id = sec.session_id
|
|
156
|
-
WHERE
|
|
158
|
+
WHERE ${tc.sql} ${wsClause}
|
|
157
159
|
GROUP BY sec.session_id, s.status
|
|
158
160
|
HAVING ${statusFilter}
|
|
159
161
|
ORDER BY distance
|
|
160
162
|
LIMIT ${limitParam}`, params);
|
|
161
163
|
return result.rows.map((r) => ({ sessionId: r.session_id, distance: r.distance }));
|
|
162
164
|
}
|
|
163
|
-
async keywordSearch(query, limit, opts) {
|
|
165
|
+
async keywordSearch(tenantId, query, limit, opts) {
|
|
164
166
|
const wsIds = opts?.workstreamIds;
|
|
165
167
|
if (wsIds !== undefined && wsIds.length === 0)
|
|
166
168
|
return [];
|
|
@@ -178,6 +180,8 @@ export class PgSessionStore {
|
|
|
178
180
|
params.push(wsIds);
|
|
179
181
|
wsClause = `AND workstream_id = ANY($${params.length}::text[])`;
|
|
180
182
|
}
|
|
183
|
+
const tc = tenantClausePg(tenantId, params.length + 1);
|
|
184
|
+
params.push(tc.param);
|
|
181
185
|
params.push(k);
|
|
182
186
|
const limitParam = `$${params.length}`;
|
|
183
187
|
const result = await this.pool.query(`SELECT id AS session_id,
|
|
@@ -186,39 +190,46 @@ export class PgSessionStore {
|
|
|
186
190
|
WHERE fts_vector @@ websearch_to_tsquery('english', $1)
|
|
187
191
|
AND ${statusFilter}
|
|
188
192
|
${wsClause}
|
|
193
|
+
AND ${tc.sql}
|
|
189
194
|
ORDER BY score DESC
|
|
190
195
|
LIMIT ${limitParam}`, params);
|
|
191
196
|
return result.rows.map((r) => ({ sessionId: r.session_id, score: r.score }));
|
|
192
197
|
}
|
|
193
|
-
async resolveSuccessors(ids) {
|
|
198
|
+
async resolveSuccessors(tenantId, ids) {
|
|
194
199
|
if (ids.length === 0)
|
|
195
200
|
return new Map();
|
|
196
201
|
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
197
|
-
const
|
|
198
|
-
|
|
202
|
+
const tc = tenantClausePg(tenantId, ids.length + 1, "s.tenant_id");
|
|
203
|
+
const result = await this.pool.query(`SELECT se.from_session, se.to_session
|
|
204
|
+
FROM session_edges se
|
|
205
|
+
JOIN sessions s ON s.id = se.to_session
|
|
206
|
+
WHERE se.kind = 'supersedes' AND se.to_session IN (${placeholders}) AND ${tc.sql}`, [...ids, tc.param]);
|
|
199
207
|
const out = new Map();
|
|
200
208
|
for (const r of result.rows)
|
|
201
209
|
out.set(r.to_session, r.from_session);
|
|
202
210
|
return out;
|
|
203
211
|
}
|
|
204
|
-
async updateStatus(sessionId, status) {
|
|
212
|
+
async updateStatus(tenantId, sessionId, status) {
|
|
205
213
|
if (status === "idle") {
|
|
206
214
|
throw new Error("Cannot persist derived status 'idle' — only active/closed/superseded");
|
|
207
215
|
}
|
|
208
|
-
|
|
216
|
+
const tc = tenantClausePg(tenantId, 3);
|
|
217
|
+
await this.pool.query(`UPDATE sessions SET status = $1, updated_at = NOW() WHERE id = $2 AND ${tc.sql}`, [status, sessionId, tc.param]);
|
|
209
218
|
}
|
|
210
|
-
async markSuperseded(predecessorId, successorId) {
|
|
219
|
+
async markSuperseded(tenantId, predecessorId, successorId) {
|
|
211
220
|
if (predecessorId === successorId) {
|
|
212
221
|
throw new Error("A session cannot supersede itself");
|
|
213
222
|
}
|
|
214
223
|
const client = await this.pool.connect();
|
|
215
224
|
try {
|
|
216
225
|
await client.query("BEGIN");
|
|
217
|
-
const
|
|
226
|
+
const predExistsTc = tenantClausePg(tenantId, 2);
|
|
227
|
+
const predExists = await client.query(`SELECT COUNT(*) AS c FROM sessions WHERE id = $1 AND ${predExistsTc.sql}`, [predecessorId, predExistsTc.param]);
|
|
218
228
|
if (Number(predExists.rows[0]?.c) === 0) {
|
|
219
229
|
throw new Error(`predecessor session ${predecessorId} not found`);
|
|
220
230
|
}
|
|
221
|
-
const
|
|
231
|
+
const succExistsTc = tenantClausePg(tenantId, 2);
|
|
232
|
+
const succExists = await client.query(`SELECT COUNT(*) AS c FROM sessions WHERE id = $1 AND ${succExistsTc.sql}`, [successorId, succExistsTc.param]);
|
|
222
233
|
if (Number(succExists.rows[0]?.c) === 0) {
|
|
223
234
|
throw new Error(`successor session ${successorId} not found`);
|
|
224
235
|
}
|
|
@@ -247,8 +258,12 @@ export class PgSessionStore {
|
|
|
247
258
|
await client.query(`INSERT INTO session_edges (from_session, to_session, kind)
|
|
248
259
|
VALUES ($1, $2, 'supersedes')
|
|
249
260
|
ON CONFLICT DO NOTHING`, [successorId, predecessorId]);
|
|
250
|
-
|
|
251
|
-
|
|
261
|
+
const statusTc = tenantClausePg(tenantId, 2);
|
|
262
|
+
await client.query(`UPDATE sessions SET status = 'superseded', updated_at = NOW() WHERE id = $1 AND ${statusTc.sql}`, [predecessorId, statusTc.param]);
|
|
263
|
+
// Cascade supersedence to facts in a single correlated UPDATE, scoped to
|
|
264
|
+
// the caller's tenant on both sides of the join.
|
|
265
|
+
const sTc = tenantClausePg(tenantId, 3, "s.tenant_id");
|
|
266
|
+
const pTc = tenantClausePg(tenantId, 3, "p.tenant_id");
|
|
252
267
|
const cascadeSQL = `
|
|
253
268
|
UPDATE facts AS p
|
|
254
269
|
SET superseded_by = (
|
|
@@ -257,18 +272,21 @@ export class PgSessionStore {
|
|
|
257
272
|
AND s.subject = p.subject
|
|
258
273
|
AND s.predicate = p.predicate
|
|
259
274
|
AND s.superseded_by IS NULL
|
|
275
|
+
AND ${sTc.sql}
|
|
260
276
|
LIMIT 1
|
|
261
277
|
)
|
|
262
278
|
WHERE p.source_session_id = $1
|
|
279
|
+
AND ${pTc.sql}
|
|
263
280
|
AND EXISTS (
|
|
264
281
|
SELECT 1 FROM facts s
|
|
265
282
|
WHERE s.source_session_id = $2
|
|
266
283
|
AND s.subject = p.subject
|
|
267
284
|
AND s.predicate = p.predicate
|
|
268
285
|
AND s.superseded_by IS NULL
|
|
286
|
+
AND ${sTc.sql}
|
|
269
287
|
)
|
|
270
288
|
`;
|
|
271
|
-
const cascaded = await client.query(cascadeSQL + " RETURNING p.id", [predecessorId, successorId]);
|
|
289
|
+
const cascaded = await client.query(cascadeSQL + " RETURNING p.id", [predecessorId, successorId, sTc.param]);
|
|
272
290
|
const cascadedIds = cascaded.rows.map((r) => r.id);
|
|
273
291
|
if (cascadedIds.length > 0) {
|
|
274
292
|
await client.query("DELETE FROM fact_embeddings WHERE fact_id = ANY($1)", [cascadedIds]);
|
|
@@ -283,39 +301,49 @@ export class PgSessionStore {
|
|
|
283
301
|
client.release();
|
|
284
302
|
}
|
|
285
303
|
}
|
|
286
|
-
async
|
|
287
|
-
|
|
304
|
+
async getSessionScopeById(tenantId, id) {
|
|
305
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
306
|
+
const r = await this.pool.query(`SELECT scope FROM sessions WHERE id = $1 AND ${tc.sql}`, [id, tc.param]);
|
|
307
|
+
return r.rows[0]?.scope ?? null;
|
|
308
|
+
}
|
|
309
|
+
async setWorkstreamBinding(tenantId, sessionId, workstreamId, source, confidence) {
|
|
310
|
+
const tc = tenantClausePg(tenantId, 5);
|
|
311
|
+
await this.pool.query(`UPDATE sessions SET workstream_id = $1, binding_source = $2, binding_confidence = $3, updated_at = NOW() WHERE id = $4 AND ${tc.sql}`, [workstreamId, source, confidence, sessionId, tc.param]);
|
|
288
312
|
}
|
|
289
|
-
async listSessionIdsByWorkstreams(workstreamIds) {
|
|
313
|
+
async listSessionIdsByWorkstreams(tenantId, workstreamIds) {
|
|
290
314
|
if (workstreamIds.length === 0)
|
|
291
315
|
return [];
|
|
292
316
|
const ph = workstreamIds.map((_, i) => `$${i + 1}`).join(",");
|
|
293
|
-
const
|
|
317
|
+
const tc = tenantClausePg(tenantId, workstreamIds.length + 1);
|
|
318
|
+
const r = await this.pool.query(`SELECT id FROM sessions WHERE workstream_id IN (${ph}) AND ${tc.sql} ORDER BY started_at ASC`, [...workstreamIds, tc.param]);
|
|
294
319
|
return r.rows.map((row) => row.id);
|
|
295
320
|
}
|
|
296
|
-
async getEntities(sessionId) {
|
|
297
|
-
return (await this.loadEntities([sessionId])).get(sessionId) ?? [];
|
|
321
|
+
async getEntities(tenantId, sessionId) {
|
|
322
|
+
return (await this.loadEntities(tenantId, [sessionId])).get(sessionId) ?? [];
|
|
298
323
|
}
|
|
299
|
-
async getWorkstreamIds(sessionIds) {
|
|
324
|
+
async getWorkstreamIds(tenantId, sessionIds) {
|
|
300
325
|
const out = new Map();
|
|
301
326
|
if (sessionIds.length === 0)
|
|
302
327
|
return out;
|
|
303
328
|
const ph = sessionIds.map((_, i) => `$${i + 1}`).join(",");
|
|
304
|
-
const
|
|
329
|
+
const tc = tenantClausePg(tenantId, sessionIds.length + 1);
|
|
330
|
+
const result = await this.pool.query(`SELECT id, workstream_id FROM sessions WHERE id IN (${ph}) AND ${tc.sql}`, [...sessionIds, tc.param]);
|
|
305
331
|
for (const r of result.rows)
|
|
306
332
|
out.set(r.id, r.workstream_id);
|
|
307
333
|
return out;
|
|
308
334
|
}
|
|
309
|
-
async recentWrites(limit) {
|
|
335
|
+
async recentWrites(tenantId, limit) {
|
|
336
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
310
337
|
const result = await this.pool.query(`SELECT id, runtime, label, summary, created_at AS "createdAt"
|
|
311
|
-
FROM sessions ORDER BY created_at DESC LIMIT $1`, [limit]);
|
|
338
|
+
FROM sessions WHERE ${tc.sql} ORDER BY created_at DESC LIMIT $1`, [limit, tc.param]);
|
|
312
339
|
if (result.rows.length === 0)
|
|
313
340
|
return [];
|
|
314
341
|
const ids = result.rows.map((r) => r.id);
|
|
342
|
+
const entTc = tenantClausePg(tenantId, 2);
|
|
315
343
|
const entityResult = await this.pool.query(`SELECT session_id, entity_canonical
|
|
316
344
|
FROM session_entities
|
|
317
|
-
WHERE session_id = ANY($1)
|
|
318
|
-
ORDER BY entity_canonical`, [ids]);
|
|
345
|
+
WHERE session_id = ANY($1) AND ${entTc.sql}
|
|
346
|
+
ORDER BY entity_canonical`, [ids, entTc.param]);
|
|
319
347
|
const byId = new Map();
|
|
320
348
|
for (const e of entityResult.rows) {
|
|
321
349
|
const list = byId.get(e.session_id);
|
|
@@ -326,15 +354,17 @@ export class PgSessionStore {
|
|
|
326
354
|
}
|
|
327
355
|
return result.rows.map((r) => ({ ...r, entities: byId.get(r.id) ?? [] }));
|
|
328
356
|
}
|
|
329
|
-
async recentMarkers(limit) {
|
|
357
|
+
async recentMarkers(tenantId, limit) {
|
|
358
|
+
const tc = tenantClausePg(tenantId, 2, "s.tenant_id");
|
|
330
359
|
const result = await this.pool.query(`SELECT m.session_id AS "sessionId", m.kind, m.text, s.label, s.created_at AS "createdAt"
|
|
331
360
|
FROM markers m
|
|
332
361
|
JOIN sessions s ON s.id = m.session_id
|
|
362
|
+
WHERE ${tc.sql}
|
|
333
363
|
ORDER BY s.created_at DESC, m.position ASC
|
|
334
|
-
LIMIT $1`, [limit]);
|
|
364
|
+
LIMIT $1`, [limit, tc.param]);
|
|
335
365
|
return result.rows;
|
|
336
366
|
}
|
|
337
|
-
async insertSession(record, embedder = null, supersedes = null, factSink = null) {
|
|
367
|
+
async insertSession(tenantId, record, embedder = null, supersedes = null, factSink = null) {
|
|
338
368
|
const client = await this.pool.connect();
|
|
339
369
|
try {
|
|
340
370
|
await client.query("BEGIN");
|
|
@@ -342,8 +372,10 @@ export class PgSessionStore {
|
|
|
342
372
|
id, runtime, runtime_session_id, started_at, ended_at, duration_min,
|
|
343
373
|
label, summary, body, status, transcript_kind, transcript_path,
|
|
344
374
|
transcript_offset, transcript_length,
|
|
345
|
-
classifier_provider, classifier_model, classifier_confidence
|
|
346
|
-
|
|
375
|
+
classifier_provider, classifier_model, classifier_confidence,
|
|
376
|
+
scope, agent_persona, parent_session_id,
|
|
377
|
+
primary_model, total_tokens, skill, tenant_id
|
|
378
|
+
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)
|
|
347
379
|
ON CONFLICT (id) DO UPDATE SET
|
|
348
380
|
ended_at = EXCLUDED.ended_at,
|
|
349
381
|
duration_min = EXCLUDED.duration_min,
|
|
@@ -354,6 +386,12 @@ export class PgSessionStore {
|
|
|
354
386
|
classifier_provider = EXCLUDED.classifier_provider,
|
|
355
387
|
classifier_model = EXCLUDED.classifier_model,
|
|
356
388
|
classifier_confidence = EXCLUDED.classifier_confidence,
|
|
389
|
+
scope = COALESCE(EXCLUDED.scope, sessions.scope),
|
|
390
|
+
agent_persona = COALESCE(EXCLUDED.agent_persona, sessions.agent_persona),
|
|
391
|
+
parent_session_id = COALESCE(EXCLUDED.parent_session_id, sessions.parent_session_id),
|
|
392
|
+
primary_model = COALESCE(EXCLUDED.primary_model, sessions.primary_model),
|
|
393
|
+
total_tokens = COALESCE(EXCLUDED.total_tokens, sessions.total_tokens),
|
|
394
|
+
skill = COALESCE(EXCLUDED.skill, sessions.skill),
|
|
357
395
|
updated_at = NOW()`, [
|
|
358
396
|
record.id, record.runtime, record.runtimeSessionId,
|
|
359
397
|
record.startedAt, record.endedAt, record.durationMin,
|
|
@@ -364,6 +402,13 @@ export class PgSessionStore {
|
|
|
364
402
|
record.classifier?.provider ?? null,
|
|
365
403
|
record.classifier?.model ?? null,
|
|
366
404
|
record.classifier?.confidence ?? null,
|
|
405
|
+
record.scope,
|
|
406
|
+
record.agentPersona ?? null,
|
|
407
|
+
record.parentSessionId ?? null,
|
|
408
|
+
record.primaryModel ?? null,
|
|
409
|
+
record.totalTokens ?? null,
|
|
410
|
+
record.skill ?? null,
|
|
411
|
+
tenantId,
|
|
367
412
|
]);
|
|
368
413
|
await client.query("DELETE FROM markers WHERE session_id = $1", [record.id]);
|
|
369
414
|
for (let i = 0; i < record.decisions.length; i++) {
|
|
@@ -379,36 +424,43 @@ export class PgSessionStore {
|
|
|
379
424
|
const rawNewEntities = [...new Set(record.entities.map((e) => e.trim()).filter(Boolean))];
|
|
380
425
|
// Resolve each extracted entity through entity_variants so merged surface
|
|
381
426
|
// forms bind to the canonical instead of resurrecting the retired source.
|
|
382
|
-
const
|
|
427
|
+
const variantTc = tenantClausePg(tenantId, 1);
|
|
428
|
+
const variantRes = await client.query(`SELECT variant, canonical FROM entity_variants WHERE ${variantTc.sql} AND variant = ANY($2)`, [variantTc.param, rawNewEntities]);
|
|
383
429
|
const variantMap = new Map(variantRes.rows.map((r) => [r.variant, r.canonical]));
|
|
384
430
|
const newEntities = rawNewEntities.map((name) => variantMap.get(name) ?? name);
|
|
385
|
-
const
|
|
431
|
+
const oldTc = tenantClausePg(tenantId, 1);
|
|
432
|
+
const oldRes = await client.query(`SELECT entity_canonical FROM session_entities WHERE ${oldTc.sql} AND session_id = $2`, [oldTc.param, record.id]);
|
|
386
433
|
const oldEntities = new Set(oldRes.rows.map((r) => r.entity_canonical));
|
|
387
|
-
|
|
434
|
+
const deleteTc = tenantClausePg(tenantId, 1);
|
|
435
|
+
await client.query(`DELETE FROM session_entities WHERE ${deleteTc.sql} AND session_id = $2`, [deleteTc.param, record.id]);
|
|
388
436
|
for (const name of newEntities) {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
437
|
+
const insertTc = tenantClausePg(tenantId, 1);
|
|
438
|
+
await client.query(`INSERT INTO entities (tenant_id, canonical, type, status, source, first_seen_session, last_seen_session, session_count)
|
|
439
|
+
VALUES ($1, $2, 'candidate', 'candidate', 'auto-detected', $3, $3, 0)
|
|
440
|
+
ON CONFLICT (tenant_id, canonical) DO NOTHING`, [insertTc.param, name, record.id]);
|
|
392
441
|
// Update last_seen for entities newly added to this session; matches prior touch semantics.
|
|
393
442
|
if (!oldEntities.has(name)) {
|
|
394
|
-
|
|
443
|
+
const touchTc = tenantClausePg(tenantId, 2);
|
|
444
|
+
await client.query(`UPDATE entities SET last_seen_session = $1, updated_at = NOW() WHERE ${touchTc.sql} AND canonical = $3`, [record.id, touchTc.param, name]);
|
|
395
445
|
}
|
|
396
|
-
await client.query("INSERT INTO session_entities (session_id, entity_canonical) VALUES ($1, $2)", [record.id, name]);
|
|
446
|
+
await client.query("INSERT INTO session_entities (tenant_id, session_id, entity_canonical) VALUES ($1, $2, $3)", [tenantId, record.id, name]);
|
|
397
447
|
}
|
|
398
448
|
// Recompute session_count exactly for every entity in (old union new) so
|
|
399
449
|
// counts reflect reality regardless of prior drift.
|
|
400
450
|
const allTouched = [...new Set([...oldEntities, ...newEntities])];
|
|
401
451
|
for (const name of allTouched) {
|
|
402
|
-
|
|
452
|
+
const recomputeTc = tenantClausePg(tenantId, 2);
|
|
453
|
+
await client.query(`UPDATE entities SET session_count = (SELECT COUNT(*) FROM session_entities WHERE ${recomputeTc.sql} AND entity_canonical = $1), updated_at = NOW() WHERE ${recomputeTc.sql} AND canonical = $1`, [name, recomputeTc.param]);
|
|
403
454
|
}
|
|
404
455
|
if (supersedes && supersedes.priorSessionId !== record.id) {
|
|
405
456
|
const predecessorStatus = supersedes.kind === "replaces" ? "replaced" : "superseded";
|
|
406
457
|
await client.query(`INSERT INTO session_edges (from_session, to_session, kind)
|
|
407
458
|
VALUES ($1, $2, $3) ON CONFLICT DO NOTHING`, [record.id, supersedes.priorSessionId, supersedes.kind]);
|
|
408
|
-
|
|
459
|
+
const predStatusTc = tenantClausePg(tenantId, 3);
|
|
460
|
+
await client.query(`UPDATE sessions SET status = $1, updated_at = NOW() WHERE id = $2 AND ${predStatusTc.sql}`, [predecessorStatus, supersedes.priorSessionId, predStatusTc.param]);
|
|
409
461
|
}
|
|
410
462
|
else {
|
|
411
|
-
const priorId = await findContinuesPredecessorPg(client, record.id, record.entities);
|
|
463
|
+
const priorId = await findContinuesPredecessorPg(client, tenantId, record.id, record.entities);
|
|
412
464
|
if (priorId !== null) {
|
|
413
465
|
await client.query(`INSERT INTO session_edges (from_session, to_session, kind)
|
|
414
466
|
VALUES ($1, $2, 'continues') ON CONFLICT DO NOTHING`, [record.id, priorId]);
|
|
@@ -416,7 +468,7 @@ export class PgSessionStore {
|
|
|
416
468
|
}
|
|
417
469
|
// Atomic session+facts ingest on the session's own client. Single source of truth: pg-fact-ingest.ts.
|
|
418
470
|
if (factSink !== null) {
|
|
419
|
-
await ingestSessionFactsOnClient(client, record.id, factSink.facts);
|
|
471
|
+
await ingestSessionFactsOnClient(client, tenantId, record.id, factSink.facts, record.scope);
|
|
420
472
|
}
|
|
421
473
|
await client.query("COMMIT");
|
|
422
474
|
}
|
|
@@ -443,6 +495,7 @@ export class PgSessionStore {
|
|
|
443
495
|
await this.pool.query("INSERT INTO session_chunk_map (chunk_id, session_id, chunk_idx) VALUES ($1, $2, $3)", [chunkId, record.id, chunkIdx]);
|
|
444
496
|
}
|
|
445
497
|
catch (err) {
|
|
498
|
+
recordEmbedFailure("chunk");
|
|
446
499
|
process.stderr.write(`[nlm] embedding chunk failed session=${record.id} chunk=${chunkIdx}: ${String(err)}\n`);
|
|
447
500
|
}
|
|
448
501
|
}
|
|
@@ -456,27 +509,30 @@ export class PgSessionStore {
|
|
|
456
509
|
continue;
|
|
457
510
|
try {
|
|
458
511
|
const { vector } = await embedder.embed(factText, "document");
|
|
459
|
-
await factSink.factStore.upsertEmbedding(fact.id, vector);
|
|
512
|
+
await factSink.factStore.upsertEmbedding(tenantId, fact.id, vector);
|
|
460
513
|
}
|
|
461
|
-
catch {
|
|
462
|
-
// Tolerated;
|
|
514
|
+
catch (err) {
|
|
515
|
+
// Tolerated; the fact row stays current, semantic recall misses
|
|
516
|
+
// it until a future re-ingest.
|
|
517
|
+
recordEmbedFailure("fact");
|
|
518
|
+
process.stderr.write(`[nlm] embedding fact failed fact=${fact.id}: ${String(err)}\n`);
|
|
463
519
|
}
|
|
464
520
|
}
|
|
465
521
|
}
|
|
466
522
|
}
|
|
467
523
|
}
|
|
468
|
-
async insertSessionForTest(session) {
|
|
524
|
+
async insertSessionForTest(session, tenantId = DEFAULT_TEAM_ID) {
|
|
469
525
|
const status = session.status === "idle" ? "active" : session.status;
|
|
470
526
|
await this.pool.query(`INSERT INTO sessions (id, runtime, runtime_session_id, started_at, ended_at,
|
|
471
|
-
duration_min, label, summary, body, status, transcript_kind, transcript_path)
|
|
472
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, [
|
|
527
|
+
duration_min, label, summary, body, status, transcript_kind, transcript_path, tenant_id)
|
|
528
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`, [
|
|
473
529
|
session.id, session.runtime, session.runtimeSessionId, session.startedAt,
|
|
474
530
|
session.endedAt, session.durationMin, session.label, session.summary,
|
|
475
|
-
session.body, status, session.transcriptKind, session.transcriptPath,
|
|
531
|
+
session.body, status, session.transcriptKind, session.transcriptPath, tenantId,
|
|
476
532
|
]);
|
|
477
533
|
for (const e of session.entities) {
|
|
478
|
-
await this.pool.query("INSERT INTO entities (canonical, type, status) VALUES ($1, 'candidate', 'active') ON CONFLICT DO NOTHING", [e]);
|
|
479
|
-
await this.pool.query("INSERT INTO session_entities (session_id, entity_canonical) VALUES ($1, $2) ON CONFLICT DO NOTHING", [session.id, e]);
|
|
534
|
+
await this.pool.query("INSERT INTO entities (tenant_id, canonical, type, status) VALUES ($1, $2, 'candidate', 'active') ON CONFLICT DO NOTHING", [tenantId, e]);
|
|
535
|
+
await this.pool.query("INSERT INTO session_entities (tenant_id, session_id, entity_canonical) VALUES ($1, $2, $3) ON CONFLICT DO NOTHING", [tenantId, session.id, e]);
|
|
480
536
|
}
|
|
481
537
|
for (let i = 0; i < session.decisions.length; i++) {
|
|
482
538
|
await this.pool.query("INSERT INTO markers (session_id, kind, text, position) VALUES ($1, 'decision', $2, $3)", [session.id, session.decisions[i], i]);
|
|
@@ -486,31 +542,41 @@ export class PgSessionStore {
|
|
|
486
542
|
}
|
|
487
543
|
}
|
|
488
544
|
/** PG counterpart of SqliteSessionStore.listBackfillCandidates. */
|
|
489
|
-
async listBackfillCandidates(filter) {
|
|
545
|
+
async listBackfillCandidates(tenantId, filter) {
|
|
490
546
|
const params = [filter.cutoff];
|
|
491
547
|
let fromClause = "";
|
|
492
548
|
if (filter.from) {
|
|
493
549
|
params.push(filter.from);
|
|
494
550
|
fromClause = `AND s.id > $${params.length}`;
|
|
495
551
|
}
|
|
552
|
+
// facts.tenant_id is always stamped to match its source_session_id's
|
|
553
|
+
// session tenant (every write site stamps both together), so scoping by
|
|
554
|
+
// source_session_id = s.id against an already tenant-filtered `s` is
|
|
555
|
+
// already sufficient. The f.tenant_id = s.tenant_id condition below is
|
|
556
|
+
// defense in depth (guard test C4 permits column-to-column tenant
|
|
557
|
+
// equality as a join form).
|
|
496
558
|
const existingFactsClause = filter.reprocess
|
|
497
559
|
? ""
|
|
498
|
-
: "AND NOT EXISTS (SELECT 1 FROM facts f WHERE f.source_session_id = s.id)";
|
|
560
|
+
: "AND NOT EXISTS (SELECT 1 FROM facts f WHERE f.source_session_id = s.id AND f.tenant_id = s.tenant_id)";
|
|
561
|
+
const tc = tenantClausePg(tenantId, params.length + 1, "s.tenant_id");
|
|
562
|
+
params.push(tc.param);
|
|
499
563
|
const result = await this.pool.query(`SELECT s.id, s.started_at, s.body FROM sessions s
|
|
500
564
|
WHERE s.started_at < $1 AND s.body IS NOT NULL AND length(s.body) > 0
|
|
501
565
|
${existingFactsClause}
|
|
502
566
|
${fromClause}
|
|
567
|
+
AND ${tc.sql}
|
|
503
568
|
ORDER BY s.started_at ASC, s.id ASC`, params);
|
|
504
569
|
return result.rows.map((r) => ({ id: r.id, startedAt: r.started_at, body: r.body }));
|
|
505
570
|
}
|
|
506
571
|
/** PG counterpart of SqliteSessionStore.insertFactsForSession — writes facts
|
|
507
572
|
* for an EXISTING session row (deterministic supersedence + best-effort
|
|
508
573
|
* embeddings) in one transaction. Used by the fact backfill. */
|
|
509
|
-
async insertFactsForSession(sessionId, factStore, facts, embedder = null) {
|
|
574
|
+
async insertFactsForSession(tenantId, sessionId, factStore, facts, embedder = null) {
|
|
575
|
+
const sessionScope = await this.getSessionScopeById(tenantId, sessionId);
|
|
510
576
|
const client = await this.pool.connect();
|
|
511
577
|
try {
|
|
512
578
|
await client.query("BEGIN");
|
|
513
|
-
await ingestSessionFactsOnClient(client, sessionId, facts);
|
|
579
|
+
await ingestSessionFactsOnClient(client, tenantId, sessionId, facts, sessionScope);
|
|
514
580
|
await client.query("COMMIT");
|
|
515
581
|
}
|
|
516
582
|
catch (err) {
|
|
@@ -527,7 +593,7 @@ export class PgSessionStore {
|
|
|
527
593
|
continue;
|
|
528
594
|
try {
|
|
529
595
|
const { vector } = await embedder.embed(factText, "document");
|
|
530
|
-
await factStore.upsertEmbedding(fact.id, vector);
|
|
596
|
+
await factStore.upsertEmbedding(tenantId, fact.id, vector);
|
|
531
597
|
}
|
|
532
598
|
catch {
|
|
533
599
|
// Best-effort; a per-fact embed failure leaves the fact current but
|
|
@@ -536,12 +602,13 @@ export class PgSessionStore {
|
|
|
536
602
|
}
|
|
537
603
|
}
|
|
538
604
|
}
|
|
539
|
-
async loadEntities(ids) {
|
|
605
|
+
async loadEntities(tenantId, ids) {
|
|
540
606
|
if (ids.length === 0)
|
|
541
607
|
return new Map();
|
|
542
608
|
const placeholders = ids.map((_, i) => `$${i + 1}`).join(",");
|
|
609
|
+
const tc = tenantClausePg(tenantId, ids.length + 1);
|
|
543
610
|
const result = await this.pool.query(`SELECT session_id, entity_canonical FROM session_entities
|
|
544
|
-
WHERE session_id IN (${placeholders}) ORDER BY session_id`, [...ids]);
|
|
611
|
+
WHERE session_id IN (${placeholders}) AND ${tc.sql} ORDER BY session_id`, [...ids, tc.param]);
|
|
545
612
|
const out = new Map();
|
|
546
613
|
for (const r of result.rows) {
|
|
547
614
|
const list = out.get(r.session_id);
|
|
@@ -637,6 +704,11 @@ function rowToSession(row, entitiesById, markersById, overlay, edges) {
|
|
|
637
704
|
classifierProvider: row.classifier_provider ?? null,
|
|
638
705
|
classifierModel: row.classifier_model ?? null,
|
|
639
706
|
classifierConfidence: row.classifier_confidence ?? null,
|
|
707
|
+
agentPersona: row.agent_persona ?? null,
|
|
708
|
+
parentSessionId: row.parent_session_id ?? null,
|
|
709
|
+
primaryModel: row.primary_model ?? null,
|
|
710
|
+
totalTokens: row.total_tokens ?? null,
|
|
711
|
+
skill: row.skill ?? null,
|
|
640
712
|
};
|
|
641
713
|
}
|
|
642
714
|
//# sourceMappingURL=pg-session-store.js.map
|