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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-helpers.js","sourceRoot":"","sources":["../../src/hook/hook-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"hook-helpers.js","sourceRoot":"","sources":["../../src/hook/hook-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,KAAyB;IACrE,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,OAAO,KAAK,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAW,EACX,IAAiB,EACjB,EAAU;IAEV,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IAClE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAA6B;IAC3D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACtF,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC"}
|
|
@@ -12,15 +12,17 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Fail-open by design: any error yields a clean exit with no output.
|
|
14
14
|
*/
|
|
15
|
-
import { pathToFileURL } from "node:url";
|
|
16
15
|
import { loadSurfaced } from "../core/hook/memo.js";
|
|
16
|
+
import { DEFAULT_TEAM_ID } from "../core/tenancy/default-team.js";
|
|
17
17
|
import { autoloadEnv } from "../llm/env-autoload.js";
|
|
18
18
|
import { hookAuthHeaders } from "./hook-auth.js";
|
|
19
|
-
import { readStdin, fetchWithTimeout, appendHookEvent } from "./hook-helpers.js";
|
|
19
|
+
import { readStdin, fetchWithTimeout, appendHookEvent, isMainModule } from "./hook-helpers.js";
|
|
20
20
|
import { DEFAULT_NLM_PORT } from "../shared/net.js";
|
|
21
21
|
const POST_TIMEOUT_MS = 1500;
|
|
22
22
|
export async function runPreCompact(input, portValue = process.env["NLM_PORT"] ?? DEFAULT_NLM_PORT) {
|
|
23
|
-
|
|
23
|
+
// Client-side hook composition root: no per-tenant CLI/hook concept exists
|
|
24
|
+
// today, so DEFAULT_TEAM_ID is this surface's real identity, not a placeholder.
|
|
25
|
+
const surfacedSet = [...loadSurfaced(DEFAULT_TEAM_ID, input.conversationId)];
|
|
24
26
|
const payload = {
|
|
25
27
|
conversation_id: input.conversationId,
|
|
26
28
|
transcript_path: input.transcriptPath,
|
|
@@ -61,7 +63,7 @@ async function main() {
|
|
|
61
63
|
// Fail open — never block Claude Code compaction.
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
|
-
if (
|
|
66
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
65
67
|
void main();
|
|
66
68
|
}
|
|
67
69
|
//# sourceMappingURL=pre-compact-hook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pre-compact-hook.js","sourceRoot":"","sources":["../../src/hook/pre-compact-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"pre-compact-hook.js","sourceRoot":"","sources":["../../src/hook/pre-compact-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,eAAe,GAAG,IAAI,CAAC;AAY7B,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,KAAsB,EACtB,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,gBAAgB;IAEvD,2EAA2E;IAC3E,gFAAgF;IAChF,MAAM,WAAW,GAAG,CAAC,GAAG,YAAY,CAAC,eAAe,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG;QACd,eAAe,EAAE,KAAK,CAAC,cAAc;QACrC,eAAe,EAAE,KAAK,CAAC,cAAc;QACrC,YAAY,EAAE,WAAW;QACzB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC7B,CAAC;IACF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAChC,oBAAoB,SAAS,uBAAuB,EACpD;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,eAAe,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;YAChE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,EACD,eAAe,CAChB,CAAC;QACF,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IACjE,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,MAAwB;IACzC,eAAe,CAAC;QACd,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,IAAI,EAAE,aAAa;QACnB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,WAAW,EAAE,CAAC;QACd,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAG7B,CAAC;QACF,MAAM,cAAc,GAClB,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1E,MAAM,cAAc,GAClB,OAAO,OAAO,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC;QACvE,SAAS,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;AACH,CAAC;AAED,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,KAAK,IAAI,EAAE,CAAC;AACd,CAAC"}
|
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
* read from NLM_HOOK_RUNTIME (default "claude-code") so packaged hooks can
|
|
10
10
|
* share this entrypoint without polluting query logs.
|
|
11
11
|
*/
|
|
12
|
-
import { type PointerExemplar, type PointerFact } from "../core/hook/pointer-block.js";
|
|
12
|
+
import { type PointerConcept, type PointerExemplar, type PointerFact } from "../core/hook/pointer-block.js";
|
|
13
13
|
import { type RecallHitInput } from "../core/hook/select.js";
|
|
14
|
+
import { type RecallOutcome } from "./recall-over-http.js";
|
|
14
15
|
export declare function parseHookDeadline(raw: string | undefined, defaultMs?: number): number;
|
|
15
|
-
export declare
|
|
16
|
+
export declare function hookDeadlineMs(): number;
|
|
16
17
|
export type HookMode = "shadow" | "live";
|
|
17
18
|
export declare function hookRuntimeFromEnv(env?: NodeJS.ProcessEnv): string;
|
|
18
19
|
/**
|
|
@@ -46,6 +47,8 @@ export interface RecallFetchResult {
|
|
|
46
47
|
readonly hits: ReadonlyArray<RecallHitInput>;
|
|
47
48
|
readonly facts: ReadonlyArray<PointerFact>;
|
|
48
49
|
readonly exemplars?: ReadonlyArray<PointerExemplar>;
|
|
50
|
+
readonly concepts?: ReadonlyArray<PointerConcept>;
|
|
51
|
+
readonly outcome?: RecallOutcome;
|
|
49
52
|
}
|
|
50
53
|
export type GateMode = "shadow" | "live";
|
|
51
54
|
export interface RecallGate {
|
|
@@ -9,18 +9,18 @@
|
|
|
9
9
|
* read from NLM_HOOK_RUNTIME (default "claude-code") so packaged hooks can
|
|
10
10
|
* share this entrypoint without polluting query logs.
|
|
11
11
|
*/
|
|
12
|
-
import { pathToFileURL } from "node:url";
|
|
13
12
|
import { classifyPrompt } from "../core/hook/gate.js";
|
|
14
13
|
import { recentConversationContext, topicalWordCount } from "./recent-context.js";
|
|
15
14
|
import { appendHookLog } from "../core/hook/hook-log.js";
|
|
16
15
|
import { loadSurfaced, recordSurfaced } from "../core/hook/memo.js";
|
|
16
|
+
import { DEFAULT_TEAM_ID } from "../core/tenancy/default-team.js";
|
|
17
17
|
import { formatPointerBlock } from "../core/hook/pointer-block.js";
|
|
18
18
|
import { selectHits } from "../core/hook/select.js";
|
|
19
19
|
import { autoloadEnv } from "../llm/env-autoload.js";
|
|
20
20
|
import { recallOverHttp } from "./recall-over-http.js";
|
|
21
21
|
import { parseScoreFloor, parseRelativeFloor } from "./score-floor.js";
|
|
22
22
|
import { makeOllamaGate, parseRecallGateMode } from "./recall-gate.js";
|
|
23
|
-
import { readStdin, hookModeFromEnv } from "./hook-helpers.js";
|
|
23
|
+
import { readStdin, hookModeFromEnv, isMainModule } from "./hook-helpers.js";
|
|
24
24
|
// Keyword recall returns raw BM25 scores (unbounded, not the 0..1 hybrid
|
|
25
25
|
// scale). FTS5 MATCH already gates relevance — only lexically-matching
|
|
26
26
|
// sessions come back — so the default floor is 0. NLM_RECALL_SCORE_FLOOR lets
|
|
@@ -29,12 +29,15 @@ import { readStdin, hookModeFromEnv } from "./hook-helpers.js";
|
|
|
29
29
|
// parseScoreFloor guards against a bad env value: a non-numeric / non-finite /
|
|
30
30
|
// negative input falls back to 0 instead of silently deny-all'ing recall
|
|
31
31
|
// (matchScore >= NaN is always false in select.ts).
|
|
32
|
-
|
|
32
|
+
// Lazy, not module-scope: autoloadEnv() runs inside main(), after imports are
|
|
33
|
+
// evaluated, so an eager read silently ignores ~/.nlm/.env. See recallTimeoutMs
|
|
34
|
+
// in recall-over-http.ts.
|
|
35
|
+
const scoreThreshold = () => parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
|
|
33
36
|
// Portable per-fire noise floor: drop tail hits below this fraction of the
|
|
34
37
|
// fire's median score. Default 0.9 (calibrated, #284) — trims weak tail recalls
|
|
35
38
|
// while keeping ~97% of cited ones. Only the per-message keyword path runs this;
|
|
36
39
|
// the session-start hybrid path is left unfiltered (unmeasured).
|
|
37
|
-
const
|
|
40
|
+
const relativeFloor = () => parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
|
|
38
41
|
const PER_FIRE_CAP = 3;
|
|
39
42
|
const PER_CONVERSATION_CAP = 10;
|
|
40
43
|
const PROMPT_PREVIEW_CHARS = 200;
|
|
@@ -48,7 +51,9 @@ export function parseHookDeadline(raw, defaultMs = 4000) {
|
|
|
48
51
|
// RECALL_TIMEOUT_MS (default 4000ms in recall-over-http.ts) with headroom.
|
|
49
52
|
// Invariant: HOOK_DEADLINE_MS > RECALL_TIMEOUT_MS at defaults. If the outer
|
|
50
53
|
// equals the inner, the deadline fires before post-recall work can complete.
|
|
51
|
-
export
|
|
54
|
+
export function hookDeadlineMs() {
|
|
55
|
+
return parseHookDeadline(process.env["NLM_HOOK_DEADLINE_MS"], 6000);
|
|
56
|
+
}
|
|
52
57
|
async function withDeadline(p, ms, fallback) {
|
|
53
58
|
if (ms <= 0)
|
|
54
59
|
return fallback;
|
|
@@ -111,7 +116,9 @@ export async function runHook(input, deps) {
|
|
|
111
116
|
const gate = classifyPrompt(input.prompt);
|
|
112
117
|
const preview = input.prompt.slice(0, PROMPT_PREVIEW_CHARS);
|
|
113
118
|
if (gate === "generative" || gate === "skip") {
|
|
114
|
-
|
|
119
|
+
// Client-side hook composition root: no per-tenant CLI/hook concept exists
|
|
120
|
+
// today, so DEFAULT_TEAM_ID is this surface's real identity, not a placeholder.
|
|
121
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
115
122
|
ts: new Date().toISOString(),
|
|
116
123
|
conversationId: input.conversationId,
|
|
117
124
|
promptPreview: preview,
|
|
@@ -123,21 +130,24 @@ export async function runHook(input, deps) {
|
|
|
123
130
|
});
|
|
124
131
|
return "";
|
|
125
132
|
}
|
|
126
|
-
const deadline = Date.now() + (deps.deadlineMs ??
|
|
127
|
-
|
|
133
|
+
const deadline = Date.now() + (deps.deadlineMs ?? hookDeadlineMs());
|
|
134
|
+
// The outer deadline and the inner HTTP timeout are separate budgets; both
|
|
135
|
+
// yield an empty result, so both must name themselves or the log conflates
|
|
136
|
+
// them with a real miss.
|
|
137
|
+
let fetched = { hits: [], facts: [], outcome: "timeout" };
|
|
128
138
|
try {
|
|
129
|
-
fetched = normalizeRecall(await withDeadline(deps.recall(buildRecallQuery(input)), deadline - Date.now(), { hits: [], facts: [] }));
|
|
139
|
+
fetched = normalizeRecall(await withDeadline(deps.recall(buildRecallQuery(input)), deadline - Date.now(), { hits: [], facts: [], outcome: "timeout" }));
|
|
130
140
|
}
|
|
131
141
|
catch {
|
|
132
|
-
fetched = { hits: [], facts: [] };
|
|
142
|
+
fetched = { hits: [], facts: [], outcome: "unreachable" };
|
|
133
143
|
}
|
|
134
144
|
const hits = fetched.hits;
|
|
135
|
-
const surfaced = loadSurfaced(input.conversationId);
|
|
145
|
+
const surfaced = loadSurfaced(DEFAULT_TEAM_ID, input.conversationId);
|
|
136
146
|
const selected = selectHits({
|
|
137
147
|
hits,
|
|
138
148
|
surfaced,
|
|
139
|
-
scoreThreshold:
|
|
140
|
-
relativeFloor:
|
|
149
|
+
scoreThreshold: scoreThreshold(),
|
|
150
|
+
relativeFloor: relativeFloor(),
|
|
141
151
|
perFireCap: PER_FIRE_CAP,
|
|
142
152
|
perConversationCap: PER_CONVERSATION_CAP,
|
|
143
153
|
});
|
|
@@ -163,9 +173,9 @@ export async function runHook(input, deps) {
|
|
|
163
173
|
injected = selected.filter((h) => !drop.has(h.id));
|
|
164
174
|
}
|
|
165
175
|
}
|
|
166
|
-
const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars);
|
|
176
|
+
const block = formatPointerBlock(injected, fetched.facts, fetched.exemplars, fetched.concepts ?? []);
|
|
167
177
|
const estTokens = Math.ceil(block.length / 4);
|
|
168
|
-
appendHookLog({
|
|
178
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
169
179
|
ts: new Date().toISOString(),
|
|
170
180
|
conversationId: input.conversationId,
|
|
171
181
|
promptPreview: preview,
|
|
@@ -174,10 +184,11 @@ export async function runHook(input, deps) {
|
|
|
174
184
|
wouldInject: injected.map((h) => h.id),
|
|
175
185
|
estTokens,
|
|
176
186
|
mode: deps.mode,
|
|
187
|
+
...(fetched.outcome ? { recallOutcome: fetched.outcome } : {}),
|
|
177
188
|
...(gateDecisions ? { gateDecisions } : {}),
|
|
178
189
|
});
|
|
179
190
|
if (deps.mode === "live" && injected.length > 0) {
|
|
180
|
-
recordSurfaced(input.conversationId, injected.map((h) => h.id));
|
|
191
|
+
recordSurfaced(DEFAULT_TEAM_ID, input.conversationId, injected.map((h) => h.id));
|
|
181
192
|
return block;
|
|
182
193
|
}
|
|
183
194
|
return "";
|
|
@@ -221,7 +232,7 @@ async function main() {
|
|
|
221
232
|
}
|
|
222
233
|
}
|
|
223
234
|
// Run main() only when invoked directly as a script, not when imported by tests.
|
|
224
|
-
if (
|
|
235
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
225
236
|
void main();
|
|
226
237
|
}
|
|
227
238
|
//# sourceMappingURL=prompt-recall-hook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-recall-hook.js","sourceRoot":"","sources":["../../src/hook/prompt-recall-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"prompt-recall-hook.js","sourceRoot":"","sources":["../../src/hook/prompt-recall-hook.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,13 +13,37 @@
|
|
|
13
13
|
* code exemplar recall). The HTTP handler returns this when &withExemplars=true.
|
|
14
14
|
*/
|
|
15
15
|
import type { RecallHitInput } from "../core/hook/select.js";
|
|
16
|
-
import type { PointerExemplar, PointerFact } from "../core/hook/pointer-block.js";
|
|
16
|
+
import type { PointerConcept, PointerExemplar, PointerFact } from "../core/hook/pointer-block.js";
|
|
17
17
|
export declare const RECALL_LIMIT = 5;
|
|
18
18
|
export declare function parseRecallTimeout(raw: string | undefined): number;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Read at call time, not module scope. Hook entrypoints call autoloadEnv()
|
|
21
|
+
* inside main(), which runs AFTER every import has been evaluated — so a
|
|
22
|
+
* module-scope read captures the environment before ~/.nlm/.env is loaded and
|
|
23
|
+
* silently ignores anything set there. Same hazard the MCP servers avoid by
|
|
24
|
+
* importing a side-effect env module first; a lazy read is immune to import
|
|
25
|
+
* order entirely. Keep every env-derived hook knob lazy for this reason.
|
|
26
|
+
*/
|
|
27
|
+
export declare function recallTimeoutMs(): number;
|
|
28
|
+
/**
|
|
29
|
+
* Why the recall returned what it did. Without this, a timed-out recall and a
|
|
30
|
+
* genuinely-empty one are the same empty object, so a dead recall path reads
|
|
31
|
+
* as "nothing relevant" on every diagnostic surface — the failure that hid a
|
|
32
|
+
* two-week hook outage behind a healthy-looking digest.
|
|
33
|
+
*/
|
|
34
|
+
export type RecallOutcome = "ok" | "timeout" | "unreachable" | "http-error" | "skipped";
|
|
20
35
|
export interface RecallOverHttpResult {
|
|
21
36
|
readonly hits: ReadonlyArray<RecallHitInput>;
|
|
22
37
|
readonly facts: ReadonlyArray<PointerFact>;
|
|
23
38
|
readonly exemplars: ReadonlyArray<PointerExemplar>;
|
|
39
|
+
readonly concepts: ReadonlyArray<PointerConcept>;
|
|
40
|
+
readonly outcome: RecallOutcome;
|
|
24
41
|
}
|
|
25
|
-
|
|
42
|
+
/**
|
|
43
|
+
* `source` is the recall-precision bucket this fire is attributed to. It must
|
|
44
|
+
* name the CALLER, not the transport: prompt recall queries a real user prompt
|
|
45
|
+
* while session-start queries a derived project name, so blending them under
|
|
46
|
+
* one label hides two very different achievable ceilings behind one number.
|
|
47
|
+
* Defaults to "hook" because prompt recall is the majority caller.
|
|
48
|
+
*/
|
|
49
|
+
export declare function recallOverHttp(prompt: string, runtime?: string, conversationId?: string, mode?: "keyword" | "hybrid", source?: string): Promise<RecallOverHttpResult>;
|
|
@@ -29,32 +29,56 @@ export function parseRecallTimeout(raw) {
|
|
|
29
29
|
const n = Number(raw);
|
|
30
30
|
return Number.isFinite(n) && n > 0 ? n : 4000;
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Read at call time, not module scope. Hook entrypoints call autoloadEnv()
|
|
34
|
+
* inside main(), which runs AFTER every import has been evaluated — so a
|
|
35
|
+
* module-scope read captures the environment before ~/.nlm/.env is loaded and
|
|
36
|
+
* silently ignores anything set there. Same hazard the MCP servers avoid by
|
|
37
|
+
* importing a side-effect env module first; a lazy read is immune to import
|
|
38
|
+
* order entirely. Keep every env-derived hook knob lazy for this reason.
|
|
39
|
+
*/
|
|
40
|
+
export function recallTimeoutMs() {
|
|
41
|
+
return parseRecallTimeout(process.env["NLM_HOOK_RECALL_TIMEOUT_MS"]);
|
|
42
|
+
}
|
|
43
|
+
const emptyResult = (outcome) => ({
|
|
44
|
+
hits: [],
|
|
45
|
+
facts: [],
|
|
46
|
+
exemplars: [],
|
|
47
|
+
concepts: [],
|
|
48
|
+
outcome,
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* `source` is the recall-precision bucket this fire is attributed to. It must
|
|
52
|
+
* name the CALLER, not the transport: prompt recall queries a real user prompt
|
|
53
|
+
* while session-start queries a derived project name, so blending them under
|
|
54
|
+
* one label hides two very different achievable ceilings behind one number.
|
|
55
|
+
* Defaults to "hook" because prompt recall is the majority caller.
|
|
56
|
+
*/
|
|
57
|
+
export async function recallOverHttp(prompt, runtime, conversationId, mode = "keyword", source = "hook") {
|
|
34
58
|
const query = extractRecallQuery(prompt);
|
|
35
59
|
if (query === null)
|
|
36
|
-
return
|
|
60
|
+
return emptyResult("skipped");
|
|
37
61
|
const portValue = process.env["NLM_PORT"] ?? DEFAULT_NLM_PORT;
|
|
38
62
|
const url =
|
|
39
63
|
// 127.0.0.1, not localhost: each hook is a fresh process with no connection
|
|
40
64
|
// reuse, and Node resolves localhost to IPv6 ::1 first — a measured ~50-300ms
|
|
41
65
|
// per-fire connect penalty vs ~3ms on the explicit IPv4 loopback.
|
|
42
66
|
`http://127.0.0.1:${portValue}/api/recall` +
|
|
43
|
-
`?q=${encodeURIComponent(query)}&mode=${mode}&limit=${RECALL_LIMIT}&withFacts=true&withExemplars=true` +
|
|
67
|
+
`?q=${encodeURIComponent(query)}&mode=${mode}&limit=${RECALL_LIMIT}&withFacts=true&withExemplars=true&withConcepts=true` +
|
|
44
68
|
(conversationId ? `&conversation_id=${encodeURIComponent(conversationId)}` : "");
|
|
45
69
|
try {
|
|
46
|
-
const extra = { "x-recall-source":
|
|
70
|
+
const extra = { "x-recall-source": source };
|
|
47
71
|
if (runtime)
|
|
48
72
|
extra["x-recall-runtime"] = runtime;
|
|
49
|
-
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) },
|
|
73
|
+
const res = await fetchWithTimeout(url, { headers: hookAuthHeaders(extra) }, recallTimeoutMs());
|
|
50
74
|
if (!res.ok)
|
|
51
|
-
return
|
|
75
|
+
return emptyResult("http-error");
|
|
52
76
|
let body;
|
|
53
77
|
try {
|
|
54
78
|
body = (await res.json());
|
|
55
79
|
}
|
|
56
80
|
catch {
|
|
57
|
-
return
|
|
81
|
+
return emptyResult("http-error");
|
|
58
82
|
}
|
|
59
83
|
const hits = (body.results ?? []).map((r) => ({
|
|
60
84
|
id: r.id,
|
|
@@ -75,10 +99,19 @@ export async function recallOverHttp(prompt, runtime, conversationId, mode = "ke
|
|
|
75
99
|
repo: e.repo,
|
|
76
100
|
taskContext: e.taskContext,
|
|
77
101
|
}));
|
|
78
|
-
|
|
102
|
+
const concepts = (body.relatedConcepts ?? []).map((c) => ({
|
|
103
|
+
concept: c.concept,
|
|
104
|
+
status: c.status,
|
|
105
|
+
attemptCount: c.attemptCount,
|
|
106
|
+
nextStep: c.nextStep,
|
|
107
|
+
}));
|
|
108
|
+
return { hits, facts, exemplars, concepts, outcome: "ok" };
|
|
79
109
|
}
|
|
80
|
-
catch {
|
|
81
|
-
|
|
110
|
+
catch (err) {
|
|
111
|
+
// fetchWithTimeout aborts on the deadline, which surfaces as AbortError.
|
|
112
|
+
// Anything else reaching here is a transport failure (refused, DNS, reset).
|
|
113
|
+
const aborted = err instanceof Error && err.name === "AbortError";
|
|
114
|
+
return emptyResult(aborted ? "timeout" : "unreachable");
|
|
82
115
|
}
|
|
83
116
|
}
|
|
84
117
|
//# sourceMappingURL=recall-over-http.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recall-over-http.js","sourceRoot":"","sources":["../../src/hook/recall-over-http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC;AAE9B,8EAA8E;AAC9E,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,uDAAuD;AACvD,MAAM,UAAU,kBAAkB,CAAC,GAAuB;IACxD,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"recall-over-http.js","sourceRoot":"","sources":["../../src/hook/recall-over-http.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,13 +11,15 @@
|
|
|
11
11
|
* UserPromptSubmit. Fail-open by design: any error yields a clean exit
|
|
12
12
|
* with no output, so the hook can never block Claude Code shutdown.
|
|
13
13
|
*/
|
|
14
|
-
import { pathToFileURL } from "node:url";
|
|
15
14
|
import { clearSurfaced } from "../core/hook/memo.js";
|
|
15
|
+
import { DEFAULT_TEAM_ID } from "../core/tenancy/default-team.js";
|
|
16
16
|
import { clearCited } from "../core/hook/cite-memo.js";
|
|
17
|
-
import { readStdin, hookModeFromEnv, appendHookEvent } from "./hook-helpers.js";
|
|
17
|
+
import { readStdin, hookModeFromEnv, appendHookEvent, isMainModule } from "./hook-helpers.js";
|
|
18
18
|
export function runSessionEnd(conversationId) {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
// Client-side hook composition root: no per-tenant CLI/hook concept exists
|
|
20
|
+
// today, so DEFAULT_TEAM_ID is this surface's real identity, not a placeholder.
|
|
21
|
+
const surfacedCleared = clearSurfaced(DEFAULT_TEAM_ID, conversationId);
|
|
22
|
+
const citedCleared = clearCited(DEFAULT_TEAM_ID, conversationId);
|
|
21
23
|
return { conversationId, cleared: surfacedCleared || citedCleared };
|
|
22
24
|
}
|
|
23
25
|
function logSessionEnd(result) {
|
|
@@ -40,7 +42,7 @@ async function main() {
|
|
|
40
42
|
// Fail open — never block Claude Code shutdown.
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
|
-
if (
|
|
45
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
44
46
|
void main();
|
|
45
47
|
}
|
|
46
48
|
//# sourceMappingURL=session-end-hook.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-end-hook.js","sourceRoot":"","sources":["../../src/hook/session-end-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"session-end-hook.js","sourceRoot":"","sources":["../../src/hook/session-end-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAO9F,MAAM,UAAU,aAAa,CAAC,cAAsB;IAClD,2EAA2E;IAC3E,gFAAgF;IAChF,MAAM,eAAe,GAAG,aAAa,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,UAAU,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC;IACjE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,IAAI,YAAY,EAAE,CAAC;AACtE,CAAC;AAED,SAAS,aAAa,CAAC,MAAwB;IAC7C,eAAe,CAAC;QACd,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC5B,IAAI,EAAE,aAAa;QACnB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,IAAI,EAAE,eAAe,EAAE;KACxB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA6B,CAAC;QAC5D,MAAM,cAAc,GAClB,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1E,aAAa,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,KAAK,IAAI,EAAE,CAAC;AACd,CAAC"}
|
|
@@ -12,16 +12,29 @@
|
|
|
12
12
|
* memo writes, same NLM_HOOK_MODE semantics.
|
|
13
13
|
*/
|
|
14
14
|
import { type RecallHitInput } from "../core/hook/select.js";
|
|
15
|
+
import { type RecallOutcome } from "./recall-over-http.js";
|
|
15
16
|
export type HookMode = "shadow" | "live";
|
|
17
|
+
export interface SessionStartRecall {
|
|
18
|
+
readonly hits: ReadonlyArray<RecallHitInput>;
|
|
19
|
+
readonly outcome: RecallOutcome;
|
|
20
|
+
}
|
|
16
21
|
export interface SessionStartInput {
|
|
17
22
|
readonly conversationId: string;
|
|
18
23
|
readonly query: string;
|
|
19
24
|
}
|
|
20
25
|
export interface RunSessionStartDeps {
|
|
21
26
|
readonly mode: HookMode;
|
|
22
|
-
readonly recall: (query: string, conversationId?: string) => Promise<
|
|
27
|
+
readonly recall: (query: string, conversationId?: string) => Promise<SessionStartRecall>;
|
|
23
28
|
}
|
|
24
29
|
/** Orchestration. Returns the text to emit on stdout ("" for nothing). */
|
|
25
30
|
export declare function runHook(input: SessionStartInput, deps: RunSessionStartDeps): Promise<string>;
|
|
26
31
|
/** Join the failure-mode block (if any) above the session-recall block. */
|
|
27
32
|
export declare function composeSessionStartOutput(failureModeBlock: string, recallBlock: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Branch name plus recent commit subjects. A bare directory name is often a
|
|
35
|
+
* single word ("nlm-memory"), which the recall query extractor rejects as too
|
|
36
|
+
* short, so SessionStart surfaced nothing for most repos.
|
|
37
|
+
*/
|
|
38
|
+
export declare function readGitContext(workingDirectory: string): string;
|
|
39
|
+
/** Derive a best-effort query from SessionStart payload fields. */
|
|
40
|
+
export declare function buildQuery(workingDirectory: string, projectName: string, gitContext: string): string;
|
|
@@ -11,50 +11,59 @@
|
|
|
11
11
|
* Mirrors prompt-recall-hook.ts shape exactly: same pointer-block format, same
|
|
12
12
|
* memo writes, same NLM_HOOK_MODE semantics.
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { execFileSync } from "node:child_process";
|
|
15
15
|
import { appendHookLog } from "../core/hook/hook-log.js";
|
|
16
16
|
import { loadSurfaced, recordSurfaced } from "../core/hook/memo.js";
|
|
17
|
+
import { DEFAULT_TEAM_ID } from "../core/tenancy/default-team.js";
|
|
17
18
|
import { formatPointerBlock } from "../core/hook/pointer-block.js";
|
|
18
19
|
import { selectHits } from "../core/hook/select.js";
|
|
19
20
|
import { autoloadEnv } from "../llm/env-autoload.js";
|
|
20
21
|
import { hookAuthHeaders } from "./hook-auth.js";
|
|
21
22
|
import { parseScoreFloor, parseRelativeFloor } from "./score-floor.js";
|
|
22
23
|
import { recallOverHttp } from "./recall-over-http.js";
|
|
23
|
-
import { readStdin, hookModeFromEnv, fetchWithTimeout } from "./hook-helpers.js";
|
|
24
|
+
import { readStdin, hookModeFromEnv, fetchWithTimeout, isMainModule } from "./hook-helpers.js";
|
|
24
25
|
import { DEFAULT_NLM_PORT } from "../shared/net.js";
|
|
25
26
|
// This hook recalls in hybrid mode, whose matchScore is normalized to 0..1
|
|
26
27
|
// (mergeHybrid in recall-service.ts), so the default absolute floor is 0.
|
|
27
28
|
// NLM_RECALL_SCORE_FLOOR is shared with the keyword-mode prompt hook; the
|
|
28
29
|
// calibrated keyword floor (2.0, raw BM25) would deny-all here on the 0..1
|
|
29
30
|
// scale, so it is opt-in only. parseScoreFloor guards a bad env value.
|
|
30
|
-
|
|
31
|
+
// Lazy, not module-scope: autoloadEnv() runs inside main(), after imports are
|
|
32
|
+
// evaluated, so an eager read silently ignores ~/.nlm/.env. See recallTimeoutMs
|
|
33
|
+
// in recall-over-http.ts.
|
|
34
|
+
const scoreThreshold = () => parseScoreFloor(process.env["NLM_RECALL_SCORE_FLOOR"]);
|
|
31
35
|
// The relative floor IS scale-invariant (ratio to the fire median), so it
|
|
32
36
|
// applies cleanly to this hybrid path too — parity with the per-message hook.
|
|
33
|
-
const
|
|
37
|
+
const relativeFloor = () => parseRelativeFloor(process.env["NLM_RECALL_REL_FLOOR"], 0.9);
|
|
34
38
|
const PER_FIRE_CAP = 3;
|
|
35
39
|
const PER_CONVERSATION_CAP = 10;
|
|
36
40
|
const RECALL_TIMEOUT_MS = 2000;
|
|
37
41
|
/** Orchestration. Returns the text to emit on stdout ("" for nothing). */
|
|
38
42
|
export async function runHook(input, deps) {
|
|
39
43
|
let hits = [];
|
|
44
|
+
let recallOutcome = "unreachable";
|
|
40
45
|
try {
|
|
41
|
-
|
|
46
|
+
const fetched = await deps.recall(input.query, input.conversationId);
|
|
47
|
+
hits = fetched.hits;
|
|
48
|
+
recallOutcome = fetched.outcome;
|
|
42
49
|
}
|
|
43
50
|
catch {
|
|
44
51
|
hits = [];
|
|
45
52
|
}
|
|
46
|
-
|
|
53
|
+
// Client-side hook composition root: no per-tenant CLI/hook concept exists
|
|
54
|
+
// today, so DEFAULT_TEAM_ID is this surface's real identity, not a placeholder.
|
|
55
|
+
const surfaced = loadSurfaced(DEFAULT_TEAM_ID, input.conversationId);
|
|
47
56
|
const selected = selectHits({
|
|
48
57
|
hits,
|
|
49
58
|
surfaced,
|
|
50
|
-
scoreThreshold:
|
|
51
|
-
relativeFloor:
|
|
59
|
+
scoreThreshold: scoreThreshold(),
|
|
60
|
+
relativeFloor: relativeFloor(),
|
|
52
61
|
perFireCap: PER_FIRE_CAP,
|
|
53
62
|
perConversationCap: PER_CONVERSATION_CAP,
|
|
54
63
|
});
|
|
55
64
|
const block = formatPointerBlock(selected);
|
|
56
65
|
const estTokens = Math.ceil(block.length / 4);
|
|
57
|
-
appendHookLog({
|
|
66
|
+
appendHookLog(DEFAULT_TEAM_ID, {
|
|
58
67
|
ts: new Date().toISOString(),
|
|
59
68
|
conversationId: input.conversationId,
|
|
60
69
|
promptPreview: input.query,
|
|
@@ -63,9 +72,10 @@ export async function runHook(input, deps) {
|
|
|
63
72
|
wouldInject: selected.map((h) => h.id),
|
|
64
73
|
estTokens,
|
|
65
74
|
mode: deps.mode,
|
|
75
|
+
recallOutcome,
|
|
66
76
|
});
|
|
67
77
|
if (deps.mode === "live" && selected.length > 0) {
|
|
68
|
-
recordSurfaced(input.conversationId, selected.map((h) => h.id));
|
|
78
|
+
recordSurfaced(DEFAULT_TEAM_ID, input.conversationId, selected.map((h) => h.id));
|
|
69
79
|
return block;
|
|
70
80
|
}
|
|
71
81
|
return "";
|
|
@@ -92,10 +102,37 @@ async function fetchFailureModeBlock(repo) {
|
|
|
92
102
|
return "";
|
|
93
103
|
}
|
|
94
104
|
}
|
|
105
|
+
const GIT_TIMEOUT_MS = 300;
|
|
106
|
+
const RECENT_COMMITS = 3;
|
|
107
|
+
function git(cwd, args) {
|
|
108
|
+
try {
|
|
109
|
+
return execFileSync("git", ["-C", cwd, ...args], {
|
|
110
|
+
encoding: "utf8",
|
|
111
|
+
timeout: GIT_TIMEOUT_MS,
|
|
112
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
113
|
+
}).trim();
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Branch name plus recent commit subjects. A bare directory name is often a
|
|
121
|
+
* single word ("nlm-memory"), which the recall query extractor rejects as too
|
|
122
|
+
* short, so SessionStart surfaced nothing for most repos.
|
|
123
|
+
*/
|
|
124
|
+
export function readGitContext(workingDirectory) {
|
|
125
|
+
if (!workingDirectory)
|
|
126
|
+
return "";
|
|
127
|
+
const branch = git(workingDirectory, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
128
|
+
const subjects = git(workingDirectory, ["log", `-${RECENT_COMMITS}`, "--format=%s"]);
|
|
129
|
+
const branchWords = branch === "HEAD" ? "" : branch.replace(/[/_-]+/g, " ");
|
|
130
|
+
return [branchWords, subjects.replace(/\n/g, " ")].filter(Boolean).join(" ");
|
|
131
|
+
}
|
|
95
132
|
/** Derive a best-effort query from SessionStart payload fields. */
|
|
96
|
-
function buildQuery(workingDirectory, projectName) {
|
|
133
|
+
export function buildQuery(workingDirectory, projectName, gitContext) {
|
|
97
134
|
const dirTail = workingDirectory.split("/").filter(Boolean).at(-1) ?? "";
|
|
98
|
-
const parts = [dirTail, projectName].filter(Boolean);
|
|
135
|
+
const parts = [dirTail, projectName, gitContext].filter(Boolean);
|
|
99
136
|
return parts.join(" ").trim() || "session start";
|
|
100
137
|
}
|
|
101
138
|
async function main() {
|
|
@@ -110,12 +147,15 @@ async function main() {
|
|
|
110
147
|
? payload.working_directory
|
|
111
148
|
: "";
|
|
112
149
|
const projectName = typeof payload.project_name === "string" ? payload.project_name : "";
|
|
113
|
-
const query = buildQuery(workingDirectory, projectName);
|
|
150
|
+
const query = buildQuery(workingDirectory, projectName, readGitContext(workingDirectory));
|
|
114
151
|
const mode = hookModeFromEnv();
|
|
115
152
|
const [out, failureModes] = await Promise.all([
|
|
116
153
|
runHook({ conversationId, query }, {
|
|
117
154
|
mode,
|
|
118
|
-
recall: async (q, cid) =>
|
|
155
|
+
recall: async (q, cid) => {
|
|
156
|
+
const r = await recallOverHttp(q, "claude-code", cid === "unknown" ? undefined : cid, "hybrid", "session-start-hook");
|
|
157
|
+
return { hits: r.hits, outcome: r.outcome };
|
|
158
|
+
},
|
|
119
159
|
}),
|
|
120
160
|
mode === "live" ? fetchFailureModeBlock(workingDirectory) : Promise.resolve(""),
|
|
121
161
|
]);
|
|
@@ -127,7 +167,7 @@ async function main() {
|
|
|
127
167
|
// Fail open — never block or fail a session start.
|
|
128
168
|
}
|
|
129
169
|
}
|
|
130
|
-
if (
|
|
170
|
+
if (isMainModule(import.meta.url, process.argv[1])) {
|
|
131
171
|
void main();
|
|
132
172
|
}
|
|
133
173
|
//# sourceMappingURL=session-start-hook.js.map
|