hippo-memory 1.71.0 → 1.72.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/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +6 -21
- 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 +1 -1
- package/dist/api/audit.d.ts +29 -1
- package/dist/api/audit.js +44 -5
- package/dist/api/auth.d.ts +7 -4
- package/dist/api/auth.js +12 -8
- 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-render.js +4 -3
- package/dist/api/context-select.js +9 -11
- package/dist/api/context.js +17 -8
- 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 +1 -1
- 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 +6 -2
- package/dist/api/forget.js +18 -7
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- 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 +4 -0
- package/dist/api/learn.js +53 -27
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +19 -1
- package/dist/api/memories.js +39 -0
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/outcome.js +1 -1
- 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 +6 -0
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.js +1 -1
- package/dist/api/prompt-hook.d.ts +15 -2
- package/dist/api/prompt-hook.js +44 -4
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +3 -3
- package/dist/api/recall-pipeline.js +6 -7
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +19 -44
- package/dist/api/remember-local.js +1 -1
- package/dist/api/remember.d.ts +2 -1
- package/dist/api/remember.js +3 -2
- package/dist/api/session-end.d.ts +22 -0
- package/dist/api/session-end.js +101 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +13 -9
- 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 +1 -1
- package/dist/api/types.d.ts +2 -0
- 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 +4 -2
- package/dist/capture/compaction-spool.js +20 -6
- 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 +2 -1
- package/dist/capture/session-worker.js +3 -4
- 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 +13 -13
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +12 -13
- 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 +5 -0
- package/dist/cli/client.js +24 -8
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +12 -12
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +23 -27
- 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 +4 -281
- 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 +3 -5
- package/dist/cli/hook-runtime.js +7 -34
- 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/lenient-id.d.ts +2 -0
- package/dist/cli/lenient-id.js +13 -0
- 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/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 +175 -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 +17 -17
- package/dist/cli/remember.js +12 -12
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +3 -3
- package/dist/cli/session-hooks.d.ts +1 -1
- package/dist/cli/session-hooks.js +45 -115
- 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 +1 -1
- package/dist/cli/transfer.js +33 -31
- package/dist/cli/usage.d.ts +0 -79
- package/dist/cli/usage.js +1 -695
- package/dist/cli/verb-row.d.ts +32 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +232 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +244 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +254 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +312 -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 +23 -313
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +37 -3
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +3 -28
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +33 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +28 -0
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +2 -27
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +1 -1
- package/dist/consolidate/dag.js +15 -9
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +5 -3
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +2 -1
- package/dist/consolidate/merge.js +2 -2
- 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 +8 -5
- package/dist/consolidate/traces.js +3 -3
- 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 +7 -2
- 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 +2 -2
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +10 -4
- package/dist/core/memory.js +25 -18
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.js +6 -16
- 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 +10 -1
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +0 -1
- package/dist/db/connect.js +5 -6
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- 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.js +3 -3
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +17 -4
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.js +11 -8
- 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 +18 -15
- 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/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +11 -4
- 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 +4 -2
- 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 +1 -1
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.js +7 -5
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/learn/autolearn.d.ts +10 -2
- package/dist/learn/autolearn.js +32 -12
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +6 -4
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.js +10 -6
- 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.js +3 -1
- 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 +2 -1
- package/dist/mcp/stdio.js +24 -8
- 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 +63 -97
- 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 +9 -0
- package/dist/search/embed-memories.js +377 -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 +10 -13
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +17 -7
- package/dist/server/boot.js +7 -66
- package/dist/server/client-ip.d.ts +0 -2
- package/dist/server/client-ip.js +3 -2
- 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 -132
- 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 +15 -38
- 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/types.d.ts +22 -10
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +5 -4
- package/dist/server.js +5 -4
- package/dist/sharing/global-store.js +2 -2
- 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 +1 -1
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +37 -34
- package/dist/store/ambient.js +5 -6
- 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 +42 -23
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +1 -1
- 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 +417 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.js +7 -4
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +32 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +30 -53
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +18 -47
- package/dist/store/dashboard-reads.js +7 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +36 -3
- package/dist/store/delivery-recorder.d.ts +10 -3
- package/dist/store/delivery-recorder.js +12 -5
- package/dist/store/descendant-page.js +6 -3
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +3 -1
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +13 -4
- package/dist/store/entry-reads.js +47 -11
- package/dist/store/entry-writes.d.ts +5 -5
- package/dist/store/entry-writes.js +32 -12
- 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 +20 -18
- package/dist/store/graph-reads.js +4 -2
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +6 -6
- package/dist/store/index-and-stats.js +2 -2
- 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 +10 -6
- package/dist/store/open.d.ts +0 -4
- package/dist/store/open.js +40 -53
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +9 -3
- 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/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +18 -2
- package/dist/store/rejected-values.js +2 -1
- 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/rule-sql.d.ts +9 -0
- package/dist/store/rule-sql.js +21 -2
- package/dist/store/search-rows.js +9 -4
- 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 +3 -3
- package/dist/store/sqlite/entry-writes-group.js +2 -2
- 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 +9 -0
- package/dist/store/sqlite/held-connection.js +41 -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 +1 -1
- package/dist/store/sqlite/store.js +14 -12
- package/dist/store/summaries.d.ts +3 -3
- package/dist/store/summaries.js +5 -4
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +3 -2
- 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 +3 -0
- package/dist/util/anthropic-messages.js +22 -5
- 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 +2 -1
- package/dist/util/env.js +2 -1
- package/dist/util/format.d.ts +3 -0
- package/dist/util/format.js +6 -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 +3 -1
- package/dist/util/request-scope.js +11 -6
- package/dist/util/secret-detect.js +6 -1
- 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/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 +2 -2
- 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
package/dist/index.js
CHANGED
|
@@ -36,8 +36,9 @@ export { sleep } from './api/sleep.js';
|
|
|
36
36
|
// Announced public in CHANGELOG 1.26.3 but never re-exported; the rest of dedupe.js stays internal.
|
|
37
37
|
export { strengthBucket } from './consolidate/dedupe.js';
|
|
38
38
|
// Feature 1: Embedding search
|
|
39
|
-
export { isEmbeddingAvailable, getEmbedding } from './
|
|
40
|
-
export { cosineSimilarity
|
|
39
|
+
export { isEmbeddingAvailable, getEmbedding } from './embeddings/local.js';
|
|
40
|
+
export { cosineSimilarity } from './store/embeddings/index.js';
|
|
41
|
+
export { embedMemory, embedAll } from './search/embed-memories.js';
|
|
41
42
|
export { loadEmbeddingIndex, saveEmbeddingIndex } from './store/vector-index.js';
|
|
42
43
|
// Feature 2: Auto-learn from errors
|
|
43
44
|
export { captureError, extractLessons, partitionLessons, deduplicateLesson, runWatched, fetchGitLog, } from './learn/autolearn.js';
|
|
@@ -15,9 +15,17 @@ export declare function partitionLessons(lessons: string[]): {
|
|
|
15
15
|
/** Check if a substantially similar memory already exists: true if overlap > threshold (default 0.7).
|
|
16
16
|
* `tenantId` applies only on the root-string overload; a pre-loaded MemoryEntry[] is already scoped, so it is ignored there. */
|
|
17
17
|
export declare function deduplicateLesson(hippoRootOrEntries: string | MemoryEntry[], lesson: string, threshold?: number, tenantId?: string): boolean;
|
|
18
|
+
/** A transfer command that has not exited in this long is hung on a prompt or a dead remote. */
|
|
19
|
+
export declare const RUN_WATCHED_DEADLINE_MS: number;
|
|
20
|
+
/** The command passed its deadline and was killed. */
|
|
21
|
+
export declare class RunWatchedTimeoutError extends Error {
|
|
22
|
+
readonly deadlineMs: number;
|
|
23
|
+
readonly stderr: string;
|
|
24
|
+
constructor(deadlineMs: number, stderr: string);
|
|
25
|
+
}
|
|
18
26
|
/** Run a command in a shell, streaming stderr live; never pass text the caller did not write.
|
|
19
|
-
* Returns: { exitCode, stderr }
|
|
20
|
-
export declare function runWatched(command: string): Promise<{
|
|
27
|
+
* Returns: { exitCode, stderr } with only the last 64 KiB of stderr; rejects with RunWatchedTimeoutError past `deadlineMs`. */
|
|
28
|
+
export declare function runWatched(command: string, deadlineMs?: number): Promise<{
|
|
21
29
|
exitCode: number;
|
|
22
30
|
stderr: string;
|
|
23
31
|
}>;
|
package/dist/learn/autolearn.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Auto-learn from errors and git history.
|
|
2
2
|
* Agents learn from failures without explicit hippo remember calls. */
|
|
3
|
-
import {
|
|
3
|
+
import { execFileSync, spawn } from 'child_process';
|
|
4
4
|
import { createMemory, Layer, DEFAULT_HALF_LIFE_DAYS } from '../core/memory.js';
|
|
5
5
|
import { loadAllEntries } from '../store/entry-reads.js';
|
|
6
6
|
import { textOverlap } from '../util/tokenize.js';
|
|
@@ -97,25 +97,45 @@ export function deduplicateLesson(hippoRootOrEntries, lesson, threshold = 0.7, t
|
|
|
97
97
|
}
|
|
98
98
|
return false;
|
|
99
99
|
}
|
|
100
|
+
/** The most stderr `runWatched` returns; the terminal still gets all of it. */
|
|
101
|
+
const STDERR_TAIL_BYTES = 64 * 1024;
|
|
102
|
+
/** A transfer command that has not exited in this long is hung on a prompt or a dead remote. */
|
|
103
|
+
export const RUN_WATCHED_DEADLINE_MS = 30 * 60_000;
|
|
104
|
+
/** The command passed its deadline and was killed. */
|
|
105
|
+
export class RunWatchedTimeoutError extends Error {
|
|
106
|
+
deadlineMs;
|
|
107
|
+
stderr;
|
|
108
|
+
constructor(deadlineMs, stderr) {
|
|
109
|
+
super(`the command did not exit within ${deadlineMs} ms and was killed`);
|
|
110
|
+
this.deadlineMs = deadlineMs;
|
|
111
|
+
this.stderr = stderr;
|
|
112
|
+
this.name = 'RunWatchedTimeoutError';
|
|
113
|
+
}
|
|
114
|
+
}
|
|
100
115
|
/** Run a command in a shell, streaming stderr live; never pass text the caller did not write.
|
|
101
|
-
* Returns: { exitCode, stderr }
|
|
102
|
-
export function runWatched(command) {
|
|
103
|
-
return new Promise((resolve) => {
|
|
116
|
+
* Returns: { exitCode, stderr } with only the last 64 KiB of stderr; rejects with RunWatchedTimeoutError past `deadlineMs`. */
|
|
117
|
+
export function runWatched(command, deadlineMs = RUN_WATCHED_DEADLINE_MS) {
|
|
118
|
+
return new Promise((resolve, reject) => {
|
|
104
119
|
// Use shell: true so the command string is handled by the shell as-is
|
|
105
120
|
const child = spawn(command, { shell: true, stdio: ['inherit', 'inherit', 'pipe'], windowsHide: true });
|
|
106
|
-
|
|
121
|
+
let tail = Buffer.alloc(0);
|
|
107
122
|
child.stderr.on('data', (chunk) => {
|
|
108
|
-
|
|
109
|
-
|
|
123
|
+
tail = Buffer.concat([tail, chunk]);
|
|
124
|
+
if (tail.length > STDERR_TAIL_BYTES)
|
|
125
|
+
tail = tail.subarray(tail.length - STDERR_TAIL_BYTES);
|
|
110
126
|
process.stderr.write(chunk);
|
|
111
127
|
});
|
|
128
|
+
// SHORTCUT: kills the shell only; on Windows a grandchild can outlive it. A process-tree kill is the upgrade path.
|
|
129
|
+
const timer = setTimeout(() => {
|
|
130
|
+
child.kill('SIGKILL');
|
|
131
|
+
reject(new RunWatchedTimeoutError(deadlineMs, tail.toString('utf8')));
|
|
132
|
+
}, deadlineMs);
|
|
112
133
|
child.on('close', (code) => {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
stderr: Buffer.concat(stderrChunks).toString('utf8'),
|
|
116
|
-
});
|
|
134
|
+
clearTimeout(timer);
|
|
135
|
+
resolve({ exitCode: code ?? 1, stderr: tail.toString('utf8') });
|
|
117
136
|
});
|
|
118
137
|
child.on('error', (err) => {
|
|
138
|
+
clearTimeout(timer);
|
|
119
139
|
resolve({ exitCode: 1, stderr: err.message });
|
|
120
140
|
});
|
|
121
141
|
});
|
|
@@ -123,7 +143,7 @@ export function runWatched(command) {
|
|
|
123
143
|
/** Check whether a directory is a git work tree. */
|
|
124
144
|
export function isGitRepo(cwd) {
|
|
125
145
|
try {
|
|
126
|
-
const raw =
|
|
146
|
+
const raw = execFileSync('git', ['rev-parse', '--is-inside-work-tree'], {
|
|
127
147
|
encoding: 'utf8',
|
|
128
148
|
cwd,
|
|
129
149
|
timeout: 10000,
|
package/dist/learn/churn-git.js
CHANGED
|
@@ -3,12 +3,13 @@ import { execFileSync } from 'child_process';
|
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as os from 'os';
|
|
5
5
|
import * as path from 'path';
|
|
6
|
-
import { DAY_MS } from '../util/time.js';
|
|
6
|
+
import { DAY_MS, MINUTE_MS } from '../util/time.js';
|
|
7
7
|
import { errorMessage } from '../util/log.js';
|
|
8
|
+
import { isJsonObject, isJsonString } from '../util/json.js';
|
|
8
9
|
// A `git log --name-status` dump can run to tens of MB; default 1MB pipe would truncate it.
|
|
9
10
|
const GIT_MAX_BUFFER = 64 * 1024 * 1024;
|
|
10
11
|
// Longer than the 10 s of one-line git reads because a full log dump on a large repo is slow, yet bounded so a wedged git cannot stall sleep.
|
|
11
|
-
const GIT_TIMEOUT_MS =
|
|
12
|
+
const GIT_TIMEOUT_MS = MINUTE_MS;
|
|
12
13
|
/** A real git failure (not git grep's expected exit-1-no-match). Callers abort the whole run on this. */
|
|
13
14
|
export class GitReadError extends Error {
|
|
14
15
|
}
|
|
@@ -93,9 +94,17 @@ export function packageScriptsAt(repoRoot, rev) {
|
|
|
93
94
|
return {};
|
|
94
95
|
const raw = runGit(['show', `${rev}:package.json`], repoRoot);
|
|
95
96
|
try {
|
|
96
|
-
// SAFETY: optional chaining makes a `null` or scalar package.json read as "no scripts".
|
|
97
97
|
const parsed = JSON.parse(raw);
|
|
98
|
-
|
|
98
|
+
const scripts = isJsonObject(parsed) ? parsed.scripts : undefined;
|
|
99
|
+
if (!isJsonObject(scripts))
|
|
100
|
+
return {};
|
|
101
|
+
const out = {};
|
|
102
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
103
|
+
if (!isJsonString(command))
|
|
104
|
+
return {};
|
|
105
|
+
out[name] = command;
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
99
108
|
}
|
|
100
109
|
catch (err) {
|
|
101
110
|
if (err instanceof SyntaxError)
|
package/dist/learn/extract.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MemoryEntry, EmotionalValence } from '../core/memory.js';
|
|
2
|
+
import { type AnthropicMessageFailure } from '../util/anthropic-messages.js';
|
|
2
3
|
export interface ExtractedFact {
|
|
3
4
|
content: string;
|
|
4
5
|
tags: string[];
|
|
@@ -8,8 +9,8 @@ export interface ExtractOptions {
|
|
|
8
9
|
apiKey: string;
|
|
9
10
|
model?: string;
|
|
10
11
|
fetcher?: typeof fetch;
|
|
11
|
-
/** Told why a call produced nothing, so callers can surface it instead of guessing. */
|
|
12
|
-
onError?: (msg: string) => void;
|
|
12
|
+
/** Told why a call produced nothing, so callers can surface it instead of guessing; `failure` is set when the API call itself failed. */
|
|
13
|
+
onError?: (msg: string, failure?: AnthropicMessageFailure) => void;
|
|
13
14
|
}
|
|
14
15
|
export declare function extractFacts(text: string, opts: ExtractOptions): Promise<ExtractedFact[]>;
|
|
15
16
|
export declare function storeExtractedFacts(hippoRoot: string, source: MemoryEntry, facts: ExtractedFact[]): MemoryEntry[];
|
package/dist/learn/extract.js
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { Layer, createMemory } from '../core/memory.js';
|
|
2
2
|
import { writeEntry } from '../store/entry-writes.js';
|
|
3
3
|
import { loadConfig } from '../core/config.js';
|
|
4
|
-
import { RejectedValueError } from '../
|
|
4
|
+
import { RejectedValueError } from '../core/api-errors.js';
|
|
5
5
|
import { redactSecretsStrict } from '../util/secret-detect.js';
|
|
6
6
|
import { describeMessageFailure, sendAnthropicMessage } from '../util/anthropic-messages.js';
|
|
7
7
|
import { neverAutoShareTags } from '../sharing/share.js';
|
|
8
8
|
import { errorMessage, log } from '../util/log.js';
|
|
9
9
|
import { isJsonString } from '../util/json.js';
|
|
10
10
|
import { certainDefect } from '../core/memory-quality.js';
|
|
11
|
-
const EXTRACTION_PROMPT = `You are extracting factual statements from a conversation or memory entry.
|
|
11
|
+
const EXTRACTION_PROMPT = `You are extracting factual statements from a conversation or memory entry. ` +
|
|
12
|
+
`Extract 1-8 standalone factual statements that would be useful to remember later.
|
|
12
13
|
|
|
13
14
|
Rules:
|
|
14
15
|
- Each fact must be a complete, standalone sentence
|
|
15
16
|
- Include the speaker's name in every fact (e.g. "Alice prefers..." not "She prefers...")
|
|
16
17
|
- Preserve specific details: names, numbers, dates, paths, IDs
|
|
17
|
-
- Return a JSON array of objects with: content (string), tags (array of "speaker:X" and "topic:Y" strings),
|
|
18
|
+
- Return a JSON array of objects with: content (string), tags (array of "speaker:X" and "topic:Y" strings), ` +
|
|
19
|
+
`valence ("neutral", "positive", "negative", or "critical")
|
|
18
20
|
- Return an empty array [] for small talk with no extractable facts
|
|
19
21
|
- Output ONLY the JSON array, no preamble or explanation
|
|
20
22
|
|
|
@@ -31,7 +33,7 @@ export async function extractFacts(text, opts) {
|
|
|
31
33
|
fetcher: opts.fetcher,
|
|
32
34
|
});
|
|
33
35
|
if (!reply.ok) {
|
|
34
|
-
opts.onError?.(describeMessageFailure(reply.failure));
|
|
36
|
+
opts.onError?.(describeMessageFailure(reply.failure), reply.failure);
|
|
35
37
|
return [];
|
|
36
38
|
}
|
|
37
39
|
try {
|
|
@@ -7,7 +7,8 @@ const FORWARD_CLAIM_PATTERNS = [
|
|
|
7
7
|
// Verb + duration tail: requires `<verb> take <N> <unit>`, because a bare `will take` matched `who will take ownership of auth?`.
|
|
8
8
|
new RegExp(String.raw `\b(?:will|should|gonna|going\s+to)\s+take\s+${DURATION_TAIL}`, 'i'),
|
|
9
9
|
// Ship + by/in + duration-or-day: a bare `ship in` matched `how does this ship in Docker?`, so a duration tail or literal day-of-week is required.
|
|
10
|
-
new RegExp(String.raw `\bship(?:ping|s)?\s+(?:by|in)\s+(?:(?:about|around)\s+)?(?:next\s+)
|
|
10
|
+
new RegExp(String.raw `\bship(?:ping|s)?\s+(?:by|in)\s+(?:(?:about|around)\s+)?(?:next\s+)?` +
|
|
11
|
+
String.raw `(?:${DURATION_TAIL}|(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday))\b`, 'i'),
|
|
11
12
|
/\bestimate(?:d)?\s+(?:at\s+)?(?:~|≈|about|around)?\s*\d+/i,
|
|
12
13
|
/\b(?:by|in|within)\s+(?:about|around|~)?\s*\d+\s*(?:day|week|month|hour)s?\b/i,
|
|
13
14
|
/\bETA\s*(?:is|:)?\s*\d+/i,
|
|
@@ -17,7 +18,8 @@ const FORWARD_CLAIM_PATTERNS = [
|
|
|
17
18
|
/(?<=^|\s)~\s*\d+\s*(?:day|week|month|hour)s?\b/i,
|
|
18
19
|
// Should + verb + duration tail. Same tightening as the leading 'will
|
|
19
20
|
// take' rule: 'should ship by EOD' must include a quantifier.
|
|
20
|
-
new RegExp(String.raw `\bshould\s+(?:be|ship|finish|complete|land)\s+(?:by|in|within)\s+(?:(?:about|around)\s+)?(?:next\s+)
|
|
21
|
+
new RegExp(String.raw `\bshould\s+(?:be|ship|finish|complete|land)\s+(?:by|in|within)\s+(?:(?:about|around)\s+)?(?:next\s+)?` +
|
|
22
|
+
String.raw `(?:${DURATION_TAIL}|(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday))\b`, 'i'),
|
|
21
23
|
];
|
|
22
24
|
/** Pronouns, function words and modal verbs the regex set already gates on; dropped before class resolution so overlap comes from domain tokens. */
|
|
23
25
|
const STOP_WORDS = new Set([
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { addTagToEntries,
|
|
1
|
+
import { addTagToEntries, writeEntriesTogether } from '../store/entry-writes.js';
|
|
2
2
|
import { confirmedOutcomeTimes } from '../store/audit.js';
|
|
3
|
-
import {
|
|
3
|
+
import { loadAllEntries, loadEntriesByIds, loadEntriesMentioning, readEntry } from '../store/entry-reads.js';
|
|
4
|
+
import { chunked } from '../util/chunked.js';
|
|
4
5
|
import { CHURN_STALE_TAG } from '../core/memory.js';
|
|
5
6
|
import { GitReadError, gitLsFilesAtHead, fetchChurnWindowLog, gitGrepPresence, resolveCommitBefore, packageScriptsAt, } from './churn-git.js';
|
|
6
7
|
const HEADLINE_CHARS = 60;
|
|
@@ -46,9 +47,12 @@ export function extractInvalidationTarget(message) {
|
|
|
46
47
|
* Tag matching is EXACT: the FULL pattern must equal a tag, so a pattern merely containing a common tag word cannot mass-weaken every memory with that tag. */
|
|
47
48
|
export function invalidateMatching(hippoRoot, target, tenantId, options) {
|
|
48
49
|
// tenantId opt-in: when set, only that tenant's memories are weakened; undefined is host-wide.
|
|
49
|
-
//
|
|
50
|
-
const
|
|
51
|
-
|
|
50
|
+
// The onlyId read is tenant-scoped too, so another tenant's id is invisible here.
|
|
51
|
+
const entries = options?.onlyId === undefined
|
|
52
|
+
? loadEntriesMentioning(hippoRoot, invalidationTokenize(target.from), target.from.toLowerCase().trim(), tenantId)
|
|
53
|
+
: [readEntry(hippoRoot, options.onlyId, tenantId)].filter((entry) => entry !== null);
|
|
54
|
+
const { result, weakened } = weakenMatches(entries, target, options);
|
|
55
|
+
writeEntriesTogether(hippoRoot, weakened);
|
|
52
56
|
return result;
|
|
53
57
|
}
|
|
54
58
|
/** invalidateMatching for a batch: matches against `live`, the caller's list of the tenant's rows, and keeps it current.
|
|
@@ -59,7 +63,7 @@ export function invalidateMatchingAmong(hippoRoot, live, target, tenantId) {
|
|
|
59
63
|
// loadEntriesByIds reads at most 500 ids a call.
|
|
60
64
|
const fresh = new Map(chunked(ids, 500).flatMap((chunk) => loadEntriesByIds(hippoRoot, chunk, tenantId)).map((entry) => [entry.id, entry]));
|
|
61
65
|
const { result, weakened } = weakenMatches(ids.flatMap((id) => fresh.get(id) ?? []), target);
|
|
62
|
-
|
|
66
|
+
writeEntriesTogether(hippoRoot, weakened);
|
|
63
67
|
const byId = new Map(weakened.map((entry) => [entry.id, entry]));
|
|
64
68
|
for (let i = 0; i < live.length; i++)
|
|
65
69
|
live[i] = byId.get(live[i].id) ?? live[i];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type ToolCall } from './protocol.js';
|
|
2
2
|
export declare function runPredictBaserateTool({ args, ctx, hippoRoot, tenantId }: ToolCall): Promise<string>;
|
|
3
|
-
export declare function runStatusTool({ hippoRoot, config, tenantId }: ToolCall): string;
|
|
3
|
+
export declare function runStatusTool({ ctx, hippoRoot, config, tenantId }: ToolCall): string;
|
|
4
4
|
export declare function runConflictsTool(call: ToolCall): string;
|
|
5
5
|
export declare function runResolveTool({ args, ctx, hippoRoot, tenantId }: ToolCall): string;
|
|
6
|
-
export declare function runShareTool({ args, ctx, hippoRoot, tenantId }: ToolCall): string
|
|
6
|
+
export declare function runShareTool({ args, ctx, hippoRoot, tenantId }: ToolCall): Promise<string>;
|
|
7
7
|
export declare function runPeersTool({ tenantId }: ToolCall): string;
|
|
8
8
|
//# sourceMappingURL=admin-tools.d.ts.map
|
package/dist/mcp/admin-tools.js
CHANGED
|
@@ -1,30 +1,25 @@
|
|
|
1
1
|
// Store health and admin tool handlers: base rates, status, conflicts, resolve, share and peers.
|
|
2
2
|
import { evalNow } from '../core/ablation.js';
|
|
3
|
-
import { loadStrengthTallies } from '../store/candidates.js';
|
|
4
|
-
import { countOpenConflicts, listTouchableConflicts, resolveConflict } from '../store/conflicts.js';
|
|
5
3
|
import { shareMemory, listPeers } from '../sharing/share.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { chunked, loadEntriesByIds, readEntry } from '../store/entry-reads.js';
|
|
4
|
+
import { ConflictError, NotFoundError } from '../core/api-errors.js';
|
|
5
|
+
import { predictionBaserate } from '../api/predictions.js';
|
|
6
|
+
import { listOpenConflicts, resolveMemoryConflict } from '../api/conflicts.js';
|
|
7
|
+
import { getMemoryStatus, getTouchableMemory } from '../api/memories.js';
|
|
11
8
|
import { mcpActor } from './protocol.js';
|
|
12
9
|
import { isJsonString } from '../util/json.js';
|
|
13
10
|
import { DATE_PREFIX_CHARS } from '../util/token-text.js';
|
|
14
11
|
const BASERATE_DECIMALS = 3;
|
|
15
12
|
const NOT_RESOLVED = 'Could not resolve. Check the conflict ID and --keep value.';
|
|
16
|
-
/** The scope of memory `id`, null when it has none or does not exist. */
|
|
17
|
-
function memoryScope(hippoRoot, id) {
|
|
18
|
-
return readEntry(hippoRoot, id)?.scope ?? null;
|
|
19
|
-
}
|
|
20
13
|
export async function runPredictBaserateTool({ args, ctx, hippoRoot, tenantId }) {
|
|
21
14
|
// Text-only reply, matching the other MCP tools; the group's read writes the audit row, so no surface can skip it.
|
|
22
15
|
const classTag = String(args.class_tag || '').trim();
|
|
23
16
|
if (!classTag)
|
|
24
17
|
return 'No class_tag provided. Usage: pass class_tag matching a class used in past predictions (e.g. "migration-effort").';
|
|
25
|
-
const baserate = await
|
|
18
|
+
const baserate = await predictionBaserate({ hippoRoot, tenantId, actor: mcpActor(ctx), store: ctx?.store }, classTag);
|
|
26
19
|
if (baserate.nClosed === 0) {
|
|
27
|
-
return `No closed predictions in class "${classTag}" yet. Create one via hippo_predict (or 'hippo predict ...' CLI)
|
|
20
|
+
return `No closed predictions in class "${classTag}" yet. Create one via hippo_predict (or 'hippo predict ...' CLI) ` +
|
|
21
|
+
`and close it with hippo_predict_close once the actual outcome is known. ` +
|
|
22
|
+
`Base rates need closed predictions with numeric actual_value to compute.`;
|
|
28
23
|
}
|
|
29
24
|
const lines = [baserate.summary, ''];
|
|
30
25
|
lines.push(`n_closed: ${baserate.nClosed}`);
|
|
@@ -41,36 +36,21 @@ export async function runPredictBaserateTool({ args, ctx, hippoRoot, tenantId })
|
|
|
41
36
|
lines.push(`mae: ${baserate.mae.toFixed(BASERATE_DECIMALS)}`);
|
|
42
37
|
return lines.join('\n');
|
|
43
38
|
}
|
|
44
|
-
export function runStatusTool({ hippoRoot, config, tenantId }) {
|
|
39
|
+
export function runStatusTool({ ctx, hippoRoot, config, tenantId }) {
|
|
45
40
|
// honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
|
|
46
|
-
const tallies =
|
|
41
|
+
const tallies = getMemoryStatus({ hippoRoot, tenantId, actor: mcpActor(ctx), store: ctx?.store }, evalNow(), 0.1);
|
|
47
42
|
const avgStrength = tallies.total > 0 ? (tallies.strengthSum / tallies.total).toFixed(2) : '0';
|
|
48
|
-
const conflicts = countOpenConflicts(hippoRoot, tenantId);
|
|
49
43
|
return [
|
|
50
44
|
`Memories: ${tallies.total} (${tallies.pinned} pinned, ${tallies.errors} errors)`,
|
|
51
45
|
`Avg strength: ${avgStrength}`,
|
|
52
46
|
`At risk (<0.1): ${tallies.atRisk}`,
|
|
53
|
-
`Open conflicts: ${
|
|
47
|
+
`Open conflicts: ${tallies.openConflicts}`,
|
|
54
48
|
`Half-life default: ${config.defaultHalfLifeDays}d`,
|
|
55
49
|
].join('\n');
|
|
56
50
|
}
|
|
57
|
-
/** Pairs whose two rows the caller could recall: its repo or user-global, and no scope it was not asked for. */
|
|
58
|
-
function recallablePairs(call, conflicts, project) {
|
|
59
|
-
const own = personalScopeOf(mcpActor(call.ctx));
|
|
60
|
-
const ids = [...new Set(conflicts.flatMap((c) => [c.memory_a_id, c.memory_b_id]))];
|
|
61
|
-
// loadEntriesByIds reads at most one chunk of ids per call.
|
|
62
|
-
const rows = new Map(chunked(ids).flatMap((chunk) => loadEntriesByIds(call.hippoRoot, chunk, call.tenantId)).map((row) => [row.id, row]));
|
|
63
|
-
const shown = (id) => {
|
|
64
|
-
const row = rows.get(id);
|
|
65
|
-
return row !== undefined && classifyOriginProject(row.origin_project, project) !== 'cross-project'
|
|
66
|
-
&& passesScopeFilterForRecall(row.scope ?? null, undefined, own);
|
|
67
|
-
};
|
|
68
|
-
return conflicts.filter((c) => shown(c.memory_a_id) && shown(c.memory_b_id));
|
|
69
|
-
}
|
|
70
51
|
export function runConflictsTool(call) {
|
|
71
52
|
const { ctx, hippoRoot, tenantId } = call;
|
|
72
|
-
const
|
|
73
|
-
const conflicts = ctx?.project ? recallablePairs(call, touchable, ctx.project) : touchable;
|
|
53
|
+
const conflicts = listOpenConflicts({ hippoRoot, tenantId, actor: mcpActor(ctx), store: ctx?.store }, ctx?.project);
|
|
74
54
|
if (conflicts.length === 0)
|
|
75
55
|
return 'No open conflicts.';
|
|
76
56
|
return conflicts.map((c) => `conflict_${c.id}: ${c.memory_a_id} <-> ${c.memory_b_id} (score=${c.score.toFixed(2)}) — ${c.reason}`).join('\n');
|
|
@@ -79,33 +59,32 @@ export function runResolveTool({ args, ctx, hippoRoot, tenantId }) {
|
|
|
79
59
|
const conflictId = Number(args.conflict_id);
|
|
80
60
|
const keepId = String(args.keep || '');
|
|
81
61
|
const forget = Boolean(args.forget);
|
|
82
|
-
// Optional rejectLoser + reason pass straight to resolveConflict, as the CLI's --reject-loser does.
|
|
83
62
|
const rejectLoser = Boolean(args.rejectLoser);
|
|
84
63
|
const reason = isJsonString(args.reason) ? args.reason : undefined;
|
|
85
64
|
if (isNaN(conflictId) || !keepId)
|
|
86
65
|
return 'Required: conflict_id and keep.';
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
66
|
+
let loserId;
|
|
67
|
+
try {
|
|
68
|
+
const apiCtx = { hippoRoot, tenantId, actor: mcpActor(ctx), store: ctx?.store };
|
|
69
|
+
({ loserId } = resolveMemoryConflict(apiCtx, conflictId, { keepId, forget, rejectLoser, reason }));
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
// A missing, unreachable or settled conflict answers alike, so the reply says nothing of a pair the caller cannot touch.
|
|
73
|
+
if (err instanceof NotFoundError || err instanceof ConflictError)
|
|
74
|
+
return NOT_RESOLVED;
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
98
77
|
const action = rejectLoser ? 'rejected (tombstoned) and removed' : forget ? 'deleted' : 'weakened';
|
|
99
|
-
return `Resolved conflict ${conflictId}: kept ${keepId}, ${action} ${
|
|
78
|
+
return `Resolved conflict ${conflictId}: kept ${keepId}, ${action} ${loserId}`;
|
|
100
79
|
}
|
|
101
|
-
export function runShareTool({ args, ctx, hippoRoot, tenantId }) {
|
|
80
|
+
export async function runShareTool({ args, ctx, hippoRoot, tenantId }) {
|
|
102
81
|
const shareId = String(args.id || '');
|
|
103
82
|
if (!shareId)
|
|
104
83
|
return 'Required: id (memory ID to share).';
|
|
105
84
|
const force = Boolean(args.force);
|
|
85
|
+
const actor = mcpActor(ctx);
|
|
106
86
|
// Checked before shareMemory, whose personal-row refusal would tell another person the id exists.
|
|
107
|
-
|
|
108
|
-
throw new NotFoundError(`Memory not found: ${shareId}`);
|
|
87
|
+
await getTouchableMemory({ hippoRoot, tenantId, actor, store: ctx?.store }, shareId);
|
|
109
88
|
// Pass tenantId so shareMemory's readEntry filters by tenant; otherwise a Bearer for tenant A could share tenant B's id to the global store.
|
|
110
89
|
// The 'Memory not found' error matches the cross-tenant deny shape elsewhere.
|
|
111
90
|
const shared = shareMemory(hippoRoot, shareId, { force, tenantId });
|
package/dist/mcp/format.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Text the MCP recall and context tools print, and what each printed piece costs the token budget.
|
|
2
|
+
import { truncateWithEllipsis } from '../util/ellipsize.js';
|
|
2
3
|
import { confidenceLabel } from '../core/memory.js';
|
|
3
4
|
import { formatHandoffEvidenceLine } from '../core/handoff.js';
|
|
4
5
|
import { printedTokens } from '../api/context-render.js';
|
|
@@ -25,7 +26,7 @@ function handoffLines(h) {
|
|
|
25
26
|
}
|
|
26
27
|
function trailLines(events) {
|
|
27
28
|
return events.map((e) => {
|
|
28
|
-
const preview = e.content
|
|
29
|
+
const preview = truncateWithEllipsis(e.content, MCP_PREVIEW_CHARS, '…');
|
|
29
30
|
return `- [${e.event_type}] ${preview}`;
|
|
30
31
|
});
|
|
31
32
|
}
|
|
@@ -111,7 +112,7 @@ export function tailSection(rows) {
|
|
|
111
112
|
const lines = ['', '## Fresh tail / substituted summaries'];
|
|
112
113
|
for (const r of rows) {
|
|
113
114
|
const tag = r.isSummary ? '[summary]' : '[tail]';
|
|
114
|
-
const head = r.content
|
|
115
|
+
const head = truncateWithEllipsis(r.content, MCP_PREVIEW_CHARS, '…');
|
|
115
116
|
if (r.isSummary && r.substitutedFor && r.substitutedFor.length > 0) {
|
|
116
117
|
lines.push(`- ${tag} ${r.id} (covers ${r.substitutedFor.length} rows): ${head}`);
|
|
117
118
|
}
|
package/dist/mcp/framing.d.ts
CHANGED
package/dist/mcp/framing.js
CHANGED
|
@@ -31,7 +31,7 @@ export function parseFrame(buffer) {
|
|
|
31
31
|
return { kind: 'oversize', rest: Buffer.from(trimmed.subarray(Math.min(end, trimmed.length))), remainder: Math.max(0, end - trimmed.length) };
|
|
32
32
|
}
|
|
33
33
|
if (trimmed.length < bodyStart + contentLength)
|
|
34
|
-
return { kind: 'incomplete' };
|
|
34
|
+
return { kind: 'incomplete', needs: start + bodyStart + contentLength };
|
|
35
35
|
const body = trimmed.subarray(bodyStart, bodyStart + contentLength).toString('utf-8');
|
|
36
36
|
return { kind: 'message', body, rest: Buffer.from(trimmed.subarray(bodyStart + contentLength)) };
|
|
37
37
|
}
|
package/dist/mcp/memory-tools.js
CHANGED
|
@@ -29,7 +29,8 @@ export async function runRememberTool({ args, ctx, hippoRoot, config, tenantId }
|
|
|
29
29
|
});
|
|
30
30
|
const [entry] = await storeFor(apiCtx).entriesByIds([result.id], tenantId);
|
|
31
31
|
// Auto-sleep runs on hippo.db, so another store skips it.
|
|
32
|
-
|
|
32
|
+
const allowed = (ctx?.store === undefined || ctx.store.kind === 'sqlite') && ctx?.autoSleep !== false;
|
|
33
|
+
startAutoSleepIfDue(hippoRoot, tenantId, config.autoSleep, allowed, ctx?.autoSleepRunner);
|
|
33
34
|
const halfLife = entry?.half_life_days ?? config.defaultHalfLifeDays;
|
|
34
35
|
const tagStr = entry?.tags.join(', ') || tags.join(', ') || 'none';
|
|
35
36
|
const warnings = (result.warnings ?? []).map((w) => `\nWarning: ${w}`).join('');
|
|
@@ -54,6 +55,7 @@ export async function runOutcomeTool({ args, ctx, hippoRoot, tenantId }) {
|
|
|
54
55
|
}
|
|
55
56
|
export function runLearnTool({ args, ctx, hippoRoot, tenantId }) {
|
|
56
57
|
const days = Number(args.days) || 7;
|
|
58
|
+
// process.cwd() is the server's repo, not a remote caller's, so api learn refuses all but stdio and a host admin (mcpActor fails closed).
|
|
57
59
|
const result = apiLearn({ hippoRoot, tenantId, actor: mcpActor(ctx), store: ctx?.store }, { repoPath: process.cwd(), days, profile: MCP_LEARN });
|
|
58
60
|
if (result.status === 'not-a-repo')
|
|
59
61
|
return 'No git history found.';
|
package/dist/mcp/protocol.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { type ResolveProjectIdentityOpts } from '../core/project-identity.js';
|
|
|
4
4
|
import { type JsonValue } from '../util/json.js';
|
|
5
5
|
import type { CallerProject } from '../api/prompt-hook.js';
|
|
6
6
|
import type { HippoStore } from '../store/index.js';
|
|
7
|
+
import type { AutoSleepRunner } from '../api/auto-sleep.js';
|
|
7
8
|
/** Same bounded walk as the CLI (ends at home, so HIPPO_HOME wins over ~/.hippo); cwd/opts are the test seam. */
|
|
8
9
|
export declare function findHippoRoot(cwd?: string, opts?: ResolveProjectIdentityOpts): string | null;
|
|
9
10
|
interface McpRequest {
|
|
@@ -25,7 +26,7 @@ interface McpResponse {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
/** JSON-RPC reply for a request that threw: typed API errors keep their text; anything else is logged and answered generically. */
|
|
28
|
-
export declare function mcpErrorResponse<E>(id: McpResponse['id'], err: E, requestId?: string): McpResponse;
|
|
29
|
+
export declare function mcpErrorResponse<E>(id: McpResponse['id'], err: E, requestId?: string, call?: string): McpResponse;
|
|
29
30
|
export type { McpRequest, McpResponse };
|
|
30
31
|
/** Optional context from a non-stdio transport (the HTTP server's bound hippoRoot and auth-resolved tenantId/actor), so executeTool skips the
|
|
31
32
|
* findHippoRoot() walk and the env-based resolveTenantId({}) fallback, which would pick the wrong store and tenant for HTTP callers. Stdio passes nothing. */
|
|
@@ -33,25 +34,28 @@ export interface McpContext {
|
|
|
33
34
|
hippoRoot: string;
|
|
34
35
|
tenantId: string;
|
|
35
36
|
actor: string;
|
|
36
|
-
/** The caller's role
|
|
37
|
-
|
|
38
|
-
role?: 'admin' | 'member';
|
|
37
|
+
/** The caller's authenticated role. Required so no transport can forget it; only stdio, which passes no context, is admin without one. */
|
|
38
|
+
role: 'admin' | 'member';
|
|
39
39
|
/** Scope grants for the HTTP-MCP caller's key. Absent for stdio (admin, needs none). */
|
|
40
40
|
scopes?: readonly string[];
|
|
41
41
|
viaAuthResolver?: true;
|
|
42
|
-
/** Set by the HTTP transport for the host's operator;
|
|
42
|
+
/** Set by the HTTP transport for the host's operator; never implied by the role. */
|
|
43
43
|
hostAdmin?: true;
|
|
44
44
|
owner?: string;
|
|
45
45
|
project?: CallerProject;
|
|
46
46
|
store?: HippoStore;
|
|
47
47
|
autoSleep?: false;
|
|
48
|
+
/** Set by the HTTP transport so auto-sleep runs off the server's event loop; stdio consolidates in its own process. */
|
|
49
|
+
autoSleepRunner?: AutoSleepRunner;
|
|
48
50
|
/** Per-client key for state isolation under HTTP-MCP: 'stdio-${pid}' for stdio, hash(bearer + remoteAddr) for HTTP (built in src/server/mcp-http.ts);
|
|
49
51
|
* defaults to `${tenantId}:default`. */
|
|
50
52
|
clientKey?: string;
|
|
51
53
|
}
|
|
52
|
-
/** The api-layer actor for a tool call
|
|
53
|
-
*
|
|
54
|
+
/** The api-layer actor for a tool call. Only stdio passes no context: it is the local operator, host admin. Any context runs as its own role, and an
|
|
55
|
+
* untyped caller that sends none runs as a member, so a missing role fails closed. */
|
|
54
56
|
export declare function mcpActor(ctx: McpContext | undefined): ApiActor;
|
|
57
|
+
/** Stdio or a host admin: the only callers whose server cwd and git history are their own to read. */
|
|
58
|
+
export declare function ownsServerCwd(ctx: McpContext | undefined): boolean;
|
|
55
59
|
/** One tool call after the store, config and tenant are resolved; every handler reads the same four. */
|
|
56
60
|
export interface ToolCall {
|
|
57
61
|
args: Record<string, JsonValue>;
|
package/dist/mcp/protocol.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
// MCP wire types, the caller context, and the JSON predicates every tool handler narrows its arguments with.
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import {
|
|
4
|
+
import { mapApiError } from '../api/error-reply.js';
|
|
5
|
+
import { INTERNAL_ERROR_MESSAGE } from '../util/http-util.js';
|
|
5
6
|
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
6
7
|
import { currentRequestId } from '../util/request-scope.js';
|
|
7
8
|
import { getGlobalRoot } from '../sharing/global-store.js';
|
|
8
9
|
import { findHippoStoreDir } from '../core/project-identity.js';
|
|
9
|
-
import {
|
|
10
|
+
import { STORE_BUSY_MESSAGE } from '../store/port.js';
|
|
11
|
+
import { isStoreBusy } from '../store/sqlite/busy.js';
|
|
10
12
|
// ── Find hippo root ──
|
|
11
13
|
/** Same bounded walk as the CLI (ends at home, so HIPPO_HOME wins over ~/.hippo); cwd/opts are the test seam. */
|
|
12
14
|
export function findHippoRoot(cwd = process.cwd(), opts) {
|
|
@@ -18,29 +20,40 @@ export function findHippoRoot(cwd = process.cwd(), opts) {
|
|
|
18
20
|
return fs.existsSync(global) ? global : null;
|
|
19
21
|
}
|
|
20
22
|
/** JSON-RPC reply for a request that threw: typed API errors keep their text; anything else is logged and answered generically. */
|
|
21
|
-
export function mcpErrorResponse(id, err, requestId = currentRequestId() ?? randomUUID()) {
|
|
22
|
-
|
|
23
|
+
export function mcpErrorResponse(id, err, requestId = currentRequestId() ?? randomUUID(), call) {
|
|
24
|
+
const where = call === undefined ? '' : ` (${call})`;
|
|
25
|
+
if (isStoreBusy(err)) {
|
|
26
|
+
log.warn(`mcp request${where} failed: ${errorMessage(err)}`, { requestId });
|
|
23
27
|
return { jsonrpc: '2.0', id, error: { code: -32603, message: STORE_BUSY_MESSAGE } };
|
|
28
|
+
}
|
|
24
29
|
const { status, message } = mapApiError(err);
|
|
25
|
-
if (status !== 500)
|
|
30
|
+
if (status !== 500) {
|
|
31
|
+
log.info(`mcp request${where} failed: ${errorMessage(err)}`, { requestId, status });
|
|
26
32
|
return { jsonrpc: '2.0', id, error: { code: -32603, message } };
|
|
27
|
-
|
|
33
|
+
}
|
|
34
|
+
log.error(`mcp request${where} failed: ${errorMessage(err)}`, { requestId, ...errorFields(err) });
|
|
28
35
|
return {
|
|
29
36
|
jsonrpc: '2.0',
|
|
30
37
|
id,
|
|
31
38
|
error: { code: -32603, message: `${INTERNAL_ERROR_MESSAGE} (request id ${requestId})`, data: { requestId } },
|
|
32
39
|
};
|
|
33
40
|
}
|
|
34
|
-
/** The api-layer actor for a tool call
|
|
35
|
-
*
|
|
41
|
+
/** The api-layer actor for a tool call. Only stdio passes no context: it is the local operator, host admin. Any context runs as its own role, and an
|
|
42
|
+
* untyped caller that sends none runs as a member, so a missing role fails closed. */
|
|
36
43
|
export function mcpActor(ctx) {
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
if (ctx === undefined)
|
|
45
|
+
return { subject: 'mcp', role: 'admin', hostAdmin: true };
|
|
46
|
+
const actor = { subject: ctx.actor ?? 'mcp', role: ctx.role === 'admin' ? 'admin' : 'member', scopes: ctx.scopes };
|
|
47
|
+
if (ctx.viaAuthResolver)
|
|
39
48
|
actor.viaAuthResolver = true;
|
|
40
|
-
if (ctx
|
|
49
|
+
if (ctx.hostAdmin)
|
|
41
50
|
actor.hostAdmin = true;
|
|
42
|
-
if (ctx
|
|
51
|
+
if (ctx.owner !== undefined)
|
|
43
52
|
actor.owner = ctx.owner;
|
|
44
53
|
return actor;
|
|
45
54
|
}
|
|
55
|
+
/** Stdio or a host admin: the only callers whose server cwd and git history are their own to read. */
|
|
56
|
+
export function ownsServerCwd(ctx) {
|
|
57
|
+
return mcpActor(ctx).hostAdmin === true;
|
|
58
|
+
}
|
|
46
59
|
//# sourceMappingURL=protocol.js.map
|