@remnic/core 9.19.0 → 9.20.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/dist/access-admin-ops-surface.d.ts +8 -8
- package/dist/access-admin-ops-surface.js +8 -8
- package/dist/access-boundary.d.ts +8 -8
- package/dist/access-boundary.js +8 -8
- package/dist/access-cli.js +32 -32
- package/dist/access-http.d.ts +8 -8
- package/dist/access-http.js +12 -12
- package/dist/access-identity-continuity-surface.d.ts +6 -6
- package/dist/access-identity-continuity-surface.js +8 -8
- package/dist/access-lcm-surface.d.ts +8 -8
- package/dist/access-lcm-surface.js +8 -8
- package/dist/access-mcp.d.ts +8 -8
- package/dist/access-mcp.js +11 -11
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-BsawJa-L.d.ts → access-namespace-preflight-tmwQgCT6.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +8 -8
- package/dist/access-observe-write-surface.d.ts +8 -8
- package/dist/access-observe-write-surface.js +8 -8
- package/dist/access-operations-batch.js +9 -9
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +10 -10
- package/dist/access-recall-concurrency.d.ts +8 -8
- package/dist/access-recall-concurrency.js +8 -8
- package/dist/access-recall-response.d.ts +8 -8
- package/dist/access-recall-response.js +8 -8
- package/dist/access-recall-surface.d.ts +8 -8
- package/dist/access-recall-surface.js +8 -8
- package/dist/{access-service-DLuVnV6a.d.ts → access-service-BqUii7LY.d.ts} +6 -6
- package/dist/access-service.d.ts +8 -8
- package/dist/access-service.js +8 -8
- package/dist/access-surface-catalog.d.ts +8 -8
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/{auto-sync-IH3G25MT.js → auto-sync-UPTUVE4X.js} +3 -3
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +6 -6
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +4 -4
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-O6P8694A.d.ts → catalog-iWvWz61I.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +5 -5
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-YUWFASAK.js → chunk-275ENJDK.js} +2 -2
- package/dist/{chunk-EZFVVEQG.js → chunk-3ZUY2VQF.js} +2 -2
- package/dist/{chunk-HRREDJSL.js → chunk-4F6AANKS.js} +3 -3
- package/dist/{chunk-U7D5HWNG.js → chunk-4PYLBXX6.js} +2 -2
- package/dist/{chunk-3LZSS77C.js → chunk-53WDAG7X.js} +2 -2
- package/dist/{chunk-QEEMLGCO.js → chunk-5IXPWEQB.js} +5 -5
- package/dist/{chunk-VSVX777Y.js → chunk-5JQLAQUZ.js} +2 -2
- package/dist/{chunk-DR65EEXG.js → chunk-62QM5MKY.js} +7 -7
- package/dist/{chunk-WYL5ODHJ.js → chunk-6NZ7U4R4.js} +1 -1
- package/dist/chunk-6NZ7U4R4.js.map +1 -0
- package/dist/{chunk-OFQUY5NZ.js → chunk-7M6APKJL.js} +331 -5
- package/dist/chunk-7M6APKJL.js.map +1 -0
- package/dist/{chunk-OOJQ6ID5.js → chunk-AT3TDN6O.js} +1017 -296
- package/dist/chunk-AT3TDN6O.js.map +1 -0
- package/dist/{chunk-DQCUBRTZ.js → chunk-B7C3TF5H.js} +2 -2
- package/dist/{chunk-RPOOJPMB.js → chunk-EILX7SQR.js} +3 -3
- package/dist/{chunk-D5H3B36B.js → chunk-EXU5IQ3S.js} +2 -2
- package/dist/{chunk-KUF7OIFK.js → chunk-EZKKHVFY.js} +2 -2
- package/dist/{chunk-S5HCKQ7Q.js → chunk-GEUDRENF.js} +2 -2
- package/dist/{chunk-X7GOH7Y6.js → chunk-HJEEAO4O.js} +2 -2
- package/dist/{chunk-FL7MNSH3.js → chunk-HPOY2PHQ.js} +3 -3
- package/dist/{chunk-Q55XM4SU.js → chunk-JFDEYXF7.js} +2 -2
- package/dist/{chunk-UVSDFM7R.js → chunk-JN3IUA2Q.js} +2 -2
- package/dist/{chunk-PLRDZ2OO.js → chunk-JWMYVQAM.js} +2 -2
- package/dist/{chunk-KOFVOVJG.js → chunk-KHRKEELC.js} +17 -17
- package/dist/{chunk-Y4JHE2ML.js → chunk-LI4ZOFHW.js} +2 -2
- package/dist/{chunk-MLW3J7IC.js → chunk-LMHDFOVV.js} +3 -3
- package/dist/{chunk-X6E5WAGX.js → chunk-N7EVMKP6.js} +6 -6
- package/dist/{chunk-HCNG42P3.js → chunk-Q3FWRDCP.js} +2 -2
- package/dist/{chunk-5MFHOX5T.js → chunk-QO2KODU6.js} +2 -2
- package/dist/{chunk-W3DJOT22.js → chunk-TCZWBJBO.js} +2 -2
- package/dist/{chunk-B3ABVQ36.js → chunk-UHVXE24Y.js} +2 -1
- package/dist/{chunk-UX3ZXN34.js → chunk-UV72DEZD.js} +2 -2
- package/dist/{chunk-OZSL2QZC.js → chunk-V5TSUGRB.js} +5 -5
- package/dist/{chunk-CH3BRJ3P.js → chunk-X5QS5C2O.js} +2 -2
- package/dist/{cli-0dQHR6e6.d.ts → cli-DPEhq0Cp.d.ts} +5 -5
- package/dist/cli.d.ts +10 -10
- package/dist/cli.js +25 -25
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +4 -4
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +4 -4
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +4 -4
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +4 -4
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +6 -6
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +468 -88
- package/dist/index.js +66 -36
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +4 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +5 -5
- package/dist/mcp-memory-inspector-app.d.ts +8 -8
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +5 -5
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +4 -4
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +2 -2
- package/dist/operator-toolkit.js +9 -9
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +3 -3
- package/dist/orchestration/maintenance.js +9 -9
- package/dist/{orchestrator-B8ickLkd.d.ts → orchestrator-DB93S48I.d.ts} +5 -5
- package/dist/orchestrator.d.ts +6 -6
- package/dist/orchestrator.js +32 -32
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-B669unGm.d.ts → pipeline-DmGc-H66.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{qmd-D0PVXmea.d.ts → qmd-cJT0crkF.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/{scope-profiles-BOp3gSzp.d.ts → scope-profiles-KG2nODX7.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-C7SZNzUJ.d.ts → semantic-consolidation-BaZlg0D8.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +5 -5
- package/dist/semantic-rule-promotion.js +4 -4
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +4 -4
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/{storage-CJ_Fia4H.d.ts → storage-BKhHHnRo.d.ts} +2 -221
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +3 -3
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-GeWGXq9E.d.ts → types-GBQZuT7l.d.ts} +395 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +4 -4
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/config.ts +3 -3
- package/src/meetings/build.test.ts +646 -0
- package/src/meetings/build.ts +365 -0
- package/src/meetings/cli.test.ts +276 -0
- package/src/meetings/cli.ts +242 -0
- package/src/meetings/config.test.ts +72 -0
- package/src/meetings/config.ts +183 -0
- package/src/meetings/errors.ts +13 -0
- package/src/meetings/fuse.test.ts +208 -0
- package/src/meetings/fuse.ts +297 -0
- package/src/meetings/index.ts +11 -1
- package/src/meetings/memory-generator.ts +116 -0
- package/src/meetings/recall-exclusion.test.ts +88 -0
- package/src/meetings/store.test.ts +232 -0
- package/src/meetings/store.ts +465 -0
- package/src/meetings/types.ts +111 -0
- package/src/orchestration/orchestrator-helpers.ts +23 -3
- package/src/orchestration/recall-search-pipeline.test.ts +182 -0
- package/src/orchestration/recall-search-pipeline.ts +36 -15
- package/src/types.ts +6 -0
- package/dist/chunk-OFQUY5NZ.js.map +0 -1
- package/dist/chunk-OOJQ6ID5.js.map +0 -1
- package/dist/chunk-WYL5ODHJ.js.map +0 -1
- /package/dist/{auto-sync-IH3G25MT.js.map → auto-sync-UPTUVE4X.js.map} +0 -0
- /package/dist/{chunk-YUWFASAK.js.map → chunk-275ENJDK.js.map} +0 -0
- /package/dist/{chunk-EZFVVEQG.js.map → chunk-3ZUY2VQF.js.map} +0 -0
- /package/dist/{chunk-HRREDJSL.js.map → chunk-4F6AANKS.js.map} +0 -0
- /package/dist/{chunk-U7D5HWNG.js.map → chunk-4PYLBXX6.js.map} +0 -0
- /package/dist/{chunk-3LZSS77C.js.map → chunk-53WDAG7X.js.map} +0 -0
- /package/dist/{chunk-QEEMLGCO.js.map → chunk-5IXPWEQB.js.map} +0 -0
- /package/dist/{chunk-VSVX777Y.js.map → chunk-5JQLAQUZ.js.map} +0 -0
- /package/dist/{chunk-DR65EEXG.js.map → chunk-62QM5MKY.js.map} +0 -0
- /package/dist/{chunk-DQCUBRTZ.js.map → chunk-B7C3TF5H.js.map} +0 -0
- /package/dist/{chunk-RPOOJPMB.js.map → chunk-EILX7SQR.js.map} +0 -0
- /package/dist/{chunk-D5H3B36B.js.map → chunk-EXU5IQ3S.js.map} +0 -0
- /package/dist/{chunk-KUF7OIFK.js.map → chunk-EZKKHVFY.js.map} +0 -0
- /package/dist/{chunk-S5HCKQ7Q.js.map → chunk-GEUDRENF.js.map} +0 -0
- /package/dist/{chunk-X7GOH7Y6.js.map → chunk-HJEEAO4O.js.map} +0 -0
- /package/dist/{chunk-FL7MNSH3.js.map → chunk-HPOY2PHQ.js.map} +0 -0
- /package/dist/{chunk-Q55XM4SU.js.map → chunk-JFDEYXF7.js.map} +0 -0
- /package/dist/{chunk-UVSDFM7R.js.map → chunk-JN3IUA2Q.js.map} +0 -0
- /package/dist/{chunk-PLRDZ2OO.js.map → chunk-JWMYVQAM.js.map} +0 -0
- /package/dist/{chunk-KOFVOVJG.js.map → chunk-KHRKEELC.js.map} +0 -0
- /package/dist/{chunk-Y4JHE2ML.js.map → chunk-LI4ZOFHW.js.map} +0 -0
- /package/dist/{chunk-MLW3J7IC.js.map → chunk-LMHDFOVV.js.map} +0 -0
- /package/dist/{chunk-X6E5WAGX.js.map → chunk-N7EVMKP6.js.map} +0 -0
- /package/dist/{chunk-HCNG42P3.js.map → chunk-Q3FWRDCP.js.map} +0 -0
- /package/dist/{chunk-5MFHOX5T.js.map → chunk-QO2KODU6.js.map} +0 -0
- /package/dist/{chunk-W3DJOT22.js.map → chunk-TCZWBJBO.js.map} +0 -0
- /package/dist/{chunk-B3ABVQ36.js.map → chunk-UHVXE24Y.js.map} +0 -0
- /package/dist/{chunk-UX3ZXN34.js.map → chunk-UV72DEZD.js.map} +0 -0
- /package/dist/{chunk-OZSL2QZC.js.map → chunk-V5TSUGRB.js.map} +0 -0
- /package/dist/{chunk-CH3BRJ3P.js.map → chunk-X5QS5C2O.js.map} +0 -0
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
loadSyncState,
|
|
7
7
|
syncWearableSource,
|
|
8
8
|
wearableSourceLabel
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UV72DEZD.js";
|
|
10
10
|
import {
|
|
11
11
|
CompressionGuidelineCoordinator
|
|
12
12
|
} from "./chunk-B7GROTXD.js";
|
|
13
13
|
import {
|
|
14
14
|
MaintenanceScheduler
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-V5TSUGRB.js";
|
|
16
16
|
import {
|
|
17
17
|
runPeerProfileReasoner
|
|
18
18
|
} from "./chunk-I74SUMNI.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
import {
|
|
29
29
|
CompoundingEngine,
|
|
30
30
|
defaultTierMigrationCycleBudget
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-3ZUY2VQF.js";
|
|
32
32
|
import {
|
|
33
33
|
SharedContextManager
|
|
34
34
|
} from "./chunk-JGUXPJUQ.js";
|
|
@@ -210,7 +210,7 @@ import {
|
|
|
210
210
|
buildEntityRecallSection,
|
|
211
211
|
entityRecentTranscriptLookbackHours,
|
|
212
212
|
readRecentEntityTranscriptEntries
|
|
213
|
-
} from "./chunk-
|
|
213
|
+
} from "./chunk-EZKKHVFY.js";
|
|
214
214
|
import {
|
|
215
215
|
normalizeReplaySessionKey
|
|
216
216
|
} from "./chunk-AJVLDJU6.js";
|
|
@@ -220,14 +220,14 @@ import {
|
|
|
220
220
|
import {
|
|
221
221
|
compareVerifiedEpisodeResults,
|
|
222
222
|
searchVerifiedEpisodes
|
|
223
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-5JQLAQUZ.js";
|
|
224
224
|
import {
|
|
225
225
|
ThreadingManager
|
|
226
226
|
} from "./chunk-OJP3N7UK.js";
|
|
227
227
|
import {
|
|
228
228
|
compareVerifiedSemanticRuleResults,
|
|
229
229
|
searchVerifiedSemanticRules
|
|
230
|
-
} from "./chunk-
|
|
230
|
+
} from "./chunk-EXU5IQ3S.js";
|
|
231
231
|
import {
|
|
232
232
|
searchWorkProductLedgerEntries
|
|
233
233
|
} from "./chunk-ZRWB5D4H.js";
|
|
@@ -240,14 +240,14 @@ import {
|
|
|
240
240
|
import {
|
|
241
241
|
runNamespaceMaintenanceFanout,
|
|
242
242
|
summarizeNamespaceMaintenanceHealth
|
|
243
|
-
} from "./chunk-
|
|
243
|
+
} from "./chunk-N7EVMKP6.js";
|
|
244
244
|
import {
|
|
245
245
|
NamespaceCatalog,
|
|
246
246
|
planNamespaceMaintenance
|
|
247
|
-
} from "./chunk-
|
|
247
|
+
} from "./chunk-275ENJDK.js";
|
|
248
248
|
import {
|
|
249
249
|
NamespaceStorageRouter
|
|
250
|
-
} from "./chunk-
|
|
250
|
+
} from "./chunk-QO2KODU6.js";
|
|
251
251
|
import {
|
|
252
252
|
searchHarmonicRetrieval
|
|
253
253
|
} from "./chunk-AV5ZEH4M.js";
|
|
@@ -282,7 +282,7 @@ import {
|
|
|
282
282
|
materializeAfterSemanticConsolidation,
|
|
283
283
|
parseConsolidationResponse,
|
|
284
284
|
parseOperatorAwareConsolidationResponse
|
|
285
|
-
} from "./chunk-
|
|
285
|
+
} from "./chunk-53WDAG7X.js";
|
|
286
286
|
import {
|
|
287
287
|
BootstrapEngine
|
|
288
288
|
} from "./chunk-MYVPLJOO.js";
|
|
@@ -301,6 +301,9 @@ import {
|
|
|
301
301
|
import {
|
|
302
302
|
isDisagreementPrompt
|
|
303
303
|
} from "./chunk-H3FZVNRN.js";
|
|
304
|
+
import {
|
|
305
|
+
detectMeetings
|
|
306
|
+
} from "./chunk-7M6APKJL.js";
|
|
304
307
|
import {
|
|
305
308
|
compileCorrectionRule,
|
|
306
309
|
correctionsFilePath,
|
|
@@ -334,7 +337,7 @@ import {
|
|
|
334
337
|
clusterByKey,
|
|
335
338
|
createCorrectionService,
|
|
336
339
|
detectPassiveCorrections
|
|
337
|
-
} from "./chunk-
|
|
340
|
+
} from "./chunk-62QM5MKY.js";
|
|
338
341
|
import {
|
|
339
342
|
importCapsule
|
|
340
343
|
} from "./chunk-7CPOZH6Y.js";
|
|
@@ -354,7 +357,7 @@ import {
|
|
|
354
357
|
} from "./chunk-JGSKJHF7.js";
|
|
355
358
|
import {
|
|
356
359
|
buildXraySnapshot
|
|
357
|
-
} from "./chunk-
|
|
360
|
+
} from "./chunk-JFDEYXF7.js";
|
|
358
361
|
import {
|
|
359
362
|
NamespaceSearchRouter
|
|
360
363
|
} from "./chunk-SB4OKS6C.js";
|
|
@@ -400,7 +403,7 @@ import {
|
|
|
400
403
|
} from "./chunk-W4FBGYGK.js";
|
|
401
404
|
import {
|
|
402
405
|
buildChainFollowupGenerator
|
|
403
|
-
} from "./chunk-
|
|
406
|
+
} from "./chunk-Q3FWRDCP.js";
|
|
404
407
|
import {
|
|
405
408
|
ContentHashIndex,
|
|
406
409
|
QmdResultResolver,
|
|
@@ -408,6 +411,7 @@ import {
|
|
|
408
411
|
compareEntityTimestamps,
|
|
409
412
|
composeFusionDayMeta,
|
|
410
413
|
fingerprintEntityStructuredFacts,
|
|
414
|
+
fuseCluster,
|
|
411
415
|
fuseDay,
|
|
412
416
|
hashFusionBody,
|
|
413
417
|
parseEntityFile,
|
|
@@ -417,17 +421,18 @@ import {
|
|
|
417
421
|
reconstructFusionInputs,
|
|
418
422
|
selfDeps,
|
|
419
423
|
serializeFusionDay
|
|
420
|
-
} from "./chunk-
|
|
424
|
+
} from "./chunk-4F6AANKS.js";
|
|
421
425
|
import {
|
|
422
426
|
bodyIsEscaped,
|
|
423
427
|
decodeTranscriptBody,
|
|
424
428
|
escapeSegmentText,
|
|
429
|
+
escapeSpeakerLabel,
|
|
425
430
|
isValidTranscriptDate,
|
|
426
431
|
loadSpeakerRegistry,
|
|
427
432
|
parseDayTranscript,
|
|
428
433
|
saveSpeakerRegistry,
|
|
429
434
|
speakerRegistryKey
|
|
430
|
-
} from "./chunk-
|
|
435
|
+
} from "./chunk-UHVXE24Y.js";
|
|
431
436
|
import {
|
|
432
437
|
buildRetiredFactTombstoneInputs
|
|
433
438
|
} from "./chunk-2QMKMVHH.js";
|
|
@@ -448,14 +453,15 @@ import {
|
|
|
448
453
|
} from "./chunk-J6A3CX5N.js";
|
|
449
454
|
import {
|
|
450
455
|
confidenceTier
|
|
451
|
-
} from "./chunk-
|
|
456
|
+
} from "./chunk-6NZ7U4R4.js";
|
|
452
457
|
import {
|
|
453
458
|
namespaceIdentityFromToken,
|
|
454
459
|
namespaceIdentityToken,
|
|
455
460
|
normalizeNamespaceIdentity
|
|
456
461
|
} from "./chunk-EGGE52UU.js";
|
|
457
462
|
import {
|
|
458
|
-
assertPathInsideRoot
|
|
463
|
+
assertPathInsideRoot,
|
|
464
|
+
pathIsInside
|
|
459
465
|
} from "./chunk-GCASGYIO.js";
|
|
460
466
|
import {
|
|
461
467
|
inferMemoryStatus,
|
|
@@ -868,8 +874,8 @@ var ExtractionQueueCoordinator = class {
|
|
|
868
874
|
log.warn(`waitForExtractionIdle timed out after ${timeoutMs}ms`);
|
|
869
875
|
return false;
|
|
870
876
|
}
|
|
871
|
-
const { promise, resolve } = Promise.withResolvers();
|
|
872
|
-
setTimeout(
|
|
877
|
+
const { promise, resolve: resolve2 } = Promise.withResolvers();
|
|
878
|
+
setTimeout(resolve2, 50);
|
|
873
879
|
await promise;
|
|
874
880
|
}
|
|
875
881
|
return true;
|
|
@@ -1009,20 +1015,20 @@ var SemanticConsolidationCoordinator = class {
|
|
|
1009
1015
|
result.errors++;
|
|
1010
1016
|
continue;
|
|
1011
1017
|
}
|
|
1012
|
-
let
|
|
1018
|
+
let canonicalContent2;
|
|
1013
1019
|
let operator;
|
|
1014
1020
|
if (operatorAwareEnabled) {
|
|
1015
1021
|
const parsed = parseOperatorAwareConsolidationResponse(
|
|
1016
1022
|
response.content,
|
|
1017
1023
|
cluster
|
|
1018
1024
|
);
|
|
1019
|
-
|
|
1025
|
+
canonicalContent2 = parsed.output;
|
|
1020
1026
|
operator = parsed.operator;
|
|
1021
1027
|
} else {
|
|
1022
|
-
|
|
1028
|
+
canonicalContent2 = parseConsolidationResponse(response.content);
|
|
1023
1029
|
operator = chooseConsolidationOperator(cluster);
|
|
1024
1030
|
}
|
|
1025
|
-
cluster.canonicalContent =
|
|
1031
|
+
cluster.canonicalContent = canonicalContent2;
|
|
1026
1032
|
const sorted = [...cluster.memories].sort(
|
|
1027
1033
|
(a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
|
|
1028
1034
|
);
|
|
@@ -1036,7 +1042,7 @@ var SemanticConsolidationCoordinator = class {
|
|
|
1036
1042
|
}
|
|
1037
1043
|
const canonicalEnvelope = composeMemoryEnvelope(
|
|
1038
1044
|
{
|
|
1039
|
-
content:
|
|
1045
|
+
content: canonicalContent2,
|
|
1040
1046
|
category: newest.frontmatter.category,
|
|
1041
1047
|
confidence: newest.frontmatter.confidence,
|
|
1042
1048
|
tags: [
|
|
@@ -2080,7 +2086,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2080
2086
|
namespaces,
|
|
2081
2087
|
{
|
|
2082
2088
|
readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),
|
|
2083
|
-
readMemoryFrontmatter: async (
|
|
2089
|
+
readMemoryFrontmatter: async (path32, preferredNamespace) => {
|
|
2084
2090
|
if (!fallbackReader) {
|
|
2085
2091
|
for (const ns of namespaces) {
|
|
2086
2092
|
try {
|
|
@@ -2092,7 +2098,7 @@ var RecallRerankCoordinator = class _RecallRerankCoordinator {
|
|
|
2092
2098
|
}
|
|
2093
2099
|
if (!fallbackReader) return null;
|
|
2094
2100
|
const memory = await this.readQmdResultMemory(
|
|
2095
|
-
|
|
2101
|
+
path32,
|
|
2096
2102
|
fallbackReader,
|
|
2097
2103
|
namespaces,
|
|
2098
2104
|
preferredNamespace
|
|
@@ -2837,8 +2843,8 @@ function utcDateKeysForLocalDay(date, timeZone) {
|
|
|
2837
2843
|
const hourMs = 36e5;
|
|
2838
2844
|
const scanStart = date.getTime() - 48 * hourMs;
|
|
2839
2845
|
const scanEnd = date.getTime() + 48 * hourMs;
|
|
2840
|
-
for (let
|
|
2841
|
-
const candidate = new Date(
|
|
2846
|
+
for (let ms = scanStart; ms <= scanEnd; ms += hourMs) {
|
|
2847
|
+
const candidate = new Date(ms);
|
|
2842
2848
|
if (formatDateInTimeZone(candidate, timeZone) === targetLocalDate) {
|
|
2843
2849
|
keys.add(utcDateKey(candidate));
|
|
2844
2850
|
}
|
|
@@ -2883,14 +2889,14 @@ async function qmdStartupCollectionCheckWithTimeout(promise, controller, label)
|
|
|
2883
2889
|
const timeoutMs = qmdStartupCollectionCheckTimeoutMs();
|
|
2884
2890
|
let timer;
|
|
2885
2891
|
let settled = false;
|
|
2886
|
-
const timeoutPromise = new Promise((
|
|
2892
|
+
const timeoutPromise = new Promise((resolve2) => {
|
|
2887
2893
|
timer = setTimeout(() => {
|
|
2888
2894
|
if (settled) return;
|
|
2889
2895
|
controller.abort();
|
|
2890
2896
|
log.warn(
|
|
2891
2897
|
`QMD startup collection check for ${label} timed out after ${timeoutMs}ms; keeping search enabled fail-open`
|
|
2892
2898
|
);
|
|
2893
|
-
|
|
2899
|
+
resolve2("unknown");
|
|
2894
2900
|
}, timeoutMs);
|
|
2895
2901
|
timer.unref?.();
|
|
2896
2902
|
});
|
|
@@ -2995,17 +3001,20 @@ function splitTurnsBySourceValidAt(turns, options = {}) {
|
|
|
2995
3001
|
function isArtifactMemoryPath(filePath) {
|
|
2996
3002
|
return /(?:^|[\\/])artifacts(?:[\\/]|$)/i.test(filePath);
|
|
2997
3003
|
}
|
|
3004
|
+
function isMeetingRecordPath(filePath) {
|
|
3005
|
+
return /(?:^|[\\/])meetings[\\/]\d{4}-\d{2}-\d{2}[\\/]mtg-\d{4}-\d{2}-\d{2}-[0-9a-f]{8}\.md$/i.test(filePath);
|
|
3006
|
+
}
|
|
2998
3007
|
var ACTIVITY_DIGEST_TOPLEVEL = /^activity[\\/]\d{4}-\d{2}-\d{2}\.md$/i;
|
|
2999
3008
|
var ACTIVITY_DIGEST_ANYWHERE = /(?:^|[\\/])activity[\\/]\d{4}-\d{2}-\d{2}\.md$/i;
|
|
3000
3009
|
function isActivityDigestPath(filePath, memoryRoot) {
|
|
3001
3010
|
if (memoryRoot !== void 0 && memoryRoot.length > 0) {
|
|
3002
|
-
const
|
|
3003
|
-
return ACTIVITY_DIGEST_TOPLEVEL.test(
|
|
3011
|
+
const relative2 = path4.relative(memoryRoot, path4.resolve(memoryRoot, filePath));
|
|
3012
|
+
return ACTIVITY_DIGEST_TOPLEVEL.test(relative2);
|
|
3004
3013
|
}
|
|
3005
3014
|
return ACTIVITY_DIGEST_ANYWHERE.test(filePath);
|
|
3006
3015
|
}
|
|
3007
3016
|
function isGenericRecallExcludedPath(filePath, memoryRoot) {
|
|
3008
|
-
return isArtifactMemoryPath(filePath) || isActivityDigestPath(filePath, memoryRoot);
|
|
3017
|
+
return isArtifactMemoryPath(filePath) || isActivityDigestPath(filePath, memoryRoot) || isMeetingRecordPath(filePath);
|
|
3009
3018
|
}
|
|
3010
3019
|
function buildCompressionGuidelinesMarkdown2(events, generatedAtIso = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
3011
3020
|
return buildCompressionGuidelinesMarkdown(events, generatedAtIso);
|
|
@@ -7818,9 +7827,9 @@ ${rows.join("\n")}
|
|
|
7818
7827
|
}
|
|
7819
7828
|
return merged.sort(compareVerifiedEpisodeResults).slice(0, maxResults);
|
|
7820
7829
|
}),
|
|
7821
|
-
new Promise((
|
|
7830
|
+
new Promise((resolve2) => {
|
|
7822
7831
|
timeoutHandle = setTimeout(
|
|
7823
|
-
() =>
|
|
7832
|
+
() => resolve2([]),
|
|
7824
7833
|
VERIFIED_RECALL_TIMEOUT_MS
|
|
7825
7834
|
);
|
|
7826
7835
|
})
|
|
@@ -7898,9 +7907,9 @@ ${rows.join("\n")}
|
|
|
7898
7907
|
}
|
|
7899
7908
|
return merged.sort(compareVerifiedSemanticRuleResults).slice(0, maxResults);
|
|
7900
7909
|
}),
|
|
7901
|
-
new Promise((
|
|
7910
|
+
new Promise((resolve2) => {
|
|
7902
7911
|
rulesTimeoutHandle = setTimeout(
|
|
7903
|
-
() =>
|
|
7912
|
+
() => resolve2([]),
|
|
7904
7913
|
VERIFIED_RULES_TIMEOUT_MS
|
|
7905
7914
|
);
|
|
7906
7915
|
})
|
|
@@ -8626,7 +8635,7 @@ ${formatted}`;
|
|
|
8626
8635
|
);
|
|
8627
8636
|
const results = await Promise.race([
|
|
8628
8637
|
this.deps.searchConversationRecallResults(retrievalQuery, topK),
|
|
8629
|
-
new Promise((
|
|
8638
|
+
new Promise((resolve2) => setTimeout(() => resolve2([]), timeoutMs))
|
|
8630
8639
|
]).catch(() => []);
|
|
8631
8640
|
const durationMs = Date.now() - startedAtMs;
|
|
8632
8641
|
if (durationMs >= timeoutMs) {
|
|
@@ -8840,9 +8849,9 @@ ${formatted}`;
|
|
|
8840
8849
|
}
|
|
8841
8850
|
const outcome = await (timeoutMs !== null ? Promise.race([
|
|
8842
8851
|
promise,
|
|
8843
|
-
new Promise((
|
|
8852
|
+
new Promise((resolve2) => {
|
|
8844
8853
|
timeoutHandle = setTimeout(
|
|
8845
|
-
() =>
|
|
8854
|
+
() => resolve2({ status: "timed_out" }),
|
|
8846
8855
|
timeoutMs
|
|
8847
8856
|
);
|
|
8848
8857
|
})
|
|
@@ -8878,9 +8887,9 @@ ${formatted}`;
|
|
|
8878
8887
|
try {
|
|
8879
8888
|
const result = await (timeoutMs !== null ? Promise.race([
|
|
8880
8889
|
task(stepSignal),
|
|
8881
|
-
new Promise((
|
|
8890
|
+
new Promise((resolve2) => {
|
|
8882
8891
|
timeoutHandle = setTimeout(
|
|
8883
|
-
() =>
|
|
8892
|
+
() => resolve2({ status: "timed_out" }),
|
|
8884
8893
|
timeoutMs
|
|
8885
8894
|
);
|
|
8886
8895
|
})
|
|
@@ -10692,8 +10701,8 @@ var ArchiveScoringWorkerPool = class {
|
|
|
10692
10701
|
const idle = this.idle.pop();
|
|
10693
10702
|
if (idle) return idle;
|
|
10694
10703
|
if (this.workers.length < this.targetSize) return this.spawn();
|
|
10695
|
-
return new Promise((
|
|
10696
|
-
const entry = { resolve, reject };
|
|
10704
|
+
return new Promise((resolve2, reject) => {
|
|
10705
|
+
const entry = { resolve: resolve2, reject };
|
|
10697
10706
|
this.waiters.push(entry);
|
|
10698
10707
|
if (!abortSignal) return;
|
|
10699
10708
|
const onAbort = () => {
|
|
@@ -10734,7 +10743,7 @@ var ArchiveScoringWorkerPool = class {
|
|
|
10734
10743
|
return worker;
|
|
10735
10744
|
}
|
|
10736
10745
|
dispatch(worker, task, abortSignal, onAbandon) {
|
|
10737
|
-
return new Promise((
|
|
10746
|
+
return new Promise((resolve2, reject) => {
|
|
10738
10747
|
let settled = false;
|
|
10739
10748
|
const timer = setTimeout(() => {
|
|
10740
10749
|
if (settled) return;
|
|
@@ -10748,7 +10757,7 @@ var ArchiveScoringWorkerPool = class {
|
|
|
10748
10757
|
if (settled) return;
|
|
10749
10758
|
settled = true;
|
|
10750
10759
|
cleanup();
|
|
10751
|
-
if (reply.ok)
|
|
10760
|
+
if (reply.ok) resolve2(reply.results);
|
|
10752
10761
|
else reject(new Error(reply.error));
|
|
10753
10762
|
};
|
|
10754
10763
|
const onError = (err) => {
|
|
@@ -10770,7 +10779,7 @@ var ArchiveScoringWorkerPool = class {
|
|
|
10770
10779
|
settled = true;
|
|
10771
10780
|
cleanup();
|
|
10772
10781
|
onAbandon();
|
|
10773
|
-
|
|
10782
|
+
resolve2([]);
|
|
10774
10783
|
};
|
|
10775
10784
|
const cleanup = () => {
|
|
10776
10785
|
clearTimeout(timer);
|
|
@@ -10977,9 +10986,17 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
10977
10986
|
const scopedSeedResults = queryAwarePrefilter.candidatePaths?.size ? await this.deps.searchScopedMemoryCandidates(
|
|
10978
10987
|
queryAwarePrefilter.candidatePaths,
|
|
10979
10988
|
prompt,
|
|
10980
|
-
|
|
10989
|
+
// Overfetch the FULL scoped candidate set BEFORE the generic-recall
|
|
10990
|
+
// exclusion `filterRecallCandidates` applies below (L464). Capping to
|
|
10991
|
+
// `qmdFetchLimit` here lets excluded paths (artifacts, activity digests,
|
|
10992
|
+
// meeting records) consume the caller's budget and drop legitimate hits
|
|
10993
|
+
// with no refill — the hot-path mirror of the archive-fallback fix. The
|
|
10994
|
+
// candidate set is an already-bounded prefilter, so its size is the
|
|
10995
|
+
// natural ceiling; the post-exclusion cap is applied by filterRecallCandidates.
|
|
10996
|
+
queryAwarePrefilter.candidatePaths.size,
|
|
10981
10997
|
{ allowArchived: options.collection !== void 0 }
|
|
10982
10998
|
) : [];
|
|
10999
|
+
const recallable = (r) => !isGenericRecallExcludedPath(r.path, this.deps.config.memoryDir);
|
|
10983
11000
|
let fetchLimit = Math.max(qmdFetchLimit, qmdHybridFetchLimit);
|
|
10984
11001
|
const maxFetchLimit = Math.min(
|
|
10985
11002
|
320,
|
|
@@ -11104,7 +11121,7 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11104
11121
|
[...primaryResults, ...hybridResults],
|
|
11105
11122
|
this.deps.namespaceFromPath,
|
|
11106
11123
|
fetchLimit,
|
|
11107
|
-
{ transportFallback: "hybrid" }
|
|
11124
|
+
{ transportFallback: "hybrid", filter: recallable }
|
|
11108
11125
|
);
|
|
11109
11126
|
}
|
|
11110
11127
|
}
|
|
@@ -11113,7 +11130,8 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11113
11130
|
mergedResults = dedupeResultsByNamespace(
|
|
11114
11131
|
[...scopedSeedResults, ...mergedResults],
|
|
11115
11132
|
this.deps.namespaceFromPath,
|
|
11116
|
-
fetchLimit
|
|
11133
|
+
fetchLimit,
|
|
11134
|
+
{ filter: recallable }
|
|
11117
11135
|
);
|
|
11118
11136
|
}
|
|
11119
11137
|
const filteredResults = filterRecallCandidates(mergedResults, {
|
|
@@ -11177,14 +11195,22 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11177
11195
|
const cappedLimit = Math.max(0, limit);
|
|
11178
11196
|
if (cappedLimit === 0) return [];
|
|
11179
11197
|
if (queryAwarePrefilter?.candidatePaths?.size === 0) return [];
|
|
11180
|
-
const
|
|
11181
|
-
|
|
11198
|
+
const candidatePaths = queryAwarePrefilter?.candidatePaths;
|
|
11199
|
+
const scopedSeedResults = (candidatePaths?.size ? await this.deps.searchScopedMemoryCandidates(
|
|
11200
|
+
candidatePaths,
|
|
11182
11201
|
prompt,
|
|
11183
|
-
|
|
11202
|
+
// Overfetch the FULL scoped candidate set BEFORE the generic-recall
|
|
11203
|
+
// exclusion below. Capping to `cappedLimit` first lets excluded paths
|
|
11204
|
+
// (artifacts, activity digests, meeting records) consume the caller's
|
|
11205
|
+
// budget and drop legitimate hits with no refill — e.g. a prefilter of
|
|
11206
|
+
// [meetingRecord, facts/a.md] at limit 1 would return nothing. The
|
|
11207
|
+
// candidate set is an already-bounded prefilter, so its size is the
|
|
11208
|
+
// natural ceiling; the post-exclusion cap is applied below.
|
|
11209
|
+
candidatePaths.size,
|
|
11184
11210
|
{ allowArchived: true }
|
|
11185
|
-
) : [];
|
|
11211
|
+
) : []).filter((result) => !isGenericRecallExcludedPath(result.path, this.deps.config.memoryDir));
|
|
11186
11212
|
if (scopedSeedResults.length >= cappedLimit) {
|
|
11187
|
-
return scopedSeedResults.
|
|
11213
|
+
return scopedSeedResults.slice(0, cappedLimit);
|
|
11188
11214
|
}
|
|
11189
11215
|
const tokens = Array.from(new Set(tokenizeRecallQuery(prompt)));
|
|
11190
11216
|
if (tokens.length === 0) return scopedSeedResults;
|
|
@@ -11246,11 +11272,11 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11246
11272
|
try {
|
|
11247
11273
|
return await Promise.race([
|
|
11248
11274
|
taskPromise,
|
|
11249
|
-
new Promise((
|
|
11275
|
+
new Promise((resolve2) => {
|
|
11250
11276
|
timeoutHandle = setTimeout(() => {
|
|
11251
11277
|
timedOut = true;
|
|
11252
11278
|
abandonToDeadline();
|
|
11253
|
-
|
|
11279
|
+
resolve2(fallback);
|
|
11254
11280
|
}, remainingMs);
|
|
11255
11281
|
})
|
|
11256
11282
|
]);
|
|
@@ -11416,9 +11442,9 @@ var RecallSearchPipelineCoordinator = class {
|
|
|
11416
11442
|
boostInput.memoryByPath,
|
|
11417
11443
|
{ allowLifecycleFiltered: true, asOfMs: options.asOfMs }
|
|
11418
11444
|
),
|
|
11419
|
-
new Promise((
|
|
11445
|
+
new Promise((resolve2) => {
|
|
11420
11446
|
timeoutHandle = setTimeout(
|
|
11421
|
-
() =>
|
|
11447
|
+
() => resolve2({ status: "timed_out" }),
|
|
11422
11448
|
boostTimeoutMs
|
|
11423
11449
|
);
|
|
11424
11450
|
})
|
|
@@ -11995,7 +12021,7 @@ var TurnIngestionCoordinator = class {
|
|
|
11995
12021
|
if (a.order === b.order) return 0;
|
|
11996
12022
|
return a.order < b.order ? -1 : 1;
|
|
11997
12023
|
}).map(
|
|
11998
|
-
({ bufferKey, turns: sessionSlice }) => new Promise((
|
|
12024
|
+
({ bufferKey, turns: sessionSlice }) => new Promise((resolve2, reject) => {
|
|
11999
12025
|
void this.deps.queueBufferedExtraction(sessionSlice, "trigger_mode", {
|
|
12000
12026
|
skipDedupeCheck: true,
|
|
12001
12027
|
forceExtractionAttempt: true,
|
|
@@ -12007,7 +12033,7 @@ var TurnIngestionCoordinator = class {
|
|
|
12007
12033
|
abortSignal: options.abortSignal,
|
|
12008
12034
|
writeNamespaceOverride: options.writeNamespaceOverride,
|
|
12009
12035
|
principalOverride: options.principalOverride,
|
|
12010
|
-
onTaskSettled: (err) => err ? reject(err) :
|
|
12036
|
+
onTaskSettled: (err) => err ? reject(err) : resolve2()
|
|
12011
12037
|
}).catch(reject);
|
|
12012
12038
|
})
|
|
12013
12039
|
);
|
|
@@ -12136,7 +12162,7 @@ var TurnIngestionCoordinator = class {
|
|
|
12136
12162
|
for (const sessionSlice of sessionSlices) {
|
|
12137
12163
|
try {
|
|
12138
12164
|
const result = await new Promise(
|
|
12139
|
-
(
|
|
12165
|
+
(resolve2, reject) => {
|
|
12140
12166
|
void this.deps.queueBufferedExtraction(sessionSlice, "trigger_mode", {
|
|
12141
12167
|
skipDedupeCheck: true,
|
|
12142
12168
|
forceExtractionAttempt: true,
|
|
@@ -12147,7 +12173,7 @@ var TurnIngestionCoordinator = class {
|
|
|
12147
12173
|
extractionDeadlineMs: options.deadlineMs,
|
|
12148
12174
|
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
12149
12175
|
writeNamespaceOverride: this.deps.bulkImportWriteNamespace(),
|
|
12150
|
-
onTaskSettled: (err, result2) => err ? reject(err) :
|
|
12176
|
+
onTaskSettled: (err, result2) => err ? reject(err) : resolve2(
|
|
12151
12177
|
result2 ?? {
|
|
12152
12178
|
status: "skipped",
|
|
12153
12179
|
reason: "missing_extraction_result",
|
|
@@ -12896,8 +12922,8 @@ var RecallIntrospectionCoordinator = class {
|
|
|
12896
12922
|
async waitForDirectAnswerObservationIdle(timeoutMs = 6e4) {
|
|
12897
12923
|
let timeoutHandle = null;
|
|
12898
12924
|
try {
|
|
12899
|
-
const timeoutPromise = new Promise((
|
|
12900
|
-
timeoutHandle = setTimeout(() =>
|
|
12925
|
+
const timeoutPromise = new Promise((resolve2) => {
|
|
12926
|
+
timeoutHandle = setTimeout(() => resolve2("timeout"), timeoutMs);
|
|
12901
12927
|
});
|
|
12902
12928
|
const result = await Promise.race([
|
|
12903
12929
|
this.deps.directAnswerObservationChain.then(() => "ok"),
|
|
@@ -13113,8 +13139,8 @@ var OrchestratorInitCoordinator = class {
|
|
|
13113
13139
|
}
|
|
13114
13140
|
deps;
|
|
13115
13141
|
async initialize() {
|
|
13116
|
-
this.deps.deferredReady = new Promise((
|
|
13117
|
-
this.deps.resolveDeferredReady =
|
|
13142
|
+
this.deps.deferredReady = new Promise((resolve2) => {
|
|
13143
|
+
this.deps.resolveDeferredReady = resolve2;
|
|
13118
13144
|
});
|
|
13119
13145
|
try {
|
|
13120
13146
|
await migrateFromEngram({
|
|
@@ -13420,7 +13446,7 @@ var OrchestratorInitCoordinator = class {
|
|
|
13420
13446
|
if (signal.aborted) return;
|
|
13421
13447
|
if (!this.deps.wearablesAutoSyncHandle && this.deps.config.wearables.enabled && this.deps.config.wearables.autoSyncEnabled && Object.values(this.deps.config.wearables.sources).some((source) => source.enabled)) {
|
|
13422
13448
|
try {
|
|
13423
|
-
const { startWearablesAutoSync } = await import("./auto-sync-
|
|
13449
|
+
const { startWearablesAutoSync } = await import("./auto-sync-UPTUVE4X.js");
|
|
13424
13450
|
if (signal.aborted) return;
|
|
13425
13451
|
this.deps.wearablesAutoSyncHandle = startWearablesAutoSync(
|
|
13426
13452
|
{
|
|
@@ -15703,14 +15729,14 @@ var RecallEntryCoordinator = class {
|
|
|
15703
15729
|
if (this.deps.initPromise) {
|
|
15704
15730
|
const gateResult = await Promise.race([
|
|
15705
15731
|
this.deps.initPromise.then(() => "ok"),
|
|
15706
|
-
new Promise((
|
|
15732
|
+
new Promise((resolve2) => {
|
|
15707
15733
|
initGateTimeoutHandle = setTimeout(
|
|
15708
|
-
() =>
|
|
15734
|
+
() => resolve2("timeout"),
|
|
15709
15735
|
this.deps.config.initGateTimeoutMs
|
|
15710
15736
|
);
|
|
15711
15737
|
}),
|
|
15712
|
-
abortController.signal.aborted ? Promise.resolve("aborted") : new Promise((
|
|
15713
|
-
onInitGateAbort = () =>
|
|
15738
|
+
abortController.signal.aborted ? Promise.resolve("aborted") : new Promise((resolve2) => {
|
|
15739
|
+
onInitGateAbort = () => resolve2("aborted");
|
|
15714
15740
|
abortController.signal.addEventListener(
|
|
15715
15741
|
"abort",
|
|
15716
15742
|
onInitGateAbort,
|
|
@@ -16035,9 +16061,9 @@ var SessionContextCoordinator = class {
|
|
|
16035
16061
|
try {
|
|
16036
16062
|
await Promise.race([
|
|
16037
16063
|
this.deps.initPromise.catch(() => void 0),
|
|
16038
|
-
new Promise((
|
|
16064
|
+
new Promise((resolve2) => {
|
|
16039
16065
|
initGateTimeoutHandle = setTimeout(
|
|
16040
|
-
|
|
16066
|
+
resolve2,
|
|
16041
16067
|
this.deps.config.initGateTimeoutMs
|
|
16042
16068
|
);
|
|
16043
16069
|
})
|
|
@@ -16058,14 +16084,14 @@ var SessionContextCoordinator = class {
|
|
|
16058
16084
|
for (const bufferKey of bufferKeys) {
|
|
16059
16085
|
const turns = this.deps.buffer.getTurns(bufferKey);
|
|
16060
16086
|
if (turns.length === 0) continue;
|
|
16061
|
-
await new Promise((
|
|
16087
|
+
await new Promise((resolve2, reject) => {
|
|
16062
16088
|
void this.deps.queueBufferedExtraction(turns, "trigger_mode", {
|
|
16063
16089
|
bufferKey,
|
|
16064
16090
|
clearBufferAfterExtraction: true,
|
|
16065
16091
|
skipDedupeCheck: true,
|
|
16066
16092
|
forceExtractionAttempt: true,
|
|
16067
16093
|
abortSignal: options.abortSignal,
|
|
16068
|
-
onTaskSettled: (error) => error ? reject(error) :
|
|
16094
|
+
onTaskSettled: (error) => error ? reject(error) : resolve2()
|
|
16069
16095
|
}).catch(reject);
|
|
16070
16096
|
});
|
|
16071
16097
|
}
|
|
@@ -16149,8 +16175,8 @@ var XrayCaptureQueue = class {
|
|
|
16149
16175
|
const previous = this.tail;
|
|
16150
16176
|
let release = () => {
|
|
16151
16177
|
};
|
|
16152
|
-
this.tail = new Promise((
|
|
16153
|
-
release =
|
|
16178
|
+
this.tail = new Promise((resolve2) => {
|
|
16179
|
+
release = resolve2;
|
|
16154
16180
|
});
|
|
16155
16181
|
try {
|
|
16156
16182
|
await this.waitForTurn(previous, signal);
|
|
@@ -17111,8 +17137,8 @@ var Orchestrator = class {
|
|
|
17111
17137
|
};
|
|
17112
17138
|
this.lcmEngine = new LcmEngine(config, summarizeFn);
|
|
17113
17139
|
}
|
|
17114
|
-
this.initPromise = new Promise((
|
|
17115
|
-
this.resolveInit =
|
|
17140
|
+
this.initPromise = new Promise((resolve2) => {
|
|
17141
|
+
this.resolveInit = resolve2;
|
|
17116
17142
|
});
|
|
17117
17143
|
}
|
|
17118
17144
|
/** Get or create a BoxBuilder for the given namespace storage root (namespace-isolated). */
|
|
@@ -17416,7 +17442,7 @@ ${doc.content}` : doc.content,
|
|
|
17416
17442
|
log.warn(`waitForConsolidationIdle timed out after ${timeoutMs}ms`);
|
|
17417
17443
|
return false;
|
|
17418
17444
|
}
|
|
17419
|
-
await new Promise((
|
|
17445
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
17420
17446
|
}
|
|
17421
17447
|
return true;
|
|
17422
17448
|
}
|
|
@@ -19184,9 +19210,9 @@ function readStructuralSymbol(entry) {
|
|
|
19184
19210
|
const rec = entry;
|
|
19185
19211
|
const symbol = typeof rec.symbol === "string" ? rec.symbol.trim() : "";
|
|
19186
19212
|
if (!symbol) return null;
|
|
19187
|
-
const
|
|
19213
|
+
const path32 = typeof rec.path === "string" && rec.path.length > 0 ? rec.path : void 0;
|
|
19188
19214
|
const kind = typeof rec.kind === "string" && rec.kind.length > 0 ? rec.kind : void 0;
|
|
19189
|
-
const item =
|
|
19215
|
+
const item = path32 !== void 0 && kind !== void 0 ? { symbol, path: path32, kind } : path32 !== void 0 ? { symbol, path: path32 } : kind !== void 0 ? { symbol, kind } : { symbol };
|
|
19190
19216
|
return item;
|
|
19191
19217
|
}
|
|
19192
19218
|
function classifySpawnError(err) {
|
|
@@ -19272,15 +19298,15 @@ var FilesystemBackend = class {
|
|
|
19272
19298
|
}
|
|
19273
19299
|
resolveRemotePath(remotePath) {
|
|
19274
19300
|
const resolved = path17.isAbsolute(remotePath) ? path17.resolve(remotePath) : path17.resolve(this.basePath, remotePath);
|
|
19275
|
-
const
|
|
19276
|
-
if (
|
|
19301
|
+
const relative2 = path17.relative(this.basePath, resolved);
|
|
19302
|
+
if (relative2 === ".." || relative2.startsWith(`..${path17.sep}`) || path17.isAbsolute(relative2)) {
|
|
19277
19303
|
throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);
|
|
19278
19304
|
}
|
|
19279
19305
|
return resolved;
|
|
19280
19306
|
}
|
|
19281
19307
|
isInsideBase(candidate, realBase) {
|
|
19282
|
-
const
|
|
19283
|
-
return
|
|
19308
|
+
const relative2 = path17.relative(realBase, candidate);
|
|
19309
|
+
return relative2 === "" || relative2 !== ".." && !relative2.startsWith(`..${path17.sep}`) && !path17.isAbsolute(relative2);
|
|
19284
19310
|
}
|
|
19285
19311
|
async realBasePathIfExists() {
|
|
19286
19312
|
try {
|
|
@@ -19630,8 +19656,8 @@ function resolveManifestAssetPath(memoryDir, originalPath) {
|
|
|
19630
19656
|
}
|
|
19631
19657
|
const memoryRoot = path20.resolve(memoryDir);
|
|
19632
19658
|
const fullPath = path20.resolve(memoryRoot, originalPath);
|
|
19633
|
-
const
|
|
19634
|
-
if (
|
|
19659
|
+
const relative2 = path20.relative(memoryRoot, fullPath);
|
|
19660
|
+
if (relative2 === "" || relative2 === ".." || relative2.startsWith(`..${path20.sep}`) || path20.isAbsolute(relative2)) {
|
|
19635
19661
|
return null;
|
|
19636
19662
|
}
|
|
19637
19663
|
return fullPath;
|
|
@@ -20166,8 +20192,8 @@ async function generateContextTree(options) {
|
|
|
20166
20192
|
};
|
|
20167
20193
|
}
|
|
20168
20194
|
function isPathInside(root, candidate) {
|
|
20169
|
-
const
|
|
20170
|
-
return
|
|
20195
|
+
const relative2 = path21.relative(root, candidate);
|
|
20196
|
+
return relative2 === "" || !relative2.startsWith("..") && !path21.isAbsolute(relative2);
|
|
20171
20197
|
}
|
|
20172
20198
|
function assertNotSymlink(targetPath, label) {
|
|
20173
20199
|
try {
|
|
@@ -20204,11 +20230,11 @@ function assertSafeInputRoot(realMemoryDir, targetPath, label) {
|
|
|
20204
20230
|
}
|
|
20205
20231
|
function assertSafeOutputTarget(realOutputDir, outputPath) {
|
|
20206
20232
|
let current = realOutputDir;
|
|
20207
|
-
const
|
|
20208
|
-
if (
|
|
20233
|
+
const relative2 = path21.relative(realOutputDir, outputPath);
|
|
20234
|
+
if (relative2.startsWith("..") || path21.isAbsolute(relative2)) {
|
|
20209
20235
|
throw new Error(`context tree output path escapes outputDir: ${outputPath}`);
|
|
20210
20236
|
}
|
|
20211
|
-
for (const segment of
|
|
20237
|
+
for (const segment of relative2.split(path21.sep).filter(Boolean)) {
|
|
20212
20238
|
current = path21.join(current, segment);
|
|
20213
20239
|
try {
|
|
20214
20240
|
const stat5 = fs.lstatSync(current);
|
|
@@ -20240,8 +20266,8 @@ function validateProjectionCategories(categories) {
|
|
|
20240
20266
|
}
|
|
20241
20267
|
function resolveContainedOutputPath(outputRoot, ...segments) {
|
|
20242
20268
|
const resolved = path21.resolve(outputRoot, ...segments);
|
|
20243
|
-
const
|
|
20244
|
-
if (
|
|
20269
|
+
const relative2 = path21.relative(outputRoot, resolved);
|
|
20270
|
+
if (relative2 === "" || !relative2.startsWith("..") && !path21.isAbsolute(relative2)) {
|
|
20245
20271
|
return resolved;
|
|
20246
20272
|
}
|
|
20247
20273
|
throw new Error(`context tree output path escapes outputDir: ${segments.join("/")}`);
|
|
@@ -21345,8 +21371,8 @@ function realMemoryRoot(memoryDir) {
|
|
|
21345
21371
|
}
|
|
21346
21372
|
}
|
|
21347
21373
|
function isPathInside2(rootReal, candidateReal) {
|
|
21348
|
-
const
|
|
21349
|
-
return
|
|
21374
|
+
const relative2 = path25.relative(rootReal, candidateReal);
|
|
21375
|
+
return relative2 === "" || !!relative2 && !relative2.startsWith("..") && !path25.isAbsolute(relative2);
|
|
21350
21376
|
}
|
|
21351
21377
|
function isSafeDirectory(rootReal, dir) {
|
|
21352
21378
|
try {
|
|
@@ -22222,8 +22248,8 @@ function isProcessAlive(pid) {
|
|
|
22222
22248
|
return true;
|
|
22223
22249
|
}
|
|
22224
22250
|
}
|
|
22225
|
-
function sleepSync(
|
|
22226
|
-
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0,
|
|
22251
|
+
function sleepSync(ms) {
|
|
22252
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
22227
22253
|
}
|
|
22228
22254
|
function createPersonalSpace(baseDir, memoryDirOverride) {
|
|
22229
22255
|
const homeDir = baseDir ?? resolveHomeDir();
|
|
@@ -22608,8 +22634,8 @@ function safeRealpath(filePath) {
|
|
|
22608
22634
|
}
|
|
22609
22635
|
}
|
|
22610
22636
|
function isPathInsideRoot(candidatePath, rootPath) {
|
|
22611
|
-
const
|
|
22612
|
-
return
|
|
22637
|
+
const relative2 = path27.relative(rootPath, candidatePath);
|
|
22638
|
+
return relative2 === "" || !relative2.startsWith("..") && !path27.isAbsolute(relative2);
|
|
22613
22639
|
}
|
|
22614
22640
|
function parseSimpleFrontmatter(content) {
|
|
22615
22641
|
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
@@ -23187,187 +23213,873 @@ async function generateActivityMemories(date, digestBody, config, deps) {
|
|
|
23187
23213
|
return result;
|
|
23188
23214
|
}
|
|
23189
23215
|
|
|
23190
|
-
// src/meetings/
|
|
23191
|
-
|
|
23192
|
-
|
|
23193
|
-
|
|
23194
|
-
|
|
23195
|
-
|
|
23196
|
-
"teams.microsoft.com",
|
|
23197
|
-
"meet.google.com",
|
|
23198
|
-
"Webex",
|
|
23199
|
-
"Slack",
|
|
23200
|
-
// huddle windows
|
|
23201
|
-
"FaceTime"
|
|
23202
|
-
];
|
|
23203
|
-
var DEFAULT_MEETINGS_DETECTION_CONFIG = {
|
|
23204
|
-
appPatterns: [...DEFAULT_MEETING_APP_PATTERNS],
|
|
23205
|
-
minOverlapMinutes: 2,
|
|
23206
|
-
audioOnlyMinMinutes: 15,
|
|
23207
|
-
mergeGapMinutes: 2
|
|
23216
|
+
// src/meetings/errors.ts
|
|
23217
|
+
var MeetingsInputError = class extends Error {
|
|
23218
|
+
constructor(message) {
|
|
23219
|
+
super(message);
|
|
23220
|
+
this.name = "MeetingsInputError";
|
|
23221
|
+
}
|
|
23208
23222
|
};
|
|
23209
|
-
|
|
23210
|
-
|
|
23211
|
-
|
|
23212
|
-
|
|
23213
|
-
|
|
23214
|
-
const [year, month, day, hour, minute, second] = m.slice(1).map(Number);
|
|
23215
|
-
const daysInMonth = month >= 1 && month <= 12 ? new Date(Date.UTC(year, month, 0)).getUTCDate() : 0;
|
|
23216
|
-
if (day < 1 || day > daysInMonth || hour > 23 || minute > 59 || second > 59) return Number.NaN;
|
|
23217
|
-
return Date.parse(iso);
|
|
23223
|
+
|
|
23224
|
+
// src/meetings/fuse.ts
|
|
23225
|
+
var SORT_STR = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
23226
|
+
function formatClockUtc(ms) {
|
|
23227
|
+
return new Date(ms).toISOString().slice(11, 16);
|
|
23218
23228
|
}
|
|
23219
23229
|
function overlapMs(aStart, aEnd, bStart, bEnd) {
|
|
23220
|
-
|
|
23221
|
-
|
|
23222
|
-
|
|
23223
|
-
|
|
23224
|
-
|
|
23225
|
-
|
|
23226
|
-
|
|
23227
|
-
|
|
23228
|
-
|
|
23229
|
-
|
|
23230
|
-
|
|
23231
|
-
|
|
23232
|
-
const
|
|
23233
|
-
const
|
|
23234
|
-
|
|
23235
|
-
|
|
23236
|
-
|
|
23237
|
-
|
|
23238
|
-
|
|
23239
|
-
|
|
23240
|
-
|
|
23241
|
-
|
|
23242
|
-
|
|
23243
|
-
|
|
23244
|
-
|
|
23245
|
-
|
|
23246
|
-
|
|
23247
|
-
|
|
23248
|
-
|
|
23249
|
-
|
|
23250
|
-
|
|
23251
|
-
|
|
23252
|
-
|
|
23253
|
-
|
|
23254
|
-
|
|
23255
|
-
|
|
23256
|
-
|
|
23257
|
-
|
|
23258
|
-
|
|
23230
|
+
return Math.max(0, Math.min(aEnd, bEnd) - Math.max(aStart, bStart));
|
|
23231
|
+
}
|
|
23232
|
+
function segmentInWindow(seg, windowStartMs, windowEndMs) {
|
|
23233
|
+
const startMs = seg.startIso === void 0 ? NaN : Date.parse(seg.startIso);
|
|
23234
|
+
if (Number.isNaN(startMs)) return null;
|
|
23235
|
+
const endParsed = seg.endIso === void 0 ? NaN : Date.parse(seg.endIso);
|
|
23236
|
+
const endMs = Number.isNaN(endParsed) ? startMs : endParsed;
|
|
23237
|
+
if (endMs === startMs) return startMs >= windowStartMs && startMs < windowEndMs;
|
|
23238
|
+
return overlapMs(startMs, endMs, windowStartMs, windowEndMs) > 0;
|
|
23239
|
+
}
|
|
23240
|
+
function clipConversation(conv, windowStartMs, windowEndMs) {
|
|
23241
|
+
const convStart = Date.parse(conv.startIso);
|
|
23242
|
+
const convEnd = conv.endIso === void 0 ? convStart : Date.parse(conv.endIso);
|
|
23243
|
+
const convOverlaps = Number.isFinite(convStart) && overlapMs(convStart, Number.isFinite(convEnd) ? convEnd : convStart, windowStartMs, windowEndMs) > 0;
|
|
23244
|
+
const kept = [];
|
|
23245
|
+
let earliestStart;
|
|
23246
|
+
let earliestIso;
|
|
23247
|
+
let latestEnd;
|
|
23248
|
+
let latestIso;
|
|
23249
|
+
for (const seg of conv.segments) {
|
|
23250
|
+
const decision = segmentInWindow(seg, windowStartMs, windowEndMs);
|
|
23251
|
+
if (decision === false || decision === null && !convOverlaps) continue;
|
|
23252
|
+
kept.push(seg);
|
|
23253
|
+
if (seg.startIso !== void 0) {
|
|
23254
|
+
const s = Date.parse(seg.startIso);
|
|
23255
|
+
if (Number.isFinite(s) && (earliestStart === void 0 || s < earliestStart)) {
|
|
23256
|
+
earliestStart = s;
|
|
23257
|
+
earliestIso = seg.startIso;
|
|
23258
|
+
}
|
|
23259
|
+
const endIso = seg.endIso ?? seg.startIso;
|
|
23260
|
+
const e = Date.parse(endIso);
|
|
23261
|
+
if (Number.isFinite(e) && (latestEnd === void 0 || e > latestEnd)) {
|
|
23262
|
+
latestEnd = e;
|
|
23263
|
+
latestIso = endIso;
|
|
23264
|
+
}
|
|
23265
|
+
}
|
|
23266
|
+
}
|
|
23267
|
+
if (kept.length === 0) return null;
|
|
23268
|
+
return {
|
|
23269
|
+
source: conv.source,
|
|
23270
|
+
conversationId: conv.conversationId,
|
|
23271
|
+
...conv.title !== void 0 ? { title: conv.title } : {},
|
|
23272
|
+
...conv.summary !== void 0 ? { summary: conv.summary } : {},
|
|
23273
|
+
startIso: earliestIso ?? conv.startIso,
|
|
23274
|
+
...latestIso !== void 0 ? { endIso: latestIso } : conv.endIso !== void 0 ? { endIso: conv.endIso } : {},
|
|
23275
|
+
segments: kept
|
|
23276
|
+
};
|
|
23277
|
+
}
|
|
23278
|
+
function shortenUrl(url) {
|
|
23279
|
+
return url.replace(/^[a-z]+:\/\//i, "");
|
|
23280
|
+
}
|
|
23281
|
+
function contextLabel(snap) {
|
|
23282
|
+
if (snap.url !== void 0 && snap.url.length > 0) return `${snap.app}: ${shortenUrl(snap.url)}`;
|
|
23283
|
+
if (snap.title !== void 0 && snap.title.length > 0) return `${snap.app}: ${snap.title}`;
|
|
23284
|
+
return snap.app;
|
|
23285
|
+
}
|
|
23286
|
+
function isMeetingAppSnapshot(snap, meetingApp, appPatterns) {
|
|
23287
|
+
const hay = `${snap.app} ${snap.title ?? ""} ${snap.url ?? ""}`.toLowerCase();
|
|
23288
|
+
if (meetingApp !== void 0 && meetingApp.length > 0 && hay.includes(meetingApp.toLowerCase())) {
|
|
23289
|
+
return true;
|
|
23290
|
+
}
|
|
23291
|
+
for (const pattern of appPatterns) {
|
|
23292
|
+
if (pattern.length > 0 && hay.includes(pattern.toLowerCase())) return true;
|
|
23293
|
+
}
|
|
23294
|
+
return false;
|
|
23295
|
+
}
|
|
23296
|
+
var MEETING_APP_KEY = "\0meeting-app";
|
|
23297
|
+
function buildScreenContext(activity, windowStartMs, windowEndMs, meetingApp, config) {
|
|
23298
|
+
const win = activity.map((snap) => ({ snap, ms: Date.parse(snap.tsUtc) })).filter((entry) => Number.isFinite(entry.ms) && entry.ms >= windowStartMs && entry.ms < windowEndMs).sort((a, b) => a.ms - b.ms || SORT_STR(a.snap.app, b.snap.app));
|
|
23299
|
+
const keyOf = (snap) => isMeetingAppSnapshot(snap, meetingApp, config.appPatterns) ? MEETING_APP_KEY : `${snap.app}\0${snap.url ?? snap.title ?? ""}`;
|
|
23300
|
+
const events = [];
|
|
23301
|
+
const includedText = [];
|
|
23302
|
+
let runStartIdx = 0;
|
|
23303
|
+
while (runStartIdx < win.length) {
|
|
23304
|
+
const key = keyOf(win[runStartIdx].snap);
|
|
23305
|
+
let runEndIdx = runStartIdx + 1;
|
|
23306
|
+
while (runEndIdx < win.length && keyOf(win[runEndIdx].snap) === key) runEndIdx++;
|
|
23307
|
+
const runStartMs = win[runStartIdx].ms;
|
|
23308
|
+
const runEndMs = runEndIdx < win.length ? win[runEndIdx].ms : win[runEndIdx - 1].ms;
|
|
23309
|
+
const dwellSeconds = Math.floor((runEndMs - runStartMs) / 1e3);
|
|
23310
|
+
const head = win[runStartIdx].snap;
|
|
23311
|
+
const isMeetingApp = key === MEETING_APP_KEY;
|
|
23312
|
+
if (isMeetingApp) {
|
|
23313
|
+
for (let i = runStartIdx; i < runEndIdx; i++) {
|
|
23314
|
+
const text = win[i].snap.text;
|
|
23315
|
+
if (text !== void 0 && text.trim().length > 0) includedText.push(text.trim());
|
|
23316
|
+
}
|
|
23317
|
+
} else if (dwellSeconds >= config.contextDwellSeconds) {
|
|
23318
|
+
events.push({
|
|
23319
|
+
tsUtc: new Date(runStartMs).toISOString(),
|
|
23320
|
+
clock: formatClockUtc(runStartMs),
|
|
23321
|
+
app: head.app,
|
|
23322
|
+
label: contextLabel(head),
|
|
23323
|
+
dwellSeconds
|
|
23259
23324
|
});
|
|
23260
|
-
|
|
23325
|
+
for (let i = runStartIdx; i < runEndIdx; i++) {
|
|
23326
|
+
const text = win[i].snap.text;
|
|
23327
|
+
if (text !== void 0 && text.trim().length > 0) includedText.push(text.trim());
|
|
23328
|
+
}
|
|
23261
23329
|
}
|
|
23262
|
-
|
|
23263
|
-
|
|
23264
|
-
|
|
23265
|
-
|
|
23266
|
-
|
|
23267
|
-
|
|
23268
|
-
|
|
23269
|
-
|
|
23270
|
-
|
|
23271
|
-
|
|
23272
|
-
|
|
23273
|
-
|
|
23274
|
-
|
|
23275
|
-
|
|
23276
|
-
|
|
23277
|
-
|
|
23278
|
-
|
|
23279
|
-
|
|
23280
|
-
|
|
23281
|
-
|
|
23282
|
-
|
|
23283
|
-
|
|
23284
|
-
|
|
23285
|
-
|
|
23330
|
+
runStartIdx = runEndIdx;
|
|
23331
|
+
}
|
|
23332
|
+
const excerpts = [];
|
|
23333
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23334
|
+
let used = 0;
|
|
23335
|
+
for (const text of includedText) {
|
|
23336
|
+
if (seen.has(text)) continue;
|
|
23337
|
+
if (used + text.length > config.maxContextChars) break;
|
|
23338
|
+
seen.add(text);
|
|
23339
|
+
excerpts.push(text);
|
|
23340
|
+
used += text.length;
|
|
23341
|
+
}
|
|
23342
|
+
return { events, excerpts, snapshotCount: win.length };
|
|
23343
|
+
}
|
|
23344
|
+
function fuseMeeting(input, config, options = {}) {
|
|
23345
|
+
const windowStartMs = Date.parse(input.meeting.startUtc);
|
|
23346
|
+
const windowEndMs = Date.parse(input.meeting.endUtc);
|
|
23347
|
+
if (!Number.isFinite(windowStartMs) || !Number.isFinite(windowEndMs) || windowEndMs <= windowStartMs) {
|
|
23348
|
+
throw new RangeError(
|
|
23349
|
+
`meetings: meeting ${input.meeting.id} has an invalid window [${input.meeting.startUtc}, ${input.meeting.endUtc}).`
|
|
23350
|
+
);
|
|
23351
|
+
}
|
|
23352
|
+
const clipped = [];
|
|
23353
|
+
for (const conv of input.conversations) {
|
|
23354
|
+
const clip = clipConversation(conv, windowStartMs, windowEndMs);
|
|
23355
|
+
if (clip !== null) clipped.push(clip);
|
|
23356
|
+
}
|
|
23357
|
+
const fused = clipped.length > 0 ? fuseCluster(clipped, {
|
|
23358
|
+
...options.sourceTrust !== void 0 ? { sourceTrust: options.sourceTrust } : {},
|
|
23359
|
+
...options.windowToleranceMs !== void 0 ? { windowToleranceMs: options.windowToleranceMs } : {}
|
|
23360
|
+
}) : { sources: [], speakers: [], segments: [], disagreements: [], startIso: input.meeting.startUtc };
|
|
23361
|
+
const corroborated = /* @__PURE__ */ new Set();
|
|
23362
|
+
for (const segment of fused.segments) {
|
|
23363
|
+
for (const alt of segment.provenance.alternatives) {
|
|
23364
|
+
if (alt.source === segment.provenance.source) continue;
|
|
23365
|
+
corroborated.add(alt.source);
|
|
23366
|
+
}
|
|
23367
|
+
}
|
|
23368
|
+
const attendees = /* @__PURE__ */ new Set();
|
|
23369
|
+
for (const speaker of fused.speakers) {
|
|
23370
|
+
if (!speaker.isSelf) attendees.add(speaker.label);
|
|
23371
|
+
}
|
|
23372
|
+
const screen = buildScreenContext(
|
|
23373
|
+
input.activity ?? [],
|
|
23374
|
+
windowStartMs,
|
|
23375
|
+
windowEndMs,
|
|
23376
|
+
input.meeting.app,
|
|
23377
|
+
config
|
|
23378
|
+
);
|
|
23379
|
+
return {
|
|
23380
|
+
attendees: [...attendees].sort(SORT_STR),
|
|
23381
|
+
sources: [...fused.sources].sort(SORT_STR),
|
|
23382
|
+
corroboratedBy: [...corroborated].sort(SORT_STR),
|
|
23383
|
+
screenContext: screen.events,
|
|
23384
|
+
contextExcerpts: screen.excerpts,
|
|
23385
|
+
transcript: fused.segments,
|
|
23386
|
+
speakers: fused.speakers,
|
|
23387
|
+
snapshotCount: screen.snapshotCount
|
|
23388
|
+
};
|
|
23389
|
+
}
|
|
23390
|
+
|
|
23391
|
+
// src/meetings/store.ts
|
|
23392
|
+
import { createHash as createHash9 } from "crypto";
|
|
23393
|
+
import * as path29 from "path";
|
|
23394
|
+
var MEETINGS_DIR_NAME = "meetings";
|
|
23395
|
+
var MEETING_KIND = "meeting";
|
|
23396
|
+
var MEETING_FORMAT_VERSION = 1;
|
|
23397
|
+
var MEETING_ID_PATTERN = /^mtg-(\d{4}-\d{2}-\d{2})-[0-9a-f]{8}$/;
|
|
23398
|
+
function meetingIdDate(id) {
|
|
23399
|
+
const match = MEETING_ID_PATTERN.exec(id);
|
|
23400
|
+
return match === null ? null : match[1];
|
|
23401
|
+
}
|
|
23402
|
+
function canonicalContent(base, fused) {
|
|
23403
|
+
return JSON.stringify({
|
|
23404
|
+
formatVersion: MEETING_FORMAT_VERSION,
|
|
23405
|
+
id: base.id,
|
|
23406
|
+
date: base.date,
|
|
23407
|
+
startUtc: base.startUtc,
|
|
23408
|
+
endUtc: base.endUtc,
|
|
23409
|
+
app: base.app ?? null,
|
|
23410
|
+
detectionSource: base.detectionSource,
|
|
23411
|
+
title: base.title ?? null,
|
|
23412
|
+
attendees: fused.attendees,
|
|
23413
|
+
sources: fused.sources,
|
|
23414
|
+
corroboratedBy: fused.corroboratedBy,
|
|
23415
|
+
screenContext: fused.screenContext,
|
|
23416
|
+
contextExcerpts: fused.contextExcerpts,
|
|
23417
|
+
transcript: fused.transcript,
|
|
23418
|
+
speakers: fused.speakers,
|
|
23419
|
+
snapshotCount: fused.snapshotCount
|
|
23420
|
+
});
|
|
23421
|
+
}
|
|
23422
|
+
function composeMeetingRecord(base, fused) {
|
|
23423
|
+
const contentHash = createHash9("sha256").update(canonicalContent(base, fused), "utf-8").digest("hex");
|
|
23424
|
+
return {
|
|
23425
|
+
...base,
|
|
23426
|
+
...fused,
|
|
23427
|
+
contentHash,
|
|
23428
|
+
formatVersion: MEETING_FORMAT_VERSION
|
|
23429
|
+
};
|
|
23430
|
+
}
|
|
23431
|
+
function formatClockUtc2(iso) {
|
|
23432
|
+
const ms = Date.parse(iso);
|
|
23433
|
+
if (Number.isNaN(ms)) return "--:--";
|
|
23434
|
+
return new Date(ms).toISOString().slice(11, 16);
|
|
23435
|
+
}
|
|
23436
|
+
function renderTranscriptLine(segment) {
|
|
23437
|
+
const clock = formatClockUtc2(segment.startIso ?? "");
|
|
23438
|
+
return `**${escapeSpeakerLabel(segment.speaker)}** [${clock}]: ${escapeSegmentText(segment.text)}`;
|
|
23439
|
+
}
|
|
23440
|
+
function frontmatterList(key, values) {
|
|
23441
|
+
if (values.length === 0) return [`${key}: []`];
|
|
23442
|
+
const lines = [`${key}:`];
|
|
23443
|
+
for (const value of values) lines.push(` - ${JSON.stringify(value)}`);
|
|
23444
|
+
return lines;
|
|
23445
|
+
}
|
|
23446
|
+
function serializeMeetingRecord(record) {
|
|
23447
|
+
const lines = ["---"];
|
|
23448
|
+
lines.push(`kind: ${MEETING_KIND}`);
|
|
23449
|
+
lines.push(`formatVersion: ${record.formatVersion}`);
|
|
23450
|
+
lines.push(`id: ${JSON.stringify(record.id)}`);
|
|
23451
|
+
lines.push(`date: ${JSON.stringify(record.date)}`);
|
|
23452
|
+
lines.push(`startUtc: ${JSON.stringify(record.startUtc)}`);
|
|
23453
|
+
lines.push(`endUtc: ${JSON.stringify(record.endUtc)}`);
|
|
23454
|
+
if (record.app !== void 0) lines.push(`app: ${JSON.stringify(record.app)}`);
|
|
23455
|
+
lines.push(`detectionSource: ${JSON.stringify(record.detectionSource)}`);
|
|
23456
|
+
if (record.title !== void 0) lines.push(`title: ${JSON.stringify(record.title)}`);
|
|
23457
|
+
lines.push(...frontmatterList("attendees", record.attendees));
|
|
23458
|
+
lines.push(...frontmatterList("sources", record.sources));
|
|
23459
|
+
lines.push(...frontmatterList("corroboratedBy", record.corroboratedBy));
|
|
23460
|
+
lines.push(`snapshotCount: ${record.snapshotCount}`);
|
|
23461
|
+
lines.push(`contentHash: ${JSON.stringify(record.contentHash)}`);
|
|
23462
|
+
lines.push("---");
|
|
23463
|
+
lines.push("");
|
|
23464
|
+
const heading = record.title !== void 0 && record.title.length > 0 ? ` \xB7 ${record.title}` : "";
|
|
23465
|
+
lines.push(`# Meeting ${record.id}${heading}`);
|
|
23466
|
+
lines.push("");
|
|
23467
|
+
lines.push("## Attendees");
|
|
23468
|
+
lines.push("");
|
|
23469
|
+
if (record.attendees.length === 0) {
|
|
23470
|
+
lines.push("_None resolved._");
|
|
23471
|
+
} else {
|
|
23472
|
+
for (const attendee of record.attendees) lines.push(`- ${attendee}`);
|
|
23473
|
+
}
|
|
23474
|
+
lines.push("");
|
|
23475
|
+
if (record.screenContext.length > 0 || record.contextExcerpts.length > 0) {
|
|
23476
|
+
lines.push("## Screen context");
|
|
23477
|
+
lines.push("");
|
|
23478
|
+
for (const event of record.screenContext) {
|
|
23479
|
+
lines.push(`- [${event.clock}] ${event.label}`);
|
|
23480
|
+
}
|
|
23481
|
+
if (record.contextExcerpts.length > 0) {
|
|
23482
|
+
if (record.screenContext.length > 0) lines.push("");
|
|
23483
|
+
lines.push("Notable excerpts:");
|
|
23484
|
+
lines.push("");
|
|
23485
|
+
for (const excerpt of record.contextExcerpts) lines.push(`> ${excerpt.replace(/\n/g, " ")}`);
|
|
23486
|
+
}
|
|
23487
|
+
lines.push("");
|
|
23488
|
+
}
|
|
23489
|
+
lines.push("## Transcript");
|
|
23490
|
+
lines.push("");
|
|
23491
|
+
if (record.transcript.length === 0) {
|
|
23492
|
+
lines.push("_No transcript segments in this window._");
|
|
23493
|
+
} else {
|
|
23494
|
+
for (const segment of record.transcript) lines.push(renderTranscriptLine(segment));
|
|
23495
|
+
}
|
|
23496
|
+
lines.push("");
|
|
23497
|
+
return `${lines.join("\n")}`;
|
|
23498
|
+
}
|
|
23499
|
+
function parseScalar(value) {
|
|
23500
|
+
const trimmed = value.trim();
|
|
23501
|
+
if (trimmed.startsWith('"')) {
|
|
23502
|
+
try {
|
|
23503
|
+
return JSON.parse(trimmed);
|
|
23504
|
+
} catch {
|
|
23505
|
+
return trimmed;
|
|
23506
|
+
}
|
|
23507
|
+
}
|
|
23508
|
+
return trimmed;
|
|
23509
|
+
}
|
|
23510
|
+
function parseMeetingRecordSummary(raw) {
|
|
23511
|
+
if (!raw.startsWith("---\n")) return null;
|
|
23512
|
+
const closeIndex = raw.indexOf("\n---\n", 4);
|
|
23513
|
+
if (closeIndex === -1) return null;
|
|
23514
|
+
const frontmatter = raw.slice(4, closeIndex).split("\n");
|
|
23515
|
+
const scalars = {};
|
|
23516
|
+
const lists = {};
|
|
23517
|
+
let currentList = null;
|
|
23518
|
+
for (const line of frontmatter) {
|
|
23519
|
+
const listItem = /^ {2}- (.*)$/.exec(line);
|
|
23520
|
+
if (listItem !== null && currentList !== null) {
|
|
23521
|
+
lists[currentList].push(parseScalar(listItem[1]));
|
|
23286
23522
|
continue;
|
|
23287
23523
|
}
|
|
23288
|
-
|
|
23289
|
-
|
|
23290
|
-
|
|
23291
|
-
|
|
23292
|
-
|
|
23293
|
-
|
|
23294
|
-
|
|
23295
|
-
|
|
23524
|
+
const kv = /^([A-Za-z][A-Za-z0-9]*):\s*(.*)$/.exec(line);
|
|
23525
|
+
if (kv === null) continue;
|
|
23526
|
+
const key = kv[1];
|
|
23527
|
+
const value = kv[2];
|
|
23528
|
+
if (value === "") {
|
|
23529
|
+
currentList = key;
|
|
23530
|
+
lists[key] = [];
|
|
23531
|
+
} else if (value === "[]") {
|
|
23532
|
+
currentList = null;
|
|
23533
|
+
lists[key] = [];
|
|
23534
|
+
} else {
|
|
23535
|
+
currentList = null;
|
|
23536
|
+
scalars[key] = value;
|
|
23296
23537
|
}
|
|
23297
23538
|
}
|
|
23298
|
-
return
|
|
23539
|
+
if (scalars.kind !== void 0 && parseScalar(scalars.kind) !== MEETING_KIND) return null;
|
|
23540
|
+
const id = scalars.id !== void 0 ? parseScalar(scalars.id) : void 0;
|
|
23541
|
+
const contentHash = scalars.contentHash !== void 0 ? parseScalar(scalars.contentHash) : void 0;
|
|
23542
|
+
if (id === void 0 || contentHash === void 0) return null;
|
|
23543
|
+
return {
|
|
23544
|
+
id,
|
|
23545
|
+
date: scalars.date !== void 0 ? parseScalar(scalars.date) : "",
|
|
23546
|
+
startUtc: scalars.startUtc !== void 0 ? parseScalar(scalars.startUtc) : "",
|
|
23547
|
+
endUtc: scalars.endUtc !== void 0 ? parseScalar(scalars.endUtc) : "",
|
|
23548
|
+
...scalars.app !== void 0 ? { app: parseScalar(scalars.app) } : {},
|
|
23549
|
+
detectionSource: scalars.detectionSource !== void 0 ? parseScalar(scalars.detectionSource) : "",
|
|
23550
|
+
...scalars.title !== void 0 ? { title: parseScalar(scalars.title) } : {},
|
|
23551
|
+
attendees: lists.attendees ?? [],
|
|
23552
|
+
sources: lists.sources ?? [],
|
|
23553
|
+
corroboratedBy: lists.corroboratedBy ?? [],
|
|
23554
|
+
snapshotCount: scalars.snapshotCount !== void 0 ? Number(scalars.snapshotCount) || 0 : 0,
|
|
23555
|
+
contentHash
|
|
23556
|
+
};
|
|
23299
23557
|
}
|
|
23300
|
-
var
|
|
23301
|
-
|
|
23302
|
-
|
|
23303
|
-
|
|
23558
|
+
var MeetingRecordStore = class {
|
|
23559
|
+
constructor(memoryDir, io) {
|
|
23560
|
+
this.memoryDir = memoryDir;
|
|
23561
|
+
this.io = io;
|
|
23562
|
+
this.meetingsDir = path29.join(memoryDir, MEETINGS_DIR_NAME);
|
|
23563
|
+
}
|
|
23564
|
+
memoryDir;
|
|
23565
|
+
io;
|
|
23566
|
+
meetingsDir;
|
|
23567
|
+
recordPath(date, id) {
|
|
23568
|
+
if (!isValidTranscriptDate(date)) {
|
|
23569
|
+
throw new Error(`invalid meeting date '${String(date)}' \u2014 expected YYYY-MM-DD`);
|
|
23570
|
+
}
|
|
23571
|
+
const idDate = meetingIdDate(id);
|
|
23572
|
+
if (idDate === null) {
|
|
23573
|
+
throw new Error(`invalid meeting id '${String(id)}' \u2014 expected mtg-YYYY-MM-DD-<hash>`);
|
|
23574
|
+
}
|
|
23575
|
+
if (idDate !== date) {
|
|
23576
|
+
throw new Error(`meeting id '${id}' does not belong to date '${date}'`);
|
|
23577
|
+
}
|
|
23578
|
+
return path29.join(this.meetingsDir, date, `${id}.md`);
|
|
23579
|
+
}
|
|
23580
|
+
/** Idempotently persist a record: skip the write when contentHash is unchanged. */
|
|
23581
|
+
async saveMeetingRecord(record) {
|
|
23582
|
+
const filePath = this.recordPath(record.date, record.id);
|
|
23583
|
+
await this.assertPathContained(filePath);
|
|
23584
|
+
const existing = await this.readRaw(filePath);
|
|
23585
|
+
if (existing !== null) {
|
|
23586
|
+
const summary = parseMeetingRecordSummary(existing);
|
|
23587
|
+
if (summary !== null && summary.contentHash === record.contentHash) {
|
|
23588
|
+
return { path: filePath, written: false, contentHash: record.contentHash };
|
|
23589
|
+
}
|
|
23590
|
+
}
|
|
23591
|
+
await this.io.writeFile(filePath, serializeMeetingRecord(record));
|
|
23592
|
+
return { path: filePath, written: true, contentHash: record.contentHash };
|
|
23593
|
+
}
|
|
23594
|
+
/** Read a stored record's raw markdown; null when absent. */
|
|
23595
|
+
async readMeetingRecord(date, id) {
|
|
23596
|
+
const filePath = this.recordPath(date, id);
|
|
23597
|
+
await this.assertPathContained(filePath);
|
|
23598
|
+
return this.readRaw(filePath);
|
|
23599
|
+
}
|
|
23600
|
+
/**
|
|
23601
|
+
* Read + parse every stored record for a day exactly ONCE, sorted by start
|
|
23602
|
+
* time (ascending, id tiebreak). The single day-read path both `listMeetingIds`
|
|
23603
|
+
* and `listMeetingSummaries` derive from — no record is read twice.
|
|
23604
|
+
*/
|
|
23605
|
+
async readDaySummaries(date) {
|
|
23606
|
+
if (!isValidTranscriptDate(date)) {
|
|
23607
|
+
throw new Error(`invalid meeting date '${String(date)}' \u2014 expected YYYY-MM-DD`);
|
|
23608
|
+
}
|
|
23609
|
+
const dayDir = path29.join(this.meetingsDir, date);
|
|
23610
|
+
await this.assertPathContained(dayDir);
|
|
23611
|
+
let entries;
|
|
23612
|
+
try {
|
|
23613
|
+
entries = await this.io.readDir(dayDir);
|
|
23614
|
+
} catch (err) {
|
|
23615
|
+
if (err.code === "ENOENT") return [];
|
|
23616
|
+
throw err;
|
|
23617
|
+
}
|
|
23618
|
+
const summaries = [];
|
|
23619
|
+
for (const entry of entries) {
|
|
23620
|
+
if (!entry.endsWith(".md")) continue;
|
|
23621
|
+
const id = entry.slice(0, -3);
|
|
23622
|
+
if (meetingIdDate(id) !== date) continue;
|
|
23623
|
+
const raw = await this.readMeetingRecord(date, id);
|
|
23624
|
+
if (raw === null) continue;
|
|
23625
|
+
const summary = parseMeetingRecordSummary(raw);
|
|
23626
|
+
if (summary !== null) summaries.push(summary);
|
|
23627
|
+
}
|
|
23628
|
+
summaries.sort((a, b) => a.startUtc < b.startUtc ? -1 : a.startUtc > b.startUtc ? 1 : SORT_STR2(a.id, b.id));
|
|
23629
|
+
return summaries;
|
|
23630
|
+
}
|
|
23631
|
+
/** List meeting ids stored for a day, sorted by start time (ascending). */
|
|
23632
|
+
async listMeetingIds(date) {
|
|
23633
|
+
return (await this.readDaySummaries(date)).map((summary) => summary.id);
|
|
23634
|
+
}
|
|
23635
|
+
/** Read parsed summaries for a day, sorted by start time. */
|
|
23636
|
+
async listMeetingSummaries(date) {
|
|
23637
|
+
return this.readDaySummaries(date);
|
|
23638
|
+
}
|
|
23639
|
+
/** List dates that have at least one stored meeting record, newest first. */
|
|
23640
|
+
async listMeetingDates() {
|
|
23641
|
+
await this.assertPathContained(this.meetingsDir);
|
|
23642
|
+
let entries;
|
|
23643
|
+
try {
|
|
23644
|
+
entries = await this.io.readDir(this.meetingsDir);
|
|
23645
|
+
} catch (err) {
|
|
23646
|
+
if (err.code === "ENOENT") return [];
|
|
23647
|
+
throw err;
|
|
23648
|
+
}
|
|
23649
|
+
const dates = entries.filter((entry) => isValidTranscriptDate(entry));
|
|
23650
|
+
dates.sort((a, b) => a > b ? -1 : a < b ? 1 : 0);
|
|
23651
|
+
return dates;
|
|
23652
|
+
}
|
|
23653
|
+
/** Remove a stored record. Idempotent: a no-op when already absent. */
|
|
23654
|
+
async deleteMeetingRecord(date, id) {
|
|
23655
|
+
const filePath = this.recordPath(date, id);
|
|
23656
|
+
await this.assertPathContained(filePath);
|
|
23657
|
+
try {
|
|
23658
|
+
await this.io.deleteFile(filePath);
|
|
23659
|
+
} catch (err) {
|
|
23660
|
+
if (err.code === "ENOENT") return;
|
|
23661
|
+
throw err;
|
|
23662
|
+
}
|
|
23663
|
+
}
|
|
23664
|
+
async readRaw(filePath) {
|
|
23665
|
+
try {
|
|
23666
|
+
return await this.io.readFile(filePath);
|
|
23667
|
+
} catch (err) {
|
|
23668
|
+
if (err.code === "ENOENT") return null;
|
|
23669
|
+
throw err;
|
|
23670
|
+
}
|
|
23671
|
+
}
|
|
23672
|
+
async assertPathContained(targetPath) {
|
|
23673
|
+
let rootReal;
|
|
23674
|
+
try {
|
|
23675
|
+
rootReal = await this.io.realpath(this.memoryDir);
|
|
23676
|
+
} catch {
|
|
23677
|
+
rootReal = path29.resolve(this.memoryDir);
|
|
23678
|
+
}
|
|
23679
|
+
await this.assertNoEscape(rootReal, this.meetingsDir);
|
|
23680
|
+
await this.assertNoEscape(rootReal, path29.dirname(targetPath));
|
|
23681
|
+
await this.assertNoEscape(rootReal, targetPath);
|
|
23682
|
+
await this.assertNotSymlink(this.meetingsDir, "directory");
|
|
23683
|
+
const dayDir = this.dayDirWithin(targetPath);
|
|
23684
|
+
if (dayDir !== null) await this.assertNotSymlink(dayDir, "directory");
|
|
23685
|
+
if (targetPath.endsWith(".md")) await this.assertNotSymlink(targetPath, "record file");
|
|
23686
|
+
}
|
|
23687
|
+
/** The `<meetings>/<date>` directory on the path to `targetPath`, or null when
|
|
23688
|
+
* `targetPath` is the meetings root itself. */
|
|
23689
|
+
dayDirWithin(targetPath) {
|
|
23690
|
+
const rel = path29.relative(this.meetingsDir, targetPath);
|
|
23691
|
+
if (rel === "" || rel.startsWith("..") || path29.isAbsolute(rel)) return null;
|
|
23692
|
+
const first = rel.split(path29.sep)[0];
|
|
23693
|
+
if (first === void 0 || first.length === 0) return null;
|
|
23694
|
+
return path29.join(this.meetingsDir, first);
|
|
23695
|
+
}
|
|
23696
|
+
async assertNotSymlink(target, kind) {
|
|
23697
|
+
let stat5;
|
|
23698
|
+
try {
|
|
23699
|
+
stat5 = await this.io.lstat(target);
|
|
23700
|
+
} catch (err) {
|
|
23701
|
+
if (err.code === "ENOENT") return;
|
|
23702
|
+
throw err;
|
|
23703
|
+
}
|
|
23704
|
+
if (stat5.isSymbolicLink) {
|
|
23705
|
+
const label = path29.relative(this.memoryDir, target) || MEETINGS_DIR_NAME;
|
|
23706
|
+
throw new Error(
|
|
23707
|
+
`meetings ${kind} '${label}' is a symbolic link \u2014 refusing to follow it even when it resolves inside the memory dir (AGENTS.md pattern #3)`
|
|
23708
|
+
);
|
|
23709
|
+
}
|
|
23710
|
+
}
|
|
23711
|
+
async assertNoEscape(rootReal, candidate) {
|
|
23712
|
+
let candidateReal;
|
|
23713
|
+
try {
|
|
23714
|
+
candidateReal = await this.io.realpath(candidate);
|
|
23715
|
+
} catch {
|
|
23716
|
+
return;
|
|
23717
|
+
}
|
|
23718
|
+
if (!pathIsInside(rootReal, candidateReal)) {
|
|
23719
|
+
throw new Error(
|
|
23720
|
+
"meeting record path resolves outside the memory dir \u2014 refusing to follow a symlink/traversal (AGENTS.md pattern #3)"
|
|
23721
|
+
);
|
|
23722
|
+
}
|
|
23723
|
+
}
|
|
23304
23724
|
};
|
|
23305
|
-
|
|
23306
|
-
|
|
23307
|
-
|
|
23308
|
-
function
|
|
23309
|
-
const
|
|
23310
|
-
|
|
23311
|
-
|
|
23312
|
-
|
|
23313
|
-
|
|
23314
|
-
|
|
23315
|
-
|
|
23316
|
-
|
|
23317
|
-
|
|
23318
|
-
|
|
23319
|
-
|
|
23320
|
-
|
|
23725
|
+
var SORT_STR2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
23726
|
+
|
|
23727
|
+
// src/meetings/build.ts
|
|
23728
|
+
function buildMeetingRecordsForDay(data, config, options = {}, resolveMeetingId = (meeting) => meeting.id) {
|
|
23729
|
+
const meetings = detectMeetings(data.detection, {
|
|
23730
|
+
appPatterns: config.appPatterns,
|
|
23731
|
+
minOverlapMinutes: config.minOverlapMinutes,
|
|
23732
|
+
audioOnlyMinMinutes: config.audioOnlyMinMinutes,
|
|
23733
|
+
mergeGapMinutes: config.mergeGapMinutes
|
|
23734
|
+
});
|
|
23735
|
+
return meetings.map((meeting) => {
|
|
23736
|
+
const fused = fuseMeeting(
|
|
23737
|
+
{ meeting, conversations: data.conversations, ...data.activity !== void 0 ? { activity: data.activity } : {} },
|
|
23738
|
+
config,
|
|
23739
|
+
options
|
|
23740
|
+
);
|
|
23741
|
+
return composeMeetingRecord(
|
|
23742
|
+
{
|
|
23743
|
+
id: resolveMeetingId(meeting),
|
|
23744
|
+
date: meeting.date,
|
|
23745
|
+
startUtc: meeting.startUtc,
|
|
23746
|
+
endUtc: meeting.endUtc,
|
|
23747
|
+
...meeting.app !== void 0 ? { app: meeting.app } : {},
|
|
23748
|
+
detectionSource: meeting.detectionSource,
|
|
23749
|
+
...meeting.title !== void 0 ? { title: meeting.title } : {}
|
|
23750
|
+
},
|
|
23751
|
+
fused
|
|
23752
|
+
);
|
|
23753
|
+
});
|
|
23754
|
+
}
|
|
23755
|
+
var MeetingsBuilder = class {
|
|
23756
|
+
constructor(opts) {
|
|
23757
|
+
this.opts = opts;
|
|
23758
|
+
}
|
|
23759
|
+
opts;
|
|
23760
|
+
async buildDay(date) {
|
|
23761
|
+
if (!this.opts.config.enabled) {
|
|
23762
|
+
return { date, enabled: false, meetings: [], built: 0, skipped: 0, removed: [] };
|
|
23763
|
+
}
|
|
23764
|
+
const data = await this.opts.source.loadDayData(date);
|
|
23765
|
+
if (data.detection.date !== date) {
|
|
23766
|
+
throw new RangeError(
|
|
23767
|
+
`meetings: day source returned detection.date "${data.detection.date}" for requested day "${date}".`
|
|
23768
|
+
);
|
|
23769
|
+
}
|
|
23770
|
+
const existing = await this.opts.store.listMeetingSummaries(date);
|
|
23771
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
23772
|
+
const resolveMeetingId = (meeting) => this.adoptExistingId(meeting, existing, claimed);
|
|
23773
|
+
const records = buildMeetingRecordsForDay(
|
|
23774
|
+
data,
|
|
23775
|
+
this.opts.config,
|
|
23776
|
+
this.opts.fusionOptions ?? {},
|
|
23777
|
+
resolveMeetingId
|
|
23778
|
+
);
|
|
23779
|
+
const meetings = [];
|
|
23780
|
+
let built = 0;
|
|
23781
|
+
let skipped = 0;
|
|
23782
|
+
const builtIds = /* @__PURE__ */ new Set();
|
|
23783
|
+
const priorIds = new Set(existing.map((summary2) => summary2.id));
|
|
23784
|
+
const unchangedIds = [];
|
|
23785
|
+
const updatedIds = [];
|
|
23786
|
+
for (const record of records) {
|
|
23787
|
+
const save = await this.opts.store.saveMeetingRecord(record);
|
|
23788
|
+
if (save.written) {
|
|
23789
|
+
built++;
|
|
23790
|
+
if (priorIds.has(record.id)) updatedIds.push(record.id);
|
|
23791
|
+
} else {
|
|
23792
|
+
skipped++;
|
|
23793
|
+
unchangedIds.push(record.id);
|
|
23794
|
+
}
|
|
23795
|
+
builtIds.add(record.id);
|
|
23796
|
+
meetings.push({
|
|
23797
|
+
id: record.id,
|
|
23798
|
+
startUtc: record.startUtc,
|
|
23799
|
+
endUtc: record.endUtc,
|
|
23800
|
+
detectionSource: record.detectionSource,
|
|
23801
|
+
sources: record.sources,
|
|
23802
|
+
attendees: record.attendees,
|
|
23803
|
+
snapshotCount: record.snapshotCount,
|
|
23804
|
+
written: save.written
|
|
23805
|
+
});
|
|
23806
|
+
}
|
|
23807
|
+
const removed = [];
|
|
23808
|
+
for (const existingId of await this.opts.store.listMeetingIds(date)) {
|
|
23809
|
+
if (builtIds.has(existingId)) continue;
|
|
23810
|
+
await this.opts.store.deleteMeetingRecord(date, existingId);
|
|
23811
|
+
removed.push(existingId);
|
|
23812
|
+
}
|
|
23813
|
+
const summary = { date, enabled: true, meetings, built, skipped, removed };
|
|
23814
|
+
let outcome;
|
|
23815
|
+
if (this.opts.memoryGenerator !== void 0) {
|
|
23816
|
+
try {
|
|
23817
|
+
outcome = await this.opts.memoryGenerator.onRecordsBuilt({
|
|
23818
|
+
built: records,
|
|
23819
|
+
removedIds: removed,
|
|
23820
|
+
unchangedIds,
|
|
23821
|
+
updatedIds
|
|
23822
|
+
});
|
|
23823
|
+
} catch (err) {
|
|
23824
|
+
log.error("meetings: memory generation failed after records were persisted", err);
|
|
23825
|
+
summary.memoryWarning = "memory generation failed after records were persisted; see logs for detail";
|
|
23826
|
+
}
|
|
23827
|
+
}
|
|
23828
|
+
if (outcome?.episodes !== void 0) summary.episodes = outcome.episodes;
|
|
23829
|
+
if (outcome?.facts !== void 0) summary.facts = outcome.facts;
|
|
23830
|
+
if (outcome?.warnings !== void 0 && outcome.warnings.length > 0) {
|
|
23831
|
+
summary.memoryWarning = outcome.warnings.join("; ");
|
|
23832
|
+
}
|
|
23833
|
+
if (built > 0 || removed.length > 0 || (outcome?.reindexNeeded ?? false)) {
|
|
23834
|
+
try {
|
|
23835
|
+
await this.opts.hooks?.reindex?.(summary);
|
|
23836
|
+
} catch (err) {
|
|
23837
|
+
log.error("meetings: reindex hook failed after records were persisted", err);
|
|
23838
|
+
summary.reindexWarning = "reindex hook failed after records were persisted; see logs for detail";
|
|
23839
|
+
}
|
|
23840
|
+
}
|
|
23841
|
+
return summary;
|
|
23842
|
+
}
|
|
23843
|
+
/**
|
|
23844
|
+
* Pick the existing same-day record whose window best overlaps `meeting` and
|
|
23845
|
+
* reuse its id — but ONLY when adoption is safe: the windows substantially
|
|
23846
|
+
* coincide (overlap covers a majority of the shorter window), OR a corroborating
|
|
23847
|
+
* identity signal (same app, same title, or a shared transcript source) is
|
|
23848
|
+
* BACKED by a non-marginal overlap (>= a quarter of the shorter window). Coarse
|
|
23849
|
+
* identity signals alone never license adoption across a thin sliver of overlap,
|
|
23850
|
+
* or two genuinely different back-to-back same-app meetings would overwrite each
|
|
23851
|
+
* other's record and `show <old-id>` would point at the wrong meeting. Candidate
|
|
23852
|
+
* selection is deterministic (max overlap, then earliest start, then id).
|
|
23853
|
+
* Returns the detector's fresh id when nothing qualifies.
|
|
23854
|
+
*/
|
|
23855
|
+
adoptExistingId(meeting, existing, claimed) {
|
|
23856
|
+
const dStart = Date.parse(meeting.startUtc);
|
|
23857
|
+
const dEnd = Date.parse(meeting.endUtc);
|
|
23858
|
+
if (!Number.isFinite(dStart) || !Number.isFinite(dEnd)) return meeting.id;
|
|
23859
|
+
let best;
|
|
23860
|
+
for (const record of existing) {
|
|
23861
|
+
if (claimed.has(record.id)) continue;
|
|
23862
|
+
const eStart = Date.parse(record.startUtc);
|
|
23863
|
+
const eEnd = Date.parse(record.endUtc);
|
|
23864
|
+
if (!Number.isFinite(eStart) || !Number.isFinite(eEnd)) continue;
|
|
23865
|
+
const overlap = Math.min(dEnd, eEnd) - Math.max(dStart, eStart);
|
|
23866
|
+
if (overlap <= 0) continue;
|
|
23867
|
+
const better = best === void 0 || overlap > best.overlap || overlap === best.overlap && (record.startUtc < best.record.startUtc || record.startUtc === best.record.startUtc && record.id < best.record.id);
|
|
23868
|
+
if (better) best = { record, overlap, existingDurationMs: eEnd - eStart };
|
|
23869
|
+
}
|
|
23870
|
+
if (best === void 0) return meeting.id;
|
|
23871
|
+
const shorterWindowMs = Math.min(dEnd - dStart, best.existingDurationMs);
|
|
23872
|
+
if (shorterWindowMs <= 0) return meeting.id;
|
|
23873
|
+
const substantial = best.overlap * 2 >= shorterWindowMs;
|
|
23874
|
+
const sharedSource = meeting.sources.some((source) => best.record.sources.includes(source));
|
|
23875
|
+
const sameApp = meeting.app !== void 0 && best.record.app !== void 0 && meeting.app.toLowerCase() === best.record.app.toLowerCase();
|
|
23876
|
+
const meetingTitle = meeting.title?.trim() ?? "";
|
|
23877
|
+
const sameTitle = meetingTitle.length > 0 && meetingTitle === (best.record.title?.trim() ?? "");
|
|
23878
|
+
const hasIdentitySignal = sharedSource || sameApp || sameTitle;
|
|
23879
|
+
const nonMarginalOverlap = best.overlap * 4 >= shorterWindowMs;
|
|
23880
|
+
if (!substantial && !(hasIdentitySignal && nonMarginalOverlap)) return meeting.id;
|
|
23881
|
+
claimed.add(best.record.id);
|
|
23882
|
+
return best.record.id;
|
|
23883
|
+
}
|
|
23884
|
+
};
|
|
23885
|
+
|
|
23886
|
+
// src/meetings/cli.ts
|
|
23887
|
+
var USAGE = `Usage: meetings <command> [options]
|
|
23888
|
+
|
|
23889
|
+
Commands:
|
|
23890
|
+
list [--date <YYYY-MM-DD>] List meeting records (all days, or one day)
|
|
23891
|
+
show <meeting-id> Print a stored meeting record
|
|
23892
|
+
build --date <YYYY-MM-DD> Detect + fuse + store the day's meetings
|
|
23893
|
+
|
|
23894
|
+
Add --json to list/build for machine-readable output.
|
|
23895
|
+
`;
|
|
23896
|
+
var VALUE_FLAGS = { "--date": true };
|
|
23897
|
+
var BOOLEAN_FLAGS = { "--json": true };
|
|
23898
|
+
function parseFlags(args) {
|
|
23899
|
+
const flags = /* @__PURE__ */ new Map();
|
|
23900
|
+
const positional = [];
|
|
23901
|
+
for (let i = 0; i < args.length; i++) {
|
|
23902
|
+
const arg = args[i];
|
|
23903
|
+
if (!arg.startsWith("--")) {
|
|
23904
|
+
positional.push(arg);
|
|
23905
|
+
continue;
|
|
23906
|
+
}
|
|
23907
|
+
if (VALUE_FLAGS[arg] === true) {
|
|
23908
|
+
const value = args[i + 1];
|
|
23909
|
+
if (value === void 0 || value.startsWith("--")) {
|
|
23910
|
+
throw new MeetingsInputError(`flag ${arg} requires a value`);
|
|
23911
|
+
}
|
|
23912
|
+
flags.set(arg, value);
|
|
23913
|
+
i++;
|
|
23914
|
+
continue;
|
|
23915
|
+
}
|
|
23916
|
+
if (BOOLEAN_FLAGS[arg] === true) {
|
|
23917
|
+
flags.set(arg, true);
|
|
23321
23918
|
continue;
|
|
23322
23919
|
}
|
|
23323
|
-
|
|
23920
|
+
const known = [...Object.keys(VALUE_FLAGS), ...Object.keys(BOOLEAN_FLAGS)].sort().join(", ");
|
|
23921
|
+
throw new MeetingsInputError(`unknown flag ${arg} (valid: ${known})`);
|
|
23324
23922
|
}
|
|
23325
|
-
return
|
|
23923
|
+
return { flags, positional };
|
|
23326
23924
|
}
|
|
23327
|
-
function
|
|
23328
|
-
|
|
23329
|
-
|
|
23330
|
-
|
|
23331
|
-
}
|
|
23332
|
-
|
|
23333
|
-
|
|
23334
|
-
|
|
23335
|
-
|
|
23336
|
-
|
|
23337
|
-
|
|
23338
|
-
|
|
23339
|
-
|
|
23340
|
-
|
|
23341
|
-
|
|
23342
|
-
|
|
23343
|
-
|
|
23344
|
-
|
|
23345
|
-
|
|
23346
|
-
|
|
23347
|
-
|
|
23348
|
-
|
|
23349
|
-
|
|
23350
|
-
const
|
|
23351
|
-
|
|
23352
|
-
|
|
23353
|
-
|
|
23354
|
-
|
|
23355
|
-
|
|
23356
|
-
|
|
23357
|
-
|
|
23358
|
-
|
|
23359
|
-
|
|
23360
|
-
|
|
23361
|
-
|
|
23362
|
-
|
|
23363
|
-
|
|
23364
|
-
|
|
23925
|
+
function requireDate(parsed) {
|
|
23926
|
+
const value = parsed.flags.get("--date");
|
|
23927
|
+
if (typeof value !== "string") {
|
|
23928
|
+
throw new MeetingsInputError("--date <YYYY-MM-DD> is required");
|
|
23929
|
+
}
|
|
23930
|
+
if (!isValidTranscriptDate(value)) {
|
|
23931
|
+
throw new MeetingsInputError(`--date must be a real YYYY-MM-DD; got '${value}'`);
|
|
23932
|
+
}
|
|
23933
|
+
return value;
|
|
23934
|
+
}
|
|
23935
|
+
function renderSummaryLine(summary) {
|
|
23936
|
+
const attendees = summary.attendees.length > 0 ? summary.attendees.join(", ") : "(none)";
|
|
23937
|
+
const sources = summary.sources.length > 0 ? summary.sources.join("+") : "(none)";
|
|
23938
|
+
const corroborated = summary.corroboratedBy.length > 0 ? ` corroborated=${summary.corroboratedBy.join("+")}` : "";
|
|
23939
|
+
return ` ${summary.id} ${summary.startUtc}\u2013${summary.endUtc} [${summary.detectionSource}] sources=${sources}${corroborated} attendees=${attendees} snapshots=${summary.snapshotCount}`;
|
|
23940
|
+
}
|
|
23941
|
+
function renderBuildSummary(summary) {
|
|
23942
|
+
if (!summary.enabled) {
|
|
23943
|
+
return `meetings disabled \u2014 set meetings.enabled=true to build (${summary.date})`;
|
|
23944
|
+
}
|
|
23945
|
+
const lines = [
|
|
23946
|
+
`${summary.date}: ${summary.meetings.length} meeting${summary.meetings.length === 1 ? "" : "s"} (${summary.built} written, ${summary.skipped} unchanged, ${summary.removed.length} removed)`
|
|
23947
|
+
];
|
|
23948
|
+
for (const meeting of summary.meetings) {
|
|
23949
|
+
const sources = meeting.sources.length > 0 ? meeting.sources.join("+") : "(none)";
|
|
23950
|
+
lines.push(
|
|
23951
|
+
` ${meeting.id} ${meeting.startUtc}\u2013${meeting.endUtc} [${meeting.detectionSource}] sources=${sources} snapshots=${meeting.snapshotCount} ${meeting.written ? "written" : "unchanged"}`
|
|
23952
|
+
);
|
|
23953
|
+
}
|
|
23954
|
+
if (summary.reindexWarning !== void 0) {
|
|
23955
|
+
lines.push(` warning: ${summary.reindexWarning}`);
|
|
23956
|
+
}
|
|
23957
|
+
if (summary.memoryWarning !== void 0) {
|
|
23958
|
+
lines.push(` warning: ${summary.memoryWarning}`);
|
|
23959
|
+
}
|
|
23960
|
+
return lines.join("\n");
|
|
23961
|
+
}
|
|
23962
|
+
async function runMeetingsCliCommand(deps, args, io) {
|
|
23963
|
+
const [command, ...rest] = args;
|
|
23964
|
+
try {
|
|
23965
|
+
switch (command) {
|
|
23966
|
+
case void 0:
|
|
23967
|
+
case "help":
|
|
23968
|
+
case "--help": {
|
|
23969
|
+
io.stdout.write(USAGE);
|
|
23970
|
+
return command === void 0 ? 1 : 0;
|
|
23971
|
+
}
|
|
23972
|
+
case "list": {
|
|
23973
|
+
const parsed = parseFlags(rest);
|
|
23974
|
+
const json = parsed.flags.has("--json");
|
|
23975
|
+
const dateFlag = parsed.flags.get("--date");
|
|
23976
|
+
if (typeof dateFlag === "string" && !isValidTranscriptDate(dateFlag)) {
|
|
23977
|
+
throw new MeetingsInputError(`--date must be a real YYYY-MM-DD; got '${dateFlag}'`);
|
|
23978
|
+
}
|
|
23979
|
+
if (!deps.config.enabled) {
|
|
23980
|
+
if (json) {
|
|
23981
|
+
io.stdout.write(typeof dateFlag === "string" ? "[]\n" : "{}\n");
|
|
23982
|
+
} else {
|
|
23983
|
+
io.stdout.write("meetings disabled \u2014 set meetings.enabled=true to build\n");
|
|
23984
|
+
}
|
|
23985
|
+
return 0;
|
|
23986
|
+
}
|
|
23987
|
+
if (typeof dateFlag === "string") {
|
|
23988
|
+
const summaries = await deps.store.listMeetingSummaries(dateFlag);
|
|
23989
|
+
if (json) {
|
|
23990
|
+
io.stdout.write(`${JSON.stringify(summaries, null, 2)}
|
|
23991
|
+
`);
|
|
23992
|
+
return 0;
|
|
23993
|
+
}
|
|
23994
|
+
if (summaries.length === 0) {
|
|
23995
|
+
io.stdout.write(`No meetings for ${dateFlag}.
|
|
23996
|
+
`);
|
|
23997
|
+
return 0;
|
|
23998
|
+
}
|
|
23999
|
+
io.stdout.write(`${dateFlag}:
|
|
24000
|
+
`);
|
|
24001
|
+
for (const summary of summaries) io.stdout.write(`${renderSummaryLine(summary)}
|
|
24002
|
+
`);
|
|
24003
|
+
return 0;
|
|
24004
|
+
}
|
|
24005
|
+
const dates = await deps.store.listMeetingDates();
|
|
24006
|
+
if (json) {
|
|
24007
|
+
const out = {};
|
|
24008
|
+
for (const date of dates) out[date] = await deps.store.listMeetingSummaries(date);
|
|
24009
|
+
io.stdout.write(`${JSON.stringify(out, null, 2)}
|
|
24010
|
+
`);
|
|
24011
|
+
return 0;
|
|
24012
|
+
}
|
|
24013
|
+
if (dates.length === 0) {
|
|
24014
|
+
io.stdout.write("No meetings recorded.\n");
|
|
24015
|
+
return 0;
|
|
24016
|
+
}
|
|
24017
|
+
for (const date of dates) {
|
|
24018
|
+
const summaries = await deps.store.listMeetingSummaries(date);
|
|
24019
|
+
io.stdout.write(`${date}:
|
|
24020
|
+
`);
|
|
24021
|
+
for (const summary of summaries) io.stdout.write(`${renderSummaryLine(summary)}
|
|
24022
|
+
`);
|
|
24023
|
+
}
|
|
24024
|
+
return 0;
|
|
24025
|
+
}
|
|
24026
|
+
case "show": {
|
|
24027
|
+
const parsed = parseFlags(rest);
|
|
24028
|
+
if (!deps.config.enabled) {
|
|
24029
|
+
io.stdout.write("meetings disabled \u2014 set meetings.enabled=true to build\n");
|
|
24030
|
+
return 0;
|
|
24031
|
+
}
|
|
24032
|
+
const id = parsed.positional[0];
|
|
24033
|
+
if (id === void 0) {
|
|
24034
|
+
throw new MeetingsInputError("show requires a meeting id");
|
|
24035
|
+
}
|
|
24036
|
+
const date = meetingIdDate(id);
|
|
24037
|
+
if (date === null) {
|
|
24038
|
+
throw new MeetingsInputError(`invalid meeting id '${id}' \u2014 expected mtg-YYYY-MM-DD-<hash>`);
|
|
24039
|
+
}
|
|
24040
|
+
if (!isValidTranscriptDate(date)) {
|
|
24041
|
+
throw new MeetingsInputError(`invalid meeting id '${id}' \u2014 '${date}' is not a real calendar date`);
|
|
24042
|
+
}
|
|
24043
|
+
const raw = await deps.store.readMeetingRecord(date, id);
|
|
24044
|
+
if (raw === null) {
|
|
24045
|
+
throw new MeetingsInputError(`meeting '${id}' not found`);
|
|
24046
|
+
}
|
|
24047
|
+
io.stdout.write(raw.endsWith("\n") ? raw : `${raw}
|
|
24048
|
+
`);
|
|
24049
|
+
return 0;
|
|
24050
|
+
}
|
|
24051
|
+
case "build": {
|
|
24052
|
+
const parsed = parseFlags(rest);
|
|
24053
|
+
const date = requireDate(parsed);
|
|
24054
|
+
const summary = await deps.builder.buildDay(date);
|
|
24055
|
+
if (parsed.flags.has("--json")) {
|
|
24056
|
+
io.stdout.write(`${JSON.stringify(summary, null, 2)}
|
|
24057
|
+
`);
|
|
24058
|
+
return 0;
|
|
24059
|
+
}
|
|
24060
|
+
io.stdout.write(`${renderBuildSummary(summary)}
|
|
24061
|
+
`);
|
|
24062
|
+
return 0;
|
|
24063
|
+
}
|
|
24064
|
+
default:
|
|
24065
|
+
throw new MeetingsInputError(`unknown meetings command '${command}'
|
|
24066
|
+
|
|
24067
|
+
${USAGE}`);
|
|
24068
|
+
}
|
|
24069
|
+
} catch (err) {
|
|
24070
|
+
if (err instanceof MeetingsInputError) {
|
|
24071
|
+
io.stderr.write(`meetings: ${err.message}
|
|
24072
|
+
`);
|
|
24073
|
+
return 1;
|
|
24074
|
+
}
|
|
24075
|
+
throw err;
|
|
24076
|
+
}
|
|
23365
24077
|
}
|
|
23366
24078
|
|
|
23367
24079
|
// src/session-summaries/index.ts
|
|
23368
24080
|
import { createHash as createHash10 } from "crypto";
|
|
23369
24081
|
import { lstat as lstat2, mkdir as mkdir7, readFile as readFile6, readdir as readdir4, rename, rm, stat as stat4, writeFile as writeFile7 } from "fs/promises";
|
|
23370
|
-
import
|
|
24082
|
+
import path30 from "path";
|
|
23371
24083
|
|
|
23372
24084
|
// src/session-summaries/adapters.ts
|
|
23373
24085
|
var VALID_ROLES = /* @__PURE__ */ new Set(["user", "assistant", "tool", "system", "other"]);
|
|
@@ -23872,7 +24584,7 @@ function shortHash(value, length = 16) {
|
|
|
23872
24584
|
async function listTranscriptFiles(root, maxFiles) {
|
|
23873
24585
|
const out = [];
|
|
23874
24586
|
let truncated = false;
|
|
23875
|
-
const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${
|
|
24587
|
+
const entrySortKey = (entryName, isDirectory) => isDirectory ? `${entryName}${path30.sep}` : entryName;
|
|
23876
24588
|
async function visit(dir) {
|
|
23877
24589
|
if (truncated) return;
|
|
23878
24590
|
const entries = (await readdir4(dir, { withFileTypes: true })).sort(
|
|
@@ -23882,13 +24594,13 @@ async function listTranscriptFiles(root, maxFiles) {
|
|
|
23882
24594
|
if (truncated) return;
|
|
23883
24595
|
if (entry.name.startsWith(".")) continue;
|
|
23884
24596
|
if (entry.isSymbolicLink()) continue;
|
|
23885
|
-
const fullPath =
|
|
24597
|
+
const fullPath = path30.join(dir, entry.name);
|
|
23886
24598
|
if (entry.isDirectory()) {
|
|
23887
24599
|
await visit(fullPath);
|
|
23888
24600
|
continue;
|
|
23889
24601
|
}
|
|
23890
24602
|
if (!entry.isFile()) continue;
|
|
23891
|
-
const ext =
|
|
24603
|
+
const ext = path30.extname(entry.name).toLowerCase();
|
|
23892
24604
|
if (!SUPPORTED_EXTENSIONS.has(ext)) continue;
|
|
23893
24605
|
out.push(fullPath);
|
|
23894
24606
|
if (out.length > maxFiles) {
|
|
@@ -23915,7 +24627,7 @@ function normalizeInputDir(inputDir) {
|
|
|
23915
24627
|
if (typeof inputDir !== "string" || inputDir.trim().length === 0) {
|
|
23916
24628
|
throw new Error("inputDir must be a non-empty string");
|
|
23917
24629
|
}
|
|
23918
|
-
return
|
|
24630
|
+
return path30.resolve(expandTildePath(inputDir.trim()));
|
|
23919
24631
|
}
|
|
23920
24632
|
function initRoleCounts() {
|
|
23921
24633
|
return {
|
|
@@ -24072,11 +24784,11 @@ async function collectLocalSessionSummaries(options) {
|
|
|
24072
24784
|
continue;
|
|
24073
24785
|
}
|
|
24074
24786
|
seenFileHashes.add(fileHash);
|
|
24075
|
-
const fileExtension =
|
|
24787
|
+
const fileExtension = path30.extname(filePath).toLowerCase();
|
|
24076
24788
|
const parsed = await adapter.parseFile(
|
|
24077
24789
|
{
|
|
24078
24790
|
content,
|
|
24079
|
-
fileName:
|
|
24791
|
+
fileName: path30.basename(filePath),
|
|
24080
24792
|
fileExtension,
|
|
24081
24793
|
fileRef: fileHash
|
|
24082
24794
|
},
|
|
@@ -24132,7 +24844,7 @@ async function collectLocalSessionSummaries(options) {
|
|
|
24132
24844
|
}
|
|
24133
24845
|
async function readRedactionConfig(pathLike) {
|
|
24134
24846
|
if (!pathLike) return void 0;
|
|
24135
|
-
const raw = await readFile6(
|
|
24847
|
+
const raw = await readFile6(path30.resolve(expandTildePath(pathLike)), "utf-8");
|
|
24136
24848
|
const parsed = JSON.parse(raw);
|
|
24137
24849
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
24138
24850
|
throw new Error("redaction config must be a JSON object");
|
|
@@ -24145,15 +24857,15 @@ function toJsonl(drafts) {
|
|
|
24145
24857
|
}
|
|
24146
24858
|
function defaultDraftOutputPath(memoryDir, generatedAt) {
|
|
24147
24859
|
const stamp = generatedAt.replace(/[:.]/g, "-");
|
|
24148
|
-
return
|
|
24149
|
-
|
|
24860
|
+
return path30.join(
|
|
24861
|
+
path30.resolve(expandTildePath(memoryDir)),
|
|
24150
24862
|
"state",
|
|
24151
24863
|
"session-summary-drafts",
|
|
24152
24864
|
`session-summaries-${stamp}.jsonl`
|
|
24153
24865
|
);
|
|
24154
24866
|
}
|
|
24155
24867
|
async function writeDrafts(filePath, drafts) {
|
|
24156
|
-
await mkdir7(
|
|
24868
|
+
await mkdir7(path30.dirname(filePath), { recursive: true });
|
|
24157
24869
|
const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
24158
24870
|
try {
|
|
24159
24871
|
await writeFile7(tempPath, toJsonl(drafts), "utf-8");
|
|
@@ -24171,7 +24883,7 @@ async function runLocalSessionSummaryCliCommand(options) {
|
|
|
24171
24883
|
});
|
|
24172
24884
|
const wroteFiles = [];
|
|
24173
24885
|
if (options.output) {
|
|
24174
|
-
const outputPath =
|
|
24886
|
+
const outputPath = path30.resolve(expandTildePath(options.output));
|
|
24175
24887
|
await writeDrafts(outputPath, report.drafts);
|
|
24176
24888
|
wroteFiles.push(outputPath);
|
|
24177
24889
|
}
|
|
@@ -24206,19 +24918,19 @@ async function runLocalSessionSummaryCliCommand(options) {
|
|
|
24206
24918
|
|
|
24207
24919
|
// src/transfer/capsule-fork.ts
|
|
24208
24920
|
import { lstat as lstat3, mkdir as mkdir8, readFile as readFile7, realpath as realpath2, writeFile as writeFile8 } from "fs/promises";
|
|
24209
|
-
import
|
|
24921
|
+
import path31 from "path";
|
|
24210
24922
|
async function forkCapsule(opts) {
|
|
24211
24923
|
validateForkId(opts.forkId);
|
|
24212
|
-
const rootAbs =
|
|
24924
|
+
const rootAbs = path31.resolve(opts.targetRoot);
|
|
24213
24925
|
await assertIsDirectoryNotSymlink(rootAbs, "forkCapsule", "targetRoot");
|
|
24214
|
-
const forkDirAbs =
|
|
24926
|
+
const forkDirAbs = path31.join(rootAbs, "forks", opts.forkId);
|
|
24215
24927
|
const forkEntryExists = await pathEntryExists(forkDirAbs);
|
|
24216
24928
|
if (forkEntryExists) {
|
|
24217
24929
|
throw new Error(
|
|
24218
24930
|
`forkCapsule: fork path already exists \u2014 forkId "${opts.forkId}" is already in use at: ${forkDirAbs}`
|
|
24219
24931
|
);
|
|
24220
24932
|
}
|
|
24221
|
-
const archiveAbs =
|
|
24933
|
+
const archiveAbs = path31.resolve(opts.sourceArchive);
|
|
24222
24934
|
const importResult = await importCapsule({
|
|
24223
24935
|
archivePath: archiveAbs,
|
|
24224
24936
|
root: rootAbs,
|
|
@@ -24240,10 +24952,10 @@ async function forkCapsule(opts) {
|
|
|
24240
24952
|
importedRecords: importResult.imported.length,
|
|
24241
24953
|
skippedRecords: importResult.skipped.length
|
|
24242
24954
|
};
|
|
24243
|
-
const lineagePath =
|
|
24955
|
+
const lineagePath = path31.join(forkDirAbs, "lineage.json");
|
|
24244
24956
|
const rootReal = await realpath2(rootAbs);
|
|
24245
24957
|
await assertRealpathInsideRoot(rootReal, lineagePath, `forks/${opts.forkId}/lineage.json`, "forkCapsule");
|
|
24246
|
-
await mkdir8(
|
|
24958
|
+
await mkdir8(path31.dirname(lineagePath), { recursive: true });
|
|
24247
24959
|
await writeFile8(lineagePath, JSON.stringify(lineage, null, 2) + "\n", "utf-8");
|
|
24248
24960
|
return {
|
|
24249
24961
|
archivePath: archiveAbs,
|
|
@@ -24257,11 +24969,11 @@ async function readForkLineage(targetRoot, forkId) {
|
|
|
24257
24969
|
if (typeof forkId !== "string" || forkId.length === 0 || forkId.length > 64 || !CAPSULE_ID_PATTERN.test(forkId)) {
|
|
24258
24970
|
return null;
|
|
24259
24971
|
}
|
|
24260
|
-
const rootAbs =
|
|
24972
|
+
const rootAbs = path31.resolve(targetRoot);
|
|
24261
24973
|
const rootReal = await realpath2(rootAbs).catch(() => rootAbs);
|
|
24262
|
-
const lineagePath =
|
|
24263
|
-
const rel =
|
|
24264
|
-
if (rel.startsWith("..") ||
|
|
24974
|
+
const lineagePath = path31.join(rootReal, "forks", forkId, "lineage.json");
|
|
24975
|
+
const rel = path31.relative(rootReal, lineagePath);
|
|
24976
|
+
if (rel.startsWith("..") || path31.isAbsolute(rel)) {
|
|
24265
24977
|
return null;
|
|
24266
24978
|
}
|
|
24267
24979
|
if (!await isLineagePathContained(rootReal, lineagePath)) {
|
|
@@ -24302,19 +25014,19 @@ async function pathEntryExists(absPath) {
|
|
|
24302
25014
|
async function isLineagePathContained(rootReal, lineagePath) {
|
|
24303
25015
|
let existing = lineagePath;
|
|
24304
25016
|
const suffix = [];
|
|
24305
|
-
while (existing !==
|
|
25017
|
+
while (existing !== path31.dirname(existing)) {
|
|
24306
25018
|
const st = await lstat3(existing).catch(() => null);
|
|
24307
25019
|
if (st !== null) break;
|
|
24308
|
-
suffix.unshift(
|
|
24309
|
-
existing =
|
|
25020
|
+
suffix.unshift(path31.basename(existing));
|
|
25021
|
+
existing = path31.dirname(existing);
|
|
24310
25022
|
}
|
|
24311
25023
|
const existingReal = await realpath2(existing).catch(() => existing);
|
|
24312
|
-
const targetReal = suffix.length > 0 ?
|
|
24313
|
-
const rel =
|
|
25024
|
+
const targetReal = suffix.length > 0 ? path31.join(existingReal, ...suffix) : existingReal;
|
|
25025
|
+
const rel = path31.relative(rootReal, targetReal);
|
|
24314
25026
|
if (rel === "") return true;
|
|
24315
25027
|
if (rel === "..") return false;
|
|
24316
|
-
if (rel.startsWith(`..${
|
|
24317
|
-
if (
|
|
25028
|
+
if (rel.startsWith(`..${path31.sep}`)) return false;
|
|
25029
|
+
if (path31.isAbsolute(rel)) return false;
|
|
24318
25030
|
return true;
|
|
24319
25031
|
}
|
|
24320
25032
|
|
|
@@ -24443,10 +25155,19 @@ export {
|
|
|
24443
25155
|
locateTranscriptPath,
|
|
24444
25156
|
isEligibleActivityFact,
|
|
24445
25157
|
generateActivityMemories,
|
|
24446
|
-
|
|
24447
|
-
|
|
24448
|
-
|
|
24449
|
-
|
|
25158
|
+
MeetingsInputError,
|
|
25159
|
+
fuseMeeting,
|
|
25160
|
+
MEETINGS_DIR_NAME,
|
|
25161
|
+
MEETING_KIND,
|
|
25162
|
+
MEETING_FORMAT_VERSION,
|
|
25163
|
+
meetingIdDate,
|
|
25164
|
+
composeMeetingRecord,
|
|
25165
|
+
serializeMeetingRecord,
|
|
25166
|
+
parseMeetingRecordSummary,
|
|
25167
|
+
MeetingRecordStore,
|
|
25168
|
+
buildMeetingRecordsForDay,
|
|
25169
|
+
MeetingsBuilder,
|
|
25170
|
+
runMeetingsCliCommand,
|
|
24450
25171
|
registerLocalSessionSourceAdapter,
|
|
24451
25172
|
getLocalSessionSourceAdapter,
|
|
24452
25173
|
listLocalSessionSourceAdapters,
|
|
@@ -24462,4 +25183,4 @@ export {
|
|
|
24462
25183
|
blendGraphExpandedRecallScore,
|
|
24463
25184
|
Orchestrator
|
|
24464
25185
|
};
|
|
24465
|
-
//# sourceMappingURL=chunk-
|
|
25186
|
+
//# sourceMappingURL=chunk-AT3TDN6O.js.map
|