hippo-memory 1.71.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -5
- package/dist/agent-memories/apply.d.ts +0 -11
- package/dist/agent-memories/apply.js +11 -26
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/copilot.d.ts +1 -3
- package/dist/agent-memories/copilot.js +1 -17
- package/dist/agent-memories/project-folds.d.ts +10 -0
- package/dist/agent-memories/project-folds.js +34 -0
- package/dist/agent-memories/sync.js +8 -6
- package/dist/api/assemble.js +3 -2
- package/dist/api/audit.d.ts +30 -2
- package/dist/api/audit.js +48 -7
- package/dist/api/auth.d.ts +11 -9
- package/dist/api/auth.js +39 -40
- package/dist/api/auto-sleep.d.ts +5 -2
- package/dist/api/auto-sleep.js +7 -3
- package/dist/api/availability.js +2 -3
- package/dist/api/cards.d.ts +42 -0
- package/dist/api/cards.js +52 -0
- package/dist/api/conflicts.d.ts +28 -0
- package/dist/api/conflicts.js +61 -0
- package/dist/api/context-auto.js +4 -2
- package/dist/api/context-render.js +4 -3
- package/dist/api/context-select.js +15 -29
- package/dist/api/context.js +29 -18
- package/dist/api/continuity.d.ts +47 -0
- package/dist/api/continuity.js +66 -0
- package/dist/api/dormant.js +4 -2
- package/dist/api/drill-down.js +3 -2
- package/dist/api/embeddings.d.ts +17 -0
- package/dist/api/embeddings.js +28 -0
- package/dist/api/error-reply.d.ts +8 -0
- package/dist/api/error-reply.js +21 -0
- package/dist/api/forget.d.ts +7 -3
- package/dist/api/forget.js +24 -14
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +5 -9
- package/dist/api/graph.js +2 -1
- package/dist/api/index.d.ts +4 -2
- package/dist/api/index.js +4 -2
- package/dist/api/instruction-detect.js +5 -1
- package/dist/api/learn.d.ts +5 -1
- package/dist/api/learn.js +71 -44
- package/dist/api/ledger-db.d.ts +2 -6
- package/dist/api/ledger-db.js +4 -36
- package/dist/api/memories.d.ts +21 -1
- package/dist/api/memories.js +51 -1
- package/dist/api/objects.d.ts +1 -1
- package/dist/api/objects.js +2 -1
- package/dist/api/outcome.d.ts +5 -5
- package/dist/api/outcome.js +17 -16
- package/dist/api/pilot-arm.d.ts +1 -11
- package/dist/api/pilot-arm.js +5 -45
- package/dist/api/predictions.d.ts +3 -1
- package/dist/api/predictions.js +8 -1
- package/dist/api/projects.d.ts +21 -0
- package/dist/api/projects.js +24 -0
- package/dist/api/promote.d.ts +3 -3
- package/dist/api/promote.js +26 -28
- package/dist/api/prompt-hook.d.ts +17 -2
- package/dist/api/prompt-hook.js +45 -4
- package/dist/api/quarantine.js +2 -1
- package/dist/api/recall-cli.d.ts +3 -0
- package/dist/api/recall-cli.js +13 -4
- package/dist/api/recall-core.js +10 -5
- package/dist/api/recall-pipeline.js +23 -24
- package/dist/api/recall-request.js +1 -1
- package/dist/api/recall-types.d.ts +3 -1
- package/dist/api/recall.d.ts +0 -3
- package/dist/api/recall.js +51 -73
- package/dist/api/remember-local.d.ts +5 -2
- package/dist/api/remember-local.js +15 -7
- package/dist/api/remember.d.ts +7 -3
- package/dist/api/remember.js +19 -16
- package/dist/api/session-end.d.ts +46 -0
- package/dist/api/session-end.js +131 -0
- package/dist/api/sleep-run.d.ts +1 -1
- package/dist/api/sleep-run.js +16 -11
- package/dist/api/sleep.js +4 -3
- package/dist/api/status.d.ts +24 -0
- package/dist/api/status.js +40 -0
- package/dist/api/store-init.d.ts +4 -0
- package/dist/api/store-init.js +9 -0
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +3 -7
- package/dist/api/types.js +6 -1
- package/dist/capture/caller-session.d.ts +0 -3
- package/dist/capture/caller-session.js +1 -12
- package/dist/capture/capture-error.d.ts +2 -2
- package/dist/capture/capture-error.js +23 -18
- package/dist/capture/codex-patch.js +3 -1
- package/dist/capture/command.js +36 -95
- package/dist/capture/compact.js +10 -5
- package/dist/capture/compaction-items-caller.js +11 -20
- package/dist/capture/compaction-record.d.ts +7 -93
- package/dist/capture/compaction-record.js +29 -426
- package/dist/capture/compaction-spool.d.ts +7 -7
- package/dist/capture/compaction-spool.js +60 -51
- package/dist/capture/copilot-transcript.d.ts +2 -1
- package/dist/capture/copilot-transcript.js +2 -1
- package/dist/capture/extract.d.ts +5 -2
- package/dist/capture/extract.js +4 -3
- package/dist/capture/failure-caller.d.ts +1 -1
- package/dist/capture/failure-caller.js +21 -16
- package/dist/capture/failure-reading.d.ts +2 -1
- package/dist/capture/failure-reading.js +7 -9
- package/dist/capture/pre-compact-caller.js +5 -4
- package/dist/capture/session-digest.js +4 -3
- package/dist/capture/session-end-caller.js +3 -2
- package/dist/capture/session-worker.js +22 -10
- package/dist/capture/transcript.d.ts +2 -1
- package/dist/capture/transcript.js +6 -3
- package/dist/capture/working-state.d.ts +4 -2
- package/dist/capture/working-state.js +4 -2
- package/dist/cli/audit-prune.d.ts +0 -25
- package/dist/cli/audit-prune.js +1 -27
- package/dist/cli/audit.js +20 -20
- package/dist/cli/auth.d.ts +1 -1
- package/dist/cli/auth.js +16 -17
- package/dist/cli/briefs.d.ts +1 -4
- package/dist/cli/briefs.js +37 -292
- package/dist/cli/card.js +41 -33
- package/dist/cli/client.d.ts +6 -2
- package/dist/cli/client.js +37 -21
- package/dist/cli/compact-resume-payload.js +1 -1
- package/dist/cli/context.d.ts +1 -1
- package/dist/cli/context.js +13 -13
- package/dist/cli/continuity.d.ts +1 -1
- package/dist/cli/continuity.js +36 -39
- package/dist/cli/curate.d.ts +2 -2
- package/dist/cli/curate.js +32 -36
- package/dist/cli/dag.d.ts +1 -1
- package/dist/cli/dag.js +23 -8
- package/dist/cli/decisions.d.ts +0 -2
- package/dist/cli/decisions.js +7 -285
- package/dist/cli/eval.d.ts +1 -1
- package/dist/cli/eval.js +12 -13
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +21 -25
- package/dist/cli/flag-values.js +16 -6
- package/dist/cli/flags.d.ts +0 -289
- package/dist/cli/flags.js +3 -138
- package/dist/cli/graph.d.ts +3 -0
- package/dist/cli/graph.js +83 -0
- package/dist/cli/hook-runtime.d.ts +6 -6
- package/dist/cli/hook-runtime.js +9 -36
- package/dist/cli/incidents.d.ts +3 -0
- package/dist/cli/incidents.js +112 -0
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +28 -19
- package/dist/cli/install-steps.d.ts +2 -1
- package/dist/cli/install-steps.js +11 -3
- package/dist/cli/last-sleep.js +1 -1
- package/dist/cli/maintenance.d.ts +3 -3
- package/dist/cli/maintenance.js +29 -30
- package/dist/cli/notes.d.ts +2 -0
- package/dist/cli/notes.js +41 -0
- package/dist/cli/object-verbs.d.ts +2 -2
- package/dist/cli/object-verbs.js +4 -4
- package/dist/cli/open-browser.d.ts +14 -0
- package/dist/cli/open-browser.js +26 -0
- package/dist/cli/playbooks.d.ts +3 -4
- package/dist/cli/playbooks.js +126 -290
- package/dist/cli/predictions.d.ts +3 -0
- package/dist/cli/predictions.js +174 -0
- package/dist/cli/print.js +2 -1
- package/dist/cli/projects.js +30 -22
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +6 -5
- package/dist/cli/recall.js +13 -7
- package/dist/cli/refine-llm.js +18 -17
- package/dist/cli/remember.js +17 -17
- package/dist/cli/scheduler.js +2 -1
- package/dist/cli/serve.js +11 -6
- package/dist/cli/session-hooks.d.ts +1 -5
- package/dist/cli/session-hooks.js +89 -168
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +17 -10
- package/dist/cli/shared.d.ts +2 -6
- package/dist/cli/shared.js +9 -29
- package/dist/cli/sleep-render.js +6 -3
- package/dist/cli/sleep.js +6 -37
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +32 -35
- package/dist/cli/transfer.d.ts +3 -3
- package/dist/cli/transfer.js +64 -43
- package/dist/cli/usage.d.ts +1 -80
- package/dist/cli/usage.js +2 -696
- package/dist/cli/verb-row.d.ts +34 -0
- package/dist/cli/verb-row.js +6 -0
- package/dist/cli/verbs/health.d.ts +27 -0
- package/dist/cli/verbs/health.js +234 -0
- package/dist/cli/verbs/memory.d.ts +16 -0
- package/dist/cli/verbs/memory.js +236 -0
- package/dist/cli/verbs/objects.d.ts +20 -0
- package/dist/cli/verbs/objects.js +257 -0
- package/dist/cli/verbs/sessions.d.ts +31 -0
- package/dist/cli/verbs/sessions.js +314 -0
- package/dist/cli/verbs.d.ts +81 -0
- package/dist/cli/verbs.js +7 -0
- package/dist/cli/versioned-verbs.d.ts +51 -0
- package/dist/cli/versioned-verbs.js +79 -0
- package/dist/cli.d.ts +1 -272
- package/dist/cli.js +24 -315
- package/dist/connectors/dlq.d.ts +39 -3
- package/dist/connectors/dlq.js +39 -4
- package/dist/connectors/github/backfill.js +12 -3
- package/dist/connectors/github/deletion.js +2 -1
- package/dist/connectors/github/dlq.js +31 -73
- package/dist/connectors/github/ingest.d.ts +2 -6
- package/dist/connectors/github/ingest.js +5 -29
- package/dist/connectors/github/tenant-routing.js +2 -1
- package/dist/connectors/github/webhook.d.ts +2 -1
- package/dist/connectors/github/webhook.js +35 -2
- package/dist/connectors/ingest.d.ts +10 -0
- package/dist/connectors/ingest.js +29 -0
- package/dist/connectors/slack/deletion.js +2 -1
- package/dist/connectors/slack/dlq.js +49 -71
- package/dist/connectors/slack/ingest.d.ts +2 -6
- package/dist/connectors/slack/ingest.js +4 -28
- package/dist/connectors/slack/tenant-routing.js +2 -1
- package/dist/connectors/slack/webhook.d.ts +2 -1
- package/dist/connectors/slack/webhook.js +2 -1
- package/dist/consolidate/conflicts.js +2 -2
- package/dist/consolidate/dag.js +29 -18
- package/dist/consolidate/dedupe.d.ts +7 -0
- package/dist/consolidate/dedupe.js +6 -4
- package/dist/consolidate/llm-passes.js +45 -19
- package/dist/consolidate/memory-value.js +3 -2
- package/dist/consolidate/merge.js +8 -8
- package/dist/consolidate/physics-pass.d.ts +6 -1
- package/dist/consolidate/physics-pass.js +26 -6
- package/dist/consolidate/replay.js +11 -4
- package/dist/consolidate/sleep.js +9 -6
- package/dist/consolidate/traces.js +5 -5
- package/dist/core/ablation.d.ts +10 -0
- package/dist/core/ablation.js +12 -0
- package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
- package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
- package/dist/core/ambient.d.ts +4 -0
- package/dist/core/ambient.js +39 -18
- package/dist/core/api-errors.d.ts +16 -0
- package/dist/core/api-errors.js +20 -0
- package/dist/core/card.js +3 -1
- package/dist/core/compaction-timing.d.ts +7 -0
- package/dist/core/compaction-timing.js +9 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/config.js +22 -18
- package/dist/core/cosine.d.ts +3 -0
- package/dist/core/cosine.js +19 -0
- package/dist/{store → core}/markdown.d.ts +1 -1
- package/dist/{store → core}/markdown.js +4 -4
- package/dist/core/memory-audit.d.ts +17 -0
- package/dist/core/memory-audit.js +54 -0
- package/dist/core/memory.d.ts +14 -8
- package/dist/core/memory.js +35 -23
- package/dist/{consolidate → core}/merged-row.d.ts +1 -1
- package/dist/{consolidate → core}/merged-row.js +1 -1
- package/dist/core/physics.d.ts +3 -1
- package/dist/core/physics.js +23 -18
- package/dist/core/prediction.d.ts +3 -0
- package/dist/core/prediction.js +6 -0
- package/dist/core/project-identity.d.ts +3 -0
- package/dist/core/project-identity.js +12 -2
- package/dist/{store → core}/recall-scope.d.ts +1 -10
- package/dist/{store → core}/recall-scope.js +2 -19
- package/dist/core/search-types.d.ts +1 -1
- package/dist/dashboard/dashboard-actions.d.ts +2 -2
- package/dist/dashboard/dashboard-actions.js +5 -5
- package/dist/dashboard/dashboard-queries.js +2 -7
- package/dist/dashboard/dashboard-snapshot.js +1 -3
- package/dist/dashboard/dashboard.js +16 -5
- package/dist/db/busy.d.ts +2 -7
- package/dist/db/busy.js +21 -26
- package/dist/db/connect.d.ts +2 -2
- package/dist/db/connect.js +7 -7
- package/dist/db/index.d.ts +3 -3
- package/dist/db/index.js +3 -3
- package/dist/db/migrate.js +14 -7
- package/dist/db/migrations/index.d.ts +1 -1
- package/dist/db/migrations/index.js +3 -1
- package/dist/db/migrations/v11.js +1 -0
- package/dist/db/migrations/v14.js +1 -0
- package/dist/db/migrations/v55.d.ts +3 -0
- package/dist/db/migrations/v55.js +17 -0
- package/dist/db/open.d.ts +0 -2
- package/dist/db/open.js +6 -10
- package/dist/db/physics-state.d.ts +0 -4
- package/dist/db/physics-state.js +7 -33
- package/dist/db/request-stores.d.ts +1 -0
- package/dist/db/request-stores.js +2 -1
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -2
- package/dist/db/vector-store.js +19 -5
- package/dist/db/wal-checkpointer.js +2 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +18 -15
- package/dist/embeddings/local.d.ts +62 -0
- package/dist/embeddings/local.js +146 -0
- package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
- package/dist/{store/embeddings → embeddings}/provider.js +19 -25
- package/dist/embeddings/transformers.d.ts +26 -0
- package/dist/embeddings/transformers.js +89 -0
- package/dist/entry/session-text.d.ts +1 -1
- package/dist/entry/session-text.js +1 -1
- package/dist/entry/store-kit.d.ts +37 -0
- package/dist/entry/store-kit.js +25 -0
- package/dist/entry/testing.d.ts +6 -0
- package/dist/entry/testing.js +7 -0
- package/dist/eval/eval-suite.js +17 -11
- package/dist/eval/eval.js +1 -1
- package/dist/eval/judgment.js +12 -5
- package/dist/graph/extract.js +3 -3
- package/dist/graph/recall.js +1 -1
- package/dist/graph/view.js +13 -5
- package/dist/graph/write.d.ts +1 -1
- package/dist/graph/write.js +9 -9
- package/dist/hooks/codex-session.js +3 -2
- package/dist/hooks/codex-wrapper.js +2 -1
- package/dist/hooks/json-hooks.js +10 -4
- package/dist/hooks/opencode.js +8 -5
- package/dist/hooks/shared.d.ts +0 -6
- package/dist/hooks/shared.js +4 -15
- package/dist/importers/core.js +4 -4
- package/dist/importers/sources.js +5 -4
- package/dist/importers/vault.d.ts +1 -1
- package/dist/importers/vault.js +25 -23
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/learn/autolearn.d.ts +15 -3
- package/dist/learn/autolearn.js +38 -16
- package/dist/learn/churn-git.js +13 -4
- package/dist/learn/extract.d.ts +3 -2
- package/dist/learn/extract.js +7 -5
- package/dist/learn/forward-claim-detector.js +4 -2
- package/dist/learn/invalidation.d.ts +2 -1
- package/dist/learn/invalidation.js +18 -9
- package/dist/mcp/admin-tools.d.ts +2 -2
- package/dist/mcp/admin-tools.js +27 -48
- package/dist/mcp/format.js +3 -2
- package/dist/mcp/framing.d.ts +1 -0
- package/dist/mcp/framing.js +1 -1
- package/dist/mcp/memory-tools.d.ts +1 -1
- package/dist/mcp/memory-tools.js +8 -9
- package/dist/mcp/protocol.d.ts +11 -7
- package/dist/mcp/protocol.js +25 -12
- package/dist/mcp/recall-tools.js +12 -9
- package/dist/mcp/request.js +22 -20
- package/dist/mcp/stdio.js +37 -16
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +44 -21
- package/dist/objects/customer-notes.d.ts +2 -2
- package/dist/objects/decisions.d.ts +2 -2
- package/dist/objects/descriptor.d.ts +1 -1
- package/dist/objects/incidents.d.ts +2 -2
- package/dist/objects/lifecycle.d.ts +1 -1
- package/dist/objects/lifecycle.js +2 -1
- package/dist/objects/policies.d.ts +2 -2
- package/dist/objects/policies.js +2 -1
- package/dist/objects/processes.d.ts +2 -2
- package/dist/objects/project-briefs.d.ts +2 -2
- package/dist/objects/project-briefs.js +2 -3
- package/dist/objects/skills.d.ts +2 -2
- package/dist/postinstall.js +1 -1
- package/dist/rerankers/clef.js +3 -6
- package/dist/rerankers/cross-encoder.d.ts +31 -2
- package/dist/rerankers/cross-encoder.js +71 -98
- package/dist/rerankers/index.js +5 -4
- package/dist/rerankers/jev.js +2 -4
- package/dist/rerankers/outage-warning.d.ts +3 -1
- package/dist/rerankers/outage-warning.js +5 -3
- package/dist/search/bm25-search.js +1 -1
- package/dist/search/boosts.js +1 -1
- package/dist/search/embed-memories.d.ts +12 -0
- package/dist/search/embed-memories.js +389 -0
- package/dist/search/engine.d.ts +8 -0
- package/dist/search/engine.js +10 -0
- package/dist/search/goal-boost.d.ts +1 -1
- package/dist/search/goal-boost.js +6 -3
- package/dist/search/hybrid.d.ts +9 -2
- package/dist/search/hybrid.js +9 -4
- package/dist/search/physics-search.d.ts +6 -3
- package/dist/search/physics-search.js +22 -15
- package/dist/search/rerank.js +1 -1
- package/dist/search/vector.d.ts +8 -6
- package/dist/search/vector.js +14 -17
- package/dist/server/auth.d.ts +3 -1
- package/dist/server/auth.js +24 -15
- package/dist/server/boot.d.ts +2 -1
- package/dist/server/boot.js +34 -84
- package/dist/server/client-ip.d.ts +9 -6
- package/dist/server/client-ip.js +36 -17
- package/dist/server/deadline.d.ts +0 -2
- package/dist/server/deadline.js +1 -7
- package/dist/server/defaults.d.ts +1 -0
- package/dist/server/defaults.js +1 -0
- package/dist/server/mcp-http.js +16 -11
- package/dist/server/request.js +7 -2
- package/dist/server/route-checks.d.ts +7 -0
- package/dist/server/route-checks.js +42 -0
- package/dist/server/route-table.d.ts +9 -8
- package/dist/server/route-table.js +127 -133
- package/dist/server/routes/admin.d.ts +8 -8
- package/dist/server/routes/admin.js +13 -21
- package/dist/server/routes/customer-notes.d.ts +6 -6
- package/dist/server/routes/customer-notes.js +1 -2
- package/dist/server/routes/decisions.d.ts +6 -6
- package/dist/server/routes/decisions.js +2 -4
- package/dist/server/routes/incidents.d.ts +6 -6
- package/dist/server/routes/incidents.js +2 -5
- package/dist/server/routes/memories.d.ts +9 -9
- package/dist/server/routes/memories.js +19 -40
- package/dist/server/routes/object-routes.d.ts +6 -6
- package/dist/server/routes/object-routes.js +4 -7
- package/dist/server/routes/policies.d.ts +7 -7
- package/dist/server/routes/policies.js +2 -4
- package/dist/server/routes/predictions.d.ts +6 -6
- package/dist/server/routes/predictions.js +9 -13
- package/dist/server/routes/processes.d.ts +6 -6
- package/dist/server/routes/processes.js +1 -2
- package/dist/server/routes/project-briefs.d.ts +7 -7
- package/dist/server/routes/project-briefs.js +2 -4
- package/dist/server/routes/recall.d.ts +5 -5
- package/dist/server/routes/recall.js +6 -10
- package/dist/server/routes/skills.d.ts +7 -7
- package/dist/server/routes/skills.js +2 -4
- package/dist/server/server-detect.d.ts +7 -1
- package/dist/server/server-detect.js +36 -11
- package/dist/server/sleep-child.js +26 -7
- package/dist/server/sleep-offload.d.ts +11 -5
- package/dist/server/sleep-offload.js +17 -11
- package/dist/server/tls.d.ts +7 -2
- package/dist/server/tls.js +17 -5
- package/dist/server/types.d.ts +29 -12
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +4 -40
- package/dist/server.js +3 -29
- package/dist/sharing/global-store.d.ts +4 -5
- package/dist/sharing/global-store.js +8 -13
- package/dist/sharing/global-sync.js +38 -45
- package/dist/sharing/project-merge.d.ts +7 -14
- package/dist/sharing/project-merge.js +57 -121
- package/dist/sharing/search-both.js +10 -3
- package/dist/sharing/share.d.ts +2 -0
- package/dist/sharing/share.js +39 -38
- package/dist/store/ambient.js +7 -7
- package/dist/store/audit-event.d.ts +1 -1
- package/dist/store/audit.d.ts +0 -16
- package/dist/store/audit.js +4 -55
- package/dist/store/auth.d.ts +4 -2
- package/dist/store/auth.js +7 -3
- package/dist/store/candidates.d.ts +3 -2
- package/dist/store/candidates.js +59 -30
- package/dist/store/capture-write.d.ts +17 -0
- package/dist/store/capture-write.js +35 -0
- package/dist/store/cards.js +6 -5
- package/dist/store/compaction-caller.d.ts +18 -0
- package/dist/store/compaction-caller.js +29 -0
- package/dist/store/compactions-record.d.ts +115 -0
- package/dist/store/compactions-record.js +418 -0
- package/dist/store/compactions.js +6 -4
- package/dist/store/conflicts.d.ts +7 -1
- package/dist/store/conflicts.js +13 -9
- package/dist/store/connectors/dlq.d.ts +10 -0
- package/dist/store/connectors/dlq.js +33 -0
- package/dist/store/connectors/event-log.d.ts +13 -0
- package/dist/store/connectors/event-log.js +24 -0
- package/dist/store/connectors/github.d.ts +7 -9
- package/dist/store/connectors/github.js +35 -60
- package/dist/store/connectors/slack.d.ts +2 -11
- package/dist/store/connectors/slack.js +24 -57
- package/dist/store/dashboard-reads.js +8 -6
- package/dist/store/delete-and-batch.d.ts +6 -0
- package/dist/store/delete-and-batch.js +40 -6
- package/dist/store/delivery-recorder.d.ts +12 -5
- package/dist/store/delivery-recorder.js +13 -11
- package/dist/store/descendant-page.js +8 -4
- package/dist/store/dormant.d.ts +1 -1
- package/dist/store/dormant.js +10 -4
- package/dist/store/embeddings/index.d.ts +2 -12
- package/dist/store/embeddings/index.js +5 -374
- package/dist/store/entry-reads.d.ts +35 -4
- package/dist/store/entry-reads.js +86 -19
- package/dist/store/entry-row.js +9 -2
- package/dist/store/entry-writes.d.ts +15 -12
- package/dist/store/entry-writes.js +54 -22
- package/dist/store/failure-log-at.d.ts +8 -0
- package/dist/store/failure-log-at.js +16 -0
- package/dist/store/failure-log.d.ts +2 -2
- package/dist/store/failure-log.js +5 -3
- package/dist/{trust → store}/gated-write.d.ts +3 -1
- package/dist/{trust → store}/gated-write.js +7 -5
- package/dist/store/goals.js +22 -19
- package/dist/store/graph-reads.js +9 -6
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/graph-writes.d.ts +6 -6
- package/dist/store/graph-writes.js +48 -71
- package/dist/store/half-life.js +2 -2
- package/dist/store/handoffs.d.ts +10 -4
- package/dist/store/handoffs.js +10 -9
- package/dist/store/index-and-stats.js +2 -2
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +1 -1
- package/dist/store/key-writes.js +1 -1
- package/dist/store/ledger-turn.d.ts +9 -0
- package/dist/store/ledger-turn.js +38 -0
- package/dist/store/mirrors.js +19 -10
- package/dist/store/open.d.ts +2 -5
- package/dist/store/open.js +42 -54
- package/dist/store/pilot-arm.d.ts +12 -0
- package/dist/store/pilot-arm.js +42 -0
- package/dist/store/port.d.ts +68 -6
- package/dist/store/port.js +8 -0
- package/dist/store/predictions.d.ts +1 -2
- package/dist/store/predictions.js +3 -6
- package/dist/store/project-tags.d.ts +62 -0
- package/dist/store/project-tags.js +67 -0
- package/dist/store/quality-repair.js +1 -1
- package/dist/store/quarantine.js +2 -1
- package/dist/store/recall-trace.d.ts +2 -0
- package/dist/store/recall-trace.js +20 -3
- package/dist/store/rejected-values.js +16 -10
- package/dist/store/rejection-probe.d.ts +4 -0
- package/dist/store/rejection-probe.js +19 -0
- package/dist/store/rejection.d.ts +0 -17
- package/dist/store/rejection.js +1 -21
- package/dist/store/rows.js +2 -2
- package/dist/store/rule-sql.d.ts +11 -0
- package/dist/store/rule-sql.js +31 -6
- package/dist/store/search-rows.d.ts +5 -5
- package/dist/store/search-rows.js +18 -16
- package/dist/store/sessions.js +4 -2
- package/dist/store/set-aside.d.ts +14 -0
- package/dist/store/set-aside.js +23 -0
- package/dist/store/sqlite/busy.d.ts +3 -0
- package/dist/store/sqlite/busy.js +8 -0
- package/dist/store/sqlite/connector-events-group.js +4 -7
- package/dist/store/sqlite/connector-writes-group.js +6 -4
- package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
- package/dist/store/sqlite/entry-writes-group.js +3 -3
- package/dist/store/sqlite/error-codec.js +4 -3
- package/dist/store/sqlite/executor.js +10 -4
- package/dist/store/sqlite/graph-reads-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +11 -0
- package/dist/store/sqlite/held-connection.js +41 -0
- package/dist/store/sqlite/last-recall-group.d.ts +13 -0
- package/dist/store/sqlite/last-recall-group.js +57 -0
- package/dist/store/sqlite/local.d.ts +0 -17
- package/dist/store/sqlite/local.js +0 -31
- package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
- package/dist/store/sqlite/maintenance-groups.js +60 -0
- package/dist/store/sqlite/object-rows.d.ts +1 -1
- package/dist/store/sqlite/objects-group.d.ts +1 -1
- package/dist/store/sqlite/objects-group.js +15 -7
- package/dist/store/sqlite/store.d.ts +1 -8
- package/dist/store/sqlite/store.js +13 -22
- package/dist/store/summaries.d.ts +10 -3
- package/dist/store/summaries.js +54 -11
- package/dist/store/token-ledger-rows.js +3 -2
- package/dist/store/token-ledger.d.ts +0 -7
- package/dist/store/token-ledger.js +0 -35
- package/dist/store/vector-index.js +8 -4
- package/dist/support-bundle.js +2 -3
- package/dist/trust/reject-flow.js +2 -2
- package/dist/util/agent-homes.d.ts +15 -0
- package/dist/util/agent-homes.js +34 -0
- package/dist/util/anthropic-messages.d.ts +6 -1
- package/dist/util/anthropic-messages.js +26 -7
- package/dist/util/atomic-write.d.ts +5 -2
- package/dist/util/atomic-write.js +12 -8
- package/dist/util/chunked.d.ts +3 -0
- package/dist/util/chunked.js +10 -0
- package/dist/util/ellipsize.d.ts +3 -0
- package/dist/util/ellipsize.js +5 -0
- package/dist/util/env.d.ts +12 -2
- package/dist/util/env.js +12 -2
- package/dist/util/format.d.ts +5 -0
- package/dist/util/format.js +10 -0
- package/dist/util/hook-payload.d.ts +8 -0
- package/dist/util/hook-payload.js +37 -0
- package/dist/util/http-retry.d.ts +6 -0
- package/dist/util/http-retry.js +43 -5
- package/dist/util/http-util.d.ts +0 -8
- package/dist/util/http-util.js +10 -21
- package/dist/util/limits.d.ts +7 -0
- package/dist/util/limits.js +14 -0
- package/dist/util/log.d.ts +4 -0
- package/dist/util/log.js +9 -0
- package/dist/util/request-scope.d.ts +9 -3
- package/dist/util/request-scope.js +18 -9
- package/dist/util/secret-detect.js +6 -1
- package/dist/util/spawn-argv.d.ts +9 -0
- package/dist/util/spawn-argv.js +57 -0
- package/dist/util/sql.d.ts +3 -0
- package/dist/util/sql.js +6 -0
- package/dist/util/sqlite-blocked.d.ts +2 -0
- package/dist/util/sqlite-blocked.js +5 -0
- package/dist/util/stream-tee.d.ts +3 -0
- package/dist/util/stream-tee.js +35 -0
- package/dist/util/time.d.ts +4 -0
- package/dist/util/time.js +4 -0
- package/dist/util/vector-codec.d.ts +4 -0
- package/dist/util/vector-codec.js +15 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +1 -1
- package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
- package/extensions/openclaw-plugin/package.json +1 -1
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -2
- package/dist/api/on-store.d.ts +0 -16
- package/dist/api/on-store.js +0 -38
- package/dist/store/embeddings/local.d.ts +0 -15
- package/dist/store/embeddings/local.js +0 -175
- /package/dist/{cli → api}/correction-latency.d.ts +0 -0
- /package/dist/{cli → api}/correction-latency.js +0 -0
- /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
- /package/dist/{cli → api}/provenance-coverage.js +0 -0
- /package/dist/{store → core}/object-types.d.ts +0 -0
- /package/dist/{store → core}/object-types.js +0 -0
- /package/dist/{capture → util}/compaction-items.d.ts +0 -0
- /package/dist/{capture → util}/compaction-items.js +0 -0
- /package/dist/{store → util}/yaml.d.ts +0 -0
- /package/dist/{store → util}/yaml.js +0 -0
package/README.md
CHANGED
|
@@ -137,7 +137,7 @@ hippo init
|
|
|
137
137
|
# Scheduled machine-level daily runner (6:15am) via crontab
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
-
To leave parts out: `--no-hooks` skips the instruction files and hooks, `--no-schedule` the daily run, and `--no-learn` the git history and agent memory import. `HIPPO_SKIP_AUTO_INTEGRATIONS=1` skips the same files and hooks that `--no-hooks` does.
|
|
140
|
+
To leave parts out: `--no-hooks` skips the instruction files and hooks, `--no-schedule` the daily run, and `--no-learn` the git history and agent memory import. `HIPPO_SKIP_AUTO_INTEGRATIONS=1` skips the same files and hooks that `--no-hooks` does, and `HIPPO_SKIP_SCHEDULE=1` skips the daily run as `--no-schedule` does.
|
|
141
141
|
|
|
142
142
|
### Agent memories
|
|
143
143
|
|
|
@@ -675,11 +675,13 @@ hippo sleep
|
|
|
675
675
|
Wrap any command with `hippo watch` to auto-learn from failures:
|
|
676
676
|
|
|
677
677
|
```bash
|
|
678
|
-
hippo watch
|
|
678
|
+
hippo watch -- npm run build
|
|
679
679
|
# if it fails, Hippo captures the error automatically
|
|
680
680
|
# next time an agent asks about build issues, the memory is there
|
|
681
681
|
```
|
|
682
682
|
|
|
683
|
+
The command runs with no shell, so each argument reaches the program as written. To run a shell line with pipes or `&&`, pass it as one string after `--shell`: `hippo watch --shell "npm test && npm run build"`.
|
|
684
|
+
|
|
683
685
|
---
|
|
684
686
|
|
|
685
687
|
## CLI Reference
|
|
@@ -736,7 +738,7 @@ hippo watch "npm run build"
|
|
|
736
738
|
| `hippo failures [--days n]` | Failed tool calls the capture-error hook saw, by outcome, and how many errors first happened in another session |
|
|
737
739
|
| `hippo embed` | Embed all memories for semantic search |
|
|
738
740
|
| `hippo embed --status` | Show embedding coverage |
|
|
739
|
-
| `hippo watch
|
|
741
|
+
| `hippo watch -- <command> [args...]` | Run command with no shell, auto-learn from failures (`--shell "<line>"` runs one line through the shell) |
|
|
740
742
|
| `hippo learn --git` | Scan recent git commits for lessons |
|
|
741
743
|
| `hippo learn --git --days <n>` | Scan N days back (default: 7) |
|
|
742
744
|
| `hippo learn --git --repos <paths>` | Scan multiple repos (comma-separated) |
|
|
@@ -784,8 +786,8 @@ hippo watch "npm run build"
|
|
|
784
786
|
| `hippo dashboard` | Open web dashboard at localhost:3333 (memory health by project, and the card board); open the printed URL, which carries a per-start access token |
|
|
785
787
|
| `hippo dashboard --port <n>` | Use custom port |
|
|
786
788
|
| `hippo mcp` | Start MCP server (stdio transport) |
|
|
787
|
-
| `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as host admin; `HIPPO_REQUIRE_AUTH=1` wins over it |
|
|
788
|
-
| `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind
|
|
789
|
+
| `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as a member (`HIPPO_KEYLESS_LOCAL_ROLE=admin` makes them host admin, for sleep and the quarantine routes); `HIPPO_REQUIRE_AUTH=1` wins over it. Each caller gets 20 requests a second, burst 40 (`HIPPO_CALLER_RPS`; `0` turns it off). See [Security defaults](docs/UPGRADING-2.0.md#security-defaults) |
|
|
790
|
+
| `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind refuses to start, since API keys and memory text would travel in cleartext; behind a TLS-terminating proxy, pass `--allow-cleartext` (or set `HIPPO_ALLOW_CLEARTEXT=1`) |
|
|
789
791
|
|
|
790
792
|
On `heartbeat`, `block`, `review` and `complete`, a given `--run` is checked against the card's live run and the command is refused, unchanged, if the two do not match.
|
|
791
793
|
|
|
@@ -3,7 +3,6 @@ import { type MemoryEntry } from '../core/memory.js';
|
|
|
3
3
|
import { type Tally } from './report.js';
|
|
4
4
|
import type { AgentMemoryTool } from '../core/agent-memory-tools.js';
|
|
5
5
|
import type { Container } from './types.js';
|
|
6
|
-
export declare const SYNC_ACTOR = "agent-memories";
|
|
7
6
|
export interface StoreSession {
|
|
8
7
|
readonly db: DatabaseSyncLike;
|
|
9
8
|
readonly hippoRoot: string;
|
|
@@ -36,14 +35,4 @@ export interface ContainerOutcome {
|
|
|
36
35
|
}
|
|
37
36
|
/** Throws SQLITE_BUSY when another writer holds the store past its busy timeout; nothing is written then. */
|
|
38
37
|
export declare function syncContainer(s: StoreSession, work: ContainerWork): ContainerOutcome;
|
|
39
|
-
export type SetAsideWhy = 'note-gone' | 'note-changed' | 'handover' | 'project-merge' | 'project-repair';
|
|
40
|
-
export type SetAsideResult = {
|
|
41
|
-
readonly kind: 'untagged';
|
|
42
|
-
readonly entry: MemoryEntry;
|
|
43
|
-
} | {
|
|
44
|
-
readonly kind: 'dormant';
|
|
45
|
-
readonly id: string;
|
|
46
|
-
};
|
|
47
|
-
/** Design 6's set-aside on the caller's transaction: a pinned row only loses the tag, any other goes dormant, restorable. */
|
|
48
|
-
export declare function setAsideRow(db: DatabaseSyncLike, tag: string, row: MemoryEntry, why: SetAsideWhy): SetAsideResult;
|
|
49
38
|
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -1,41 +1,26 @@
|
|
|
1
1
|
// One container's sync in one transaction on the caller's handle: lookup, plan, then every write (plan designs 6 to 8).
|
|
2
2
|
import { appendAuditEvent } from '../store/audit.js';
|
|
3
3
|
import { withTrialScope, withWriteScope } from '../db/index.js';
|
|
4
|
-
import { deleteDormantRow, dormantSnapshotsBySourcePrefix,
|
|
5
|
-
import { gatedWrite } from '../
|
|
4
|
+
import { deleteDormantRow, dormantSnapshotsBySourcePrefix, readDormantSnapshot, replaceDormantEntry } from '../store/dormant.js';
|
|
5
|
+
import { gatedWrite } from '../store/gated-write.js';
|
|
6
|
+
import { strengthAblation } from '../core/ablation.js';
|
|
6
7
|
import { Layer, calculateStrength, createMemory } from '../core/memory.js';
|
|
7
8
|
import { findRejectedValue, rejectionDigest } from '../store/rejection.js';
|
|
8
9
|
import { redactSecretsStrict } from '../util/secret-detect.js';
|
|
9
10
|
import { stampOriginProject } from '../store/entry-row.js';
|
|
10
|
-
import {
|
|
11
|
+
import { renameEntrySourceAndOriginAt, renameEntrySourceAt, setEntryTagsInTx, supersedeEntryAt } from '../store/entry-writes.js';
|
|
12
|
+
import { SYNC_ACTOR, setAsideRow } from '../store/set-aside.js';
|
|
11
13
|
import { entryIdTakenAt, selectLiveEntriesBySourcePrefix } from '../store/entry-reads.js';
|
|
12
14
|
import { markSummaryDirtyInTx } from '../store/summary-dirty.js';
|
|
13
15
|
import { itemHash } from './keys.js';
|
|
14
16
|
import { planContainer } from './plan.js';
|
|
15
17
|
import { emptyTally } from './report.js';
|
|
16
18
|
import { MIN_ITEM_CHARS, itemSource, splitSource, storedText } from './source.js';
|
|
17
|
-
export const SYNC_ACTOR = 'agent-memories';
|
|
18
19
|
/** Throws SQLITE_BUSY when another writer holds the store past its busy timeout; nothing is written then. */
|
|
19
20
|
export function syncContainer(s, work) {
|
|
20
21
|
const run = () => new ContainerRun(s, work).run();
|
|
21
22
|
return s.dryRun ? withTrialScope(s.db, 'sync_container', run) : withWriteScope(s.db, 'sync_container', run);
|
|
22
23
|
}
|
|
23
|
-
/** Design 6's set-aside on the caller's transaction: a pinned row only loses the tag, any other goes dormant, restorable. */
|
|
24
|
-
export function setAsideRow(db, tag, row, why) {
|
|
25
|
-
const untagged = { ...row, tags: row.tags.filter((t) => t !== tag) };
|
|
26
|
-
const audit = (metadata) => appendAuditEvent(db, { tenantId: row.tenantId, actor: SYNC_ACTOR, op: 'agent_memory_set_aside', targetId: row.id, metadata });
|
|
27
|
-
if (row.pinned) {
|
|
28
|
-
setEntryTagsInTx(db, untagged);
|
|
29
|
-
audit({ why, untagged: true });
|
|
30
|
-
return { kind: 'untagged', entry: untagged };
|
|
31
|
-
}
|
|
32
|
-
const now = new Date();
|
|
33
|
-
// Sleep's dormant move skips kept rows, so the steps are written out here without its filter.
|
|
34
|
-
insertDormantRow(db, { entry: untagged, strength: calculateStrength(row, now), reason: 'source-deleted', dormantAt: now.toISOString() });
|
|
35
|
-
deleteEntryRowInTx(db, row, SYNC_ACTOR);
|
|
36
|
-
audit({ why });
|
|
37
|
-
return { kind: 'dormant', id: row.id };
|
|
38
|
-
}
|
|
39
24
|
class ContainerRun {
|
|
40
25
|
s;
|
|
41
26
|
w;
|
|
@@ -99,7 +84,7 @@ class ContainerRun {
|
|
|
99
84
|
continue;
|
|
100
85
|
const source = itemSource(this.w.prefix, key, item.text);
|
|
101
86
|
for (const row of rows) {
|
|
102
|
-
if (renameEntrySourceAt(this.s.db, row.
|
|
87
|
+
if (renameEntrySourceAt(this.s.db, row.tenant_id, row.id, row.source, source) === 0)
|
|
103
88
|
continue;
|
|
104
89
|
this.tally.adopted++;
|
|
105
90
|
this.mirror.push({ ...row, source });
|
|
@@ -112,7 +97,7 @@ class ContainerRun {
|
|
|
112
97
|
let moved = 0;
|
|
113
98
|
for (const row of selectLiveEntriesBySourcePrefix(this.s.db, this.s.tenantId, old)) {
|
|
114
99
|
const source = this.w.prefix + row.source.slice(old.length);
|
|
115
|
-
if (renameEntrySourceAndOriginAt(this.s.db, row.
|
|
100
|
+
if (renameEntrySourceAndOriginAt(this.s.db, row.tenant_id, row.id, { from: row.source, to: source, origin }) === 0)
|
|
116
101
|
continue;
|
|
117
102
|
moved++;
|
|
118
103
|
this.mirror.push({ ...row, source, origin_project: origin ?? row.origin_project });
|
|
@@ -165,11 +150,11 @@ class ContainerRun {
|
|
|
165
150
|
}
|
|
166
151
|
/** api.supersede's steps on this transaction; false when another writer superseded the row first. */
|
|
167
152
|
supersede(old, newId) {
|
|
168
|
-
if (!supersedeEntryAt(this.s.db, old.
|
|
153
|
+
if (!supersedeEntryAt(this.s.db, old.tenant_id, old.id, newId))
|
|
169
154
|
return false;
|
|
170
155
|
if (old.dag_parent_id)
|
|
171
|
-
markSummaryDirtyInTx(this.s.db, old.dag_parent_id, old.
|
|
172
|
-
appendAuditEvent(this.s.db, { tenantId: old.
|
|
156
|
+
markSummaryDirtyInTx(this.s.db, old.dag_parent_id, old.tenant_id, SYNC_ACTOR);
|
|
157
|
+
appendAuditEvent(this.s.db, { tenantId: old.tenant_id, actor: SYNC_ACTOR, op: 'supersede', targetId: old.id, metadata: { newId } });
|
|
173
158
|
this.mirror.push({ ...old, superseded_by: newId });
|
|
174
159
|
return true;
|
|
175
160
|
}
|
|
@@ -223,7 +208,7 @@ class ContainerRun {
|
|
|
223
208
|
tags: [...tags, this.tag],
|
|
224
209
|
last_retrieved: now.toISOString(),
|
|
225
210
|
};
|
|
226
|
-
if (!this.gated(stampOriginProject(this.s.hippoRoot, { ...revived, strength: calculateStrength(revived, now) })))
|
|
211
|
+
if (!this.gated(stampOriginProject(this.s.hippoRoot, { ...revived, strength: calculateStrength(revived, now, { ablation: strengthAblation() }) })))
|
|
227
212
|
return;
|
|
228
213
|
deleteDormantRow(this.s.db, this.s.tenantId, dormantId);
|
|
229
214
|
appendAuditEvent(this.s.db, {
|
|
@@ -4,7 +4,7 @@ import path from 'node:path';
|
|
|
4
4
|
import { resolveProjectIdentity } from '../core/project-identity.js';
|
|
5
5
|
import { realpathOrResolve } from '../util/real-path.js';
|
|
6
6
|
import { isStringValue } from '../core/capture-contract.js';
|
|
7
|
-
import { claudeConfigDir } from '../
|
|
7
|
+
import { claudeConfigDir } from '../util/agent-homes.js';
|
|
8
8
|
import { expandHome, frontmatterField, itemTime, readTextFile, splitFrontmatter } from './files.js';
|
|
9
9
|
import { markdownNotes, readFolderStore, uniqueFolders } from './folder-store.js';
|
|
10
10
|
import { gitLayout } from './git.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Codex CLI's memory_summary.md, the one memory file Codex puts in its prompt, read as a single text-keyed file.
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import { codexHomeDir } from '../
|
|
4
|
+
import { codexHomeDir } from '../util/agent-homes.js';
|
|
5
5
|
import { readTextFile } from './files.js';
|
|
6
6
|
import { textItemKeys } from './keys.js';
|
|
7
7
|
import { splitMarkdownItems } from './markdown.js';
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { Adapter
|
|
2
|
-
/** VS Code's user-data resolution: portable install first, then the app-data override, then the platform default. */
|
|
3
|
-
export declare function vscodeDataFolders(ctx: Pick<AdapterContext, 'env' | 'home' | 'platform'>): string[];
|
|
1
|
+
import type { Adapter } from './types.js';
|
|
4
2
|
export declare const copilotAdapter: Adapter;
|
|
5
3
|
//# sourceMappingURL=copilot.d.ts.map
|
|
@@ -5,24 +5,8 @@ import { readTextFile } from './files.js';
|
|
|
5
5
|
import { readFolderStore } from './folder-store.js';
|
|
6
6
|
import { gitLayout } from './git.js';
|
|
7
7
|
import { errorMessage } from '../util/log.js';
|
|
8
|
-
|
|
8
|
+
import { vscodeDataFolders } from '../util/agent-homes.js';
|
|
9
9
|
const MEMORY_TOOL = ['github.copilot-chat', 'memory-tool', 'memories'];
|
|
10
|
-
/** VS Code's user-data resolution: portable install first, then the app-data override, then the platform default. */
|
|
11
|
-
export function vscodeDataFolders(ctx) {
|
|
12
|
-
const { env, home, platform } = ctx;
|
|
13
|
-
if (env.VSCODE_PORTABLE)
|
|
14
|
-
return [path.join(env.VSCODE_PORTABLE, 'user-data')];
|
|
15
|
-
let appData;
|
|
16
|
-
if (env.VSCODE_APPDATA)
|
|
17
|
-
appData = env.VSCODE_APPDATA;
|
|
18
|
-
else if (platform === 'win32')
|
|
19
|
-
appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');
|
|
20
|
-
else if (platform === 'darwin')
|
|
21
|
-
appData = path.join(home, 'Library', 'Application Support');
|
|
22
|
-
else
|
|
23
|
-
appData = env.XDG_CONFIG_HOME || path.join(home, '.config');
|
|
24
|
-
return PRODUCTS.map((product) => path.join(appData, product));
|
|
25
|
-
}
|
|
26
10
|
/** A `file:` URI as a local path; null for any other scheme or a URI with a host part. */
|
|
27
11
|
function fileUriToPath(uri, platform) {
|
|
28
12
|
if (!uri.startsWith('file://'))
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ProjectTagReads } from '../store/project-tags.js';
|
|
2
|
+
export interface ProjectFold {
|
|
3
|
+
readonly from: string;
|
|
4
|
+
readonly into: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function foldEdges(store: Pick<ProjectTagReads, 'auditEvents'>): ProjectFold[];
|
|
7
|
+
export declare function foldedInto(edges: readonly ProjectFold[], names: readonly string[]): string[];
|
|
8
|
+
/** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
|
|
9
|
+
export declare function namesFoldedInto(store: Pick<ProjectTagReads, 'auditEvents'>, names: readonly string[]): string[];
|
|
10
|
+
//# sourceMappingURL=project-folds.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Project names folded into others, read from the audit trail: the sync files imports under the surviving name, and `hippo projects` repair agrees.
|
|
2
|
+
import { isObjectLike, isStringValue } from '../core/capture-contract.js';
|
|
3
|
+
function foldOf(value) {
|
|
4
|
+
if (!isObjectLike(value) || Array.isArray(value))
|
|
5
|
+
return [];
|
|
6
|
+
const { from, into } = value;
|
|
7
|
+
return isStringValue(from) && isStringValue(into) ? [{ from, into }] : [];
|
|
8
|
+
}
|
|
9
|
+
export function foldEdges(store) {
|
|
10
|
+
return [
|
|
11
|
+
...store.auditEvents('project_merge').flatMap((e) => foldOf(e.metadata)),
|
|
12
|
+
...store.auditEvents('project_repair')
|
|
13
|
+
.flatMap((e) => (Array.isArray(e.metadata.folds) ? e.metadata.folds.flatMap(foldOf) : [])),
|
|
14
|
+
];
|
|
15
|
+
}
|
|
16
|
+
export function foldedInto(edges, names) {
|
|
17
|
+
const seen = new Set(names);
|
|
18
|
+
let grew = true;
|
|
19
|
+
while (grew) {
|
|
20
|
+
grew = false;
|
|
21
|
+
for (const { from, into } of edges) {
|
|
22
|
+
if (!seen.has(into) || seen.has(from))
|
|
23
|
+
continue;
|
|
24
|
+
seen.add(from);
|
|
25
|
+
grew = true;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [...seen].filter((n) => !names.includes(n));
|
|
29
|
+
}
|
|
30
|
+
/** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
|
|
31
|
+
export function namesFoldedInto(store, names) {
|
|
32
|
+
return foldedInto(foldEdges(store), names);
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=project-folds.js.map
|
|
@@ -6,16 +6,18 @@ import path from 'node:path';
|
|
|
6
6
|
import { errorMessage } from '../util/log.js';
|
|
7
7
|
import { loadConfig } from '../core/config.js';
|
|
8
8
|
import { closeHippoDb, isSqliteBusy, openHippoDb, outsideRequestStores, withWriteScope } from '../db/index.js';
|
|
9
|
-
import { namesFoldedInto } from '
|
|
10
|
-
import {
|
|
9
|
+
import { namesFoldedInto } from './project-folds.js';
|
|
10
|
+
import { projectTagReads } from '../store/project-tags.js';
|
|
11
|
+
import { isGlobalStoreRoot, isInitialized, projectNames, resolveGlobalRootDir, resolveProjectIdentity, } from '../core/project-identity.js';
|
|
11
12
|
import { duplicateKey, heldTextKeys } from '../util/same-text.js';
|
|
12
13
|
import { removeEntryMirrors } from '../store/mirrors.js';
|
|
13
|
-
import { initStore
|
|
14
|
+
import { initStore } from '../store/open.js';
|
|
14
15
|
import { writeEntryMirrors } from '../store/entry-writes.js';
|
|
15
16
|
import { selectLiveEntriesBySourcePrefix, selectRowsOutsideSourcePrefixAt } from '../store/entry-reads.js';
|
|
16
17
|
import { updateStats } from '../store/index-and-stats.js';
|
|
17
18
|
import { resolveTenantId } from '../store/tenant.js';
|
|
18
|
-
import { setAsideRow
|
|
19
|
+
import { setAsideRow } from '../store/set-aside.js';
|
|
20
|
+
import { syncContainer } from './apply.js';
|
|
19
21
|
import { claudeCodeAdapter, claudeTranscriptListing, transcriptNotesProject } from './claude-code.js';
|
|
20
22
|
import { codexAdapter } from './codex.js';
|
|
21
23
|
import { copilotAdapter } from './copilot.js';
|
|
@@ -230,7 +232,7 @@ function syncStore(pass, listings, store, opts, report) {
|
|
|
230
232
|
/** The legacy names plus every name a merge or repair folded into the project; the audit read runs once per pass. */
|
|
231
233
|
function earlierNames(db, tenantId, id, legacyOrigins) {
|
|
232
234
|
const names = [id, ...legacyOrigins];
|
|
233
|
-
return [...legacyOrigins, ...namesFoldedInto(db, tenantId, names)].filter((n) => n !== '' && n !== id);
|
|
235
|
+
return [...legacyOrigins, ...namesFoldedInto(projectTagReads(db, tenantId), names)].filter((n) => n !== '' && n !== id);
|
|
234
236
|
}
|
|
235
237
|
function containerWork(tool, container, options) {
|
|
236
238
|
const { platform, legacy, origin, earlier } = options;
|
|
@@ -316,7 +318,7 @@ function handOver(synced, projectRoot, opts, report) {
|
|
|
316
318
|
// A folder with no git and no marker wrote as '' before its store existed, and as its own name after.
|
|
317
319
|
// Names folded into this project's in the global store were its rows too.
|
|
318
320
|
const names = projectNames(resolveProjectIdentity(projectRoot));
|
|
319
|
-
const origins = [...new Set([...names, ...namesFoldedInto(db, tenantId, names), ''])];
|
|
321
|
+
const origins = [...new Set([...names, ...namesFoldedInto(projectTagReads(db, tenantId), names), ''])];
|
|
320
322
|
for (const work of synced)
|
|
321
323
|
handOverContainer(db, globalRoot, tenantId, work, { origins, platform: opts.machine.platform, report });
|
|
322
324
|
}
|
package/dist/api/assemble.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Session context assembly under a token budget.
|
|
2
|
-
import { requireGroup
|
|
2
|
+
import { requireGroup } from '../store/index.js';
|
|
3
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
3
4
|
import { estimateTokens } from '../util/token-text.js';
|
|
4
|
-
import { passesScopeFilterForRecall, assertScopeRequestAllowed, personalScopeOf } from '../
|
|
5
|
+
import { passesScopeFilterForRecall, assertScopeRequestAllowed, personalScopeOf } from '../core/recall-scope.js';
|
|
5
6
|
import { classifyOriginProject, projectNames } from '../core/project-identity.js';
|
|
6
7
|
const DEFAULT_FRESH_TAIL_COUNT = 10;
|
|
7
8
|
const DEFAULT_ROW_CAP = 5000;
|
package/dist/api/audit.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { AuditEvent,
|
|
1
|
+
import type { AuditEvent, AuditOp } from '../store/audit.js';
|
|
2
|
+
import { type AuditIssue, type AuditResult } from '../core/memory-audit.js';
|
|
3
|
+
import type { QualityRepairResult } from '../store/quality-repair.js';
|
|
2
4
|
import type { KeysetPosition } from '../util/keyset.js';
|
|
3
5
|
import type { Context } from './types.js';
|
|
4
6
|
export interface AuditListOpts {
|
|
@@ -14,5 +16,31 @@ export declare function auditList(ctx: Context, opts: AuditListOpts): Promise<Au
|
|
|
14
16
|
/** The pass that removes audit errors; it leads the reason on each forget row. */
|
|
15
17
|
export type AuditPass = 'audit --fix' | 'sleep-audit';
|
|
16
18
|
/** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
|
|
17
|
-
export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): string[]
|
|
19
|
+
export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): Promise<string[]>;
|
|
20
|
+
/** The caller's memories run through the quality audit; a memory that backs an object is never marked for removal. */
|
|
21
|
+
export declare function auditMemoryQuality(ctx: Context): Promise<AuditResult>;
|
|
22
|
+
/** Audit repair for the caller's tenant: a preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
|
|
23
|
+
export declare function repairMemoryQuality(ctx: Context, apply: boolean): Promise<QualityRepairResult>;
|
|
24
|
+
/** The repair sleep and the daily runner apply once per store after an upgrade; null when it already ran there. */
|
|
25
|
+
export declare function repairMemoryQualityOnce(ctx: Context): Promise<QualityRepairResult | null>;
|
|
26
|
+
export interface PruneAuditOpts {
|
|
27
|
+
/** Cutoff in days. Rows with `ts < (now - N days)` are deleted. */
|
|
28
|
+
olderThanDays: number;
|
|
29
|
+
/** When true, count matching rows but do NOT delete. Default false. */
|
|
30
|
+
dryRun?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export interface PruneAuditResult {
|
|
33
|
+
/** ISO timestamp of the cutoff. Rows with ts strictly less than this were deleted. */
|
|
34
|
+
cutoff: string;
|
|
35
|
+
/** Number of audit_log rows deleted (or that would be deleted, if dryRun). */
|
|
36
|
+
count: number;
|
|
37
|
+
/** Echo back whether this was a dry run. */
|
|
38
|
+
dryRun: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** Cutoff ISO timestamp for N days ago; exported so tests can pin "now" without mocking Date. */
|
|
41
|
+
export declare function computeCutoff(days: number, now?: Date): string;
|
|
42
|
+
/** Delete the caller's tenant's audit_log rows older than `olderThanDays`, then record an `audit_prune` row as `ctx.actor`; opt-in, since
|
|
43
|
+
* retention floors (HIPAA, SOX, GDPR) apply. The row is written after the DELETE, so a call never prunes its own record.
|
|
44
|
+
* Throws on non-positive days or an empty tenant. */
|
|
45
|
+
export declare function pruneAuditLog(ctx: Context, opts: PruneAuditOpts): Promise<PruneAuditResult>;
|
|
18
46
|
//# sourceMappingURL=audit.d.ts.map
|
package/dist/api/audit.js
CHANGED
|
@@ -1,17 +1,58 @@
|
|
|
1
|
-
// Audit log queries
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
// Audit log queries and retention, and the memory-quality audit with its repair passes.
|
|
2
|
+
import { auditMemories } from '../core/memory-audit.js';
|
|
3
|
+
import { DAY_MS } from '../util/time.js';
|
|
4
|
+
import { requireGroup } from '../store/index.js';
|
|
5
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
4
6
|
/** Read audit events scoped to `ctx.tenantId` on the store the request runs on. Read-only, no audit emit. */
|
|
5
7
|
export async function auditList(ctx, opts) {
|
|
6
8
|
return requireGroup(storeFor(ctx), 'auditLog').listAuditEvents({
|
|
7
9
|
tenantId: ctx.tenantId, op: opts.op, since: opts.since, limit: opts.limit, after: opts.after,
|
|
8
10
|
});
|
|
9
11
|
}
|
|
12
|
+
function maintenanceOf(ctx) {
|
|
13
|
+
return requireGroup(storeFor(ctx), 'auditMaintenance');
|
|
14
|
+
}
|
|
10
15
|
/** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
|
|
11
|
-
export function removeAuditErrors(ctx, pass, issues) {
|
|
12
|
-
|
|
16
|
+
export async function removeAuditErrors(ctx, pass, issues) {
|
|
17
|
+
const removals = issues
|
|
13
18
|
.filter((issue) => issue.severity === 'error')
|
|
14
|
-
.
|
|
15
|
-
|
|
19
|
+
.map((issue) => ({ id: issue.memoryId, reason: `${pass}: ${issue.reason}` }));
|
|
20
|
+
if (removals.length === 0)
|
|
21
|
+
return [];
|
|
22
|
+
return maintenanceOf(ctx).deleteAutomatically(removals, ctx.actor.subject);
|
|
23
|
+
}
|
|
24
|
+
/** The caller's memories run through the quality audit; a memory that backs an object is never marked for removal. */
|
|
25
|
+
export async function auditMemoryQuality(ctx) {
|
|
26
|
+
const maintenance = maintenanceOf(ctx);
|
|
27
|
+
return auditMemories(await maintenance.tenantEntries(ctx.tenantId), await maintenance.objectBackedIds());
|
|
28
|
+
}
|
|
29
|
+
/** Audit repair for the caller's tenant: a preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
|
|
30
|
+
export async function repairMemoryQuality(ctx, apply) {
|
|
31
|
+
return maintenanceOf(ctx).repairQuality(ctx.tenantId, apply);
|
|
32
|
+
}
|
|
33
|
+
/** The repair sleep and the daily runner apply once per store after an upgrade; null when it already ran there. */
|
|
34
|
+
export async function repairMemoryQualityOnce(ctx) {
|
|
35
|
+
return maintenanceOf(ctx).repairQualityOnce(ctx.tenantId);
|
|
36
|
+
}
|
|
37
|
+
/** Cutoff ISO timestamp for N days ago; exported so tests can pin "now" without mocking Date. */
|
|
38
|
+
export function computeCutoff(days, now = new Date()) {
|
|
39
|
+
const cutoff = new Date(now.getTime() - days * DAY_MS);
|
|
40
|
+
return cutoff.toISOString();
|
|
41
|
+
}
|
|
42
|
+
/** Delete the caller's tenant's audit_log rows older than `olderThanDays`, then record an `audit_prune` row as `ctx.actor`; opt-in, since
|
|
43
|
+
* retention floors (HIPAA, SOX, GDPR) apply. The row is written after the DELETE, so a call never prunes its own record.
|
|
44
|
+
* Throws on non-positive days or an empty tenant. */
|
|
45
|
+
export async function pruneAuditLog(ctx, opts) {
|
|
46
|
+
if (!Number.isFinite(opts.olderThanDays) || opts.olderThanDays <= 0) {
|
|
47
|
+
throw new Error(`pruneAuditLog: olderThanDays must be a positive number, got ${opts.olderThanDays}`);
|
|
48
|
+
}
|
|
49
|
+
if (!ctx.tenantId) {
|
|
50
|
+
throw new Error('pruneAuditLog: tenantId is required');
|
|
51
|
+
}
|
|
52
|
+
const dryRun = opts.dryRun === true;
|
|
53
|
+
const cutoff = computeCutoff(opts.olderThanDays);
|
|
54
|
+
const prune = { tenantId: ctx.tenantId, cutoff, actor: ctx.actor.subject, olderThanDays: opts.olderThanDays, dryRun };
|
|
55
|
+
const count = await maintenanceOf(ctx).pruneAuditRows(prune);
|
|
56
|
+
return { cutoff, count, dryRun };
|
|
16
57
|
}
|
|
17
58
|
//# sourceMappingURL=audit.js.map
|
package/dist/api/auth.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type ApiKeyListRow } from '../store/auth.js';
|
|
1
|
+
import { DEFAULT_KEY_TTL_DAYS, type ApiKeyListItem, type ApiKeyListRow } from '../store/auth.js';
|
|
2
2
|
import type { KeysetPosition } from '../util/keyset.js';
|
|
3
|
-
import type
|
|
3
|
+
import { type Context } from './types.js';
|
|
4
4
|
export interface AuthCreateOpts {
|
|
5
5
|
label?: string;
|
|
6
6
|
/** Defaults to `'member'`, which admin-gated routes such as `POST /v1/sleep` refuse; an admin key has to be asked for by name. */
|
|
@@ -21,7 +21,9 @@ export interface AuthCreateResult {
|
|
|
21
21
|
}
|
|
22
22
|
/** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
|
|
23
23
|
* Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
|
|
24
|
-
export declare function authCreate
|
|
24
|
+
export declare function authCreate(ctx: Context, opts: AuthCreateOpts): Promise<AuthCreateResult>;
|
|
25
|
+
export { DEFAULT_KEY_TTL_DAYS };
|
|
26
|
+
export declare const MAX_TTL_DAYS = 3650;
|
|
25
27
|
export interface AuthCreateSelfOpts {
|
|
26
28
|
label?: string;
|
|
27
29
|
/** Days until the new key expires. */
|
|
@@ -35,25 +37,26 @@ export interface AuthCreateSelfResult extends AuthCreateResult {
|
|
|
35
37
|
}
|
|
36
38
|
/** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
|
|
37
39
|
* binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
|
|
38
|
-
export declare function authCreateSelf
|
|
40
|
+
export declare function authCreateSelf(ctx: Context, opts: AuthCreateSelfOpts): Promise<AuthCreateSelfResult>;
|
|
39
41
|
type KeyListOpts = {
|
|
40
42
|
active: boolean;
|
|
41
43
|
limit?: number;
|
|
42
44
|
after?: KeysetPosition;
|
|
43
45
|
};
|
|
44
46
|
/** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
|
|
45
|
-
export declare function authListRows
|
|
47
|
+
export declare function authListRows(ctx: Context, opts: KeyListOpts): Promise<ApiKeyListRow[]>;
|
|
48
|
+
/** Every tenant's keys in the store, live ones only unless `active` is false; the host's own view, so the host admin only. */
|
|
49
|
+
export declare function authListAllTenants(ctx: Context, active: boolean): ApiKeyListItem[];
|
|
46
50
|
export interface AuthRevokeResult {
|
|
47
51
|
ok: true;
|
|
48
52
|
revokedAt: string;
|
|
49
53
|
}
|
|
50
|
-
export type AuthRevokeReply<C extends Context> = StoreReply<C, AuthRevokeResult>;
|
|
51
54
|
/** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
|
|
52
55
|
* The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
|
|
53
|
-
export declare function authRevoke
|
|
56
|
+
export declare function authRevoke(ctx: Context, keyId: string): Promise<AuthRevokeResult>;
|
|
54
57
|
/** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
|
|
55
58
|
* so the local CLI can run revoke and grant in the key's own tenant. */
|
|
56
|
-
export declare function authKeyTenant(ctx: Context, keyId: string): string | undefined
|
|
59
|
+
export declare function authKeyTenant(ctx: Context, keyId: string): Promise<string | undefined>;
|
|
57
60
|
/** Shared result shape for authGrant/authUngrant, named per the file's oxlint anti-slop rule. */
|
|
58
61
|
export interface AuthGrantResult {
|
|
59
62
|
ok: true;
|
|
@@ -62,5 +65,4 @@ export interface AuthGrantResult {
|
|
|
62
65
|
export declare function authGrant(ctx: Context, keyId: string, scope: string): AuthGrantResult;
|
|
63
66
|
/** Revoke `keyId`'s grant on `scope`. Same authorization and lookup rules as authGrant. */
|
|
64
67
|
export declare function authUngrant(ctx: Context, keyId: string, scope: string): AuthGrantResult;
|
|
65
|
-
export {};
|
|
66
68
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/api/auth.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// API key management: create, list, revoke, and grant or ungrant restricted scopes.
|
|
2
2
|
import { BadRequestError, ForbiddenError, NotFoundError } from '../core/api-errors.js';
|
|
3
|
-
import { mintApiKey, } from '../store/auth.js';
|
|
3
|
+
import { DEFAULT_KEY_TTL_DAYS, listApiKeys, mintApiKey, } from '../store/auth.js';
|
|
4
|
+
import { requireGroup } from '../store/index.js';
|
|
5
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
4
6
|
import { changeScopeGrant } from '../store/sqlite/local.js';
|
|
5
|
-
import { sqliteSyncStore } from '../store/sqlite/store.js';
|
|
6
7
|
import { DAY_MS } from '../util/time.js';
|
|
7
|
-
import {
|
|
8
|
+
import { requireHostAdmin } from './types.js';
|
|
8
9
|
const API_KEY_SUBJECT = 'api_key:';
|
|
9
10
|
/** The key id an API-key actor's subject names, or null for any other actor. */
|
|
10
11
|
function keyIdOfSubject(subject) {
|
|
@@ -12,23 +13,21 @@ function keyIdOfSubject(subject) {
|
|
|
12
13
|
}
|
|
13
14
|
/** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
|
|
14
15
|
* Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
|
|
15
|
-
export function authCreate(ctx, opts) {
|
|
16
|
-
// The key and its auth_create row commit together on
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
});
|
|
16
|
+
export async function authCreate(ctx, opts) {
|
|
17
|
+
// The key and its auth_create row commit together on every store, so a failed audit write leaves no key.
|
|
18
|
+
const keyWrites = requireGroup(storeFor(ctx), 'keyWrites');
|
|
19
|
+
const { plaintext, mint } = adminKeyMint(ctx, opts);
|
|
20
|
+
await keyWrites.createApiKey(mint);
|
|
21
|
+
return createResult(mint, plaintext);
|
|
22
22
|
}
|
|
23
23
|
/** A key row in the caller's tenant, made here so only its hash ever reaches a store. */
|
|
24
24
|
function newKey(ctx, fields) {
|
|
25
25
|
const { keyId, plaintext, keyHash } = mintApiKey();
|
|
26
26
|
return { plaintext, key: { ...fields, keyId, keyHash, tenantId: ctx.tenantId, createdAt: new Date().toISOString() } };
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
const DEFAULT_KEY_TTL_DAYS = 90;
|
|
28
|
+
export { DEFAULT_KEY_TTL_DAYS };
|
|
30
29
|
// The ceiling keeps toISOString in range.
|
|
31
|
-
const MAX_TTL_DAYS = 3650;
|
|
30
|
+
export const MAX_TTL_DAYS = 3650;
|
|
32
31
|
/** A 400, not a RangeError, since the caller of the mint chose these. */
|
|
33
32
|
function mintExpiry({ ttlDays, noExpiry }) {
|
|
34
33
|
if (noExpiry && ttlDays !== undefined) {
|
|
@@ -70,12 +69,11 @@ function assertSelfMintOpts({ ttlDays, perSubject }) {
|
|
|
70
69
|
}
|
|
71
70
|
/** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
|
|
72
71
|
* binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
|
|
73
|
-
export function authCreateSelf(ctx, opts) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
72
|
+
export async function authCreateSelf(ctx, opts) {
|
|
73
|
+
const keyWrites = requireGroup(storeFor(ctx), 'keyWrites');
|
|
74
|
+
const { plaintext, mint } = selfKeyMint(ctx, opts);
|
|
75
|
+
await keyWrites.createSelfApiKey(mint);
|
|
76
|
+
return selfResult(mint, plaintext);
|
|
79
77
|
}
|
|
80
78
|
function selfKeyMint(ctx, opts) {
|
|
81
79
|
if (!ctx.actor.viaAuthResolver) {
|
|
@@ -97,16 +95,20 @@ function selfResult({ key }, plaintext) {
|
|
|
97
95
|
return { keyId: key.keyId, plaintext, tenantId: key.tenantId, role: 'member', expiresAt: key.expiresAt };
|
|
98
96
|
}
|
|
99
97
|
/** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
|
|
100
|
-
export function authListRows(ctx, opts) {
|
|
101
|
-
return
|
|
98
|
+
export async function authListRows(ctx, opts) {
|
|
99
|
+
return listRows(ctx, storeFor(ctx), opts);
|
|
102
100
|
}
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
/** Every tenant's keys in the store, live ones only unless `active` is false; the host's own view, so the host admin only. */
|
|
102
|
+
export function authListAllTenants(ctx, active) {
|
|
103
|
+
requireHostAdmin(ctx, "Listing every tenant's keys");
|
|
104
|
+
return listApiKeys(ctx.hippoRoot, { active });
|
|
105
|
+
}
|
|
106
|
+
async function listRows(ctx, store, opts) {
|
|
107
|
+
const keyWrites = requireGroup(store, 'keyWrites');
|
|
105
108
|
const keyId = memberKeyIdOf(ctx.actor);
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
});
|
|
109
|
+
const record = keyId === null ? undefined : await store.findApiKey(keyId);
|
|
110
|
+
const filter = memberListFilter(ctx.actor, record?.ownerSubject);
|
|
111
|
+
return filter === null ? [] : keyWrites.listApiKeys({ ...opts, tenantId: ctx.tenantId, ...filter });
|
|
110
112
|
}
|
|
111
113
|
/** The key id of a member API key caller, whose owner decides what it lists; null for any other caller. */
|
|
112
114
|
function memberKeyIdOf(actor) {
|
|
@@ -139,16 +141,14 @@ function assertMayRevoke(ctx, keyId, row) {
|
|
|
139
141
|
}
|
|
140
142
|
/** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
|
|
141
143
|
* The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
|
|
142
|
-
export function authRevoke(ctx, keyId) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
});
|
|
151
|
-
});
|
|
144
|
+
export async function authRevoke(ctx, keyId) {
|
|
145
|
+
const store = storeFor(ctx);
|
|
146
|
+
const keyAudit = requireGroup(store, 'keyAudit');
|
|
147
|
+
assertMemberKeyRevokesSelf(ctx, keyId);
|
|
148
|
+
const record = await store.findApiKey(keyId);
|
|
149
|
+
assertMayRevoke(ctx, keyId, keyOwnerOf(record));
|
|
150
|
+
const revoke = { tenantId: ctx.tenantId, keyId, actor: ctx.actor.subject, at: new Date().toISOString() };
|
|
151
|
+
return { ok: true, revokedAt: await keyAudit.revokeApiKey(revoke) };
|
|
152
152
|
}
|
|
153
153
|
function assertMemberKeyRevokesSelf(ctx, keyId) {
|
|
154
154
|
if (ctx.actor.role !== 'admin' && !ctx.actor.viaAuthResolver && keyIdOfSubject(ctx.actor.subject) !== keyId) {
|
|
@@ -160,12 +160,11 @@ function keyOwnerOf(record) {
|
|
|
160
160
|
}
|
|
161
161
|
/** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
|
|
162
162
|
* so the local CLI can run revoke and grant in the key's own tenant. */
|
|
163
|
-
export function authKeyTenant(ctx, keyId) {
|
|
163
|
+
export async function authKeyTenant(ctx, keyId) {
|
|
164
164
|
if (!ctx.actor.hostAdmin) {
|
|
165
165
|
throw new ForbiddenError('Only the host admin can look up a key across tenants');
|
|
166
166
|
}
|
|
167
|
-
|
|
168
|
-
return sqliteSyncStore(ctx.hippoRoot).findApiKey(keyId)?.tenantId;
|
|
167
|
+
return (await storeFor(ctx).findApiKey(keyId))?.tenantId;
|
|
169
168
|
}
|
|
170
169
|
/** Grant `keyId` read access to one restricted `scope`. Admin only. */
|
|
171
170
|
export function authGrant(ctx, keyId, scope) {
|