hippo-memory 1.70.0 → 1.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/agent-memories/claude-code.d.ts +4 -2
- package/dist/agent-memories/claude-code.js +14 -5
- package/dist/agent-memories/files.js +23 -12
- package/dist/agent-memories/markdown.d.ts +1 -3
- package/dist/agent-memories/markdown.js +1 -3
- package/dist/agent-memories/report.js +2 -1
- package/dist/agent-memories/sync.d.ts +4 -2
- package/dist/agent-memories/sync.js +10 -5
- package/dist/api/assemble.d.ts +7 -44
- package/dist/api/assemble.js +2 -22
- package/dist/api/audit.d.ts +5 -1
- package/dist/api/audit.js +9 -1
- package/dist/api/auth.d.ts +13 -22
- package/dist/api/auth.js +34 -24
- package/dist/api/auto-sleep.js +2 -2
- package/dist/api/availability.d.ts +2 -15
- package/dist/api/availability.js +2 -15
- package/dist/api/context-select.js +3 -4
- package/dist/api/context-types.d.ts +10 -35
- package/dist/api/context.d.ts +5 -22
- package/dist/api/context.js +21 -38
- package/dist/api/dormant.d.ts +5 -21
- package/dist/api/dormant.js +7 -26
- package/dist/api/drill-down.d.ts +7 -46
- package/dist/api/drill-down.js +5 -26
- package/dist/api/forget.d.ts +5 -24
- package/dist/api/forget.js +5 -28
- package/dist/api/graph.d.ts +8 -0
- package/dist/api/graph.js +7 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/instruction-detect.js +16 -5
- package/dist/api/ledger-db.d.ts +2 -1
- package/dist/api/ledger-db.js +5 -3
- package/dist/api/memories.d.ts +5 -0
- package/dist/api/memories.js +7 -0
- package/dist/api/objects.d.ts +9 -0
- package/dist/api/objects.js +11 -0
- package/dist/api/on-store.js +5 -3
- package/dist/api/predictions.d.ts +9 -0
- package/dist/api/predictions.js +18 -0
- package/dist/api/promote.d.ts +13 -17
- package/dist/api/promote.js +11 -19
- package/dist/api/prompt-hook.d.ts +4 -4
- package/dist/api/prompt-hook.js +10 -9
- package/dist/api/recall-cli.d.ts +55 -0
- package/dist/api/recall-cli.js +94 -0
- package/dist/api/recall-core.js +14 -6
- package/dist/api/recall-finish.d.ts +53 -0
- package/dist/api/recall-finish.js +30 -0
- package/dist/api/recall-history.d.ts +17 -84
- package/dist/api/recall-history.js +15 -88
- package/dist/api/recall-pipeline.d.ts +2 -3
- package/dist/api/recall-pipeline.js +16 -9
- package/dist/api/recall-types.d.ts +64 -304
- package/dist/api/recall.d.ts +5 -33
- package/dist/api/recall.js +59 -60
- package/dist/api/refine.d.ts +7 -0
- package/dist/api/refine.js +10 -0
- package/dist/api/remember-local.d.ts +57 -0
- package/dist/api/remember-local.js +90 -0
- package/dist/api/remember.d.ts +18 -1
- package/dist/api/remember.js +13 -1
- package/dist/api/sleep-run.d.ts +1 -3
- package/dist/api/sleep-run.js +17 -21
- package/dist/api/sleep.d.ts +9 -28
- package/dist/api/tokens.d.ts +3 -10
- package/dist/api/tokens.js +3 -10
- package/dist/api/types.d.ts +6 -29
- package/dist/api/types.js +4 -22
- package/dist/capture/command.d.ts +4 -12
- package/dist/capture/command.js +6 -22
- package/dist/capture/compact.d.ts +4 -15
- package/dist/capture/compact.js +16 -25
- package/dist/capture/compaction-record.js +101 -69
- package/dist/capture/compaction-spool.d.ts +1 -1
- package/dist/capture/compaction-spool.js +1 -1
- package/dist/capture/session-digest.d.ts +1 -1
- package/dist/capture/session-digest.js +13 -7
- package/dist/capture/transcript.d.ts +2 -10
- package/dist/capture/transcript.js +4 -18
- package/dist/cli/api-context.d.ts +3 -0
- package/dist/cli/api-context.js +6 -0
- package/dist/cli/audit-prune.d.ts +6 -39
- package/dist/cli/audit-prune.js +6 -39
- package/dist/cli/audit.d.ts +1 -1
- package/dist/cli/audit.js +33 -34
- package/dist/cli/auth.d.ts +2 -2
- package/dist/cli/auth.js +57 -39
- package/dist/cli/briefs.d.ts +4 -4
- package/dist/cli/briefs.js +18 -22
- package/dist/cli/card.d.ts +2 -2
- package/dist/cli/card.js +31 -32
- package/dist/cli/client.d.ts +7 -27
- package/dist/cli/client.js +24 -43
- package/dist/cli/compact-resume-payload.js +3 -2
- package/dist/cli/context.d.ts +1 -2
- package/dist/cli/context.js +12 -8
- package/dist/cli/continuity.d.ts +6 -6
- package/dist/cli/continuity.js +62 -64
- package/dist/cli/correction-latency.d.ts +2 -14
- package/dist/cli/correction-latency.js +2 -14
- package/dist/cli/curate.d.ts +13 -17
- package/dist/cli/curate.js +68 -92
- package/dist/cli/dag.d.ts +4 -4
- package/dist/cli/dag.js +33 -27
- package/dist/cli/decisions.d.ts +4 -4
- package/dist/cli/decisions.js +33 -47
- package/dist/cli/eval.js +15 -13
- package/dist/cli/exit.d.ts +6 -0
- package/dist/cli/exit.js +11 -0
- package/dist/cli/explain.d.ts +1 -2
- package/dist/cli/explain.js +6 -4
- package/dist/cli/flag-values.d.ts +6 -1
- package/dist/cli/flag-values.js +27 -10
- package/dist/cli/flags.d.ts +1 -0
- package/dist/cli/flags.js +1 -1
- package/dist/cli/github.d.ts +14 -0
- package/dist/{connectors/github/cli-impl.js → cli/github.js} +43 -71
- package/dist/cli/goals.d.ts +2 -2
- package/dist/cli/goals.js +46 -50
- package/dist/cli/hook-runtime.d.ts +9 -27
- package/dist/cli/hook-runtime.js +15 -31
- package/dist/cli/init.d.ts +2 -2
- package/dist/cli/init.js +6 -12
- package/dist/cli/install-steps.js +3 -12
- package/dist/cli/last-sleep.d.ts +2 -1
- package/dist/cli/last-sleep.js +3 -0
- package/dist/cli/maintenance.d.ts +4 -4
- package/dist/cli/maintenance.js +14 -19
- package/dist/cli/object-verbs.js +4 -3
- package/dist/cli/owner-validation.d.ts +5 -28
- package/dist/cli/owner-validation.js +5 -28
- package/dist/cli/playbooks.d.ts +4 -4
- package/dist/cli/playbooks.js +23 -28
- package/dist/cli/print.d.ts +2 -5
- package/dist/cli/print.js +1 -4
- package/dist/cli/projects.d.ts +2 -2
- package/dist/cli/projects.js +1 -3
- package/dist/cli/provenance-coverage.d.ts +2 -6
- package/dist/cli/provenance-coverage.js +2 -6
- package/dist/cli/quality-repair-once.js +2 -2
- package/dist/cli/recall.d.ts +2 -4
- package/dist/cli/recall.js +55 -131
- package/dist/cli/refine-llm.d.ts +5 -31
- package/dist/cli/refine-llm.js +9 -36
- package/dist/cli/remember.d.ts +3 -3
- package/dist/cli/remember.js +122 -180
- package/dist/cli/scheduler.d.ts +2 -17
- package/dist/cli/scheduler.js +12 -18
- package/dist/cli/serve.js +21 -12
- package/dist/cli/session-hooks.d.ts +10 -18
- package/dist/cli/session-hooks.js +112 -113
- package/dist/cli/setup.d.ts +4 -4
- package/dist/cli/setup.js +19 -21
- package/dist/cli/shared.d.ts +9 -23
- package/dist/cli/shared.js +9 -32
- package/dist/cli/slack.d.ts +2 -2
- package/dist/cli/slack.js +19 -23
- package/dist/cli/sleep.d.ts +3 -2
- package/dist/cli/sleep.js +15 -16
- package/dist/cli/status.d.ts +9 -12
- package/dist/cli/status.js +55 -98
- package/dist/cli/stdin.d.ts +4 -6
- package/dist/cli/stdin.js +2 -3
- package/dist/cli/transfer.d.ts +9 -9
- package/dist/cli/transfer.js +66 -89
- package/dist/cli/usage.js +11 -5
- package/dist/cli.d.ts +66 -448
- package/dist/cli.js +87 -263
- package/dist/connectors/github/backfill.d.ts +5 -25
- package/dist/connectors/github/backfill.js +14 -49
- package/dist/connectors/github/deletion.d.ts +4 -18
- package/dist/connectors/github/deletion.js +2 -15
- package/dist/connectors/github/dlq.d.ts +8 -33
- package/dist/connectors/github/dlq.js +12 -29
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +4 -10
- package/dist/connectors/github/octokit-client.d.ts +4 -16
- package/dist/connectors/github/octokit-client.js +27 -24
- package/dist/connectors/github/ratelimit.d.ts +3 -14
- package/dist/connectors/github/ratelimit.js +3 -14
- package/dist/connectors/github/scope.d.ts +3 -5
- package/dist/connectors/github/scope.js +3 -5
- package/dist/connectors/github/signature.d.ts +4 -26
- package/dist/connectors/github/signature.js +4 -26
- package/dist/connectors/github/tenant-routing.d.ts +2 -24
- package/dist/connectors/github/tenant-routing.js +4 -26
- package/dist/connectors/github/transform.js +2 -16
- package/dist/connectors/github/types.d.ts +3 -15
- package/dist/connectors/github/types.js +2 -9
- package/dist/connectors/github/webhook.d.ts +2 -16
- package/dist/connectors/github/webhook.js +6 -22
- package/dist/connectors/slack/backfill.d.ts +4 -17
- package/dist/connectors/slack/backfill.js +4 -13
- package/dist/connectors/slack/dlq.d.ts +2 -19
- package/dist/connectors/slack/dlq.js +2 -19
- package/dist/connectors/slack/ingest.d.ts +2 -3
- package/dist/connectors/slack/ingest.js +2 -3
- package/dist/connectors/slack/scope.d.ts +2 -8
- package/dist/connectors/slack/scope.js +2 -8
- package/dist/connectors/slack/signature.d.ts +1 -6
- package/dist/connectors/slack/tenant-routing.d.ts +2 -19
- package/dist/connectors/slack/tenant-routing.js +2 -21
- package/dist/connectors/slack/transform.d.ts +2 -18
- package/dist/connectors/slack/transform.js +2 -18
- package/dist/connectors/slack/types.d.ts +3 -9
- package/dist/connectors/slack/types.js +2 -4
- package/dist/connectors/slack/web-client.js +33 -27
- package/dist/connectors/slack/webhook.d.ts +2 -19
- package/dist/connectors/slack/webhook.js +5 -26
- package/dist/connectors/slack/workspaces.d.ts +4 -24
- package/dist/connectors/slack/workspaces.js +4 -24
- package/dist/consolidate/conflicts.js +6 -14
- package/dist/consolidate/dag-summary.d.ts +8 -0
- package/dist/consolidate/dag-summary.js +41 -0
- package/dist/consolidate/dag.d.ts +5 -28
- package/dist/consolidate/dag.js +14 -75
- package/dist/consolidate/decay.js +7 -19
- package/dist/consolidate/dedupe.d.ts +6 -52
- package/dist/consolidate/dedupe.js +13 -71
- package/dist/consolidate/flush-units.d.ts +3 -4
- package/dist/consolidate/flush-units.js +3 -3
- package/dist/consolidate/half-life-migration.d.ts +3 -26
- package/dist/consolidate/half-life-migration.js +11 -28
- package/dist/consolidate/llm-passes.js +4 -21
- package/dist/consolidate/memory-value-weights.d.ts +2 -13
- package/dist/consolidate/memory-value-weights.js +2 -13
- package/dist/consolidate/memory-value.d.ts +11 -84
- package/dist/consolidate/memory-value.js +16 -104
- package/dist/consolidate/merge.js +10 -31
- package/dist/consolidate/merged-row.js +2 -1
- package/dist/consolidate/physics-pass.js +1 -3
- package/dist/consolidate/replay.d.ts +6 -38
- package/dist/consolidate/replay.js +14 -52
- package/dist/consolidate/run.js +1 -1
- package/dist/consolidate/sleep.d.ts +1 -8
- package/dist/consolidate/sleep.js +5 -17
- package/dist/consolidate/trace.d.ts +3 -18
- package/dist/consolidate/trace.js +3 -18
- package/dist/consolidate/traces.js +6 -22
- package/dist/core/ablation.d.ts +4 -91
- package/dist/core/ablation.js +4 -91
- package/dist/core/ambient.d.ts +1 -8
- package/dist/core/ambient.js +1 -8
- package/dist/core/capture-contract.d.ts +4 -2
- package/dist/core/capture-contract.js +4 -2
- package/dist/core/card.d.ts +4 -1
- package/dist/core/card.js +8 -0
- package/dist/core/compare.d.ts +11 -67
- package/dist/core/compare.js +9 -63
- package/dist/core/config.d.ts +10 -24
- package/dist/core/config.js +13 -14
- package/dist/core/handoff.d.ts +1 -7
- package/dist/core/handoff.js +1 -7
- package/dist/core/memory-quality.js +1 -1
- package/dist/core/memory.d.ts +41 -164
- package/dist/core/memory.js +51 -221
- package/dist/core/package-root.d.ts +3 -0
- package/dist/core/package-root.js +5 -0
- package/dist/core/physics-config.d.ts +1 -4
- package/dist/core/physics-config.js +3 -8
- package/dist/core/physics.d.ts +15 -61
- package/dist/core/physics.js +59 -122
- package/dist/core/project-identity.d.ts +17 -58
- package/dist/core/project-identity.js +17 -38
- package/dist/core/project-remote.js +13 -2
- package/dist/core/raw-append-only.d.ts +5 -0
- package/dist/core/raw-append-only.js +7 -0
- package/dist/core/salience.d.ts +1 -7
- package/dist/core/salience.js +1 -7
- package/dist/dashboard/dashboard-actions.js +2 -2
- package/dist/dashboard/dashboard-snapshot.d.ts +2 -1
- package/dist/dashboard/dashboard-snapshot.js +11 -2
- package/dist/dashboard/dashboard-types.d.ts +2 -1
- package/dist/dashboard/dashboard.d.ts +1 -0
- package/dist/dashboard/dashboard.js +50 -4
- package/dist/db/busy.d.ts +1 -1
- package/dist/db/busy.js +17 -8
- package/dist/db/connect.d.ts +1 -0
- package/dist/db/connect.js +3 -3
- package/dist/db/migrate.js +3 -3
- package/dist/db/migrations/types.d.ts +2 -5
- package/dist/db/migrations/v14.js +2 -3
- package/dist/db/migrations/v15.js +2 -8
- package/dist/db/migrations/v16.js +2 -3
- package/dist/db/migrations/v17.js +2 -3
- package/dist/db/migrations/v19.js +2 -5
- package/dist/db/migrations/v20.js +2 -7
- package/dist/db/migrations/v22.js +4 -17
- package/dist/db/migrations/v23.js +3 -14
- package/dist/db/migrations/v24.js +2 -4
- package/dist/db/migrations/v25.js +3 -8
- package/dist/db/migrations/v26.js +2 -13
- package/dist/db/migrations/v27.js +3 -11
- package/dist/db/migrations/v28.js +2 -14
- package/dist/db/migrations/v29.js +4 -18
- package/dist/db/migrations/v30.js +4 -16
- package/dist/db/migrations/v31.js +2 -15
- package/dist/db/migrations/v32.js +4 -22
- package/dist/db/migrations/v33.js +2 -15
- package/dist/db/migrations/v34.js +2 -11
- package/dist/db/migrations/v35.js +2 -11
- package/dist/db/migrations/v36.js +2 -11
- package/dist/db/migrations/v37.js +8 -33
- package/dist/db/migrations/v38.js +5 -38
- package/dist/db/migrations/v39.js +9 -20
- package/dist/db/migrations/v40.js +2 -9
- package/dist/db/migrations/v41.js +2 -24
- package/dist/db/migrations/v43.js +1 -1
- package/dist/db/migrations/v44.js +2 -8
- package/dist/db/migrations/v45.js +2 -7
- package/dist/db/migrations/v47.js +2 -3
- package/dist/db/migrations/v51.js +1 -1
- package/dist/db/open.d.ts +2 -0
- package/dist/db/open.js +17 -1
- package/dist/db/physics-state.d.ts +6 -22
- package/dist/db/physics-state.js +25 -36
- package/dist/db/raw-archive-mirror-cleanup.d.ts +2 -17
- package/dist/db/raw-archive-mirror-cleanup.js +2 -17
- package/dist/db/vector-store.d.ts +2 -0
- package/dist/db/vector-store.js +8 -1
- package/dist/doctor.js +74 -19
- package/dist/entry/session-text.js +2 -1
- package/dist/eval/eval-stats.d.ts +15 -53
- package/dist/eval/eval-stats.js +12 -42
- package/dist/eval/eval-suite.d.ts +2 -13
- package/dist/eval/eval-suite.js +74 -34
- package/dist/eval/eval.d.ts +6 -24
- package/dist/eval/eval.js +7 -34
- package/dist/eval/judgment.d.ts +0 -3
- package/dist/eval/judgment.js +19 -11
- package/dist/extensions/openclaw-plugin/index.js +1 -1
- package/dist/graph/extract.d.ts +5 -27
- package/dist/graph/extract.js +7 -33
- package/dist/graph/recall.d.ts +7 -20
- package/dist/graph/recall.js +14 -76
- package/dist/graph/stream.d.ts +7 -39
- package/dist/graph/stream.js +11 -34
- package/dist/graph/view.d.ts +9 -35
- package/dist/graph/view.js +11 -39
- package/dist/hooks/codex-wrapper.js +2 -2
- package/dist/hooks/copilot.js +2 -1
- package/dist/hooks/hook-blocks.d.ts +6 -2
- package/dist/hooks/hook-blocks.js +37 -124
- package/dist/hooks/json-hooks.d.ts +4 -36
- package/dist/hooks/json-hooks.js +18 -57
- package/dist/hooks/opencode.d.ts +0 -38
- package/dist/hooks/opencode.js +9 -76
- package/dist/hooks/shared.d.ts +8 -17
- package/dist/hooks/shared.js +29 -20
- package/dist/importers/core.d.ts +12 -37
- package/dist/importers/core.js +9 -27
- package/dist/importers/markdown-parse.d.ts +8 -22
- package/dist/importers/markdown-parse.js +8 -25
- package/dist/importers/markdown.js +3 -12
- package/dist/importers/sources.js +7 -35
- package/dist/importers/vault.d.ts +2 -8
- package/dist/importers/vault.js +25 -81
- package/dist/index.d.ts +6 -2
- package/dist/index.js +6 -2
- package/dist/learn/autolearn.d.ts +14 -41
- package/dist/learn/autolearn.js +14 -41
- package/dist/learn/extract.js +2 -4
- package/dist/learn/forward-claim-detector.d.ts +6 -30
- package/dist/learn/forward-claim-detector.js +14 -66
- package/dist/learn/invalidation.d.ts +6 -18
- package/dist/learn/invalidation.js +9 -26
- package/dist/mcp/admin-tools.js +3 -5
- package/dist/mcp/memory-tools.js +4 -9
- package/dist/mcp/protocol.d.ts +8 -26
- package/dist/mcp/protocol.js +3 -6
- package/dist/mcp/recall-tools.js +3 -3
- package/dist/mcp/request.d.ts +3 -11
- package/dist/mcp/request.js +10 -26
- package/dist/mcp/server.d.ts +3 -9
- package/dist/mcp/server.js +5 -16
- package/dist/mcp/session-state.d.ts +1 -1
- package/dist/mcp/session-state.js +5 -11
- package/dist/mcp/stdio.d.ts +2 -6
- package/dist/mcp/stdio.js +48 -12
- package/dist/mcp/tools.js +5 -3
- package/dist/objects/customer-notes.d.ts +7 -42
- package/dist/objects/customer-notes.js +7 -48
- package/dist/objects/decisions.d.ts +12 -50
- package/dist/objects/decisions.js +15 -53
- package/dist/objects/incidents.d.ts +7 -38
- package/dist/objects/incidents.js +7 -41
- package/dist/objects/policies.d.ts +11 -89
- package/dist/objects/policies.js +11 -98
- package/dist/objects/processes.d.ts +7 -52
- package/dist/objects/processes.js +7 -61
- package/dist/objects/project-briefs.d.ts +11 -55
- package/dist/objects/project-briefs.js +14 -75
- package/dist/objects/skills.d.ts +7 -42
- package/dist/objects/skills.js +8 -54
- package/dist/postinstall.js +6 -19
- package/dist/predictions/planning-fallacy.d.ts +11 -34
- package/dist/rerankers/clef.js +3 -31
- package/dist/rerankers/cross-encoder.js +4 -6
- package/dist/rerankers/jev.js +9 -6
- package/dist/rerankers/llm.d.ts +2 -11
- package/dist/rerankers/llm.js +14 -14
- package/dist/rerankers/outage-warning.d.ts +2 -1
- package/dist/rerankers/outage-warning.js +2 -1
- package/dist/rerankers/remote.d.ts +1 -0
- package/dist/rerankers/remote.js +2 -0
- package/dist/rerankers/types.d.ts +2 -14
- package/dist/search/boosts.d.ts +0 -2
- package/dist/search/boosts.js +2 -2
- package/dist/search/goal-boost.d.ts +23 -0
- package/dist/search/goal-boost.js +90 -0
- package/dist/search/hybrid.d.ts +2 -0
- package/dist/search/multihop.js +2 -3
- package/dist/search/path-context.d.ts +5 -18
- package/dist/search/path-context.js +5 -18
- package/dist/search/physics-search.js +11 -8
- package/dist/search/rrf.d.ts +7 -35
- package/dist/search/rrf.js +5 -30
- package/dist/search/vector.d.ts +7 -0
- package/dist/search/vector.js +35 -5
- package/dist/server/auth.d.ts +9 -28
- package/dist/server/auth.js +32 -25
- package/dist/server/boot.d.ts +2 -21
- package/dist/server/boot.js +63 -96
- package/dist/server/client-ip.d.ts +3 -19
- package/dist/server/client-ip.js +5 -28
- package/dist/server/defaults.d.ts +3 -0
- package/dist/server/defaults.js +4 -0
- package/dist/server/key-check-bounds.d.ts +2 -1
- package/dist/server/lifecycle.d.ts +5 -4
- package/dist/server/lifecycle.js +19 -4
- package/dist/server/mcp-http.js +10 -44
- package/dist/server/rate-limit.d.ts +5 -18
- package/dist/server/rate-limit.js +4 -13
- package/dist/server/request.d.ts +4 -8
- package/dist/server/request.js +9 -17
- package/dist/server/route-table.js +42 -49
- package/dist/server/routes/admin.js +22 -28
- package/dist/server/routes/customer-notes.js +7 -12
- package/dist/server/routes/decisions.js +10 -17
- package/dist/server/routes/incidents.js +12 -20
- package/dist/server/routes/memories.js +12 -32
- package/dist/server/routes/object-routes.d.ts +0 -5
- package/dist/server/routes/object-routes.js +7 -15
- package/dist/server/routes/policies.js +10 -18
- package/dist/server/routes/predictions.js +13 -25
- package/dist/server/routes/processes.js +16 -26
- package/dist/server/routes/project-briefs.js +9 -16
- package/dist/server/routes/recall.js +10 -35
- package/dist/server/routes/skills.js +8 -18
- package/dist/server/server-detect.d.ts +9 -53
- package/dist/server/server-detect.js +24 -90
- package/dist/server/sleep-offload.js +4 -1
- package/dist/server/types.d.ts +12 -10
- package/dist/server/validation.d.ts +3 -1
- package/dist/server/validation.js +10 -23
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -2
- package/dist/sharing/global-store.d.ts +19 -0
- package/dist/sharing/global-store.js +75 -0
- package/dist/sharing/global-sync.d.ts +6 -0
- package/dist/sharing/global-sync.js +80 -0
- package/dist/sharing/project-merge.d.ts +4 -5
- package/dist/sharing/project-merge.js +9 -7
- package/dist/sharing/scope.d.ts +4 -11
- package/dist/sharing/scope.js +4 -11
- package/dist/sharing/search-both.d.ts +60 -0
- package/dist/sharing/search-both.js +138 -0
- package/dist/sharing/share.d.ts +38 -0
- package/dist/sharing/share.js +226 -0
- package/dist/store/ambient.js +4 -9
- package/dist/store/audit-event.d.ts +4 -12
- package/dist/store/audit-event.js +4 -12
- package/dist/store/audit.d.ts +2 -5
- package/dist/store/audit.js +4 -12
- package/dist/store/auth.d.ts +6 -6
- package/dist/store/auth.js +10 -9
- package/dist/store/candidates.d.ts +20 -3
- package/dist/store/candidates.js +77 -48
- package/dist/store/card-detail.d.ts +2 -1
- package/dist/store/card-detail.js +2 -1
- package/dist/store/cards.d.ts +14 -9
- package/dist/store/cards.js +72 -126
- package/dist/store/conflicts.d.ts +4 -21
- package/dist/store/conflicts.js +71 -150
- package/dist/store/connectors/github.d.ts +10 -10
- package/dist/store/connectors/github.js +10 -10
- package/dist/store/dashboard-reads.js +4 -8
- package/dist/store/delete-and-batch.d.ts +11 -31
- package/dist/store/delete-and-batch.js +48 -64
- package/dist/store/delivery-recorder.d.ts +8 -4
- package/dist/store/delivery-recorder.js +25 -15
- package/dist/store/diagnostics.js +6 -13
- package/dist/store/dormant.d.ts +7 -29
- package/dist/store/dormant.js +15 -56
- package/dist/store/embeddings/index.d.ts +11 -80
- package/dist/store/embeddings/index.js +71 -207
- package/dist/store/embeddings/local.js +15 -32
- package/dist/store/embeddings/provider.d.ts +16 -53
- package/dist/store/embeddings/provider.js +41 -69
- package/dist/store/entry-reads.d.ts +21 -57
- package/dist/store/entry-reads.js +65 -126
- package/dist/store/entry-row.d.ts +6 -35
- package/dist/store/entry-row.js +9 -37
- package/dist/store/entry-writes.d.ts +10 -16
- package/dist/store/entry-writes.js +17 -35
- package/dist/store/goals.d.ts +3 -40
- package/dist/store/goals.js +21 -160
- package/dist/store/graph-queue.d.ts +6 -22
- package/dist/store/graph-queue.js +14 -45
- package/dist/store/graph-reads.d.ts +11 -35
- package/dist/store/graph-reads.js +20 -58
- package/dist/store/graph-rows.d.ts +3 -6
- package/dist/store/graph-rows.js +6 -9
- package/dist/store/graph-view-rows.d.ts +2 -1
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -31
- package/dist/store/graph-writes.js +13 -37
- package/dist/store/half-life.d.ts +2 -1
- package/dist/store/half-life.js +14 -16
- package/dist/store/handoffs.d.ts +5 -11
- package/dist/store/handoffs.js +16 -34
- package/dist/store/index-and-stats.d.ts +6 -19
- package/dist/store/index-and-stats.js +34 -82
- package/dist/store/markdown.d.ts +2 -6
- package/dist/store/markdown.js +21 -20
- package/dist/store/mirrors.d.ts +2 -6
- package/dist/store/mirrors.js +14 -23
- package/dist/store/open.js +6 -13
- package/dist/store/planning-fallacy-evidence.d.ts +2 -30
- package/dist/store/planning-fallacy-evidence.js +8 -37
- package/dist/store/port.d.ts +82 -79
- package/dist/store/predictions.d.ts +11 -51
- package/dist/store/predictions.js +38 -119
- package/dist/{cli → store}/quality-repair.js +15 -31
- package/dist/store/raw-archive.d.ts +4 -16
- package/dist/store/raw-archive.js +14 -29
- package/dist/store/recall-scope.d.ts +19 -79
- package/dist/store/recall-scope.js +21 -82
- package/dist/store/recall-trace.d.ts +10 -77
- package/dist/store/recall-trace.js +19 -95
- package/dist/store/rejected-values.js +7 -19
- package/dist/store/rejection.d.ts +12 -58
- package/dist/store/rejection.js +13 -65
- package/dist/store/report-reads.d.ts +6 -0
- package/dist/store/report-reads.js +29 -0
- package/dist/store/rows.d.ts +9 -19
- package/dist/store/rows.js +36 -34
- package/dist/store/rule-sql.d.ts +5 -0
- package/dist/store/rule-sql.js +37 -0
- package/dist/store/search-rows.d.ts +7 -38
- package/dist/store/search-rows.js +14 -50
- package/dist/store/sessions.d.ts +10 -47
- package/dist/store/sessions.js +17 -73
- package/dist/store/sqlite/connector-events-group.js +2 -2
- package/dist/store/sqlite/entry-writes-group.js +2 -2
- package/dist/store/sqlite/error-codec.js +4 -2
- package/dist/store/sqlite/executor.d.ts +2 -1
- package/dist/store/sqlite/executor.js +2 -1
- package/dist/store/sqlite/local.d.ts +3 -3
- package/dist/store/sqlite/local.js +1 -0
- package/dist/store/sqlite/object-rows.js +6 -3
- package/dist/store/sqlite/objects-group.js +4 -2
- package/dist/store/sqlite/quarantine-group.js +2 -2
- package/dist/store/sqlite/store.d.ts +1 -4
- package/dist/store/sqlite/store.js +2 -3
- package/dist/store/sqlite/vector-reads-group.js +2 -2
- package/dist/store/sqlite/worker-jobs.js +1 -1
- package/dist/store/sqlite/worker-ops.d.ts +13 -2
- package/dist/store/sqlite/worker-ops.js +13 -2
- package/dist/store/sqlite/worker-store.js +5 -2
- package/dist/store/summaries.d.ts +10 -62
- package/dist/store/summaries.js +34 -146
- package/dist/store/summary-dirty.js +1 -1
- package/dist/store/tenant-lookup.d.ts +6 -1
- package/dist/store/tenant-lookup.js +7 -0
- package/dist/store/tenant.d.ts +2 -16
- package/dist/store/tenant.js +4 -19
- package/dist/store/token-ledger.d.ts +13 -43
- package/dist/store/token-ledger.js +19 -50
- package/dist/store/usage-reports.js +5 -13
- package/dist/store/vector-index.d.ts +46 -0
- package/dist/store/vector-index.js +170 -0
- package/dist/store/working-memory.d.ts +6 -25
- package/dist/store/working-memory.js +18 -52
- package/dist/store/yaml.d.ts +1 -5
- package/dist/store/yaml.js +2 -6
- package/dist/support-bundle.js +7 -5
- package/dist/trust/reject-flow.js +1 -3
- package/dist/util/anthropic-messages.js +14 -2
- package/dist/util/atomic-write.d.ts +2 -1
- package/dist/util/atomic-write.js +35 -4
- package/dist/util/capped-json.d.ts +6 -0
- package/dist/util/capped-json.js +46 -0
- package/dist/util/crash-handlers.d.ts +8 -1
- package/dist/util/crash-handlers.js +52 -10
- package/dist/util/env.d.ts +13 -6
- package/dist/util/env.js +14 -7
- package/dist/util/home-path.d.ts +2 -1
- package/dist/util/home-path.js +4 -2
- package/dist/util/http-retry.d.ts +3 -1
- package/dist/util/http-retry.js +26 -5
- package/dist/util/log.d.ts +3 -2
- package/dist/util/log.js +25 -9
- package/dist/util/request-scope.d.ts +2 -1
- package/dist/util/request-scope.js +2 -1
- package/dist/util/secret-detect.d.ts +5 -30
- package/dist/util/secret-detect.js +13 -39
- package/dist/util/stored-json.d.ts +1 -1
- package/dist/util/stored-json.js +1 -1
- package/dist/util/token-text.d.ts +1 -4
- package/dist/util/token-text.js +1 -4
- package/dist/util/transcript-tail.d.ts +2 -0
- package/dist/util/transcript-tail.js +24 -23
- package/dist/util/version.d.ts +5 -20
- package/dist/util/version.js +5 -20
- package/extensions/openclaw-plugin/index.ts +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/dist/connectors/github/cli-impl.d.ts +0 -25
- package/dist/sharing/shared.d.ts +0 -187
- package/dist/sharing/shared.js +0 -563
- package/dist/store/vector-writes.d.ts +0 -13
- package/dist/store/vector-writes.js +0 -89
- /package/dist/{cli → store}/quality-repair.d.ts +0 -0
package/dist/api/tokens.d.ts
CHANGED
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
import type { TokenSummary, TokenSurface } from '../store/token-ledger.js';
|
|
2
2
|
import type { FailureSummary } from '../store/failure-log.js';
|
|
3
3
|
import type { Context } from './types.js';
|
|
4
|
-
/**
|
|
5
|
-
* Record memory text handed to an agent in the token ledger.
|
|
6
|
-
* Best-effort: never throws, because a ledger failure must not fail the
|
|
7
|
-
* recall or context call that produced the text.
|
|
8
|
-
*/
|
|
4
|
+
/** Records memory text handed to an agent in the token ledger. Best-effort: never throws, since a ledger failure must not fail the recall or context call. */
|
|
9
5
|
export declare function recordTokens(ctx: Context, surface: TokenSurface, use: {
|
|
10
6
|
items: number;
|
|
11
7
|
tokens: number;
|
|
12
8
|
sessionId?: string | null;
|
|
13
9
|
}): Promise<void>;
|
|
14
|
-
/**
|
|
15
|
-
*
|
|
16
|
-
* tokens sent, skipped as unchanged and re-read by later model calls, per
|
|
17
|
-
* surface, with session counts and mean tokens per session.
|
|
18
|
-
*/
|
|
10
|
+
/** Token ledger totals for the tenant over the last `days` days (default 30): tokens sent, skipped as unchanged and re-read,
|
|
11
|
+
* per surface, with session counts and mean tokens per session. */
|
|
19
12
|
export declare function tokenSummary(ctx: Context, opts?: {
|
|
20
13
|
days?: number;
|
|
21
14
|
}): TokenSummary;
|
package/dist/api/tokens.js
CHANGED
|
@@ -4,11 +4,7 @@ import { storeFor } from '../store/index.js';
|
|
|
4
4
|
import { failureLogSummary, tokenUseSummary } from '../store/usage-reports.js';
|
|
5
5
|
import { errorMessage, log } from '../util/log.js';
|
|
6
6
|
import { DAY_MS } from '../util/time.js';
|
|
7
|
-
/**
|
|
8
|
-
* Record memory text handed to an agent in the token ledger.
|
|
9
|
-
* Best-effort: never throws, because a ledger failure must not fail the
|
|
10
|
-
* recall or context call that produced the text.
|
|
11
|
-
*/
|
|
7
|
+
/** Records memory text handed to an agent in the token ledger. Best-effort: never throws, since a ledger failure must not fail the recall or context call. */
|
|
12
8
|
export async function recordTokens(ctx, surface, use) {
|
|
13
9
|
try {
|
|
14
10
|
await storeFor(ctx).recordTokens({
|
|
@@ -25,11 +21,8 @@ export async function recordTokens(ctx, surface, use) {
|
|
|
25
21
|
log.warnThenDebug('api-token-ledger', `token ledger write failed; the reply is unaffected: ${errorMessage(err)}`);
|
|
26
22
|
}
|
|
27
23
|
}
|
|
28
|
-
/**
|
|
29
|
-
*
|
|
30
|
-
* tokens sent, skipped as unchanged and re-read by later model calls, per
|
|
31
|
-
* surface, with session counts and mean tokens per session.
|
|
32
|
-
*/
|
|
24
|
+
/** Token ledger totals for the tenant over the last `days` days (default 30): tokens sent, skipped as unchanged and re-read,
|
|
25
|
+
* per surface, with session counts and mean tokens per session. */
|
|
33
26
|
export function tokenSummary(ctx, opts = {}) {
|
|
34
27
|
return tokenUseSummary(ctx.hippoRoot, ctx.tenantId, reportWindowStart(opts.days));
|
|
35
28
|
}
|
package/dist/api/types.d.ts
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import { BadRequestError } from '../core/api-errors.js';
|
|
2
2
|
import type { HippoStore } from '../store/index.js';
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Carries the audit-log subject plus a role for /v1/sleep admin gating. Audit
|
|
7
|
-
* helpers take the bare `string`, so callers pass `ctx.actor.subject`. Role checks happen at the request
|
|
8
|
-
* boundary (e.g. /v1/sleep), except in authCreate and authRevoke (ForbiddenError).
|
|
9
|
-
*/
|
|
3
|
+
/** Actor identity + role for a Context: the audit-log subject (pass `ctx.actor.subject` to audit helpers) and the role for admin gating.
|
|
4
|
+
* Role checks happen at the request boundary (e.g. /v1/sleep), except in authCreate and authRevoke (ForbiddenError). */
|
|
10
5
|
export interface Actor {
|
|
11
6
|
/** 'cli' | 'localhost:cli' | 'api_key:<key_id>' | 'mcp' | 'connector:slack' | 'connector:github' */
|
|
12
7
|
subject: string;
|
|
@@ -34,31 +29,13 @@ export type StoreReply<C extends Context, R> = C extends {
|
|
|
34
29
|
readonly hippoRoot: string;
|
|
35
30
|
readonly store?: undefined;
|
|
36
31
|
} ? R : R | Promise<R>;
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
39
|
-
* used by CLI and CLI-run connector Context constructors so the role
|
|
40
|
-
* boilerplate isn't repeated at every site. Bearer-authed callers (HTTP
|
|
41
|
-
* /v1/*) construct Actor directly from the api_keys row's role column via
|
|
42
|
-
* buildContextWithAuth in src/server.ts.
|
|
43
|
-
*/
|
|
32
|
+
/** Builds process-local Actor values (admin and host admin) for CLI and CLI-run connector Contexts; Bearer-authed callers build Actor from the api_keys row
|
|
33
|
+
* instead. */
|
|
44
34
|
export declare function adminActor(subject: string): Actor;
|
|
45
35
|
/** The per-person key: an unowned key gets its own bucket by key id rather than sharing one. */
|
|
46
36
|
export declare function ownerOrSubject(actor: Actor): string;
|
|
47
|
-
/**
|
|
48
|
-
*
|
|
49
|
-
* that has been opted into via env. Carries a stable `code` field for HTTP /
|
|
50
|
-
* MCP / CLI render paths to discriminate without parsing the message.
|
|
51
|
-
*
|
|
52
|
-
* Codes:
|
|
53
|
-
* - 'fresh_tail_requires_session_id' — `freshTailCount > 0` AND no
|
|
54
|
-
* `freshTailSessionId` AND `HIPPO_REQUIRE_SESSION_SCOPED_FRESH_TAIL=1`.
|
|
55
|
-
* Default behaviour (env unset) returns tenant-wide rows; the env gate
|
|
56
|
-
* is opt-in so multi-session tenants can fail loud instead of silently
|
|
57
|
-
* surfacing cross-session rows tagged `isFreshTail=true`.
|
|
58
|
-
* - 'invalid_scorer_window' — `opts.scorerWindow` is set to a non-positive,
|
|
59
|
-
* non-integer, or non-finite value. 0 would route through FTS/LIKE
|
|
60
|
-
* `LIMIT 0` and then an uncapped full-store fallback, so it is validated upfront.
|
|
61
|
-
*/
|
|
37
|
+
/** Thrown by `api.recall` on a contract violation; the stable `code` lets callers discriminate without parsing the message.
|
|
38
|
+
* 'fresh_tail_requires_session_id' (needs HIPPO_REQUIRE_SESSION_SCOPED_FRESH_TAIL=1) or 'invalid_scorer_window' (0 would hit an uncapped fallback). */
|
|
62
39
|
export declare class RecallContractError extends BadRequestError {
|
|
63
40
|
readonly code: 'fresh_tail_requires_session_id' | 'invalid_scorer_window';
|
|
64
41
|
constructor(code: 'fresh_tail_requires_session_id' | 'invalid_scorer_window', message: string);
|
package/dist/api/types.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
// Request context (caller identity and tenant) shared by every API module, plus the recall contract error.
|
|
2
2
|
import { BadRequestError } from '../core/api-errors.js';
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
* used by CLI and CLI-run connector Context constructors so the role
|
|
6
|
-
* boilerplate isn't repeated at every site. Bearer-authed callers (HTTP
|
|
7
|
-
* /v1/*) construct Actor directly from the api_keys row's role column via
|
|
8
|
-
* buildContextWithAuth in src/server.ts.
|
|
9
|
-
*/
|
|
3
|
+
/** Builds process-local Actor values (admin and host admin) for CLI and CLI-run connector Contexts; Bearer-authed callers build Actor from the api_keys row
|
|
4
|
+
* instead. */
|
|
10
5
|
export function adminActor(subject) {
|
|
11
6
|
return { subject, role: 'admin', hostAdmin: true };
|
|
12
7
|
}
|
|
@@ -14,21 +9,8 @@ export function adminActor(subject) {
|
|
|
14
9
|
export function ownerOrSubject(actor) {
|
|
15
10
|
return actor.owner ?? actor.subject;
|
|
16
11
|
}
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
* that has been opted into via env. Carries a stable `code` field for HTTP /
|
|
20
|
-
* MCP / CLI render paths to discriminate without parsing the message.
|
|
21
|
-
*
|
|
22
|
-
* Codes:
|
|
23
|
-
* - 'fresh_tail_requires_session_id' — `freshTailCount > 0` AND no
|
|
24
|
-
* `freshTailSessionId` AND `HIPPO_REQUIRE_SESSION_SCOPED_FRESH_TAIL=1`.
|
|
25
|
-
* Default behaviour (env unset) returns tenant-wide rows; the env gate
|
|
26
|
-
* is opt-in so multi-session tenants can fail loud instead of silently
|
|
27
|
-
* surfacing cross-session rows tagged `isFreshTail=true`.
|
|
28
|
-
* - 'invalid_scorer_window' — `opts.scorerWindow` is set to a non-positive,
|
|
29
|
-
* non-integer, or non-finite value. 0 would route through FTS/LIKE
|
|
30
|
-
* `LIMIT 0` and then an uncapped full-store fallback, so it is validated upfront.
|
|
31
|
-
*/
|
|
12
|
+
/** Thrown by `api.recall` on a contract violation; the stable `code` lets callers discriminate without parsing the message.
|
|
13
|
+
* 'fresh_tail_requires_session_id' (needs HIPPO_REQUIRE_SESSION_SCOPED_FRESH_TAIL=1) or 'invalid_scorer_window' (0 would hit an uncapped fallback). */
|
|
32
14
|
export class RecallContractError extends BadRequestError {
|
|
33
15
|
code;
|
|
34
16
|
constructor(code, message) {
|
|
@@ -12,21 +12,13 @@ export interface CaptureOptions {
|
|
|
12
12
|
stdinText?: string;
|
|
13
13
|
stdinTimedOut?: boolean;
|
|
14
14
|
sessionTurns?: readonly SessionTurn[];
|
|
15
|
-
/**
|
|
16
|
-
*
|
|
17
|
-
* pattern used by `hippo sleep --log-file` so the SessionEnd hook output
|
|
18
|
-
* (invisible during TUI teardown) can be surfaced via `hippo last-sleep`
|
|
19
|
-
* on the next session start. Appends rather than truncates — `hippo sleep`
|
|
20
|
-
* writes the same file first in the SessionEnd sequence.
|
|
21
|
-
*/
|
|
15
|
+
/** Tee stdout/stderr to this log file while capture runs, so SessionEnd output (lost in TUI teardown) shows via `hippo last-sleep`.
|
|
16
|
+
* Appends, because `hippo sleep` writes the same file first. */
|
|
22
17
|
logFile?: string;
|
|
23
18
|
dryRun: boolean;
|
|
24
19
|
global: boolean;
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
* AND `global` is false, the dedup check only considers this tenant's
|
|
28
|
-
* existing memories. Undefined means host-wide dedup. Ignored when `global: true` (global captures are host-wide).
|
|
29
|
-
*/
|
|
20
|
+
/** Tenant scope for the dedup read in `cmdCaptureCore`: when set and `global` is false, only this tenant's memories count.
|
|
21
|
+
* Undefined means host-wide dedup; ignored when `global: true`. */
|
|
30
22
|
tenantId?: string;
|
|
31
23
|
/** The session's project: rows are stamped with its id, and dedup reads its rows under either name. */
|
|
32
24
|
originProject?: ProjectRef;
|
package/dist/capture/command.js
CHANGED
|
@@ -8,7 +8,7 @@ import { writeEntryMirrors } from '../store/entry-writes.js';
|
|
|
8
8
|
import { EVERY_SCOPE, loadTextsHoldingWords } from '../store/candidates.js';
|
|
9
9
|
import { updateStatsOn } from '../store/index-and-stats.js';
|
|
10
10
|
import { gatedWrite } from '../trust/gated-write.js';
|
|
11
|
-
import { getGlobalRoot, initGlobal } from '../sharing/
|
|
11
|
+
import { getGlobalRoot, initGlobal } from '../sharing/global-store.js';
|
|
12
12
|
import { embedMemory } from '../store/embeddings/index.js';
|
|
13
13
|
import { maskEmails, redactSecretsStrict } from '../util/secret-detect.js';
|
|
14
14
|
import { RejectedValueError, checkRejectionGuard } from '../store/rejection.js';
|
|
@@ -20,11 +20,7 @@ import { errorMessage, log } from '../util/log.js';
|
|
|
20
20
|
import { extractFromTexts } from './extract.js';
|
|
21
21
|
import { collectSessionTurns, sessionTail, resolveLastSessionTranscript } from './transcript.js';
|
|
22
22
|
export function cmdCapture(hippoRoot, options) {
|
|
23
|
-
// Tee
|
|
24
|
-
// SessionEnd hook so output (otherwise swallowed by TUI teardown) surfaces
|
|
25
|
-
// on the next session start via `hippo last-sleep`. Runs second in the
|
|
26
|
-
// SessionEnd sequence after `hippo sleep`, so we APPEND rather than
|
|
27
|
-
// truncate — sleep already wrote its own header + body to this file.
|
|
23
|
+
// Tee to a log file for the SessionEnd hook; APPEND, because `hippo sleep` runs first in that sequence and already wrote its header and body.
|
|
28
24
|
const restoreStdio = options.logFile ? beginLogTee(options.logFile) : null;
|
|
29
25
|
try {
|
|
30
26
|
cmdCaptureCore(hippoRoot, options);
|
|
@@ -41,12 +37,7 @@ export function cmdCapture(hippoRoot, options) {
|
|
|
41
37
|
restoreStdio();
|
|
42
38
|
}
|
|
43
39
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Append-mode tee: writes a banner line then mirrors every stdout/stderr
|
|
46
|
-
* chunk to `logFile` until the returned restore function is called.
|
|
47
|
-
* Failures to write the log are non-fatal; the real streams still get
|
|
48
|
-
* the data.
|
|
49
|
-
*/
|
|
40
|
+
/** Append-mode tee: mirror every stdout/stderr chunk to `logFile` until the returned restore function is called; a log-write failure is non-fatal. */
|
|
50
41
|
function beginLogTee(logFile) {
|
|
51
42
|
if (!writeLogBanner(logFile))
|
|
52
43
|
return () => { };
|
|
@@ -56,16 +47,10 @@ function beginLogTee(logFile) {
|
|
|
56
47
|
const wrapWrite = (origWrite) => {
|
|
57
48
|
const wrapped = (...args) => {
|
|
58
49
|
tee(args[0]);
|
|
59
|
-
// SAFETY: forwarding the exact arguments
|
|
60
|
-
// `write` received is safe regardless of which overload the call
|
|
61
|
-
// site used — Node dispatches on the actual argument shapes at
|
|
62
|
-
// runtime, and `StreamWriteArgs` is the union of both overloads'
|
|
63
|
-
// parameter lists.
|
|
50
|
+
// SAFETY: forwarding the exact arguments the real overloaded `write` received is safe; `StreamWriteArgs` is the union of both overloads' parameter lists.
|
|
64
51
|
return origWrite(...args);
|
|
65
52
|
};
|
|
66
|
-
// SAFETY: `wrapped` matches both real `write` overload shapes
|
|
67
|
-
// assigned to; TS can't verify a single implementation covers an
|
|
68
|
-
// overloaded type, but this one forwards to the real stream method.
|
|
53
|
+
// SAFETY: `wrapped` matches both real `write` overload shapes; TS cannot verify one implementation covers an overloaded type.
|
|
69
54
|
return wrapped;
|
|
70
55
|
};
|
|
71
56
|
process.stdout.write = wrapWrite(origStdoutWrite);
|
|
@@ -131,8 +116,7 @@ function cmdCaptureCore(hippoRoot, options) {
|
|
|
131
116
|
};
|
|
132
117
|
printCaptureTally(options, captureExtractedItems(targetRoot, writeOpts, extracted, keys));
|
|
133
118
|
}
|
|
134
|
-
// Dedup only against rows this capture's reader sees: another tenant's rows,
|
|
135
|
-
// project's, are hidden from it, so they must not stop its own copy.
|
|
119
|
+
// Dedup only against rows this capture's reader sees: another tenant's or project's rows are hidden, so they must not stop its own copy.
|
|
136
120
|
// Only a row holding an item's longest word can hold that item, so the store returns those rows and no others.
|
|
137
121
|
function storedKeysInView(targetRoot, options, extracted) {
|
|
138
122
|
const stored = loadTextsHoldingWords(targetRoot, options.global ? undefined : options.tenantId, extracted.map((item) => longestWord(item.content)), undefined, EVERY_SCOPE);
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import { type HookRuntime } from '../core/capture-contract.js';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* (transcript paths, session ids). Strip C0 control chars — newlines above
|
|
5
|
-
* all — so a crafted value can't inject fake `[hippo] ...` log lines.
|
|
6
|
-
* Exported for every `[hippo]`-prefixed log writer that interpolates
|
|
7
|
-
* payload-controlled values (cli.ts appendSessionEndCloseLog) — one shared
|
|
8
|
-
* guard, not per-file copies.
|
|
9
|
-
*/
|
|
2
|
+
/** Log-forgery guard: strip C0 control chars (newlines above all) from payload-controlled values so a crafted value cannot inject fake `[hippo]` log lines.
|
|
3
|
+
* Exported as the one shared guard for every `[hippo]`-prefixed log writer that interpolates payload values. */
|
|
10
4
|
export declare function sanitizeLogMessage(message: string): string;
|
|
11
5
|
export interface PreCompactOptions {
|
|
12
6
|
stdinText?: string;
|
|
@@ -16,13 +10,8 @@ export interface PreCompactOptions {
|
|
|
16
10
|
/** Called once when the hook accepts a compaction, with the text it printed or null when it printed none. */
|
|
17
11
|
onBoundary?: (printed: string | null) => void;
|
|
18
12
|
}
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
* so this verb must exit 0 on every path — malformed stdin, missing
|
|
22
|
-
* transcript, and store errors all degrade to a logged no-op rather than a
|
|
23
|
-
* thrown error. Callers (src/cli.ts) must not wrap this in anything that
|
|
24
|
-
* could turn a caught-and-logged failure back into a non-zero exit.
|
|
25
|
-
*/
|
|
13
|
+
/** PreCompact hook entry point. Exit code 2 BLOCKS compaction, so every path (bad stdin, missing transcript, store error) must exit 0 as a logged no-op.
|
|
14
|
+
* Callers must not wrap this in anything that turns a caught-and-logged failure into a non-zero exit. */
|
|
26
15
|
export declare function cmdPreCompact(hippoRoot: string, options: PreCompactOptions): Promise<void>;
|
|
27
16
|
export interface PostCompactOptions {
|
|
28
17
|
stdinText?: string;
|
package/dist/capture/compact.js
CHANGED
|
@@ -10,19 +10,10 @@ import { errorMessage, log as logger } from '../util/log.js';
|
|
|
10
10
|
import { resolveLastSessionTranscript } from './transcript.js';
|
|
11
11
|
import { isVscodeTranscript } from './copilot-transcript.js';
|
|
12
12
|
import { mergeWorkingState, transcriptWorkingState } from './working-state.js';
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// `hippo pre-compact` — PreCompact hook producer
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
13
|
// Diagnostic-only log; a long-lived install must not grow it unbounded.
|
|
17
14
|
const PRE_COMPACT_LOG_MAX_BYTES = 256 * 1024;
|
|
18
|
-
/**
|
|
19
|
-
*
|
|
20
|
-
* (transcript paths, session ids). Strip C0 control chars — newlines above
|
|
21
|
-
* all — so a crafted value can't inject fake `[hippo] ...` log lines.
|
|
22
|
-
* Exported for every `[hippo]`-prefixed log writer that interpolates
|
|
23
|
-
* payload-controlled values (cli.ts appendSessionEndCloseLog) — one shared
|
|
24
|
-
* guard, not per-file copies.
|
|
25
|
-
*/
|
|
15
|
+
/** Log-forgery guard: strip C0 control chars (newlines above all) from payload-controlled values so a crafted value cannot inject fake `[hippo]` log lines.
|
|
16
|
+
* Exported as the one shared guard for every `[hippo]`-prefixed log writer that interpolates payload values. */
|
|
26
17
|
export function sanitizeLogMessage(message) {
|
|
27
18
|
// eslint-disable-next-line no-control-regex
|
|
28
19
|
return message.replace(/[\x00-\x1f]/g, '');
|
|
@@ -30,11 +21,18 @@ export function sanitizeLogMessage(message) {
|
|
|
30
21
|
function appendPreCompactLog(logFile, message) {
|
|
31
22
|
try {
|
|
32
23
|
fs.mkdirSync(path.dirname(logFile), { recursive: true });
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
// One handle, so the cap acts on the file it measured; two hooks writing in the same instant can overwrite one diagnostic line, which this log accepts.
|
|
25
|
+
const fd = fs.openSync(logFile, fs.constants.O_RDWR | fs.constants.O_CREAT);
|
|
26
|
+
try {
|
|
27
|
+
const size = fs.fstatSync(fd).size;
|
|
28
|
+
const startFresh = size > PRE_COMPACT_LOG_MAX_BYTES; // a dumb cap, no rotation
|
|
29
|
+
if (startFresh)
|
|
30
|
+
fs.ftruncateSync(fd, 0);
|
|
31
|
+
fs.writeSync(fd, `[hippo] ${new Date().toISOString()} ${sanitizeLogMessage(message)}\n`, startFresh ? 0 : size, 'utf8');
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
fs.closeSync(fd);
|
|
36
35
|
}
|
|
37
|
-
fs.appendFileSync(logFile, `[hippo] ${new Date().toISOString()} ${sanitizeLogMessage(message)}\n`, 'utf8');
|
|
38
36
|
}
|
|
39
37
|
catch (err) {
|
|
40
38
|
// Diagnostic-only; a log write failure must never affect the exit-0 contract.
|
|
@@ -74,9 +72,7 @@ function snapshotJustSaved(hippoRoot, sessionId) {
|
|
|
74
72
|
/** Runs the PreCompact producer: records the compaction, asks the summariser for memories, saves a working-state snapshot. Never extracts memories itself; SessionEnd capture owns that. */
|
|
75
73
|
function runPreCompact(hippoRoot, options, logFile) {
|
|
76
74
|
const { stdinText, stdinTimedOut = false, runtime = 'claude-code' } = options;
|
|
77
|
-
//
|
|
78
|
-
// ones that never ran `hippo init`, so gate before any store-opening call
|
|
79
|
-
// (saveActiveTaskSnapshot etc. call initStore, which would create one).
|
|
75
|
+
// PreCompact fires in every Claude Code project, including ones that never ran `hippo init`; gate before any call that would create a store.
|
|
80
76
|
if (!isInitialized(hippoRoot)) {
|
|
81
77
|
appendPreCompactLog(logFile, 'skip: store not initialized');
|
|
82
78
|
return;
|
|
@@ -180,13 +176,8 @@ function saveDerivedSnapshot(hippoRoot, logFile, sessionId, recordId, derived) {
|
|
|
180
176
|
}
|
|
181
177
|
}
|
|
182
178
|
}
|
|
183
|
-
/**
|
|
184
|
-
*
|
|
185
|
-
* so this verb must exit 0 on every path — malformed stdin, missing
|
|
186
|
-
* transcript, and store errors all degrade to a logged no-op rather than a
|
|
187
|
-
* thrown error. Callers (src/cli.ts) must not wrap this in anything that
|
|
188
|
-
* could turn a caught-and-logged failure back into a non-zero exit.
|
|
189
|
-
*/
|
|
179
|
+
/** PreCompact hook entry point. Exit code 2 BLOCKS compaction, so every path (bad stdin, missing transcript, store error) must exit 0 as a logged no-op.
|
|
180
|
+
* Callers must not wrap this in anything that turns a caught-and-logged failure into a non-zero exit. */
|
|
190
181
|
export async function cmdPreCompact(hippoRoot, options) {
|
|
191
182
|
const logFile = options.logFile ?? defaultPreCompactLogPath();
|
|
192
183
|
try {
|
|
@@ -284,6 +284,55 @@ export function saveItems(db, hippoRoot, ctx, log) {
|
|
|
284
284
|
finishItemWrites(hippoRoot, writes, log);
|
|
285
285
|
return writes.written.length;
|
|
286
286
|
}
|
|
287
|
+
/** One failure, told once to the hook's output and once to the structured log. */
|
|
288
|
+
function reportFailure(log, step, reason) {
|
|
289
|
+
log(`${step} failed: ${reason}`);
|
|
290
|
+
logger.error(`post-compact: ${step} failed: ${reason}`);
|
|
291
|
+
}
|
|
292
|
+
function recordStep(step) {
|
|
293
|
+
try {
|
|
294
|
+
const record = recordSummary(step.db, step.hippoRoot, step.tenantId, { meta: step.payload, text: step.text, at: step.at });
|
|
295
|
+
step.result.snapshotSaved = record.snapshotSaved;
|
|
296
|
+
return record;
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
if (isSqliteBusy(err))
|
|
300
|
+
throw err;
|
|
301
|
+
reportFailure(step.log, 'record step', errorMessage(err));
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/** Busy with a saved record defers to sleep; any other failure goes to the caller. */
|
|
306
|
+
function itemsStep(step, record) {
|
|
307
|
+
const { payload, hippoRoot, log } = step;
|
|
308
|
+
try {
|
|
309
|
+
step.result.written = saveItems(step.db, hippoRoot, {
|
|
310
|
+
tenantId: step.tenantId,
|
|
311
|
+
recordId: record?.id ?? null,
|
|
312
|
+
sessionId: payload.sessionId,
|
|
313
|
+
originProject: record?.originProject ?? compactionOrigin(hippoRoot, payload.cwd),
|
|
314
|
+
cwd: payload.cwd,
|
|
315
|
+
items: step.text.items,
|
|
316
|
+
}, log);
|
|
317
|
+
}
|
|
318
|
+
catch (err) {
|
|
319
|
+
if (!isSqliteBusy(err) || record === null)
|
|
320
|
+
throw err;
|
|
321
|
+
// The record already holds the items; sleep finishes them.
|
|
322
|
+
step.result.deferred = true;
|
|
323
|
+
log(`store busy, items left for the next sleep: ${errorMessage(err)}`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
function spoolSummary(hippoRoot, payload, text, at, reason, result, log) {
|
|
327
|
+
try {
|
|
328
|
+
spool(hippoRoot, resolveTenantId({}), payload, text, at);
|
|
329
|
+
result.deferred = true;
|
|
330
|
+
log(`store busy, summary spooled: ${reason}`);
|
|
331
|
+
}
|
|
332
|
+
catch (spoolErr) {
|
|
333
|
+
reportFailure(log, 'spool', errorMessage(spoolErr));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
287
336
|
/** The PostCompact work: record the summary, then write its items. Each step is independent; a busy store spools or defers. Never throws. */
|
|
288
337
|
export function saveCompaction(hippoRoot, payload, log) {
|
|
289
338
|
const result = { written: null, deferred: false, snapshotSaved: false };
|
|
@@ -298,52 +347,14 @@ export function saveCompaction(hippoRoot, payload, log) {
|
|
|
298
347
|
let db;
|
|
299
348
|
try {
|
|
300
349
|
db = openHippoDb(hippoRoot, { busyWaitMs: COMPACTION_DB_WAIT_MS });
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
record = recordSummary(db, hippoRoot, tenantId, { meta: payload, text, at });
|
|
305
|
-
result.snapshotSaved = record.snapshotSaved;
|
|
306
|
-
}
|
|
307
|
-
catch (err) {
|
|
308
|
-
if (isSqliteBusy(err))
|
|
309
|
-
throw err;
|
|
310
|
-
log(`record step failed: ${errorMessage(err)}`);
|
|
311
|
-
logger.error(`post-compact: record step failed: ${errorMessage(err)}`);
|
|
312
|
-
}
|
|
313
|
-
try {
|
|
314
|
-
result.written = saveItems(db, hippoRoot, {
|
|
315
|
-
tenantId,
|
|
316
|
-
recordId: record?.id ?? null,
|
|
317
|
-
sessionId: payload.sessionId,
|
|
318
|
-
originProject: record?.originProject ?? compactionOrigin(hippoRoot, payload.cwd),
|
|
319
|
-
cwd: payload.cwd,
|
|
320
|
-
items: text.items,
|
|
321
|
-
}, log);
|
|
322
|
-
}
|
|
323
|
-
catch (err) {
|
|
324
|
-
if (!isSqliteBusy(err) || record === null)
|
|
325
|
-
throw err;
|
|
326
|
-
// The record already holds the items; sleep finishes them.
|
|
327
|
-
result.deferred = true;
|
|
328
|
-
log(`store busy, items left for the next sleep: ${errorMessage(err)}`);
|
|
329
|
-
}
|
|
350
|
+
const step = { db, hippoRoot, tenantId: resolveTenantId({}), payload, text, at, result, log };
|
|
351
|
+
itemsStep(step, recordStep(step));
|
|
330
352
|
}
|
|
331
353
|
catch (err) {
|
|
332
|
-
if (isSqliteBusy(err) || db === undefined)
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
log(`store busy, summary spooled: ${errorMessage(err)}`);
|
|
337
|
-
}
|
|
338
|
-
catch (spoolErr) {
|
|
339
|
-
log(`spool failed: ${errorMessage(spoolErr)}`);
|
|
340
|
-
logger.error(`post-compact: spool failed: ${errorMessage(spoolErr)}`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
log(`items step failed: ${errorMessage(err)}`);
|
|
345
|
-
logger.error(`post-compact: items step failed: ${errorMessage(err)}`);
|
|
346
|
-
}
|
|
354
|
+
if (isSqliteBusy(err) || db === undefined)
|
|
355
|
+
spoolSummary(hippoRoot, payload, text, at, errorMessage(err), result, log);
|
|
356
|
+
else
|
|
357
|
+
reportFailure(log, 'items step', errorMessage(err));
|
|
347
358
|
}
|
|
348
359
|
finally {
|
|
349
360
|
if (db)
|
|
@@ -400,61 +411,74 @@ function closeWithoutSummary(db, tenantId, id, log) {
|
|
|
400
411
|
function nextStartedAt(db, record) {
|
|
401
412
|
return nextCompactionStart(db, record.tenantId, record.sessionId, record.startedAt);
|
|
402
413
|
}
|
|
414
|
+
/** The one place a record becomes the argument saveItems takes. */
|
|
415
|
+
function itemContext(tenantId, record, items = record.items) {
|
|
416
|
+
return { tenantId, recordId: record.id, sessionId: record.sessionId, originProject: record.originProject, cwd: record.cwd, items };
|
|
417
|
+
}
|
|
403
418
|
/** Records a spooled summary, then writes its items. */
|
|
404
419
|
function spoolImporter(db, hippoRoot, log) {
|
|
405
420
|
return (spooled, recorded) => {
|
|
406
421
|
const record = recordSummary(db, hippoRoot, spooled.tenantId, { meta: spooled.payload, text: spooled.text, at: spooled.at });
|
|
407
422
|
// The record holds the items now, so the file is done even if the write below fails.
|
|
408
423
|
recorded();
|
|
409
|
-
saveItems(db, hippoRoot,
|
|
424
|
+
saveItems(db, hippoRoot, itemContext(spooled.tenantId, record), log);
|
|
410
425
|
};
|
|
411
426
|
}
|
|
412
|
-
|
|
413
|
-
export function replayCompactions(db, hippoRoot, log, deadline = Number.POSITIVE_INFINITY) {
|
|
414
|
-
const tenantId = resolveTenantId({});
|
|
415
|
-
const now = Date.now();
|
|
427
|
+
function replayStalled(db, hippoRoot, tenantId, now, log, deadline) {
|
|
416
428
|
let finished = 0;
|
|
417
429
|
const stalled = stalledSummarisedRows(db, tenantId, new Date(now - REPLAY_AFTER_MS).toISOString()).map(toRecord);
|
|
418
430
|
for (const record of stalled) {
|
|
419
431
|
if (Date.now() > deadline)
|
|
420
432
|
break;
|
|
421
433
|
try {
|
|
422
|
-
saveItems(db, hippoRoot,
|
|
434
|
+
saveItems(db, hippoRoot, itemContext(tenantId, record), log);
|
|
423
435
|
finished++;
|
|
424
436
|
}
|
|
425
437
|
catch (err) {
|
|
426
438
|
log(`replay of ${record.id} failed: ${errorMessage(err)}`);
|
|
427
439
|
}
|
|
428
440
|
}
|
|
441
|
+
return finished;
|
|
442
|
+
}
|
|
443
|
+
function replaySpool(db, hippoRoot, tenantId, log, deadline) {
|
|
429
444
|
try {
|
|
430
|
-
|
|
445
|
+
return importSpool(hippoRoot, tenantId, log, deadline, spoolImporter(db, hippoRoot, log));
|
|
431
446
|
}
|
|
432
447
|
catch (err) {
|
|
433
448
|
log(`spool import failed: ${errorMessage(err)}`);
|
|
449
|
+
return 0;
|
|
434
450
|
}
|
|
451
|
+
}
|
|
452
|
+
/** Fills one open record from its transcript; true when it saved items. */
|
|
453
|
+
function fillFromTranscript(db, hippoRoot, tenantId, record, log) {
|
|
454
|
+
if (record.transcriptPath === null || !fs.existsSync(record.transcriptPath))
|
|
455
|
+
return false;
|
|
456
|
+
const next = nextStartedAt(db, record);
|
|
457
|
+
const found = transcriptSummary(record.transcriptPath, Date.parse(record.startedAt), next === null ? Number.POSITIVE_INFINITY : Date.parse(next));
|
|
458
|
+
if (found === null) {
|
|
459
|
+
// The record is past REPLAY_AFTER_MS, so a window that is fully scanned or out of reach stays empty.
|
|
460
|
+
closeWithoutSummary(db, tenantId, record.id, log);
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
const { found: listed, ...text } = readCompactionText(found);
|
|
464
|
+
if (!listed)
|
|
465
|
+
log(`no memories section in the transcript summary for ${record.id}`);
|
|
466
|
+
if (!markSummarised(db, tenantId, record.id, { text, summarisedAt: new Date().toISOString() })) {
|
|
467
|
+
log(`${record.id} was filled by another process`);
|
|
468
|
+
return false;
|
|
469
|
+
}
|
|
470
|
+
saveItems(db, hippoRoot, itemContext(tenantId, record, text.items), log);
|
|
471
|
+
return true;
|
|
472
|
+
}
|
|
473
|
+
function replayOpen(db, hippoRoot, tenantId, now, log, deadline) {
|
|
474
|
+
let finished = 0;
|
|
435
475
|
const open = openTranscriptRows(db, tenantId, new Date(now - REPLAY_AFTER_MS).toISOString(), new Date(now - TRANSCRIPT_FILL_WINDOW_MS).toISOString()).map(toRecord);
|
|
436
476
|
for (const record of open) {
|
|
437
477
|
if (Date.now() > deadline)
|
|
438
478
|
break;
|
|
439
479
|
try {
|
|
440
|
-
if (
|
|
441
|
-
|
|
442
|
-
const next = nextStartedAt(db, record);
|
|
443
|
-
const found = transcriptSummary(record.transcriptPath, Date.parse(record.startedAt), next === null ? Number.POSITIVE_INFINITY : Date.parse(next));
|
|
444
|
-
if (found === null) {
|
|
445
|
-
// The record is past REPLAY_AFTER_MS, so a window that is fully scanned or out of reach stays empty.
|
|
446
|
-
closeWithoutSummary(db, tenantId, record.id, log);
|
|
447
|
-
continue;
|
|
448
|
-
}
|
|
449
|
-
const { found: listed, ...text } = readCompactionText(found);
|
|
450
|
-
if (!listed)
|
|
451
|
-
log(`no memories section in the transcript summary for ${record.id}`);
|
|
452
|
-
if (!markSummarised(db, tenantId, record.id, { text, summarisedAt: new Date().toISOString() })) {
|
|
453
|
-
log(`${record.id} was filled by another process`);
|
|
454
|
-
continue;
|
|
455
|
-
}
|
|
456
|
-
saveItems(db, hippoRoot, { tenantId, recordId: record.id, sessionId: record.sessionId, originProject: record.originProject, cwd: record.cwd, items: text.items }, log);
|
|
457
|
-
finished++;
|
|
480
|
+
if (fillFromTranscript(db, hippoRoot, tenantId, record, log))
|
|
481
|
+
finished++;
|
|
458
482
|
}
|
|
459
483
|
catch (err) {
|
|
460
484
|
log(`transcript fill of ${record.id} failed: ${errorMessage(err)}`);
|
|
@@ -462,6 +486,14 @@ export function replayCompactions(db, hippoRoot, log, deadline = Number.POSITIVE
|
|
|
462
486
|
}
|
|
463
487
|
return finished;
|
|
464
488
|
}
|
|
489
|
+
/** Finishes what a killed hook or a busy store left: `summarised` records, spool files, and `started` records the transcript can fill. Returns how many compactions it saved. */
|
|
490
|
+
export function replayCompactions(db, hippoRoot, log, deadline = Number.POSITIVE_INFINITY) {
|
|
491
|
+
const tenantId = resolveTenantId({});
|
|
492
|
+
const now = Date.now();
|
|
493
|
+
return replayStalled(db, hippoRoot, tenantId, now, log, deadline)
|
|
494
|
+
+ replaySpool(db, hippoRoot, tenantId, log, deadline)
|
|
495
|
+
+ replayOpen(db, hippoRoot, tenantId, now, log, deadline);
|
|
496
|
+
}
|
|
465
497
|
/** For `hippo sleep` and post-compact: opens the store itself and never throws. */
|
|
466
498
|
export function replayCompactionsAt(hippoRoot, log, opts = {}) {
|
|
467
499
|
let db;
|
|
@@ -21,7 +21,7 @@ export interface SpoolFs {
|
|
|
21
21
|
}): void;
|
|
22
22
|
}
|
|
23
23
|
/** Test-only seam, so a test can make one fs call fail; null restores the real fs. */
|
|
24
|
-
export declare function
|
|
24
|
+
export declare function _setSpoolFsForTests(next: SpoolFs | null): void;
|
|
25
25
|
export interface SpooledCompaction {
|
|
26
26
|
tenantId: string;
|
|
27
27
|
payload: PostCompactPayload;
|
|
@@ -29,7 +29,7 @@ const NEW_STEM = /^(\d{13})-[0-9a-f]{8}$/;
|
|
|
29
29
|
const LEGACY_STEM_TIME = /-(\d+)$/;
|
|
30
30
|
let fsx = fs;
|
|
31
31
|
/** Test-only seam, so a test can make one fs call fail; null restores the real fs. */
|
|
32
|
-
export function
|
|
32
|
+
export function _setSpoolFsForTests(next) {
|
|
33
33
|
fsx = next ?? fs;
|
|
34
34
|
}
|
|
35
35
|
const stamp = (ms) => String(Math.trunc(ms)).padStart(STAMP_DIGITS, '0');
|
|
@@ -30,7 +30,7 @@ export declare function readSessionTranscript(transcriptPath: string, log: (mess
|
|
|
30
30
|
/** The transcript, read once and scanned, or null with the reason logged. */
|
|
31
31
|
export declare function readSessionScan(transcriptPath: string, log: (message: string) => void): SessionScan | null;
|
|
32
32
|
/** Test-only seam, the scheduler's pattern: lets a test prove a network path never reaches the probe. Null restores it. */
|
|
33
|
-
export declare function
|
|
33
|
+
export declare function _setDigestExistsProbeForTests(probe: ((p: string) => boolean) | null): void;
|
|
34
34
|
/** The store root is realpath'd; transcript paths are not, and a deleted file has no realpath of its own. Null for a network path. */
|
|
35
35
|
export declare function realFsPath(p: string): string | null;
|
|
36
36
|
/** Repo-relative with forward slashes, '' for the root itself, null outside the repo or when the path cannot be resolved. */
|
|
@@ -18,7 +18,7 @@ import { loadLiveContentsBySourceAndTag } from '../store/entry-reads.js';
|
|
|
18
18
|
import { SNAPSHOT_AMBIENT_MAX_AGE_MS } from '../store/sessions.js';
|
|
19
19
|
import { loadLatestHandoff } from '../store/handoffs.js';
|
|
20
20
|
import { isSyntheticMessage } from '../store/token-ledger.js';
|
|
21
|
-
import {
|
|
21
|
+
import { readOpenTranscriptTail } from '../util/transcript-tail.js';
|
|
22
22
|
/** Five-word runs are stock phrases; six in a row is a copied clause. */
|
|
23
23
|
export const ECHO_WINDOW = 6;
|
|
24
24
|
/** Five sentences of about 150 chars leave room for the Changed line inside the total cap. */
|
|
@@ -228,11 +228,17 @@ export function scanSessionTranscript(jsonl) {
|
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
230
|
export function readSessionTranscript(transcriptPath, log) {
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
const fd = fs.openSync(transcriptPath, 'r');
|
|
232
|
+
try {
|
|
233
|
+
const size = fs.fstatSync(fd).size;
|
|
234
|
+
if (size <= READ_CAP_BYTES)
|
|
235
|
+
return fs.readFileSync(fd, 'utf8');
|
|
236
|
+
log(`digest: transcript is ${size} bytes, reading its last ${READ_CAP_BYTES}`);
|
|
237
|
+
return readOpenTranscriptTail(fd, size, READ_CAP_BYTES);
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
fs.closeSync(fd);
|
|
241
|
+
}
|
|
236
242
|
}
|
|
237
243
|
/** The transcript, read once and scanned, or null with the reason logged. */
|
|
238
244
|
export function readSessionScan(transcriptPath, log) {
|
|
@@ -246,7 +252,7 @@ export function readSessionScan(transcriptPath, log) {
|
|
|
246
252
|
}
|
|
247
253
|
let existsProbe = fs.existsSync;
|
|
248
254
|
/** Test-only seam, the scheduler's pattern: lets a test prove a network path never reaches the probe. Null restores it. */
|
|
249
|
-
export function
|
|
255
|
+
export function _setDigestExistsProbeForTests(probe) {
|
|
250
256
|
existsProbe = probe ?? fs.existsSync;
|
|
251
257
|
}
|
|
252
258
|
/** A \\host or //host path would make existsSync open an SMB connection to a host named in transcript text. */
|