hippo-memory 1.60.0 → 1.61.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/ablation.js +9 -27
- package/dist/agent-memories/apply.js +4 -1
- package/dist/agent-memories/claude-code.js +1 -1
- package/dist/agent-memories/codex.js +1 -1
- package/dist/agent-memories/gemini.js +1 -1
- package/dist/agent-memories/legacy.js +1 -1
- package/dist/agent-memories/source.js +1 -1
- package/dist/agent-memories/sync.js +8 -3
- package/dist/ambient-store.d.ts +14 -0
- package/dist/ambient-store.js +90 -0
- package/dist/ambient.d.ts +23 -0
- package/dist/ambient.js +72 -50
- package/dist/api/assemble.d.ts +93 -0
- package/dist/api/assemble.js +152 -0
- package/dist/api/audit.d.ts +17 -0
- package/dist/api/audit.js +23 -0
- package/dist/api/auth.d.ts +79 -0
- package/dist/api/auth.js +178 -0
- package/dist/api/context-types.d.ts +105 -0
- package/dist/api/context-types.js +3 -0
- package/dist/api/context.d.ts +31 -0
- package/dist/api/context.js +705 -0
- package/dist/api/dormant.d.ts +30 -0
- package/dist/api/dormant.js +140 -0
- package/dist/api/drill-down.d.ts +84 -0
- package/dist/api/drill-down.js +123 -0
- package/dist/api/forget.d.ts +57 -0
- package/dist/api/forget.js +87 -0
- package/dist/api/goals.d.ts +18 -0
- package/dist/api/goals.js +33 -0
- package/dist/api/learn.d.ts +31 -0
- package/dist/api/learn.js +88 -0
- package/dist/api/outcome.d.ts +61 -0
- package/dist/api/outcome.js +66 -0
- package/dist/api/promote.d.ts +54 -0
- package/dist/api/promote.js +203 -0
- package/dist/api/quarantine.d.ts +24 -0
- package/dist/api/quarantine.js +121 -0
- package/dist/api/recall-types.d.ts +390 -0
- package/dist/api/recall-types.js +3 -0
- package/dist/api/recall.d.ts +36 -0
- package/dist/api/recall.js +634 -0
- package/dist/api/remember.d.ts +35 -0
- package/dist/api/remember.js +43 -0
- package/dist/api/sleep.d.ts +136 -0
- package/dist/api/sleep.js +271 -0
- package/dist/api/tokens.d.ts +26 -0
- package/dist/api/tokens.js +60 -0
- package/dist/api/types.d.ts +56 -0
- package/dist/api/types.js +38 -0
- package/dist/api.d.ts +20 -1262
- package/dist/api.js +25 -2727
- package/dist/audit.d.ts +3 -0
- package/dist/audit.js +6 -3
- package/dist/auth.d.ts +45 -4
- package/dist/auth.js +125 -48
- package/dist/autolearn.js +2 -2
- package/dist/capture/command.d.ts +33 -0
- package/dist/capture/command.js +264 -0
- package/dist/capture/compact.d.ts +44 -0
- package/dist/capture/compact.js +354 -0
- package/dist/capture/extract.d.ts +21 -0
- package/dist/capture/extract.js +464 -0
- package/dist/capture/transcript.d.ts +40 -0
- package/dist/capture/transcript.js +193 -0
- package/dist/capture-error.js +2 -1
- package/dist/churn-git.js +4 -2
- package/dist/cli/audit.d.ts +3 -0
- package/dist/cli/audit.js +159 -0
- package/dist/cli/auth.d.ts +2 -0
- package/dist/cli/auth.js +171 -0
- package/dist/cli/briefs.d.ts +4 -0
- package/dist/cli/briefs.js +435 -0
- package/dist/cli/card.d.ts +3 -0
- package/dist/cli/card.js +333 -0
- package/dist/cli/context.d.ts +15 -0
- package/dist/cli/context.js +366 -0
- package/dist/cli/continuity.d.ts +6 -0
- package/dist/cli/continuity.js +445 -0
- package/dist/cli/curate.d.ts +19 -0
- package/dist/cli/curate.js +555 -0
- package/dist/cli/dag.d.ts +5 -0
- package/dist/cli/dag.js +177 -0
- package/dist/cli/decisions.d.ts +4 -0
- package/dist/cli/decisions.js +528 -0
- package/dist/cli/eval.d.ts +5 -0
- package/dist/cli/eval.js +213 -0
- package/dist/cli/explain.d.ts +4 -0
- package/dist/cli/explain.js +150 -0
- package/dist/cli/goals.d.ts +2 -0
- package/dist/cli/goals.js +196 -0
- package/dist/cli/hook-blocks.d.ts +18 -0
- package/dist/cli/hook-blocks.js +233 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.js +305 -0
- package/dist/cli/maintenance.d.ts +4 -0
- package/dist/cli/maintenance.js +179 -0
- package/dist/cli/playbooks.d.ts +4 -0
- package/dist/cli/playbooks.js +556 -0
- package/dist/cli/projects.js +1 -1
- package/dist/cli/recall.d.ts +7 -0
- package/dist/cli/recall.js +597 -0
- package/dist/cli/remember.d.ts +5 -0
- package/dist/cli/remember.js +442 -0
- package/dist/cli/serve.d.ts +5 -0
- package/dist/cli/serve.js +40 -0
- package/dist/cli/session-hooks.d.ts +29 -0
- package/dist/cli/session-hooks.js +637 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +376 -0
- package/dist/cli/shared.d.ts +15 -19
- package/dist/cli/shared.js +50 -341
- package/dist/cli/slack.d.ts +2 -0
- package/dist/cli/slack.js +171 -0
- package/dist/cli/status.d.ts +18 -0
- package/dist/cli/status.js +400 -0
- package/dist/cli/transfer.d.ts +10 -0
- package/dist/cli/transfer.js +438 -0
- package/dist/cli/usage.d.ts +85 -0
- package/dist/cli/usage.js +741 -0
- package/dist/cli.d.ts +71 -120
- package/dist/cli.js +170 -8469
- package/dist/client.js +15 -8
- package/dist/compaction-record.js +6 -4
- package/dist/connectors/github/backfill.js +94 -87
- package/dist/connectors/github/cli-impl.js +4 -3
- package/dist/connectors/github/dlq.js +67 -54
- package/dist/connectors/github/ingest.js +34 -35
- package/dist/connectors/github/tenant-routing.js +3 -2
- package/dist/connectors/github/webhook.js +135 -216
- package/dist/connectors/slack/dlq.js +49 -61
- package/dist/connectors/slack/ingest.js +55 -48
- package/dist/connectors/slack/tenant-routing.js +4 -3
- package/dist/connectors/slack/webhook.js +72 -74
- package/dist/consolidate/conflicts.d.ts +10 -0
- package/dist/consolidate/conflicts.js +178 -0
- package/dist/consolidate/decay.d.ts +12 -0
- package/dist/consolidate/decay.js +145 -0
- package/dist/consolidate/llm-passes.d.ts +3 -0
- package/dist/consolidate/llm-passes.js +141 -0
- package/dist/consolidate/merge.d.ts +7 -0
- package/dist/consolidate/merge.js +251 -0
- package/dist/consolidate/physics-pass.d.ts +3 -0
- package/dist/consolidate/physics-pass.js +60 -0
- package/dist/consolidate/run.d.ts +69 -0
- package/dist/consolidate/run.js +76 -0
- package/dist/consolidate/sleep.d.ts +18 -0
- package/dist/consolidate/sleep.js +209 -0
- package/dist/consolidate/traces.d.ts +4 -0
- package/dist/consolidate/traces.js +178 -0
- package/dist/context-auto.js +7 -11
- package/dist/context-render.d.ts +1 -1
- package/dist/context-render.js +1 -1
- package/dist/customer-notes.d.ts +3 -0
- package/dist/customer-notes.js +6 -4
- package/dist/dag.js +6 -5
- package/dist/dashboard-actions.d.ts +20 -0
- package/dist/dashboard-actions.js +88 -0
- package/dist/dashboard-params.d.ts +45 -0
- package/dist/dashboard-params.js +127 -0
- package/dist/dashboard-queries.d.ts +15 -0
- package/dist/dashboard-queries.js +355 -0
- package/dist/dashboard-snapshot.d.ts +138 -0
- package/dist/dashboard-snapshot.js +308 -0
- package/dist/dashboard-types.d.ts +163 -0
- package/dist/dashboard-types.js +3 -0
- package/dist/dashboard.d.ts +6 -7
- package/dist/dashboard.js +228 -202
- package/dist/db/busy.d.ts +5 -0
- package/dist/db/busy.js +24 -0
- package/dist/db/continuity.d.ts +5 -0
- package/dist/db/continuity.js +145 -0
- package/dist/db/meta.d.ts +8 -0
- package/dist/db/meta.js +35 -0
- package/dist/db/migrate.d.ts +9 -0
- package/dist/db/migrate.js +138 -0
- package/dist/db/migrations/index.d.ts +5 -0
- package/dist/db/migrations/index.js +109 -0
- package/dist/db/migrations/types.d.ts +14 -0
- package/dist/db/migrations/types.js +2 -0
- package/dist/db/migrations/v01.d.ts +3 -0
- package/dist/db/migrations/v01.js +38 -0
- package/dist/db/migrations/v02.d.ts +3 -0
- package/dist/db/migrations/v02.js +21 -0
- package/dist/db/migrations/v03.d.ts +3 -0
- package/dist/db/migrations/v03.js +22 -0
- package/dist/db/migrations/v04.d.ts +3 -0
- package/dist/db/migrations/v04.js +28 -0
- package/dist/db/migrations/v05.d.ts +3 -0
- package/dist/db/migrations/v05.js +21 -0
- package/dist/db/migrations/v06.d.ts +3 -0
- package/dist/db/migrations/v06.js +25 -0
- package/dist/db/migrations/v07.d.ts +3 -0
- package/dist/db/migrations/v07.js +13 -0
- package/dist/db/migrations/v08.d.ts +3 -0
- package/dist/db/migrations/v08.js +8 -0
- package/dist/db/migrations/v09.d.ts +3 -0
- package/dist/db/migrations/v09.js +13 -0
- package/dist/db/migrations/v10.d.ts +3 -0
- package/dist/db/migrations/v10.js +17 -0
- package/dist/db/migrations/v11.d.ts +3 -0
- package/dist/db/migrations/v11.js +15 -0
- package/dist/db/migrations/v12.d.ts +3 -0
- package/dist/db/migrations/v12.js +11 -0
- package/dist/db/migrations/v13.d.ts +3 -0
- package/dist/db/migrations/v13.js +15 -0
- package/dist/db/migrations/v14.d.ts +3 -0
- package/dist/db/migrations/v14.js +66 -0
- package/dist/db/migrations/v15.d.ts +3 -0
- package/dist/db/migrations/v15.js +42 -0
- package/dist/db/migrations/v16.d.ts +3 -0
- package/dist/db/migrations/v16.js +61 -0
- package/dist/db/migrations/v17.d.ts +3 -0
- package/dist/db/migrations/v17.js +46 -0
- package/dist/db/migrations/v18.d.ts +3 -0
- package/dist/db/migrations/v18.js +60 -0
- package/dist/db/migrations/v19.d.ts +3 -0
- package/dist/db/migrations/v19.js +28 -0
- package/dist/db/migrations/v20.d.ts +3 -0
- package/dist/db/migrations/v20.js +42 -0
- package/dist/db/migrations/v21.d.ts +3 -0
- package/dist/db/migrations/v21.js +16 -0
- package/dist/db/migrations/v22.d.ts +3 -0
- package/dist/db/migrations/v22.js +82 -0
- package/dist/db/migrations/v23.d.ts +3 -0
- package/dist/db/migrations/v23.js +48 -0
- package/dist/db/migrations/v24.d.ts +3 -0
- package/dist/db/migrations/v24.js +72 -0
- package/dist/db/migrations/v25.d.ts +3 -0
- package/dist/db/migrations/v25.js +46 -0
- package/dist/db/migrations/v26.d.ts +3 -0
- package/dist/db/migrations/v26.js +23 -0
- package/dist/db/migrations/v27.d.ts +3 -0
- package/dist/db/migrations/v27.js +57 -0
- package/dist/db/migrations/v28.d.ts +3 -0
- package/dist/db/migrations/v28.js +38 -0
- package/dist/db/migrations/v29.d.ts +3 -0
- package/dist/db/migrations/v29.js +78 -0
- package/dist/db/migrations/v30.d.ts +3 -0
- package/dist/db/migrations/v30.js +92 -0
- package/dist/db/migrations/v31.d.ts +3 -0
- package/dist/db/migrations/v31.js +74 -0
- package/dist/db/migrations/v32.d.ts +3 -0
- package/dist/db/migrations/v32.js +102 -0
- package/dist/db/migrations/v33.d.ts +3 -0
- package/dist/db/migrations/v33.js +104 -0
- package/dist/db/migrations/v34.d.ts +3 -0
- package/dist/db/migrations/v34.js +93 -0
- package/dist/db/migrations/v35.d.ts +3 -0
- package/dist/db/migrations/v35.js +98 -0
- package/dist/db/migrations/v36.d.ts +3 -0
- package/dist/db/migrations/v36.js +98 -0
- package/dist/db/migrations/v37.d.ts +3 -0
- package/dist/db/migrations/v37.js +219 -0
- package/dist/db/migrations/v38.d.ts +3 -0
- package/dist/db/migrations/v38.js +277 -0
- package/dist/db/migrations/v39.d.ts +3 -0
- package/dist/db/migrations/v39.js +59 -0
- package/dist/db/migrations/v40.d.ts +3 -0
- package/dist/db/migrations/v40.js +74 -0
- package/dist/db/migrations/v41.d.ts +3 -0
- package/dist/db/migrations/v41.js +43 -0
- package/dist/db/migrations/v42.d.ts +3 -0
- package/dist/db/migrations/v42.js +41 -0
- package/dist/db/migrations/v43.d.ts +3 -0
- package/dist/db/migrations/v43.js +67 -0
- package/dist/db/migrations/v44.d.ts +3 -0
- package/dist/db/migrations/v44.js +28 -0
- package/dist/db/migrations/v45.d.ts +3 -0
- package/dist/db/migrations/v45.js +30 -0
- package/dist/db/migrations/v46.d.ts +3 -0
- package/dist/db/migrations/v46.js +25 -0
- package/dist/db/migrations/v47.d.ts +3 -0
- package/dist/db/migrations/v47.js +17 -0
- package/dist/db/migrations/v48.d.ts +3 -0
- package/dist/db/migrations/v48.js +10 -0
- package/dist/db/migrations/v49.d.ts +3 -0
- package/dist/db/migrations/v49.js +31 -0
- package/dist/db/migrations/v50.d.ts +3 -0
- package/dist/db/migrations/v50.js +67 -0
- package/dist/db/migrations/v51.d.ts +3 -0
- package/dist/db/migrations/v51.js +14 -0
- package/dist/db/migrations/v52.d.ts +3 -0
- package/dist/db/migrations/v52.js +7 -0
- package/dist/db/open.d.ts +23 -0
- package/dist/db/open.js +146 -0
- package/dist/db/sqlite.d.ts +21 -0
- package/dist/db/sqlite.js +8 -0
- package/dist/db/tables.d.ts +7 -0
- package/dist/db/tables.js +38 -0
- package/dist/db.d.ts +6 -46
- package/dist/db.js +5 -3049
- package/dist/decisions.d.ts +4 -1
- package/dist/decisions.js +9 -7
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +4 -1
- package/dist/doctor.js +3 -3
- package/dist/embedding-provider.d.ts +1 -1
- package/dist/embedding-provider.js +4 -3
- package/dist/embeddings.d.ts +9 -52
- package/dist/embeddings.js +43 -297
- package/dist/env.d.ts +75 -0
- package/dist/env.js +119 -0
- package/dist/eval-suite.js +1 -1
- package/dist/eval.js +2 -2
- package/dist/extract.js +1 -1
- package/dist/gated-write.js +3 -1
- package/dist/goals.d.ts +3 -1
- package/dist/goals.js +18 -0
- package/dist/graph/read.d.ts +73 -0
- package/dist/graph/read.js +325 -0
- package/dist/graph/rows.d.ts +45 -0
- package/dist/graph/rows.js +51 -0
- package/dist/graph/types.d.ts +83 -0
- package/dist/graph/types.js +11 -0
- package/dist/graph/write.d.ts +93 -0
- package/dist/{graph.js → graph/write.js} +6 -384
- package/dist/graph-extract.js +2 -1
- package/dist/graph-recall.d.ts +1 -1
- package/dist/graph-recall.js +2 -2
- package/dist/graph-stream.js +1 -1
- package/dist/graph-view.d.ts +1 -1
- package/dist/graph-view.js +1 -1
- package/dist/half-life-migration.d.ts +1 -1
- package/dist/half-life-migration.js +2 -1
- package/dist/hooks/codex-session.d.ts +8 -0
- package/dist/hooks/codex-session.js +76 -0
- package/dist/hooks/codex-wrapper.d.ts +55 -0
- package/dist/hooks/codex-wrapper.js +288 -0
- package/dist/hooks/json-hooks.d.ts +63 -0
- package/dist/hooks/json-hooks.js +356 -0
- package/dist/hooks/opencode.d.ts +50 -0
- package/dist/hooks/opencode.js +202 -0
- package/dist/hooks/shared.d.ts +54 -0
- package/dist/hooks/shared.js +77 -0
- package/dist/http-retry.d.ts +2 -0
- package/dist/http-retry.js +4 -3
- package/dist/http-util.d.ts +3 -0
- package/dist/http-util.js +10 -0
- package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
- package/dist/importers/core.js +141 -0
- package/dist/importers/markdown-parse.d.ts +41 -0
- package/dist/importers/markdown-parse.js +132 -0
- package/dist/importers/markdown.d.ts +3 -0
- package/dist/importers/markdown.js +92 -0
- package/dist/importers/sources.d.ts +7 -0
- package/dist/importers/sources.js +229 -0
- package/dist/importers/vault.d.ts +11 -0
- package/dist/importers/vault.js +352 -0
- package/dist/incidents.d.ts +3 -0
- package/dist/incidents.js +7 -5
- package/dist/index.d.ts +25 -6
- package/dist/index.js +23 -6
- package/dist/invalidation.js +2 -1
- package/dist/judgment.js +2 -1
- package/dist/keyset.d.ts +13 -0
- package/dist/keyset.js +8 -0
- package/dist/local-embedding.d.ts +13 -0
- package/dist/local-embedding.js +165 -0
- package/dist/log.d.ts +7 -0
- package/dist/log.js +19 -1
- package/dist/mcp/admin-tools.d.ts +8 -0
- package/dist/mcp/admin-tools.js +116 -0
- package/dist/mcp/format.d.ts +27 -0
- package/dist/mcp/format.js +135 -0
- package/dist/mcp/memory-tools.d.ts +5 -0
- package/dist/mcp/memory-tools.js +83 -0
- package/dist/mcp/protocol.d.ts +83 -0
- package/dist/mcp/protocol.js +55 -0
- package/dist/mcp/recall-tools.d.ts +6 -0
- package/dist/mcp/recall-tools.js +320 -0
- package/dist/mcp/request.d.ts +10 -0
- package/dist/mcp/request.js +163 -0
- package/dist/mcp/server.d.ts +4 -75
- package/dist/mcp/server.js +7 -1190
- package/dist/mcp/session-state.d.ts +11 -0
- package/dist/mcp/session-state.js +28 -0
- package/dist/mcp/stdio.d.ts +8 -0
- package/dist/mcp/stdio.js +79 -0
- package/dist/mcp/tools.d.ts +11 -0
- package/dist/mcp/tools.js +247 -0
- package/dist/memory.d.ts +3 -0
- package/dist/memory.js +27 -1
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +2 -1
- package/dist/owner-validation.js +2 -1
- package/dist/physics-state.js +10 -7
- package/dist/policies.d.ts +3 -0
- package/dist/policies.js +8 -6
- package/dist/postinstall.js +3 -2
- package/dist/predictions/planning-fallacy.d.ts +100 -0
- package/dist/predictions/planning-fallacy.js +190 -0
- package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
- package/dist/predictions/store.js +434 -0
- package/dist/processes.d.ts +3 -0
- package/dist/processes.js +7 -5
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +7 -5
- package/dist/project-identity.js +3 -2
- package/dist/project-merge.js +3 -1
- package/dist/quarantine.d.ts +2 -1
- package/dist/quarantine.js +8 -5
- package/dist/raw-archive.js +1 -1
- package/dist/recall-history.js +3 -2
- package/dist/recall-pipeline.d.ts +2 -2
- package/dist/recall-pipeline.js +16 -8
- package/dist/recall-scope.js +1 -1
- package/dist/recall-trace.d.ts +1 -1
- package/dist/refine-llm.js +2 -1
- package/dist/reject-flow.js +6 -1
- package/dist/rerankers/clef.js +6 -5
- package/dist/rerankers/jev.d.ts +1 -1
- package/dist/rerankers/jev.js +4 -4
- package/dist/rerankers/llm.d.ts +4 -2
- package/dist/rerankers/llm.js +58 -38
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/salience.js +1 -1
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.js +26 -4
- package/dist/scope.js +4 -3
- package/dist/search/as-of.d.ts +10 -0
- package/dist/search/as-of.js +22 -0
- package/dist/search/bm25-search.d.ts +14 -0
- package/dist/search/bm25-search.js +43 -0
- package/dist/search/bm25.d.ts +15 -0
- package/dist/search/bm25.js +54 -0
- package/dist/search/boosts.d.ts +54 -0
- package/dist/search/boosts.js +94 -0
- package/dist/search/breakdown.d.ts +7 -0
- package/dist/search/breakdown.js +20 -0
- package/dist/search/explain.d.ts +25 -0
- package/dist/search/explain.js +31 -0
- package/dist/search/finalize.d.ts +8 -0
- package/dist/search/finalize.js +52 -0
- package/dist/search/fusion.d.ts +27 -0
- package/dist/search/fusion.js +42 -0
- package/dist/search/hybrid-score.d.ts +20 -0
- package/dist/search/hybrid-score.js +73 -0
- package/dist/search/hybrid.d.ts +46 -0
- package/dist/search/hybrid.js +64 -0
- package/dist/search/physics-search.d.ts +29 -0
- package/dist/search/physics-search.js +162 -0
- package/dist/search/rerank.d.ts +10 -0
- package/dist/search/rerank.js +72 -0
- package/dist/search/temporal.d.ts +15 -0
- package/dist/search/temporal.js +45 -0
- package/dist/search/types.d.ts +91 -0
- package/dist/search/types.js +2 -0
- package/dist/search/vector.d.ts +30 -0
- package/dist/search/vector.js +71 -0
- package/dist/secret-detect.d.ts +2 -0
- package/dist/secret-detect.js +2 -1
- package/dist/server/auth.d.ts +52 -0
- package/dist/server/auth.js +221 -0
- package/dist/server/client-ip.d.ts +25 -0
- package/dist/server/client-ip.js +92 -0
- package/dist/server/cursor.d.ts +23 -0
- package/dist/server/cursor.js +58 -0
- package/dist/server/lifecycle.d.ts +7 -0
- package/dist/server/lifecycle.js +29 -0
- package/dist/server/mcp-http.d.ts +5 -0
- package/dist/server/mcp-http.js +199 -0
- package/dist/server/request.d.ts +33 -0
- package/dist/server/request.js +103 -0
- package/dist/server/routes/admin.d.ts +9 -0
- package/dist/server/routes/admin.js +158 -0
- package/dist/server/routes/customer-notes.d.ts +7 -0
- package/dist/server/routes/customer-notes.js +112 -0
- package/dist/server/routes/decisions.d.ts +7 -0
- package/dist/server/routes/decisions.js +133 -0
- package/dist/server/routes/incidents.d.ts +7 -0
- package/dist/server/routes/incidents.js +126 -0
- package/dist/server/routes/memories.d.ts +10 -0
- package/dist/server/routes/memories.js +179 -0
- package/dist/server/routes/policies.d.ts +8 -0
- package/dist/server/routes/policies.js +151 -0
- package/dist/server/routes/predictions.d.ts +7 -0
- package/dist/server/routes/predictions.js +164 -0
- package/dist/server/routes/processes.d.ts +7 -0
- package/dist/server/routes/processes.js +161 -0
- package/dist/server/routes/project-briefs.d.ts +8 -0
- package/dist/server/routes/project-briefs.js +136 -0
- package/dist/server/routes/recall.d.ts +8 -0
- package/dist/server/routes/recall.js +340 -0
- package/dist/server/routes/skills.d.ts +8 -0
- package/dist/server/routes/skills.js +150 -0
- package/dist/server/types.d.ts +56 -0
- package/dist/server/types.js +2 -0
- package/dist/server/validation.d.ts +14 -0
- package/dist/server/validation.js +91 -0
- package/dist/server.d.ts +7 -61
- package/dist/server.js +69 -2362
- package/dist/session-digest.d.ts +1 -1
- package/dist/session-digest.js +9 -2
- package/dist/shared.d.ts +3 -1
- package/dist/shared.js +26 -22
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +7 -5
- package/dist/stdin.js +2 -2
- package/dist/store/audit-event.d.ts +19 -0
- package/dist/store/audit-event.js +33 -0
- package/dist/store/candidates.d.ts +42 -0
- package/dist/store/candidates.js +152 -0
- package/dist/store/conflicts.d.ts +44 -0
- package/dist/store/conflicts.js +444 -0
- package/dist/store/delete-and-batch.d.ts +63 -0
- package/dist/store/delete-and-batch.js +310 -0
- package/dist/store/entry-reads.d.ts +92 -0
- package/dist/store/entry-reads.js +255 -0
- package/dist/store/entry-row.d.ts +67 -0
- package/dist/store/entry-row.js +208 -0
- package/dist/store/entry-writes.d.ts +46 -0
- package/dist/store/entry-writes.js +148 -0
- package/dist/store/handoffs.d.ts +26 -0
- package/dist/store/handoffs.js +184 -0
- package/dist/store/index-and-stats.d.ts +52 -0
- package/dist/store/index-and-stats.js +214 -0
- package/dist/store/markdown.d.ts +10 -0
- package/dist/store/markdown.js +108 -0
- package/dist/store/mirrors.d.ts +49 -0
- package/dist/store/mirrors.js +312 -0
- package/dist/store/open.d.ts +15 -0
- package/dist/store/open.js +223 -0
- package/dist/store/rows.d.ts +178 -0
- package/dist/store/rows.js +158 -0
- package/dist/store/search-rows.d.ts +86 -0
- package/dist/store/search-rows.js +254 -0
- package/dist/store/sessions.d.ts +83 -0
- package/dist/store/sessions.js +272 -0
- package/dist/store/summaries.d.ts +94 -0
- package/dist/store/summaries.js +377 -0
- package/dist/store/tenant-lookup.d.ts +12 -0
- package/dist/store/tenant-lookup.js +16 -0
- package/dist/store-cards.js +2 -1
- package/dist/summary-dirty.d.ts +4 -0
- package/dist/summary-dirty.js +32 -0
- package/dist/support-bundle.js +4 -3
- package/dist/tenant.js +2 -2
- package/dist/tokenize.d.ts +2 -0
- package/dist/tokenize.js +16 -0
- package/dist/transcript-tail.d.ts +7 -0
- package/dist/transcript-tail.js +48 -0
- package/dist/vector-store.d.ts +27 -0
- package/dist/vector-store.js +210 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +2 -2
- package/dist/working-memory.js +1 -1
- package/dist/yaml.js +36 -11
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
- package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/dist-ui/assets/index-DPN7cP19.js +33 -0
- package/dist-ui/assets/index-dFloKRVr.css +1 -0
- package/dist-ui/index.html +3 -25
- 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 +1 -1
- package/dist/capture.d.ts +0 -155
- package/dist/capture.js +0 -1295
- package/dist/consolidate.d.ts +0 -58
- package/dist/consolidate.js +0 -1124
- package/dist/graph.d.ts +0 -245
- package/dist/hooks.d.ts +0 -208
- package/dist/hooks.js +0 -1076
- package/dist/importers.js +0 -900
- package/dist/predictions.js +0 -620
- package/dist/search.d.ts +0 -320
- package/dist/search.js +0 -970
- package/dist/store.d.ts +0 -776
- package/dist/store.js +0 -3473
- package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
- package/dist-ui/assets/index-BhT8RvO6.js +0 -61
- package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
- package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// /v1/incidents routes.
|
|
2
|
+
import { closeIncident, loadIncidentById, loadIncidents, resolveIncident, saveIncident, VALID_INCIDENT_STATES } from '../../incidents.js';
|
|
3
|
+
import { HttpError, sendJson } from '../../http-util.js';
|
|
4
|
+
import { NotFoundError } from '../../api-errors.js';
|
|
5
|
+
import { buildContextWithAuth } from '../auth.js';
|
|
6
|
+
import { byCreatedAt, pageOf, parseCursor } from '../cursor.js';
|
|
7
|
+
import { isJsonString, isSetMember, parseJsonBody, parseListLimit } from '../validation.js';
|
|
8
|
+
// ── incidents (E2 first-class object) ──
|
|
9
|
+
//
|
|
10
|
+
// 5 routes: POST /v1/incidents (open; body text + context + linkedMemoryIds[]),
|
|
11
|
+
// GET /v1/incidents (list, status filter), GET /v1/incidents/:id (show),
|
|
12
|
+
// POST /v1/incidents/:id/resolve (open -> resolved; body resolutionText),
|
|
13
|
+
// POST /v1/incidents/:id/close (open|resolved -> closed). Bearer-authed +
|
|
14
|
+
// tenant-scoped via buildContextWithAuth. status validated against
|
|
15
|
+
// VALID_INCIDENT_STATES. DoS caps: text 4096, context 4096, resolutionText
|
|
16
|
+
// 4096 (v1.11.4 pattern). Mirrors /v1/decisions; lifecycle is
|
|
17
|
+
// open->resolved->closed (no supersede), so linkedMemoryIds replaces
|
|
18
|
+
// supersedesDecisionId on create.
|
|
19
|
+
export async function handleCreateIncident({ req, res, opts }) {
|
|
20
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
21
|
+
const body = await parseJsonBody(req, ctx);
|
|
22
|
+
const text = body['text'];
|
|
23
|
+
if (!isJsonString(text) || text.length === 0) {
|
|
24
|
+
throw new HttpError(400, 'text is required (non-empty string)');
|
|
25
|
+
}
|
|
26
|
+
if (text.length > 4096) {
|
|
27
|
+
throw new HttpError(400, 'text exceeds 4096-character cap');
|
|
28
|
+
}
|
|
29
|
+
const contextRaw = body['context'];
|
|
30
|
+
let context;
|
|
31
|
+
if (contextRaw !== undefined && contextRaw !== null) {
|
|
32
|
+
if (!isJsonString(contextRaw)) {
|
|
33
|
+
throw new HttpError(400, 'context must be a string');
|
|
34
|
+
}
|
|
35
|
+
if (contextRaw.length > 4096) {
|
|
36
|
+
throw new HttpError(400, 'context exceeds 4096-character cap');
|
|
37
|
+
}
|
|
38
|
+
context = contextRaw;
|
|
39
|
+
}
|
|
40
|
+
const linkedRaw = body['linkedMemoryIds'];
|
|
41
|
+
let linkedMemoryIds;
|
|
42
|
+
if (linkedRaw !== undefined && linkedRaw !== null) {
|
|
43
|
+
if (!Array.isArray(linkedRaw)) {
|
|
44
|
+
throw new HttpError(400, 'linkedMemoryIds must be an array of memory ids');
|
|
45
|
+
}
|
|
46
|
+
if (linkedRaw.length > 256) {
|
|
47
|
+
throw new HttpError(400, 'linkedMemoryIds exceeds 256-item cap');
|
|
48
|
+
}
|
|
49
|
+
const isValidMemoryId = (item) => isJsonString(item) && item.length > 0 && item.length <= 4096;
|
|
50
|
+
if (!linkedRaw.every(isValidMemoryId)) {
|
|
51
|
+
throw new HttpError(400, 'each linkedMemoryIds entry must be a non-empty string <= 4096 chars');
|
|
52
|
+
}
|
|
53
|
+
linkedMemoryIds = linkedRaw;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
const incident = saveIncident(opts.hippoRoot, ctx.tenantId, {
|
|
57
|
+
incidentText: text,
|
|
58
|
+
context,
|
|
59
|
+
linkedMemoryIds,
|
|
60
|
+
}, ctx.actor.subject);
|
|
61
|
+
sendJson(res, 201, { incident });
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
// A missing referenced row is a conflict with the create, not a missing target.
|
|
65
|
+
if (e instanceof NotFoundError)
|
|
66
|
+
throw new HttpError(409, e.message);
|
|
67
|
+
throw e;
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
export async function handleListIncidents({ req, res, opts, query }) {
|
|
72
|
+
const status = query.get('status') ?? 'all';
|
|
73
|
+
const limit = parseListLimit(query.get('limit'));
|
|
74
|
+
const after = parseCursor(query.get('cursor'), 'string', 'integer');
|
|
75
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
76
|
+
let incidents;
|
|
77
|
+
if (status === 'all') {
|
|
78
|
+
incidents = loadIncidents(opts.hippoRoot, ctx.tenantId, { limit: limit + 1, after });
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
if (!isSetMember(VALID_INCIDENT_STATES, status)) {
|
|
82
|
+
throw new HttpError(400, `status must be one of: open | resolved | closed | all (got "${status}")`);
|
|
83
|
+
}
|
|
84
|
+
incidents = loadIncidents(opts.hippoRoot, ctx.tenantId, {
|
|
85
|
+
status,
|
|
86
|
+
limit: limit + 1,
|
|
87
|
+
after,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const page = pageOf(incidents, limit, byCreatedAt);
|
|
91
|
+
sendJson(res, 200, { incidents: page.items, next_cursor: page.nextCursor });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
export async function handleResolveIncident({ req, res, opts }, incidentResolveMatch) {
|
|
95
|
+
const id = parseInt(incidentResolveMatch[1], 10);
|
|
96
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
97
|
+
const body = await parseJsonBody(req, ctx);
|
|
98
|
+
const resolutionText = body['resolutionText'];
|
|
99
|
+
if (!isJsonString(resolutionText) || resolutionText.trim().length === 0) {
|
|
100
|
+
throw new HttpError(400, 'resolutionText is required (non-empty string)');
|
|
101
|
+
}
|
|
102
|
+
if (resolutionText.length > 4096) {
|
|
103
|
+
throw new HttpError(400, 'resolutionText exceeds 4096-character cap');
|
|
104
|
+
}
|
|
105
|
+
const incident = resolveIncident(opts.hippoRoot, ctx.tenantId, id, resolutionText, ctx.actor.subject);
|
|
106
|
+
sendJson(res, 200, { incident });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
export async function handleCloseIncident({ req, res, opts }, incidentCloseMatch) {
|
|
110
|
+
const id = parseInt(incidentCloseMatch[1], 10);
|
|
111
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
112
|
+
const incident = closeIncident(opts.hippoRoot, ctx.tenantId, id, ctx.actor.subject);
|
|
113
|
+
sendJson(res, 200, { incident });
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
export async function handleGetIncident({ req, res, opts }, incidentByIdMatch) {
|
|
117
|
+
const id = parseInt(incidentByIdMatch[1], 10);
|
|
118
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
119
|
+
const incident = loadIncidentById(opts.hippoRoot, ctx.tenantId, id);
|
|
120
|
+
if (!incident) {
|
|
121
|
+
throw new HttpError(404, `incident ${id} not found`);
|
|
122
|
+
}
|
|
123
|
+
sendJson(res, 200, { incident });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=incidents.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateMemory({ req, res, opts }: RouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleGetGraph({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleArchiveMemory({ req, res, opts }: RouteRequest, archiveMatch: Record<string, string>): Promise<void>;
|
|
5
|
+
export declare function handleSupersedeMemory({ req, res, opts }: RouteRequest, supersedeMatch: Record<string, string>): Promise<void>;
|
|
6
|
+
export declare function handlePromoteMemory({ req, res, opts }: RouteRequest, promoteMatch: Record<string, string>): Promise<void>;
|
|
7
|
+
export declare function handleForgetMemory({ req, res, opts }: RouteRequest, idMatch: Record<string, string>): Promise<void>;
|
|
8
|
+
export declare function handleApplyOutcome({ req, res, opts }: RouteRequest): Promise<void>;
|
|
9
|
+
export declare function handleSleep({ req, res, opts }: RouteRequest): Promise<void>;
|
|
10
|
+
//# sourceMappingURL=memories.d.ts.map
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
// Memory write routes: create, graph, archive, supersede, promote, forget, outcome, sleep.
|
|
2
|
+
import { archiveRaw, forget, outcome, outcomeForLastRecall, promote, remember, sleep, supersede } from '../../api.js';
|
|
3
|
+
import { buildGraphModel } from '../../graph-view.js';
|
|
4
|
+
import { MAX_ENTITY_NAME_LEN } from '../../graph/types.js';
|
|
5
|
+
import { HttpError, sendJson } from '../../http-util.js';
|
|
6
|
+
import { assertCrossTenantAdmin, buildContextWithAuth, isLoopback } from '../auth.js';
|
|
7
|
+
import { getString, getStringArray, isJsonBoolean, isJsonString, isSetMember, parseJsonBody, parseListLimit, validateIdSegment } from '../validation.js';
|
|
8
|
+
const VALID_KINDS = new Set([
|
|
9
|
+
'raw',
|
|
10
|
+
'distilled',
|
|
11
|
+
'superseded',
|
|
12
|
+
'archived',
|
|
13
|
+
]);
|
|
14
|
+
// POST /v1/memories
|
|
15
|
+
export async function handleCreateMemory({ req, res, opts }) {
|
|
16
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
17
|
+
const body = await parseJsonBody(req, ctx);
|
|
18
|
+
const content = getString(body, 'content');
|
|
19
|
+
if (!content) {
|
|
20
|
+
throw new HttpError(400, 'content is required');
|
|
21
|
+
}
|
|
22
|
+
const kindRaw = getString(body, 'kind');
|
|
23
|
+
if (kindRaw !== undefined && !isSetMember(VALID_KINDS, kindRaw)) {
|
|
24
|
+
throw new HttpError(400, `invalid kind: ${kindRaw}`);
|
|
25
|
+
}
|
|
26
|
+
const result = remember(ctx, {
|
|
27
|
+
content,
|
|
28
|
+
kind: kindRaw,
|
|
29
|
+
scope: getString(body, 'scope'),
|
|
30
|
+
owner: getString(body, 'owner'),
|
|
31
|
+
artifactRef: getString(body, 'artifactRef'),
|
|
32
|
+
tags: getStringArray(body, 'tags'),
|
|
33
|
+
});
|
|
34
|
+
sendJson(res, 200, result);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// GET /v1/graph?entity=NAME&limit=N — read-only entity/relation graph (tenant-scoped)
|
|
38
|
+
export async function handleGetGraph({ req, res, opts, query }) {
|
|
39
|
+
const entityRaw = query.get('entity');
|
|
40
|
+
// Cap at the graph entity-name cap (512), not the id-shaped 256, so a valid
|
|
41
|
+
// long decision/policy name remains focusable over HTTP (codex P2).
|
|
42
|
+
if (entityRaw !== null && entityRaw.length > MAX_ENTITY_NAME_LEN) {
|
|
43
|
+
throw new HttpError(400, `entity exceeds the ${MAX_ENTITY_NAME_LEN}-character cap`);
|
|
44
|
+
}
|
|
45
|
+
const limit = parseListLimit(query.get('limit'));
|
|
46
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
47
|
+
const model = buildGraphModel(ctx.hippoRoot, ctx.tenantId, {
|
|
48
|
+
entity: entityRaw ?? undefined,
|
|
49
|
+
limit,
|
|
50
|
+
});
|
|
51
|
+
sendJson(res, 200, model);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// /v1/memories/:id/* and DELETE /v1/memories/:id
|
|
55
|
+
export async function handleArchiveMemory({ req, res, opts }, archiveMatch) {
|
|
56
|
+
validateIdSegment(archiveMatch.id, 'memory id');
|
|
57
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
58
|
+
const body = await parseJsonBody(req, ctx);
|
|
59
|
+
const reason = getString(body, 'reason');
|
|
60
|
+
if (!reason) {
|
|
61
|
+
throw new HttpError(400, 'reason is required');
|
|
62
|
+
}
|
|
63
|
+
const result = archiveRaw(ctx, archiveMatch.id, reason);
|
|
64
|
+
sendJson(res, 200, result);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
export async function handleSupersedeMemory({ req, res, opts }, supersedeMatch) {
|
|
68
|
+
validateIdSegment(supersedeMatch.id, 'memory id');
|
|
69
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
70
|
+
const body = await parseJsonBody(req, ctx);
|
|
71
|
+
const content = getString(body, 'content');
|
|
72
|
+
if (!content) {
|
|
73
|
+
throw new HttpError(400, 'content is required');
|
|
74
|
+
}
|
|
75
|
+
const result = supersede(ctx, supersedeMatch.id, content);
|
|
76
|
+
sendJson(res, 200, result);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
export async function handlePromoteMemory({ req, res, opts }, promoteMatch) {
|
|
80
|
+
validateIdSegment(promoteMatch.id, 'memory id');
|
|
81
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
82
|
+
const result = promote(ctx, promoteMatch.id);
|
|
83
|
+
sendJson(res, 200, result);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
export async function handleForgetMemory({ req, res, opts }, idMatch) {
|
|
87
|
+
validateIdSegment(idMatch.id, 'memory id');
|
|
88
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
89
|
+
const result = forget(ctx, idMatch.id);
|
|
90
|
+
sendJson(res, 200, result);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// POST /v1/outcome — apply a positive/negative outcome to memory ids.
|
|
94
|
+
// Body: {ids?: string[], good: boolean}. If ids omitted, falls back to
|
|
95
|
+
// the last-recall path (api.outcomeForLastRecall); returned shape is
|
|
96
|
+
// {applied, ids} in that case so callers can disambiguate "no recent
|
|
97
|
+
// recall" from "all ids skipped". Each applied id writes one audit_log
|
|
98
|
+
// row (op='outcome', actor from Bearer).
|
|
99
|
+
export async function handleApplyOutcome({ req, res, opts }) {
|
|
100
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
101
|
+
const body = await parseJsonBody(req, ctx);
|
|
102
|
+
const good = body['good'];
|
|
103
|
+
if (!isJsonBoolean(good)) {
|
|
104
|
+
throw new HttpError(400, 'good is required (boolean)');
|
|
105
|
+
}
|
|
106
|
+
const idsRaw = body['ids'];
|
|
107
|
+
let ids;
|
|
108
|
+
if (idsRaw !== undefined) {
|
|
109
|
+
if (!Array.isArray(idsRaw)) {
|
|
110
|
+
throw new HttpError(400, 'ids must be an array of non-empty strings');
|
|
111
|
+
}
|
|
112
|
+
const isNonEmptyId = (item) => isJsonString(item) && item.length > 0;
|
|
113
|
+
if (!idsRaw.every(isNonEmptyId)) {
|
|
114
|
+
throw new HttpError(400, 'ids must be an array of non-empty strings');
|
|
115
|
+
}
|
|
116
|
+
// v1.11.5: DoS cap on ids.length. Each id triggers ~3 DB ops (readEntry +
|
|
117
|
+
// writeEntry + appendAuditEvent). N=1000 keeps per-request work bounded
|
|
118
|
+
// to sub-second wall time on SQLite hot path. Cap BEFORE buildContextWithAuth
|
|
119
|
+
// so attack traffic doesn't pay the api-key lookup cost.
|
|
120
|
+
if (idsRaw.length > 1000) {
|
|
121
|
+
throw new HttpError(400, 'ids exceeds 1000-id cap');
|
|
122
|
+
}
|
|
123
|
+
ids = idsRaw;
|
|
124
|
+
}
|
|
125
|
+
if (ids !== undefined) {
|
|
126
|
+
const { applied } = outcome(ctx, ids, good);
|
|
127
|
+
sendJson(res, 200, { applied });
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
const result = outcomeForLastRecall(ctx, good);
|
|
131
|
+
sendJson(res, 200, result);
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// POST /v1/sleep — host-wide consolidation pipeline (consolidate + dedup +
|
|
136
|
+
// audit + share + ambient). serve() refuses non-loopback hosts at boot, AND
|
|
137
|
+
// this per-request loopback assertion makes the host-wide semantic fail-
|
|
138
|
+
// closed regardless of any future serve() boot-config change. Body:
|
|
139
|
+
// {dry_run?, no_share?}. Returns SleepResult JSON.
|
|
140
|
+
//
|
|
141
|
+
// Tenant scope (Episode A follow-up tracked in TODOS.md): api.sleep operates
|
|
142
|
+
// on the WHOLE hippoRoot (cross-tenant by design, matching CLI cmdSleep).
|
|
143
|
+
// The loopback-only guard is the trust boundary today. Future non-loopback
|
|
144
|
+
// serving must also zero the cross-tenant counters for other tenants
|
|
145
|
+
// (D1 in docs/decisions/2026-05-24-blocked-items.md).
|
|
146
|
+
export async function handleSleep({ req, res, opts }) {
|
|
147
|
+
// Defensive per-request loopback guard. Uses the canonical isLoopback()
|
|
148
|
+
// helper above so any future extension (additional mapped/IPv6 forms,
|
|
149
|
+
// NAT64 prefixes) flows through without drift. serve()'s boot-time host
|
|
150
|
+
// check is the primary trust boundary; this is belt-and-suspenders.
|
|
151
|
+
if (!isLoopback(req.socket.remoteAddress)) {
|
|
152
|
+
throw new HttpError(403, '/v1/sleep is loopback-only (host-wide consolidation; see CHANGELOG v1.11.4)');
|
|
153
|
+
}
|
|
154
|
+
// v1.12.0 A5 v2 sub-1: admin-role gate. Forward-defensive — exists today
|
|
155
|
+
// under loopback-only enforcement (loopback fallback is admin by default;
|
|
156
|
+
// any Bearer-authed caller now carries an explicit role from the api_keys
|
|
157
|
+
// row). When non-loopback serving lands, this gate is the actual auth
|
|
158
|
+
// boundary on host-wide sleep.
|
|
159
|
+
const sleepCtx = await buildContextWithAuth(req, opts);
|
|
160
|
+
// Sleep consolidates every tenant under hippoRoot, so it is a cross-tenant action.
|
|
161
|
+
assertCrossTenantAdmin(sleepCtx, '/v1/sleep');
|
|
162
|
+
const body = await parseJsonBody(req, sleepCtx);
|
|
163
|
+
const dryRunRaw = body['dry_run'];
|
|
164
|
+
if (dryRunRaw !== undefined && !isJsonBoolean(dryRunRaw)) {
|
|
165
|
+
throw new HttpError(400, 'dry_run must be a boolean');
|
|
166
|
+
}
|
|
167
|
+
const noShareRaw = body['no_share'];
|
|
168
|
+
if (noShareRaw !== undefined && !isJsonBoolean(noShareRaw)) {
|
|
169
|
+
throw new HttpError(400, 'no_share must be a boolean');
|
|
170
|
+
}
|
|
171
|
+
// v1.12.0: sleepCtx already built above for the admin-role gate; reuse.
|
|
172
|
+
const result = await sleep(sleepCtx, {
|
|
173
|
+
dryRun: dryRunRaw === true,
|
|
174
|
+
noShare: noShareRaw === true,
|
|
175
|
+
});
|
|
176
|
+
sendJson(res, 200, result);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=memories.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreatePolicy({ req, res, opts }: RouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListPolicies({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
4
|
+
export declare function handlePoliciesAsOf({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
5
|
+
export declare function handleSupersedePolicy({ req, res, opts }: RouteRequest, policySupersedeMatch: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleClosePolicy({ req, res, opts }: RouteRequest, policyCloseMatch: RegExpMatchArray): Promise<void>;
|
|
7
|
+
export declare function handleGetPolicy({ req, res, opts }: RouteRequest, policyByIdMatch: RegExpMatchArray): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=policies.d.ts.map
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// /v1/policies routes.
|
|
2
|
+
import { closePolicy, loadPolicies, loadPoliciesAsOf, loadPolicyById, savePolicy, VALID_POLICY_STATES } from '../../policies.js';
|
|
3
|
+
import { HttpError, sendJson } from '../../http-util.js';
|
|
4
|
+
import { buildContextWithAuth } from '../auth.js';
|
|
5
|
+
import { byCreatedAt, pageOf, parseCursor } from '../cursor.js';
|
|
6
|
+
import { isJsonString, isSetMember, parseJsonBody, parseListLimit } from '../validation.js';
|
|
7
|
+
// HTTP-boundary check for an optional policy date field (validFrom/validTo).
|
|
8
|
+
// Type + length only; savePolicy/loadPoliciesAsOf normalize + format-validate the
|
|
9
|
+
// value (an unparseable date throws there -> mapped to 400). 64-char cap bounds a
|
|
10
|
+
// junk string before it reaches the Date parser.
|
|
11
|
+
function optionalDateField(raw, label) {
|
|
12
|
+
if (raw === undefined || raw === null)
|
|
13
|
+
return undefined;
|
|
14
|
+
if (!isJsonString(raw)) {
|
|
15
|
+
throw new HttpError(400, `${label} must be a string`);
|
|
16
|
+
}
|
|
17
|
+
if (raw.length > 64) {
|
|
18
|
+
throw new HttpError(400, `${label} exceeds 64-character cap`);
|
|
19
|
+
}
|
|
20
|
+
return raw;
|
|
21
|
+
}
|
|
22
|
+
// ── policies (E2 first-class object, bi-temporal-first) ──
|
|
23
|
+
//
|
|
24
|
+
// 6 routes: POST /v1/policies (new; processName-style body policyName +
|
|
25
|
+
// policyText + validFrom? + validTo?), GET /v1/policies (list, status filter),
|
|
26
|
+
// GET /v1/policies/asof (date + optional name; the bi-temporal as-of query;
|
|
27
|
+
// placed BEFORE the /:id GET so the literal 'asof' is matched first), GET
|
|
28
|
+
// /v1/policies/:id, POST /v1/policies/:id/supersede, POST /v1/policies/:id/close.
|
|
29
|
+
// Date inputs are normalized + range-validated in the store; an invalid/inverted
|
|
30
|
+
// date throws -> 400. DoS caps: policyName/policyText/changeSummary 4096.
|
|
31
|
+
export async function handleCreatePolicy({ req, res, opts }) {
|
|
32
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
33
|
+
const body = await parseJsonBody(req, ctx);
|
|
34
|
+
const policyName = body['policyName'];
|
|
35
|
+
if (!isJsonString(policyName) || policyName.trim().length === 0) {
|
|
36
|
+
throw new HttpError(400, 'policyName is required (non-empty string)');
|
|
37
|
+
}
|
|
38
|
+
if (policyName.length > 4096) {
|
|
39
|
+
throw new HttpError(400, 'policyName exceeds 4096-character cap');
|
|
40
|
+
}
|
|
41
|
+
const policyText = body['policyText'];
|
|
42
|
+
if (!isJsonString(policyText) || policyText.trim().length === 0) {
|
|
43
|
+
throw new HttpError(400, 'policyText is required (non-empty string)');
|
|
44
|
+
}
|
|
45
|
+
if (policyText.length > 4096) {
|
|
46
|
+
throw new HttpError(400, 'policyText exceeds 4096-character cap');
|
|
47
|
+
}
|
|
48
|
+
const validFrom = optionalDateField(body['validFrom'], 'validFrom');
|
|
49
|
+
const validTo = optionalDateField(body['validTo'], 'validTo');
|
|
50
|
+
const policy = savePolicy(opts.hippoRoot, ctx.tenantId, {
|
|
51
|
+
policyName,
|
|
52
|
+
policyText,
|
|
53
|
+
validFrom,
|
|
54
|
+
validTo,
|
|
55
|
+
}, ctx.actor.subject);
|
|
56
|
+
sendJson(res, 201, { policy });
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
export async function handleListPolicies({ req, res, opts, query }) {
|
|
60
|
+
const status = query.get('status') ?? 'all';
|
|
61
|
+
const limit = parseListLimit(query.get('limit'));
|
|
62
|
+
const after = parseCursor(query.get('cursor'), 'string', 'integer');
|
|
63
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
64
|
+
let policies;
|
|
65
|
+
if (status === 'all') {
|
|
66
|
+
policies = loadPolicies(opts.hippoRoot, ctx.tenantId, { limit: limit + 1, after });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
if (!isSetMember(VALID_POLICY_STATES, status)) {
|
|
70
|
+
throw new HttpError(400, `status must be one of: active | superseded | closed | all (got "${status}")`);
|
|
71
|
+
}
|
|
72
|
+
policies = loadPolicies(opts.hippoRoot, ctx.tenantId, {
|
|
73
|
+
status,
|
|
74
|
+
limit: limit + 1,
|
|
75
|
+
after,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const page = pageOf(policies, limit, byCreatedAt);
|
|
79
|
+
sendJson(res, 200, { policies: page.items, next_cursor: page.nextCursor });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// The as-of query: must precede the /:id GET (literal 'asof' is non-numeric so
|
|
83
|
+
// the /(\d+)/ route would not match it, but order it first for clarity).
|
|
84
|
+
export async function handlePoliciesAsOf({ req, res, opts, query }) {
|
|
85
|
+
const date = query.get('date');
|
|
86
|
+
if (date === null || date.length === 0) {
|
|
87
|
+
throw new HttpError(400, 'date is required (ISO-8601 valid-time)');
|
|
88
|
+
}
|
|
89
|
+
const name = query.get('name') ?? undefined;
|
|
90
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
91
|
+
const policies = loadPoliciesAsOf(opts.hippoRoot, ctx.tenantId, date, { name });
|
|
92
|
+
sendJson(res, 200, { policies });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
export async function handleSupersedePolicy({ req, res, opts }, policySupersedeMatch) {
|
|
96
|
+
const id = parseInt(policySupersedeMatch[1], 10);
|
|
97
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
98
|
+
const body = await parseJsonBody(req, ctx);
|
|
99
|
+
const policyText = body['policyText'];
|
|
100
|
+
if (!isJsonString(policyText) || policyText.trim().length === 0) {
|
|
101
|
+
throw new HttpError(400, 'policyText is required (non-empty string)');
|
|
102
|
+
}
|
|
103
|
+
if (policyText.length > 4096) {
|
|
104
|
+
throw new HttpError(400, 'policyText exceeds 4096-character cap');
|
|
105
|
+
}
|
|
106
|
+
const validFrom = optionalDateField(body['validFrom'], 'validFrom');
|
|
107
|
+
const validTo = optionalDateField(body['validTo'], 'validTo');
|
|
108
|
+
const changeRaw = body['changeSummary'];
|
|
109
|
+
let changeSummary;
|
|
110
|
+
if (changeRaw !== undefined && changeRaw !== null) {
|
|
111
|
+
if (!isJsonString(changeRaw)) {
|
|
112
|
+
throw new HttpError(400, 'changeSummary must be a string');
|
|
113
|
+
}
|
|
114
|
+
if (changeRaw.length > 4096) {
|
|
115
|
+
throw new HttpError(400, 'changeSummary exceeds 4096-character cap');
|
|
116
|
+
}
|
|
117
|
+
changeSummary = changeRaw;
|
|
118
|
+
}
|
|
119
|
+
const existing = loadPolicyById(opts.hippoRoot, ctx.tenantId, id);
|
|
120
|
+
if (!existing) {
|
|
121
|
+
throw new HttpError(404, `policy ${id} not found`);
|
|
122
|
+
}
|
|
123
|
+
const policy = savePolicy(opts.hippoRoot, ctx.tenantId, {
|
|
124
|
+
policyName: existing.policyName,
|
|
125
|
+
policyText,
|
|
126
|
+
validFrom,
|
|
127
|
+
validTo,
|
|
128
|
+
changeSummary,
|
|
129
|
+
supersedesPolicyId: id,
|
|
130
|
+
}, ctx.actor.subject);
|
|
131
|
+
sendJson(res, 200, { policy });
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
export async function handleClosePolicy({ req, res, opts }, policyCloseMatch) {
|
|
135
|
+
const id = parseInt(policyCloseMatch[1], 10);
|
|
136
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
137
|
+
const policy = closePolicy(opts.hippoRoot, ctx.tenantId, id, ctx.actor.subject);
|
|
138
|
+
sendJson(res, 200, { policy });
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
export async function handleGetPolicy({ req, res, opts }, policyByIdMatch) {
|
|
142
|
+
const id = parseInt(policyByIdMatch[1], 10);
|
|
143
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
144
|
+
const policy = loadPolicyById(opts.hippoRoot, ctx.tenantId, id);
|
|
145
|
+
if (!policy) {
|
|
146
|
+
throw new HttpError(404, `policy ${id} not found`);
|
|
147
|
+
}
|
|
148
|
+
sendJson(res, 200, { policy });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=policies.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreatePrediction({ req, res, opts }: RouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListPredictions({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
4
|
+
export declare function handlePredictionStats({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
5
|
+
export declare function handleGetPrediction({ req, res, opts }: RouteRequest, predictionByIdMatch: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleClosePrediction({ req, res, opts }: RouteRequest, predictionCloseMatch: RegExpMatchArray): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=predictions.d.ts.map
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// /v1/predictions routes.
|
|
2
|
+
import { closePrediction, computePredictionBaserate, loadOpenPredictions, loadPredictionById, loadPredictionsByClass, savePrediction, VALID_CLOSURE_STATES } from '../../predictions/store.js';
|
|
3
|
+
import { HttpError, sendJson } from '../../http-util.js';
|
|
4
|
+
import { buildContextWithAuth } from '../auth.js';
|
|
5
|
+
import { byCreatedAt, pageOf, parseCursor } from '../cursor.js';
|
|
6
|
+
import { isJsonNumber, isJsonString, isSetMember, parseJsonBody, parseListLimit } from '../validation.js';
|
|
7
|
+
// ── E2 prediction first-class object (v0.31) ──
|
|
8
|
+
// docs/plans/2026-05-26-e2-prediction-object.md
|
|
9
|
+
//
|
|
10
|
+
// 4 routes: POST /v1/predictions (create), GET /v1/predictions (list),
|
|
11
|
+
// GET /v1/predictions/:id (show), POST /v1/predictions/:id/close (close).
|
|
12
|
+
// All Bearer-authed + tenant-scoped via buildContextWithAuth. closure_state
|
|
13
|
+
// validated against VALID_CLOSURE_STATES (3 states). DoS caps on claim
|
|
14
|
+
// (4096 chars) + closureNote (2048 chars) per v1.11.4 pattern.
|
|
15
|
+
export async function handleCreatePrediction({ req, res, opts }) {
|
|
16
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
17
|
+
const body = await parseJsonBody(req, ctx);
|
|
18
|
+
const claim = body['claim'];
|
|
19
|
+
if (!isJsonString(claim) || claim.length === 0) {
|
|
20
|
+
throw new HttpError(400, 'claim is required (non-empty string)');
|
|
21
|
+
}
|
|
22
|
+
if (claim.length > 4096) {
|
|
23
|
+
throw new HttpError(400, 'claim exceeds 4096-character cap');
|
|
24
|
+
}
|
|
25
|
+
const classTag = body['classTag'];
|
|
26
|
+
if (!isJsonString(classTag) || classTag.length === 0) {
|
|
27
|
+
throw new HttpError(400, 'classTag is required (non-empty string)');
|
|
28
|
+
}
|
|
29
|
+
const estimate = body['estimate'];
|
|
30
|
+
let estimateValue;
|
|
31
|
+
if (estimate !== undefined && estimate !== null) {
|
|
32
|
+
if (!isJsonNumber(estimate) || !Number.isFinite(estimate)) {
|
|
33
|
+
throw new HttpError(400, 'estimate must be a finite number');
|
|
34
|
+
}
|
|
35
|
+
estimateValue = estimate;
|
|
36
|
+
}
|
|
37
|
+
const unit = body['unit'];
|
|
38
|
+
let estimateUnit;
|
|
39
|
+
if (unit !== undefined && unit !== null) {
|
|
40
|
+
if (!isJsonString(unit)) {
|
|
41
|
+
throw new HttpError(400, 'unit must be a string');
|
|
42
|
+
}
|
|
43
|
+
estimateUnit = unit;
|
|
44
|
+
}
|
|
45
|
+
const targetDate = body['targetDate'];
|
|
46
|
+
let targetDateValue;
|
|
47
|
+
if (targetDate !== undefined && targetDate !== null) {
|
|
48
|
+
if (!isJsonString(targetDate)) {
|
|
49
|
+
throw new HttpError(400, 'targetDate must be an ISO date string');
|
|
50
|
+
}
|
|
51
|
+
targetDateValue = targetDate;
|
|
52
|
+
}
|
|
53
|
+
const prediction = savePrediction(opts.hippoRoot, ctx.tenantId, {
|
|
54
|
+
classTag,
|
|
55
|
+
claimText: claim,
|
|
56
|
+
estimateValue,
|
|
57
|
+
estimateUnit,
|
|
58
|
+
targetDate: targetDateValue,
|
|
59
|
+
}, ctx.actor.subject);
|
|
60
|
+
sendJson(res, 201, { prediction });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
export async function handleListPredictions({ req, res, opts, query }) {
|
|
64
|
+
const classTag = query.get('class') ?? undefined;
|
|
65
|
+
const status = query.get('status') ?? 'all';
|
|
66
|
+
const limit = parseListLimit(query.get('limit'));
|
|
67
|
+
const after = parseCursor(query.get('cursor'), 'string', 'integer');
|
|
68
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
69
|
+
let predictions;
|
|
70
|
+
if (status === 'all') {
|
|
71
|
+
if (classTag) {
|
|
72
|
+
predictions = loadPredictionsByClass(opts.hippoRoot, ctx.tenantId, classTag, { limit: limit + 1, after });
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
predictions = loadOpenPredictions(opts.hippoRoot, ctx.tenantId, { limit: limit + 1, after });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else if (status === 'open') {
|
|
79
|
+
predictions = loadOpenPredictions(opts.hippoRoot, ctx.tenantId, {
|
|
80
|
+
classTag: classTag || undefined,
|
|
81
|
+
limit: limit + 1,
|
|
82
|
+
after,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
if (!isSetMember(VALID_CLOSURE_STATES, status)) {
|
|
87
|
+
throw new HttpError(400, `status must be one of: open | closed | closed-unknown | all (got "${status}")`);
|
|
88
|
+
}
|
|
89
|
+
if (!classTag) {
|
|
90
|
+
throw new HttpError(400, 'status filter (non-open) requires class param');
|
|
91
|
+
}
|
|
92
|
+
predictions = loadPredictionsByClass(opts.hippoRoot, ctx.tenantId, classTag, {
|
|
93
|
+
closureState: status,
|
|
94
|
+
limit: limit + 1,
|
|
95
|
+
after,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const page = pageOf(predictions, limit, byCreatedAt);
|
|
99
|
+
sendJson(res, 200, { predictions: page.items, next_cursor: page.nextCursor });
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// J3 reference-class / planning-fallacy detector (v0.31).
|
|
103
|
+
// Order matters: this must match BEFORE /v1/predictions/:id since 'stats'
|
|
104
|
+
// is not a number — the :id regex requires \d+ so they don't conflict,
|
|
105
|
+
// but routing this first avoids the dispatch order risk.
|
|
106
|
+
export async function handlePredictionStats({ req, res, opts, query }) {
|
|
107
|
+
const classTag = query.get('class');
|
|
108
|
+
if (!classTag || classTag.length === 0) {
|
|
109
|
+
throw new HttpError(400, 'class param is required');
|
|
110
|
+
}
|
|
111
|
+
if (classTag.length > 256) {
|
|
112
|
+
throw new HttpError(400, 'class exceeds 256-character cap');
|
|
113
|
+
}
|
|
114
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
115
|
+
const baserate = computePredictionBaserate(opts.hippoRoot, ctx.tenantId, classTag, ctx.actor.subject);
|
|
116
|
+
sendJson(res, 200, { baserate });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
export async function handleGetPrediction({ req, res, opts }, predictionByIdMatch) {
|
|
120
|
+
const id = parseInt(predictionByIdMatch[1], 10);
|
|
121
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
122
|
+
const prediction = loadPredictionById(opts.hippoRoot, ctx.tenantId, id);
|
|
123
|
+
if (!prediction) {
|
|
124
|
+
throw new HttpError(404, `prediction ${id} not found`);
|
|
125
|
+
}
|
|
126
|
+
sendJson(res, 200, { prediction });
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
export async function handleClosePrediction({ req, res, opts }, predictionCloseMatch) {
|
|
130
|
+
const id = parseInt(predictionCloseMatch[1], 10);
|
|
131
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
132
|
+
const body = await parseJsonBody(req, ctx);
|
|
133
|
+
const state = body['state'];
|
|
134
|
+
if (!isJsonString(state) || !isSetMember(VALID_CLOSURE_STATES, state) || state === 'open') {
|
|
135
|
+
throw new HttpError(400, 'state is required and must be one of: closed | closed-unknown');
|
|
136
|
+
}
|
|
137
|
+
const actual = body['actual'];
|
|
138
|
+
let actualValue;
|
|
139
|
+
if (actual !== undefined && actual !== null) {
|
|
140
|
+
if (!isJsonNumber(actual) || !Number.isFinite(actual)) {
|
|
141
|
+
throw new HttpError(400, 'actual must be a finite number');
|
|
142
|
+
}
|
|
143
|
+
actualValue = actual;
|
|
144
|
+
}
|
|
145
|
+
const note = body['note'];
|
|
146
|
+
let closureNote;
|
|
147
|
+
if (note !== undefined && note !== null) {
|
|
148
|
+
if (!isJsonString(note)) {
|
|
149
|
+
throw new HttpError(400, 'note must be a string');
|
|
150
|
+
}
|
|
151
|
+
if (note.length > 2048) {
|
|
152
|
+
throw new HttpError(400, 'note exceeds 2048-character cap');
|
|
153
|
+
}
|
|
154
|
+
closureNote = note;
|
|
155
|
+
}
|
|
156
|
+
const prediction = closePrediction(opts.hippoRoot, ctx.tenantId, id, {
|
|
157
|
+
closureState: state,
|
|
158
|
+
actualValue,
|
|
159
|
+
closureNote,
|
|
160
|
+
}, ctx.actor.subject);
|
|
161
|
+
sendJson(res, 200, { prediction });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=predictions.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateProcess({ req, res, opts }: RouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListProcesses({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleSupersedeProcess({ req, res, opts }: RouteRequest, processSupersedeMatch: RegExpMatchArray): Promise<void>;
|
|
5
|
+
export declare function handleCloseProcess({ req, res, opts }: RouteRequest, processCloseMatch: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleGetProcess({ req, res, opts }: RouteRequest, processByIdMatch: RegExpMatchArray): Promise<void>;
|
|
7
|
+
//# sourceMappingURL=processes.d.ts.map
|