hippo-memory 1.71.0 → 2.0.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 +7 -5
- package/dist/agent-memories/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +11 -26
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/copilot.d.ts +1 -3
- package/dist/agent-memories/copilot.js +1 -17
- package/dist/agent-memories/project-folds.d.ts +10 -0
- package/dist/agent-memories/project-folds.js +34 -0
- package/dist/agent-memories/sync.js +8 -6
- package/dist/api/assemble.js +3 -2
- package/dist/api/audit.d.ts +30 -2
- package/dist/api/audit.js +48 -7
- package/dist/api/auth.d.ts +11 -9
- package/dist/api/auth.js +39 -40
- package/dist/api/auto-sleep.d.ts +5 -2
- package/dist/api/auto-sleep.js +7 -3
- package/dist/api/availability.js +2 -3
- package/dist/api/cards.d.ts +42 -0
- package/dist/api/cards.js +52 -0
- package/dist/api/conflicts.d.ts +28 -0
- package/dist/api/conflicts.js +61 -0
- package/dist/api/context-auto.js +4 -2
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +15 -29
- package/dist/api/context.js +29 -18
- package/dist/api/continuity.d.ts +47 -0
- package/dist/api/continuity.js +66 -0
- package/dist/api/dormant.js +4 -2
- package/dist/api/drill-down.js +3 -2
- package/dist/api/embeddings.d.ts +17 -0
- package/dist/api/embeddings.js +28 -0
- package/dist/api/error-reply.d.ts +8 -0
- package/dist/api/error-reply.js +21 -0
- package/dist/api/forget.d.ts +7 -3
- package/dist/api/forget.js +24 -14
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/graph.js +2 -1
- package/dist/api/index.d.ts +4 -2
- package/dist/api/index.js +4 -2
- package/dist/api/instruction-detect.js +5 -1
- package/dist/api/learn.d.ts +5 -1
- package/dist/api/learn.js +71 -44
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +21 -1
- package/dist/api/memories.js +51 -1
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/objects.js +2 -1
- package/dist/api/outcome.d.ts +5 -5
- package/dist/api/outcome.js +17 -16
- package/dist/api/pilot-arm.d.ts +1 -11
- package/dist/api/pilot-arm.js +5 -45
- package/dist/api/predictions.d.ts +3 -1
- package/dist/api/predictions.js +8 -1
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.d.ts +3 -3
- package/dist/api/promote.js +26 -28
- package/dist/api/prompt-hook.d.ts +17 -2
- package/dist/api/prompt-hook.js +45 -4
- package/dist/api/quarantine.js +2 -1
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +10 -5
- package/dist/api/recall-pipeline.js +23 -24
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall-types.d.ts +3 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +51 -73
- package/dist/api/remember-local.d.ts +5 -2
- package/dist/api/remember-local.js +15 -7
- package/dist/api/remember.d.ts +7 -3
- package/dist/api/remember.js +19 -16
- package/dist/api/session-end.d.ts +46 -0
- package/dist/api/session-end.js +131 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +16 -11
- package/dist/api/sleep.js +4 -3
- package/dist/api/status.d.ts +24 -0
- package/dist/api/status.js +40 -0
- package/dist/api/store-init.d.ts +4 -0
- package/dist/api/store-init.js +9 -0
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +3 -7
- package/dist/api/types.js +6 -1
- package/dist/capture/caller-session.d.ts +0 -3
- package/dist/capture/caller-session.js +1 -12
- package/dist/capture/capture-error.d.ts +2 -2
- package/dist/capture/capture-error.js +23 -18
- package/dist/capture/codex-patch.js +3 -1
- package/dist/capture/command.js +36 -95
- package/dist/capture/compact.js +10 -5
- package/dist/capture/compaction-items-caller.js +11 -20
- package/dist/capture/compaction-record.d.ts +7 -93
- package/dist/capture/compaction-record.js +29 -426
- package/dist/capture/compaction-spool.d.ts +7 -7
- package/dist/capture/compaction-spool.js +60 -51
- package/dist/capture/copilot-transcript.d.ts +2 -1
- package/dist/capture/copilot-transcript.js +2 -1
- package/dist/capture/extract.d.ts +5 -2
- package/dist/capture/extract.js +4 -3
- package/dist/capture/failure-caller.d.ts +1 -1
- package/dist/capture/failure-caller.js +21 -16
- package/dist/capture/failure-reading.d.ts +2 -1
- package/dist/capture/failure-reading.js +7 -9
- package/dist/capture/pre-compact-caller.js +5 -4
- package/dist/capture/session-digest.js +4 -3
- package/dist/capture/session-end-caller.js +3 -2
- package/dist/capture/session-worker.js +22 -10
- package/dist/capture/transcript.d.ts +2 -1
- package/dist/capture/transcript.js +6 -3
- package/dist/capture/working-state.d.ts +4 -2
- package/dist/capture/working-state.js +4 -2
- package/dist/cli/audit-prune.d.ts +0 -25
- package/dist/cli/audit-prune.js +1 -27
- package/dist/cli/audit.js +20 -20
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +16 -17
- package/dist/cli/briefs.d.ts +1 -4
- package/dist/cli/briefs.js +37 -292
- package/dist/cli/card.js +41 -33
- package/dist/cli/client.d.ts +6 -2
- package/dist/cli/client.js +37 -21
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +13 -13
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +2 -2
- package/dist/cli/curate.js +32 -36
- package/dist/cli/dag.d.ts +1 -1
- package/dist/cli/dag.js +23 -8
- package/dist/cli/decisions.d.ts +0 -2
- package/dist/cli/decisions.js +7 -285
- package/dist/cli/eval.d.ts +1 -1
- package/dist/cli/eval.js +12 -13
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +21 -25
- package/dist/cli/flag-values.js +16 -6
- package/dist/cli/flags.d.ts +0 -289
- package/dist/cli/flags.js +3 -138
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.js +83 -0
- package/dist/cli/hook-runtime.d.ts +6 -6
- package/dist/cli/hook-runtime.js +9 -36
- package/dist/cli/incidents.d.ts +3 -0
- package/dist/cli/incidents.js +112 -0
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +28 -19
- package/dist/cli/install-steps.d.ts +2 -1
- package/dist/cli/install-steps.js +11 -3
- package/dist/cli/last-sleep.js +1 -1
- package/dist/cli/maintenance.d.ts +3 -3
- package/dist/cli/maintenance.js +29 -30
- package/dist/cli/notes.d.ts +2 -0
- package/dist/cli/notes.js +41 -0
- package/dist/cli/object-verbs.d.ts +2 -2
- package/dist/cli/object-verbs.js +4 -4
- package/dist/cli/open-browser.d.ts +14 -0
- package/dist/cli/open-browser.js +26 -0
- package/dist/cli/playbooks.d.ts +3 -4
- package/dist/cli/playbooks.js +126 -290
- package/dist/cli/predictions.d.ts +3 -0
- package/dist/cli/predictions.js +174 -0
- package/dist/cli/print.js +2 -1
- package/dist/cli/projects.js +30 -22
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +6 -5
- package/dist/cli/recall.js +13 -7
- package/dist/cli/refine-llm.js +18 -17
- package/dist/cli/remember.js +17 -17
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +11 -6
- package/dist/cli/session-hooks.d.ts +1 -5
- package/dist/cli/session-hooks.js +89 -168
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +17 -10
- package/dist/cli/shared.d.ts +2 -6
- package/dist/cli/shared.js +9 -29
- package/dist/cli/sleep-render.js +6 -3
- package/dist/cli/sleep.js +6 -37
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +32 -35
- package/dist/cli/transfer.d.ts +3 -3
- package/dist/cli/transfer.js +64 -43
- package/dist/cli/usage.d.ts +1 -80
- package/dist/cli/usage.js +2 -696
- package/dist/cli/verb-row.d.ts +34 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +234 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +236 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +257 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +314 -0
- package/dist/cli/verbs.d.ts +81 -0
- package/dist/cli/verbs.js +7 -0
- package/dist/cli/versioned-verbs.d.ts +51 -0
- package/dist/cli/versioned-verbs.js +79 -0
- package/dist/cli.d.ts +1 -272
- package/dist/cli.js +24 -315
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +39 -4
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/deletion.js +2 -1
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +5 -29
- package/dist/connectors/github/tenant-routing.js +2 -1
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +35 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +29 -0
- package/dist/connectors/slack/deletion.js +2 -1
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +4 -28
- package/dist/connectors/slack/tenant-routing.js +2 -1
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +2 -2
- package/dist/consolidate/dag.js +29 -18
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +6 -4
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +3 -2
- package/dist/consolidate/merge.js +8 -8
- package/dist/consolidate/physics-pass.d.ts +6 -1
- package/dist/consolidate/physics-pass.js +26 -6
- package/dist/consolidate/replay.js +11 -4
- package/dist/consolidate/sleep.js +9 -6
- package/dist/consolidate/traces.js +5 -5
- package/dist/core/ablation.d.ts +10 -0
- package/dist/core/ablation.js +12 -0
- package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
- package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
- package/dist/core/ambient.d.ts +4 -0
- package/dist/core/ambient.js +39 -18
- package/dist/core/api-errors.d.ts +16 -0
- package/dist/core/api-errors.js +20 -0
- package/dist/core/card.js +3 -1
- package/dist/core/compaction-timing.d.ts +7 -0
- package/dist/core/compaction-timing.js +9 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +22 -18
- package/dist/core/cosine.d.ts +3 -0
- package/dist/core/cosine.js +19 -0
- package/dist/{store → core}/markdown.d.ts +1 -1
- package/dist/{store → core}/markdown.js +4 -4
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +14 -8
- package/dist/core/memory.js +35 -23
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.d.ts +3 -1
- package/dist/core/physics.js +23 -18
- package/dist/core/prediction.d.ts +3 -0
- package/dist/core/prediction.js +6 -0
- package/dist/core/project-identity.d.ts +3 -0
- package/dist/core/project-identity.js +12 -2
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/core/search-types.d.ts +1 -1
- package/dist/dashboard/dashboard-actions.d.ts +2 -2
- package/dist/dashboard/dashboard-actions.js +5 -5
- package/dist/dashboard/dashboard-queries.js +2 -7
- package/dist/dashboard/dashboard-snapshot.js +1 -3
- package/dist/dashboard/dashboard.js +16 -5
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +2 -2
- package/dist/db/connect.js +7 -7
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrate.js +14 -7
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v11.js +1 -0
- package/dist/db/migrations/v14.js +1 -0
- package/dist/db/migrations/v55.d.ts +3 -0
- package/dist/db/migrations/v55.js +17 -0
- package/dist/db/open.d.ts +0 -2
- package/dist/db/open.js +6 -10
- package/dist/db/physics-state.d.ts +0 -4
- package/dist/db/physics-state.js +7 -33
- package/dist/db/request-stores.d.ts +1 -0
- package/dist/db/request-stores.js +2 -1
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +19 -5
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +18 -15
- package/dist/embeddings/local.d.ts +62 -0
- package/dist/embeddings/local.js +146 -0
- package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
- package/dist/{store/embeddings → embeddings}/provider.js +19 -25
- package/dist/embeddings/transformers.d.ts +26 -0
- package/dist/embeddings/transformers.js +89 -0
- package/dist/entry/session-text.d.ts +1 -1
- package/dist/entry/session-text.js +1 -1
- package/dist/entry/store-kit.d.ts +37 -0
- package/dist/entry/store-kit.js +25 -0
- package/dist/entry/testing.d.ts +6 -0
- package/dist/entry/testing.js +7 -0
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +12 -5
- package/dist/graph/extract.js +3 -3
- package/dist/graph/recall.js +1 -1
- package/dist/graph/view.js +13 -5
- package/dist/graph/write.d.ts +1 -1
- package/dist/graph/write.js +9 -9
- package/dist/hooks/codex-session.js +3 -2
- package/dist/hooks/codex-wrapper.js +2 -1
- package/dist/hooks/json-hooks.js +10 -4
- package/dist/hooks/opencode.js +8 -5
- package/dist/hooks/shared.d.ts +0 -6
- package/dist/hooks/shared.js +4 -15
- package/dist/importers/core.js +4 -4
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.d.ts +1 -1
- package/dist/importers/vault.js +25 -23
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/learn/autolearn.d.ts +15 -3
- package/dist/learn/autolearn.js +38 -16
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +7 -5
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.d.ts +2 -1
- package/dist/learn/invalidation.js +18 -9
- package/dist/mcp/admin-tools.d.ts +2 -2
- package/dist/mcp/admin-tools.js +27 -48
- package/dist/mcp/format.js +3 -2
- package/dist/mcp/framing.d.ts +1 -0
- package/dist/mcp/framing.js +1 -1
- package/dist/mcp/memory-tools.d.ts +1 -1
- package/dist/mcp/memory-tools.js +8 -9
- package/dist/mcp/protocol.d.ts +11 -7
- package/dist/mcp/protocol.js +25 -12
- package/dist/mcp/recall-tools.js +12 -9
- package/dist/mcp/request.js +22 -20
- package/dist/mcp/stdio.js +37 -16
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +44 -21
- package/dist/objects/customer-notes.d.ts +2 -2
- package/dist/objects/decisions.d.ts +2 -2
- package/dist/objects/descriptor.d.ts +1 -1
- package/dist/objects/incidents.d.ts +2 -2
- package/dist/objects/lifecycle.d.ts +1 -1
- package/dist/objects/lifecycle.js +2 -1
- package/dist/objects/policies.d.ts +2 -2
- package/dist/objects/policies.js +2 -1
- package/dist/objects/processes.d.ts +2 -2
- package/dist/objects/project-briefs.d.ts +2 -2
- package/dist/objects/project-briefs.js +2 -3
- package/dist/objects/skills.d.ts +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/rerankers/clef.js +3 -6
- package/dist/rerankers/cross-encoder.d.ts +31 -2
- package/dist/rerankers/cross-encoder.js +71 -98
- package/dist/rerankers/index.js +5 -4
- package/dist/rerankers/jev.js +2 -4
- package/dist/rerankers/outage-warning.d.ts +3 -1
- package/dist/rerankers/outage-warning.js +5 -3
- package/dist/search/bm25-search.js +1 -1
- package/dist/search/boosts.js +1 -1
- package/dist/search/embed-memories.d.ts +12 -0
- package/dist/search/embed-memories.js +389 -0
- package/dist/search/engine.d.ts +8 -0
- package/dist/search/engine.js +10 -0
- package/dist/search/goal-boost.d.ts +1 -1
- package/dist/search/goal-boost.js +6 -3
- package/dist/search/hybrid.d.ts +9 -2
- package/dist/search/hybrid.js +9 -4
- package/dist/search/physics-search.d.ts +6 -3
- package/dist/search/physics-search.js +22 -15
- package/dist/search/rerank.js +1 -1
- package/dist/search/vector.d.ts +8 -6
- package/dist/search/vector.js +14 -17
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.js +24 -15
- package/dist/server/boot.d.ts +2 -1
- package/dist/server/boot.js +34 -84
- package/dist/server/client-ip.d.ts +9 -6
- package/dist/server/client-ip.js +36 -17
- package/dist/server/deadline.d.ts +0 -2
- package/dist/server/deadline.js +1 -7
- package/dist/server/defaults.d.ts +1 -0
- package/dist/server/defaults.js +1 -0
- package/dist/server/mcp-http.js +16 -11
- package/dist/server/request.js +7 -2
- package/dist/server/route-checks.d.ts +7 -0
- package/dist/server/route-checks.js +42 -0
- package/dist/server/route-table.d.ts +9 -8
- package/dist/server/route-table.js +127 -133
- package/dist/server/routes/admin.d.ts +8 -8
- package/dist/server/routes/admin.js +13 -21
- package/dist/server/routes/customer-notes.d.ts +6 -6
- package/dist/server/routes/customer-notes.js +1 -2
- package/dist/server/routes/decisions.d.ts +6 -6
- package/dist/server/routes/decisions.js +2 -4
- package/dist/server/routes/incidents.d.ts +6 -6
- package/dist/server/routes/incidents.js +2 -5
- package/dist/server/routes/memories.d.ts +9 -9
- package/dist/server/routes/memories.js +19 -40
- package/dist/server/routes/object-routes.d.ts +6 -6
- package/dist/server/routes/object-routes.js +4 -7
- package/dist/server/routes/policies.d.ts +7 -7
- package/dist/server/routes/policies.js +2 -4
- package/dist/server/routes/predictions.d.ts +6 -6
- package/dist/server/routes/predictions.js +9 -13
- package/dist/server/routes/processes.d.ts +6 -6
- package/dist/server/routes/processes.js +1 -2
- package/dist/server/routes/project-briefs.d.ts +7 -7
- package/dist/server/routes/project-briefs.js +2 -4
- package/dist/server/routes/recall.d.ts +5 -5
- package/dist/server/routes/recall.js +6 -10
- package/dist/server/routes/skills.d.ts +7 -7
- package/dist/server/routes/skills.js +2 -4
- package/dist/server/server-detect.d.ts +7 -1
- package/dist/server/server-detect.js +36 -11
- package/dist/server/sleep-child.js +26 -7
- package/dist/server/sleep-offload.d.ts +11 -5
- package/dist/server/sleep-offload.js +17 -11
- package/dist/server/tls.d.ts +7 -2
- package/dist/server/tls.js +17 -5
- package/dist/server/types.d.ts +29 -12
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +4 -40
- package/dist/server.js +3 -29
- package/dist/sharing/global-store.d.ts +4 -5
- package/dist/sharing/global-store.js +8 -13
- package/dist/sharing/global-sync.js +38 -45
- package/dist/sharing/project-merge.d.ts +7 -14
- package/dist/sharing/project-merge.js +57 -121
- package/dist/sharing/search-both.js +10 -3
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +39 -38
- package/dist/store/ambient.js +7 -7
- package/dist/store/audit-event.d.ts +1 -1
- package/dist/store/audit.d.ts +0 -16
- package/dist/store/audit.js +4 -55
- package/dist/store/auth.d.ts +4 -2
- package/dist/store/auth.js +7 -3
- package/dist/store/candidates.d.ts +3 -2
- package/dist/store/candidates.js +59 -30
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +6 -5
- package/dist/store/compaction-caller.d.ts +18 -0
- package/dist/store/compaction-caller.js +29 -0
- package/dist/store/compactions-record.d.ts +115 -0
- package/dist/store/compactions-record.js +418 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.d.ts +7 -1
- package/dist/store/conflicts.js +13 -9
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +33 -0
- package/dist/store/connectors/event-log.d.ts +13 -0
- package/dist/store/connectors/event-log.js +24 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +35 -60
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +24 -57
- package/dist/store/dashboard-reads.js +8 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +40 -6
- package/dist/store/delivery-recorder.d.ts +12 -5
- package/dist/store/delivery-recorder.js +13 -11
- package/dist/store/descendant-page.js +8 -4
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +10 -4
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +35 -4
- package/dist/store/entry-reads.js +86 -19
- package/dist/store/entry-row.js +9 -2
- package/dist/store/entry-writes.d.ts +15 -12
- package/dist/store/entry-writes.js +54 -22
- package/dist/store/failure-log-at.d.ts +8 -0
- package/dist/store/failure-log-at.js +16 -0
- package/dist/store/failure-log.d.ts +2 -2
- package/dist/store/failure-log.js +5 -3
- package/dist/{trust → store}/gated-write.d.ts +3 -1
- package/dist/{trust → store}/gated-write.js +7 -5
- package/dist/store/goals.js +22 -19
- package/dist/store/graph-reads.js +9 -6
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/half-life.js +2 -2
- package/dist/store/handoffs.d.ts +10 -4
- package/dist/store/handoffs.js +10 -9
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +1 -1
- package/dist/store/key-writes.js +1 -1
- package/dist/store/ledger-turn.d.ts +9 -0
- package/dist/store/ledger-turn.js +38 -0
- package/dist/store/mirrors.js +19 -10
- package/dist/store/open.d.ts +2 -5
- package/dist/store/open.js +42 -54
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +68 -6
- package/dist/store/port.js +8 -0
- package/dist/store/predictions.d.ts +1 -2
- package/dist/store/predictions.js +3 -6
- package/dist/store/project-tags.d.ts +62 -0
- package/dist/store/project-tags.js +67 -0
- package/dist/store/quality-repair.js +1 -1
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +20 -3
- package/dist/store/rejected-values.js +16 -10
- package/dist/store/rejection-probe.d.ts +4 -0
- package/dist/store/rejection-probe.js +19 -0
- package/dist/store/rejection.d.ts +0 -17
- package/dist/store/rejection.js +1 -21
- package/dist/store/rows.js +2 -2
- package/dist/store/rule-sql.d.ts +11 -0
- package/dist/store/rule-sql.js +31 -6
- package/dist/store/search-rows.d.ts +5 -5
- package/dist/store/search-rows.js +18 -16
- package/dist/store/sessions.js +4 -2
- package/dist/store/set-aside.d.ts +14 -0
- package/dist/store/set-aside.js +23 -0
- package/dist/store/sqlite/busy.d.ts +3 -0
- package/dist/store/sqlite/busy.js +8 -0
- package/dist/store/sqlite/connector-events-group.js +4 -7
- package/dist/store/sqlite/connector-writes-group.js +6 -4
- package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
- package/dist/store/sqlite/entry-writes-group.js +3 -3
- package/dist/store/sqlite/error-codec.js +4 -3
- package/dist/store/sqlite/executor.js +10 -4
- package/dist/store/sqlite/graph-reads-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +11 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/last-recall-group.d.ts +13 -0
- package/dist/store/sqlite/last-recall-group.js +57 -0
- package/dist/store/sqlite/local.d.ts +0 -17
- package/dist/store/sqlite/local.js +0 -31
- package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
- package/dist/store/sqlite/maintenance-groups.js +60 -0
- package/dist/store/sqlite/object-rows.d.ts +1 -1
- package/dist/store/sqlite/objects-group.d.ts +1 -1
- package/dist/store/sqlite/objects-group.js +15 -7
- package/dist/store/sqlite/store.d.ts +1 -8
- package/dist/store/sqlite/store.js +13 -22
- package/dist/store/summaries.d.ts +10 -3
- package/dist/store/summaries.js +54 -11
- package/dist/store/token-ledger-rows.js +3 -2
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +8 -4
- package/dist/support-bundle.js +2 -3
- package/dist/trust/reject-flow.js +2 -2
- package/dist/util/agent-homes.d.ts +15 -0
- package/dist/util/agent-homes.js +34 -0
- package/dist/util/anthropic-messages.d.ts +6 -1
- package/dist/util/anthropic-messages.js +26 -7
- package/dist/util/atomic-write.d.ts +5 -2
- package/dist/util/atomic-write.js +12 -8
- package/dist/util/chunked.d.ts +3 -0
- package/dist/util/chunked.js +10 -0
- package/dist/util/ellipsize.d.ts +3 -0
- package/dist/util/ellipsize.js +5 -0
- package/dist/util/env.d.ts +12 -2
- package/dist/util/env.js +12 -2
- package/dist/util/format.d.ts +5 -0
- package/dist/util/format.js +10 -0
- package/dist/util/hook-payload.d.ts +8 -0
- package/dist/util/hook-payload.js +37 -0
- package/dist/util/http-retry.d.ts +6 -0
- package/dist/util/http-retry.js +43 -5
- package/dist/util/http-util.d.ts +0 -8
- package/dist/util/http-util.js +10 -21
- package/dist/util/limits.d.ts +7 -0
- package/dist/util/limits.js +14 -0
- package/dist/util/log.d.ts +4 -0
- package/dist/util/log.js +9 -0
- package/dist/util/request-scope.d.ts +9 -3
- package/dist/util/request-scope.js +18 -9
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/spawn-argv.d.ts +9 -0
- package/dist/util/spawn-argv.js +57 -0
- package/dist/util/sql.d.ts +3 -0
- package/dist/util/sql.js +6 -0
- package/dist/util/sqlite-blocked.d.ts +2 -0
- package/dist/util/sqlite-blocked.js +5 -0
- package/dist/util/stream-tee.d.ts +3 -0
- package/dist/util/stream-tee.js +35 -0
- package/dist/util/time.d.ts +4 -0
- package/dist/util/time.js +4 -0
- package/dist/util/vector-codec.d.ts +4 -0
- package/dist/util/vector-codec.js +15 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +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 +4 -2
- package/dist/api/on-store.d.ts +0 -16
- package/dist/api/on-store.js +0 -38
- package/dist/store/embeddings/local.d.ts +0 -15
- package/dist/store/embeddings/local.js +0 -175
- /package/dist/{cli → api}/correction-latency.d.ts +0 -0
- /package/dist/{cli → api}/correction-latency.js +0 -0
- /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
- /package/dist/{cli → api}/provenance-coverage.js +0 -0
- /package/dist/{store → core}/object-types.d.ts +0 -0
- /package/dist/{store → core}/object-types.js +0 -0
- /package/dist/{capture → util}/compaction-items.d.ts +0 -0
- /package/dist/{capture → util}/compaction-items.js +0 -0
- /package/dist/{store → util}/yaml.d.ts +0 -0
- /package/dist/{store → util}/yaml.js +0 -0
|
@@ -5,17 +5,12 @@ import { spawn } from 'child_process';
|
|
|
5
5
|
import { resolveCodexSessionTranscript } from '../hooks/codex-session.js';
|
|
6
6
|
import { resolveCodexWrapperPaths } from '../hooks/codex-wrapper.js';
|
|
7
7
|
import { resolveJsonHookPaths } from '../hooks/json-hooks.js';
|
|
8
|
-
import { isInitialized } from '../store/open.js';
|
|
9
|
-
import { loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, closeTaskSnapshotsForSession, listSessionEvents, } from '../store/sessions.js';
|
|
10
|
-
import { writeSessionEndHandoff } from '../store/handoffs.js';
|
|
11
8
|
import { readSessionScan, recordSessionDigest } from '../capture/session-digest.js';
|
|
12
9
|
import { captureToolFailure } from '../capture/capture-error.js';
|
|
13
|
-
import { readApiCalls, recordRereads, } from '../store/token-ledger.js';
|
|
14
10
|
import { estimateTokens } from '../util/token-text.js';
|
|
15
11
|
import { currentMachine, importSessionFolder } from '../agent-memories/sync.js';
|
|
16
12
|
import { summaryLine } from '../agent-memories/report.js';
|
|
17
|
-
import { resolveProjectIdentity } from '../core/project-identity.js';
|
|
18
|
-
import { getGlobalRoot } from '../sharing/global-store.js';
|
|
13
|
+
import { resolveProjectIdentity, isInitialized } from '../core/project-identity.js';
|
|
19
14
|
import { cmdCapture } from '../capture/command.js';
|
|
20
15
|
import { cmdPreCompact, cmdPostCompact } from '../capture/compact.js';
|
|
21
16
|
import { transcriptWorkingState } from '../capture/working-state.js';
|
|
@@ -25,18 +20,19 @@ import { loadTurnPosition, runSessionWorker, saveTurnPosition, turnsAfter } from
|
|
|
25
20
|
import { isStringValue, readSessionEnd, readVscodeStop } from '../core/capture-contract.js';
|
|
26
21
|
import { loadConfig } from '../core/config.js';
|
|
27
22
|
import { autoSleepDue } from '../api/auto-sleep.js';
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { COMPACT_RESUME_EVENT_CONTENT_CAP, COMPACT_RESUME_MAX_AGE_MS, compactResumeText } from '../api/context-render.js';
|
|
23
|
+
import { COMPACTION_DB_WAIT_MS } from '../core/compaction-timing.js';
|
|
24
|
+
import { compactResumeBlock, sessionEndWork as runSessionEnd } from '../api/session-end.js';
|
|
31
25
|
import { normaliseHookPayload, readHookStdin, readStdinBounded } from './stdin.js';
|
|
32
26
|
import { errorMessage, log } from '../util/log.js';
|
|
27
|
+
import { cmdShimArgs } from '../util/spawn-argv.js';
|
|
33
28
|
import { bookLedgerTurn } from '../api/ledger-db.js';
|
|
34
|
-
import { flushDeliveryRecorder } from '../api/prompt-hook.js';
|
|
29
|
+
import { flushDeliveryRecorder, startDeliveryRecorder, startToolFailureRecorder } from '../api/prompt-hook.js';
|
|
35
30
|
import { printError } from './output.js';
|
|
36
31
|
import { cmdLastSleep } from './last-sleep.js';
|
|
37
32
|
import { readCompactResumePayload } from './compact-resume-payload.js';
|
|
33
|
+
import { cliApiContext } from './api-context.js';
|
|
38
34
|
import { boolFlag, flagIsTrue, stringFlag } from './flag-values.js';
|
|
39
|
-
import { logSessionEndImport, appendSessionEndCloseLog, reportSessionEndFailure, resetHookInjection, hookStoreRoot, hookRuntime, payloadCwdRoot, runHookWithStores, inPilotHoldout,
|
|
35
|
+
import { logSessionEndImport, appendSessionEndCloseLog, reportSessionEndFailure, resetHookInjection, hookStoreRoot, hookRuntime, payloadCwdRoot, runHookWithStores, inPilotHoldout, hostSessionId, } from './hook-runtime.js';
|
|
40
36
|
import { CliExit } from './exit.js';
|
|
41
37
|
/** SessionStart(compact) injector: prints the task snapshot and session trail lost to compaction; no pinned memories (UserPromptSubmit re-injects them).
|
|
42
38
|
* Every path exits 0: a malformed payload or store read failure degrades to empty stdout, never a throw. */
|
|
@@ -51,10 +47,13 @@ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
|
|
|
51
47
|
const payloadState = readCompactResumePayload(stdinText, stdinTimedOut);
|
|
52
48
|
let suppressOutput = payloadState.suppressOutput;
|
|
53
49
|
const payloadSessionId = payloadState.payloadSessionId;
|
|
54
|
-
if (payloadState.boundary)
|
|
55
|
-
rec = startDeliveryRecorder(hippoRoot,
|
|
50
|
+
if (payloadState.boundary) {
|
|
51
|
+
rec = startDeliveryRecorder(cliApiContext(hippoRoot, tenantId), {
|
|
52
|
+
stdinText, runtime: 'claude-code', eventType: 'compact-resume', envSessionId: hostSessionId(),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
56
55
|
// A compaction follows a prompt or SessionStart that booked the arm, so this only reads it.
|
|
57
|
-
if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, false)) {
|
|
56
|
+
if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, { write: false })) {
|
|
58
57
|
suppressOutput = true;
|
|
59
58
|
rec?.disabled();
|
|
60
59
|
}
|
|
@@ -72,30 +71,10 @@ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
|
|
|
72
71
|
throw new CliExit(0);
|
|
73
72
|
}
|
|
74
73
|
function restoreCompactSnapshot(hippoRoot, tenantId, payloadSessionId, rec) {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
// either side missing, or a manual invocation with no payload session_id, still prints.
|
|
78
|
-
const sessionMismatch = !!snapshot &&
|
|
79
|
-
payloadSessionId !== null &&
|
|
80
|
-
snapshot.session_id !== null &&
|
|
81
|
-
payloadSessionId !== snapshot.session_id;
|
|
82
|
-
if (!snapshot || sessionMismatch)
|
|
74
|
+
const text = compactResumeBlock(cliApiContext(hippoRoot, tenantId), payloadSessionId);
|
|
75
|
+
if (text === null)
|
|
83
76
|
return;
|
|
84
|
-
// Loaded before the print so a bad trail row costs the trail, not the snapshot; stderr stays out of the model's context.
|
|
85
|
-
let events = [];
|
|
86
|
-
try {
|
|
87
|
-
if (snapshot.session_id) {
|
|
88
|
-
events = listSessionEvents(hippoRoot, tenantId, { session_id: snapshot.session_id }).map((e) => ({
|
|
89
|
-
...e,
|
|
90
|
-
content: truncateCodePointSafe(e.content, COMPACT_RESUME_EVENT_CONTENT_CAP),
|
|
91
|
-
}));
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
catch (err) {
|
|
95
|
-
log.warn(`hippo compact-resume: trail skipped: ${errorMessage(err)}`);
|
|
96
|
-
}
|
|
97
77
|
// Printed in one write so the ledger books exactly the text the model is handed.
|
|
98
|
-
const text = compactResumeText(snapshot, events);
|
|
99
78
|
console.log(text);
|
|
100
79
|
rec?.delivered({ state: 'sent', emittedText: `${text}\n` });
|
|
101
80
|
bookLedgerTurn(hippoRoot, {
|
|
@@ -123,27 +102,24 @@ export async function handleSessionEnd({ hippoRoot, tenantId, flags }) {
|
|
|
123
102
|
const root = payloadCwdRoot(hippoRoot, stdinText, runtime);
|
|
124
103
|
const input = stop ?? sessionEndInput(stdinText, raw.timedOut, runtime);
|
|
125
104
|
// Only a host payload ends a session: a manual run and a reply's end (turn mode) are not boundaries.
|
|
126
|
-
const rec = !turn && input !== null && !input.manual
|
|
105
|
+
const rec = !turn && input !== null && !input.manual
|
|
106
|
+
? startDeliveryRecorder(cliApiContext(hookStoreRoot(root), tenantId), { stdinText, runtime, eventType: 'session-end', envSessionId: hostSessionId() })
|
|
107
|
+
: null;
|
|
127
108
|
const sessionId = input?.sessionId ?? null;
|
|
128
109
|
// Resolved here because only this process saw the payload; the worker captures just the path it is handed.
|
|
129
110
|
// Always a hook, so never scan: an empty stdin here is not a manual run. The Copilot CLI's sessionEnd names no transcript, so its log is found by id.
|
|
130
111
|
const named = input?.transcriptPath ?? null;
|
|
131
112
|
const transcriptPath = (named !== null && fs.existsSync(named) ? named : null)
|
|
132
113
|
?? (runtime === 'copilot' && sessionId ? copilotTranscriptFor(sessionId) : null);
|
|
114
|
+
const worker = { logFile, transcriptPath, sessionId, turn };
|
|
133
115
|
try {
|
|
134
|
-
spawnSessionEndWorker(sessionEndWorkerArgs(
|
|
116
|
+
spawnSessionEndWorker(sessionEndWorkerArgs(worker));
|
|
135
117
|
}
|
|
136
118
|
catch (err) {
|
|
137
119
|
log.debug(`session-end: the worker did not spawn, running inline: ${errorMessage(err)}`);
|
|
138
120
|
// Inline is the last resort, handed what the child's argv would have carried.
|
|
139
|
-
if (logFile)
|
|
140
|
-
flags['log-file'] = logFile;
|
|
141
|
-
if (transcriptPath)
|
|
142
|
-
flags['transcript'] = transcriptPath;
|
|
143
|
-
if (sessionId)
|
|
144
|
-
flags['session-id'] = sessionId;
|
|
145
121
|
try {
|
|
146
|
-
await cmdSessionEndWorker(root, tenantId, flags);
|
|
122
|
+
await cmdSessionEndWorker(root, tenantId, inlineWorkerFlags(flags, worker));
|
|
147
123
|
}
|
|
148
124
|
finally {
|
|
149
125
|
await runHookWithStores(() => flushDeliveryRecorder(rec));
|
|
@@ -161,7 +137,8 @@ function sessionEndInput(stdinText, timedOut, runtime) {
|
|
|
161
137
|
log.debug(`session-end: ${receipt.reason}`);
|
|
162
138
|
return null;
|
|
163
139
|
}
|
|
164
|
-
function sessionEndWorkerArgs(
|
|
140
|
+
function sessionEndWorkerArgs(o) {
|
|
141
|
+
const { logFile, transcriptPath, sessionId, turn } = o;
|
|
165
142
|
const workerArgs = [process.argv[1], '__session-end-worker'];
|
|
166
143
|
if (logFile)
|
|
167
144
|
workerArgs.push('--log-file', logFile);
|
|
@@ -173,6 +150,26 @@ function sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn) {
|
|
|
173
150
|
workerArgs.push('--turn');
|
|
174
151
|
return workerArgs;
|
|
175
152
|
}
|
|
153
|
+
/** The flags the detached worker would parse from its argv, so the inline run sees what the child would have; the hook's own flags fill the gaps. */
|
|
154
|
+
function inlineWorkerFlags(flags, w) {
|
|
155
|
+
const out = {};
|
|
156
|
+
const keep = (name, value) => {
|
|
157
|
+
if (value)
|
|
158
|
+
out[name] = value;
|
|
159
|
+
};
|
|
160
|
+
keep('log-file', w.logFile ?? flags['log-file']);
|
|
161
|
+
keep('transcript', w.transcriptPath ?? flags['transcript']);
|
|
162
|
+
keep('session-id', w.sessionId ?? flags['session-id']);
|
|
163
|
+
if (flagIsTrue(flags, 'turn'))
|
|
164
|
+
out['turn'] = true;
|
|
165
|
+
if (flagIsTrue(flags, 'dry-run'))
|
|
166
|
+
out['dry-run'] = true;
|
|
167
|
+
if (flagIsTrue(flags, 'no-learn'))
|
|
168
|
+
out['no-learn'] = true;
|
|
169
|
+
if (flagIsTrue(flags, 'no-share'))
|
|
170
|
+
out['no-share'] = true;
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
176
173
|
function spawnSessionEndWorker(workerArgs) {
|
|
177
174
|
const child = spawn(process.execPath, workerArgs, {
|
|
178
175
|
detached: true,
|
|
@@ -195,64 +192,38 @@ async function cmdSessionEndWorker(hippoRoot, tenantId, flags) {
|
|
|
195
192
|
export function handleSessionEndWorker({ hippoRoot, tenantId, flags }) {
|
|
196
193
|
return cmdSessionEndWorker(hippoRoot, tenantId, flags);
|
|
197
194
|
}
|
|
198
|
-
|
|
195
|
+
function sessionEndWork(hippoRoot, tenantId, flags, mode) {
|
|
199
196
|
const transcriptPath = stringFlag(flags, 'transcript');
|
|
200
|
-
const
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const flushRereadLog = () => { for (const line of rereadLog.splice(0))
|
|
206
|
-
appendSessionEndCloseLog(closeLogFile, line); };
|
|
207
|
-
process.once('exit', flushRereadLog);
|
|
208
|
-
// Like the other hooks: project store, else global; a folder with neither must not get one made.
|
|
209
|
-
const store = hookStoreRoot(hippoRoot);
|
|
210
|
-
if (!isInitialized(store)) {
|
|
211
|
-
appendSessionEndCloseLog(closeLogFile, 'skip: no hippo store for this folder or globally', { startFresh: true });
|
|
212
|
-
flushRereadLog();
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
if (mode === 'turn' && closeSessionId)
|
|
216
|
-
await sleepIfDue(hippoRoot, tenantId, flags, closeLogFile, transcriptPath, closeSessionId);
|
|
217
|
-
else
|
|
218
|
-
await sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
|
|
219
|
-
flushRereadLog();
|
|
220
|
-
const digestLog = (message) => appendSessionEndCloseLog(closeLogFile, message);
|
|
221
|
-
const scan = transcriptPath ? readSessionScan(transcriptPath, digestLog) : null;
|
|
222
|
-
const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
|
|
223
|
-
if (mode === 'turn')
|
|
224
|
-
captureNewTurns(transcriptPath, closeSessionId, scan, capture, digestLog);
|
|
225
|
-
else
|
|
226
|
-
capture(scan?.turns);
|
|
227
|
-
recordSessionDigest(hippoRoot, scan, {
|
|
228
|
-
key: closeSessionId || path.basename(transcriptPath ?? '', '.jsonl'),
|
|
197
|
+
const logFile = stringFlag(flags, 'log-file') ?? null;
|
|
198
|
+
const sessionId = stringFlag(flags, 'session-id') ?? null;
|
|
199
|
+
return runSessionEnd({
|
|
200
|
+
mode,
|
|
201
|
+
hippoRoot,
|
|
229
202
|
tenantId,
|
|
230
|
-
|
|
203
|
+
sessionId,
|
|
204
|
+
transcriptPath,
|
|
205
|
+
contextFor: (root) => cliApiContext(root, tenantId),
|
|
206
|
+
storeRoot: () => hookStoreRoot(hippoRoot),
|
|
207
|
+
log: (line, opts) => appendSessionEndCloseLog(logFile, line, opts),
|
|
208
|
+
sleep: () => (mode === 'turn' && sessionId
|
|
209
|
+
? sleepIfDue(hippoRoot, tenantId, flags, logFile, transcriptPath, sessionId)
|
|
210
|
+
: sleepProjectStore(hippoRoot, tenantId, flags, logFile, transcriptPath)),
|
|
211
|
+
readScan: (log) => (transcriptPath ? readSessionScan(transcriptPath, log) : null),
|
|
212
|
+
capture: (store, scan) => {
|
|
213
|
+
const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
|
|
214
|
+
if (mode === 'turn')
|
|
215
|
+
captureNewTurns(transcriptPath, sessionId, scan, capture, (line) => appendSessionEndCloseLog(logFile, line));
|
|
216
|
+
else
|
|
217
|
+
capture(scan?.turns);
|
|
218
|
+
},
|
|
219
|
+
digest: (scan, log) => recordSessionDigest(hippoRoot, scan, {
|
|
220
|
+
key: sessionId || path.basename(transcriptPath ?? '', '.jsonl'),
|
|
221
|
+
tenantId,
|
|
222
|
+
log,
|
|
223
|
+
}),
|
|
224
|
+
workingState: (log) => (transcriptPath ? transcriptWorkingState(transcriptPath, log) : null),
|
|
225
|
+
evidence: () => collectHandoffEvidence(process.cwd(), 'unknown'),
|
|
231
226
|
});
|
|
232
|
-
// Close only this session's snapshot, after sleep+capture; if session-end never fires (crash, kill -9) the freshness bound in
|
|
233
|
-
// loadFreshActiveTaskSnapshot is the backstop. The handoff is written first, while the snapshot writeSessionEndHandoff reads is active.
|
|
234
|
-
if (closeSessionId)
|
|
235
|
-
writeEndHandoff(store, tenantId, closeSessionId, transcriptPath, closeLogFile, mode === 'turn');
|
|
236
|
-
if (mode === 'turn') {
|
|
237
|
-
// The chat goes on after a reply, so its snapshot stays for the next compaction to restore.
|
|
238
|
-
appendSessionEndCloseLog(closeLogFile, 'skip snapshot close: turn mode');
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
closeEndedSessionSnapshot(store, tenantId, closeSessionId, closeLogFile);
|
|
242
|
-
}
|
|
243
|
-
function closeEndedSessionSnapshot(store, tenantId, closeSessionId, closeLogFile) {
|
|
244
|
-
try {
|
|
245
|
-
if (closeSessionId) {
|
|
246
|
-
const closed = closeTaskSnapshotsForSession(store, tenantId, closeSessionId);
|
|
247
|
-
appendSessionEndCloseLog(closeLogFile, `closed ${closed} active snapshot(s) for session ${closeSessionId}`);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
appendSessionEndCloseLog(closeLogFile, 'skip: no session_id in SessionEnd payload, active snapshot left untouched');
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
catch (err) {
|
|
254
|
-
appendSessionEndCloseLog(closeLogFile, `snapshot close failed: ${errorMessage(err)}`);
|
|
255
|
-
}
|
|
256
227
|
}
|
|
257
228
|
async function sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath) {
|
|
258
229
|
// Sleeping the global store from here would learn this folder's git commits into it; it has its own daily sleep.
|
|
@@ -330,53 +301,6 @@ function captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath,
|
|
|
330
301
|
return false;
|
|
331
302
|
}
|
|
332
303
|
}
|
|
333
|
-
function writeEndHandoff(store, tenantId, closeSessionId, transcriptPath, closeLogFile, inPlace = false) {
|
|
334
|
-
try {
|
|
335
|
-
const ownSnapshot = loadActiveTaskSnapshot(store, tenantId)?.session_id === closeSessionId;
|
|
336
|
-
// A never-compacted session has no snapshot; read even when it has one, as another session's PreCompact can take the slot before the write.
|
|
337
|
-
const derived = transcriptPath
|
|
338
|
-
? transcriptWorkingState(transcriptPath, (message) => appendSessionEndCloseLog(closeLogFile, message))
|
|
339
|
-
: null;
|
|
340
|
-
if (!ownSnapshot && !derived) {
|
|
341
|
-
appendSessionEndCloseLog(closeLogFile, 'skip: no snapshot or transcript for session');
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
const evidence = collectHandoffEvidence(process.cwd(), 'unknown');
|
|
345
|
-
const handoff = writeSessionEndHandoff(store, tenantId, closeSessionId, evidence, derived, undefined, { inPlace });
|
|
346
|
-
appendSessionEndCloseLog(closeLogFile, handoff ? `wrote handoff for session ${closeSessionId}` : `skip: kept the existing handoff for session ${closeSessionId}`);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
catch (err) {
|
|
350
|
-
// SAFETY: catch clauses bind unknown, but Node/V8 always throws an Error here.
|
|
351
|
-
appendSessionEndCloseLog(closeLogFile, `handoff write failed: ${errorMessage(err)}`);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
/** Books the ending session's re-reads in each store its ledger rows can land in (project and global); returns the log lines. */
|
|
355
|
-
async function bookSessionRereads(hippoRoot, tenantId, transcriptPath, sessionId) {
|
|
356
|
-
if (!transcriptPath || !sessionId)
|
|
357
|
-
return [];
|
|
358
|
-
let read;
|
|
359
|
-
try {
|
|
360
|
-
read = await readApiCalls(transcriptPath);
|
|
361
|
-
}
|
|
362
|
-
catch (err) {
|
|
363
|
-
return [`skip re-read count: cannot read the transcript: ${errorMessage(err)}`];
|
|
364
|
-
}
|
|
365
|
-
const roots = new Set([hippoRoot, getGlobalRoot()].filter((root) => isInitialized(root)).map((root) => path.resolve(root)));
|
|
366
|
-
const lines = [];
|
|
367
|
-
let tokens = 0;
|
|
368
|
-
for (const root of roots) {
|
|
369
|
-
try {
|
|
370
|
-
tokens += recordRereads(root, tenantId, sessionId, read.calls);
|
|
371
|
-
}
|
|
372
|
-
catch (err) {
|
|
373
|
-
lines.push(`re-read count failed: ${errorMessage(err)}`);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
const skipped = read.malformed > 0 ? `, ${read.malformed} unparsable transcript lines skipped` : '';
|
|
377
|
-
lines.push(`re-read ${tokens} tokens over ${read.calls.length} model calls for session ${sessionId}${skipped}`);
|
|
378
|
-
return lines;
|
|
379
|
-
}
|
|
380
304
|
function loadCodexWrapperMetadata() {
|
|
381
305
|
const { metadataPath } = resolveCodexWrapperPaths();
|
|
382
306
|
if (!fs.existsSync(metadataPath)) {
|
|
@@ -385,20 +309,6 @@ function loadCodexWrapperMetadata() {
|
|
|
385
309
|
// SAFETY: the file is the one installCodexWrapper wrote; handleCodexRun reads only logFile and realCodexPath from it.
|
|
386
310
|
return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
387
311
|
}
|
|
388
|
-
/** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
|
|
389
|
-
export function quoteCmdArg(arg) {
|
|
390
|
-
if (arg.length === 0)
|
|
391
|
-
return '""';
|
|
392
|
-
if (!/[ \t"&()^<>|%!]/.test(arg))
|
|
393
|
-
return arg;
|
|
394
|
-
return `"${arg.replace(/"/g, '""').replace(/%/g, '"^%"')}"`;
|
|
395
|
-
}
|
|
396
|
-
/** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
|
|
397
|
-
export function cmdShimArgs(shimPath, forwardArgs) {
|
|
398
|
-
const command = `"${shimPath}"${forwardArgs.length > 0 ? ` ${forwardArgs.map(quoteCmdArg).join(' ')}` : ''}`;
|
|
399
|
-
// The line is already quoted for cmd.exe, so Node must not quote it again; /s strips the outer pair.
|
|
400
|
-
return ['/d', '/v:off', '/s', '/c', `"${command}"`];
|
|
401
|
-
}
|
|
402
312
|
function spawnRealCodex(realCodexPath, forwardArgs, cwd) {
|
|
403
313
|
const ext = path.extname(realCodexPath).toLowerCase();
|
|
404
314
|
if (process.platform === 'win32' && ext === '.ps1') {
|
|
@@ -565,15 +475,17 @@ function captureCodexTranscript(hippoRoot, tenantId, store, flags, logFile) {
|
|
|
565
475
|
reportSessionEndFailure(logFile ?? null, 'codex session-end: transcript scan or digest', err);
|
|
566
476
|
}
|
|
567
477
|
}
|
|
568
|
-
export async function handlePreCompact({ hippoRoot, flags }) {
|
|
478
|
+
export async function handlePreCompact({ hippoRoot, tenantId, flags }) {
|
|
569
479
|
// Bounded wait, not a TTY guard: an idle non-TTY pipe must not hang.
|
|
570
480
|
const { text: stdinText, timedOut: stdinTimedOut } = await readHookStdin();
|
|
571
481
|
const runtime = hookRuntime(flags);
|
|
572
482
|
const root = payloadCwdRoot(hippoRoot, stdinText, runtime);
|
|
573
483
|
await runHookWithStores(async () => {
|
|
574
484
|
// Started before any store wait, so two fires of one hook carry timestamps close enough to match as duplicates.
|
|
575
|
-
const rec = startDeliveryRecorder(hookStoreRoot(root),
|
|
576
|
-
|
|
485
|
+
const rec = startDeliveryRecorder(cliApiContext(hookStoreRoot(root), tenantId), {
|
|
486
|
+
stdinText, runtime, eventType: 'pre-compact', envSessionId: hostSessionId(),
|
|
487
|
+
});
|
|
488
|
+
resetHookInjection(root, tenantId, stdinText, null);
|
|
577
489
|
await cmdPreCompact(hookStoreRoot(root), {
|
|
578
490
|
stdinText,
|
|
579
491
|
stdinTimedOut,
|
|
@@ -587,7 +499,8 @@ export async function handlePreCompact({ hippoRoot, flags }) {
|
|
|
587
499
|
});
|
|
588
500
|
}
|
|
589
501
|
export async function handlePostCompact({ hippoRoot, flags }) {
|
|
590
|
-
// PostCompact hook: saves the compaction summary and its memories, then prints one plain line, because Claude Code shows this hook's
|
|
502
|
+
// PostCompact hook: saves the compaction summary and its memories, then prints one plain line, because Claude Code shows this hook's
|
|
503
|
+
// stdout as-is. Always exits 0.
|
|
591
504
|
const { text, timedOut } = await readHookStdin();
|
|
592
505
|
const logFlag = flags['log-file'];
|
|
593
506
|
const store = hookStoreRoot(hippoRoot);
|
|
@@ -618,7 +531,15 @@ export async function handleCaptureError({ hippoRoot, tenantId, flags }) {
|
|
|
618
531
|
if (isInitialized(root) && payload) {
|
|
619
532
|
// SAFETY: JSON.parse returns a JSON value by definition.
|
|
620
533
|
const failure = JSON.parse(payload);
|
|
621
|
-
|
|
534
|
+
const rec = startToolFailureRecorder(cliApiContext(root, tenantId), { stdinText: text, runtime: hookRuntime(flags), envSessionId: hostSessionId() });
|
|
535
|
+
await runHookWithStores(() => {
|
|
536
|
+
try {
|
|
537
|
+
return captureToolFailure(root, tenantId, failure, (id) => rec?.logged(id));
|
|
538
|
+
}
|
|
539
|
+
finally {
|
|
540
|
+
flushDeliveryRecorder(rec);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
622
543
|
}
|
|
623
544
|
}
|
|
624
545
|
catch (err) {
|
|
@@ -629,7 +550,7 @@ export async function handleCaptureError({ hippoRoot, tenantId, flags }) {
|
|
|
629
550
|
export async function handleCompactResume({ hippoRoot, tenantId }) {
|
|
630
551
|
const { text: stdinText, timedOut: stdinTimedOut } = await readHookStdin();
|
|
631
552
|
await runHookWithStores(() => {
|
|
632
|
-
resetHookInjection(hippoRoot, stdinText, 'compact');
|
|
553
|
+
resetHookInjection(hippoRoot, tenantId, stdinText, 'compact');
|
|
633
554
|
cmdCompactResume(hookStoreRoot(hippoRoot), tenantId, stdinText, stdinTimedOut);
|
|
634
555
|
});
|
|
635
556
|
}
|
package/dist/cli/setup.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CommandContext } from './flag-values.js';
|
|
2
2
|
export declare function handleHook({ args }: CommandContext): void;
|
|
3
3
|
export declare function handleSetup({ flags }: CommandContext): void;
|
|
4
|
-
export declare function handleDailyRunner(
|
|
4
|
+
export declare function handleDailyRunner({ tenantId }: CommandContext): Promise<void>;
|
|
5
5
|
//# sourceMappingURL=setup.d.ts.map
|
package/dist/cli/setup.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// `hippo hook`, `hippo setup` and `hippo daily-runner`: install and run the agent and machine integrations.
|
|
2
|
+
import { MINUTE_MS } from '../util/time.js';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
import * as fs from 'fs';
|
|
4
5
|
import { execFileSync } from 'child_process';
|
|
@@ -7,7 +8,7 @@ import { detectInstalledTools } from '../hooks/shared.js';
|
|
|
7
8
|
import { ensureCodexWrapperInstalled, installCodexWrapper, detectRealCodexPath, uninstallCodexWrapper, } from '../hooks/codex-wrapper.js';
|
|
8
9
|
import { installOpencodePlugin, uninstallOpencodePlugin, resolveOpencodePluginPath } from '../hooks/opencode.js';
|
|
9
10
|
import { COPILOT_CLI_MCP, VSCODE_MCP, copilotMcpSnippet, copilotPaths, installCopilot, isCopilotCliPresent, isMcpFailure, uninstallCopilot, } from '../hooks/copilot.js';
|
|
10
|
-
import { isInitialized } from '../
|
|
11
|
+
import { isInitialized } from '../core/project-identity.js';
|
|
11
12
|
import { currentMachine, importUserMemories } from '../agent-memories/sync.js';
|
|
12
13
|
import { getGlobalRoot } from '../sharing/global-store.js';
|
|
13
14
|
import { listRegisteredWorkspaces, runDailyMaintenance } from './scheduler.js';
|
|
@@ -188,7 +189,8 @@ const VSCODE_INSTRUCTIONS_REMOVE_LINES = {
|
|
|
188
189
|
absent: () => '',
|
|
189
190
|
kept: (file) => `Left ${file}: it is not the text hippo wrote. Delete it by hand if no agent needs it.`,
|
|
190
191
|
};
|
|
191
|
-
const VSCODE_HOOKS_LINE = 'VS Code: hooks need VS Code 1.109.3 or later with chat.useHooks on (the default); older versions get the MCP server and the
|
|
192
|
+
const VSCODE_HOOKS_LINE = 'VS Code: hooks need VS Code 1.109.3 or later with chat.useHooks on (the default); older versions get the MCP server and the ' +
|
|
193
|
+
'instructions file only.';
|
|
192
194
|
function mcpInstallLine(file, mcp, host) {
|
|
193
195
|
return isMcpFailure(mcp) ? mcpFailureLine(file, mcp, addByHand(host)) : MCP_MERGE_LINES[mcp](file, host);
|
|
194
196
|
}
|
|
@@ -198,7 +200,8 @@ function printVscodeInstall(result, indent) {
|
|
|
198
200
|
console.log(`${indent}${VSCODE_INSTRUCTIONS_INSTALL_LINES[result.instructions](paths.instructions)}`);
|
|
199
201
|
if (paths.profiles.length > 0) {
|
|
200
202
|
const names = paths.profiles.map((dir) => path.basename(dir)).join(', ');
|
|
201
|
-
console.log(`${indent}Found VS Code profiles (${names}) under ${path.join(paths.userDir, 'profiles')}:
|
|
203
|
+
console.log(`${indent}Found VS Code profiles (${names}) under ${path.join(paths.userDir, 'profiles')}: ` +
|
|
204
|
+
'hippo set up the default profile only; copy the "hippo" server and prompts/hippo.instructions.md into a profile to use hippo there.');
|
|
202
205
|
}
|
|
203
206
|
}
|
|
204
207
|
function printCopilotInstall(result, indent) {
|
|
@@ -206,7 +209,8 @@ function printCopilotInstall(result, indent) {
|
|
|
206
209
|
const hooks = result.hooks ? `Installed hippo's Copilot hooks (${copilotHookEvents().join(', ')}) ->` : "hippo's Copilot hooks are already in";
|
|
207
210
|
console.log(`${indent}${hooks} ${paths.hooks}`);
|
|
208
211
|
if (result.mcp === null || result.instructions === null) {
|
|
209
|
-
console.log(`${indent}No Copilot CLI files in ${path.dirname(paths.mcpConfig)},
|
|
212
|
+
console.log(`${indent}No Copilot CLI files in ${path.dirname(paths.mcpConfig)}, ` +
|
|
213
|
+
'so hippo skipped mcp-config.json and copilot-instructions.md, which only the Copilot CLI reads');
|
|
210
214
|
}
|
|
211
215
|
else {
|
|
212
216
|
console.log(`${indent}${mcpInstallLine(paths.mcpConfig, result.mcp, COPILOT_CLI_MCP)}`);
|
|
@@ -226,8 +230,10 @@ function mcpRemoveLines(file, mcp) {
|
|
|
226
230
|
return [`Removed the "hippo" MCP server from ${file}`];
|
|
227
231
|
if (mcp === 'user-owned')
|
|
228
232
|
return [`Left the "hippo" MCP server in ${file}: hippo did not write it`];
|
|
229
|
-
if (mcp === 'unreadable')
|
|
230
|
-
return [`WARNING: ${file} has comments or is not a JSON object hippo can edit, so it was left unchanged;
|
|
233
|
+
if (mcp === 'unreadable') {
|
|
234
|
+
return [`WARNING: ${file} has comments or is not a JSON object hippo can edit, so it was left unchanged; ` +
|
|
235
|
+
'remove the "hippo" server by hand if hippo added it'];
|
|
236
|
+
}
|
|
231
237
|
return [];
|
|
232
238
|
}
|
|
233
239
|
function printCopilotUninstall(result) {
|
|
@@ -473,21 +479,21 @@ function setupPluginTool(tool, dryRun) {
|
|
|
473
479
|
}
|
|
474
480
|
}
|
|
475
481
|
// Three times the 10 minutes POST /v1/sleep allows a consolidation, so a slow real sleep fits and a hung child cannot stall every later workspace.
|
|
476
|
-
const DAILY_STEP_TIMEOUT_MS = 30 *
|
|
482
|
+
const DAILY_STEP_TIMEOUT_MS = 30 * MINUTE_MS;
|
|
477
483
|
/** Why a child step failed; a child killed at the deadline says so, since its own message is only the spawn error code. */
|
|
478
484
|
function dailyStepFailure(err, timeoutMs) {
|
|
479
485
|
if (err instanceof Error && 'code' in err && err.code === 'ETIMEDOUT')
|
|
480
486
|
return `timed out after ${timeoutMs} ms and was stopped`;
|
|
481
487
|
return errorMessage(err);
|
|
482
488
|
}
|
|
483
|
-
export function handleDailyRunner(
|
|
489
|
+
export async function handleDailyRunner({ tenantId }) {
|
|
484
490
|
const globalRoot = getGlobalRoot();
|
|
485
491
|
// No workspace sleep ever opens the global store, yet hooks in folders without a store compact into it.
|
|
486
492
|
if (isInitialized(globalRoot)) {
|
|
487
493
|
const finished = replayCompactionsAt(globalRoot, (message) => log.warn(`compaction replay: ${message}`));
|
|
488
494
|
if (finished > 0)
|
|
489
495
|
console.log(`Finished saving ${finished} compaction${finished === 1 ? '' : 's'} left over in the global store.`);
|
|
490
|
-
repairQualityOnceAt(globalRoot);
|
|
496
|
+
await repairQualityOnceAt(globalRoot, tenantId);
|
|
491
497
|
}
|
|
492
498
|
printAgentImport(importUserMemories(globalRoot, { machine: currentMachine() }), '');
|
|
493
499
|
const workspaces = listRegisteredWorkspaces(globalRoot);
|
|
@@ -516,7 +522,8 @@ export function handleDailyRunner(_ctx) {
|
|
|
516
522
|
log.error(`daily-runner failed in ${cwd} during \`${action}\`: ${dailyStepFailure(err, timeout)}`, { workspace: cwd, ...errorFields(err) });
|
|
517
523
|
}
|
|
518
524
|
});
|
|
519
|
-
console.log(`Daily maintenance complete: ${processed} workspace${processed === 1 ? '' : 's'} processed,
|
|
525
|
+
console.log(`Daily maintenance complete: ${processed} workspace${processed === 1 ? '' : 's'} processed, ` +
|
|
526
|
+
`${failed} command failure${failed === 1 ? '' : 's'}.`);
|
|
520
527
|
// The scheduler that runs this only sees the exit code, so a failed workspace must not read as a clean run.
|
|
521
528
|
if (failed > 0)
|
|
522
529
|
process.exitCode = 1;
|
package/dist/cli/shared.d.ts
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { type ChurnStaleResult } from '../learn/invalidation.js';
|
|
2
|
-
import { type AuditOp } from '../store/audit.js';
|
|
3
2
|
import { type ServerInfo } from '../server/server-detect.js';
|
|
4
|
-
import type { JsonObject } from '../store/working-memory.js';
|
|
5
3
|
import type { CliFlags } from './flag-values.js';
|
|
6
|
-
/** Emit an audit event on its own short-lived connection to `hippoRoot`'s db; swallows all errors, since audit must never crash a CLI command. */
|
|
7
|
-
export declare function emitCliAudit(hippoRoot: string, op: AuditOp, targetId?: string, metadata?: JsonObject): void;
|
|
8
4
|
export declare function requireInit(hippoRoot: string): void;
|
|
9
5
|
/** Runs detectChurnStale against every store this repo's memories can live in. */
|
|
10
|
-
export declare function runChurnStaleForRepo(hippoRoot: string, dryRun: boolean): {
|
|
6
|
+
export declare function runChurnStaleForRepo(hippoRoot: string, tenantId: string, dryRun: boolean): {
|
|
11
7
|
root: string;
|
|
12
8
|
result: ChurnStaleResult;
|
|
13
9
|
}[];
|
|
@@ -21,7 +17,7 @@ interface LearnFromRepoResult {
|
|
|
21
17
|
skipped: number;
|
|
22
18
|
lowInfo: number;
|
|
23
19
|
}
|
|
24
|
-
export declare function learnFromRepo(hippoRoot: string, repoPath: string, days: number, label?: string): LearnFromRepoResult
|
|
20
|
+
export declare function learnFromRepo(hippoRoot: string, tenantId: string, repoPath: string, days: number, label?: string): Promise<LearnFromRepoResult>;
|
|
25
21
|
export declare function resolveAuthRoot(hippoRoot: string, flags: CliFlags): string;
|
|
26
22
|
export {};
|
|
27
23
|
//# sourceMappingURL=shared.d.ts.map
|
package/dist/cli/shared.js
CHANGED
|
@@ -1,36 +1,17 @@
|
|
|
1
|
-
// Store and server helpers the CLI verbs share:
|
|
1
|
+
// Store and server helpers the CLI verbs share: init checks, server routing, git learning and the auth root.
|
|
2
2
|
// This module must never import cli.ts.
|
|
3
3
|
import { envApiKey, envRequireServer } from '../util/env.js';
|
|
4
4
|
import { execFileSync } from 'child_process';
|
|
5
5
|
import { isSharedStore } from '../core/config.js';
|
|
6
|
-
import { isInitialized } from '../store/open.js';
|
|
7
6
|
import { detectChurnStale } from '../learn/invalidation.js';
|
|
8
|
-
import { resolveProjectIdentity } from '../core/project-identity.js';
|
|
7
|
+
import { resolveProjectIdentity, isInitialized } from '../core/project-identity.js';
|
|
9
8
|
import { getGlobalRoot, initGlobal } from '../sharing/global-store.js';
|
|
10
|
-
import { reportAuditWriteFailure } from '../store/audit.js';
|
|
11
|
-
import { sqliteSyncStore } from '../store/sqlite/store.js';
|
|
12
9
|
import * as client from './client.js';
|
|
13
10
|
import { detectServer, removePidfileIfOwned } from '../server/server-detect.js';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
11
|
+
import { learn, CLI_LEARN } from '../api/index.js';
|
|
12
|
+
import { cliApiContext } from './api-context.js';
|
|
16
13
|
import { errorMessage, log } from '../util/log.js';
|
|
17
14
|
import { printError } from './output.js';
|
|
18
|
-
/** Emit an audit event on its own short-lived connection to `hippoRoot`'s db; swallows all errors, since audit must never crash a CLI command. */
|
|
19
|
-
export function emitCliAudit(hippoRoot, op, targetId, metadata) {
|
|
20
|
-
try {
|
|
21
|
-
sqliteSyncStore(hippoRoot).appendAuditEvents([{
|
|
22
|
-
tenantId: resolveTenantId({}),
|
|
23
|
-
actor: 'cli',
|
|
24
|
-
op,
|
|
25
|
-
targetId,
|
|
26
|
-
metadata,
|
|
27
|
-
}]);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
// Best effort: the command already did its work.
|
|
31
|
-
reportAuditWriteFailure(op, String(error), targetId);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
15
|
export function requireInit(hippoRoot) {
|
|
35
16
|
if (!isInitialized(hippoRoot)) {
|
|
36
17
|
printError(`No hippo store at ${hippoRoot} (searched ${process.cwd()} and its parents up to your home directory). Run \`hippo init\` first.`);
|
|
@@ -38,12 +19,11 @@ export function requireInit(hippoRoot) {
|
|
|
38
19
|
}
|
|
39
20
|
}
|
|
40
21
|
/** Runs detectChurnStale against every store this repo's memories can live in. */
|
|
41
|
-
export function runChurnStaleForRepo(hippoRoot, dryRun) {
|
|
22
|
+
export function runChurnStaleForRepo(hippoRoot, tenantId, dryRun) {
|
|
42
23
|
const repoRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], { cwd: process.cwd(), encoding: 'utf8', timeout: 10_000, windowsHide: true }).trim();
|
|
43
24
|
const { name: projectName, legacyName } = resolveProjectIdentity(process.cwd());
|
|
44
25
|
const globalRoot = getGlobalRoot();
|
|
45
26
|
const roots = globalRoot !== hippoRoot && isInitialized(globalRoot) ? [hippoRoot, globalRoot] : [hippoRoot];
|
|
46
|
-
const tenantId = resolveTenantId({});
|
|
47
27
|
return roots.map((root) => {
|
|
48
28
|
// One store failing must not abort sleep's later phases or skip the other store.
|
|
49
29
|
try {
|
|
@@ -89,7 +69,8 @@ export async function runViaServerIfAvailable(hippoRoot, httpFn) {
|
|
|
89
69
|
if (failure === 'delivery-unknown') {
|
|
90
70
|
// Every caller is a non-idempotent write, so replaying on the direct path would store a row the server may already have committed;
|
|
91
71
|
// leave the pidfile alone: the next command's connect-phase failure heals it.
|
|
92
|
-
printError(`hippo: the connection to ${info.url} dropped or timed out mid-request, so the write may already have been applied.
|
|
72
|
+
printError(`hippo: the connection to ${info.url} dropped or timed out mid-request, so the write may already have been applied. ` +
|
|
73
|
+
'Not retrying locally. Check with `hippo recall` before running this again.');
|
|
93
74
|
process.exit(1);
|
|
94
75
|
}
|
|
95
76
|
throw err;
|
|
@@ -102,10 +83,9 @@ export function skipLearnOnSharedStore(hippoRoot) {
|
|
|
102
83
|
console.log("Shared store: skipped learning from this account's git commits and coding agents' own memories.");
|
|
103
84
|
return true;
|
|
104
85
|
}
|
|
105
|
-
export function learnFromRepo(hippoRoot, repoPath, days, label) {
|
|
86
|
+
export async function learnFromRepo(hippoRoot, tenantId, repoPath, days, label) {
|
|
106
87
|
const prefix = label ? `[${label}] ` : '';
|
|
107
|
-
const
|
|
108
|
-
const result = learn(ctx, { repoPath, days, profile: CLI_LEARN });
|
|
88
|
+
const result = await learn(cliApiContext(hippoRoot, tenantId), { repoPath, days, profile: CLI_LEARN });
|
|
109
89
|
if (result.status === 'not-a-repo') {
|
|
110
90
|
console.log(`${prefix}No git history found (or not a git repository).`);
|
|
111
91
|
return { added: 0, skipped: 0, lowInfo: 0 };
|
package/dist/cli/sleep-render.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { renderAmbientSummary } from '../core/ambient.js';
|
|
3
3
|
/** The lines `hippo sleep` prints for an api.sleep result; pure, so the snapshot tests read them without a console spy. */
|
|
4
4
|
export function sleepResultLines(result) {
|
|
5
|
-
return [...sleepCountLines(result), ...(result.dryRun ? ['\n(dry run - nothing
|
|
5
|
+
return [...sleepCountLines(result), ...(result.dryRun ? ['\n(dry run - nothing ' +
|
|
6
|
+
'written)'] : []), ...sleepDedupeAndAuditLines(result), ...sleepShareAndGraphLines(result)];
|
|
6
7
|
}
|
|
7
8
|
function sleepCountLines(result) {
|
|
8
|
-
const lines = [`Running consolidation${result.dryRun ? ' (dry
|
|
9
|
+
const lines = [`Running consolidation${result.dryRun ? ' (dry ' +
|
|
10
|
+
'run)' : ''}...`, `\nResults:`, ` Active memories: ${result.active}`, ` Removed (decayed): ${result.removed}`];
|
|
9
11
|
// Only when dormant.enabled moved something, so every other render stays byte-identical.
|
|
10
12
|
if (result.dormant !== undefined && result.dormant > 0) {
|
|
11
13
|
lines.push(` Kept dormant: ${result.dormant} (hippo dormant to list)`);
|
|
@@ -29,7 +31,8 @@ function sleepDedupeAndAuditLines(result) {
|
|
|
29
31
|
parts.push(`${epiDups} duplicate episodic lessons`);
|
|
30
32
|
if (crossDups > 0)
|
|
31
33
|
parts.push(`${crossDups} cross-layer duplicates`);
|
|
32
|
-
lines.push(`\n${result.dryRun ? 'Would
|
|
34
|
+
lines.push(`\n${result.dryRun ? 'Would ' +
|
|
35
|
+
'dedupe' : 'Deduped'} ${removed} duplicates (${parts.join(', ')}). ${result.dryRun ? 'Would keep' : 'Kept'} stronger copies.`);
|
|
33
36
|
}
|
|
34
37
|
if (result.audit) {
|
|
35
38
|
if (result.audit.errorsRemoved > 0) {
|