hippo-memory 1.69.0 → 1.70.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 +5 -2
- package/dist/agent-memories/apply.d.ts +3 -3
- package/dist/agent-memories/apply.js +16 -31
- package/dist/agent-memories/claude-code.d.ts +1 -3
- package/dist/agent-memories/claude-code.js +11 -7
- package/dist/agent-memories/copilot.js +3 -2
- package/dist/agent-memories/files.js +3 -2
- package/dist/agent-memories/gemini.js +6 -5
- package/dist/agent-memories/keys.js +3 -2
- package/dist/agent-memories/legacy.d.ts +2 -2
- package/dist/agent-memories/legacy.js +2 -2
- package/dist/agent-memories/report.d.ts +1 -1
- package/dist/agent-memories/report.js +1 -1
- package/dist/agent-memories/source.d.ts +1 -1
- package/dist/agent-memories/source.js +6 -5
- package/dist/agent-memories/sync.d.ts +1 -1
- package/dist/agent-memories/sync.js +24 -33
- package/dist/agent-memories/types.d.ts +1 -1
- package/dist/api/assemble.d.ts +2 -2
- package/dist/api/assemble.js +42 -32
- package/dist/api/audit.d.ts +4 -7
- package/dist/api/audit.js +6 -20
- package/dist/api/auth.d.ts +5 -18
- package/dist/api/auth.js +44 -194
- package/dist/api/auto-sleep.d.ts +13 -0
- package/dist/api/auto-sleep.js +32 -0
- package/dist/{availability.d.ts → api/availability.d.ts} +2 -2
- package/dist/{availability.js → api/availability.js} +12 -29
- package/dist/{context-auto.js → api/context-auto.js} +2 -1
- package/dist/{context-render.d.ts → api/context-render.d.ts} +4 -4
- package/dist/{context-render.js → api/context-render.js} +7 -6
- package/dist/api/context-select.d.ts +5 -5
- package/dist/api/context-select.js +37 -45
- package/dist/api/context-types.d.ts +5 -5
- package/dist/api/context.d.ts +2 -4
- package/dist/api/context.js +48 -61
- package/dist/api/dormant.d.ts +3 -3
- package/dist/api/dormant.js +38 -107
- package/dist/api/drill-down.d.ts +2 -2
- package/dist/api/drill-down.js +37 -65
- package/dist/api/forget.d.ts +2 -11
- package/dist/api/forget.js +13 -46
- package/dist/api/goals.d.ts +1 -1
- package/dist/api/goals.js +2 -2
- package/dist/api/index.d.ts +26 -0
- package/dist/api/index.js +29 -0
- package/dist/api/instruction-detect.js +74 -0
- package/dist/api/learn.js +63 -55
- package/dist/api/ledger-db.d.ts +20 -0
- package/dist/api/ledger-db.js +79 -0
- package/dist/api/on-store.d.ts +16 -0
- package/dist/api/on-store.js +36 -0
- package/dist/api/outcome.d.ts +5 -42
- package/dist/api/outcome.js +15 -80
- package/dist/{pilot-arm.d.ts → api/pilot-arm.d.ts} +1 -1
- package/dist/{pilot-arm.js → api/pilot-arm.js} +15 -23
- package/dist/api/promote.d.ts +4 -15
- package/dist/api/promote.js +29 -106
- package/dist/{prompt-hook.d.ts → api/prompt-hook.d.ts} +7 -7
- package/dist/{prompt-hook.js → api/prompt-hook.js} +34 -53
- package/dist/api/quarantine.d.ts +5 -5
- package/dist/api/quarantine.js +30 -106
- package/dist/api/recall-core.d.ts +4 -0
- package/dist/api/recall-core.js +112 -0
- package/dist/{recall-history.js → api/recall-history.js} +30 -25
- package/dist/{recall-pipeline.d.ts → api/recall-pipeline.d.ts} +5 -5
- package/dist/{recall-pipeline.js → api/recall-pipeline.js} +47 -42
- package/dist/api/recall-record.d.ts +10 -13
- package/dist/api/recall-record.js +10 -30
- package/dist/api/recall-request.d.ts +2 -2
- package/dist/api/recall-request.js +3 -3
- package/dist/api/recall-types.d.ts +41 -16
- package/dist/api/recall.d.ts +1 -1
- package/dist/api/recall.js +39 -37
- package/dist/api/remember.d.ts +10 -12
- package/dist/api/remember.js +29 -45
- package/dist/api/session-owners.d.ts +4 -0
- package/dist/api/session-owners.js +17 -0
- package/dist/api/sleep-run.d.ts +7 -7
- package/dist/api/sleep-run.js +63 -75
- package/dist/api/sleep.d.ts +1 -1
- package/dist/api/tokens.d.ts +2 -2
- package/dist/api/tokens.js +9 -21
- package/dist/api/types.d.ts +2 -2
- package/dist/api/types.js +1 -1
- package/dist/capture/caller-session.d.ts +2 -2
- package/dist/capture/caller-session.js +8 -8
- package/dist/{capture-error.d.ts → capture/capture-error.d.ts} +2 -2
- package/dist/{capture-error.js → capture/capture-error.js} +7 -7
- package/dist/{codex-patch.js → capture/codex-patch.js} +1 -1
- package/dist/capture/command.d.ts +1 -1
- package/dist/capture/command.js +54 -41
- package/dist/capture/compact-resume-caller.d.ts +1 -1
- package/dist/capture/compact-resume-caller.js +7 -7
- package/dist/capture/compact.d.ts +4 -1
- package/dist/capture/compact.js +40 -22
- package/dist/capture/compaction-items-caller.d.ts +1 -1
- package/dist/capture/compaction-items-caller.js +7 -5
- package/dist/{compaction-items.js → capture/compaction-items.js} +27 -3
- package/dist/{compaction-record.d.ts → capture/compaction-record.d.ts} +10 -6
- package/dist/{compaction-record.js → capture/compaction-record.js} +48 -94
- package/dist/{compaction-spool.js → capture/compaction-spool.js} +17 -13
- package/dist/capture/copilot-transcript.js +1 -1
- package/dist/capture/extract.js +2 -2
- package/dist/capture/failure-caller.d.ts +2 -2
- package/dist/capture/failure-caller.js +6 -6
- package/dist/capture/failure-reading.d.ts +2 -5
- package/dist/capture/failure-reading.js +11 -12
- package/dist/{handoff-evidence.d.ts → capture/handoff-evidence.d.ts} +1 -1
- package/dist/{handoff-evidence.js → capture/handoff-evidence.js} +2 -1
- package/dist/capture/pre-compact-caller.d.ts +1 -1
- package/dist/capture/pre-compact-caller.js +2 -2
- package/dist/{session-digest.d.ts → capture/session-digest.d.ts} +1 -5
- package/dist/{session-digest.js → capture/session-digest.js} +17 -23
- package/dist/capture/session-end-caller.d.ts +2 -2
- package/dist/capture/session-end-caller.js +1 -1
- package/dist/capture/session-texts.d.ts +1 -1
- package/dist/capture/session-texts.js +5 -5
- package/dist/capture/session-worker.js +6 -4
- package/dist/{share-scrub.js → capture/share-scrub.js} +2 -2
- package/dist/capture/transcript.js +68 -74
- package/dist/capture/working-state.d.ts +0 -3
- package/dist/capture/working-state.js +7 -7
- package/dist/{audit-prune.d.ts → cli/audit-prune.d.ts} +1 -2
- package/dist/{audit-prune.js → cli/audit-prune.js} +5 -39
- package/dist/cli/audit.d.ts +2 -2
- package/dist/cli/audit.js +77 -72
- package/dist/cli/auth.d.ts +2 -1
- package/dist/cli/auth.js +18 -20
- package/dist/cli/briefs.d.ts +4 -3
- package/dist/cli/briefs.js +59 -181
- package/dist/cli/card.d.ts +2 -1
- package/dist/cli/card.js +25 -23
- package/dist/{client.d.ts → cli/client.d.ts} +1 -1
- package/dist/{client.js → cli/client.js} +1 -1
- package/dist/cli/compact-resume-payload.d.ts +8 -0
- package/dist/cli/compact-resume-payload.js +39 -0
- package/dist/cli/context.d.ts +2 -13
- package/dist/cli/context.js +41 -71
- package/dist/cli/continuity.d.ts +6 -5
- package/dist/cli/continuity.js +109 -99
- package/dist/{correction-latency.d.ts → cli/correction-latency.d.ts} +1 -1
- package/dist/cli/curate.d.ts +9 -9
- package/dist/cli/curate.js +177 -149
- package/dist/cli/dag.d.ts +4 -4
- package/dist/cli/dag.js +46 -34
- package/dist/cli/decisions.d.ts +4 -3
- package/dist/cli/decisions.js +108 -218
- package/dist/cli/eval.d.ts +1 -3
- package/dist/cli/eval.js +43 -31
- package/dist/cli/explain.d.ts +1 -1
- package/dist/cli/explain.js +35 -19
- package/dist/cli/flag-values.d.ts +25 -0
- package/dist/cli/flag-values.js +103 -0
- package/dist/cli/flags.d.ts +303 -0
- package/dist/cli/flags.js +169 -0
- package/dist/cli/goals.d.ts +2 -1
- package/dist/cli/goals.js +39 -34
- package/dist/cli/hook-runtime.d.ts +49 -0
- package/dist/cli/hook-runtime.js +155 -0
- package/dist/cli/init.d.ts +2 -1
- package/dist/cli/init.js +151 -118
- package/dist/cli/install-steps.d.ts +7 -0
- package/dist/cli/install-steps.js +110 -0
- package/dist/cli/last-sleep.d.ts +2 -1
- package/dist/cli/last-sleep.js +9 -7
- package/dist/cli/maintenance.d.ts +5 -4
- package/dist/cli/maintenance.js +31 -27
- package/dist/cli/object-verbs.d.ts +40 -0
- package/dist/cli/object-verbs.js +65 -0
- package/dist/{owner-validation.d.ts → cli/owner-validation.d.ts} +0 -1
- package/dist/{owner-validation.js → cli/owner-validation.js} +2 -2
- package/dist/cli/playbooks.d.ts +4 -3
- package/dist/cli/playbooks.js +77 -280
- package/dist/cli/print.d.ts +18 -0
- package/dist/cli/print.js +85 -0
- package/dist/cli/projects.d.ts +2 -3
- package/dist/cli/projects.js +56 -49
- package/dist/{provenance-coverage.d.ts → cli/provenance-coverage.d.ts} +1 -1
- package/dist/cli/quality-repair-once.js +4 -4
- package/dist/{quality-repair.js → cli/quality-repair.js} +23 -37
- package/dist/cli/recall.d.ts +2 -4
- package/dist/cli/recall.js +101 -150
- package/dist/{refine-llm.d.ts → cli/refine-llm.d.ts} +1 -1
- package/dist/{refine-llm.js → cli/refine-llm.js} +70 -82
- package/dist/cli/remember.d.ts +1 -3
- package/dist/cli/remember.js +124 -103
- package/dist/{scheduler.d.ts → cli/scheduler.d.ts} +3 -1
- package/dist/{scheduler.js → cli/scheduler.js} +13 -7
- package/dist/cli/serve.d.ts +1 -1
- package/dist/cli/serve.js +34 -4
- package/dist/cli/session-hooks.d.ts +4 -4
- package/dist/cli/session-hooks.js +190 -184
- package/dist/cli/setup.d.ts +2 -1
- package/dist/cli/setup.js +41 -21
- package/dist/cli/shared.d.ts +5 -95
- package/dist/cli/shared.js +18 -369
- package/dist/cli/slack.d.ts +2 -1
- package/dist/cli/slack.js +31 -55
- package/dist/cli/sleep-render.d.ts +4 -0
- package/dist/cli/sleep-render.js +61 -0
- package/dist/cli/sleep.d.ts +2 -8
- package/dist/cli/sleep.js +20 -76
- package/dist/cli/status.d.ts +3 -3
- package/dist/cli/status.js +39 -41
- package/dist/{stdin.js → cli/stdin.js} +6 -6
- package/dist/cli/transfer.d.ts +4 -4
- package/dist/cli/transfer.js +68 -42
- package/dist/cli/usage.js +4 -2
- package/dist/cli.d.ts +289 -5
- package/dist/cli.js +184 -117
- package/dist/connectors/dlq.d.ts +44 -0
- package/dist/connectors/dlq.js +30 -0
- package/dist/connectors/github/backfill.d.ts +1 -1
- package/dist/connectors/github/backfill.js +29 -66
- package/dist/connectors/github/cli-impl.js +59 -74
- package/dist/connectors/github/deletion.d.ts +5 -6
- package/dist/connectors/github/deletion.js +18 -52
- package/dist/connectors/github/dlq.d.ts +7 -61
- package/dist/connectors/github/dlq.js +19 -119
- package/dist/connectors/github/ingest.d.ts +2 -31
- package/dist/connectors/github/ingest.js +20 -83
- package/dist/connectors/github/octokit-client.d.ts +1 -1
- package/dist/connectors/github/octokit-client.js +2 -1
- package/dist/connectors/github/tenant-routing.d.ts +2 -2
- package/dist/connectors/github/tenant-routing.js +10 -36
- package/dist/connectors/github/transform.d.ts +1 -1
- package/dist/connectors/github/types.d.ts +1 -1
- package/dist/connectors/github/types.js +15 -18
- package/dist/connectors/github/webhook.d.ts +3 -2
- package/dist/connectors/github/webhook.js +84 -87
- package/dist/connectors/slack/backfill.d.ts +1 -1
- package/dist/connectors/slack/backfill.js +5 -29
- package/dist/connectors/slack/deletion.d.ts +4 -7
- package/dist/connectors/slack/deletion.js +20 -49
- package/dist/connectors/slack/dlq.d.ts +7 -49
- package/dist/connectors/slack/dlq.js +25 -118
- package/dist/connectors/slack/ingest.d.ts +5 -18
- package/dist/connectors/slack/ingest.js +27 -91
- package/dist/connectors/slack/signature.js +2 -1
- package/dist/connectors/slack/tenant-routing.d.ts +4 -1
- package/dist/connectors/slack/tenant-routing.js +13 -14
- package/dist/connectors/slack/transform.d.ts +1 -1
- package/dist/connectors/slack/types.d.ts +1 -1
- package/dist/connectors/slack/types.js +3 -12
- package/dist/connectors/slack/web-client.js +2 -2
- package/dist/connectors/slack/webhook.d.ts +3 -2
- package/dist/connectors/slack/webhook.js +75 -82
- package/dist/connectors/slack/workspaces.d.ts +4 -17
- package/dist/connectors/slack/workspaces.js +4 -34
- package/dist/consolidate/conflicts.d.ts +1 -1
- package/dist/consolidate/conflicts.js +4 -4
- package/dist/{dag.d.ts → consolidate/dag.d.ts} +1 -1
- package/dist/{dag.js → consolidate/dag.js} +60 -81
- package/dist/consolidate/decay.d.ts +2 -2
- package/dist/consolidate/decay.js +28 -22
- package/dist/{dedupe.js → consolidate/dedupe.js} +11 -19
- package/dist/consolidate/flush-units.d.ts +2 -2
- package/dist/{half-life-migration.d.ts → consolidate/half-life-migration.d.ts} +3 -9
- package/dist/consolidate/half-life-migration.js +106 -0
- package/dist/consolidate/llm-passes.js +8 -8
- package/dist/{memory-value.d.ts → consolidate/memory-value.d.ts} +7 -2
- package/dist/{memory-value.js → consolidate/memory-value.js} +9 -7
- package/dist/consolidate/merge.js +57 -54
- package/dist/{merged-row.d.ts → consolidate/merged-row.d.ts} +1 -1
- package/dist/{merged-row.js → consolidate/merged-row.js} +2 -2
- package/dist/consolidate/physics-pass.js +46 -46
- package/dist/{replay.d.ts → consolidate/replay.d.ts} +1 -1
- package/dist/{replay.js → consolidate/replay.js} +2 -2
- package/dist/consolidate/run.d.ts +7 -13
- package/dist/consolidate/run.js +6 -37
- package/dist/consolidate/sleep.d.ts +1 -1
- package/dist/consolidate/sleep.js +64 -134
- package/dist/{trace.js → consolidate/trace.js} +4 -6
- package/dist/consolidate/traces.js +34 -29
- package/dist/{ablation.js → core/ablation.js} +1 -1
- package/dist/{agent-memories/tools.d.ts → core/agent-memory-tools.d.ts} +1 -1
- package/dist/{agent-memories/tools.js → core/agent-memory-tools.js} +1 -1
- package/dist/{ambient.js → core/ambient.js} +12 -10
- package/dist/{capture-contract.d.ts → core/capture-contract.d.ts} +13 -2
- package/dist/{capture-contract.js → core/capture-contract.js} +64 -0
- package/dist/{compare.d.ts → core/compare.d.ts} +2 -0
- package/dist/{compare.js → core/compare.js} +10 -3
- package/dist/{config.d.ts → core/config.d.ts} +6 -6
- package/dist/{config.js → core/config.js} +99 -72
- package/dist/core/handoff.js +87 -0
- package/dist/{memory-quality.js → core/memory-quality.js} +1 -1
- package/dist/{memory.d.ts → core/memory.d.ts} +17 -5
- package/dist/{memory.js → core/memory.js} +110 -82
- package/dist/{physics.d.ts → core/physics.d.ts} +1 -1
- package/dist/{physics.js → core/physics.js} +2 -1
- package/dist/{project-identity.d.ts → core/project-identity.d.ts} +0 -5
- package/dist/{project-identity.js → core/project-identity.js} +5 -17
- package/dist/{project-remote.js → core/project-remote.js} +4 -4
- package/dist/{prompt-recall.js → core/prompt-recall.js} +1 -1
- package/dist/{salience.js → core/salience.js} +35 -20
- package/dist/{search/types.d.ts → core/search-types.d.ts} +2 -2
- package/dist/{search/types.js → core/search-types.js} +1 -1
- package/dist/core/session-digest-row.d.ts +5 -0
- package/dist/core/session-digest-row.js +6 -0
- package/dist/{dashboard-actions.d.ts → dashboard/dashboard-actions.d.ts} +1 -1
- package/dist/{dashboard-actions.js → dashboard/dashboard-actions.js} +5 -5
- package/dist/{dashboard-queries.d.ts → dashboard/dashboard-queries.d.ts} +7 -2
- package/dist/{dashboard-queries.js → dashboard/dashboard-queries.js} +6 -10
- package/dist/{dashboard-snapshot.d.ts → dashboard/dashboard-snapshot.d.ts} +9 -9
- package/dist/{dashboard-snapshot.js → dashboard/dashboard-snapshot.js} +101 -104
- package/dist/{dashboard.js → dashboard/dashboard.js} +124 -53
- package/dist/db/backup.js +1 -1
- package/dist/db/busy.d.ts +18 -1
- package/dist/db/busy.js +74 -9
- package/dist/db/connect.d.ts +10 -2
- package/dist/db/connect.js +43 -10
- package/dist/db/index.d.ts +9 -0
- package/dist/db/index.js +8 -0
- package/dist/db/meta.d.ts +4 -0
- package/dist/db/meta.js +11 -1
- package/dist/db/migrate.d.ts +8 -1
- package/dist/db/migrate.js +25 -30
- package/dist/db/migrations/v08.js +1 -1
- package/dist/db/migrations/v14.js +39 -35
- package/dist/db/migrations/v16.js +29 -26
- package/dist/db/migrations/v18.js +6 -5
- package/dist/db/migrations/v20.js +4 -2
- package/dist/db/migrations/v22.js +39 -36
- package/dist/db/migrations/v24.js +27 -22
- package/dist/db/migrations/v29.js +37 -32
- package/dist/db/migrations/v31.js +36 -31
- package/dist/db/migrations/v35.js +1 -1
- package/dist/db/migrations/v39.js +1 -1
- package/dist/db/migrations/v40.js +15 -14
- package/dist/db/migrations/v43.js +7 -6
- package/dist/db/migrations/v44.js +1 -1
- package/dist/db/migrations/v45.js +1 -1
- package/dist/db/migrations/v46.js +1 -1
- package/dist/db/migrations/v47.js +1 -1
- package/dist/db/migrations/v48.js +1 -1
- package/dist/db/migrations/v49.js +1 -1
- package/dist/db/migrations/v50.js +8 -7
- package/dist/db/migrations/v52.js +1 -1
- package/dist/db/open.d.ts +9 -1
- package/dist/db/open.js +21 -4
- package/dist/{physics-state.d.ts → db/physics-state.d.ts} +3 -3
- package/dist/{physics-state.js → db/physics-state.js} +9 -16
- package/dist/{raw-archive-mirror-cleanup.d.ts → db/raw-archive-mirror-cleanup.d.ts} +5 -5
- package/dist/{raw-archive-mirror-cleanup.js → db/raw-archive-mirror-cleanup.js} +11 -6
- package/dist/db/request-stores.d.ts +15 -2
- package/dist/db/request-stores.js +37 -15
- package/dist/db/tables.d.ts +2 -0
- package/dist/db/tables.js +6 -0
- package/dist/{vector-store.d.ts → db/vector-store.d.ts} +4 -2
- package/dist/{vector-store.js → db/vector-store.js} +76 -51
- package/dist/db/wal-checkpointer.d.ts +11 -0
- package/dist/db/wal-checkpointer.js +92 -0
- package/dist/doctor.js +105 -136
- package/dist/entry/json-hooks.d.ts +1 -1
- package/dist/entry/json-hooks.js +1 -1
- package/dist/entry/project-identity.d.ts +1 -1
- package/dist/entry/project-identity.js +1 -1
- package/dist/entry/session-text.d.ts +3 -3
- package/dist/entry/session-text.js +3 -3
- package/dist/{eval-stats.js → eval/eval-stats.js} +12 -9
- package/dist/{eval-suite.d.ts → eval/eval-suite.d.ts} +1 -1
- package/dist/{eval-suite.js → eval/eval-suite.js} +25 -23
- package/dist/{eval.d.ts → eval/eval.d.ts} +1 -1
- package/dist/{eval.js → eval/eval.js} +29 -22
- package/dist/{judgment.d.ts → eval/judgment.d.ts} +1 -3
- package/dist/{judgment.js → eval/judgment.js} +4 -9
- package/dist/extensions/openclaw-plugin/index.js +1 -2
- package/dist/graph/delta.d.ts +3 -2
- package/dist/graph/delta.js +9 -23
- package/dist/{graph-extract.d.ts → graph/extract.d.ts} +6 -6
- package/dist/{graph-extract.js → graph/extract.js} +37 -52
- package/dist/{graph-recall.d.ts → graph/recall.d.ts} +2 -2
- package/dist/{graph-recall.js → graph/recall.js} +55 -36
- package/dist/{graph-stream.d.ts → graph/stream.d.ts} +2 -2
- package/dist/{graph-stream.js → graph/stream.js} +9 -7
- package/dist/{graph-view.d.ts → graph/view.d.ts} +6 -3
- package/dist/{graph-view.js → graph/view.js} +127 -167
- package/dist/graph/write.d.ts +4 -76
- package/dist/graph/write.js +13 -397
- package/dist/hooks/codex-session.js +1 -1
- package/dist/hooks/codex-wrapper.js +14 -15
- package/dist/hooks/copilot.d.ts +1 -8
- package/dist/hooks/copilot.js +14 -15
- package/dist/{cli → hooks}/hook-blocks.js +1 -1
- package/dist/hooks/json-hooks.d.ts +1 -1
- package/dist/hooks/json-hooks.js +31 -122
- package/dist/hooks/opencode.js +35 -27
- package/dist/hooks/shared.d.ts +0 -4
- package/dist/hooks/shared.js +1 -5
- package/dist/importers/core.d.ts +2 -6
- package/dist/importers/core.js +41 -39
- package/dist/importers/markdown-parse.d.ts +1 -10
- package/dist/importers/markdown-parse.js +2 -19
- package/dist/importers/markdown.js +2 -1
- package/dist/importers/sources.js +50 -46
- package/dist/importers/vault.js +71 -92
- package/dist/index.d.ts +22 -22
- package/dist/index.js +21 -21
- package/dist/{autolearn.d.ts → learn/autolearn.d.ts} +2 -2
- package/dist/{autolearn.js → learn/autolearn.js} +13 -11
- package/dist/{churn-git.d.ts → learn/churn-git.d.ts} +1 -1
- package/dist/{churn-git.js → learn/churn-git.js} +6 -4
- package/dist/{extract.d.ts → learn/extract.d.ts} +1 -1
- package/dist/learn/extract.js +125 -0
- package/dist/{forward-claim-detector.d.ts → learn/forward-claim-detector.d.ts} +1 -1
- package/dist/{forward-claim-detector.js → learn/forward-claim-detector.js} +1 -1
- package/dist/{invalidation.d.ts → learn/invalidation.d.ts} +4 -0
- package/dist/{invalidation.js → learn/invalidation.js} +83 -99
- package/dist/mcp/admin-tools.d.ts +1 -1
- package/dist/mcp/admin-tools.js +37 -60
- package/dist/mcp/format.d.ts +5 -5
- package/dist/mcp/format.js +7 -6
- package/dist/mcp/framing.d.ts +6 -0
- package/dist/mcp/framing.js +11 -3
- package/dist/mcp/memory-tools.js +7 -27
- package/dist/mcp/protocol.d.ts +6 -10
- package/dist/mcp/protocol.js +8 -14
- package/dist/mcp/recall-tools.d.ts +2 -2
- package/dist/mcp/recall-tools.js +68 -50
- package/dist/mcp/request.js +62 -60
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/session-state.d.ts +1 -2
- package/dist/mcp/session-state.js +2 -2
- package/dist/mcp/shared-gate.js +1 -1
- package/dist/mcp/stdio.js +69 -31
- package/dist/mcp/tool-args.js +2 -1
- package/dist/mcp/tools.js +2 -2
- package/dist/{customer-notes.d.ts → objects/customer-notes.d.ts} +7 -24
- package/dist/objects/customer-notes.js +112 -0
- package/dist/{decisions.d.ts → objects/decisions.d.ts} +13 -28
- package/dist/objects/decisions.js +101 -0
- package/dist/objects/descriptor.d.ts +52 -0
- package/dist/objects/descriptor.js +4 -0
- package/dist/objects/fields.d.ts +15 -0
- package/dist/objects/fields.js +21 -0
- package/dist/{incidents.d.ts → objects/incidents.d.ts} +17 -44
- package/dist/objects/incidents.js +130 -0
- package/dist/objects/lifecycle.d.ts +27 -0
- package/dist/objects/lifecycle.js +96 -0
- package/dist/{policies.d.ts → objects/policies.d.ts} +14 -27
- package/dist/objects/policies.js +189 -0
- package/dist/{processes.d.ts → objects/processes.d.ts} +14 -34
- package/dist/objects/processes.js +146 -0
- package/dist/{project-briefs.d.ts → objects/project-briefs.d.ts} +19 -40
- package/dist/objects/project-briefs.js +255 -0
- package/dist/{skills.d.ts → objects/skills.d.ts} +11 -26
- package/dist/objects/skills.js +156 -0
- package/dist/postinstall.js +4 -2
- package/dist/predictions/planning-fallacy.d.ts +4 -76
- package/dist/predictions/planning-fallacy.js +4 -129
- package/dist/rerankers/clef.d.ts +2 -6
- package/dist/rerankers/clef.js +27 -47
- package/dist/rerankers/cross-encoder.d.ts +0 -7
- package/dist/rerankers/cross-encoder.js +15 -23
- package/dist/rerankers/index.js +8 -7
- package/dist/rerankers/jev.d.ts +1 -4
- package/dist/rerankers/jev.js +30 -49
- package/dist/rerankers/llm.d.ts +2 -4
- package/dist/rerankers/llm.js +33 -50
- package/dist/rerankers/outage-warning.d.ts +7 -0
- package/dist/rerankers/outage-warning.js +31 -0
- package/dist/rerankers/remote.d.ts +3 -0
- package/dist/rerankers/remote.js +23 -0
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/search/as-of.d.ts +1 -1
- package/dist/search/bm25-search.d.ts +2 -2
- package/dist/search/bm25-search.js +7 -7
- package/dist/search/bm25.d.ts +1 -1
- package/dist/search/bm25.js +1 -1
- package/dist/search/boosts.d.ts +5 -1
- package/dist/search/boosts.js +34 -13
- package/dist/search/breakdown.d.ts +2 -2
- package/dist/search/breakdown.js +2 -1
- package/dist/search/explain.d.ts +1 -1
- package/dist/search/explain.js +3 -2
- package/dist/search/finalize.d.ts +2 -2
- package/dist/search/finalize.js +4 -3
- package/dist/search/fusion.d.ts +1 -1
- package/dist/search/fusion.js +3 -3
- package/dist/search/hybrid-score.d.ts +2 -2
- package/dist/search/hybrid-score.js +1 -1
- package/dist/search/hybrid.d.ts +4 -4
- package/dist/search/hybrid.js +11 -8
- package/dist/{multihop.d.ts → search/multihop.d.ts} +2 -2
- package/dist/{multihop.js → search/multihop.js} +7 -5
- package/dist/{path-context.js → search/path-context.js} +3 -1
- package/dist/search/physics-search.d.ts +4 -4
- package/dist/search/physics-search.js +15 -15
- package/dist/search/rerank.d.ts +3 -3
- package/dist/search/rerank.js +4 -3
- package/dist/search/temporal.d.ts +1 -1
- package/dist/search/temporal.js +5 -2
- package/dist/search/vector.d.ts +3 -3
- package/dist/search/vector.js +17 -11
- package/dist/server/auth.d.ts +1 -1
- package/dist/server/auth.js +26 -18
- package/dist/server/boot.d.ts +24 -0
- package/dist/server/boot.js +465 -0
- package/dist/server/client-ip.d.ts +5 -1
- package/dist/server/client-ip.js +18 -6
- package/dist/server/cursor.d.ts +1 -1
- package/dist/server/cursor.js +2 -3
- package/dist/server/deadline.d.ts +13 -0
- package/dist/server/deadline.js +45 -0
- package/dist/server/key-check-bounds.d.ts +8 -0
- package/dist/server/key-check-bounds.js +46 -0
- package/dist/server/lifecycle.js +1 -1
- package/dist/server/mcp-http.d.ts +1 -4
- package/dist/server/mcp-http.js +34 -24
- package/dist/server/ready.d.ts +7 -0
- package/dist/server/ready.js +38 -0
- package/dist/server/request.d.ts +10 -4
- package/dist/server/request.js +63 -12
- package/dist/server/route-table.d.ts +15 -0
- package/dist/server/route-table.js +209 -0
- package/dist/server/routes/admin.js +13 -8
- package/dist/server/routes/customer-notes.d.ts +5 -5
- package/dist/server/routes/customer-notes.js +32 -97
- package/dist/server/routes/decisions.d.ts +5 -5
- package/dist/server/routes/decisions.js +42 -105
- package/dist/server/routes/incidents.d.ts +5 -5
- package/dist/server/routes/incidents.js +42 -95
- package/dist/server/routes/memories.js +12 -14
- package/dist/server/routes/object-routes.d.ts +40 -0
- package/dist/server/routes/object-routes.js +80 -0
- package/dist/server/routes/policies.d.ts +6 -6
- package/dist/server/routes/policies.js +40 -124
- package/dist/server/routes/predictions.js +29 -45
- package/dist/server/routes/processes.d.ts +5 -5
- package/dist/server/routes/processes.js +38 -118
- package/dist/server/routes/project-briefs.d.ts +6 -6
- package/dist/server/routes/project-briefs.js +38 -110
- package/dist/server/routes/recall.js +14 -12
- package/dist/server/routes/skills.d.ts +6 -6
- package/dist/server/routes/skills.js +37 -125
- package/dist/{server-detect.js → server/server-detect.js} +1 -1
- package/dist/server/sleep-child.d.ts +2 -0
- package/dist/server/sleep-child.js +19 -0
- package/dist/server/sleep-offload.d.ts +20 -0
- package/dist/server/sleep-offload.js +70 -0
- package/dist/server/tls.d.ts +6 -0
- package/dist/server/tls.js +24 -0
- package/dist/server/types.d.ts +27 -8
- package/dist/server/validation.d.ts +3 -4
- package/dist/server/validation.js +6 -11
- package/dist/server.d.ts +39 -61
- package/dist/server.js +24 -568
- package/dist/{project-merge.d.ts → sharing/project-merge.d.ts} +1 -1
- package/dist/{project-merge.js → sharing/project-merge.js} +26 -45
- package/dist/{scope.js → sharing/scope.js} +1 -1
- package/dist/{shared.d.ts → sharing/shared.d.ts} +10 -9
- package/dist/{shared.js → sharing/shared.js} +100 -77
- package/dist/{ambient-store.d.ts → store/ambient.d.ts} +2 -2
- package/dist/{ambient-store.js → store/ambient.js} +10 -10
- package/dist/store/audit-event.d.ts +11 -5
- package/dist/store/audit-event.js +5 -4
- package/dist/{audit.d.ts → store/audit.d.ts} +27 -3
- package/dist/{audit.js → store/audit.js} +91 -6
- package/dist/{auth.d.ts → store/auth.d.ts} +15 -32
- package/dist/{auth.js → store/auth.js} +100 -92
- package/dist/store/candidates.d.ts +23 -12
- package/dist/store/candidates.js +87 -35
- package/dist/{card-detail.d.ts → store/card-detail.d.ts} +3 -3
- package/dist/{card-detail.js → store/card-detail.js} +1 -1
- package/dist/{store-cards.d.ts → store/cards.d.ts} +14 -9
- package/dist/{store-cards.js → store/cards.js} +85 -146
- package/dist/store/compactions.d.ts +78 -0
- package/dist/store/compactions.js +93 -0
- package/dist/store/conflicts.d.ts +22 -5
- package/dist/store/conflicts.js +160 -109
- package/dist/store/connectors/github.d.ts +84 -0
- package/dist/store/connectors/github.js +180 -0
- package/dist/store/connectors/slack.d.ts +69 -0
- package/dist/store/connectors/slack.js +177 -0
- package/dist/store/dashboard-reads.d.ts +27 -0
- package/dist/store/dashboard-reads.js +92 -0
- package/dist/store/delete-and-batch.d.ts +20 -24
- package/dist/store/delete-and-batch.js +64 -40
- package/dist/{delivery-recorder.d.ts → store/delivery-recorder.d.ts} +12 -5
- package/dist/{delivery-recorder.js → store/delivery-recorder.js} +42 -30
- package/dist/store/descendant-page.d.ts +12 -0
- package/dist/store/descendant-page.js +99 -0
- package/dist/store/diagnostics.d.ts +47 -0
- package/dist/store/diagnostics.js +51 -0
- package/dist/store/doctor-reads.d.ts +16 -0
- package/dist/store/doctor-reads.js +19 -0
- package/dist/{dormant.d.ts → store/dormant.d.ts} +46 -12
- package/dist/{dormant.js → store/dormant.js} +151 -6
- package/dist/{embeddings.d.ts → store/embeddings/index.d.ts} +10 -6
- package/dist/{embeddings.js → store/embeddings/index.js} +60 -44
- package/dist/{local-embedding.d.ts → store/embeddings/local.d.ts} +1 -1
- package/dist/{local-embedding.js → store/embeddings/local.js} +68 -57
- package/dist/{embedding-provider.d.ts → store/embeddings/provider.d.ts} +2 -2
- package/dist/{embedding-provider.js → store/embeddings/provider.js} +47 -32
- package/dist/store/entry-reads.d.ts +46 -7
- package/dist/store/entry-reads.js +120 -21
- package/dist/store/entry-row.d.ts +8 -2
- package/dist/store/entry-row.js +28 -8
- package/dist/store/entry-writes.d.ts +33 -4
- package/dist/store/entry-writes.js +108 -26
- package/dist/{failure-log.d.ts → store/failure-log.d.ts} +7 -2
- package/dist/{failure-log.js → store/failure-log.js} +9 -2
- package/dist/{goals.d.ts → store/goals.d.ts} +6 -46
- package/dist/{goals.js → store/goals.js} +45 -94
- package/dist/store/graph-queue.d.ts +29 -0
- package/dist/store/graph-queue.js +101 -0
- package/dist/{graph/read.d.ts → store/graph-reads.d.ts} +26 -34
- package/dist/{graph/read.js → store/graph-reads.js} +63 -115
- package/dist/{graph/types.d.ts → store/graph-rows.d.ts} +68 -8
- package/dist/{graph/rows.js → store/graph-rows.js} +14 -3
- package/dist/store/graph-view-rows.d.ts +12 -0
- package/dist/store/graph-view-rows.js +67 -0
- package/dist/store/graph-writes.d.ts +58 -0
- package/dist/store/graph-writes.js +256 -0
- package/dist/store/half-life.d.ts +34 -0
- package/dist/store/half-life.js +77 -0
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +39 -30
- package/dist/store/index-and-stats.d.ts +8 -1
- package/dist/store/index-and-stats.js +51 -48
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.js +3 -0
- package/dist/store/key-audit.d.ts +2 -2
- package/dist/store/key-audit.js +4 -4
- package/dist/store/key-writes.d.ts +12 -5
- package/dist/store/key-writes.js +30 -4
- package/dist/store/ledger-turn.d.ts +17 -0
- package/dist/store/ledger-turn.js +27 -0
- package/dist/store/markdown.d.ts +1 -1
- package/dist/store/markdown.js +4 -3
- package/dist/store/mirrors.d.ts +5 -7
- package/dist/store/mirrors.js +39 -25
- package/dist/store/object-types.d.ts +189 -0
- package/dist/store/object-types.js +4 -0
- package/dist/store/open.d.ts +6 -4
- package/dist/store/open.js +24 -23
- package/dist/store/planning-fallacy-evidence.d.ts +42 -0
- package/dist/store/planning-fallacy-evidence.js +81 -0
- package/dist/store/port.d.ts +646 -0
- package/dist/store/port.js +17 -0
- package/dist/{predictions/store.d.ts → store/predictions.d.ts} +15 -2
- package/dist/{predictions/store.js → store/predictions.js} +52 -67
- package/dist/{quarantine.d.ts → store/quarantine.d.ts} +8 -8
- package/dist/{quarantine.js → store/quarantine.js} +64 -22
- package/dist/{raw-archive.d.ts → store/raw-archive.d.ts} +3 -1
- package/dist/{raw-archive.js → store/raw-archive.js} +6 -2
- package/dist/{recall-scope.d.ts → store/recall-scope.d.ts} +2 -2
- package/dist/{recall-scope.js → store/recall-scope.js} +3 -3
- package/dist/{recall-trace.d.ts → store/recall-trace.d.ts} +13 -14
- package/dist/{recall-trace.js → store/recall-trace.js} +38 -43
- package/dist/store/rejected-values.d.ts +55 -0
- package/dist/store/rejected-values.js +162 -0
- package/dist/{rejection.d.ts → store/rejection.d.ts} +2 -2
- package/dist/{rejection.js → store/rejection.js} +3 -2
- package/dist/store/rows.d.ts +2 -3
- package/dist/store/rows.js +18 -11
- package/dist/store/search-rows.d.ts +15 -4
- package/dist/store/search-rows.js +41 -28
- package/dist/store/sessions.d.ts +13 -2
- package/dist/store/sessions.js +79 -45
- package/dist/store/sqlite/commit-watch.d.ts +4 -0
- package/dist/store/sqlite/commit-watch.js +29 -0
- package/dist/store/sqlite/connector-events-group.d.ts +5 -0
- package/dist/store/sqlite/connector-events-group.js +50 -0
- package/dist/store/sqlite/connector-writes-group.d.ts +6 -0
- package/dist/store/sqlite/connector-writes-group.js +65 -0
- package/dist/store/sqlite/dag-reads-group.d.ts +3 -0
- package/dist/store/sqlite/dag-reads-group.js +45 -0
- package/dist/store/sqlite/entry-writes-group.d.ts +18 -0
- package/dist/store/{entry-writes-group.js → sqlite/entry-writes-group.js} +73 -60
- package/dist/store/sqlite/error-codec.d.ts +17 -0
- package/dist/store/sqlite/error-codec.js +59 -0
- package/dist/store/sqlite/executor-counts.d.ts +10 -0
- package/dist/store/sqlite/executor-counts.js +11 -0
- package/dist/store/sqlite/executor.d.ts +28 -0
- package/dist/store/sqlite/executor.js +286 -0
- package/dist/store/sqlite/graph-reads-group.d.ts +5 -0
- package/dist/store/sqlite/graph-reads-group.js +18 -0
- package/dist/store/sqlite/local.d.ts +21 -0
- package/dist/store/sqlite/local.js +38 -0
- package/dist/store/sqlite/object-rows.d.ts +102 -0
- package/dist/store/sqlite/object-rows.js +218 -0
- package/dist/store/sqlite/objects-group.d.ts +20 -0
- package/dist/store/sqlite/objects-group.js +314 -0
- package/dist/store/sqlite/predictions-group.d.ts +5 -0
- package/dist/store/sqlite/predictions-group.js +28 -0
- package/dist/store/sqlite/quarantine-group.d.ts +5 -0
- package/dist/store/sqlite/quarantine-group.js +38 -0
- package/dist/store/sqlite/store.d.ts +26 -0
- package/dist/store/sqlite/store.js +295 -0
- package/dist/store/sqlite/vector-pack.d.ts +18 -0
- package/dist/store/sqlite/vector-pack.js +46 -0
- package/dist/store/sqlite/vector-reads-group.d.ts +3 -0
- package/dist/store/sqlite/vector-reads-group.js +23 -0
- package/dist/store/sqlite/worker-entry.d.ts +2 -0
- package/dist/store/sqlite/worker-entry.js +8 -0
- package/dist/store/sqlite/worker-jobs.d.ts +5 -0
- package/dist/store/sqlite/worker-jobs.js +116 -0
- package/dist/store/sqlite/worker-ops.d.ts +124 -0
- package/dist/store/sqlite/worker-ops.js +82 -0
- package/dist/store/sqlite/worker-store.d.ts +8 -0
- package/dist/store/sqlite/worker-store.js +76 -0
- package/dist/store/summaries.d.ts +2 -11
- package/dist/store/summaries.js +17 -44
- package/dist/{summary-dirty.d.ts → store/summary-dirty.d.ts} +1 -1
- package/dist/store/tenant-lookup.d.ts +1 -1
- package/dist/{tenant.d.ts → store/tenant.d.ts} +2 -2
- package/dist/{tenant.js → store/tenant.js} +1 -1
- package/dist/store/token-ledger-rows.d.ts +61 -0
- package/dist/store/token-ledger-rows.js +68 -0
- package/dist/{token-ledger.d.ts → store/token-ledger.d.ts} +2 -9
- package/dist/{token-ledger.js → store/token-ledger.js} +31 -78
- package/dist/store/tombstone-checks.d.ts +12 -0
- package/dist/store/tombstone-checks.js +31 -0
- package/dist/store/usage-reports.d.ts +7 -0
- package/dist/store/usage-reports.js +26 -0
- package/dist/store/vector-writes.d.ts +10 -3
- package/dist/store/vector-writes.js +35 -5
- package/dist/{working-memory.d.ts → store/working-memory.d.ts} +5 -1
- package/dist/{working-memory.js → store/working-memory.js} +39 -41
- package/dist/support-bundle.d.ts +1 -1
- package/dist/support-bundle.js +13 -33
- package/dist/{gated-write.d.ts → trust/gated-write.d.ts} +2 -2
- package/dist/{gated-write.js → trust/gated-write.js} +6 -6
- package/dist/trust/quarantine.d.ts +4 -0
- package/dist/trust/quarantine.js +8 -0
- package/dist/trust/reject-flow.d.ts +23 -0
- package/dist/trust/reject-flow.js +67 -0
- package/dist/util/anthropic-messages.d.ts +31 -0
- package/dist/util/anthropic-messages.js +46 -0
- package/dist/util/atomic-write.d.ts +3 -0
- package/dist/util/atomic-write.js +107 -0
- package/dist/util/crash-handlers.d.ts +5 -0
- package/dist/util/crash-handlers.js +30 -0
- package/dist/{env.d.ts → util/env.d.ts} +15 -2
- package/dist/{env.js → util/env.js} +20 -2
- package/dist/util/home-path.js +67 -0
- package/dist/{http-retry.d.ts → util/http-retry.d.ts} +6 -2
- package/dist/{http-retry.js → util/http-retry.js} +38 -7
- package/dist/{http-util.d.ts → util/http-util.d.ts} +14 -3
- package/dist/{http-util.js → util/http-util.js} +31 -11
- package/dist/util/json.d.ts +17 -0
- package/dist/util/json.js +25 -0
- package/dist/{log.d.ts → util/log.d.ts} +5 -2
- package/dist/{log.js → util/log.js} +12 -3
- package/dist/util/real-path.d.ts +3 -0
- package/dist/util/real-path.js +15 -0
- package/dist/util/request-scope.d.ts +27 -0
- package/dist/util/request-scope.js +47 -0
- package/dist/{same-text.d.ts → util/same-text.d.ts} +1 -1
- package/dist/{secret-detect.js → util/secret-detect.js} +5 -4
- package/dist/util/stored-json.d.ts +9 -0
- package/dist/util/stored-json.js +8 -0
- package/dist/util/time.d.ts +2 -0
- package/dist/util/time.js +3 -0
- package/dist/util/token-text.d.ts +18 -0
- package/dist/util/token-text.js +23 -0
- package/dist/{version.d.ts → util/version.d.ts} +1 -1
- package/dist/{version.js → util/version.js} +1 -1
- package/extensions/openclaw-plugin/index.ts +1 -5
- 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/api.d.ts +0 -26
- package/dist/api.js +0 -29
- package/dist/connectors/github/idempotency.d.ts +0 -19
- package/dist/connectors/github/idempotency.js +0 -27
- package/dist/connectors/slack/idempotency.d.ts +0 -17
- package/dist/connectors/slack/idempotency.js +0 -31
- package/dist/customer-notes.js +0 -336
- package/dist/db.d.ts +0 -9
- package/dist/db.js +0 -8
- package/dist/decisions.js +0 -326
- package/dist/extract.js +0 -133
- package/dist/graph/rows.d.ts +0 -45
- package/dist/graph/types.js +0 -11
- package/dist/half-life-migration.js +0 -182
- package/dist/handoff.js +0 -68
- package/dist/home-path.js +0 -24
- package/dist/incidents.js +0 -349
- package/dist/instruction-detect.js +0 -27
- package/dist/json.d.ts +0 -7
- package/dist/json.js +0 -11
- package/dist/ledger-db.d.ts +0 -10
- package/dist/ledger-db.js +0 -42
- package/dist/policies.js +0 -434
- package/dist/processes.js +0 -371
- package/dist/project-briefs.js +0 -523
- package/dist/reject-flow.d.ts +0 -69
- package/dist/reject-flow.js +0 -260
- package/dist/session-owners.d.ts +0 -7
- package/dist/session-owners.js +0 -54
- package/dist/skills.js +0 -367
- package/dist/store/entry-writes-group.d.ts +0 -9
- package/dist/store-port.d.ts +0 -262
- package/dist/store-port.js +0 -178
- /package/dist/{context-auto.d.ts → api/context-auto.d.ts} +0 -0
- /package/dist/{instruction-detect.d.ts → api/instruction-detect.d.ts} +0 -0
- /package/dist/{recall-history.d.ts → api/recall-history.d.ts} +0 -0
- /package/dist/{codex-patch.d.ts → capture/codex-patch.d.ts} +0 -0
- /package/dist/{compaction-items.d.ts → capture/compaction-items.d.ts} +0 -0
- /package/dist/{compaction-spool.d.ts → capture/compaction-spool.d.ts} +0 -0
- /package/dist/{share-scrub.d.ts → capture/share-scrub.d.ts} +0 -0
- /package/dist/{correction-latency.js → cli/correction-latency.js} +0 -0
- /package/dist/{provenance-coverage.js → cli/provenance-coverage.js} +0 -0
- /package/dist/{quality-repair.d.ts → cli/quality-repair.d.ts} +0 -0
- /package/dist/{stdin.d.ts → cli/stdin.d.ts} +0 -0
- /package/dist/{dedupe.d.ts → consolidate/dedupe.d.ts} +0 -0
- /package/dist/{memory-value-weights.d.ts → consolidate/memory-value-weights.d.ts} +0 -0
- /package/dist/{memory-value-weights.js → consolidate/memory-value-weights.js} +0 -0
- /package/dist/{overlap-index.d.ts → consolidate/overlap-index.d.ts} +0 -0
- /package/dist/{overlap-index.js → consolidate/overlap-index.js} +0 -0
- /package/dist/{trace.d.ts → consolidate/trace.d.ts} +0 -0
- /package/dist/{ablation.d.ts → core/ablation.d.ts} +0 -0
- /package/dist/{ambient.d.ts → core/ambient.d.ts} +0 -0
- /package/dist/{api-errors.d.ts → core/api-errors.d.ts} +0 -0
- /package/dist/{api-errors.js → core/api-errors.js} +0 -0
- /package/dist/{card.d.ts → core/card.d.ts} +0 -0
- /package/dist/{card.js → core/card.js} +0 -0
- /package/dist/{handoff.d.ts → core/handoff.d.ts} +0 -0
- /package/dist/{memory-quality.d.ts → core/memory-quality.d.ts} +0 -0
- /package/dist/{physics-config.d.ts → core/physics-config.d.ts} +0 -0
- /package/dist/{physics-config.js → core/physics-config.js} +0 -0
- /package/dist/{project-remote.d.ts → core/project-remote.d.ts} +0 -0
- /package/dist/{prompt-recall.d.ts → core/prompt-recall.d.ts} +0 -0
- /package/dist/{salience.d.ts → core/salience.d.ts} +0 -0
- /package/dist/{dashboard-params.d.ts → dashboard/dashboard-params.d.ts} +0 -0
- /package/dist/{dashboard-params.js → dashboard/dashboard-params.js} +0 -0
- /package/dist/{dashboard-types.d.ts → dashboard/dashboard-types.d.ts} +0 -0
- /package/dist/{dashboard-types.js → dashboard/dashboard-types.js} +0 -0
- /package/dist/{dashboard.d.ts → dashboard/dashboard.d.ts} +0 -0
- /package/dist/{eval-stats.d.ts → eval/eval-stats.d.ts} +0 -0
- /package/dist/{cli → hooks}/hook-blocks.d.ts +0 -0
- /package/dist/{path-context.d.ts → search/path-context.d.ts} +0 -0
- /package/dist/{rrf.d.ts → search/rrf.d.ts} +0 -0
- /package/dist/{rrf.js → search/rrf.js} +0 -0
- /package/dist/{rate-limit.d.ts → server/rate-limit.d.ts} +0 -0
- /package/dist/{rate-limit.js → server/rate-limit.js} +0 -0
- /package/dist/{server-detect.d.ts → server/server-detect.d.ts} +0 -0
- /package/dist/{scope.d.ts → sharing/scope.d.ts} +0 -0
- /package/dist/{summary-dirty.js → store/summary-dirty.js} +0 -0
- /package/dist/{yaml.d.ts → store/yaml.d.ts} +0 -0
- /package/dist/{yaml.js → store/yaml.js} +0 -0
- /package/dist/{escape.d.ts → util/escape.d.ts} +0 -0
- /package/dist/{escape.js → util/escape.js} +0 -0
- /package/dist/{home-path.d.ts → util/home-path.d.ts} +0 -0
- /package/dist/{keyset.d.ts → util/keyset.d.ts} +0 -0
- /package/dist/{keyset.js → util/keyset.js} +0 -0
- /package/dist/{same-text.js → util/same-text.js} +0 -0
- /package/dist/{secret-detect.d.ts → util/secret-detect.d.ts} +0 -0
- /package/dist/{db → util}/sqlite-blocked.d.ts +0 -0
- /package/dist/{db → util}/sqlite-blocked.js +0 -0
- /package/dist/{tokenize.d.ts → util/tokenize.d.ts} +0 -0
- /package/dist/{tokenize.js → util/tokenize.js} +0 -0
- /package/dist/{transcript-tail.d.ts → util/transcript-tail.d.ts} +0 -0
- /package/dist/{transcript-tail.js → util/transcript-tail.js} +0 -0
- /package/dist/{write-budget.d.ts → util/write-budget.d.ts} +0 -0
- /package/dist/{write-budget.js → util/write-budget.js} +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Bounds on the scrypt work a bearer key check may start: how many derive at once, and how many one address starts for one key id.
|
|
2
|
+
import { HttpError } from '../util/http-util.js';
|
|
3
|
+
import { createRateLimiter } from './rate-limit.js';
|
|
4
|
+
// libuv runs scrypt on a pool of four threads by default, so two stay free for file and DNS work.
|
|
5
|
+
const MAX_IN_FLIGHT = 2;
|
|
6
|
+
// Four rounds of two, so a burst of unproved keys waits its turn and no wait is longer than four derivations.
|
|
7
|
+
const MAX_WAITING = 8;
|
|
8
|
+
// Room for a mistyped or rotated secret; a secret is 160 random bits, so this bounds CPU, not guessing.
|
|
9
|
+
const KEY_ADDRESS_BURST = 5;
|
|
10
|
+
// One more try every 12 s: past its burst, an address starts at most five derivations a minute for one key id.
|
|
11
|
+
const KEY_ADDRESS_TRIES_PER_SEC = 5 / 60;
|
|
12
|
+
export function keyCheckBounds(maxKeys) {
|
|
13
|
+
// A bucket idle for a full refill is back at its burst, so dropping it then gives nothing away.
|
|
14
|
+
const idleEvictMs = (KEY_ADDRESS_BURST / KEY_ADDRESS_TRIES_PER_SEC) * 1000;
|
|
15
|
+
const perKeyAddress = createRateLimiter({ ratePerSec: KEY_ADDRESS_TRIES_PER_SEC, burst: KEY_ADDRESS_BURST, idleEvictMs, maxKeys });
|
|
16
|
+
let inFlight = 0;
|
|
17
|
+
const waiting = [];
|
|
18
|
+
return {
|
|
19
|
+
admit(keyId, address) {
|
|
20
|
+
// Each answers in the words an existing limit uses: the request limit's for a full queue, the address's scrypt bucket's for spent tries.
|
|
21
|
+
if (inFlight >= MAX_IN_FLIGHT && waiting.length >= MAX_WAITING)
|
|
22
|
+
throw new HttpError(429, 'rate limit exceeded', 1);
|
|
23
|
+
if (!perKeyAddress.check(`${keyId}\u0000${address}`)) {
|
|
24
|
+
throw new HttpError(429, 'too many key checks from this address', perKeyAddress.retryAfterSec);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
async run(derive) {
|
|
28
|
+
if (inFlight < MAX_IN_FLIGHT)
|
|
29
|
+
inFlight++;
|
|
30
|
+
else
|
|
31
|
+
await new Promise((resolve) => { waiting.push(resolve); });
|
|
32
|
+
try {
|
|
33
|
+
return await derive();
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
// A waiter takes over this slot, so the count stays put across the handover and nothing slips in between.
|
|
37
|
+
const next = waiting.shift();
|
|
38
|
+
if (next)
|
|
39
|
+
next();
|
|
40
|
+
else
|
|
41
|
+
inFlight--;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=key-check-bounds.js.map
|
package/dist/server/lifecycle.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
import type {
|
|
3
|
-
import { type McpContext } from '../mcp/server.js';
|
|
4
|
-
import type { CallerProject } from '../prompt-hook.js';
|
|
2
|
+
import type { CallerProject } from '../api/prompt-hook.js';
|
|
5
3
|
import type { ResolvedServeOpts } from './types.js';
|
|
6
4
|
/** On a shared store, the caller's project from X-Hippo-Project and the comma-separated X-Hippo-Project-Aliases; any other store ignores both. */
|
|
7
5
|
export declare function callerProjectFromHeaders(req: IncomingMessage, hippoRoot: string): CallerProject | undefined;
|
|
8
|
-
export declare function mcpContextFor(ctx: Context, clientKey: string, autoSleep: McpContext['autoSleep'], project?: CallerProject): McpContext;
|
|
9
6
|
export declare function handleMcpPost(req: IncomingMessage, res: ServerResponse, opts: ResolvedServeOpts): Promise<void>;
|
|
10
7
|
export declare function handleMcpStream(req: IncomingMessage, res: ServerResponse, opts: ResolvedServeOpts, streamSlots: Map<string, number>): Promise<void>;
|
|
11
8
|
//# sourceMappingURL=mcp-http.d.ts.map
|
package/dist/server/mcp-http.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
// MCP over HTTP: POST /mcp and the GET /mcp/stream SSE keepalive.
|
|
2
|
-
import { envMcpSseHeartbeatMs, envMcpSseMaxAgeSec, envMcpSseMaxStreams } from '../env.js';
|
|
2
|
+
import { envMcpSseHeartbeatMs, envMcpSseMaxAgeSec, envMcpSseMaxStreams } from '../util/env.js';
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
|
-
import { isSharedStore } from '../config.js';
|
|
4
|
+
import { isSharedStore } from '../core/config.js';
|
|
5
5
|
import { handleMcpRequest, mcpErrorResponse } from '../mcp/server.js';
|
|
6
|
-
import { HttpError,
|
|
7
|
-
import { assertCallerProject } from '../project-identity.js';
|
|
6
|
+
import { HttpError, readBody, sendJson } from '../util/http-util.js';
|
|
7
|
+
import { assertCallerProject } from '../core/project-identity.js';
|
|
8
8
|
import { buildContextWithAuth, heartbeatVerdict, readAuthHeader, requireAuth } from './auth.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { isJsonString } from '../json.js';
|
|
9
|
+
import { clientLimitKey, subscriberKey } from './client-ip.js';
|
|
10
|
+
import { noteAccess } from './request.js';
|
|
11
|
+
import { isJsonString, isJsonObject } from '../util/json.js';
|
|
12
|
+
import { FINGERPRINT_HEX_CHARS } from '../util/token-text.js';
|
|
13
|
+
const DEFAULT_SSE_HEARTBEAT_MS = 60000;
|
|
14
|
+
const DEFAULT_SSE_MAX_AGE_SEC = 3600;
|
|
12
15
|
/**
|
|
13
16
|
* Build a per-client key for MCP state isolation under HTTP-MCP. Used by
|
|
14
17
|
* mcp/server.ts to scope `lastRecalledIds` to the calling client so two
|
|
@@ -23,9 +26,9 @@ import { isJsonString } from '../json.js';
|
|
|
23
26
|
function buildMcpClientKey(req) {
|
|
24
27
|
const auth = readAuthHeader(req);
|
|
25
28
|
const tokenHash = auth.kind === 'bearer'
|
|
26
|
-
? createHash('sha256').update(auth.token).digest('hex').slice(0,
|
|
29
|
+
? createHash('sha256').update(auth.token).digest('hex').slice(0, FINGERPRINT_HEX_CHARS)
|
|
27
30
|
: 'noauth';
|
|
28
|
-
const addr = req.socket.remoteAddress ?? 'unknown';
|
|
31
|
+
const addr = subscriberKey(req.socket.remoteAddress ?? 'unknown');
|
|
29
32
|
return `http:${tokenHash}:${addr}`;
|
|
30
33
|
}
|
|
31
34
|
// ── MCP-over-HTTP/SSE transport ──
|
|
@@ -77,7 +80,7 @@ export function callerProjectFromHeaders(req, hippoRoot) {
|
|
|
77
80
|
assertCallerProject({ name, aliases });
|
|
78
81
|
return { name, legacyName: name, aliases };
|
|
79
82
|
}
|
|
80
|
-
|
|
83
|
+
function mcpContextFor(ctx, clientKey, autoSleep, project) {
|
|
81
84
|
const mcpCtx = {
|
|
82
85
|
hippoRoot: ctx.hippoRoot,
|
|
83
86
|
tenantId: ctx.tenantId,
|
|
@@ -104,6 +107,7 @@ export async function handleMcpPost(req, res, opts) {
|
|
|
104
107
|
// pull tenant from HIPPO_TENANT, dropping a valid Bearer for tenant B
|
|
105
108
|
// back to whatever the env says.
|
|
106
109
|
const ctx = await buildContextWithAuth(req, opts);
|
|
110
|
+
noteAccess(req, { tenant: ctx.tenantId });
|
|
107
111
|
const project = callerProjectFromHeaders(req, ctx.hippoRoot);
|
|
108
112
|
const raw = await readBody(req);
|
|
109
113
|
let mcpReq;
|
|
@@ -113,7 +117,7 @@ export async function handleMcpPost(req, res, opts) {
|
|
|
113
117
|
catch {
|
|
114
118
|
throw new HttpError(400, 'invalid JSON-RPC body');
|
|
115
119
|
}
|
|
116
|
-
if (!
|
|
120
|
+
if (!isJsonObject(mcpReq) || !isJsonString(mcpReq.method)) {
|
|
117
121
|
throw new HttpError(400, 'JSON-RPC body must include a method string');
|
|
118
122
|
}
|
|
119
123
|
// SAFETY: validated above as a plain JSON object carrying a string method;
|
|
@@ -125,7 +129,7 @@ export async function handleMcpPost(req, res, opts) {
|
|
|
125
129
|
mcpRes = await handleMcpRequest(rpcReq, mcpContextFor(ctx, buildMcpClientKey(req), opts.autoSleep, project));
|
|
126
130
|
}
|
|
127
131
|
catch (err) {
|
|
128
|
-
mcpRes = mcpErrorResponse(rpcReq.id, err
|
|
132
|
+
mcpRes = mcpErrorResponse(rpcReq.id, err);
|
|
129
133
|
}
|
|
130
134
|
if (mcpRes === null) {
|
|
131
135
|
// Notification — no body, 202 Accepted.
|
|
@@ -141,8 +145,8 @@ const DEFAULT_MAX_STREAMS_PER_CLIENT = 8;
|
|
|
141
145
|
function streamSlotKey(req) {
|
|
142
146
|
const auth = readAuthHeader(req);
|
|
143
147
|
if (auth.kind === 'bearer')
|
|
144
|
-
return `key:${createHash('sha256').update(auth.token).digest('hex').slice(0,
|
|
145
|
-
return `ip:${
|
|
148
|
+
return `key:${createHash('sha256').update(auth.token).digest('hex').slice(0, FINGERPRINT_HEX_CHARS)}`;
|
|
149
|
+
return `ip:${clientLimitKey(req)}`;
|
|
146
150
|
}
|
|
147
151
|
/** Takes a stream slot or throws 429; the slot is released once, when the response closes. */
|
|
148
152
|
function acquireStreamSlot(req, res, slots) {
|
|
@@ -181,8 +185,11 @@ export async function handleMcpStream(req, res, opts, streamSlots) {
|
|
|
181
185
|
// with reason='max_age_exceeded' when reached.
|
|
182
186
|
// - MCP_SSE_HEARTBEAT_MS (default 60000) lets tests run with a short
|
|
183
187
|
// interval without waiting a full minute.
|
|
184
|
-
|
|
185
|
-
|
|
188
|
+
keepStreamAlive(req, res, opts);
|
|
189
|
+
}
|
|
190
|
+
function keepStreamAlive(req, res, opts) {
|
|
191
|
+
const heartbeatMs = envMcpSseHeartbeatMs() ?? DEFAULT_SSE_HEARTBEAT_MS;
|
|
192
|
+
const maxAgeMs = (envMcpSseMaxAgeSec() ?? DEFAULT_SSE_MAX_AGE_SEC) * 1000;
|
|
186
193
|
const startedAt = Date.now();
|
|
187
194
|
let closed = false;
|
|
188
195
|
let checking = false;
|
|
@@ -190,14 +197,7 @@ export async function handleMcpStream(req, res, opts, streamSlots) {
|
|
|
190
197
|
if (closed)
|
|
191
198
|
return;
|
|
192
199
|
closed = true;
|
|
193
|
-
|
|
194
|
-
res.write(`event: closed\ndata: ${JSON.stringify({ reason })}\n\n`);
|
|
195
|
-
}
|
|
196
|
-
catch { /* socket already gone */ }
|
|
197
|
-
try {
|
|
198
|
-
res.end();
|
|
199
|
-
}
|
|
200
|
-
catch { /* socket already gone */ }
|
|
200
|
+
endStreamWithReason(res, reason);
|
|
201
201
|
};
|
|
202
202
|
const ping = setInterval(() => {
|
|
203
203
|
if (closed) {
|
|
@@ -239,4 +239,14 @@ export async function handleMcpStream(req, res, opts, streamSlots) {
|
|
|
239
239
|
clearInterval(ping);
|
|
240
240
|
});
|
|
241
241
|
}
|
|
242
|
+
function endStreamWithReason(res, reason) {
|
|
243
|
+
try {
|
|
244
|
+
res.write(`event: closed\ndata: ${JSON.stringify({ reason })}\n\n`);
|
|
245
|
+
}
|
|
246
|
+
catch { /* socket already gone */ }
|
|
247
|
+
try {
|
|
248
|
+
res.end();
|
|
249
|
+
}
|
|
250
|
+
catch { /* socket already gone */ }
|
|
251
|
+
}
|
|
242
252
|
//# sourceMappingURL=mcp-http.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { HippoStore } from '../store/index.js';
|
|
2
|
+
export type ReadyProbe = () => Promise<boolean>;
|
|
3
|
+
/** The shared probe for a served store, so every request to that server draws on one remembered answer. */
|
|
4
|
+
export declare function readyProbeFor(store: HippoStore, readiness: {
|
|
5
|
+
ping(): Promise<void>;
|
|
6
|
+
}, now?: () => number): ReadyProbe;
|
|
7
|
+
//# sourceMappingURL=ready.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SERVER_DB_WAIT_MS, runWithRequestStores } from '../db/index.js';
|
|
2
|
+
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
3
|
+
// A prober must never see a 429, so the store read is bounded by remembering its answer instead of rate-limiting the route.
|
|
4
|
+
const READY_WINDOW_MS = 1000;
|
|
5
|
+
/** True when the store answered; one read per window whatever the caller count, and a failed read is remembered for the same window. */
|
|
6
|
+
function createReadyProbe(readiness, now = Date.now) {
|
|
7
|
+
let answer;
|
|
8
|
+
let inFlight;
|
|
9
|
+
async function read() {
|
|
10
|
+
let ok = true;
|
|
11
|
+
try {
|
|
12
|
+
await runWithRequestStores(() => readiness.ping(), { busyWaitMs: SERVER_DB_WAIT_MS });
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
log.warn(`GET /ready: the store did not answer: ${errorMessage(err)}`, errorFields(err));
|
|
16
|
+
ok = false;
|
|
17
|
+
}
|
|
18
|
+
answer = { at: now(), ok };
|
|
19
|
+
return ok;
|
|
20
|
+
}
|
|
21
|
+
return () => {
|
|
22
|
+
if (answer !== undefined && now() - answer.at < READY_WINDOW_MS)
|
|
23
|
+
return Promise.resolve(answer.ok);
|
|
24
|
+
inFlight ??= read().finally(() => { inFlight = undefined; });
|
|
25
|
+
return inFlight;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const probes = new WeakMap();
|
|
29
|
+
/** The shared probe for a served store, so every request to that server draws on one remembered answer. */
|
|
30
|
+
export function readyProbeFor(store, readiness, now = Date.now) {
|
|
31
|
+
let probe = probes.get(store);
|
|
32
|
+
if (probe === undefined) {
|
|
33
|
+
probe = createReadyProbe(readiness, now);
|
|
34
|
+
probes.set(store, probe);
|
|
35
|
+
}
|
|
36
|
+
return probe;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=ready.js.map
|
package/dist/server/request.d.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
-
/** The caller's `X-Request-Id` when it is a short plain token, else a fresh UUID. */
|
|
3
|
-
export declare function resolveRequestId(header: string | string[] | undefined): string;
|
|
4
2
|
/** One line per failed request; 4xx is the caller's mistake, a busy 503 is back-pressure and a 501 is a route not on this store, so none logs as an error. */
|
|
5
|
-
export declare function logRequestFailure<E>(req: IncomingMessage, err: E,
|
|
3
|
+
export declare function logRequestFailure<E>(req: IncomingMessage, err: E, status: number): void;
|
|
6
4
|
/** The status and client message for a failed request; a held write lock is a retryable 503, never a 500. */
|
|
7
5
|
export declare function replyFor<E>(err: E): {
|
|
8
6
|
status: number;
|
|
9
7
|
message: string;
|
|
10
8
|
};
|
|
9
|
+
/** What the route layer learned about a request, for its access line. */
|
|
10
|
+
interface AccessNote {
|
|
11
|
+
route?: string;
|
|
12
|
+
tenant?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Names the matched route (the table's pattern, never the path sent) or the caller's tenant for the request's access line. */
|
|
15
|
+
export declare function noteAccess(req: IncomingMessage, note: AccessNote): void;
|
|
16
|
+
/** The request's id, after stamping the headers every reply carries and starting the slow-request watchdog and the access line. */
|
|
17
|
+
export declare function openRequest(req: IncomingMessage, res: ServerResponse, slowWarnMs?: number): string;
|
|
11
18
|
export declare function sendError(res: ServerResponse, status: number, message: string): void;
|
|
12
19
|
interface ParsedRoute {
|
|
13
20
|
method: string;
|
|
@@ -16,7 +23,6 @@ interface ParsedRoute {
|
|
|
16
23
|
}
|
|
17
24
|
export declare function parseRequest(req: IncomingMessage): ParsedRoute;
|
|
18
25
|
export declare function matchPath(pattern: string, path: string): Record<string, string> | null;
|
|
19
|
-
export declare const requestIds: WeakMap<IncomingMessage, string>;
|
|
20
26
|
/**
|
|
21
27
|
* Reject URL-encoded slashes in path segments BEFORE the URL parser decodes
|
|
22
28
|
* them — otherwise `%2F` becomes `/`, path-split runs, and the route either
|
package/dist/server/request.js
CHANGED
|
@@ -1,29 +1,82 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { isStoreBusy, STORE_BUSY_MESSAGE } from '../db.js';
|
|
3
|
-
import { errorFields, log } from '../log.js';
|
|
4
|
-
import { HttpError, mapApiError, sendJson } from '../http-util.js';
|
|
2
|
+
import { isStoreBusy, STORE_BUSY_MESSAGE } from '../db/index.js';
|
|
3
|
+
import { errorFields, errorMessage, log } from '../util/log.js';
|
|
4
|
+
import { HttpError, mapApiError, sendJson } from '../util/http-util.js';
|
|
5
5
|
// The caller's id lands in a response header and in logs, so only a short plain token is echoed back.
|
|
6
6
|
const REQUEST_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
7
7
|
/** The caller's `X-Request-Id` when it is a short plain token, else a fresh UUID. */
|
|
8
|
-
|
|
8
|
+
function resolveRequestId(header) {
|
|
9
9
|
const value = Array.isArray(header) ? undefined : header;
|
|
10
10
|
return value && REQUEST_ID_RE.test(value) ? value : randomUUID();
|
|
11
11
|
}
|
|
12
12
|
/** One line per failed request; 4xx is the caller's mistake, a busy 503 is back-pressure and a 501 is a route not on this store, so none logs as an error. */
|
|
13
|
-
export function logRequestFailure(req, err,
|
|
14
|
-
const message =
|
|
13
|
+
export function logRequestFailure(req, err, status) {
|
|
14
|
+
const message = errorMessage(err);
|
|
15
15
|
const line = `${req.method ?? 'GET'} ${(req.url ?? '/').split('?')[0]} failed: ${message}`;
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
// A 5xx that tells the caller when to retry is back-pressure too.
|
|
17
|
+
if (isStoreBusy(err) || (status >= 500 && err instanceof HttpError && err.retryAfterSec !== undefined))
|
|
18
|
+
log.warn(line, { status });
|
|
18
19
|
else if (status >= 500 && status !== 501)
|
|
19
|
-
log.error(line, {
|
|
20
|
+
log.error(line, { status, ...errorFields(err) });
|
|
20
21
|
else
|
|
21
|
-
log.info(line, {
|
|
22
|
+
log.info(line, { status });
|
|
22
23
|
}
|
|
23
24
|
/** The status and client message for a failed request; a held write lock is a retryable 503, never a 500. */
|
|
24
25
|
export function replyFor(err) {
|
|
25
26
|
return isStoreBusy(err) ? { status: 503, message: STORE_BUSY_MESSAGE } : mapApiError(err);
|
|
26
27
|
}
|
|
28
|
+
// Above the 30 s body deadline and the 5 s resolver deadline, so a request those govern is answered before it is called slow.
|
|
29
|
+
const SLOW_REQUEST_WARN_MS = 60_000;
|
|
30
|
+
/** Logs one warn when `res` has sent nothing after `afterMs`. It never ends the request or touches the reply; the timer goes when the reply finishes or the socket closes. */
|
|
31
|
+
function watchSlowRequest(req, res, requestId, afterMs = SLOW_REQUEST_WARN_MS) {
|
|
32
|
+
const startedAt = Date.now();
|
|
33
|
+
const timer = setTimeout(() => {
|
|
34
|
+
// A reply already under way is a stream doing its job, not a stuck request.
|
|
35
|
+
if (res.headersSent)
|
|
36
|
+
return;
|
|
37
|
+
log.warn(`${req.method ?? 'GET'} ${(req.url ?? '/').split('?')[0]} is still running`, { requestId, elapsedMs: Date.now() - startedAt });
|
|
38
|
+
}, afterMs);
|
|
39
|
+
// The watchdog alone must never keep the process alive.
|
|
40
|
+
timer.unref();
|
|
41
|
+
const clear = () => clearTimeout(timer);
|
|
42
|
+
res.once('finish', clear);
|
|
43
|
+
res.once('close', clear);
|
|
44
|
+
}
|
|
45
|
+
const accessNotes = new WeakMap();
|
|
46
|
+
// A path that matched no route is caller data, so the access line never repeats it.
|
|
47
|
+
const UNMATCHED_ROUTE = 'unmatched';
|
|
48
|
+
/** Names the matched route (the table's pattern, never the path sent) or the caller's tenant for the request's access line. */
|
|
49
|
+
export function noteAccess(req, note) {
|
|
50
|
+
const held = accessNotes.get(req);
|
|
51
|
+
if (held)
|
|
52
|
+
Object.assign(held, note);
|
|
53
|
+
}
|
|
54
|
+
/** One info line per finished request. A path id and a query string can both hold caller data, so the line carries neither. */
|
|
55
|
+
function logAccessWhenFinished(req, res, requestId) {
|
|
56
|
+
const note = {};
|
|
57
|
+
accessNotes.set(req, note);
|
|
58
|
+
const startedAt = performance.now();
|
|
59
|
+
res.once('finish', () => {
|
|
60
|
+
log.info('request', {
|
|
61
|
+
requestId,
|
|
62
|
+
method: req.method ?? 'GET',
|
|
63
|
+
route: note.route ?? UNMATCHED_ROUTE,
|
|
64
|
+
status: res.statusCode,
|
|
65
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
66
|
+
tenant: note.tenant,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** The request's id, after stamping the headers every reply carries and starting the slow-request watchdog and the access line. */
|
|
71
|
+
export function openRequest(req, res, slowWarnMs) {
|
|
72
|
+
const requestId = resolveRequestId(req.headers['x-request-id']);
|
|
73
|
+
res.setHeader('X-Request-Id', requestId);
|
|
74
|
+
// Memory text is caller-written, so no browser may guess a reply into HTML or script.
|
|
75
|
+
res.setHeader('X-Content-Type-Options', 'nosniff');
|
|
76
|
+
watchSlowRequest(req, res, requestId, slowWarnMs);
|
|
77
|
+
logAccessWhenFinished(req, res, requestId);
|
|
78
|
+
return requestId;
|
|
79
|
+
}
|
|
27
80
|
export function sendError(res, status, message) {
|
|
28
81
|
sendJson(res, status, { error: message });
|
|
29
82
|
}
|
|
@@ -82,8 +135,6 @@ export function matchPath(pattern, path) {
|
|
|
82
135
|
}
|
|
83
136
|
return params;
|
|
84
137
|
}
|
|
85
|
-
// The auth helpers only see the request, so its id rides here for their log lines.
|
|
86
|
-
export const requestIds = new WeakMap();
|
|
87
138
|
/**
|
|
88
139
|
* Reject URL-encoded slashes in path segments BEFORE the URL parser decodes
|
|
89
140
|
* them — otherwise `%2F` becomes `/`, path-split runs, and the route either
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AddonRoute, ResolvedServeOpts, RouteRequest } from './types.js';
|
|
2
|
+
import type { JsonValue } from '../util/json.js';
|
|
3
|
+
export declare function isPublicRoute(method: string, path: string): boolean;
|
|
4
|
+
/** Run the first /v1 route whose method and path match. */
|
|
5
|
+
export declare function dispatchV1Route(r: RouteRequest, method: string, path: string): Promise<boolean>;
|
|
6
|
+
/** Boot-time check: an add-on path must be plain, unique and not one core serves, so no add-on shadows a core route or hides from dispatch. */
|
|
7
|
+
export declare function assertAddonRoutes(routes: readonly AddonRoute[]): void;
|
|
8
|
+
/** Boot-time check and serialization: a public path that a core GET route serves would open that route to anyone. */
|
|
9
|
+
export declare function assertPublicJson(publicJson: Readonly<Record<string, JsonValue>>): ReadonlyMap<string, string>;
|
|
10
|
+
/** Core authenticates and parses before the handler runs, so an add-on route gets the same 401, 400 and 501 as a core one. */
|
|
11
|
+
export declare function dispatchAddonRoute({ req, res, opts }: RouteRequest, method: string, path: string): Promise<boolean>;
|
|
12
|
+
/** No auth, body read or store access, so a caller with no key gets it under any store. */
|
|
13
|
+
export declare function dispatchPublicJson({ req, res, opts }: RouteRequest, method: string, path: string): boolean;
|
|
14
|
+
export declare function assertSqliteStore(opts: ResolvedServeOpts): void;
|
|
15
|
+
//# sourceMappingURL=route-table.d.ts.map
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { withSqliteOffLoop } from '../db/index.js';
|
|
2
|
+
import { hasGroup } from '../store/index.js';
|
|
3
|
+
import { runsOffLoop } from '../store/sqlite/worker-store.js';
|
|
4
|
+
import { HttpError, JSON_HEADERS, sendJson, STORE_NOT_PORTED_MESSAGE } from '../util/http-util.js';
|
|
5
|
+
import { buildContextWithAuth, requireAuth } from './auth.js';
|
|
6
|
+
import { matchPath, noteAccess } from './request.js';
|
|
7
|
+
import { handleApproveQuarantine, handleCreateAuthKey, handleListAudit, handleListAuthKeys, handleListQuarantine, handleRejectQuarantine, handleRevokeAuthKey } from './routes/admin.js';
|
|
8
|
+
import { handleCloseCustomerNote, handleCreateCustomerNote, handleGetCustomerNote, handleListCustomerNotes, handleSupersedeCustomerNote } from './routes/customer-notes.js';
|
|
9
|
+
import { handleCloseDecision, handleCreateDecision, handleGetDecision, handleListDecisions, handleSupersedeDecision } from './routes/decisions.js';
|
|
10
|
+
import { handleCloseIncident, handleCreateIncident, handleGetIncident, handleListIncidents, handleResolveIncident } from './routes/incidents.js';
|
|
11
|
+
import { handleApplyOutcome, handleArchiveMemory, handleCreateMemory, handleForgetMemory, handleGetGraph, handlePromoteMemory, handleSleep, handleSupersedeMemory } from './routes/memories.js';
|
|
12
|
+
import { handleClosePolicy, handleCreatePolicy, handleGetPolicy, handleListPolicies, handlePoliciesAsOf, handleSupersedePolicy } from './routes/policies.js';
|
|
13
|
+
import { handleClosePrediction, handleCreatePrediction, handleGetPrediction, handleListPredictions, handlePredictionStats } from './routes/predictions.js';
|
|
14
|
+
import { handleCloseProcess, handleCreateProcess, handleGetProcess, handleListProcesses, handleSupersedeProcess } from './routes/processes.js';
|
|
15
|
+
import { handleCloseProjectBrief, handleCreateProjectBrief, handleGetProjectBrief, handleListProjectBriefs, handleRefreshProjectBrief, handleSupersedeProjectBrief } from './routes/project-briefs.js';
|
|
16
|
+
import { handleAssembleSession, handleDrillRecall, handleGetContext, handleRecallMemories } from './routes/recall.js';
|
|
17
|
+
import { handleCloseSkill, handleCreateSkill, handleExportSkills, handleGetSkill, handleListSkills, handleSupersedeSkill } from './routes/skills.js';
|
|
18
|
+
import { parseJsonBody } from './validation.js';
|
|
19
|
+
// Review patch #2: explicit allow-list for unauthenticated /v1/* routes.
|
|
20
|
+
// New unauth routes MUST be added here AND get a corresponding entry in
|
|
21
|
+
// tests/server-bearer-lockdown.test.ts. Do not gate auth elsewhere by
|
|
22
|
+
// `path.startsWith` — pattern-positional auth is bypass-by-accident.
|
|
23
|
+
//
|
|
24
|
+
// The route handlers consult `isPublicRoute` before invoking
|
|
25
|
+
// `buildContextWithAuth` / `requireAuth`. Adding a route here without
|
|
26
|
+
// adding the corresponding `isPublicRoute` short-circuit in a handler is
|
|
27
|
+
// a no-op (auth still applies), so the failure mode is fail-closed.
|
|
28
|
+
// The only other unauthenticated paths are ServeOpts.publicJson's: GET only, checked at boot by assertPublicJson.
|
|
29
|
+
const PUBLIC_ROUTES = new Set([
|
|
30
|
+
'POST /v1/connectors/slack/events',
|
|
31
|
+
'POST /v1/connectors/github/events',
|
|
32
|
+
]);
|
|
33
|
+
export function isPublicRoute(method, path) {
|
|
34
|
+
return PUBLIC_ROUTES.has(`${method} ${path}`);
|
|
35
|
+
}
|
|
36
|
+
/** The /v1 routes in dispatch order; the first entry whose method and path match handles the request. */
|
|
37
|
+
const V1_ROUTES = [
|
|
38
|
+
{ method: 'POST', path: '/v1/memories', storeReady: 'entryWrites', loop: 'off', handler: handleCreateMemory },
|
|
39
|
+
{ method: 'GET', path: '/v1/graph', storeReady: 'graphReads', loop: 'off', handler: handleGetGraph },
|
|
40
|
+
{ method: 'GET', path: '/v1/memories', storeReady: 'base', loop: 'off', handler: handleRecallMemories },
|
|
41
|
+
{ method: 'GET', pattern: '/v1/sessions/:id/assemble', storeReady: 'dagReads', loop: 'off', handler: handleAssembleSession },
|
|
42
|
+
{ method: 'GET', pattern: '/v1/recall/drill/:id', storeReady: 'dagReads', handler: handleDrillRecall },
|
|
43
|
+
{ method: 'POST', pattern: '/v1/memories/:id/archive', storeReady: 'entryWrites', loop: 'off', handler: handleArchiveMemory },
|
|
44
|
+
{ method: 'POST', pattern: '/v1/memories/:id/supersede', storeReady: 'entryWrites', loop: 'off', handler: handleSupersedeMemory },
|
|
45
|
+
{ method: 'POST', pattern: '/v1/memories/:id/promote', sqliteOnly: 'copies a memory between the two local hippo.db files', handler: handlePromoteMemory },
|
|
46
|
+
{ method: 'DELETE', pattern: '/v1/memories/:id', storeReady: 'entryWrites', loop: 'off', handler: handleForgetMemory },
|
|
47
|
+
{ method: 'POST', path: '/v1/outcome', storeReady: 'entryWrites', handler: handleApplyOutcome },
|
|
48
|
+
{ method: 'GET', path: '/v1/context', storeReady: 'contextReads', handler: handleGetContext },
|
|
49
|
+
{ method: 'POST', path: '/v1/sleep', sqliteOnly: 'consolidates every tenant under the local hippo root in this process', handler: handleSleep },
|
|
50
|
+
{ method: 'POST', path: '/v1/auth/keys', storeReady: 'keyWrites', loop: 'off', handler: handleCreateAuthKey },
|
|
51
|
+
{ method: 'GET', path: '/v1/auth/keys', storeReady: 'keyWrites', loop: 'off', handler: handleListAuthKeys },
|
|
52
|
+
{ method: 'DELETE', pattern: '/v1/auth/keys/:keyId', storeReady: 'keyAudit', loop: 'off', handler: handleRevokeAuthKey },
|
|
53
|
+
{ method: 'GET', path: '/v1/quarantine', storeReady: 'quarantine', loop: 'off', handler: handleListQuarantine },
|
|
54
|
+
{ method: 'POST', pattern: '/v1/quarantine/:id/approve', storeReady: 'quarantine', loop: 'off', handler: handleApproveQuarantine },
|
|
55
|
+
{ method: 'POST', pattern: '/v1/quarantine/:id/reject', storeReady: 'quarantine', loop: 'off', handler: handleRejectQuarantine },
|
|
56
|
+
{ method: 'GET', path: '/v1/audit', storeReady: 'auditLog', loop: 'off', handler: handleListAudit },
|
|
57
|
+
{ method: 'POST', path: '/v1/predictions', storeReady: 'predictions', loop: 'off', handler: handleCreatePrediction },
|
|
58
|
+
{ method: 'GET', path: '/v1/predictions', storeReady: 'predictions', loop: 'off', handler: handleListPredictions },
|
|
59
|
+
{ method: 'GET', path: '/v1/predictions/stats', storeReady: 'predictions', loop: 'off', handler: handlePredictionStats },
|
|
60
|
+
{ method: 'GET', regex: /^\/v1\/predictions\/(\d+)$/, storeReady: 'predictions', loop: 'off', handler: handleGetPrediction },
|
|
61
|
+
{ method: 'POST', regex: /^\/v1\/predictions\/(\d+)\/close$/, storeReady: 'predictions', loop: 'off', handler: handleClosePrediction },
|
|
62
|
+
{ method: 'POST', path: '/v1/decisions', storeReady: 'objects', handler: handleCreateDecision },
|
|
63
|
+
{ method: 'GET', path: '/v1/decisions', storeReady: 'objects', handler: handleListDecisions },
|
|
64
|
+
{ method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeDecision },
|
|
65
|
+
{ method: 'POST', regex: /^\/v1\/decisions\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseDecision },
|
|
66
|
+
{ method: 'GET', regex: /^\/v1\/decisions\/(\d+)$/, storeReady: 'objects', handler: handleGetDecision },
|
|
67
|
+
{ method: 'POST', path: '/v1/incidents', storeReady: 'objects', handler: handleCreateIncident },
|
|
68
|
+
{ method: 'GET', path: '/v1/incidents', storeReady: 'objects', handler: handleListIncidents },
|
|
69
|
+
{ method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/resolve$/, storeReady: 'objects', handler: handleResolveIncident },
|
|
70
|
+
{ method: 'POST', regex: /^\/v1\/incidents\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseIncident },
|
|
71
|
+
{ method: 'GET', regex: /^\/v1\/incidents\/(\d+)$/, storeReady: 'objects', handler: handleGetIncident },
|
|
72
|
+
{ method: 'POST', path: '/v1/processes', storeReady: 'objects', handler: handleCreateProcess },
|
|
73
|
+
{ method: 'GET', path: '/v1/processes', storeReady: 'objects', handler: handleListProcesses },
|
|
74
|
+
{ method: 'POST', regex: /^\/v1\/processes\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeProcess },
|
|
75
|
+
{ method: 'POST', regex: /^\/v1\/processes\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseProcess },
|
|
76
|
+
{ method: 'GET', regex: /^\/v1\/processes\/(\d+)$/, storeReady: 'objects', handler: handleGetProcess },
|
|
77
|
+
{ method: 'POST', path: '/v1/policies', storeReady: 'objects', handler: handleCreatePolicy },
|
|
78
|
+
{ method: 'GET', path: '/v1/policies', storeReady: 'objects', handler: handleListPolicies },
|
|
79
|
+
{ method: 'GET', path: '/v1/policies/asof', storeReady: 'objects', handler: handlePoliciesAsOf },
|
|
80
|
+
{ method: 'POST', regex: /^\/v1\/policies\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedePolicy },
|
|
81
|
+
{ method: 'POST', regex: /^\/v1\/policies\/(\d+)\/close$/, storeReady: 'objects', handler: handleClosePolicy },
|
|
82
|
+
{ method: 'GET', regex: /^\/v1\/policies\/(\d+)$/, storeReady: 'objects', handler: handleGetPolicy },
|
|
83
|
+
{ method: 'POST', path: '/v1/skills', storeReady: 'objects', handler: handleCreateSkill },
|
|
84
|
+
{ method: 'GET', path: '/v1/skills', storeReady: 'objects', handler: handleListSkills },
|
|
85
|
+
{ method: 'GET', path: '/v1/skills/export', storeReady: 'objects', handler: handleExportSkills },
|
|
86
|
+
{ method: 'POST', regex: /^\/v1\/skills\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeSkill },
|
|
87
|
+
{ method: 'POST', regex: /^\/v1\/skills\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseSkill },
|
|
88
|
+
{ method: 'GET', regex: /^\/v1\/skills\/(\d+)$/, storeReady: 'objects', handler: handleGetSkill },
|
|
89
|
+
{ method: 'POST', path: '/v1/project-briefs', storeReady: 'objects', handler: handleCreateProjectBrief },
|
|
90
|
+
{ method: 'GET', path: '/v1/project-briefs', storeReady: 'objects', handler: handleListProjectBriefs },
|
|
91
|
+
{ method: 'POST', path: '/v1/project-briefs/refresh', storeReady: 'objects', handler: handleRefreshProjectBrief },
|
|
92
|
+
{ method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeProjectBrief },
|
|
93
|
+
{ method: 'POST', regex: /^\/v1\/project-briefs\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseProjectBrief },
|
|
94
|
+
{ method: 'GET', regex: /^\/v1\/project-briefs\/(\d+)$/, storeReady: 'objects', handler: handleGetProjectBrief },
|
|
95
|
+
{ method: 'POST', path: '/v1/customer-notes', storeReady: 'objects', handler: handleCreateCustomerNote },
|
|
96
|
+
{ method: 'GET', path: '/v1/customer-notes', storeReady: 'objects', handler: handleListCustomerNotes },
|
|
97
|
+
{ method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/supersede$/, storeReady: 'objects', handler: handleSupersedeCustomerNote },
|
|
98
|
+
{ method: 'POST', regex: /^\/v1\/customer-notes\/(\d+)\/close$/, storeReady: 'objects', handler: handleCloseCustomerNote },
|
|
99
|
+
{ method: 'GET', regex: /^\/v1\/customer-notes\/(\d+)$/, storeReady: 'objects', handler: handleGetCustomerNote },
|
|
100
|
+
];
|
|
101
|
+
/** The route's handler bound to this request's path params, or null when method or path differ. The matcher runs before the
|
|
102
|
+
* method check, as the inline route blocks did, so a malformed `%` escape still throws from matchPath on any method. */
|
|
103
|
+
function routeMatches(route, method, path) {
|
|
104
|
+
if ('path' in route)
|
|
105
|
+
return method === route.method && path === route.path ? route.handler : null;
|
|
106
|
+
if ('pattern' in route) {
|
|
107
|
+
const params = matchPath(route.pattern, path);
|
|
108
|
+
return method === route.method && params ? (r) => route.handler(r, params) : null;
|
|
109
|
+
}
|
|
110
|
+
const match = path.match(route.regex);
|
|
111
|
+
return method === route.method && match ? (r) => route.handler(r, match) : null;
|
|
112
|
+
}
|
|
113
|
+
/** The route as the access line names it; a regex route reads as its pattern would, so no line carries a caller's id. */
|
|
114
|
+
function routeLabel(route) {
|
|
115
|
+
if ('path' in route)
|
|
116
|
+
return route.path;
|
|
117
|
+
if ('pattern' in route)
|
|
118
|
+
return route.pattern;
|
|
119
|
+
return route.regex.source.replace(/^\^|\$$/g, '').replaceAll('\\/', '/').replaceAll('(\\d+)', ':id');
|
|
120
|
+
}
|
|
121
|
+
/** Run the first /v1 route whose method and path match. */
|
|
122
|
+
export async function dispatchV1Route(r, method, path) {
|
|
123
|
+
for (const route of V1_ROUTES) {
|
|
124
|
+
const run = routeMatches(route, method, path);
|
|
125
|
+
if (run === null)
|
|
126
|
+
continue;
|
|
127
|
+
noteAccess(r.req, { route: routeLabel(route) });
|
|
128
|
+
await refuseUnportedRoute(r.req, r.opts, route.storeReady);
|
|
129
|
+
// Only a store with worker threads has moved the route's SQLite work; under any other the handler still opens hippo.db itself.
|
|
130
|
+
await (route.loop === 'off' && runsOffLoop(r.opts.store) ? withSqliteOffLoop(() => run(r)) : run(r));
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const PLAIN_SEGMENT_RE = /^[A-Za-z0-9._~-]+$/;
|
|
136
|
+
function isPlainV1Path(path) {
|
|
137
|
+
return path.startsWith('/v1/') && new URL(path, 'http://h').pathname === path
|
|
138
|
+
&& path.slice('/v1/'.length).split('/').every((segment) => PLAIN_SEGMENT_RE.test(segment));
|
|
139
|
+
}
|
|
140
|
+
// A plain path never holds a `%`, so matchPath cannot throw here.
|
|
141
|
+
function isCorePath(method, path) {
|
|
142
|
+
return PUBLIC_ROUTES.has(`${method} ${path}`) || V1_ROUTES.some((route) => routeMatches(route, method, path) !== null);
|
|
143
|
+
}
|
|
144
|
+
/** Boot-time check: an add-on path must be plain, unique and not one core serves, so no add-on shadows a core route or hides from dispatch. */
|
|
145
|
+
export function assertAddonRoutes(routes) {
|
|
146
|
+
const seen = new Set();
|
|
147
|
+
for (const { path } of routes) {
|
|
148
|
+
if (!isPlainV1Path(path))
|
|
149
|
+
throw new Error(`add-on route '${path}' is not a plain /v1/ path (segments use A-Z a-z 0-9 . _ ~ -)`);
|
|
150
|
+
if (seen.has(path))
|
|
151
|
+
throw new Error(`add-on route '${path}' is registered twice`);
|
|
152
|
+
if (isCorePath('POST', path))
|
|
153
|
+
throw new Error(`add-on route '${path}' is already served by core`);
|
|
154
|
+
seen.add(path);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const PUBLIC_JSON_MAX_BYTES = 64 * 1024;
|
|
158
|
+
/** Boot-time check and serialization: a public path that a core GET route serves would open that route to anyone. */
|
|
159
|
+
export function assertPublicJson(publicJson) {
|
|
160
|
+
const bodies = new Map();
|
|
161
|
+
for (const [path, value] of Object.entries(publicJson)) {
|
|
162
|
+
if (!isPlainV1Path(path))
|
|
163
|
+
throw new Error(`public JSON path '${path}' is not a plain /v1/ path (segments use A-Z a-z 0-9 . _ ~ -)`);
|
|
164
|
+
if (isCorePath('GET', path))
|
|
165
|
+
throw new Error(`public JSON path '${path}' is already served by core`);
|
|
166
|
+
const text = JSON.stringify(value);
|
|
167
|
+
if (text === undefined)
|
|
168
|
+
throw new Error(`public JSON at '${path}' is not JSON`);
|
|
169
|
+
if (Buffer.byteLength(text) > PUBLIC_JSON_MAX_BYTES)
|
|
170
|
+
throw new Error(`public JSON at '${path}' is over 64 KiB`);
|
|
171
|
+
bodies.set(path, text);
|
|
172
|
+
}
|
|
173
|
+
return bodies;
|
|
174
|
+
}
|
|
175
|
+
/** Core authenticates and parses before the handler runs, so an add-on route gets the same 401, 400 and 501 as a core one. */
|
|
176
|
+
export async function dispatchAddonRoute({ req, res, opts }, method, path) {
|
|
177
|
+
const route = method === 'POST' ? opts.routes?.find((r) => r.path === path) : undefined;
|
|
178
|
+
if (!route)
|
|
179
|
+
return false;
|
|
180
|
+
noteAccess(req, { route: route.path });
|
|
181
|
+
await refuseUnportedRoute(req, opts, route.storeReady);
|
|
182
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
183
|
+
noteAccess(req, { tenant: ctx.tenantId });
|
|
184
|
+
const body = await parseJsonBody(req, ctx);
|
|
185
|
+
sendJson(res, 200, await route.handler({ ctx, body }));
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
188
|
+
/** No auth, body read or store access, so a caller with no key gets it under any store. */
|
|
189
|
+
export function dispatchPublicJson({ req, res, opts }, method, path) {
|
|
190
|
+
const text = method === 'GET' ? opts.publicJsonBodies.get(path) : undefined;
|
|
191
|
+
if (text === undefined)
|
|
192
|
+
return false;
|
|
193
|
+
noteAccess(req, { route: path });
|
|
194
|
+
res.writeHead(200, { ...JSON_HEADERS, 'cache-control': 'no-store' });
|
|
195
|
+
res.end(text);
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
export function assertSqliteStore(opts) {
|
|
199
|
+
if (opts.store.kind !== 'sqlite')
|
|
200
|
+
throw new HttpError(501, STORE_NOT_PORTED_MESSAGE);
|
|
201
|
+
}
|
|
202
|
+
/** Under another store, a route that names no group, or one the store lacks, answers 501 without running; the caller is checked first, so a bad key is still a 401. */
|
|
203
|
+
async function refuseUnportedRoute(req, opts, group) {
|
|
204
|
+
if (opts.store.kind === 'sqlite' || (group !== undefined && hasGroup(opts.store, group)))
|
|
205
|
+
return;
|
|
206
|
+
await requireAuth(req, opts);
|
|
207
|
+
assertSqliteStore(opts);
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=route-table.js.map
|