nlm-memory 0.20.0 → 0.21.0
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 +19 -10
- package/dist/cli/digest.js +60 -1
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/init.d.ts +12 -0
- package/dist/cli/init.js +49 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/nlm.d.ts +13 -1
- package/dist/cli/nlm.js +872 -61
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/scope-backfill.d.ts +34 -0
- package/dist/cli/scope-backfill.js +237 -0
- package/dist/cli/scope-backfill.js.map +1 -0
- package/dist/cli/scope-coverage.d.ts +44 -0
- package/dist/cli/scope-coverage.js +205 -0
- package/dist/cli/scope-coverage.js.map +1 -0
- package/dist/core/actions/overlay.d.ts +20 -6
- package/dist/core/actions/overlay.js +32 -18
- package/dist/core/actions/overlay.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts +14 -0
- package/dist/core/adapters/claude-code.js +36 -0
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/classifier/prompt.js +3 -3
- package/dist/core/dataset/build-dataset.js +1 -0
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +13 -3
- package/dist/core/digest/compose.js +23 -18
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/digest/hook-injection.d.ts +43 -0
- package/dist/core/digest/hook-injection.js +79 -0
- package/dist/core/digest/hook-injection.js.map +1 -0
- package/dist/core/embedding/embed-backfill.d.ts +13 -2
- package/dist/core/embedding/embed-backfill.js +181 -43
- package/dist/core/embedding/embed-backfill.js.map +1 -1
- package/dist/core/embedding/embedding-config.d.ts +17 -0
- package/dist/core/embedding/embedding-config.js +12 -0
- package/dist/core/embedding/embedding-config.js.map +1 -0
- package/dist/core/embedding/pg-embed-backfill.d.ts +31 -0
- package/dist/core/embedding/pg-embed-backfill.js +264 -0
- package/dist/core/embedding/pg-embed-backfill.js.map +1 -0
- package/dist/core/entities/dedup-suggest.d.ts +25 -0
- package/dist/core/entities/dedup-suggest.js +107 -0
- package/dist/core/entities/dedup-suggest.js.map +1 -0
- package/dist/core/eval/classifier-fixture-eval.d.ts +29 -0
- package/dist/core/eval/classifier-fixture-eval.js +217 -0
- package/dist/core/eval/classifier-fixture-eval.js.map +1 -0
- package/dist/core/eval/extraction-scoring.d.ts +63 -0
- package/dist/core/eval/extraction-scoring.js +79 -0
- package/dist/core/eval/extraction-scoring.js.map +1 -0
- package/dist/core/eval/run-eval.d.ts +40 -0
- package/dist/core/eval/run-eval.js +34 -0
- package/dist/core/eval/run-eval.js.map +1 -0
- package/dist/core/exemplars/capture-from-session.d.ts +2 -0
- package/dist/core/exemplars/capture-from-session.js +7 -3
- package/dist/core/exemplars/capture-from-session.js.map +1 -1
- package/dist/core/exemplars/diff-parse.d.ts +23 -0
- package/dist/core/exemplars/diff-parse.js +73 -0
- package/dist/core/exemplars/diff-parse.js.map +1 -0
- package/dist/core/exemplars/embed-backfill.d.ts +36 -0
- package/dist/core/exemplars/embed-backfill.js +85 -0
- package/dist/core/exemplars/embed-backfill.js.map +1 -0
- package/dist/core/exemplars/embed-text.d.ts +15 -0
- package/dist/core/exemplars/embed-text.js +18 -0
- package/dist/core/exemplars/embed-text.js.map +1 -0
- package/dist/core/exemplars/extract-exemplar.d.ts +2 -0
- package/dist/core/exemplars/extract-exemplar.js +9 -66
- package/dist/core/exemplars/extract-exemplar.js.map +1 -1
- package/dist/core/exemplars/ingest-exemplar.d.ts +1 -0
- package/dist/core/exemplars/ingest-exemplar.js +1 -0
- package/dist/core/exemplars/ingest-exemplar.js.map +1 -1
- package/dist/core/exemplars/recall-code.js +4 -0
- package/dist/core/exemplars/recall-code.js.map +1 -1
- package/dist/core/exemplars/warm-embedder.d.ts +14 -0
- package/dist/core/exemplars/warm-embedder.js +18 -0
- package/dist/core/exemplars/warm-embedder.js.map +1 -0
- package/dist/core/health/corpus-state.d.ts +8 -0
- package/dist/core/health/corpus-state.js +11 -0
- package/dist/core/health/corpus-state.js.map +1 -0
- package/dist/core/health/embed-inflight.d.ts +9 -0
- package/dist/core/health/embed-inflight.js +30 -0
- package/dist/core/health/embed-inflight.js.map +1 -0
- package/dist/core/health/embedding-lane-state.d.ts +6 -0
- package/dist/core/health/embedding-lane-state.js +18 -0
- package/dist/core/health/embedding-lane-state.js.map +1 -0
- package/dist/core/health/warmup-state.d.ts +12 -0
- package/dist/core/health/warmup-state.js +12 -0
- package/dist/core/health/warmup-state.js.map +1 -0
- package/dist/core/hook/claude-settings.d.ts +1 -1
- package/dist/core/hook/claude-settings.js +0 -1
- package/dist/core/hook/claude-settings.js.map +1 -1
- package/dist/core/hook/gate.d.ts +13 -6
- package/dist/core/hook/gate.js +47 -6
- package/dist/core/hook/gate.js.map +1 -1
- package/dist/core/hook/hook-log.d.ts +5 -0
- package/dist/core/hook/hook-log.js.map +1 -1
- package/dist/core/hook/memo.d.ts +12 -0
- package/dist/core/hook/memo.js +41 -1
- package/dist/core/hook/memo.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +1 -0
- package/dist/core/hook/pointer-block.js +23 -2
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/query-extract.d.ts +2 -1
- package/dist/core/hook/query-extract.js +10 -1
- package/dist/core/hook/query-extract.js.map +1 -1
- package/dist/core/hook/resolve-conversation-by-query.d.ts +28 -0
- package/dist/core/hook/resolve-conversation-by-query.js +98 -0
- package/dist/core/hook/resolve-conversation-by-query.js.map +1 -0
- package/dist/core/hook/select.d.ts +8 -0
- package/dist/core/hook/select.js +9 -2
- package/dist/core/hook/select.js.map +1 -1
- package/dist/core/hook/transcript.js +16 -2
- package/dist/core/hook/transcript.js.map +1 -1
- package/dist/core/ingest/backfill-derivables.d.ts +92 -0
- package/dist/core/ingest/backfill-derivables.js +175 -0
- package/dist/core/ingest/backfill-derivables.js.map +1 -0
- package/dist/core/ingest/ingest-session.d.ts +5 -0
- package/dist/core/ingest/ingest-session.js +23 -0
- package/dist/core/ingest/ingest-session.js.map +1 -1
- package/dist/core/ingest/reclassify-oversized.d.ts +5 -0
- package/dist/core/ingest/reclassify-oversized.js +9 -0
- package/dist/core/ingest/reclassify-oversized.js.map +1 -1
- package/dist/core/ingest/reprocess.d.ts +96 -0
- package/dist/core/ingest/reprocess.js +280 -0
- package/dist/core/ingest/reprocess.js.map +1 -0
- package/dist/core/ingest/transcript-derivables.d.ts +27 -0
- package/dist/core/ingest/transcript-derivables.js +138 -0
- package/dist/core/ingest/transcript-derivables.js.map +1 -0
- package/dist/core/integrity/check-invariants.d.ts +6 -1
- package/dist/core/integrity/check-invariants.js +209 -3
- package/dist/core/integrity/check-invariants.js.map +1 -1
- package/dist/core/metrics/corpus-stats.d.ts +49 -0
- package/dist/core/metrics/corpus-stats.js +111 -0
- package/dist/core/metrics/corpus-stats.js.map +1 -0
- package/dist/core/metrics/re-derivation.d.ts +48 -0
- package/dist/core/metrics/re-derivation.js +87 -0
- package/dist/core/metrics/re-derivation.js.map +1 -0
- package/dist/core/outcome/coverage.d.ts +33 -0
- package/dist/core/outcome/coverage.js +46 -0
- package/dist/core/outcome/coverage.js.map +1 -0
- package/dist/core/outcome/rollup.d.ts +33 -0
- package/dist/core/outcome/rollup.js +113 -0
- package/dist/core/outcome/rollup.js.map +1 -0
- package/dist/core/recall/citation-log.d.ts +8 -0
- package/dist/core/recall/citation-log.js +17 -0
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/hook-recall-log.d.ts +2 -2
- package/dist/core/recall/hook-recall-log.js +2 -2
- package/dist/core/recall/query-intent.d.ts +7 -0
- package/dist/core/recall/query-intent.js +25 -0
- package/dist/core/recall/query-intent.js.map +1 -0
- package/dist/core/recall/query-log.d.ts +4 -0
- package/dist/core/recall/query-log.js +4 -0
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.d.ts +37 -1
- package/dist/core/recall/recall-service.js +106 -63
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/related-exemplars.d.ts +1 -0
- package/dist/core/recall/related-exemplars.js +4 -1
- package/dist/core/recall/related-exemplars.js.map +1 -1
- package/dist/core/recall/related-facts.js +2 -2
- package/dist/core/recall/related-facts.js.map +1 -1
- package/dist/core/recall/reranker.d.ts +2 -1
- package/dist/core/recall/reranker.js +3 -3
- package/dist/core/recall/reranker.js.map +1 -1
- package/dist/core/recall-facts/fact-query-log.d.ts +7 -0
- package/dist/core/recall-facts/fact-query-log.js +2 -0
- package/dist/core/recall-facts/fact-query-log.js.map +1 -1
- package/dist/core/recall-facts/fact-recall-service.d.ts +9 -1
- package/dist/core/recall-facts/fact-recall-service.js +22 -8
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.d.ts +6 -6
- package/dist/core/scheduler/scan-once.js +15 -49
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.d.ts +10 -0
- package/dist/core/scheduler/scheduler.js +109 -13
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/scope/alias-map.d.ts +10 -0
- package/dist/core/scope/alias-map.js +41 -0
- package/dist/core/scope/alias-map.js.map +1 -0
- package/dist/core/scope/derive-scope.d.ts +8 -0
- package/dist/core/scope/derive-scope.js +54 -0
- package/dist/core/scope/derive-scope.js.map +1 -0
- package/dist/core/scope/scope-clause.d.ts +16 -0
- package/dist/core/scope/scope-clause.js +21 -0
- package/dist/core/scope/scope-clause.js.map +1 -0
- package/dist/core/scope/stamp-flag.d.ts +1 -0
- package/dist/core/scope/stamp-flag.js +4 -0
- package/dist/core/scope/stamp-flag.js.map +1 -0
- package/dist/core/signals/code-signal.d.ts +50 -0
- package/dist/core/signals/code-signal.js +54 -0
- package/dist/core/signals/code-signal.js.map +1 -0
- package/dist/core/signals/ingest-signal.d.ts +1 -1
- package/dist/core/signals/ingest-signal.js +3 -1
- package/dist/core/signals/ingest-signal.js.map +1 -1
- package/dist/core/signals/stamp-scope.d.ts +18 -0
- package/dist/core/signals/stamp-scope.js +28 -0
- package/dist/core/signals/stamp-scope.js.map +1 -0
- package/dist/core/storage/db-restore.js +3 -1
- package/dist/core/storage/db-restore.js.map +1 -1
- package/dist/core/storage/fact-batch.d.ts +9 -0
- package/dist/core/storage/fact-batch.js +14 -0
- package/dist/core/storage/fact-batch.js.map +1 -0
- package/dist/core/storage/pg-code-exemplar-store.d.ts +1 -0
- package/dist/core/storage/pg-code-exemplar-store.js +13 -2
- package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/pg-embedding-config.d.ts +29 -0
- package/dist/core/storage/pg-embedding-config.js +53 -0
- package/dist/core/storage/pg-embedding-config.js.map +1 -0
- package/dist/core/storage/pg-entity-store.d.ts +12 -0
- package/dist/core/storage/pg-entity-store.js +79 -0
- package/dist/core/storage/pg-entity-store.js.map +1 -0
- package/dist/core/storage/pg-fact-ingest.d.ts +15 -0
- package/dist/core/storage/pg-fact-ingest.js +34 -0
- package/dist/core/storage/pg-fact-ingest.js.map +1 -0
- package/dist/core/storage/pg-fact-store.d.ts +3 -0
- package/dist/core/storage/pg-fact-store.js +26 -30
- package/dist/core/storage/pg-fact-store.js.map +1 -1
- package/dist/core/storage/pg-migrate.d.ts +18 -0
- package/dist/core/storage/pg-migrate.js +73 -0
- package/dist/core/storage/pg-migrate.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +11 -2
- package/dist/core/storage/pg-session-store.js +224 -96
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/pg-signal-store.js +4 -3
- package/dist/core/storage/pg-signal-store.js.map +1 -1
- package/dist/core/storage/pg-storage.d.ts +9 -7
- package/dist/core/storage/pg-storage.js +20 -50
- package/dist/core/storage/pg-storage.js.map +1 -1
- package/dist/core/storage/pg-workstream-store.d.ts +25 -0
- package/dist/core/storage/pg-workstream-store.js +97 -0
- package/dist/core/storage/pg-workstream-store.js.map +1 -0
- package/dist/core/storage/sqlite-code-exemplar-store.d.ts +1 -0
- package/dist/core/storage/sqlite-code-exemplar-store.js +15 -2
- package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/sqlite-embedding-config.d.ts +10 -0
- package/dist/core/storage/sqlite-embedding-config.js +27 -0
- package/dist/core/storage/sqlite-embedding-config.js.map +1 -0
- package/dist/core/storage/sqlite-entity-store.d.ts +13 -0
- package/dist/core/storage/sqlite-entity-store.js +96 -0
- package/dist/core/storage/sqlite-entity-store.js.map +1 -0
- package/dist/core/storage/sqlite-fact-store.d.ts +15 -7
- package/dist/core/storage/sqlite-fact-store.js +81 -27
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-outcome-store.d.ts +89 -0
- package/dist/core/storage/sqlite-outcome-store.js +158 -0
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -0
- package/dist/core/storage/sqlite-session-store.d.ts +42 -7
- package/dist/core/storage/sqlite-session-store.js +208 -95
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-signal-store.js +4 -2
- package/dist/core/storage/sqlite-signal-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +8 -8
- package/dist/core/storage/sqlite-storage.js +21 -32
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/sqlite-workstream-store.d.ts +25 -0
- package/dist/core/storage/sqlite-workstream-store.js +99 -0
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -0
- package/dist/core/storage/supersedence-log.js +2 -0
- package/dist/core/storage/supersedence-log.js.map +1 -1
- package/dist/core/telemetry/probe-filter.d.ts +35 -0
- package/dist/core/telemetry/probe-filter.js +56 -0
- package/dist/core/telemetry/probe-filter.js.map +1 -0
- package/dist/core/update-check/check.d.ts +6 -0
- package/dist/core/update-check/check.js +35 -0
- package/dist/core/update-check/check.js.map +1 -1
- package/dist/core/work-digest/active-spans.d.ts +8 -0
- package/dist/core/work-digest/active-spans.js +29 -0
- package/dist/core/work-digest/active-spans.js.map +1 -0
- package/dist/core/work-digest/attribute.d.ts +15 -0
- package/dist/core/work-digest/attribute.js +76 -0
- package/dist/core/work-digest/attribute.js.map +1 -0
- package/dist/core/work-digest/build-work-digest.d.ts +12 -0
- package/dist/core/work-digest/build-work-digest.js +69 -0
- package/dist/core/work-digest/build-work-digest.js.map +1 -0
- package/dist/core/work-digest/compose-work-digest.d.ts +3 -0
- package/dist/core/work-digest/compose-work-digest.js +52 -0
- package/dist/core/work-digest/compose-work-digest.js.map +1 -0
- package/dist/core/work-digest/merge-active.d.ts +10 -0
- package/dist/core/work-digest/merge-active.js +22 -0
- package/dist/core/work-digest/merge-active.js.map +1 -0
- package/dist/core/work-digest/read-transcript-timestamps.d.ts +7 -0
- package/dist/core/work-digest/read-transcript-timestamps.js +40 -0
- package/dist/core/work-digest/read-transcript-timestamps.js.map +1 -0
- package/dist/core/work-digest/topics.d.ts +18 -0
- package/dist/core/work-digest/topics.js +26 -0
- package/dist/core/work-digest/topics.js.map +1 -0
- package/dist/core/work-digest/types.d.ts +45 -0
- package/dist/core/work-digest/types.js +2 -0
- package/dist/core/work-digest/types.js.map +1 -0
- package/dist/core/workstream/bind.d.ts +26 -0
- package/dist/core/workstream/bind.js +42 -0
- package/dist/core/workstream/bind.js.map +1 -0
- package/dist/core/workstream/compose-recall.d.ts +2 -0
- package/dist/core/workstream/compose-recall.js +39 -0
- package/dist/core/workstream/compose-recall.js.map +1 -0
- package/dist/core/workstream/merge-suggest.d.ts +19 -0
- package/dist/core/workstream/merge-suggest.js +61 -0
- package/dist/core/workstream/merge-suggest.js.map +1 -0
- package/dist/core/workstream/model.d.ts +21 -0
- package/dist/core/workstream/model.js +9 -0
- package/dist/core/workstream/model.js.map +1 -0
- package/dist/core/workstream/name-match.d.ts +8 -0
- package/dist/core/workstream/name-match.js +18 -0
- package/dist/core/workstream/name-match.js.map +1 -0
- package/dist/core/workstream/resolve.d.ts +10 -0
- package/dist/core/workstream/resolve.js +21 -0
- package/dist/core/workstream/resolve.js.map +1 -0
- package/dist/core/workstream/rollup.d.ts +12 -0
- package/dist/core/workstream/rollup.js +17 -0
- package/dist/core/workstream/rollup.js.map +1 -0
- package/dist/core/workstream/work-topics.d.ts +10 -0
- package/dist/core/workstream/work-topics.js +55 -0
- package/dist/core/workstream/work-topics.js.map +1 -0
- package/dist/hook/hook-helpers.d.ts +4 -0
- package/dist/hook/hook-helpers.js +36 -0
- package/dist/hook/hook-helpers.js.map +1 -0
- package/dist/hook/pre-compact-hook.d.ts +23 -0
- package/dist/hook/pre-compact-hook.js +67 -0
- package/dist/hook/pre-compact-hook.js.map +1 -0
- package/dist/hook/prompt-recall-hook.d.ts +38 -0
- package/dist/hook/prompt-recall-hook.js +124 -20
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-gate.d.ts +29 -0
- package/dist/hook/recall-gate.js +50 -0
- package/dist/hook/recall-gate.js.map +1 -0
- package/dist/hook/recall-over-http.d.ts +3 -2
- package/dist/hook/recall-over-http.js +26 -13
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/recent-context.d.ts +25 -0
- package/dist/hook/recent-context.js +104 -0
- package/dist/hook/recent-context.js.map +1 -0
- package/dist/hook/score-floor.d.ts +27 -0
- package/dist/hook/score-floor.js +42 -0
- package/dist/hook/score-floor.js.map +1 -0
- package/dist/hook/session-end-hook.js +8 -29
- package/dist/hook/session-end-hook.js.map +1 -1
- package/dist/hook/session-start-hook.js +26 -60
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +24 -60
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +6 -0
- package/dist/http/app.js +52 -44
- package/dist/http/app.js.map +1 -1
- package/dist/install/setup.js +2 -0
- package/dist/install/setup.js.map +1 -1
- package/dist/llm/build-classifier.d.ts +22 -0
- package/dist/llm/build-classifier.js +42 -0
- package/dist/llm/build-classifier.js.map +1 -0
- package/dist/llm/build-embedder.d.ts +11 -0
- package/dist/llm/build-embedder.js +42 -0
- package/dist/llm/build-embedder.js.map +1 -0
- package/dist/llm/bundled-embedder-client.d.ts +37 -0
- package/dist/llm/bundled-embedder-client.js +90 -0
- package/dist/llm/bundled-embedder-client.js.map +1 -0
- package/dist/llm/classifier-box.d.ts +13 -5
- package/dist/llm/classifier-box.js +28 -6
- package/dist/llm/classifier-box.js.map +1 -1
- package/dist/llm/classifier-egress.d.ts +18 -0
- package/dist/llm/classifier-egress.js +59 -0
- package/dist/llm/classifier-egress.js.map +1 -0
- package/dist/llm/client-shared.d.ts +4 -0
- package/dist/llm/client-shared.js +39 -0
- package/dist/llm/client-shared.js.map +1 -0
- package/dist/llm/deepseek-client.d.ts +20 -0
- package/dist/llm/deepseek-client.js +59 -45
- package/dist/llm/deepseek-client.js.map +1 -1
- package/dist/llm/embedder-info.d.ts +15 -0
- package/dist/llm/embedder-info.js +27 -0
- package/dist/llm/embedder-info.js.map +1 -0
- package/dist/llm/model-quirks.d.ts +4 -0
- package/dist/llm/model-quirks.js +7 -0
- package/dist/llm/model-quirks.js.map +1 -0
- package/dist/llm/naming.d.ts +5 -0
- package/dist/llm/naming.js +20 -0
- package/dist/llm/naming.js.map +1 -0
- package/dist/llm/ollama-client.d.ts +7 -8
- package/dist/llm/ollama-client.js +59 -51
- package/dist/llm/ollama-client.js.map +1 -1
- package/dist/llm/ollama-code-embedder.d.ts +8 -3
- package/dist/llm/ollama-code-embedder.js +14 -24
- package/dist/llm/ollama-code-embedder.js.map +1 -1
- package/dist/llm/openai-code-embedder-client.d.ts +25 -0
- package/dist/llm/openai-code-embedder-client.js +52 -0
- package/dist/llm/openai-code-embedder-client.js.map +1 -0
- package/dist/llm/openai-embedder-client.d.ts +41 -0
- package/dist/llm/openai-embedder-client.js +83 -0
- package/dist/llm/openai-embedder-client.js.map +1 -0
- package/dist/mcp/server.d.ts +69 -2
- package/dist/mcp/server.js +404 -19
- package/dist/mcp/server.js.map +1 -1
- package/dist/ports/code-embedder.d.ts +6 -1
- package/dist/ports/code-exemplar-store.d.ts +5 -0
- package/dist/ports/entity-store.d.ts +35 -0
- package/dist/ports/entity-store.js +7 -0
- package/dist/ports/entity-store.js.map +1 -0
- package/dist/ports/fact-store.d.ts +0 -0
- package/dist/ports/fact-store.js.map +1 -1
- package/dist/ports/llm-client.d.ts +9 -1
- package/dist/ports/outcome.d.ts +85 -0
- package/dist/ports/outcome.js +11 -0
- package/dist/ports/outcome.js.map +1 -0
- package/dist/ports/session-store.d.ts +12 -6
- package/dist/ports/storage.d.ts +7 -30
- package/dist/ports/storage.js +3 -7
- package/dist/ports/storage.js.map +1 -1
- package/dist/ports/transcript-adapter.d.ts +2 -0
- package/dist/ports/workstream-store.d.ts +22 -0
- package/dist/ports/workstream-store.js +2 -0
- package/dist/ports/workstream-store.js.map +1 -0
- package/dist/shared/net.d.ts +3 -0
- package/dist/shared/net.js +4 -0
- package/dist/shared/net.js.map +1 -0
- package/dist/shared/types.d.ts +56 -2
- package/dist/shared/types.js +4 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/ui/assets/{index-CMpQkbQy.js → index-CSaBtgXD.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/fixtures/classifier-gold/README.md +94 -0
- package/fixtures/classifier-gold/reference.json +318 -0
- package/fixtures/classifier-gold/transcripts/01-bug-fix-null-pointer-api.txt +75 -0
- package/fixtures/classifier-gold/transcripts/02-bug-fix-race-condition-queue.txt +77 -0
- package/fixtures/classifier-gold/transcripts/03-bug-fix-jwt-clock-skew.txt +86 -0
- package/fixtures/classifier-gold/transcripts/04-feature-webhook-retry.txt +95 -0
- package/fixtures/classifier-gold/transcripts/05-feature-csv-export.txt +86 -0
- package/fixtures/classifier-gold/transcripts/06-feature-rate-limiting.txt +61 -0
- package/fixtures/classifier-gold/transcripts/07-refactor-db-abstraction.txt +72 -0
- package/fixtures/classifier-gold/transcripts/08-refactor-config-loading.txt +89 -0
- package/fixtures/classifier-gold/transcripts/09-ops-docker-staging.txt +94 -0
- package/fixtures/classifier-gold/transcripts/10-ops-nginx-ssl.txt +121 -0
- package/fixtures/classifier-gold/transcripts/11-ops-postgres-migration.txt +74 -0
- package/fixtures/classifier-gold/transcripts/12-ops-cron-debugging.txt +73 -0
- package/fixtures/classifier-gold/transcripts/13-research-vector-db-comparison.txt +59 -0
- package/fixtures/classifier-gold/transcripts/14-research-oauth-provider.txt +74 -0
- package/fixtures/classifier-gold/transcripts/15-writing-api-docs.txt +154 -0
- package/fixtures/classifier-gold/transcripts/16-meeting-sprint-planning.txt +69 -0
- package/fixtures/classifier-gold/transcripts/17-trivial-list-files.txt +14 -0
- package/fixtures/classifier-gold/transcripts/18-trivial-version-check.txt +21 -0
- package/fixtures/classifier-gold/transcripts/19-trivial-syntax-help.txt +29 -0
- package/fixtures/classifier-gold/transcripts/20-trivial-read-package-json.txt +41 -0
- package/migrations/000_initial_schema.sql +1 -1
- package/migrations/024_backfill_exemplar_repo_basename.sql +32 -0
- package/migrations/025_workstreams.sql +30 -0
- package/migrations/026_embedding_config.sql +12 -0
- package/migrations/027_drop_legacy_session_embeddings.sql +7 -0
- package/migrations/028_classifier_provenance.sql +5 -0
- package/migrations/029_project_scope.sql +21 -0
- package/migrations/032_session_derivables.sql +11 -0
- package/migrations/pg/001_initial.sql +34 -0
- package/migrations/pg/019_split_replaces.sql +16 -7
- package/migrations/pg/025_workstreams.sql +34 -0
- package/migrations/pg/026_embedding_config.sql +12 -0
- package/migrations/pg/028_classifier_provenance.sql +5 -0
- package/migrations/pg/029_entity_variants.sql +9 -0
- package/migrations/pg/030_project_scope.sql +23 -0
- package/migrations/pg/031_widen_session_edges_kind.sql +11 -0
- package/migrations/pg/032_session_derivables.sql +17 -0
- package/nlm/index.js +405 -39
- package/package.json +12 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/scripts/prompt-recall-hook.mjs +413 -43
- package/plugin/scripts/session-start-hook.mjs +295 -61
- package/plugin/scripts/stop-hook.mjs +89 -66
- package/plugin-hermes-agent/__init__.py +2 -1
- package/templates/agent-contract/README.md +24 -0
- package/templates/agent-contract/claude-code.md +40 -0
- package/templates/agent-contract/generic.md +38 -0
- package/dist/core/embedding/embed-normalize.d.ts +0 -28
- package/dist/core/embedding/embed-normalize.js +0 -98
- package/dist/core/embedding/embed-normalize.js.map +0 -1
- package/dist/core/storage/pg-tx-context.d.ts +0 -52
- package/dist/core/storage/pg-tx-context.js +0 -149
- package/dist/core/storage/pg-tx-context.js.map +0 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const round1 = (n) => Math.round(n * 10) / 10;
|
|
2
|
+
const round2 = (n) => Math.round(n * 100) / 100;
|
|
3
|
+
function countIn(ts, iv) {
|
|
4
|
+
let n = 0;
|
|
5
|
+
for (const t of ts)
|
|
6
|
+
if (t >= iv.start && t <= iv.end)
|
|
7
|
+
n++;
|
|
8
|
+
return n;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Attribute each merged active interval to a topic and derive attention +
|
|
12
|
+
* focus. v1 uses dominant-session attribution: the whole interval goes to the
|
|
13
|
+
* session with the most messages in it (the bounded simplification over
|
|
14
|
+
* fractional splitting documented in the design). Focus is derived from the
|
|
15
|
+
* ordered, attributed segments: adjacent same-topic segments collapse into
|
|
16
|
+
* blocks; a topic change between blocks is one context switch.
|
|
17
|
+
*/
|
|
18
|
+
export function attribute(merged, sessions, opts) {
|
|
19
|
+
const segments = [];
|
|
20
|
+
for (const iv of merged) {
|
|
21
|
+
const minutes = (iv.end - iv.start) / 60_000;
|
|
22
|
+
let best;
|
|
23
|
+
let bestN = -1;
|
|
24
|
+
for (const s of sessions) {
|
|
25
|
+
const n = countIn(s.timestampsMs, iv);
|
|
26
|
+
if (n > bestN) {
|
|
27
|
+
bestN = n;
|
|
28
|
+
best = s;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
segments.push({ topic: best ? best.topic : "uncategorized", minutes, workstreamId: best?.workstreamId ?? null });
|
|
32
|
+
}
|
|
33
|
+
const totalMin = segments.reduce((t, s) => t + s.minutes, 0);
|
|
34
|
+
const byTopicMap = new Map();
|
|
35
|
+
for (const seg of segments)
|
|
36
|
+
byTopicMap.set(seg.topic, (byTopicMap.get(seg.topic) ?? 0) + seg.minutes);
|
|
37
|
+
const wsByTopic = new Map();
|
|
38
|
+
for (const seg of segments)
|
|
39
|
+
if (seg.workstreamId && !wsByTopic.has(seg.topic))
|
|
40
|
+
wsByTopic.set(seg.topic, seg.workstreamId);
|
|
41
|
+
const byTopic = [...byTopicMap.entries()]
|
|
42
|
+
.map(([topic, mins]) => {
|
|
43
|
+
const wsId = wsByTopic.get(topic);
|
|
44
|
+
return {
|
|
45
|
+
topic,
|
|
46
|
+
activeMinutes: round1(mins),
|
|
47
|
+
share: totalMin ? round2(mins / totalMin) : 0,
|
|
48
|
+
...(wsId ? { meta: { workstream_id: wsId } } : {}),
|
|
49
|
+
};
|
|
50
|
+
})
|
|
51
|
+
.sort((a, b) => b.activeMinutes - a.activeMinutes);
|
|
52
|
+
const blocks = [];
|
|
53
|
+
for (const seg of segments) {
|
|
54
|
+
const last = blocks[blocks.length - 1];
|
|
55
|
+
if (last && last.topic === seg.topic)
|
|
56
|
+
last.minutes += seg.minutes;
|
|
57
|
+
else
|
|
58
|
+
blocks.push({ topic: seg.topic, minutes: seg.minutes });
|
|
59
|
+
}
|
|
60
|
+
const contextSwitches = Math.max(0, blocks.length - 1);
|
|
61
|
+
const longestBlockMin = blocks.reduce((mx, b) => Math.max(mx, b.minutes), 0);
|
|
62
|
+
const deepMin = blocks
|
|
63
|
+
.filter((b) => b.minutes >= opts.deepBlockMin)
|
|
64
|
+
.reduce((t, b) => t + b.minutes, 0);
|
|
65
|
+
const deepWorkRatio = totalMin ? round2(deepMin / totalMin) : 0;
|
|
66
|
+
return {
|
|
67
|
+
byTopic,
|
|
68
|
+
focus: {
|
|
69
|
+
contextSwitches,
|
|
70
|
+
longestBlockMin: round1(longestBlockMin),
|
|
71
|
+
deepWorkRatio,
|
|
72
|
+
projectsTouched: byTopicMap.size,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=attribute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribute.js","sourceRoot":"","sources":["../../../src/core/work-digest/attribute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SessionStore } from "../../ports/session-store.js";
|
|
2
|
+
import { type TopicProvider } from "./topics.js";
|
|
3
|
+
import type { WorkDigest } from "./types.js";
|
|
4
|
+
export interface BuildWorkDigestDeps {
|
|
5
|
+
readonly store: Pick<SessionStore, "listByDateRange">;
|
|
6
|
+
readonly topicProvider?: TopicProvider;
|
|
7
|
+
readonly idleThresholdMin?: number;
|
|
8
|
+
readonly deepBlockMin?: number;
|
|
9
|
+
readonly readTimestamps?: (path: string, fromMs: number, toMs: number) => number[];
|
|
10
|
+
readonly workstreams?: Pick<import("../../ports/workstream-store.js").WorkstreamStore, "listAll">;
|
|
11
|
+
}
|
|
12
|
+
export declare function buildWorkDigest(deps: BuildWorkDigestDeps, date: string): Promise<WorkDigest>;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { activeSpans } from "./active-spans.js";
|
|
2
|
+
import { mergeIntervals } from "./merge-active.js";
|
|
3
|
+
import { attribute } from "./attribute.js";
|
|
4
|
+
import { readTranscriptTimestamps } from "./read-transcript-timestamps.js";
|
|
5
|
+
import { defaultTopicProvider, workstreamTopicProvider } from "./topics.js";
|
|
6
|
+
import { resolveWorkstreamId } from "../workstream/resolve.js";
|
|
7
|
+
const SCOPE_NOTE = "Agent-assisted active time. Excludes meetings and work without an agent.";
|
|
8
|
+
/** Local-midnight window for `date` (YYYY-MM-DD) in the process timezone. */
|
|
9
|
+
function dayWindow(date) {
|
|
10
|
+
const from = new Date(`${date}T00:00:00`);
|
|
11
|
+
const to = new Date(from);
|
|
12
|
+
to.setDate(to.getDate() + 1);
|
|
13
|
+
return { fromMs: from.getTime(), toMs: to.getTime(), fromIso: from.toISOString(), toIso: to.toISOString() };
|
|
14
|
+
}
|
|
15
|
+
export async function buildWorkDigest(deps, date) {
|
|
16
|
+
const idleThresholdMin = deps.idleThresholdMin ?? 5;
|
|
17
|
+
const deepBlockMin = deps.deepBlockMin ?? 25;
|
|
18
|
+
const topicProvider = deps.topicProvider ?? defaultTopicProvider;
|
|
19
|
+
const readTs = deps.readTimestamps ?? readTranscriptTimestamps;
|
|
20
|
+
const provider = deps.workstreams ? workstreamTopicProvider(topicProvider) : topicProvider;
|
|
21
|
+
const wsList = deps.workstreams ? await deps.workstreams.listAll() : [];
|
|
22
|
+
const wsById = new Map(wsList.map((w) => [w.id, { id: w.id, mergedInto: w.mergedInto }]));
|
|
23
|
+
const wsLabel = new Map(wsList.map((w) => [w.id, w.label]));
|
|
24
|
+
function resolveWs(id) {
|
|
25
|
+
if (!id)
|
|
26
|
+
return null;
|
|
27
|
+
const live = resolveWorkstreamId(id, wsById);
|
|
28
|
+
const label = wsLabel.get(live);
|
|
29
|
+
return label ? { id: live, label } : null;
|
|
30
|
+
}
|
|
31
|
+
const { fromMs, toMs, fromIso, toIso } = dayWindow(date);
|
|
32
|
+
const sessions = await deps.store.listByDateRange(fromIso, toIso);
|
|
33
|
+
const activities = [];
|
|
34
|
+
const allSpans = [];
|
|
35
|
+
const decisions = new Set();
|
|
36
|
+
const openLoops = new Set();
|
|
37
|
+
let measured = 0;
|
|
38
|
+
let skipped = 0;
|
|
39
|
+
for (const s of sessions) {
|
|
40
|
+
for (const d of s.decisions)
|
|
41
|
+
decisions.add(d);
|
|
42
|
+
for (const o of s.open)
|
|
43
|
+
openLoops.add(o);
|
|
44
|
+
const timestampsMs = s.transcriptPath ? readTs(s.transcriptPath, fromMs, toMs) : [];
|
|
45
|
+
if (timestampsMs.length === 0) {
|
|
46
|
+
skipped++;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
measured++;
|
|
50
|
+
const ws = resolveWs(s.workstreamId);
|
|
51
|
+
const topic = provider({ entities: s.entities, label: s.label, ...(ws ? { workstreamLabel: ws.label } : {}) });
|
|
52
|
+
activities.push({ sessionId: s.id, topic, timestampsMs, ...(ws ? { workstreamId: ws.id } : {}) });
|
|
53
|
+
for (const span of activeSpans(timestampsMs, idleThresholdMin))
|
|
54
|
+
allSpans.push(span);
|
|
55
|
+
}
|
|
56
|
+
const { merged, totalMinutes } = mergeIntervals(allSpans);
|
|
57
|
+
const { byTopic, focus } = attribute(merged, activities, { deepBlockMin });
|
|
58
|
+
return {
|
|
59
|
+
date,
|
|
60
|
+
idleThresholdMin,
|
|
61
|
+
scopeNote: SCOPE_NOTE,
|
|
62
|
+
coverage: { sessions: sessions.length, activeTimeMeasured: measured, activeTimeSkipped: skipped },
|
|
63
|
+
activeMinutes: Math.round(totalMinutes * 10) / 10,
|
|
64
|
+
byTopic,
|
|
65
|
+
focus,
|
|
66
|
+
progress: { decisions: [...decisions], openLoops: [...openLoops] },
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=build-work-digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-work-digest.js","sourceRoot":"","sources":["../../../src/core/work-digest/build-work-digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const PROGRESS_CAP = 8;
|
|
2
|
+
function hours(min) {
|
|
3
|
+
return (min / 60).toFixed(1) + "h";
|
|
4
|
+
}
|
|
5
|
+
function renderProgressList(items, emptyLine, label) {
|
|
6
|
+
const len = items.length;
|
|
7
|
+
if (len === 0) {
|
|
8
|
+
return [emptyLine];
|
|
9
|
+
}
|
|
10
|
+
if (len <= PROGRESS_CAP) {
|
|
11
|
+
return [` ${label} (${len}):`, ...items.map((item) => ` - ${item}`)];
|
|
12
|
+
}
|
|
13
|
+
const tail = items.slice(len - PROGRESS_CAP);
|
|
14
|
+
const overflow = len - PROGRESS_CAP;
|
|
15
|
+
return [
|
|
16
|
+
` ${label}: ${len} (showing last ${PROGRESS_CAP})`,
|
|
17
|
+
...tail.map((item) => ` - ${item}`),
|
|
18
|
+
` ... (+${overflow} more)`,
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
/** Render a WorkDigest as the shared operator-facing text. No em dashes. */
|
|
22
|
+
export function composeWorkDigest(d) {
|
|
23
|
+
const lines = [];
|
|
24
|
+
lines.push(`DAILY WORK RECAP - ${d.date}`);
|
|
25
|
+
lines.push(`(${d.scopeNote})`);
|
|
26
|
+
lines.push("");
|
|
27
|
+
if (d.activeMinutes <= 0) {
|
|
28
|
+
lines.push("no agent-assisted work recorded for this day.");
|
|
29
|
+
return lines.join("\n");
|
|
30
|
+
}
|
|
31
|
+
const skipped = d.coverage.activeTimeSkipped > 0
|
|
32
|
+
? ` (${d.coverage.activeTimeSkipped} session(s): active-time not measured)`
|
|
33
|
+
: "";
|
|
34
|
+
lines.push(`~${hours(d.activeMinutes)} active across ${d.coverage.sessions} sessions, ${d.focus.projectsTouched} projects${skipped}`);
|
|
35
|
+
lines.push("");
|
|
36
|
+
lines.push("ATTENTION");
|
|
37
|
+
for (const t of d.byTopic) {
|
|
38
|
+
const pct = Math.round(t.share * 100) + "%";
|
|
39
|
+
lines.push(` ${t.topic}: ${pct} (${hours(t.activeMinutes)})`);
|
|
40
|
+
}
|
|
41
|
+
lines.push("");
|
|
42
|
+
lines.push("FOCUS");
|
|
43
|
+
lines.push(` longest block: ${Math.round(d.focus.longestBlockMin)} min ` +
|
|
44
|
+
`context switches: ${d.focus.contextSwitches} ` +
|
|
45
|
+
`deep-work: ${Math.round(d.focus.deepWorkRatio * 100)}%`);
|
|
46
|
+
lines.push("");
|
|
47
|
+
lines.push("PROGRESS");
|
|
48
|
+
lines.push(...renderProgressList(d.progress.decisions, " decided: none recorded", "decided"));
|
|
49
|
+
lines.push(...renderProgressList(d.progress.openLoops, " open loops: none", "open loops"));
|
|
50
|
+
return lines.join("\n");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=compose-work-digest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-work-digest.js","sourceRoot":"","sources":["../../../src/core/work-digest/compose-work-digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Interval } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Union overlapping/touching activity intervals into a single wall-clock
|
|
4
|
+
* timeline so concurrently-supervised agents are not double-counted, and
|
|
5
|
+
* report the total active minutes of that timeline.
|
|
6
|
+
*/
|
|
7
|
+
export declare function mergeIntervals(intervals: ReadonlyArray<Interval>): {
|
|
8
|
+
merged: Interval[];
|
|
9
|
+
totalMinutes: number;
|
|
10
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Union overlapping/touching activity intervals into a single wall-clock
|
|
3
|
+
* timeline so concurrently-supervised agents are not double-counted, and
|
|
4
|
+
* report the total active minutes of that timeline.
|
|
5
|
+
*/
|
|
6
|
+
export function mergeIntervals(intervals) {
|
|
7
|
+
const sorted = [...intervals].sort((a, b) => a.start - b.start);
|
|
8
|
+
const merged = [];
|
|
9
|
+
for (const iv of sorted) {
|
|
10
|
+
const last = merged[merged.length - 1];
|
|
11
|
+
if (last && iv.start <= last.end) {
|
|
12
|
+
if (iv.end > last.end)
|
|
13
|
+
merged[merged.length - 1] = { start: last.start, end: iv.end };
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
merged.push({ start: iv.start, end: iv.end });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const totalMinutes = merged.reduce((t, iv) => t + (iv.end - iv.start) / 60_000, 0);
|
|
20
|
+
return { merged, totalMinutes };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=merge-active.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-active.js","sourceRoot":"","sources":["../../../src/core/work-digest/merge-active.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAkC;IAElC,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;IAChE,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,IAAI,IAAI,EAAE,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACjC,IAAI,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC;QACxF,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;IACnF,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract message timestamps (epoch ms) from a transcript JSONL file, keeping
|
|
3
|
+
* only those within [fromMs, toMs). Best-effort: a missing/unreadable file or
|
|
4
|
+
* an unparseable line yields no timestamps rather than throwing. Accepts the
|
|
5
|
+
* common timestamp fields across runtimes (claude-code/pi use `timestamp`).
|
|
6
|
+
*/
|
|
7
|
+
export declare function readTranscriptTimestamps(path: string, fromMs: number, toMs: number): number[];
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
/**
|
|
3
|
+
* Extract message timestamps (epoch ms) from a transcript JSONL file, keeping
|
|
4
|
+
* only those within [fromMs, toMs). Best-effort: a missing/unreadable file or
|
|
5
|
+
* an unparseable line yields no timestamps rather than throwing. Accepts the
|
|
6
|
+
* common timestamp fields across runtimes (claude-code/pi use `timestamp`).
|
|
7
|
+
*/
|
|
8
|
+
export function readTranscriptTimestamps(path, fromMs, toMs) {
|
|
9
|
+
let raw;
|
|
10
|
+
try {
|
|
11
|
+
raw = readFileSync(path, "utf8");
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
const out = [];
|
|
17
|
+
for (const line of raw.split("\n")) {
|
|
18
|
+
const trimmed = line.trim();
|
|
19
|
+
if (!trimmed)
|
|
20
|
+
continue;
|
|
21
|
+
let obj;
|
|
22
|
+
try {
|
|
23
|
+
obj = JSON.parse(trimmed);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const tsRaw = obj["timestamp"] ?? obj["ts"] ?? obj["created_at"];
|
|
29
|
+
if (typeof tsRaw !== "string")
|
|
30
|
+
continue;
|
|
31
|
+
const ms = Date.parse(tsRaw);
|
|
32
|
+
if (!Number.isFinite(ms))
|
|
33
|
+
continue;
|
|
34
|
+
if (ms >= fromMs && ms < toMs)
|
|
35
|
+
out.push(ms);
|
|
36
|
+
}
|
|
37
|
+
out.sort((a, b) => a - b);
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=read-transcript-timestamps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-transcript-timestamps.js","sourceRoot":"","sources":["../../../src/core/work-digest/read-transcript-timestamps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAY,EAAE,MAAc,EAAE,IAAY;IACjF,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,GAA4B,CAAC;QACjC,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC;QACjE,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,SAAS;QACxC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,SAAS;QACnC,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,GAAG,IAAI;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** The minimal session view a topic provider sees. Extensions (e.g. NLOS) can
|
|
2
|
+
* key on entities and/or label to impose their own taxonomy. */
|
|
3
|
+
export interface TopicInput {
|
|
4
|
+
readonly entities: ReadonlyArray<string>;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
/** Resolved live-workstream label, when the session is bound. Takes precedence over entity/alias topics. */
|
|
7
|
+
readonly workstreamLabel?: string;
|
|
8
|
+
}
|
|
9
|
+
export type TopicProvider = (input: TopicInput) => string;
|
|
10
|
+
/** NLM-core default: the session's first classified entity, normalized. */
|
|
11
|
+
export declare const defaultTopicProvider: TopicProvider;
|
|
12
|
+
/** NLM-core: prefer the bound workstream's label; fall through to `fallback`
|
|
13
|
+
* (alias-map / first-entity) for unbound sessions. Retires the
|
|
14
|
+
* alphabetically-first-entity dependency for bound sessions (spec §10). */
|
|
15
|
+
export declare function workstreamTopicProvider(fallback: TopicProvider): TopicProvider;
|
|
16
|
+
/** NLM-core optional: group entities into labels via an operator-supplied map.
|
|
17
|
+
* The same interface an extension uses to supply a function/taxonomy map. */
|
|
18
|
+
export declare function aliasTopicProvider(map: Record<string, string>): TopicProvider;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function normalize(s) {
|
|
2
|
+
return s.trim().toLowerCase();
|
|
3
|
+
}
|
|
4
|
+
/** NLM-core default: the session's first classified entity, normalized. */
|
|
5
|
+
export const defaultTopicProvider = (input) => {
|
|
6
|
+
const first = input.entities[0];
|
|
7
|
+
return first && first.trim() ? normalize(first) : "uncategorized";
|
|
8
|
+
};
|
|
9
|
+
/** NLM-core: prefer the bound workstream's label; fall through to `fallback`
|
|
10
|
+
* (alias-map / first-entity) for unbound sessions. Retires the
|
|
11
|
+
* alphabetically-first-entity dependency for bound sessions (spec §10). */
|
|
12
|
+
export function workstreamTopicProvider(fallback) {
|
|
13
|
+
return (input) => input.workstreamLabel && input.workstreamLabel.trim() ? input.workstreamLabel : fallback(input);
|
|
14
|
+
}
|
|
15
|
+
/** NLM-core optional: group entities into labels via an operator-supplied map.
|
|
16
|
+
* The same interface an extension uses to supply a function/taxonomy map. */
|
|
17
|
+
export function aliasTopicProvider(map) {
|
|
18
|
+
const norm = {};
|
|
19
|
+
for (const [k, v] of Object.entries(map))
|
|
20
|
+
norm[normalize(k)] = v;
|
|
21
|
+
return (input) => {
|
|
22
|
+
const base = defaultTopicProvider(input);
|
|
23
|
+
return norm[base] ?? base;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=topics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topics.js","sourceRoot":"","sources":["../../../src/core/work-digest/topics.ts"],"names":[],"mappings":"AAWA,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAChC,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,oBAAoB,GAAkB,CAAC,KAAK,EAAE,EAAE;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAChC,OAAO,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC;AACpE,CAAC,CAAC;AAEF;;4EAE4E;AAC5E,MAAM,UAAU,uBAAuB,CAAC,QAAuB;IAC7D,OAAO,CAAC,KAAK,EAAE,EAAE,CACf,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpG,CAAC;AAED;8EAC8E;AAC9E,MAAM,UAAU,kBAAkB,CAAC,GAA2B;IAC5D,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAC5B,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** A half-open-ish activity interval in epoch milliseconds (end >= start). */
|
|
2
|
+
export interface Interval {
|
|
3
|
+
readonly start: number;
|
|
4
|
+
readonly end: number;
|
|
5
|
+
}
|
|
6
|
+
/** One session's in-day message timestamps plus its resolved topic. */
|
|
7
|
+
export interface SessionActivity {
|
|
8
|
+
readonly sessionId: string;
|
|
9
|
+
readonly topic: string;
|
|
10
|
+
readonly timestampsMs: ReadonlyArray<number>;
|
|
11
|
+
readonly workstreamId?: string | null;
|
|
12
|
+
}
|
|
13
|
+
/** Attention: active minutes attributed to one topic. `meta` is an opaque
|
|
14
|
+
* extension seam (Section 7.1 of the design) — NLM core never reads it. */
|
|
15
|
+
export interface TopicShare {
|
|
16
|
+
readonly topic: string;
|
|
17
|
+
readonly activeMinutes: number;
|
|
18
|
+
readonly share: number;
|
|
19
|
+
readonly meta?: Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
export interface FocusStats {
|
|
22
|
+
readonly contextSwitches: number;
|
|
23
|
+
readonly longestBlockMin: number;
|
|
24
|
+
readonly deepWorkRatio: number;
|
|
25
|
+
readonly projectsTouched: number;
|
|
26
|
+
}
|
|
27
|
+
export interface ProgressStats {
|
|
28
|
+
readonly decisions: ReadonlyArray<string>;
|
|
29
|
+
readonly openLoops: ReadonlyArray<string>;
|
|
30
|
+
}
|
|
31
|
+
export interface Coverage {
|
|
32
|
+
readonly sessions: number;
|
|
33
|
+
readonly activeTimeMeasured: number;
|
|
34
|
+
readonly activeTimeSkipped: number;
|
|
35
|
+
}
|
|
36
|
+
export interface WorkDigest {
|
|
37
|
+
readonly date: string;
|
|
38
|
+
readonly idleThresholdMin: number;
|
|
39
|
+
readonly scopeNote: string;
|
|
40
|
+
readonly coverage: Coverage;
|
|
41
|
+
readonly activeMinutes: number;
|
|
42
|
+
readonly byTopic: ReadonlyArray<TopicShare>;
|
|
43
|
+
readonly focus: FocusStats;
|
|
44
|
+
readonly progress: ProgressStats;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/work-digest/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { WorkstreamStore } from "../../ports/workstream-store.js";
|
|
2
|
+
import type { SessionStore } from "../../ports/session-store.js";
|
|
3
|
+
import type { LLMClient } from "../../ports/llm-client.js";
|
|
4
|
+
import type { BindingSource } from "./model.js";
|
|
5
|
+
export declare const NAMING_CONTENT_CHARS = 8000;
|
|
6
|
+
export interface BindDeps {
|
|
7
|
+
readonly namer: Pick<LLMClient, "nameWorkstream">;
|
|
8
|
+
readonly workstreams: Pick<WorkstreamStore, "listAll" | "create" | "upsertEntities" | "touchLastSession">;
|
|
9
|
+
readonly sessions: Pick<SessionStore, "setWorkstreamBinding">;
|
|
10
|
+
readonly aliasToLabel: ReadonlyMap<string, string>;
|
|
11
|
+
readonly log?: (msg: string) => void;
|
|
12
|
+
readonly source?: BindingSource;
|
|
13
|
+
}
|
|
14
|
+
export interface BindInput {
|
|
15
|
+
readonly sessionId: string;
|
|
16
|
+
readonly label: string;
|
|
17
|
+
readonly summary: string;
|
|
18
|
+
readonly body?: string;
|
|
19
|
+
readonly entities: ReadonlyArray<string>;
|
|
20
|
+
readonly startedAt: string;
|
|
21
|
+
readonly scope: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface BindResult {
|
|
24
|
+
readonly workstreamId: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function bindSessionToWorkstream(deps: BindDeps, input: BindInput): Promise<BindResult | null>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { makeWorkstreamId } from "./model.js";
|
|
2
|
+
import { decideWorkstreamByName } from "./name-match.js";
|
|
3
|
+
import { scopeStampEnabled } from "../scope/stamp-flag.js";
|
|
4
|
+
export const NAMING_CONTENT_CHARS = 8000;
|
|
5
|
+
function scopeMatches(wsScope, sessionScope) {
|
|
6
|
+
return wsScope === sessionScope;
|
|
7
|
+
}
|
|
8
|
+
async function applyBinding(deps, input, workstreamId) {
|
|
9
|
+
await deps.sessions.setWorkstreamBinding(input.sessionId, workstreamId, deps.source ?? "classifier", null);
|
|
10
|
+
await deps.workstreams.upsertEntities(workstreamId, input.entities);
|
|
11
|
+
await deps.workstreams.touchLastSession(workstreamId, input.startedAt);
|
|
12
|
+
return { workstreamId };
|
|
13
|
+
}
|
|
14
|
+
export async function bindSessionToWorkstream(deps, input) {
|
|
15
|
+
try {
|
|
16
|
+
const all = await deps.workstreams.listAll();
|
|
17
|
+
const content = `${input.label}\n${(input.body || input.summary).slice(0, NAMING_CONTENT_CHARS)}`;
|
|
18
|
+
if (scopeStampEnabled()) {
|
|
19
|
+
const scoped = all.filter((w) => scopeMatches(w.scope, input.scope));
|
|
20
|
+
const named = await deps.namer.nameWorkstream(content, scoped.map((w) => ({ label: w.label })));
|
|
21
|
+
const decision = decideWorkstreamByName(named, scoped, deps.aliasToLabel);
|
|
22
|
+
if (decision.kind === "bind") {
|
|
23
|
+
return applyBinding(deps, input, decision.workstreamId);
|
|
24
|
+
}
|
|
25
|
+
if (named && named.trim()) {
|
|
26
|
+
const ws = await deps.workstreams.create({ id: makeWorkstreamId(), label: named.trim(), scope: input.scope });
|
|
27
|
+
return applyBinding(deps, input, ws.id);
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const named = await deps.namer.nameWorkstream(content, all.map((w) => ({ label: w.label })));
|
|
32
|
+
const decision = decideWorkstreamByName(named, all, deps.aliasToLabel);
|
|
33
|
+
if (decision.kind === "abstain")
|
|
34
|
+
return null;
|
|
35
|
+
return applyBinding(deps, input, decision.workstreamId);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
deps.log?.(`[workstream] bind failed for ${input.sessionId}: ${e instanceof Error ? e.message : String(e)}`);
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=bind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../../../src/core/workstream/bind.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export function composeWorkstreamRecall(view) {
|
|
2
|
+
const { workstream, sessionIds, facts, exemplars } = view;
|
|
3
|
+
const lines = [];
|
|
4
|
+
lines.push(`WORKSTREAM: ${workstream.label}`);
|
|
5
|
+
lines.push(`(${sessionIds.length} sessions${workstream.lastSessionAt ? `, last active ${workstream.lastSessionAt.slice(0, 10)}` : ""})`);
|
|
6
|
+
lines.push("");
|
|
7
|
+
const decisions = facts.filter((f) => f.kind === "decision");
|
|
8
|
+
const open = facts.filter((f) => f.kind === "open");
|
|
9
|
+
const attrs = facts.filter((f) => f.kind === "attribute");
|
|
10
|
+
if (decisions.length) {
|
|
11
|
+
lines.push("DECISIONS:");
|
|
12
|
+
for (const f of decisions)
|
|
13
|
+
lines.push(` - ${f.value}`);
|
|
14
|
+
lines.push("");
|
|
15
|
+
}
|
|
16
|
+
if (open.length) {
|
|
17
|
+
lines.push("OPEN LOOPS:");
|
|
18
|
+
for (const f of open)
|
|
19
|
+
lines.push(` - ${f.value}`);
|
|
20
|
+
lines.push("");
|
|
21
|
+
}
|
|
22
|
+
if (attrs.length) {
|
|
23
|
+
lines.push("FACTS:");
|
|
24
|
+
for (const f of attrs)
|
|
25
|
+
lines.push(` - ${f.subject} ${f.predicate} ${f.value}`);
|
|
26
|
+
lines.push("");
|
|
27
|
+
}
|
|
28
|
+
if (exemplars.length) {
|
|
29
|
+
lines.push("CODE EXEMPLARS:");
|
|
30
|
+
for (const e of exemplars)
|
|
31
|
+
lines.push(` - [${e.outcome}] ${e.repo}: ${e.taskContext}`);
|
|
32
|
+
lines.push("");
|
|
33
|
+
}
|
|
34
|
+
if (!decisions.length && !open.length && !attrs.length && !exemplars.length) {
|
|
35
|
+
lines.push("(no accumulated facts or exemplars yet)");
|
|
36
|
+
}
|
|
37
|
+
return lines.join("\n").trimEnd();
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=compose-recall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-recall.js","sourceRoot":"","sources":["../../../src/core/workstream/compose-recall.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,uBAAuB,CAAC,IAAsB;IAC5D,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,eAAe,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,YAAY,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,iBAAiB,UAAU,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACzI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAE1D,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;QAChF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC9B,KAAK,MAAM,CAAC,IAAI,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACxF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QAC5E,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface MergeSuggestInputItem {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly label: string;
|
|
4
|
+
readonly entities: ReadonlyArray<string>;
|
|
5
|
+
readonly sessionIds: ReadonlyArray<string>;
|
|
6
|
+
}
|
|
7
|
+
export interface MergeSuggestion {
|
|
8
|
+
readonly aId: string;
|
|
9
|
+
readonly aLabel: string;
|
|
10
|
+
readonly bId: string;
|
|
11
|
+
readonly bLabel: string;
|
|
12
|
+
readonly score: number;
|
|
13
|
+
readonly sharedEntities: number;
|
|
14
|
+
readonly sharedSessions: number;
|
|
15
|
+
readonly labelSimilarity: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function scoreMergePair(a: MergeSuggestInputItem, b: MergeSuggestInputItem): MergeSuggestion;
|
|
18
|
+
/** All unordered pairs scoring >= minScore, ranked desc. Pure; O(n^2) over the (small) workstream set. */
|
|
19
|
+
export declare function suggestMerges(items: ReadonlyArray<MergeSuggestInputItem>, minScore: number): ReadonlyArray<MergeSuggestion>;
|