nlm-memory 0.21.0 → 0.21.13
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 +67 -12
- package/assets/replay-eval-dark.svg +26 -0
- package/assets/replay-eval-light.svg +26 -0
- package/dist/cli/digest.js +34 -7
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/nlm.d.ts +14 -0
- package/dist/cli/nlm.js +450 -65
- 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-coverage.js +4 -1
- package/dist/cli/scope-coverage.js.map +1 -1
- 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/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 +105 -45
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +8 -0
- package/dist/core/digest/compose.js +54 -0
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/digest/hook-injection.d.ts +1 -1
- package/dist/core/digest/hook-injection.js +9 -1
- package/dist/core/digest/hook-injection.js.map +1 -1
- 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 +1 -1
- package/dist/core/exemplars/capture-from-session.js +3 -3
- 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/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/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/ingest-session.d.ts +1 -1
- package/dist/core/ingest/ingest-session.js +3 -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 +2 -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 +2 -2
- package/dist/core/ingest/reprocess.js.map +1 -1
- 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 +1 -1
- package/dist/core/outcome/coverage.js +2 -2
- package/dist/core/outcome/coverage.js.map +1 -1
- package/dist/core/outcome/rollup.d.ts +1 -1
- package/dist/core/outcome/rollup.js +4 -4
- package/dist/core/outcome/rollup.js.map +1 -1
- 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 +5 -2
- package/dist/core/recall/hook-recall-log.js +12 -6
- 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 +12 -12
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.js +15 -14
- 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 +15 -11
- package/dist/core/scheduler/scheduler.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/stamp-scope.d.ts +2 -2
- package/dist/core/signals/stamp-scope.js +2 -2
- package/dist/core/signals/stamp-scope.js.map +1 -1
- 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 +58 -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 +24 -20
- package/dist/core/storage/pg-session-store.js +162 -90
- 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 +24 -12
- 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 +16 -11
- package/dist/core/storage/pg-workstream-store.js +46 -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 +84 -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 +172 -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 +37 -22
- package/dist/core/storage/sqlite-outcome-store.js +90 -37
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -1
- package/dist/core/storage/sqlite-session-store.d.ts +29 -20
- package/dist/core/storage/sqlite-session-store.js +207 -121
- 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 +27 -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 +16 -11
- package/dist/core/storage/sqlite-workstream-store.js +52 -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 +19 -14
- package/dist/core/storage/supersedence-log.js.map +1 -1
- 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/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 +1 -1
- package/dist/core/workstream/bind.js +10 -10
- package/dist/core/workstream/bind.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 +6 -4
- package/dist/hook/pre-compact-hook.js.map +1 -1
- package/dist/hook/prompt-recall-hook.d.ts +5 -2
- package/dist/hook/prompt-recall-hook.js +28 -17
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-over-http.d.ts +27 -3
- package/dist/hook/recall-over-http.js +44 -11
- 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 +55 -15
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +9 -7
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +41 -3
- package/dist/http/app.js +355 -96
- 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 +73 -16
- package/dist/mcp/server.js +306 -83
- 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 +3 -3
- package/dist/ports/session-store.d.ts +20 -14
- 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 +19 -12
- package/dist/shared/types.d.ts +22 -0
- 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/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/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 +246 -55
- package/package.json +10 -5
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/scripts/prompt-recall-hook.mjs +244 -55
- package/plugin/scripts/session-start-hook.mjs +273 -53
- package/plugin/scripts/stop-hook.mjs +195 -37
- package/dist/ui/assets/index-CSaBtgXD.js +0 -11
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// src/hook/prompt-recall-hook.ts
|
|
4
|
-
import { pathToFileURL } from "node:url";
|
|
5
|
-
|
|
6
3
|
// src/core/hook/gate.ts
|
|
7
4
|
var LEADING_FILLER = /^(please|can you|could you|would you|will you|i need you to|i'd like you to|i want you to|i would like you to|help me|let's|lets|hey|ok|okay)\b[\s,]*/i;
|
|
8
5
|
var GENERATIVE_OPENER = /^(write|draft|create|compose|generate|brainstorm|design|outline|sketch|invent|rename|come up with)\b/i;
|
|
@@ -194,16 +191,159 @@ function recentConversationContext(transcriptPath, opts = {}) {
|
|
|
194
191
|
|
|
195
192
|
// src/core/hook/hook-log.ts
|
|
196
193
|
import { appendFileSync, mkdirSync } from "node:fs";
|
|
194
|
+
import { dirname } from "node:path";
|
|
195
|
+
|
|
196
|
+
// src/core/tenancy/tenant-state-path.ts
|
|
197
|
+
import { createHash } from "node:crypto";
|
|
197
198
|
import { homedir } from "node:os";
|
|
198
|
-
import {
|
|
199
|
-
|
|
200
|
-
|
|
199
|
+
import { join } from "node:path";
|
|
200
|
+
|
|
201
|
+
// src/core/tenancy/default-team.ts
|
|
202
|
+
var DEFAULT_TEAM_ID = "team_local";
|
|
203
|
+
|
|
204
|
+
// src/core/tenancy/tenant-state-path.ts
|
|
205
|
+
var TENANTS_DIRNAME = "tenants";
|
|
206
|
+
var SAFE_TENANT_ID = /^[A-Za-z0-9_-]+$/;
|
|
207
|
+
function sanitizeTenantId(tenantId) {
|
|
208
|
+
if (SAFE_TENANT_ID.test(tenantId)) return tenantId;
|
|
209
|
+
const sanitized = tenantId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
210
|
+
const hash = createHash("sha256").update(tenantId).digest("hex").slice(0, 8);
|
|
211
|
+
return `${sanitized}_${hash}`;
|
|
212
|
+
}
|
|
213
|
+
function stateRoot() {
|
|
214
|
+
return process.env["NLM_STATE_ROOT"] || join(homedir(), ".nlm");
|
|
215
|
+
}
|
|
216
|
+
function tenantStatePath(tenantId, ...segments) {
|
|
217
|
+
const base = stateRoot();
|
|
218
|
+
if (tenantId === DEFAULT_TEAM_ID) return join(base, ...segments);
|
|
219
|
+
return join(base, TENANTS_DIRNAME, sanitizeTenantId(tenantId), ...segments);
|
|
201
220
|
}
|
|
202
|
-
|
|
221
|
+
|
|
222
|
+
// package.json
|
|
223
|
+
var package_default = {
|
|
224
|
+
name: "nlm-memory",
|
|
225
|
+
version: "0.21.13",
|
|
226
|
+
description: "Local-first non-linear memory operating system for AI operators.",
|
|
227
|
+
type: "module",
|
|
228
|
+
license: "Apache-2.0",
|
|
229
|
+
engines: {
|
|
230
|
+
node: ">=22.0.0"
|
|
231
|
+
},
|
|
232
|
+
repository: {
|
|
233
|
+
type: "git",
|
|
234
|
+
url: "git+https://github.com/pbmagnet4/nlm-memory.git"
|
|
235
|
+
},
|
|
236
|
+
homepage: "https://github.com/pbmagnet4/nlm-memory#readme",
|
|
237
|
+
bugs: {
|
|
238
|
+
url: "https://github.com/pbmagnet4/nlm-memory/issues"
|
|
239
|
+
},
|
|
240
|
+
keywords: [
|
|
241
|
+
"ai",
|
|
242
|
+
"memory",
|
|
243
|
+
"mcp",
|
|
244
|
+
"claude-code",
|
|
245
|
+
"codex",
|
|
246
|
+
"hermes",
|
|
247
|
+
"local-first",
|
|
248
|
+
"recall",
|
|
249
|
+
"session-memory"
|
|
250
|
+
],
|
|
251
|
+
files: [
|
|
252
|
+
"dist",
|
|
253
|
+
"migrations",
|
|
254
|
+
"fixtures",
|
|
255
|
+
"templates",
|
|
256
|
+
"plugin",
|
|
257
|
+
"plugin-hermes-agent",
|
|
258
|
+
"nlm",
|
|
259
|
+
"assets",
|
|
260
|
+
"LICENSE",
|
|
261
|
+
"README.md"
|
|
262
|
+
],
|
|
263
|
+
bin: {
|
|
264
|
+
nlm: "dist/cli/nlm.js"
|
|
265
|
+
},
|
|
266
|
+
scripts: {
|
|
267
|
+
dev: "tsx watch src/cli/nlm.ts start",
|
|
268
|
+
start: "node dist/cli/nlm.js start",
|
|
269
|
+
"build:server": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
270
|
+
"build:ui": "vite build --config src/ui/vite.config.ts",
|
|
271
|
+
"build:codex-plugin": "node scripts/build-codex-plugin.mjs",
|
|
272
|
+
"verify:codex-release": "node scripts/verify-codex-release.mjs",
|
|
273
|
+
build: "npm run build:server && npm run build:ui && npm run build:codex-plugin",
|
|
274
|
+
prepare: "[ -d src ] && npm run build || true",
|
|
275
|
+
"ui:dev": "vite --config src/ui/vite.config.ts",
|
|
276
|
+
test: "vitest run",
|
|
277
|
+
"test:watch": "vitest",
|
|
278
|
+
"test:unit": "vitest run tests/unit",
|
|
279
|
+
"test:integration": "vitest run tests/integration",
|
|
280
|
+
"test:pg": "vitest run .pg.test.ts --test-timeout=20000",
|
|
281
|
+
typecheck: "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
|
|
282
|
+
"bench:longmemeval": "tsx scripts/longmemeval/run-harness.ts",
|
|
283
|
+
"bench:classifier": "tsx scripts/longmemeval/run-harness.ts --classifier",
|
|
284
|
+
"bench:compare": "tsx scripts/longmemeval/compare-classifiers.ts",
|
|
285
|
+
"eval:signals": "tsx scripts/eval/signals-eval.ts",
|
|
286
|
+
"eval:classifier": "tsx scripts/eval/classifier-eval.ts",
|
|
287
|
+
"eval:fact-recall": "tsx scripts/eval/fact-recall-eval.ts",
|
|
288
|
+
"eval:recall-impact-replay": "tsx scripts/eval/recall-impact-replay.ts",
|
|
289
|
+
"eval:code-exemplar": "tsx scripts/eval/code-exemplar-eval.ts",
|
|
290
|
+
"eval:reranker": "tsx scripts/eval/reranker-ablation.ts",
|
|
291
|
+
"eval:floor": "tsx scripts/eval/floor-calibration.ts",
|
|
292
|
+
"eval:matcher": "tsx scripts/eval/tune-matcher.ts",
|
|
293
|
+
"eval:naming": "tsx scripts/eval/tune-naming.ts",
|
|
294
|
+
"eval:rederiv-sample": "tsx scripts/eval/re-derivation-sample.ts",
|
|
295
|
+
"eval:rederiv-label": "tsx scripts/eval/re-derivation-label.ts",
|
|
296
|
+
"eval:rederiv-calibrate": "tsx scripts/eval/re-derivation-calibrate.ts"
|
|
297
|
+
},
|
|
298
|
+
dependencies: {
|
|
299
|
+
"@clack/prompts": "^1.4.0",
|
|
300
|
+
"@hono/node-server": "^2.0.3",
|
|
301
|
+
"@huggingface/transformers": "4.2.0",
|
|
302
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
303
|
+
"@toon-format/toon": "^2.3.0",
|
|
304
|
+
"better-sqlite3": "^13.0.1",
|
|
305
|
+
commander: "^15.0.0",
|
|
306
|
+
hono: "^4.6.0",
|
|
307
|
+
pg: "^8.21.0",
|
|
308
|
+
pgvector: "^0.3.0",
|
|
309
|
+
"sqlite-vec": "^0.1.6",
|
|
310
|
+
yaml: "^2.9.0",
|
|
311
|
+
zod: "^4.4.3"
|
|
312
|
+
},
|
|
313
|
+
devDependencies: {
|
|
314
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
315
|
+
"@types/node": "^22.10.0",
|
|
316
|
+
"@types/pg": "^8.20.0",
|
|
317
|
+
"@types/react": "^19.2.17",
|
|
318
|
+
"@types/react-dom": "^19.2.3",
|
|
319
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
320
|
+
esbuild: "^0.28.0",
|
|
321
|
+
react: "^19.2.7",
|
|
322
|
+
"react-dom": "^19.2.7",
|
|
323
|
+
"react-router-dom": "^6.30.3",
|
|
324
|
+
"tsc-alias": "^1.8.17",
|
|
325
|
+
tsx: "^4.19.0",
|
|
326
|
+
typescript: "^6.0.3",
|
|
327
|
+
vite: "^8.0.16",
|
|
328
|
+
vitest: "^4.1.8"
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
// src/shared/version.ts
|
|
333
|
+
var NLM_VERSION = package_default.version;
|
|
334
|
+
|
|
335
|
+
// src/core/hook/hook-log.ts
|
|
336
|
+
function logPath(tenantId) {
|
|
337
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
338
|
+
return process.env["NLM_HOOK_LOG"] ?? tenantStatePath(tenantId, "hook-log.jsonl");
|
|
339
|
+
}
|
|
340
|
+
return tenantStatePath(tenantId, "hook-log.jsonl");
|
|
341
|
+
}
|
|
342
|
+
function appendHookLog(tenantId, entry) {
|
|
203
343
|
try {
|
|
204
|
-
const path = logPath();
|
|
344
|
+
const path = logPath(tenantId);
|
|
205
345
|
mkdirSync(dirname(path), { recursive: true });
|
|
206
|
-
appendFileSync(path, `${JSON.stringify(entry)}
|
|
346
|
+
appendFileSync(path, `${JSON.stringify({ ...entry, v: NLM_VERSION })}
|
|
207
347
|
`, "utf8");
|
|
208
348
|
} catch {
|
|
209
349
|
}
|
|
@@ -219,18 +359,20 @@ import {
|
|
|
219
359
|
statSync,
|
|
220
360
|
writeFileSync
|
|
221
361
|
} from "node:fs";
|
|
222
|
-
import { homedir as homedir2 } from "node:os";
|
|
223
362
|
import { join as join2 } from "node:path";
|
|
224
|
-
function stateDir() {
|
|
225
|
-
|
|
363
|
+
function stateDir(tenantId) {
|
|
364
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
365
|
+
return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
|
|
366
|
+
}
|
|
367
|
+
return tenantStatePath(tenantId, "hook-state");
|
|
226
368
|
}
|
|
227
|
-
function memoPath(conversationId) {
|
|
369
|
+
function memoPath(tenantId, conversationId) {
|
|
228
370
|
const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
229
|
-
return join2(stateDir(), `${safe}.json`);
|
|
371
|
+
return join2(stateDir(tenantId), `${safe}.json`);
|
|
230
372
|
}
|
|
231
|
-
function loadSurfaced(conversationId) {
|
|
373
|
+
function loadSurfaced(tenantId, conversationId) {
|
|
232
374
|
try {
|
|
233
|
-
const path = memoPath(conversationId);
|
|
375
|
+
const path = memoPath(tenantId, conversationId);
|
|
234
376
|
if (!existsSync2(path)) return /* @__PURE__ */ new Set();
|
|
235
377
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
236
378
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
@@ -239,12 +381,12 @@ function loadSurfaced(conversationId) {
|
|
|
239
381
|
return /* @__PURE__ */ new Set();
|
|
240
382
|
}
|
|
241
383
|
}
|
|
242
|
-
function recordSurfaced(conversationId, ids) {
|
|
384
|
+
function recordSurfaced(tenantId, conversationId, ids) {
|
|
243
385
|
try {
|
|
244
|
-
const merged = loadSurfaced(conversationId);
|
|
386
|
+
const merged = loadSurfaced(tenantId, conversationId);
|
|
245
387
|
for (const id of ids) merged.add(id);
|
|
246
|
-
mkdirSync2(stateDir(), { recursive: true });
|
|
247
|
-
writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
|
|
388
|
+
mkdirSync2(stateDir(tenantId), { recursive: true });
|
|
389
|
+
writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
|
|
248
390
|
} catch {
|
|
249
391
|
}
|
|
250
392
|
}
|
|
@@ -270,8 +412,8 @@ function truncateSummary(s, max = 200) {
|
|
|
270
412
|
}
|
|
271
413
|
return window + " ...";
|
|
272
414
|
}
|
|
273
|
-
function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
274
|
-
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0) return "";
|
|
415
|
+
function formatPointerBlock(hits, facts = [], exemplars = [], concepts = []) {
|
|
416
|
+
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0 && concepts.length === 0) return "";
|
|
275
417
|
const out = [];
|
|
276
418
|
if (hits.length > 0) {
|
|
277
419
|
out.push("## Possibly-relevant prior sessions (nlm-memory)");
|
|
@@ -300,7 +442,19 @@ function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
|
300
442
|
out.push(`- [${e.outcome}] ${langPart}${e.repo} - ${truncateSummary(e.taskContext)}`);
|
|
301
443
|
}
|
|
302
444
|
}
|
|
303
|
-
|
|
445
|
+
if (concepts.length > 0) {
|
|
446
|
+
if (out.length > 0) out.push("");
|
|
447
|
+
out.push("## Learning state (nlm-memory)");
|
|
448
|
+
for (const c of concepts) {
|
|
449
|
+
const n = c.attemptCount === 1 ? "1 attempt" : `${c.attemptCount} attempts`;
|
|
450
|
+
out.push(`- [${c.status}] ${c.concept} (${n})`);
|
|
451
|
+
}
|
|
452
|
+
const nextSteps = [...new Set(concepts.map((c) => c.nextStep).filter((s) => !!s))].slice(0, 2);
|
|
453
|
+
for (const next of nextSteps) {
|
|
454
|
+
out.push(`Next: ${truncateSummary(next, 120)}`);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const tools = exemplars.length > 0 ? "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved), recall_code (pull the full code for a related exemplar), learner_summary (concept mastery + next step)." : "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved), learner_summary (concept mastery + next step).";
|
|
304
458
|
out.push(tools);
|
|
305
459
|
return out.join("\n");
|
|
306
460
|
}
|
|
@@ -312,10 +466,10 @@ function medianScore(hits) {
|
|
|
312
466
|
return sorted[Math.floor(sorted.length / 2)] ?? 0;
|
|
313
467
|
}
|
|
314
468
|
function selectHits(params) {
|
|
315
|
-
const { hits, surfaced, scoreThreshold, perFireCap, perConversationCap, relativeFloor = 0 } = params;
|
|
316
|
-
const relCut =
|
|
469
|
+
const { hits, surfaced, scoreThreshold: scoreThreshold2, perFireCap, perConversationCap, relativeFloor: relativeFloor2 = 0 } = params;
|
|
470
|
+
const relCut = relativeFloor2 > 0 ? relativeFloor2 * medianScore(hits) : 0;
|
|
317
471
|
const eligible = hits.filter(
|
|
318
|
-
(h) => h.matchScore >=
|
|
472
|
+
(h) => h.matchScore >= scoreThreshold2 && h.matchScore >= relCut && !surfaced.has(h.id)
|
|
319
473
|
);
|
|
320
474
|
const budget = Math.max(0, perConversationCap - surfaced.size);
|
|
321
475
|
const limit = Math.min(perFireCap, budget);
|
|
@@ -324,7 +478,7 @@ function selectHits(params) {
|
|
|
324
478
|
|
|
325
479
|
// src/llm/env-autoload.ts
|
|
326
480
|
import { readFileSync as readFileSync2, existsSync as existsSync3 } from "node:fs";
|
|
327
|
-
import { homedir as
|
|
481
|
+
import { homedir as homedir2 } from "node:os";
|
|
328
482
|
import { resolve } from "node:path";
|
|
329
483
|
var DEFAULT_SEARCH_PATHS = [
|
|
330
484
|
"~/.nlm/.env",
|
|
@@ -333,7 +487,7 @@ var DEFAULT_SEARCH_PATHS = [
|
|
|
333
487
|
"../../.env"
|
|
334
488
|
];
|
|
335
489
|
function expandHome(p) {
|
|
336
|
-
if (p.startsWith("~/")) return resolve(
|
|
490
|
+
if (p.startsWith("~/")) return resolve(homedir2(), p.slice(2));
|
|
337
491
|
return p;
|
|
338
492
|
}
|
|
339
493
|
function autoloadEnv(extraPaths = []) {
|
|
@@ -515,6 +669,18 @@ function extractRecallQuery(prompt) {
|
|
|
515
669
|
}
|
|
516
670
|
|
|
517
671
|
// src/hook/hook-helpers.ts
|
|
672
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, realpathSync } from "node:fs";
|
|
673
|
+
import { pathToFileURL } from "node:url";
|
|
674
|
+
function isMainModule(metaUrl, argv1) {
|
|
675
|
+
if (!argv1) return false;
|
|
676
|
+
let resolved;
|
|
677
|
+
try {
|
|
678
|
+
resolved = realpathSync(argv1);
|
|
679
|
+
} catch {
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
return metaUrl === pathToFileURL(resolved).href;
|
|
683
|
+
}
|
|
518
684
|
function readStdin() {
|
|
519
685
|
return new Promise((resolve2) => {
|
|
520
686
|
let data = "";
|
|
@@ -547,27 +713,36 @@ function parseRecallTimeout(raw) {
|
|
|
547
713
|
const n = Number(raw);
|
|
548
714
|
return Number.isFinite(n) && n > 0 ? n : 4e3;
|
|
549
715
|
}
|
|
550
|
-
|
|
551
|
-
|
|
716
|
+
function recallTimeoutMs() {
|
|
717
|
+
return parseRecallTimeout(process.env["NLM_HOOK_RECALL_TIMEOUT_MS"]);
|
|
718
|
+
}
|
|
719
|
+
var emptyResult = (outcome) => ({
|
|
720
|
+
hits: [],
|
|
721
|
+
facts: [],
|
|
722
|
+
exemplars: [],
|
|
723
|
+
concepts: [],
|
|
724
|
+
outcome
|
|
725
|
+
});
|
|
726
|
+
async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword", source = "hook") {
|
|
552
727
|
const query = extractRecallQuery(prompt);
|
|
553
|
-
if (query === null) return
|
|
728
|
+
if (query === null) return emptyResult("skipped");
|
|
554
729
|
const portValue = process.env["NLM_PORT"] ?? DEFAULT_NLM_PORT;
|
|
555
730
|
const url = (
|
|
556
731
|
// 127.0.0.1, not localhost: each hook is a fresh process with no connection
|
|
557
732
|
// reuse, and Node resolves localhost to IPv6 ::1 first — a measured ~50-300ms
|
|
558
733
|
// per-fire connect penalty vs ~3ms on the explicit IPv4 loopback.
|
|
559
|
-
`http://127.0.0.1:${portValue}/api/recall?q=${encodeURIComponent(query)}&mode=${mode}&limit=${RECALL_LIMIT}&withFacts=true&withExemplars=true` + (conversationId ? `&conversation_id=${encodeURIComponent(conversationId)}` : "")
|
|
734
|
+
`http://127.0.0.1:${portValue}/api/recall?q=${encodeURIComponent(query)}&mode=${mode}&limit=${RECALL_LIMIT}&withFacts=true&withExemplars=true&withConcepts=true` + (conversationId ? `&conversation_id=${encodeURIComponent(conversationId)}` : "")
|
|
560
735
|
);
|
|
561
736
|
try {
|
|
562
|
-
const extra = { "x-recall-source":
|
|
737
|
+
const extra = { "x-recall-source": source };
|
|
563
738
|
if (runtime) extra["x-recall-runtime"] = runtime;
|
|
564
|
-
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) },
|
|
565
|
-
if (!res.ok) return
|
|
739
|
+
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) }, recallTimeoutMs());
|
|
740
|
+
if (!res.ok) return emptyResult("http-error");
|
|
566
741
|
let body;
|
|
567
742
|
try {
|
|
568
743
|
body = await res.json();
|
|
569
744
|
} catch {
|
|
570
|
-
return
|
|
745
|
+
return emptyResult("http-error");
|
|
571
746
|
}
|
|
572
747
|
const hits = (body.results ?? []).map((r) => ({
|
|
573
748
|
id: r.id,
|
|
@@ -588,9 +763,16 @@ async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword")
|
|
|
588
763
|
repo: e.repo,
|
|
589
764
|
taskContext: e.taskContext
|
|
590
765
|
}));
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
766
|
+
const concepts = (body.relatedConcepts ?? []).map((c) => ({
|
|
767
|
+
concept: c.concept,
|
|
768
|
+
status: c.status,
|
|
769
|
+
attemptCount: c.attemptCount,
|
|
770
|
+
nextStep: c.nextStep
|
|
771
|
+
}));
|
|
772
|
+
return { hits, facts, exemplars, concepts, outcome: "ok" };
|
|
773
|
+
} catch (err) {
|
|
774
|
+
const aborted = err instanceof Error && err.name === "AbortError";
|
|
775
|
+
return emptyResult(aborted ? "timeout" : "unreachable");
|
|
594
776
|
}
|
|
595
777
|
}
|
|
596
778
|
|
|
@@ -657,8 +839,8 @@ ${candidate}` }
|
|
|
657
839
|
}
|
|
658
840
|
|
|
659
841
|
// src/hook/prompt-recall-hook.ts
|
|
660
|
-
var
|
|
661
|
-
var
|
|
842
|
+
var scoreThreshold = () => parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
|
|
843
|
+
var relativeFloor = () => parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
|
|
662
844
|
var PER_FIRE_CAP = 3;
|
|
663
845
|
var PER_CONVERSATION_CAP = 10;
|
|
664
846
|
var PROMPT_PREVIEW_CHARS = 200;
|
|
@@ -667,7 +849,9 @@ function parseHookDeadline(raw, defaultMs = 4e3) {
|
|
|
667
849
|
const n = Number(raw);
|
|
668
850
|
return Number.isFinite(n) && n > 0 ? n : defaultMs;
|
|
669
851
|
}
|
|
670
|
-
|
|
852
|
+
function hookDeadlineMs() {
|
|
853
|
+
return parseHookDeadline(process.env["NLM_HOOK_DEADLINE_MS"], 6e3);
|
|
854
|
+
}
|
|
671
855
|
async function withDeadline(p, ms, fallback) {
|
|
672
856
|
if (ms <= 0) return fallback;
|
|
673
857
|
let timer;
|
|
@@ -705,7 +889,7 @@ async function runHook(input, deps) {
|
|
|
705
889
|
const gate = classifyPrompt(input.prompt);
|
|
706
890
|
const preview = input.prompt.slice(0, PROMPT_PREVIEW_CHARS);
|
|
707
891
|
if (gate === "generative" || gate === "skip") {
|
|
708
|
-
appendHookLog({
|
|
892
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
709
893
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
710
894
|
conversationId: input.conversationId,
|
|
711
895
|
promptPreview: preview,
|
|
@@ -717,22 +901,26 @@ async function runHook(input, deps) {
|
|
|
717
901
|
});
|
|
718
902
|
return "";
|
|
719
903
|
}
|
|
720
|
-
const deadline = Date.now() + (deps.deadlineMs ??
|
|
721
|
-
let fetched = { hits: [], facts: [] };
|
|
904
|
+
const deadline = Date.now() + (deps.deadlineMs ?? hookDeadlineMs());
|
|
905
|
+
let fetched = { hits: [], facts: [], outcome: "timeout" };
|
|
722
906
|
try {
|
|
723
907
|
fetched = normalizeRecall(
|
|
724
|
-
await withDeadline(
|
|
908
|
+
await withDeadline(
|
|
909
|
+
deps.recall(buildRecallQuery(input)),
|
|
910
|
+
deadline - Date.now(),
|
|
911
|
+
{ hits: [], facts: [], outcome: "timeout" }
|
|
912
|
+
)
|
|
725
913
|
);
|
|
726
914
|
} catch {
|
|
727
|
-
fetched = { hits: [], facts: [] };
|
|
915
|
+
fetched = { hits: [], facts: [], outcome: "unreachable" };
|
|
728
916
|
}
|
|
729
917
|
const hits = fetched.hits;
|
|
730
|
-
const surfaced = loadSurfaced(input.conversationId);
|
|
918
|
+
const surfaced = loadSurfaced(DEFAULT_TEAM_ID, input.conversationId);
|
|
731
919
|
const selected = selectHits({
|
|
732
920
|
hits,
|
|
733
921
|
surfaced,
|
|
734
|
-
scoreThreshold:
|
|
735
|
-
relativeFloor:
|
|
922
|
+
scoreThreshold: scoreThreshold(),
|
|
923
|
+
relativeFloor: relativeFloor(),
|
|
736
924
|
perFireCap: PER_FIRE_CAP,
|
|
737
925
|
perConversationCap: PER_CONVERSATION_CAP
|
|
738
926
|
});
|
|
@@ -758,9 +946,9 @@ ${h.summary ?? ""}`) }))),
|
|
|
758
946
|
injected = selected.filter((h) => !drop.has(h.id));
|
|
759
947
|
}
|
|
760
948
|
}
|
|
761
|
-
const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars);
|
|
949
|
+
const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars, fetched.concepts ?? []);
|
|
762
950
|
const estTokens = Math.ceil(block.length / 4);
|
|
763
|
-
appendHookLog({
|
|
951
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
764
952
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
765
953
|
conversationId: input.conversationId,
|
|
766
954
|
promptPreview: preview,
|
|
@@ -769,10 +957,11 @@ ${h.summary ?? ""}`) }))),
|
|
|
769
957
|
wouldInject: injected.map((h) => h.id),
|
|
770
958
|
estTokens,
|
|
771
959
|
mode: deps.mode,
|
|
960
|
+
...fetched.outcome ? { recallOutcome: fetched.outcome } : {},
|
|
772
961
|
...gateDecisions ? { gateDecisions } : {}
|
|
773
962
|
});
|
|
774
963
|
if (deps.mode === "live" && injected.length > 0) {
|
|
775
|
-
recordSurfaced(input.conversationId, injected.map((h) => h.id));
|
|
964
|
+
recordSurfaced(DEFAULT_TEAM_ID, input.conversationId, injected.map((h) => h.id));
|
|
776
965
|
return block;
|
|
777
966
|
}
|
|
778
967
|
return "";
|
|
@@ -804,12 +993,12 @@ async function main() {
|
|
|
804
993
|
} catch {
|
|
805
994
|
}
|
|
806
995
|
}
|
|
807
|
-
if (
|
|
996
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
808
997
|
void main();
|
|
809
998
|
}
|
|
810
999
|
export {
|
|
811
|
-
HOOK_DEADLINE_MS,
|
|
812
1000
|
buildRecallQuery,
|
|
1001
|
+
hookDeadlineMs,
|
|
813
1002
|
hookRuntimeFromEnv,
|
|
814
1003
|
parseHookDeadline,
|
|
815
1004
|
promptRecallEnabled,
|