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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync, unlinkSync, renameSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { envHealthProbeMs } from '../util/env.js';
|
|
4
|
+
import { errorCode, errorFields, errorMessage, log } from '../util/log.js';
|
|
4
5
|
// Pidfile sits directly inside hippoRoot (the `.hippo` directory itself, as for openHippoDb), i.e. `${hippoRoot}/server.pid`.
|
|
5
6
|
const PIDFILE = 'server.pid';
|
|
6
7
|
/** How long detectServer waits for the `/health` probe before treating the pidfile as stale; short because it fires only when a pidfile exists with a live
|
|
@@ -11,6 +12,15 @@ const HEALTH_PROBE_TIMEOUT_MS = 300;
|
|
|
11
12
|
const HEALTH_BODY_MAX_BYTES = 64 * 1024;
|
|
12
13
|
/** Loopback hosts a recorded pidfile url may point at (serve() only binds these); any other host is malformed or forged and is not probed. */
|
|
13
14
|
const PIDFILE_LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);
|
|
15
|
+
/** The pidfile names a live process on loopback that did not answer /health in time: most likely a busy server, so a caller must neither
|
|
16
|
+
* bypass it with a second writer nor start another server beside it. */
|
|
17
|
+
export class ServerUnresponsiveError extends Error {
|
|
18
|
+
constructor(info, probeMs, options) {
|
|
19
|
+
super(`a hippo server (pid ${info.pid}) is recorded at ${info.url} but did not answer /health within ${probeMs} ms; it may be busy. ` +
|
|
20
|
+
'Retry shortly, raise HIPPO_HEALTH_PROBE_MS, or stop that server.', options);
|
|
21
|
+
this.name = 'ServerUnresponsiveError';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
14
24
|
/** False when the pidfile's pid is dead or its url could not be one serve() wrote. */
|
|
15
25
|
function isLiveLoopbackTarget(info) {
|
|
16
26
|
// Signal 0 throws if the pid is dead or owned by another user we cannot signal; either way, treat as stale.
|
|
@@ -56,14 +66,23 @@ async function readCappedBody(body) {
|
|
|
56
66
|
raw += decoder.decode();
|
|
57
67
|
return raw;
|
|
58
68
|
}
|
|
59
|
-
/** True when
|
|
69
|
+
/** True when fetch failed because nothing listens on the port (the error or its cause, or any address tried, is ECONNREFUSED). */
|
|
70
|
+
function isConnectionRefused(err) {
|
|
71
|
+
if (errorCode(err) === 'ECONNREFUSED')
|
|
72
|
+
return true;
|
|
73
|
+
const cause = err instanceof Error ? err.cause : undefined;
|
|
74
|
+
if (errorCode(cause) === 'ECONNREFUSED')
|
|
75
|
+
return true;
|
|
76
|
+
return cause instanceof AggregateError && cause.errors.length > 0 && cause.errors.every((e) => errorCode(e) === 'ECONNREFUSED');
|
|
77
|
+
}
|
|
78
|
+
/** True when /health on info.url reports the pidfile's started_at; unlinks the pidfile on any definitive mismatch and throws ServerUnresponsiveError on a
|
|
79
|
+
* probe timeout. */
|
|
60
80
|
async function healthMatchesPidfile(hippoRoot, info) {
|
|
61
|
-
//
|
|
62
|
-
//
|
|
81
|
+
// Refusal, non-200 or a malformed body unlink the pidfile as stale. A timeout proves neither a dead server nor this one, so it keeps the pidfile and throws.
|
|
82
|
+
// Any other error keeps it and warns.
|
|
83
|
+
const probeMs = envHealthProbeMs() ?? HEALTH_PROBE_TIMEOUT_MS;
|
|
63
84
|
try {
|
|
64
|
-
const res = await fetch(`${info.url}/health`, {
|
|
65
|
-
signal: AbortSignal.timeout(envHealthProbeMs() ?? HEALTH_PROBE_TIMEOUT_MS),
|
|
66
|
-
});
|
|
85
|
+
const res = await fetch(`${info.url}/health`, { signal: AbortSignal.timeout(probeMs) });
|
|
67
86
|
if (!res.ok || !res.body) {
|
|
68
87
|
removePidfile(hippoRoot);
|
|
69
88
|
return false;
|
|
@@ -81,16 +100,21 @@ async function healthMatchesPidfile(hippoRoot, info) {
|
|
|
81
100
|
return true;
|
|
82
101
|
}
|
|
83
102
|
catch (err) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
if (err instanceof Error && err.name === 'TimeoutError')
|
|
104
|
+
throw new ServerUnresponsiveError(info, probeMs, { cause: err });
|
|
105
|
+
// A refusal or a non-JSON body proves no hippo server answers there; any other failure may be a live server, so the file stays.
|
|
106
|
+
if (isConnectionRefused(err) || err instanceof SyntaxError) {
|
|
87
107
|
removePidfile(hippoRoot);
|
|
88
108
|
}
|
|
109
|
+
else {
|
|
110
|
+
log.warn(`server pidfile ${join(hippoRoot, PIDFILE)} kept: the /health probe failed (${errorMessage(err)})`, errorFields(err));
|
|
111
|
+
}
|
|
89
112
|
return false;
|
|
90
113
|
}
|
|
91
114
|
}
|
|
92
115
|
/** Returns the pidfile's ServerInfo if a live hippo server answers on the recorded url, else null (best-effort unlinking of missing/stale/malformed pidfiles).
|
|
93
|
-
* `process.kill(pid, 0)` rules out dead pids; GET /health must then return the pidfile's `started_at` (pids get reused). Probes only if the pid is live.
|
|
116
|
+
* `process.kill(pid, 0)` rules out dead pids; GET /health must then return the pidfile's `started_at` (pids get reused). Probes only if the pid is live.
|
|
117
|
+
* Throws ServerUnresponsiveError when that probe times out. */
|
|
94
118
|
export async function detectServer(hippoRoot) {
|
|
95
119
|
const path = join(hippoRoot, PIDFILE);
|
|
96
120
|
if (!existsSync(path))
|
|
@@ -99,7 +123,8 @@ export async function detectServer(hippoRoot) {
|
|
|
99
123
|
try {
|
|
100
124
|
info = JSON.parse(readFileSync(path, 'utf8'));
|
|
101
125
|
}
|
|
102
|
-
catch {
|
|
126
|
+
catch (err) {
|
|
127
|
+
log.warn(`server pidfile ${path} is unreadable (${errorMessage(err)}); removing it`);
|
|
103
128
|
removePidfile(hippoRoot);
|
|
104
129
|
return null;
|
|
105
130
|
}
|
|
@@ -1,19 +1,38 @@
|
|
|
1
|
-
// Entry of the process that runs one POST /v1/sleep; sleep-offload.ts starts it and nothing imports it.
|
|
2
|
-
// The sleep
|
|
1
|
+
// Entry of the process that runs one POST /v1/sleep or MCP auto-sleep; sleep-offload.ts starts it and nothing imports it.
|
|
2
|
+
// The sleep modules alone: the api barrel loads far more than one sleep needs, and every sleep pays for the start.
|
|
3
3
|
import { sleep } from '../api/sleep.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { consolidate } from '../consolidate/sleep.js';
|
|
5
|
+
import { runWithRequestStores, SERVER_DB_WAIT_MS } from '../db/index.js';
|
|
6
|
+
import { isStoreBusy } from '../store/sqlite/busy.js';
|
|
7
|
+
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
6
8
|
function failed(err) {
|
|
7
9
|
return { ok: false, busy: isStoreBusy(err), message: errorMessage(err), stack: err instanceof Error ? err.stack : undefined };
|
|
8
10
|
}
|
|
11
|
+
/** Resolves to the exit code once the channel has taken the reply, or failed to. */
|
|
12
|
+
function sendReply(reply) {
|
|
13
|
+
return new Promise((resolve) => {
|
|
14
|
+
process.send?.(reply, (sendErr) => {
|
|
15
|
+
if (sendErr)
|
|
16
|
+
log.error(`sleep child: sending the reply failed: ${errorMessage(sendErr)}`, errorFields(sendErr));
|
|
17
|
+
resolve(sendErr ? 1 : 0);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
}
|
|
9
21
|
process.once('message', (message) => {
|
|
10
22
|
// SAFETY: sleep-offload.ts is the only writer on this channel and sends exactly one SleepJob.
|
|
11
23
|
const job = message;
|
|
12
|
-
const
|
|
24
|
+
const work = () => job.kind === 'consolidate'
|
|
25
|
+
? consolidate(job.hippoRoot)
|
|
26
|
+
: sleep({ hippoRoot: job.hippoRoot, tenantId: job.tenantId, actor: job.actor }, job.opts);
|
|
13
27
|
// The server's own request scope and lock wait, so a busy store answers as it did when sleep ran in the server.
|
|
14
|
-
runWithRequestStores(
|
|
28
|
+
runWithRequestStores(work, { busyWaitMs: SERVER_DB_WAIT_MS })
|
|
15
29
|
.then((result) => ({ ok: true, result }), failed)
|
|
16
30
|
// Exit only once the reply is written, or the parent could see the process end first.
|
|
17
|
-
.then(
|
|
31
|
+
.then(sendReply)
|
|
32
|
+
.catch((err) => {
|
|
33
|
+
log.error(`sleep child: the reply could not be sent: ${errorMessage(err)}`, errorFields(err));
|
|
34
|
+
return 1;
|
|
35
|
+
})
|
|
36
|
+
.then((code) => process.exit(code));
|
|
18
37
|
});
|
|
19
38
|
//# sourceMappingURL=sleep-child.js.map
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { type Actor, type Context, type SleepOpts, type SleepResult } from '../api/index.js';
|
|
2
|
-
/** What the child needs to rebuild the request's context
|
|
3
|
-
export
|
|
2
|
+
/** What the child needs to rebuild the request's context (the store handle itself cannot cross a process boundary), or the store an auto-sleep consolidates. */
|
|
3
|
+
export type SleepJob = {
|
|
4
|
+
readonly kind: 'sleep';
|
|
4
5
|
readonly hippoRoot: string;
|
|
5
6
|
readonly tenantId: string;
|
|
6
7
|
readonly actor: Actor;
|
|
7
8
|
readonly opts: SleepOpts;
|
|
8
|
-
}
|
|
9
|
-
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: 'consolidate';
|
|
11
|
+
readonly hippoRoot: string;
|
|
12
|
+
};
|
|
13
|
+
export type SleepReply<R = SleepResult> = {
|
|
10
14
|
readonly ok: true;
|
|
11
|
-
readonly result:
|
|
15
|
+
readonly result: R;
|
|
12
16
|
} | {
|
|
13
17
|
readonly ok: false;
|
|
14
18
|
readonly busy: boolean;
|
|
@@ -17,4 +21,6 @@ export type SleepReply = {
|
|
|
17
21
|
};
|
|
18
22
|
/** `sleep` for the HTTP route: same result and errors, run outside the serving process and stopped at the deadline (10 minutes, or HIPPO_SLEEP_TIMEOUT_MS). */
|
|
19
23
|
export declare function sleepInChild(ctx: Context, opts: SleepOpts): Promise<SleepResult>;
|
|
24
|
+
/** The MCP auto-sleep's consolidation, in the same queue and child as POST /v1/sleep; auto-sleep only starts on a hippo.db store. */
|
|
25
|
+
export declare function consolidateInChild(hippoRoot: string): Promise<void>;
|
|
20
26
|
//# sourceMappingURL=sleep-offload.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// POST /v1/sleep
|
|
1
|
+
// POST /v1/sleep and the MCP auto-sleep run their consolidation in a child process, so the server keeps answering and a stuck run can be stopped.
|
|
2
2
|
import { spawn } from 'node:child_process';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { sleep } from '../api/index.js';
|
|
5
|
-
import { StoreBusyError } from '../
|
|
5
|
+
import { StoreBusyError } from '../store/port.js';
|
|
6
6
|
import { envSleepTimeoutMs } from '../util/env.js';
|
|
7
7
|
import { HttpError } from '../util/http-util.js';
|
|
8
8
|
const DEFAULT_SLEEP_DEADLINE_MS = 600_000;
|
|
@@ -32,7 +32,7 @@ function runInChild(job) {
|
|
|
32
32
|
// SIGKILL because the child is inside synchronous SQLite work and cannot run a handler; the OS drops its write lock.
|
|
33
33
|
const timer = setTimeout(() => { timedOut = true; child.kill('SIGKILL'); }, deadlineMs);
|
|
34
34
|
child.once('message', (message) => {
|
|
35
|
-
// SAFETY: sleep-child.ts is the only writer on this channel and sends exactly one SleepReply.
|
|
35
|
+
// SAFETY: sleep-child.ts is the only writer on this channel and sends exactly one SleepReply for the job it was given.
|
|
36
36
|
reply = message;
|
|
37
37
|
});
|
|
38
38
|
child.once('error', (err) => { clearTimeout(timer); reject(err); });
|
|
@@ -54,20 +54,26 @@ let turn = Promise.resolve();
|
|
|
54
54
|
const MAX_SLEEPS_IN_LINE = 2;
|
|
55
55
|
const SLEEP_RETRY_AFTER_SEC = 30;
|
|
56
56
|
let inLine = 0;
|
|
57
|
-
|
|
58
|
-
export function sleepInChild(ctx, opts) {
|
|
59
|
-
// The child reopens the store by path, which only SQLite has; any other store keeps sleep's own refusal.
|
|
60
|
-
if (ctx.store && ctx.store.kind !== 'sqlite')
|
|
61
|
-
return sleep(ctx, opts);
|
|
57
|
+
function inTurn(job) {
|
|
62
58
|
if (inLine >= MAX_SLEEPS_IN_LINE) {
|
|
63
59
|
return Promise.reject(new HttpError(503, 'a sleep is already running and another is waiting; retry when one has finished', SLEEP_RETRY_AFTER_SEC));
|
|
64
60
|
}
|
|
65
61
|
inLine += 1;
|
|
66
|
-
|
|
67
|
-
// One sleep at a time, as on the server's single thread: a second request waits its turn and does not fight the first for the write lock.
|
|
62
|
+
// One sleep at a time, as on the server's single thread: a second one waits its turn and does not fight the first for the write lock.
|
|
68
63
|
const run = turn.then(() => runInChild(job));
|
|
69
|
-
// A failed sleep reaches its own
|
|
64
|
+
// A failed sleep reaches its own caller through `run`; the queue only needs to know the turn is over.
|
|
70
65
|
turn = run.then(() => undefined, () => undefined).finally(() => { inLine -= 1; });
|
|
71
66
|
return run;
|
|
72
67
|
}
|
|
68
|
+
/** `sleep` for the HTTP route: same result and errors, run outside the serving process and stopped at the deadline (10 minutes, or HIPPO_SLEEP_TIMEOUT_MS). */
|
|
69
|
+
export function sleepInChild(ctx, opts) {
|
|
70
|
+
// The child reopens the store by path, which only SQLite has; any other store keeps sleep's own refusal.
|
|
71
|
+
if (ctx.store && ctx.store.kind !== 'sqlite')
|
|
72
|
+
return sleep(ctx, opts);
|
|
73
|
+
return inTurn({ kind: 'sleep', hippoRoot: ctx.hippoRoot, tenantId: ctx.tenantId, actor: ctx.actor, opts });
|
|
74
|
+
}
|
|
75
|
+
/** The MCP auto-sleep's consolidation, in the same queue and child as POST /v1/sleep; auto-sleep only starts on a hippo.db store. */
|
|
76
|
+
export async function consolidateInChild(hippoRoot) {
|
|
77
|
+
await inTurn({ kind: 'consolidate', hippoRoot });
|
|
78
|
+
}
|
|
73
79
|
//# sourceMappingURL=sleep-offload.js.map
|
package/dist/server/types.d.ts
CHANGED
|
@@ -88,6 +88,10 @@ export interface RouteRequest {
|
|
|
88
88
|
opts: ResolvedServeOpts;
|
|
89
89
|
query: URLSearchParams;
|
|
90
90
|
}
|
|
91
|
+
/** A request past the dispatch gate, carrying the caller the gate authenticated. */
|
|
92
|
+
export interface AuthedRouteRequest extends RouteRequest {
|
|
93
|
+
ctx: Context;
|
|
94
|
+
}
|
|
91
95
|
/** A route's store status: a `storeReady` group, a `sqliteOnly` reason, or neither while it waits for a group; never both. */
|
|
92
96
|
type StoreStatus = {
|
|
93
97
|
storeReady?: StoreGroup;
|
|
@@ -96,20 +100,28 @@ type StoreStatus = {
|
|
|
96
100
|
sqliteOnly: string;
|
|
97
101
|
storeReady?: never;
|
|
98
102
|
};
|
|
99
|
-
/**
|
|
100
|
-
*
|
|
101
|
-
export type
|
|
102
|
-
|
|
103
|
-
loop?: 'off';
|
|
104
|
-
} & StoreStatus & ({
|
|
103
|
+
/** What the dispatch gate proves before a handler runs: any caller, an admin, a host admin on loopback, or nothing, for a route
|
|
104
|
+
* whose handler checks the sender's signature itself. */
|
|
105
|
+
export type RouteAuth = 'caller' | 'admin' | 'host-admin-local' | 'webhook-signature';
|
|
106
|
+
export type RouteEndpoint<R> = {
|
|
105
107
|
path: string;
|
|
106
|
-
handler: (r:
|
|
108
|
+
handler: (r: R) => Promise<void>;
|
|
107
109
|
} | {
|
|
108
110
|
pattern: string;
|
|
109
|
-
handler: (r:
|
|
111
|
+
handler: (r: R, params: Record<string, string>) => Promise<void>;
|
|
110
112
|
} | {
|
|
111
113
|
regex: RegExp;
|
|
112
|
-
handler: (r:
|
|
113
|
-
}
|
|
114
|
+
handler: (r: R, match: RegExpMatchArray) => Promise<void>;
|
|
115
|
+
};
|
|
116
|
+
/** One /v1 route: an exact path, a matchPath pattern, or a regex, each paired with one method's handler. Under another store it runs only with its
|
|
117
|
+
* store's `storeReady` group; `loop: 'off'` runs its SQLite work on a worker thread, so the handler opens no hippo.db on the server thread. */
|
|
118
|
+
export type Route = {
|
|
119
|
+
method: string;
|
|
120
|
+
loop?: 'off';
|
|
121
|
+
} & StoreStatus & (({
|
|
122
|
+
auth: Exclude<RouteAuth, 'webhook-signature'>;
|
|
123
|
+
} & RouteEndpoint<AuthedRouteRequest>) | ({
|
|
124
|
+
auth: 'webhook-signature';
|
|
125
|
+
} & RouteEndpoint<RouteRequest>));
|
|
114
126
|
export {};
|
|
115
127
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -3,10 +3,9 @@ import type { Context, RememberOpts } from '../api/index.js';
|
|
|
3
3
|
import { type JsonValue } from '../util/json.js';
|
|
4
4
|
export declare function isSetMember<T extends string>(set: ReadonlySet<T>, value: string): value is T;
|
|
5
5
|
export declare const MAX_SHORT_FIELD_LEN = 4096;
|
|
6
|
-
export declare const MAX_LIST_LIMIT = 1000;
|
|
7
6
|
export declare function parseListLimit(limitRaw: string | null, defaultLimit?: number, maxLimit?: number): number;
|
|
8
7
|
/** `_authed` is proof the caller passed auth, so a full-size body is read only for
|
|
9
|
-
* an authenticated caller; the key mint reads
|
|
8
|
+
* an authenticated caller; the key mint reads under its own small cap. */
|
|
10
9
|
export declare function parseJsonBody(req: IncomingMessage, _authed: Context): Promise<Record<string, JsonValue>>;
|
|
11
10
|
export declare function parseJsonObjectText(raw: string): Record<string, JsonValue>;
|
|
12
11
|
export declare function getString(obj: Record<string, JsonValue>, key: string): string | undefined;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { HttpError,
|
|
1
|
+
import { HttpError, readBody } from '../util/http-util.js';
|
|
2
|
+
import { DEFAULT_LIST_LIMIT, MAX_ID_LEN, MAX_LIST_LIMIT, resolveListLimit } from '../util/limits.js';
|
|
2
3
|
import { isJsonString, isJsonObject } from '../util/json.js';
|
|
3
4
|
// Runtime membership check for a `ReadonlySet<T>` of string-literal members: Set<T>.has gives no narrowing, so this is the one place the `as T` assertion lives
|
|
4
5
|
// and callers narrow via the `value is T` return.
|
|
@@ -8,20 +9,14 @@ export function isSetMember(set, value) {
|
|
|
8
9
|
}
|
|
9
10
|
// Cap for short free-text HTTP fields (names, text, context, change summaries) on the object routes.
|
|
10
11
|
export const MAX_SHORT_FIELD_LEN = 4096;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
export function parseListLimit(limitRaw, defaultLimit = 100, maxLimit = MAX_LIST_LIMIT) {
|
|
15
|
-
if (limitRaw === null)
|
|
16
|
-
return defaultLimit;
|
|
17
|
-
const limit = Number(limitRaw);
|
|
18
|
-
if (!Number.isInteger(limit) || limit <= 0 || limit > maxLimit) {
|
|
12
|
+
export function parseListLimit(limitRaw, defaultLimit = DEFAULT_LIST_LIMIT, maxLimit = MAX_LIST_LIMIT) {
|
|
13
|
+
const limit = resolveListLimit(limitRaw === null ? undefined : Number(limitRaw), defaultLimit, maxLimit);
|
|
14
|
+
if (limit === undefined)
|
|
19
15
|
throw new HttpError(400, `limit must be a positive integer <= ${maxLimit}`);
|
|
20
|
-
}
|
|
21
16
|
return limit;
|
|
22
17
|
}
|
|
23
18
|
/** `_authed` is proof the caller passed auth, so a full-size body is read only for
|
|
24
|
-
* an authenticated caller; the key mint reads
|
|
19
|
+
* an authenticated caller; the key mint reads under its own small cap. */
|
|
25
20
|
export async function parseJsonBody(req, _authed) {
|
|
26
21
|
return parseJsonObjectText(await readBody(req));
|
|
27
22
|
}
|
package/dist/server.d.ts
CHANGED
|
@@ -13,8 +13,9 @@ export type { JsonValue } from './util/json.js';
|
|
|
13
13
|
export { captureSessionTexts, type SessionCaptureRequest, type SessionCaptureResult } from './capture/session-texts.js';
|
|
14
14
|
export { hasGroup, sqliteStore, type AmbientCandidateRequest, type ContextReads, type EntryRemoval, type EntryTarget, type EntryWrite, type EntryWrites, type HippoStore, type KeyAudit, type KeyListQuery, type KeyMint, type KeyRevoke, type KeyWrites, type OutcomeWrite, type RawArchive, type RecallSearchArgs, type RecallWrites, type SelfKeyMint, type StoreGroup, type StoreGroups, type SupersedeWrite, type VectorReads, type VectorBackfillQuery, type VectorRowWrite, type VectorWrite, type VectorWriteResult, type VectorWrites, } from './store/index.js';
|
|
15
15
|
export { entryAfterOutcome } from './core/memory.js';
|
|
16
|
-
export { rejectionDigest
|
|
17
|
-
export {
|
|
16
|
+
export { rejectionDigest } from './store/rejection.js';
|
|
17
|
+
export { RejectedValueError } from './core/api-errors.js';
|
|
18
|
+
export { ownScopeTouches } from './core/recall-scope.js';
|
|
18
19
|
export { BadRequestError, ConflictError } from './core/api-errors.js';
|
|
19
20
|
export type { HippoDbContext, StoreReply } from './api/types.js';
|
|
20
21
|
export type { ApiKeyListItem, ApiKeyListRow, ApiKeyRecord, ListApiKeysOpts, NewApiKey } from './store/auth.js';
|
|
@@ -37,11 +38,11 @@ export type { AmbientTallies } from './core/ambient.js';
|
|
|
37
38
|
export type { TokenUse } from './store/token-ledger.js';
|
|
38
39
|
export type { EmbeddingIndexState } from './store/vector-index.js';
|
|
39
40
|
export type { PhysicsParticle } from './core/physics.js';
|
|
40
|
-
export { StoreBusyError } from './
|
|
41
|
+
export { StoreBusyError } from './store/port.js';
|
|
41
42
|
export { decodeVector, EMBEDDING_MODEL_META_KEY, encodeVector, rankVectorRows, type VectorMatch, type VectorRow } from './db/vector-store.js';
|
|
42
43
|
export { bufferToFloat32, float32ToBuffer } from './db/physics-state.js';
|
|
43
44
|
export { replacesIndex } from './store/vector-index.js';
|
|
44
|
-
export { passesScopeFilterForRecall, RECALL_DEFAULT_DENY_SCOPES } from './
|
|
45
|
+
export { passesScopeFilterForRecall, RECALL_DEFAULT_DENY_SCOPES } from './core/recall-scope.js';
|
|
45
46
|
export { SECRET_TAGS } from './util/secret-detect.js';
|
|
46
47
|
export { tallyAmbientEntries } from './core/ambient.js';
|
|
47
48
|
export { ftsTermParts, rarestFtsQuery } from './core/prompt-recall.js';
|
package/dist/server.js
CHANGED
|
@@ -19,17 +19,18 @@ export { captureSessionTexts } from './capture/session-texts.js';
|
|
|
19
19
|
export { hasGroup, sqliteStore, } from './store/index.js';
|
|
20
20
|
// An add-on store's entry writes apply an outcome, guard tombstones and check reach exactly as hippo.db does.
|
|
21
21
|
export { entryAfterOutcome } from './core/memory.js';
|
|
22
|
-
export { rejectionDigest
|
|
23
|
-
export {
|
|
22
|
+
export { rejectionDigest } from './store/rejection.js';
|
|
23
|
+
export { RejectedValueError } from './core/api-errors.js';
|
|
24
|
+
export { ownScopeTouches } from './core/recall-scope.js';
|
|
24
25
|
export { BadRequestError, ConflictError } from './core/api-errors.js';
|
|
25
|
-
export { StoreBusyError } from './
|
|
26
|
+
export { StoreBusyError } from './store/port.js';
|
|
26
27
|
// An add-on store encodes, decodes and ranks vectors and particles with hippo.db's own code, and drops the index by its rule,
|
|
27
28
|
// so both stores keep the same bytes and return the same ids in the same order.
|
|
28
29
|
export { decodeVector, EMBEDDING_MODEL_META_KEY, encodeVector, rankVectorRows } from './db/vector-store.js';
|
|
29
30
|
export { bufferToFloat32, float32ToBuffer } from './db/physics-state.js';
|
|
30
31
|
export { replacesIndex } from './store/vector-index.js';
|
|
31
32
|
// An add-on's ContextReads applies hippo.db's scope, secret, tally and rarest-term rules with the same code.
|
|
32
|
-
export { passesScopeFilterForRecall, RECALL_DEFAULT_DENY_SCOPES } from './
|
|
33
|
+
export { passesScopeFilterForRecall, RECALL_DEFAULT_DENY_SCOPES } from './core/recall-scope.js';
|
|
33
34
|
export { SECRET_TAGS } from './util/secret-detect.js';
|
|
34
35
|
export { tallyAmbientEntries } from './core/ambient.js';
|
|
35
36
|
export { ftsTermParts, rarestFtsQuery } from './core/prompt-recall.js';
|
|
@@ -5,12 +5,12 @@ import { generateId } from '../core/memory.js';
|
|
|
5
5
|
import { initStore } from '../store/open.js';
|
|
6
6
|
import { writeEntry } from '../store/entry-writes.js';
|
|
7
7
|
import { readEntry } from '../store/entry-reads.js';
|
|
8
|
-
import { isPersonalScope } from '../
|
|
8
|
+
import { isPersonalScope } from '../core/recall-scope.js';
|
|
9
9
|
import { fallbackOrigin, resolveGlobalRootDir } from '../core/project-identity.js';
|
|
10
10
|
import { isSharedStore } from '../core/config.js';
|
|
11
11
|
import { detectSecret } from '../util/secret-detect.js';
|
|
12
12
|
import { isQuarantineScope } from '../trust/quarantine.js';
|
|
13
|
-
import { embedMemory } from '../
|
|
13
|
+
import { embedMemory } from '../search/embed-memories.js';
|
|
14
14
|
import { appendAuditEvent } from '../store/audit.js';
|
|
15
15
|
/** Returns the path to the global Hippo store.
|
|
16
16
|
* Resolution order: $HIPPO_HOME > $XDG_DATA_HOME/hippo > ~/.hippo/ */
|
|
@@ -3,70 +3,63 @@ import { BadRequestError } from '../core/api-errors.js';
|
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import { AGENT_MEMORY_SOURCE_PREFIX } from '../core/agent-memory-tools.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { writeEntriesSkippingRejected } from '../store/entry-writes.js';
|
|
7
|
+
import { loadEntriesByIds, loadEntryTextKeys } from '../store/entry-reads.js';
|
|
8
|
+
import { chunked } from '../util/chunked.js';
|
|
9
|
+
import { withRequestStoresSync } from '../db/request-stores.js';
|
|
8
10
|
import { classifyOriginProject, resolveProjectIdentity } from '../core/project-identity.js';
|
|
9
11
|
import { isSharedStore } from '../core/config.js';
|
|
10
12
|
import { detectSecret } from '../util/secret-detect.js';
|
|
11
|
-
import {
|
|
12
|
-
import { embedAll } from '../store/embeddings/index.js';
|
|
13
|
+
import { embedAll } from '../search/embed-memories.js';
|
|
13
14
|
import { log } from '../util/log.js';
|
|
14
15
|
import { logEmbedAllFailure } from './search-both.js';
|
|
15
16
|
/** Copy all global memories into the local store, skipping entries that already exist locally by ID or text (promote and share copy under a new ID).
|
|
16
17
|
* Returns the count of newly copied entries. */
|
|
17
18
|
export function syncGlobalToLocal(localRoot, globalRoot, opts = {}) {
|
|
18
19
|
if (isSharedStore(localRoot)) {
|
|
19
|
-
throw new BadRequestError(`Refusing to sync into ${localRoot}: a shared store takes no copies of a personal global store,
|
|
20
|
+
throw new BadRequestError(`Refusing to sync into ${localRoot}: a shared store takes no copies of a personal global store, ` +
|
|
21
|
+
`whose rows would reach every member.`);
|
|
20
22
|
}
|
|
21
23
|
if (!fs.existsSync(globalRoot))
|
|
22
24
|
return 0;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
return withRequestStoresSync(() => copyMissingRows(localRoot, globalRoot, opts.includeCrossProject === true));
|
|
26
|
+
}
|
|
27
|
+
const textKey = (e) => `${e.tenantId}\n${e.content}`;
|
|
28
|
+
/** One open per store and one transaction: id, tenant and text decide which rows to read whole, and the copies commit together. */
|
|
29
|
+
function copyMissingRows(localRoot, globalRoot, includeCrossProject) {
|
|
30
|
+
// Host-wide read: the global union is copied into a tenant-scoped local store, and each copy keeps its own tenant.
|
|
31
|
+
const localKeys = loadEntryTextKeys(localRoot);
|
|
32
|
+
const localIds = new Set(localKeys.map((k) => k.id));
|
|
33
|
+
const localText = new Set(localKeys.map(textKey));
|
|
34
|
+
// Only the global store's user pass sets an imported note's row aside, so a copy would outlive the note.
|
|
35
|
+
const candidates = loadEntryTextKeys(globalRoot).filter((k) => !localIds.has(k.id) && !k.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX) && !localText.has(textKey(k)));
|
|
36
|
+
if (candidates.length === 0)
|
|
37
|
+
return 0;
|
|
38
|
+
const byId = new Map(chunked(candidates.map((k) => k.id)).flatMap((ids) => loadEntriesByIds(globalRoot, ids)).map((e) => [e.id, e]));
|
|
29
39
|
// Syncing down must not re-import what ambient context excludes: other-project rows are skipped by default and secret rows never copied.
|
|
30
|
-
// origin_project is preserved on the copy (
|
|
40
|
+
// origin_project is preserved on the copy (the write stamps it only when missing).
|
|
31
41
|
const currentProject = resolveProjectIdentity(path.dirname(path.resolve(localRoot)));
|
|
32
|
-
|
|
33
|
-
// A locally rejected value must not come back through sync down: caught per item, printed as one line.
|
|
42
|
+
// A locally rejected value must not come back through sync down: skipped per item, printed as one line.
|
|
34
43
|
let rejected = 0;
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
rejected++;
|
|
50
|
-
continue;
|
|
44
|
+
const count = writeEntriesSkippingRejected(localRoot, (put) => {
|
|
45
|
+
for (const { id } of candidates) {
|
|
46
|
+
const entry = byId.get(id);
|
|
47
|
+
// A row the global store dropped between the two reads, or a text an earlier copy in this batch already brought down.
|
|
48
|
+
if (!entry || localText.has(textKey(entry)))
|
|
49
|
+
continue;
|
|
50
|
+
if (detectSecret(entry).flagged)
|
|
51
|
+
continue;
|
|
52
|
+
if (!includeCrossProject && classifyOriginProject(entry.origin_project, currentProject) === 'cross-project')
|
|
53
|
+
continue;
|
|
54
|
+
if (put(entry))
|
|
55
|
+
localText.add(textKey(entry));
|
|
56
|
+
else
|
|
57
|
+
rejected++;
|
|
51
58
|
}
|
|
52
|
-
|
|
53
|
-
count++;
|
|
54
|
-
}
|
|
59
|
+
});
|
|
55
60
|
finishSyncDown(localRoot, count, rejected);
|
|
56
61
|
return count;
|
|
57
62
|
}
|
|
58
|
-
/** False when the local store rejects the value; any other failure still throws. */
|
|
59
|
-
function writeUnlessRejected(localRoot, entry) {
|
|
60
|
-
try {
|
|
61
|
-
writeEntry(localRoot, entry);
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
if (err instanceof RejectedValueError)
|
|
66
|
-
return false;
|
|
67
|
-
throw err;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
63
|
function finishSyncDown(localRoot, count, rejected) {
|
|
71
64
|
if (rejected > 0) {
|
|
72
65
|
log.warn(`syncGlobalToLocal: skipped ${rejected} rejected value(s) (run \`hippo unreject\` on the local store to allow).`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ProjectFold } from '../agent-memories/project-folds.js';
|
|
2
|
+
import type { ProjectTagReads, ProjectTagStore } from '../store/project-tags.js';
|
|
2
3
|
export interface ProjectSummary {
|
|
3
4
|
/** '' is user-global, null is unknown; neither can be merged. */
|
|
4
5
|
readonly origin: string | null;
|
|
@@ -18,10 +19,6 @@ export interface MergeResult {
|
|
|
18
19
|
readonly compactions: number;
|
|
19
20
|
readonly backup: string | null;
|
|
20
21
|
}
|
|
21
|
-
export interface ProjectFold {
|
|
22
|
-
readonly from: string;
|
|
23
|
-
readonly into: string;
|
|
24
|
-
}
|
|
25
22
|
/** An old name whose session folders now resolve to several projects: no fold can say whose rows are whose. */
|
|
26
23
|
export interface ProjectCollision {
|
|
27
24
|
readonly name: string;
|
|
@@ -45,28 +42,24 @@ export interface RepairResult {
|
|
|
45
42
|
readonly backup: string | null;
|
|
46
43
|
}
|
|
47
44
|
/** Live rows per project name, newest write first, with how many of its imported notes are copies held elsewhere. */
|
|
48
|
-
export declare function listProjects(
|
|
45
|
+
export declare function listProjects(store: ProjectTagReads): ProjectSummary[];
|
|
49
46
|
/** Refuses user-global and unknown: they are not projects, and folding them would leak or hide every row. */
|
|
50
47
|
export declare function validateMergeNames(from: string, into: string): string | null;
|
|
51
48
|
/** Folds project `from` into `into` for one tenant in one transaction; a dry run rolls back and writes nothing, mirrors included. */
|
|
52
|
-
export declare function mergeProjects(
|
|
53
|
-
tenantId: string;
|
|
49
|
+
export declare function mergeProjects(store: ProjectTagStore, opts: {
|
|
54
50
|
from: string;
|
|
55
51
|
into: string;
|
|
56
52
|
dryRun: boolean;
|
|
57
53
|
}): MergeResult;
|
|
58
|
-
/** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
|
|
59
|
-
export declare function namesFoldedInto(db: DatabaseSyncLike, tenantId: string, names: readonly string[]): string[];
|
|
60
54
|
/** Reads only, so doctor and a dry run take no write lock; merged rows are planned before any fold, so a few may re-tag differently once folds apply. */
|
|
61
|
-
export declare function planProjectRepair(
|
|
55
|
+
export declare function planProjectRepair(store: ProjectTagReads, hippoRoot: string, globalFolds?: boolean): Omit<RepairResult, 'backup'>;
|
|
62
56
|
/** Sets aside stray imports, folds the names the resolver now maps elsewhere, then
|
|
63
57
|
* re-tags sleep's user-global merges by their parents; a dry run only plans. */
|
|
64
|
-
export declare function repairProjects(
|
|
65
|
-
tenantId: string;
|
|
58
|
+
export declare function repairProjects(store: ProjectTagStore, opts: {
|
|
66
59
|
dryRun: boolean;
|
|
67
60
|
globalFolds?: boolean;
|
|
68
61
|
}): RepairResult;
|
|
69
62
|
/** Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
|
|
70
63
|
* with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted. */
|
|
71
|
-
export declare function repairOnceOnSleep(
|
|
64
|
+
export declare function repairOnceOnSleep(store: ProjectTagStore): RepairResult | null;
|
|
72
65
|
//# sourceMappingURL=project-merge.d.ts.map
|