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,20 +1,163 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/hook/session-start-hook.ts
|
|
4
|
-
import {
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
5
|
|
|
6
6
|
// src/core/hook/hook-log.ts
|
|
7
7
|
import { appendFileSync, mkdirSync } from "node:fs";
|
|
8
|
+
import { dirname } from "node:path";
|
|
9
|
+
|
|
10
|
+
// src/core/tenancy/tenant-state-path.ts
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
8
12
|
import { homedir } from "node:os";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
|
|
15
|
+
// src/core/tenancy/default-team.ts
|
|
16
|
+
var DEFAULT_TEAM_ID = "team_local";
|
|
17
|
+
|
|
18
|
+
// src/core/tenancy/tenant-state-path.ts
|
|
19
|
+
var TENANTS_DIRNAME = "tenants";
|
|
20
|
+
var SAFE_TENANT_ID = /^[A-Za-z0-9_-]+$/;
|
|
21
|
+
function sanitizeTenantId(tenantId) {
|
|
22
|
+
if (SAFE_TENANT_ID.test(tenantId)) return tenantId;
|
|
23
|
+
const sanitized = tenantId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
24
|
+
const hash = createHash("sha256").update(tenantId).digest("hex").slice(0, 8);
|
|
25
|
+
return `${sanitized}_${hash}`;
|
|
26
|
+
}
|
|
27
|
+
function stateRoot() {
|
|
28
|
+
return process.env["NLM_STATE_ROOT"] || join(homedir(), ".nlm");
|
|
29
|
+
}
|
|
30
|
+
function tenantStatePath(tenantId, ...segments) {
|
|
31
|
+
const base = stateRoot();
|
|
32
|
+
if (tenantId === DEFAULT_TEAM_ID) return join(base, ...segments);
|
|
33
|
+
return join(base, TENANTS_DIRNAME, sanitizeTenantId(tenantId), ...segments);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// package.json
|
|
37
|
+
var package_default = {
|
|
38
|
+
name: "nlm-memory",
|
|
39
|
+
version: "0.21.13",
|
|
40
|
+
description: "Local-first non-linear memory operating system for AI operators.",
|
|
41
|
+
type: "module",
|
|
42
|
+
license: "Apache-2.0",
|
|
43
|
+
engines: {
|
|
44
|
+
node: ">=22.0.0"
|
|
45
|
+
},
|
|
46
|
+
repository: {
|
|
47
|
+
type: "git",
|
|
48
|
+
url: "git+https://github.com/pbmagnet4/nlm-memory.git"
|
|
49
|
+
},
|
|
50
|
+
homepage: "https://github.com/pbmagnet4/nlm-memory#readme",
|
|
51
|
+
bugs: {
|
|
52
|
+
url: "https://github.com/pbmagnet4/nlm-memory/issues"
|
|
53
|
+
},
|
|
54
|
+
keywords: [
|
|
55
|
+
"ai",
|
|
56
|
+
"memory",
|
|
57
|
+
"mcp",
|
|
58
|
+
"claude-code",
|
|
59
|
+
"codex",
|
|
60
|
+
"hermes",
|
|
61
|
+
"local-first",
|
|
62
|
+
"recall",
|
|
63
|
+
"session-memory"
|
|
64
|
+
],
|
|
65
|
+
files: [
|
|
66
|
+
"dist",
|
|
67
|
+
"migrations",
|
|
68
|
+
"fixtures",
|
|
69
|
+
"templates",
|
|
70
|
+
"plugin",
|
|
71
|
+
"plugin-hermes-agent",
|
|
72
|
+
"nlm",
|
|
73
|
+
"assets",
|
|
74
|
+
"LICENSE",
|
|
75
|
+
"README.md"
|
|
76
|
+
],
|
|
77
|
+
bin: {
|
|
78
|
+
nlm: "dist/cli/nlm.js"
|
|
79
|
+
},
|
|
80
|
+
scripts: {
|
|
81
|
+
dev: "tsx watch src/cli/nlm.ts start",
|
|
82
|
+
start: "node dist/cli/nlm.js start",
|
|
83
|
+
"build:server": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
|
|
84
|
+
"build:ui": "vite build --config src/ui/vite.config.ts",
|
|
85
|
+
"build:codex-plugin": "node scripts/build-codex-plugin.mjs",
|
|
86
|
+
"verify:codex-release": "node scripts/verify-codex-release.mjs",
|
|
87
|
+
build: "npm run build:server && npm run build:ui && npm run build:codex-plugin",
|
|
88
|
+
prepare: "[ -d src ] && npm run build || true",
|
|
89
|
+
"ui:dev": "vite --config src/ui/vite.config.ts",
|
|
90
|
+
test: "vitest run",
|
|
91
|
+
"test:watch": "vitest",
|
|
92
|
+
"test:unit": "vitest run tests/unit",
|
|
93
|
+
"test:integration": "vitest run tests/integration",
|
|
94
|
+
"test:pg": "vitest run .pg.test.ts --test-timeout=20000",
|
|
95
|
+
typecheck: "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json",
|
|
96
|
+
"bench:longmemeval": "tsx scripts/longmemeval/run-harness.ts",
|
|
97
|
+
"bench:classifier": "tsx scripts/longmemeval/run-harness.ts --classifier",
|
|
98
|
+
"bench:compare": "tsx scripts/longmemeval/compare-classifiers.ts",
|
|
99
|
+
"eval:signals": "tsx scripts/eval/signals-eval.ts",
|
|
100
|
+
"eval:classifier": "tsx scripts/eval/classifier-eval.ts",
|
|
101
|
+
"eval:fact-recall": "tsx scripts/eval/fact-recall-eval.ts",
|
|
102
|
+
"eval:recall-impact-replay": "tsx scripts/eval/recall-impact-replay.ts",
|
|
103
|
+
"eval:code-exemplar": "tsx scripts/eval/code-exemplar-eval.ts",
|
|
104
|
+
"eval:reranker": "tsx scripts/eval/reranker-ablation.ts",
|
|
105
|
+
"eval:floor": "tsx scripts/eval/floor-calibration.ts",
|
|
106
|
+
"eval:matcher": "tsx scripts/eval/tune-matcher.ts",
|
|
107
|
+
"eval:naming": "tsx scripts/eval/tune-naming.ts",
|
|
108
|
+
"eval:rederiv-sample": "tsx scripts/eval/re-derivation-sample.ts",
|
|
109
|
+
"eval:rederiv-label": "tsx scripts/eval/re-derivation-label.ts",
|
|
110
|
+
"eval:rederiv-calibrate": "tsx scripts/eval/re-derivation-calibrate.ts"
|
|
111
|
+
},
|
|
112
|
+
dependencies: {
|
|
113
|
+
"@clack/prompts": "^1.4.0",
|
|
114
|
+
"@hono/node-server": "^2.0.3",
|
|
115
|
+
"@huggingface/transformers": "4.2.0",
|
|
116
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
117
|
+
"@toon-format/toon": "^2.3.0",
|
|
118
|
+
"better-sqlite3": "^13.0.1",
|
|
119
|
+
commander: "^15.0.0",
|
|
120
|
+
hono: "^4.6.0",
|
|
121
|
+
pg: "^8.21.0",
|
|
122
|
+
pgvector: "^0.3.0",
|
|
123
|
+
"sqlite-vec": "^0.1.6",
|
|
124
|
+
yaml: "^2.9.0",
|
|
125
|
+
zod: "^4.4.3"
|
|
126
|
+
},
|
|
127
|
+
devDependencies: {
|
|
128
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
129
|
+
"@types/node": "^22.10.0",
|
|
130
|
+
"@types/pg": "^8.20.0",
|
|
131
|
+
"@types/react": "^19.2.17",
|
|
132
|
+
"@types/react-dom": "^19.2.3",
|
|
133
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
134
|
+
esbuild: "^0.28.0",
|
|
135
|
+
react: "^19.2.7",
|
|
136
|
+
"react-dom": "^19.2.7",
|
|
137
|
+
"react-router-dom": "^6.30.3",
|
|
138
|
+
"tsc-alias": "^1.8.17",
|
|
139
|
+
tsx: "^4.19.0",
|
|
140
|
+
typescript: "^6.0.3",
|
|
141
|
+
vite: "^8.0.16",
|
|
142
|
+
vitest: "^4.1.8"
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/shared/version.ts
|
|
147
|
+
var NLM_VERSION = package_default.version;
|
|
148
|
+
|
|
149
|
+
// src/core/hook/hook-log.ts
|
|
150
|
+
function logPath(tenantId) {
|
|
151
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
152
|
+
return process.env["NLM_HOOK_LOG"] ?? tenantStatePath(tenantId, "hook-log.jsonl");
|
|
153
|
+
}
|
|
154
|
+
return tenantStatePath(tenantId, "hook-log.jsonl");
|
|
12
155
|
}
|
|
13
|
-
function appendHookLog(entry) {
|
|
156
|
+
function appendHookLog(tenantId, entry) {
|
|
14
157
|
try {
|
|
15
|
-
const path = logPath();
|
|
158
|
+
const path = logPath(tenantId);
|
|
16
159
|
mkdirSync(dirname(path), { recursive: true });
|
|
17
|
-
appendFileSync(path, `${JSON.stringify(entry)}
|
|
160
|
+
appendFileSync(path, `${JSON.stringify({ ...entry, v: NLM_VERSION })}
|
|
18
161
|
`, "utf8");
|
|
19
162
|
} catch {
|
|
20
163
|
}
|
|
@@ -30,18 +173,20 @@ import {
|
|
|
30
173
|
statSync,
|
|
31
174
|
writeFileSync
|
|
32
175
|
} from "node:fs";
|
|
33
|
-
import { homedir as homedir2 } from "node:os";
|
|
34
176
|
import { join as join2 } from "node:path";
|
|
35
|
-
function stateDir() {
|
|
36
|
-
|
|
177
|
+
function stateDir(tenantId) {
|
|
178
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
179
|
+
return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
|
|
180
|
+
}
|
|
181
|
+
return tenantStatePath(tenantId, "hook-state");
|
|
37
182
|
}
|
|
38
|
-
function memoPath(conversationId) {
|
|
183
|
+
function memoPath(tenantId, conversationId) {
|
|
39
184
|
const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
40
|
-
return join2(stateDir(), `${safe}.json`);
|
|
185
|
+
return join2(stateDir(tenantId), `${safe}.json`);
|
|
41
186
|
}
|
|
42
|
-
function loadSurfaced(conversationId) {
|
|
187
|
+
function loadSurfaced(tenantId, conversationId) {
|
|
43
188
|
try {
|
|
44
|
-
const path = memoPath(conversationId);
|
|
189
|
+
const path = memoPath(tenantId, conversationId);
|
|
45
190
|
if (!existsSync(path)) return /* @__PURE__ */ new Set();
|
|
46
191
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
47
192
|
if (!Array.isArray(parsed)) return /* @__PURE__ */ new Set();
|
|
@@ -50,12 +195,12 @@ function loadSurfaced(conversationId) {
|
|
|
50
195
|
return /* @__PURE__ */ new Set();
|
|
51
196
|
}
|
|
52
197
|
}
|
|
53
|
-
function recordSurfaced(conversationId, ids) {
|
|
198
|
+
function recordSurfaced(tenantId, conversationId, ids) {
|
|
54
199
|
try {
|
|
55
|
-
const merged = loadSurfaced(conversationId);
|
|
200
|
+
const merged = loadSurfaced(tenantId, conversationId);
|
|
56
201
|
for (const id of ids) merged.add(id);
|
|
57
|
-
mkdirSync2(stateDir(), { recursive: true });
|
|
58
|
-
writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
|
|
202
|
+
mkdirSync2(stateDir(tenantId), { recursive: true });
|
|
203
|
+
writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
|
|
59
204
|
} catch {
|
|
60
205
|
}
|
|
61
206
|
}
|
|
@@ -81,8 +226,8 @@ function truncateSummary(s, max = 200) {
|
|
|
81
226
|
}
|
|
82
227
|
return window + " ...";
|
|
83
228
|
}
|
|
84
|
-
function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
85
|
-
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0) return "";
|
|
229
|
+
function formatPointerBlock(hits, facts = [], exemplars = [], concepts = []) {
|
|
230
|
+
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0 && concepts.length === 0) return "";
|
|
86
231
|
const out = [];
|
|
87
232
|
if (hits.length > 0) {
|
|
88
233
|
out.push("## Possibly-relevant prior sessions (nlm-memory)");
|
|
@@ -111,7 +256,19 @@ function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
|
111
256
|
out.push(`- [${e.outcome}] ${langPart}${e.repo} - ${truncateSummary(e.taskContext)}`);
|
|
112
257
|
}
|
|
113
258
|
}
|
|
114
|
-
|
|
259
|
+
if (concepts.length > 0) {
|
|
260
|
+
if (out.length > 0) out.push("");
|
|
261
|
+
out.push("## Learning state (nlm-memory)");
|
|
262
|
+
for (const c of concepts) {
|
|
263
|
+
const n = c.attemptCount === 1 ? "1 attempt" : `${c.attemptCount} attempts`;
|
|
264
|
+
out.push(`- [${c.status}] ${c.concept} (${n})`);
|
|
265
|
+
}
|
|
266
|
+
const nextSteps = [...new Set(concepts.map((c) => c.nextStep).filter((s) => !!s))].slice(0, 2);
|
|
267
|
+
for (const next of nextSteps) {
|
|
268
|
+
out.push(`Next: ${truncateSummary(next, 120)}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
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).";
|
|
115
272
|
out.push(tools);
|
|
116
273
|
return out.join("\n");
|
|
117
274
|
}
|
|
@@ -123,10 +280,10 @@ function medianScore(hits) {
|
|
|
123
280
|
return sorted[Math.floor(sorted.length / 2)] ?? 0;
|
|
124
281
|
}
|
|
125
282
|
function selectHits(params) {
|
|
126
|
-
const { hits, surfaced, scoreThreshold, perFireCap, perConversationCap, relativeFloor = 0 } = params;
|
|
127
|
-
const relCut =
|
|
283
|
+
const { hits, surfaced, scoreThreshold: scoreThreshold2, perFireCap, perConversationCap, relativeFloor: relativeFloor2 = 0 } = params;
|
|
284
|
+
const relCut = relativeFloor2 > 0 ? relativeFloor2 * medianScore(hits) : 0;
|
|
128
285
|
const eligible = hits.filter(
|
|
129
|
-
(h) => h.matchScore >=
|
|
286
|
+
(h) => h.matchScore >= scoreThreshold2 && h.matchScore >= relCut && !surfaced.has(h.id)
|
|
130
287
|
);
|
|
131
288
|
const budget = Math.max(0, perConversationCap - surfaced.size);
|
|
132
289
|
const limit = Math.min(perFireCap, budget);
|
|
@@ -135,7 +292,7 @@ function selectHits(params) {
|
|
|
135
292
|
|
|
136
293
|
// src/llm/env-autoload.ts
|
|
137
294
|
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "node:fs";
|
|
138
|
-
import { homedir as
|
|
295
|
+
import { homedir as homedir2 } from "node:os";
|
|
139
296
|
import { resolve } from "node:path";
|
|
140
297
|
var DEFAULT_SEARCH_PATHS = [
|
|
141
298
|
"~/.nlm/.env",
|
|
@@ -144,7 +301,7 @@ var DEFAULT_SEARCH_PATHS = [
|
|
|
144
301
|
"../../.env"
|
|
145
302
|
];
|
|
146
303
|
function expandHome(p) {
|
|
147
|
-
if (p.startsWith("~/")) return resolve(
|
|
304
|
+
if (p.startsWith("~/")) return resolve(homedir2(), p.slice(2));
|
|
148
305
|
return p;
|
|
149
306
|
}
|
|
150
307
|
function autoloadEnv(extraPaths = []) {
|
|
@@ -340,6 +497,18 @@ function extractRecallQuery(prompt) {
|
|
|
340
497
|
}
|
|
341
498
|
|
|
342
499
|
// src/hook/hook-helpers.ts
|
|
500
|
+
import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync3, realpathSync } from "node:fs";
|
|
501
|
+
import { pathToFileURL } from "node:url";
|
|
502
|
+
function isMainModule(metaUrl, argv1) {
|
|
503
|
+
if (!argv1) return false;
|
|
504
|
+
let resolved;
|
|
505
|
+
try {
|
|
506
|
+
resolved = realpathSync(argv1);
|
|
507
|
+
} catch {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
return metaUrl === pathToFileURL(resolved).href;
|
|
511
|
+
}
|
|
343
512
|
function readStdin() {
|
|
344
513
|
return new Promise((resolve2) => {
|
|
345
514
|
let data = "";
|
|
@@ -372,27 +541,36 @@ function parseRecallTimeout(raw) {
|
|
|
372
541
|
const n = Number(raw);
|
|
373
542
|
return Number.isFinite(n) && n > 0 ? n : 4e3;
|
|
374
543
|
}
|
|
375
|
-
|
|
376
|
-
|
|
544
|
+
function recallTimeoutMs() {
|
|
545
|
+
return parseRecallTimeout(process.env["NLM_HOOK_RECALL_TIMEOUT_MS"]);
|
|
546
|
+
}
|
|
547
|
+
var emptyResult = (outcome) => ({
|
|
548
|
+
hits: [],
|
|
549
|
+
facts: [],
|
|
550
|
+
exemplars: [],
|
|
551
|
+
concepts: [],
|
|
552
|
+
outcome
|
|
553
|
+
});
|
|
554
|
+
async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword", source = "hook") {
|
|
377
555
|
const query = extractRecallQuery(prompt);
|
|
378
|
-
if (query === null) return
|
|
556
|
+
if (query === null) return emptyResult("skipped");
|
|
379
557
|
const portValue = process.env["NLM_PORT"] ?? DEFAULT_NLM_PORT;
|
|
380
558
|
const url = (
|
|
381
559
|
// 127.0.0.1, not localhost: each hook is a fresh process with no connection
|
|
382
560
|
// reuse, and Node resolves localhost to IPv6 ::1 first — a measured ~50-300ms
|
|
383
561
|
// per-fire connect penalty vs ~3ms on the explicit IPv4 loopback.
|
|
384
|
-
`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)}` : "")
|
|
562
|
+
`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)}` : "")
|
|
385
563
|
);
|
|
386
564
|
try {
|
|
387
|
-
const extra = { "x-recall-source":
|
|
565
|
+
const extra = { "x-recall-source": source };
|
|
388
566
|
if (runtime) extra["x-recall-runtime"] = runtime;
|
|
389
|
-
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) },
|
|
390
|
-
if (!res.ok) return
|
|
567
|
+
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) }, recallTimeoutMs());
|
|
568
|
+
if (!res.ok) return emptyResult("http-error");
|
|
391
569
|
let body;
|
|
392
570
|
try {
|
|
393
571
|
body = await res.json();
|
|
394
572
|
} catch {
|
|
395
|
-
return
|
|
573
|
+
return emptyResult("http-error");
|
|
396
574
|
}
|
|
397
575
|
const hits = (body.results ?? []).map((r) => ({
|
|
398
576
|
id: r.id,
|
|
@@ -413,37 +591,47 @@ async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword")
|
|
|
413
591
|
repo: e.repo,
|
|
414
592
|
taskContext: e.taskContext
|
|
415
593
|
}));
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
594
|
+
const concepts = (body.relatedConcepts ?? []).map((c) => ({
|
|
595
|
+
concept: c.concept,
|
|
596
|
+
status: c.status,
|
|
597
|
+
attemptCount: c.attemptCount,
|
|
598
|
+
nextStep: c.nextStep
|
|
599
|
+
}));
|
|
600
|
+
return { hits, facts, exemplars, concepts, outcome: "ok" };
|
|
601
|
+
} catch (err) {
|
|
602
|
+
const aborted = err instanceof Error && err.name === "AbortError";
|
|
603
|
+
return emptyResult(aborted ? "timeout" : "unreachable");
|
|
419
604
|
}
|
|
420
605
|
}
|
|
421
606
|
|
|
422
607
|
// src/hook/session-start-hook.ts
|
|
423
|
-
var
|
|
424
|
-
var
|
|
608
|
+
var scoreThreshold = () => parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
|
|
609
|
+
var relativeFloor = () => parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
|
|
425
610
|
var PER_FIRE_CAP = 3;
|
|
426
611
|
var PER_CONVERSATION_CAP = 10;
|
|
427
|
-
var
|
|
612
|
+
var RECALL_TIMEOUT_MS = 2e3;
|
|
428
613
|
async function runHook(input, deps) {
|
|
429
614
|
let hits = [];
|
|
615
|
+
let recallOutcome = "unreachable";
|
|
430
616
|
try {
|
|
431
|
-
|
|
617
|
+
const fetched = await deps.recall(input.query, input.conversationId);
|
|
618
|
+
hits = fetched.hits;
|
|
619
|
+
recallOutcome = fetched.outcome;
|
|
432
620
|
} catch {
|
|
433
621
|
hits = [];
|
|
434
622
|
}
|
|
435
|
-
const surfaced = loadSurfaced(input.conversationId);
|
|
623
|
+
const surfaced = loadSurfaced(DEFAULT_TEAM_ID, input.conversationId);
|
|
436
624
|
const selected = selectHits({
|
|
437
625
|
hits,
|
|
438
626
|
surfaced,
|
|
439
|
-
scoreThreshold:
|
|
440
|
-
relativeFloor:
|
|
627
|
+
scoreThreshold: scoreThreshold(),
|
|
628
|
+
relativeFloor: relativeFloor(),
|
|
441
629
|
perFireCap: PER_FIRE_CAP,
|
|
442
630
|
perConversationCap: PER_CONVERSATION_CAP
|
|
443
631
|
});
|
|
444
632
|
const block = formatPointerBlock(selected);
|
|
445
633
|
const estTokens = Math.ceil(block.length / 4);
|
|
446
|
-
appendHookLog({
|
|
634
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
447
635
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
448
636
|
conversationId: input.conversationId,
|
|
449
637
|
promptPreview: input.query,
|
|
@@ -451,10 +639,11 @@ async function runHook(input, deps) {
|
|
|
451
639
|
hits: hits.map((h) => ({ id: h.id, score: h.matchScore })),
|
|
452
640
|
wouldInject: selected.map((h) => h.id),
|
|
453
641
|
estTokens,
|
|
454
|
-
mode: deps.mode
|
|
642
|
+
mode: deps.mode,
|
|
643
|
+
recallOutcome
|
|
455
644
|
});
|
|
456
645
|
if (deps.mode === "live" && selected.length > 0) {
|
|
457
|
-
recordSurfaced(input.conversationId, selected.map((h) => h.id));
|
|
646
|
+
recordSurfaced(DEFAULT_TEAM_ID, input.conversationId, selected.map((h) => h.id));
|
|
458
647
|
return block;
|
|
459
648
|
}
|
|
460
649
|
return "";
|
|
@@ -469,7 +658,7 @@ async function fetchFailureModeBlock(repo) {
|
|
|
469
658
|
try {
|
|
470
659
|
const res = await fetchWithTimeout(url, {
|
|
471
660
|
headers: hookAuthHeaders({ "x-recall-source": "session-start-hook" })
|
|
472
|
-
},
|
|
661
|
+
}, RECALL_TIMEOUT_MS);
|
|
473
662
|
if (!res.ok) return "";
|
|
474
663
|
const body = await res.json();
|
|
475
664
|
return typeof body.block === "string" ? body.block : "";
|
|
@@ -477,9 +666,29 @@ async function fetchFailureModeBlock(repo) {
|
|
|
477
666
|
return "";
|
|
478
667
|
}
|
|
479
668
|
}
|
|
480
|
-
|
|
669
|
+
var GIT_TIMEOUT_MS = 300;
|
|
670
|
+
var RECENT_COMMITS = 3;
|
|
671
|
+
function git(cwd, args) {
|
|
672
|
+
try {
|
|
673
|
+
return execFileSync("git", ["-C", cwd, ...args], {
|
|
674
|
+
encoding: "utf8",
|
|
675
|
+
timeout: GIT_TIMEOUT_MS,
|
|
676
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
677
|
+
}).trim();
|
|
678
|
+
} catch {
|
|
679
|
+
return "";
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
function readGitContext(workingDirectory) {
|
|
683
|
+
if (!workingDirectory) return "";
|
|
684
|
+
const branch = git(workingDirectory, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
685
|
+
const subjects = git(workingDirectory, ["log", `-${RECENT_COMMITS}`, "--format=%s"]);
|
|
686
|
+
const branchWords = branch === "HEAD" ? "" : branch.replace(/[/_-]+/g, " ");
|
|
687
|
+
return [branchWords, subjects.replace(/\n/g, " ")].filter(Boolean).join(" ");
|
|
688
|
+
}
|
|
689
|
+
function buildQuery(workingDirectory, projectName, gitContext) {
|
|
481
690
|
const dirTail = workingDirectory.split("/").filter(Boolean).at(-1) ?? "";
|
|
482
|
-
const parts = [dirTail, projectName].filter(Boolean);
|
|
691
|
+
const parts = [dirTail, projectName, gitContext].filter(Boolean);
|
|
483
692
|
return parts.join(" ").trim() || "session start";
|
|
484
693
|
}
|
|
485
694
|
async function main() {
|
|
@@ -490,14 +699,23 @@ async function main() {
|
|
|
490
699
|
const conversationId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
|
|
491
700
|
const workingDirectory = typeof payload.cwd === "string" ? payload.cwd : typeof payload.working_directory === "string" ? payload.working_directory : "";
|
|
492
701
|
const projectName = typeof payload.project_name === "string" ? payload.project_name : "";
|
|
493
|
-
const query = buildQuery(workingDirectory, projectName);
|
|
702
|
+
const query = buildQuery(workingDirectory, projectName, readGitContext(workingDirectory));
|
|
494
703
|
const mode = hookModeFromEnv();
|
|
495
704
|
const [out, failureModes] = await Promise.all([
|
|
496
705
|
runHook(
|
|
497
706
|
{ conversationId, query },
|
|
498
707
|
{
|
|
499
708
|
mode,
|
|
500
|
-
recall: async (q, cid) =>
|
|
709
|
+
recall: async (q, cid) => {
|
|
710
|
+
const r = await recallOverHttp(
|
|
711
|
+
q,
|
|
712
|
+
"claude-code",
|
|
713
|
+
cid === "unknown" ? void 0 : cid,
|
|
714
|
+
"hybrid",
|
|
715
|
+
"session-start-hook"
|
|
716
|
+
);
|
|
717
|
+
return { hits: r.hits, outcome: r.outcome };
|
|
718
|
+
}
|
|
501
719
|
}
|
|
502
720
|
),
|
|
503
721
|
mode === "live" ? fetchFailureModeBlock(workingDirectory) : Promise.resolve("")
|
|
@@ -507,10 +725,12 @@ async function main() {
|
|
|
507
725
|
} catch {
|
|
508
726
|
}
|
|
509
727
|
}
|
|
510
|
-
if (
|
|
728
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
511
729
|
void main();
|
|
512
730
|
}
|
|
513
731
|
export {
|
|
732
|
+
buildQuery,
|
|
514
733
|
composeSessionStartOutput,
|
|
734
|
+
readGitContext,
|
|
515
735
|
runHook
|
|
516
736
|
};
|