nlm-memory 0.21.0 → 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 +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 +45 -13
- 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
package/nlm/index.js
CHANGED
|
@@ -191,6 +191,133 @@ function extractRecallQuery(prompt) {
|
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
// src/hook/hook-helpers.ts
|
|
194
|
+
import { appendFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
195
|
+
import { pathToFileURL } from "node:url";
|
|
196
|
+
|
|
197
|
+
// package.json
|
|
198
|
+
var package_default = {
|
|
199
|
+
name: "nlm-memory",
|
|
200
|
+
version: "0.21.12",
|
|
201
|
+
description: "Local-first non-linear memory operating system for AI operators.",
|
|
202
|
+
type: "module",
|
|
203
|
+
license: "Apache-2.0",
|
|
204
|
+
engines: {
|
|
205
|
+
node: ">=22.0.0"
|
|
206
|
+
},
|
|
207
|
+
repository: {
|
|
208
|
+
type: "git",
|
|
209
|
+
url: "git+https://github.com/pbmagnet4/nlm-memory.git"
|
|
210
|
+
},
|
|
211
|
+
homepage: "https://github.com/pbmagnet4/nlm-memory#readme",
|
|
212
|
+
bugs: {
|
|
213
|
+
url: "https://github.com/pbmagnet4/nlm-memory/issues"
|
|
214
|
+
},
|
|
215
|
+
keywords: [
|
|
216
|
+
"ai",
|
|
217
|
+
"memory",
|
|
218
|
+
"mcp",
|
|
219
|
+
"claude-code",
|
|
220
|
+
"codex",
|
|
221
|
+
"hermes",
|
|
222
|
+
"local-first",
|
|
223
|
+
"recall",
|
|
224
|
+
"session-memory"
|
|
225
|
+
],
|
|
226
|
+
files: [
|
|
227
|
+
"dist",
|
|
228
|
+
"migrations",
|
|
229
|
+
"fixtures",
|
|
230
|
+
"templates",
|
|
231
|
+
"plugin",
|
|
232
|
+
"plugin-hermes-agent",
|
|
233
|
+
"nlm",
|
|
234
|
+
"assets",
|
|
235
|
+
"LICENSE",
|
|
236
|
+
"README.md"
|
|
237
|
+
],
|
|
238
|
+
bin: {
|
|
239
|
+
nlm: "dist/cli/nlm.js"
|
|
240
|
+
},
|
|
241
|
+
scripts: {
|
|
242
|
+
dev: "tsx watch src/cli/nlm.ts start",
|
|
243
|
+
start: "node dist/cli/nlm.js start",
|
|
244
|
+
"build:server": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
245
|
+
"build:ui": "vite build --config src/ui/vite.config.ts",
|
|
246
|
+
"build:codex-plugin": "node scripts/build-codex-plugin.mjs",
|
|
247
|
+
"verify:codex-release": "node scripts/verify-codex-release.mjs",
|
|
248
|
+
build: "npm run build:server && npm run build:ui && npm run build:codex-plugin",
|
|
249
|
+
prepare: "[ -d src ] && npm run build || true",
|
|
250
|
+
"ui:dev": "vite --config src/ui/vite.config.ts",
|
|
251
|
+
test: "vitest run",
|
|
252
|
+
"test:watch": "vitest",
|
|
253
|
+
"test:unit": "vitest run tests/unit",
|
|
254
|
+
"test:integration": "vitest run tests/integration",
|
|
255
|
+
"test:pg": "vitest run .pg.test.ts --test-timeout=20000",
|
|
256
|
+
typecheck: "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
|
|
257
|
+
"bench:longmemeval": "tsx scripts/longmemeval/run-harness.ts",
|
|
258
|
+
"bench:classifier": "tsx scripts/longmemeval/run-harness.ts --classifier",
|
|
259
|
+
"bench:compare": "tsx scripts/longmemeval/compare-classifiers.ts",
|
|
260
|
+
"eval:signals": "tsx scripts/eval/signals-eval.ts",
|
|
261
|
+
"eval:classifier": "tsx scripts/eval/classifier-eval.ts",
|
|
262
|
+
"eval:fact-recall": "tsx scripts/eval/fact-recall-eval.ts",
|
|
263
|
+
"eval:recall-impact-replay": "tsx scripts/eval/recall-impact-replay.ts",
|
|
264
|
+
"eval:code-exemplar": "tsx scripts/eval/code-exemplar-eval.ts",
|
|
265
|
+
"eval:reranker": "tsx scripts/eval/reranker-ablation.ts",
|
|
266
|
+
"eval:floor": "tsx scripts/eval/floor-calibration.ts",
|
|
267
|
+
"eval:matcher": "tsx scripts/eval/tune-matcher.ts",
|
|
268
|
+
"eval:naming": "tsx scripts/eval/tune-naming.ts",
|
|
269
|
+
"eval:rederiv-sample": "tsx scripts/eval/re-derivation-sample.ts",
|
|
270
|
+
"eval:rederiv-label": "tsx scripts/eval/re-derivation-label.ts",
|
|
271
|
+
"eval:rederiv-calibrate": "tsx scripts/eval/re-derivation-calibrate.ts"
|
|
272
|
+
},
|
|
273
|
+
dependencies: {
|
|
274
|
+
"@clack/prompts": "^1.4.0",
|
|
275
|
+
"@hono/node-server": "^2.0.3",
|
|
276
|
+
"@huggingface/transformers": "4.2.0",
|
|
277
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
278
|
+
"@toon-format/toon": "^2.3.0",
|
|
279
|
+
"better-sqlite3": "^13.0.1",
|
|
280
|
+
commander: "^15.0.0",
|
|
281
|
+
hono: "^4.6.0",
|
|
282
|
+
pg: "^8.21.0",
|
|
283
|
+
pgvector: "^0.3.0",
|
|
284
|
+
"sqlite-vec": "^0.1.6",
|
|
285
|
+
yaml: "^2.9.0",
|
|
286
|
+
zod: "^4.4.3"
|
|
287
|
+
},
|
|
288
|
+
devDependencies: {
|
|
289
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
290
|
+
"@types/node": "^22.10.0",
|
|
291
|
+
"@types/pg": "^8.20.0",
|
|
292
|
+
"@types/react": "^19.2.17",
|
|
293
|
+
"@types/react-dom": "^19.2.3",
|
|
294
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
295
|
+
esbuild: "^0.28.0",
|
|
296
|
+
react: "^19.2.7",
|
|
297
|
+
"react-dom": "^19.2.7",
|
|
298
|
+
"react-router-dom": "^6.30.3",
|
|
299
|
+
"tsc-alias": "^1.8.17",
|
|
300
|
+
tsx: "^4.19.0",
|
|
301
|
+
typescript: "^6.0.3",
|
|
302
|
+
vite: "^8.0.16",
|
|
303
|
+
vitest: "^4.1.8"
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// src/shared/version.ts
|
|
308
|
+
var NLM_VERSION = package_default.version;
|
|
309
|
+
|
|
310
|
+
// src/hook/hook-helpers.ts
|
|
311
|
+
function isMainModule(metaUrl, argv1) {
|
|
312
|
+
if (!argv1) return false;
|
|
313
|
+
let resolved;
|
|
314
|
+
try {
|
|
315
|
+
resolved = realpathSync(argv1);
|
|
316
|
+
} catch {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
return metaUrl === pathToFileURL(resolved).href;
|
|
320
|
+
}
|
|
194
321
|
function readStdin() {
|
|
195
322
|
return new Promise((resolve2) => {
|
|
196
323
|
let data = "";
|
|
@@ -223,27 +350,36 @@ function parseRecallTimeout(raw) {
|
|
|
223
350
|
const n = Number(raw);
|
|
224
351
|
return Number.isFinite(n) && n > 0 ? n : 4e3;
|
|
225
352
|
}
|
|
226
|
-
|
|
227
|
-
|
|
353
|
+
function recallTimeoutMs() {
|
|
354
|
+
return parseRecallTimeout(process.env["NLM_HOOK_RECALL_TIMEOUT_MS"]);
|
|
355
|
+
}
|
|
356
|
+
var emptyResult = (outcome) => ({
|
|
357
|
+
hits: [],
|
|
358
|
+
facts: [],
|
|
359
|
+
exemplars: [],
|
|
360
|
+
concepts: [],
|
|
361
|
+
outcome
|
|
362
|
+
});
|
|
363
|
+
async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword", source = "hook") {
|
|
228
364
|
const query = extractRecallQuery(prompt);
|
|
229
|
-
if (query === null) return
|
|
365
|
+
if (query === null) return emptyResult("skipped");
|
|
230
366
|
const portValue = process.env["NLM_PORT"] ?? DEFAULT_NLM_PORT;
|
|
231
367
|
const url = (
|
|
232
368
|
// 127.0.0.1, not localhost: each hook is a fresh process with no connection
|
|
233
369
|
// reuse, and Node resolves localhost to IPv6 ::1 first — a measured ~50-300ms
|
|
234
370
|
// per-fire connect penalty vs ~3ms on the explicit IPv4 loopback.
|
|
235
|
-
`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)}` : "")
|
|
371
|
+
`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)}` : "")
|
|
236
372
|
);
|
|
237
373
|
try {
|
|
238
|
-
const extra = { "x-recall-source":
|
|
374
|
+
const extra = { "x-recall-source": source };
|
|
239
375
|
if (runtime) extra["x-recall-runtime"] = runtime;
|
|
240
|
-
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) },
|
|
241
|
-
if (!res.ok) return
|
|
376
|
+
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) }, recallTimeoutMs());
|
|
377
|
+
if (!res.ok) return emptyResult("http-error");
|
|
242
378
|
let body;
|
|
243
379
|
try {
|
|
244
380
|
body = await res.json();
|
|
245
381
|
} catch {
|
|
246
|
-
return
|
|
382
|
+
return emptyResult("http-error");
|
|
247
383
|
}
|
|
248
384
|
const hits = (body.results ?? []).map((r) => ({
|
|
249
385
|
id: r.id,
|
|
@@ -264,15 +400,19 @@ async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword")
|
|
|
264
400
|
repo: e.repo,
|
|
265
401
|
taskContext: e.taskContext
|
|
266
402
|
}));
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
403
|
+
const concepts = (body.relatedConcepts ?? []).map((c) => ({
|
|
404
|
+
concept: c.concept,
|
|
405
|
+
status: c.status,
|
|
406
|
+
attemptCount: c.attemptCount,
|
|
407
|
+
nextStep: c.nextStep
|
|
408
|
+
}));
|
|
409
|
+
return { hits, facts, exemplars, concepts, outcome: "ok" };
|
|
410
|
+
} catch (err) {
|
|
411
|
+
const aborted = err instanceof Error && err.name === "AbortError";
|
|
412
|
+
return emptyResult(aborted ? "timeout" : "unreachable");
|
|
270
413
|
}
|
|
271
414
|
}
|
|
272
415
|
|
|
273
|
-
// src/hook/prompt-recall-hook.ts
|
|
274
|
-
import { pathToFileURL } from "node:url";
|
|
275
|
-
|
|
276
416
|
// src/core/hook/gate.ts
|
|
277
417
|
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;
|
|
278
418
|
var GENERATIVE_OPENER = /^(write|draft|create|compose|generate|brainstorm|design|outline|sketch|invent|rename|come up with)\b/i;
|
|
@@ -463,17 +603,47 @@ function recentConversationContext(transcriptPath, opts = {}) {
|
|
|
463
603
|
}
|
|
464
604
|
|
|
465
605
|
// src/core/hook/hook-log.ts
|
|
466
|
-
import { appendFileSync, mkdirSync } from "node:fs";
|
|
606
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync2 } from "node:fs";
|
|
607
|
+
import { dirname } from "node:path";
|
|
608
|
+
|
|
609
|
+
// src/core/tenancy/tenant-state-path.ts
|
|
610
|
+
import { createHash } from "node:crypto";
|
|
467
611
|
import { homedir as homedir2 } from "node:os";
|
|
468
|
-
import {
|
|
469
|
-
|
|
470
|
-
|
|
612
|
+
import { join } from "node:path";
|
|
613
|
+
|
|
614
|
+
// src/core/tenancy/default-team.ts
|
|
615
|
+
var DEFAULT_TEAM_ID = "team_local";
|
|
616
|
+
|
|
617
|
+
// src/core/tenancy/tenant-state-path.ts
|
|
618
|
+
var TENANTS_DIRNAME = "tenants";
|
|
619
|
+
var SAFE_TENANT_ID = /^[A-Za-z0-9_-]+$/;
|
|
620
|
+
function sanitizeTenantId(tenantId) {
|
|
621
|
+
if (SAFE_TENANT_ID.test(tenantId)) return tenantId;
|
|
622
|
+
const sanitized = tenantId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
623
|
+
const hash = createHash("sha256").update(tenantId).digest("hex").slice(0, 8);
|
|
624
|
+
return `${sanitized}_${hash}`;
|
|
625
|
+
}
|
|
626
|
+
function stateRoot() {
|
|
627
|
+
return process.env["NLM_STATE_ROOT"] || join(homedir2(), ".nlm");
|
|
628
|
+
}
|
|
629
|
+
function tenantStatePath(tenantId, ...segments) {
|
|
630
|
+
const base = stateRoot();
|
|
631
|
+
if (tenantId === DEFAULT_TEAM_ID) return join(base, ...segments);
|
|
632
|
+
return join(base, TENANTS_DIRNAME, sanitizeTenantId(tenantId), ...segments);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// src/core/hook/hook-log.ts
|
|
636
|
+
function logPath(tenantId) {
|
|
637
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
638
|
+
return process.env["NLM_HOOK_LOG"] ?? tenantStatePath(tenantId, "hook-log.jsonl");
|
|
639
|
+
}
|
|
640
|
+
return tenantStatePath(tenantId, "hook-log.jsonl");
|
|
471
641
|
}
|
|
472
|
-
function appendHookLog(entry) {
|
|
642
|
+
function appendHookLog(tenantId, entry) {
|
|
473
643
|
try {
|
|
474
|
-
const path = logPath();
|
|
475
|
-
|
|
476
|
-
|
|
644
|
+
const path = logPath(tenantId);
|
|
645
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
646
|
+
appendFileSync2(path, `${JSON.stringify({ ...entry, v: NLM_VERSION })}
|
|
477
647
|
`, "utf8");
|
|
478
648
|
} catch {
|
|
479
649
|
}
|
|
@@ -482,25 +652,27 @@ function appendHookLog(entry) {
|
|
|
482
652
|
// src/core/hook/memo.ts
|
|
483
653
|
import {
|
|
484
654
|
existsSync as existsSync3,
|
|
485
|
-
mkdirSync as
|
|
655
|
+
mkdirSync as mkdirSync3,
|
|
486
656
|
readdirSync,
|
|
487
657
|
readFileSync as readFileSync2,
|
|
488
658
|
rmSync,
|
|
489
659
|
statSync,
|
|
490
660
|
writeFileSync
|
|
491
661
|
} from "node:fs";
|
|
492
|
-
import { homedir as homedir3 } from "node:os";
|
|
493
662
|
import { join as join2 } from "node:path";
|
|
494
|
-
function stateDir() {
|
|
495
|
-
|
|
663
|
+
function stateDir(tenantId) {
|
|
664
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
665
|
+
return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
|
|
666
|
+
}
|
|
667
|
+
return tenantStatePath(tenantId, "hook-state");
|
|
496
668
|
}
|
|
497
|
-
function memoPath(conversationId) {
|
|
669
|
+
function memoPath(tenantId, conversationId) {
|
|
498
670
|
const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
499
|
-
return join2(stateDir(), `${safe}.json`);
|
|
671
|
+
return join2(stateDir(tenantId), `${safe}.json`);
|
|
500
672
|
}
|
|
501
|
-
function loadSurfaced(conversationId) {
|
|
673
|
+
function loadSurfaced(tenantId, conversationId) {
|
|
502
674
|
try {
|
|
503
|
-
const path = memoPath(conversationId);
|
|
675
|
+
const path = memoPath(tenantId, conversationId);
|
|
504
676
|
if (!existsSync3(path)) return /* @__PURE__ */ new Set();
|
|
505
677
|
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
506
678
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
@@ -509,12 +681,12 @@ function loadSurfaced(conversationId) {
|
|
|
509
681
|
return /* @__PURE__ */ new Set();
|
|
510
682
|
}
|
|
511
683
|
}
|
|
512
|
-
function recordSurfaced(conversationId, ids) {
|
|
684
|
+
function recordSurfaced(tenantId, conversationId, ids) {
|
|
513
685
|
try {
|
|
514
|
-
const merged = loadSurfaced(conversationId);
|
|
686
|
+
const merged = loadSurfaced(tenantId, conversationId);
|
|
515
687
|
for (const id of ids) merged.add(id);
|
|
516
|
-
|
|
517
|
-
writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
|
|
688
|
+
mkdirSync3(stateDir(tenantId), { recursive: true });
|
|
689
|
+
writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
|
|
518
690
|
} catch {
|
|
519
691
|
}
|
|
520
692
|
}
|
|
@@ -540,8 +712,8 @@ function truncateSummary(s, max = 200) {
|
|
|
540
712
|
}
|
|
541
713
|
return window + " ...";
|
|
542
714
|
}
|
|
543
|
-
function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
544
|
-
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0) return "";
|
|
715
|
+
function formatPointerBlock(hits, facts = [], exemplars = [], concepts = []) {
|
|
716
|
+
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0 && concepts.length === 0) return "";
|
|
545
717
|
const out = [];
|
|
546
718
|
if (hits.length > 0) {
|
|
547
719
|
out.push("## Possibly-relevant prior sessions (nlm-memory)");
|
|
@@ -570,7 +742,19 @@ function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
|
570
742
|
out.push(`- [${e.outcome}] ${langPart}${e.repo} - ${truncateSummary(e.taskContext)}`);
|
|
571
743
|
}
|
|
572
744
|
}
|
|
573
|
-
|
|
745
|
+
if (concepts.length > 0) {
|
|
746
|
+
if (out.length > 0) out.push("");
|
|
747
|
+
out.push("## Learning state (nlm-memory)");
|
|
748
|
+
for (const c of concepts) {
|
|
749
|
+
const n = c.attemptCount === 1 ? "1 attempt" : `${c.attemptCount} attempts`;
|
|
750
|
+
out.push(`- [${c.status}] ${c.concept} (${n})`);
|
|
751
|
+
}
|
|
752
|
+
const nextSteps = [...new Set(concepts.map((c) => c.nextStep).filter((s) => !!s))].slice(0, 2);
|
|
753
|
+
for (const next of nextSteps) {
|
|
754
|
+
out.push(`Next: ${truncateSummary(next, 120)}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
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).";
|
|
574
758
|
out.push(tools);
|
|
575
759
|
return out.join("\n");
|
|
576
760
|
}
|
|
@@ -582,10 +766,10 @@ function medianScore(hits) {
|
|
|
582
766
|
return sorted[Math.floor(sorted.length / 2)] ?? 0;
|
|
583
767
|
}
|
|
584
768
|
function selectHits(params) {
|
|
585
|
-
const { hits, surfaced, scoreThreshold, perFireCap, perConversationCap, relativeFloor = 0 } = params;
|
|
586
|
-
const relCut =
|
|
769
|
+
const { hits, surfaced, scoreThreshold: scoreThreshold2, perFireCap, perConversationCap, relativeFloor: relativeFloor2 = 0 } = params;
|
|
770
|
+
const relCut = relativeFloor2 > 0 ? relativeFloor2 * medianScore(hits) : 0;
|
|
587
771
|
const eligible = hits.filter(
|
|
588
|
-
(h) => h.matchScore >=
|
|
772
|
+
(h) => h.matchScore >= scoreThreshold2 && h.matchScore >= relCut && !surfaced.has(h.id)
|
|
589
773
|
);
|
|
590
774
|
const budget = Math.max(0, perConversationCap - surfaced.size);
|
|
591
775
|
const limit = Math.min(perFireCap, budget);
|
|
@@ -655,8 +839,8 @@ ${candidate}` }
|
|
|
655
839
|
}
|
|
656
840
|
|
|
657
841
|
// src/hook/prompt-recall-hook.ts
|
|
658
|
-
var
|
|
659
|
-
var
|
|
842
|
+
var scoreThreshold = () => parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
|
|
843
|
+
var relativeFloor = () => parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
|
|
660
844
|
var PER_FIRE_CAP = 3;
|
|
661
845
|
var PER_CONVERSATION_CAP = 10;
|
|
662
846
|
var PROMPT_PREVIEW_CHARS = 200;
|
|
@@ -665,7 +849,9 @@ function parseHookDeadline(raw, defaultMs = 4e3) {
|
|
|
665
849
|
const n = Number(raw);
|
|
666
850
|
return Number.isFinite(n) && n > 0 ? n : defaultMs;
|
|
667
851
|
}
|
|
668
|
-
|
|
852
|
+
function hookDeadlineMs() {
|
|
853
|
+
return parseHookDeadline(process.env["NLM_HOOK_DEADLINE_MS"], 6e3);
|
|
854
|
+
}
|
|
669
855
|
async function withDeadline(p, ms, fallback) {
|
|
670
856
|
if (ms <= 0) return fallback;
|
|
671
857
|
let timer;
|
|
@@ -703,7 +889,7 @@ async function runHook(input, deps) {
|
|
|
703
889
|
const gate = classifyPrompt(input.prompt);
|
|
704
890
|
const preview = input.prompt.slice(0, PROMPT_PREVIEW_CHARS);
|
|
705
891
|
if (gate === "generative" || gate === "skip") {
|
|
706
|
-
appendHookLog({
|
|
892
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
707
893
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
708
894
|
conversationId: input.conversationId,
|
|
709
895
|
promptPreview: preview,
|
|
@@ -715,22 +901,26 @@ async function runHook(input, deps) {
|
|
|
715
901
|
});
|
|
716
902
|
return "";
|
|
717
903
|
}
|
|
718
|
-
const deadline = Date.now() + (deps.deadlineMs ??
|
|
719
|
-
let fetched = { hits: [], facts: [] };
|
|
904
|
+
const deadline = Date.now() + (deps.deadlineMs ?? hookDeadlineMs());
|
|
905
|
+
let fetched = { hits: [], facts: [], outcome: "timeout" };
|
|
720
906
|
try {
|
|
721
907
|
fetched = normalizeRecall(
|
|
722
|
-
await withDeadline(
|
|
908
|
+
await withDeadline(
|
|
909
|
+
deps.recall(buildRecallQuery(input)),
|
|
910
|
+
deadline - Date.now(),
|
|
911
|
+
{ hits: [], facts: [], outcome: "timeout" }
|
|
912
|
+
)
|
|
723
913
|
);
|
|
724
914
|
} catch {
|
|
725
|
-
fetched = { hits: [], facts: [] };
|
|
915
|
+
fetched = { hits: [], facts: [], outcome: "unreachable" };
|
|
726
916
|
}
|
|
727
917
|
const hits = fetched.hits;
|
|
728
|
-
const surfaced = loadSurfaced(input.conversationId);
|
|
918
|
+
const surfaced = loadSurfaced(DEFAULT_TEAM_ID, input.conversationId);
|
|
729
919
|
const selected = selectHits({
|
|
730
920
|
hits,
|
|
731
921
|
surfaced,
|
|
732
|
-
scoreThreshold:
|
|
733
|
-
relativeFloor:
|
|
922
|
+
scoreThreshold: scoreThreshold(),
|
|
923
|
+
relativeFloor: relativeFloor(),
|
|
734
924
|
perFireCap: PER_FIRE_CAP,
|
|
735
925
|
perConversationCap: PER_CONVERSATION_CAP
|
|
736
926
|
});
|
|
@@ -756,9 +946,9 @@ ${h.summary ?? ""}`) }))),
|
|
|
756
946
|
injected = selected.filter((h) => !drop.has(h.id));
|
|
757
947
|
}
|
|
758
948
|
}
|
|
759
|
-
const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars);
|
|
949
|
+
const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars, fetched.concepts ?? []);
|
|
760
950
|
const estTokens = Math.ceil(block.length / 4);
|
|
761
|
-
appendHookLog({
|
|
951
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
762
952
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
763
953
|
conversationId: input.conversationId,
|
|
764
954
|
promptPreview: preview,
|
|
@@ -767,10 +957,11 @@ ${h.summary ?? ""}`) }))),
|
|
|
767
957
|
wouldInject: injected.map((h) => h.id),
|
|
768
958
|
estTokens,
|
|
769
959
|
mode: deps.mode,
|
|
960
|
+
...fetched.outcome ? { recallOutcome: fetched.outcome } : {},
|
|
770
961
|
...gateDecisions ? { gateDecisions } : {}
|
|
771
962
|
});
|
|
772
963
|
if (deps.mode === "live" && injected.length > 0) {
|
|
773
|
-
recordSurfaced(input.conversationId, injected.map((h) => h.id));
|
|
964
|
+
recordSurfaced(DEFAULT_TEAM_ID, input.conversationId, injected.map((h) => h.id));
|
|
774
965
|
return block;
|
|
775
966
|
}
|
|
776
967
|
return "";
|
|
@@ -802,7 +993,7 @@ async function main() {
|
|
|
802
993
|
} catch {
|
|
803
994
|
}
|
|
804
995
|
}
|
|
805
|
-
if (
|
|
996
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
806
997
|
void main();
|
|
807
998
|
}
|
|
808
999
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nlm-memory",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.12",
|
|
4
4
|
"description": "Local-first non-linear memory operating system for AI operators.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
"build:server": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
48
48
|
"build:ui": "vite build --config src/ui/vite.config.ts",
|
|
49
49
|
"build:codex-plugin": "node scripts/build-codex-plugin.mjs",
|
|
50
|
+
"verify:codex-release": "node scripts/verify-codex-release.mjs",
|
|
50
51
|
"build": "npm run build:server && npm run build:ui && npm run build:codex-plugin",
|
|
51
52
|
"prepare": "[ -d src ] && npm run build || true",
|
|
52
53
|
"ui:dev": "vite --config src/ui/vite.config.ts",
|
|
@@ -54,19 +55,23 @@
|
|
|
54
55
|
"test:watch": "vitest",
|
|
55
56
|
"test:unit": "vitest run tests/unit",
|
|
56
57
|
"test:integration": "vitest run tests/integration",
|
|
57
|
-
"test:pg": "vitest run
|
|
58
|
-
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json",
|
|
58
|
+
"test:pg": "vitest run .pg.test.ts --test-timeout=20000",
|
|
59
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
|
|
59
60
|
"bench:longmemeval": "tsx scripts/longmemeval/run-harness.ts",
|
|
60
61
|
"bench:classifier": "tsx scripts/longmemeval/run-harness.ts --classifier",
|
|
61
62
|
"bench:compare": "tsx scripts/longmemeval/compare-classifiers.ts",
|
|
62
63
|
"eval:signals": "tsx scripts/eval/signals-eval.ts",
|
|
63
64
|
"eval:classifier": "tsx scripts/eval/classifier-eval.ts",
|
|
64
65
|
"eval:fact-recall": "tsx scripts/eval/fact-recall-eval.ts",
|
|
66
|
+
"eval:recall-impact-replay": "tsx scripts/eval/recall-impact-replay.ts",
|
|
65
67
|
"eval:code-exemplar": "tsx scripts/eval/code-exemplar-eval.ts",
|
|
66
68
|
"eval:reranker": "tsx scripts/eval/reranker-ablation.ts",
|
|
67
69
|
"eval:floor": "tsx scripts/eval/floor-calibration.ts",
|
|
68
70
|
"eval:matcher": "tsx scripts/eval/tune-matcher.ts",
|
|
69
|
-
"eval:naming": "tsx scripts/eval/tune-naming.ts"
|
|
71
|
+
"eval:naming": "tsx scripts/eval/tune-naming.ts",
|
|
72
|
+
"eval:rederiv-sample": "tsx scripts/eval/re-derivation-sample.ts",
|
|
73
|
+
"eval:rederiv-label": "tsx scripts/eval/re-derivation-label.ts",
|
|
74
|
+
"eval:rederiv-calibrate": "tsx scripts/eval/re-derivation-calibrate.ts"
|
|
70
75
|
},
|
|
71
76
|
"dependencies": {
|
|
72
77
|
"@clack/prompts": "^1.4.0",
|
|
@@ -74,7 +79,7 @@
|
|
|
74
79
|
"@huggingface/transformers": "4.2.0",
|
|
75
80
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
76
81
|
"@toon-format/toon": "^2.3.0",
|
|
77
|
-
"better-sqlite3": "^
|
|
82
|
+
"better-sqlite3": "^13.0.1",
|
|
78
83
|
"commander": "^15.0.0",
|
|
79
84
|
"hono": "^4.6.0",
|
|
80
85
|
"pg": "^8.21.0",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nlm-memory",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.12",
|
|
4
4
|
"description": "Local-first persistent memory for AI coding agents. Recalls relevant prior sessions on every prompt; learns which sessions actually get cited. Owner-edited timeline beats append-only memory layers.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Edward Chalupa",
|
|
@@ -19,4 +19,4 @@
|
|
|
19
19
|
],
|
|
20
20
|
"mcpServers": "./.mcp.json",
|
|
21
21
|
"hooks": "./hooks/hooks.json"
|
|
22
|
-
}
|
|
22
|
+
}
|