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
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry loop for a warmup probe that must survive a backend being absent.
|
|
3
|
+
*
|
|
4
|
+
* The embedder warmup used to be a single fire-and-forget attempt with an empty
|
|
5
|
+
* catch. If the backend was not servable at that instant the stage latched cold
|
|
6
|
+
* for the daemon's entire uptime, even after the backend returned, and only a
|
|
7
|
+
* restart cleared it. Two costs, both real: a five-day silent outage while the
|
|
8
|
+
* embedder was reachable throughout, and a three-week hunt for a release
|
|
9
|
+
* "regression" that did not exist, because restarting inside the same outage
|
|
10
|
+
* window reproduces the failure every time and reads as determinism.
|
|
11
|
+
*
|
|
12
|
+
* Pure except for the injected `sleep`, so the backoff schedule is testable
|
|
13
|
+
* without timers. Never throws: a warmup probe must not be able to take down
|
|
14
|
+
* the process it is reporting on.
|
|
15
|
+
*/
|
|
16
|
+
const DEFAULT_MAX_ATTEMPTS = 60;
|
|
17
|
+
const DEFAULT_BASE_DELAY_MS = 1_000;
|
|
18
|
+
// Caps the tail at a minute: long enough that a backend absent for hours costs
|
|
19
|
+
// ~60 cheap probes, short enough that recovery is noticed within a minute.
|
|
20
|
+
const DEFAULT_MAX_DELAY_MS = 60_000;
|
|
21
|
+
function reasonOf(err) {
|
|
22
|
+
return err instanceof Error ? err.message : String(err);
|
|
23
|
+
}
|
|
24
|
+
export async function retryUntilWarm(deps) {
|
|
25
|
+
const maxAttempts = deps.maxAttempts ?? DEFAULT_MAX_ATTEMPTS;
|
|
26
|
+
const baseDelay = deps.baseDelayMs ?? DEFAULT_BASE_DELAY_MS;
|
|
27
|
+
const maxDelay = deps.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
28
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
29
|
+
try {
|
|
30
|
+
await deps.attempt();
|
|
31
|
+
deps.onSuccess();
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
try {
|
|
36
|
+
deps.onFailure(reasonOf(err), attempt);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// A broken reporter must not end the retry loop.
|
|
40
|
+
}
|
|
41
|
+
if (attempt === maxAttempts)
|
|
42
|
+
return;
|
|
43
|
+
const delay = Math.min(baseDelay * 2 ** (attempt - 1), maxDelay);
|
|
44
|
+
try {
|
|
45
|
+
await deps.sleep(delay);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=warmup-retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"warmup-retry.js","sourceRoot":"","sources":["../../../src/core/health/warmup-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAcH,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAChC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AACpC,+EAA+E;AAC/E,2EAA2E;AAC3E,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAEpC,SAAS,QAAQ,CAAC,GAAY;IAC5B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAwB;IAC3D,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,oBAAoB,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,IAAI,qBAAqB,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,IAAI,oBAAoB,CAAC;IAEzD,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBACH,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;YACzC,CAAC;YAAC,MAAM,CAAC;gBACP,iDAAiD;YACnD,CAAC;YACD,IAAI,OAAO,KAAK,WAAW;gBAAE,OAAO;YACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACjE,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -2,11 +2,26 @@ interface WarmupState {
|
|
|
2
2
|
fts5: boolean;
|
|
3
3
|
textEmbedder: boolean;
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* Why a stage is still cold. A bare `false` is indistinguishable between "the
|
|
7
|
+
* backend was absent at boot" and "this build is broken", and that ambiguity
|
|
8
|
+
* cost three weeks chasing a release regression that did not exist. `since`
|
|
9
|
+
* holds the FIRST failure so health can report how long the lane has been down
|
|
10
|
+
* rather than only the latest retry.
|
|
11
|
+
*/
|
|
12
|
+
export interface WarmupFailure {
|
|
13
|
+
readonly reason: string;
|
|
14
|
+
readonly attempts: number;
|
|
15
|
+
readonly since: string;
|
|
16
|
+
}
|
|
17
|
+
type FailureMap = Partial<Record<keyof WarmupState, WarmupFailure>>;
|
|
5
18
|
export declare function markWarm(stage: keyof WarmupState): void;
|
|
19
|
+
export declare function markWarmFailure(stage: keyof WarmupState, reason: string, attempts: number): void;
|
|
6
20
|
export declare function warmupSnapshot(): {
|
|
7
21
|
fts5: boolean;
|
|
8
22
|
textEmbedder: boolean;
|
|
9
23
|
ready: boolean;
|
|
24
|
+
lastError?: FailureMap;
|
|
10
25
|
};
|
|
11
26
|
export declare function resetWarmupState(): void;
|
|
12
27
|
export {};
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
const state = { fts5: false, textEmbedder: false };
|
|
2
|
+
let failures = {};
|
|
2
3
|
export function markWarm(stage) {
|
|
3
4
|
state[stage] = true;
|
|
5
|
+
delete failures[stage];
|
|
6
|
+
}
|
|
7
|
+
export function markWarmFailure(stage, reason, attempts) {
|
|
8
|
+
const since = failures[stage]?.since ?? new Date().toISOString();
|
|
9
|
+
failures[stage] = { reason, attempts, since };
|
|
4
10
|
}
|
|
5
11
|
export function warmupSnapshot() {
|
|
6
|
-
|
|
12
|
+
const ready = state.fts5 && state.textEmbedder;
|
|
13
|
+
const hasFailure = Object.keys(failures).length > 0;
|
|
14
|
+
return {
|
|
15
|
+
fts5: state.fts5,
|
|
16
|
+
textEmbedder: state.textEmbedder,
|
|
17
|
+
ready,
|
|
18
|
+
...(hasFailure ? { lastError: { ...failures } } : {}),
|
|
19
|
+
};
|
|
7
20
|
}
|
|
8
21
|
export function resetWarmupState() {
|
|
9
22
|
state.fts5 = false;
|
|
10
23
|
state.textEmbedder = false;
|
|
24
|
+
failures = {};
|
|
11
25
|
}
|
|
12
26
|
//# sourceMappingURL=warmup-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warmup-state.js","sourceRoot":"","sources":["../../../src/core/health/warmup-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"warmup-state.js","sourceRoot":"","sources":["../../../src/core/health/warmup-state.ts"],"names":[],"mappings":"AAoBA,MAAM,KAAK,GAAgB,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAChE,IAAI,QAAQ,GAAe,EAAE,CAAC;AAE9B,MAAM,UAAU,QAAQ,CAAC,KAAwB;IAC/C,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IACpB,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAwB,EAAE,MAAc,EAAE,QAAgB;IACxF,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACjE,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,cAAc;IAM5B,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,YAAY,CAAC;IAC/C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IACpD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,KAAK;QACL,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;IACnB,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;IAC3B,QAAQ,GAAG,EAAE,CAAC;AAChB,CAAC"}
|
|
@@ -7,14 +7,18 @@
|
|
|
7
7
|
* holds the set of (conversationId, citedId) pairs already posted, so each
|
|
8
8
|
* citation lands exactly once regardless of how many times Stop fires.
|
|
9
9
|
*
|
|
10
|
-
* Storage parallels the surfaced-memo (`memo.ts`): same state
|
|
11
|
-
* (
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Storage parallels the surfaced-memo (`memo.ts`): same tenant-derived state
|
|
11
|
+
* directory (core/tenancy/tenant-state-path.ts) — the default team's dir is
|
|
12
|
+
* `~/.nlm/hook-state/`, overridable via NLM_HOOK_STATE_DIR; every other
|
|
13
|
+
* tenant is isolated under `~/.nlm/tenants/<tenantId>/hook-state/` and
|
|
14
|
+
* ignores the env override. Filename suffix `.cited.json` distinguishes this
|
|
15
|
+
* memo from the surfaced memo's `.json` within the same directory. The
|
|
16
|
+
* existing memo-sweep walks the default team's directory by mtime and cleans
|
|
17
|
+
* both files together.
|
|
14
18
|
*
|
|
15
19
|
* Defensive: a missing or corrupt file yields an empty set; a write failure
|
|
16
20
|
* is swallowed. Telemetry path — must never break the hook.
|
|
17
21
|
*/
|
|
18
|
-
export declare function loadCited(conversationId: string): Set<string>;
|
|
19
|
-
export declare function recordCited(conversationId: string, ids: ReadonlyArray<string>): void;
|
|
20
|
-
export declare function clearCited(conversationId: string): boolean;
|
|
22
|
+
export declare function loadCited(tenantId: string, conversationId: string): Set<string>;
|
|
23
|
+
export declare function recordCited(tenantId: string, conversationId: string, ids: ReadonlyArray<string>): void;
|
|
24
|
+
export declare function clearCited(tenantId: string, conversationId: string): boolean;
|
|
@@ -7,27 +7,35 @@
|
|
|
7
7
|
* holds the set of (conversationId, citedId) pairs already posted, so each
|
|
8
8
|
* citation lands exactly once regardless of how many times Stop fires.
|
|
9
9
|
*
|
|
10
|
-
* Storage parallels the surfaced-memo (`memo.ts`): same state
|
|
11
|
-
* (
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* Storage parallels the surfaced-memo (`memo.ts`): same tenant-derived state
|
|
11
|
+
* directory (core/tenancy/tenant-state-path.ts) — the default team's dir is
|
|
12
|
+
* `~/.nlm/hook-state/`, overridable via NLM_HOOK_STATE_DIR; every other
|
|
13
|
+
* tenant is isolated under `~/.nlm/tenants/<tenantId>/hook-state/` and
|
|
14
|
+
* ignores the env override. Filename suffix `.cited.json` distinguishes this
|
|
15
|
+
* memo from the surfaced memo's `.json` within the same directory. The
|
|
16
|
+
* existing memo-sweep walks the default team's directory by mtime and cleans
|
|
17
|
+
* both files together.
|
|
14
18
|
*
|
|
15
19
|
* Defensive: a missing or corrupt file yields an empty set; a write failure
|
|
16
20
|
* is swallowed. Telemetry path — must never break the hook.
|
|
17
21
|
*/
|
|
18
22
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
19
|
-
import { homedir } from "node:os";
|
|
20
23
|
import { join } from "node:path";
|
|
21
|
-
|
|
22
|
-
|
|
24
|
+
import { tenantStatePath } from "../tenancy/tenant-state-path.js";
|
|
25
|
+
import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
|
|
26
|
+
function stateDir(tenantId) {
|
|
27
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
28
|
+
return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
|
|
29
|
+
}
|
|
30
|
+
return tenantStatePath(tenantId, "hook-state");
|
|
23
31
|
}
|
|
24
|
-
function memoPath(conversationId) {
|
|
32
|
+
function memoPath(tenantId, conversationId) {
|
|
25
33
|
const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
26
|
-
return join(stateDir(), `${safe}.cited.json`);
|
|
34
|
+
return join(stateDir(tenantId), `${safe}.cited.json`);
|
|
27
35
|
}
|
|
28
|
-
export function loadCited(conversationId) {
|
|
36
|
+
export function loadCited(tenantId, conversationId) {
|
|
29
37
|
try {
|
|
30
|
-
const path = memoPath(conversationId);
|
|
38
|
+
const path = memoPath(tenantId, conversationId);
|
|
31
39
|
if (!existsSync(path))
|
|
32
40
|
return new Set();
|
|
33
41
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
@@ -39,23 +47,23 @@ export function loadCited(conversationId) {
|
|
|
39
47
|
return new Set();
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
|
-
export function recordCited(conversationId, ids) {
|
|
50
|
+
export function recordCited(tenantId, conversationId, ids) {
|
|
43
51
|
if (ids.length === 0)
|
|
44
52
|
return;
|
|
45
53
|
try {
|
|
46
|
-
const merged = loadCited(conversationId);
|
|
54
|
+
const merged = loadCited(tenantId, conversationId);
|
|
47
55
|
for (const id of ids)
|
|
48
56
|
merged.add(id);
|
|
49
|
-
mkdirSync(stateDir(), { recursive: true });
|
|
50
|
-
writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
|
|
57
|
+
mkdirSync(stateDir(tenantId), { recursive: true });
|
|
58
|
+
writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
|
|
51
59
|
}
|
|
52
60
|
catch {
|
|
53
61
|
// Memo write failure must never break the hook.
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
|
-
export function clearCited(conversationId) {
|
|
64
|
+
export function clearCited(tenantId, conversationId) {
|
|
57
65
|
try {
|
|
58
|
-
const path = memoPath(conversationId);
|
|
66
|
+
const path = memoPath(tenantId, conversationId);
|
|
59
67
|
if (!existsSync(path))
|
|
60
68
|
return false;
|
|
61
69
|
rmSync(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cite-memo.js","sourceRoot":"","sources":["../../../src/core/hook/cite-memo.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"cite-memo.js","sourceRoot":"","sources":["../../../src/core/hook/cite-memo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,SAAS,QAAQ,CAAC,QAAgB;IAChC,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB,EAAE,cAAsB;IACxD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;IACzE,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,cAAsB;IAChE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QACxC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QAC7C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAAgB,EAChB,cAAsB,EACtB,GAA0B;IAE1B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACnD,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,cAAsB;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
* evaluated. This is the dataset the relevance gate (generative patterns +
|
|
4
4
|
* score threshold) is calibrated against during the shadow window.
|
|
5
5
|
*
|
|
6
|
-
* Path
|
|
6
|
+
* Path is tenant-derived (core/tenancy/tenant-state-path.ts): the default
|
|
7
|
+
* team's log is ~/.nlm/hook-log.jsonl, overridable via NLM_HOOK_LOG; every
|
|
8
|
+
* other tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-log.jsonl
|
|
9
|
+
* and ignores the env override.
|
|
7
10
|
* appendHookLog swallows its own errors — telemetry must never break the hook.
|
|
8
11
|
* Uses synchronous I/O: the hook is a short-lived per-prompt process, and an
|
|
9
12
|
* async write could be lost if the process exits before it flushes.
|
|
@@ -21,10 +24,18 @@ export interface HookLogEntry {
|
|
|
21
24
|
readonly wouldInject: ReadonlyArray<string>;
|
|
22
25
|
readonly estTokens: number;
|
|
23
26
|
readonly mode: "shadow" | "live";
|
|
27
|
+
/**
|
|
28
|
+
* The hook build that wrote this line. Lets the digest assert the hooks
|
|
29
|
+
* actually running match the installed version — liveness alone cannot.
|
|
30
|
+
*/
|
|
31
|
+
readonly v?: string;
|
|
32
|
+
/** Why recall returned what it did. Absent on gate-skipped fires (no recall ran).
|
|
33
|
+
* Without it, `hits: []` cannot be told apart from a recall that timed out. */
|
|
34
|
+
readonly recallOutcome?: "ok" | "timeout" | "unreachable" | "http-error" | "skipped";
|
|
24
35
|
/** Per-candidate relevance-gate decisions, when the recall gate ran. */
|
|
25
36
|
readonly gateDecisions?: ReadonlyArray<{
|
|
26
37
|
readonly id: string;
|
|
27
38
|
readonly gate: "relevant" | "irrelevant";
|
|
28
39
|
}>;
|
|
29
40
|
}
|
|
30
|
-
export declare function appendHookLog(entry: HookLogEntry): void;
|
|
41
|
+
export declare function appendHookLog(tenantId: string, entry: HookLogEntry): void;
|
|
@@ -3,23 +3,31 @@
|
|
|
3
3
|
* evaluated. This is the dataset the relevance gate (generative patterns +
|
|
4
4
|
* score threshold) is calibrated against during the shadow window.
|
|
5
5
|
*
|
|
6
|
-
* Path
|
|
6
|
+
* Path is tenant-derived (core/tenancy/tenant-state-path.ts): the default
|
|
7
|
+
* team's log is ~/.nlm/hook-log.jsonl, overridable via NLM_HOOK_LOG; every
|
|
8
|
+
* other tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-log.jsonl
|
|
9
|
+
* and ignores the env override.
|
|
7
10
|
* appendHookLog swallows its own errors — telemetry must never break the hook.
|
|
8
11
|
* Uses synchronous I/O: the hook is a short-lived per-prompt process, and an
|
|
9
12
|
* async write could be lost if the process exits before it flushes.
|
|
10
13
|
*/
|
|
11
14
|
import { appendFileSync, mkdirSync } from "node:fs";
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
import { dirname } from "node:path";
|
|
16
|
+
import { tenantStatePath } from "../tenancy/tenant-state-path.js";
|
|
17
|
+
import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
|
|
18
|
+
import { NLM_VERSION } from "../../shared/version.js";
|
|
19
|
+
function logPath(tenantId) {
|
|
20
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
21
|
+
return process.env["NLM_HOOK_LOG"] ?? tenantStatePath(tenantId, "hook-log.jsonl");
|
|
22
|
+
}
|
|
23
|
+
return tenantStatePath(tenantId, "hook-log.jsonl");
|
|
16
24
|
}
|
|
17
|
-
export function appendHookLog(entry) {
|
|
25
|
+
export function appendHookLog(tenantId, entry) {
|
|
18
26
|
try {
|
|
19
|
-
const path = logPath();
|
|
27
|
+
const path = logPath(tenantId);
|
|
20
28
|
mkdirSync(dirname(path), { recursive: true });
|
|
21
29
|
// Sync I/O: hook is a short-lived process — async write could be lost on exit.
|
|
22
|
-
appendFileSync(path, `${JSON.stringify(entry)}\n`, "utf8");
|
|
30
|
+
appendFileSync(path, `${JSON.stringify({ ...entry, v: NLM_VERSION })}\n`, "utf8");
|
|
23
31
|
}
|
|
24
32
|
catch {
|
|
25
33
|
// Telemetry failure must never break the hook.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-log.js","sourceRoot":"","sources":["../../../src/core/hook/hook-log.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hook-log.js","sourceRoot":"","sources":["../../../src/core/hook/hook-log.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAwBjD,SAAS,OAAO,CAAC,QAAgB;IAC/B,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IACpF,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,KAAmB;IACjE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC/B,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9C,+EAA+E;QAC/E,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpF,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC"}
|
package/dist/core/hook/memo.d.ts
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
* conversation holds the set of session ids already surfaced, so each is
|
|
4
4
|
* surfaced at most once per conversation.
|
|
5
5
|
*
|
|
6
|
-
* State dir
|
|
7
|
-
*
|
|
6
|
+
* State dir is tenant-derived (core/tenancy/tenant-state-path.ts): the
|
|
7
|
+
* default team's memo dir is ~/.nlm/hook-state/, overridable via
|
|
8
|
+
* NLM_HOOK_STATE_DIR (testability — mirrors query-log.ts); every other
|
|
9
|
+
* tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-state/ and
|
|
10
|
+
* ignores the env override (see the path contract note in
|
|
11
|
+
* tenant-state-path.ts).
|
|
8
12
|
*
|
|
9
13
|
* Every function is defensive: a missing or corrupt file yields an empty
|
|
10
14
|
* memo, and a write failure is swallowed. The hook must never break on memo
|
|
11
15
|
* I/O.
|
|
12
16
|
*/
|
|
13
|
-
export declare function loadSurfaced(conversationId: string): Set<string>;
|
|
14
|
-
export declare function recordSurfaced(conversationId: string, ids: ReadonlyArray<string>): void;
|
|
17
|
+
export declare function loadSurfaced(tenantId: string, conversationId: string): Set<string>;
|
|
18
|
+
export declare function recordSurfaced(tenantId: string, conversationId: string, ids: ReadonlyArray<string>): void;
|
|
15
19
|
/**
|
|
16
20
|
* Reverse lookup: which conversation most recently surfaced `sessionId`?
|
|
17
21
|
*
|
|
@@ -23,10 +27,10 @@ export declare function recordSurfaced(conversationId: string, ids: ReadonlyArra
|
|
|
23
27
|
*
|
|
24
28
|
* Defensive: any I/O error yields null so cite_session never breaks.
|
|
25
29
|
*/
|
|
26
|
-
export declare function resolveConversationForSession(sessionId: string): string | null;
|
|
30
|
+
export declare function resolveConversationForSession(tenantId: string, sessionId: string): string | null;
|
|
27
31
|
/**
|
|
28
32
|
* Delete the memo file for a closed conversation. Called by the SessionEnd
|
|
29
33
|
* hook so memo files don't accumulate forever. Returns true if a file was
|
|
30
34
|
* removed, false otherwise — callers may want to log the outcome.
|
|
31
35
|
*/
|
|
32
|
-
export declare function clearSurfaced(conversationId: string): boolean;
|
|
36
|
+
export declare function clearSurfaced(tenantId: string, conversationId: string): boolean;
|
package/dist/core/hook/memo.js
CHANGED
|
@@ -3,26 +3,34 @@
|
|
|
3
3
|
* conversation holds the set of session ids already surfaced, so each is
|
|
4
4
|
* surfaced at most once per conversation.
|
|
5
5
|
*
|
|
6
|
-
* State dir
|
|
7
|
-
*
|
|
6
|
+
* State dir is tenant-derived (core/tenancy/tenant-state-path.ts): the
|
|
7
|
+
* default team's memo dir is ~/.nlm/hook-state/, overridable via
|
|
8
|
+
* NLM_HOOK_STATE_DIR (testability — mirrors query-log.ts); every other
|
|
9
|
+
* tenant is isolated under ~/.nlm/tenants/<tenantId>/hook-state/ and
|
|
10
|
+
* ignores the env override (see the path contract note in
|
|
11
|
+
* tenant-state-path.ts).
|
|
8
12
|
*
|
|
9
13
|
* Every function is defensive: a missing or corrupt file yields an empty
|
|
10
14
|
* memo, and a write failure is swallowed. The hook must never break on memo
|
|
11
15
|
* I/O.
|
|
12
16
|
*/
|
|
13
17
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from "node:fs";
|
|
14
|
-
import { homedir } from "node:os";
|
|
15
18
|
import { join } from "node:path";
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
import { tenantStatePath } from "../tenancy/tenant-state-path.js";
|
|
20
|
+
import { DEFAULT_TEAM_ID } from "../tenancy/default-team.js";
|
|
21
|
+
function stateDir(tenantId) {
|
|
22
|
+
if (tenantId === DEFAULT_TEAM_ID) {
|
|
23
|
+
return process.env["NLM_HOOK_STATE_DIR"] ?? tenantStatePath(tenantId, "hook-state");
|
|
24
|
+
}
|
|
25
|
+
return tenantStatePath(tenantId, "hook-state");
|
|
18
26
|
}
|
|
19
|
-
function memoPath(conversationId) {
|
|
27
|
+
function memoPath(tenantId, conversationId) {
|
|
20
28
|
const safe = conversationId.replace(/[^A-Za-z0-9_-]/g, "_") || "unknown";
|
|
21
|
-
return join(stateDir(), `${safe}.json`);
|
|
29
|
+
return join(stateDir(tenantId), `${safe}.json`);
|
|
22
30
|
}
|
|
23
|
-
export function loadSurfaced(conversationId) {
|
|
31
|
+
export function loadSurfaced(tenantId, conversationId) {
|
|
24
32
|
try {
|
|
25
|
-
const path = memoPath(conversationId);
|
|
33
|
+
const path = memoPath(tenantId, conversationId);
|
|
26
34
|
if (!existsSync(path))
|
|
27
35
|
return new Set();
|
|
28
36
|
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
@@ -34,13 +42,13 @@ export function loadSurfaced(conversationId) {
|
|
|
34
42
|
return new Set();
|
|
35
43
|
}
|
|
36
44
|
}
|
|
37
|
-
export function recordSurfaced(conversationId, ids) {
|
|
45
|
+
export function recordSurfaced(tenantId, conversationId, ids) {
|
|
38
46
|
try {
|
|
39
|
-
const merged = loadSurfaced(conversationId);
|
|
47
|
+
const merged = loadSurfaced(tenantId, conversationId);
|
|
40
48
|
for (const id of ids)
|
|
41
49
|
merged.add(id);
|
|
42
|
-
mkdirSync(stateDir(), { recursive: true });
|
|
43
|
-
writeFileSync(memoPath(conversationId), JSON.stringify([...merged]), "utf8");
|
|
50
|
+
mkdirSync(stateDir(tenantId), { recursive: true });
|
|
51
|
+
writeFileSync(memoPath(tenantId, conversationId), JSON.stringify([...merged]), "utf8");
|
|
44
52
|
}
|
|
45
53
|
catch {
|
|
46
54
|
// Memo write failure must never break the hook.
|
|
@@ -57,9 +65,9 @@ export function recordSurfaced(conversationId, ids) {
|
|
|
57
65
|
*
|
|
58
66
|
* Defensive: any I/O error yields null so cite_session never breaks.
|
|
59
67
|
*/
|
|
60
|
-
export function resolveConversationForSession(sessionId) {
|
|
68
|
+
export function resolveConversationForSession(tenantId, sessionId) {
|
|
61
69
|
try {
|
|
62
|
-
const dir = stateDir();
|
|
70
|
+
const dir = stateDir(tenantId);
|
|
63
71
|
if (!existsSync(dir))
|
|
64
72
|
return null;
|
|
65
73
|
let best = null;
|
|
@@ -91,9 +99,9 @@ export function resolveConversationForSession(sessionId) {
|
|
|
91
99
|
* hook so memo files don't accumulate forever. Returns true if a file was
|
|
92
100
|
* removed, false otherwise — callers may want to log the outcome.
|
|
93
101
|
*/
|
|
94
|
-
export function clearSurfaced(conversationId) {
|
|
102
|
+
export function clearSurfaced(tenantId, conversationId) {
|
|
95
103
|
try {
|
|
96
|
-
const path = memoPath(conversationId);
|
|
104
|
+
const path = memoPath(tenantId, conversationId);
|
|
97
105
|
if (!existsSync(path))
|
|
98
106
|
return false;
|
|
99
107
|
rmSync(path);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memo.js","sourceRoot":"","sources":["../../../src/core/hook/memo.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"memo.js","sourceRoot":"","sources":["../../../src/core/hook/memo.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,MAAM,EACN,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,SAAS,QAAQ,CAAC,QAAgB;IAChC,IAAI,QAAQ,KAAK,eAAe,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACtF,CAAC;IACD,OAAO,eAAe,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,QAAQ,CAAC,QAAgB,EAAE,cAAsB;IACxD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,IAAI,SAAS,CAAC;IACzE,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,cAAsB;IACnE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QACxC,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QAC7C,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,QAAgB,EAChB,cAAsB,EACtB,GAA0B;IAE1B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QACtD,KAAK,MAAM,EAAE,IAAI,GAAG;YAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,6BAA6B,CAAC,QAAgB,EAAE,SAAiB;IAC/E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAClC,IAAI,IAAI,GAAuD,IAAI,CAAC;QACpE,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;oBAAE,SAAS;gBACpE,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC;gBACvC,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;oBAC5C,IAAI,GAAG,EAAE,cAAc,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;gBACrE,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wCAAwC;YAC1C,CAAC;QACH,CAAC;QACD,OAAO,IAAI,EAAE,cAAc,IAAI,IAAI,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,cAAsB;IACpE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACpC,MAAM,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -29,5 +29,12 @@ export interface PointerExemplar {
|
|
|
29
29
|
readonly repo: string;
|
|
30
30
|
readonly taskContext: string;
|
|
31
31
|
}
|
|
32
|
+
export interface PointerConcept {
|
|
33
|
+
readonly concept: string;
|
|
34
|
+
readonly status: string;
|
|
35
|
+
readonly attemptCount: number;
|
|
36
|
+
/** Owning enrollment's latest next_step (shared across its concepts). */
|
|
37
|
+
readonly nextStep: string | null;
|
|
38
|
+
}
|
|
32
39
|
export declare function truncateSummary(s: string, max?: number): string;
|
|
33
|
-
export declare function formatPointerBlock(hits: ReadonlyArray<PointerHit>, facts?: ReadonlyArray<PointerFact>, exemplars?: ReadonlyArray<PointerExemplar>): string;
|
|
40
|
+
export declare function formatPointerBlock(hits: ReadonlyArray<PointerHit>, facts?: ReadonlyArray<PointerFact>, exemplars?: ReadonlyArray<PointerExemplar>, concepts?: ReadonlyArray<PointerConcept>): string;
|
|
@@ -32,8 +32,8 @@ export function truncateSummary(s, max = 200) {
|
|
|
32
32
|
}
|
|
33
33
|
return window + " ...";
|
|
34
34
|
}
|
|
35
|
-
export function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
36
|
-
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0)
|
|
35
|
+
export function formatPointerBlock(hits, facts = [], exemplars = [], concepts = []) {
|
|
36
|
+
if (hits.length === 0 && facts.length === 0 && exemplars.length === 0 && concepts.length === 0)
|
|
37
37
|
return "";
|
|
38
38
|
const out = [];
|
|
39
39
|
if (hits.length > 0) {
|
|
@@ -66,9 +66,22 @@ export function formatPointerBlock(hits, facts = [], exemplars = []) {
|
|
|
66
66
|
out.push(`- [${e.outcome}] ${langPart}${e.repo} - ${truncateSummary(e.taskContext)}`);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
if (concepts.length > 0) {
|
|
70
|
+
if (out.length > 0)
|
|
71
|
+
out.push("");
|
|
72
|
+
out.push("## Learning state (nlm-memory)");
|
|
73
|
+
for (const c of concepts) {
|
|
74
|
+
const n = c.attemptCount === 1 ? "1 attempt" : `${c.attemptCount} attempts`;
|
|
75
|
+
out.push(`- [${c.status}] ${c.concept} (${n})`);
|
|
76
|
+
}
|
|
77
|
+
const nextSteps = [...new Set(concepts.map((c) => c.nextStep).filter((s) => !!s))].slice(0, 2);
|
|
78
|
+
for (const next of nextSteps) {
|
|
79
|
+
out.push(`Next: ${truncateSummary(next, 120)}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
69
82
|
const tools = exemplars.length > 0
|
|
70
|
-
? "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)."
|
|
71
|
-
: "NLM tools: recall_sessions (search), get_session (full transcript), recall_facts (prior decisions), get_fact_history (how a decision evolved).";
|
|
83
|
+
? "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)."
|
|
84
|
+
: "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).";
|
|
72
85
|
out.push(tools);
|
|
73
86
|
return out.join("\n");
|
|
74
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pointer-block.js","sourceRoot":"","sources":["../../../src/core/hook/pointer-block.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"pointer-block.js","sourceRoot":"","sources":["../../../src/core/hook/pointer-block.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resolve which
|
|
3
|
-
*
|
|
4
|
-
* for the exact query string.
|
|
2
|
+
* Resolve which conversation triggered a recall pull, by scanning the N
|
|
3
|
+
* most-recently-modified transcript JSONL files across the local runtimes'
|
|
4
|
+
* transcript stores for the exact query string.
|
|
5
5
|
*
|
|
6
6
|
* When an agent calls a recall tool, the runtime has already written the
|
|
7
7
|
* tool_use block (containing the query string) to its transcript before the
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
* deterministic, cheap join between a pull log entry and its source
|
|
10
10
|
* conversation, without requiring the agent to pass conversation_id explicitly.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* resolve to
|
|
12
|
+
* Claude Code conversations resolve to their bare transcript id; other
|
|
13
|
+
* runtimes resolve to `<runtime>:<id>` so their ids can't collide.
|
|
14
14
|
*
|
|
15
15
|
* Fail-open: any I/O error returns null so the recall path never breaks.
|
|
16
16
|
*/
|
|
17
17
|
export interface ResolveByQueryOpts {
|
|
18
|
+
/** Scan only this directory, as Claude Code transcripts. */
|
|
18
19
|
readonly rootDir?: string;
|
|
19
20
|
}
|
|
20
21
|
/**
|