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,161 @@
|
|
|
1
|
+
// /v1/processes routes.
|
|
2
|
+
import { closeProcess, loadProcessById, loadProcesses, saveProcess, VALID_PROCESS_STATES } from '../../processes.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 validation for a process `steps` body (untrusted). Returns the
|
|
8
|
+
// step strings (saveProcess re-validates + trims, this is the fail-fast 400
|
|
9
|
+
// gate). Caps mirror src/processes.ts MAX_PROCESS_STEPS / MAX_PROCESS_STEP_LEN.
|
|
10
|
+
function validateProcessStepsBody(raw) {
|
|
11
|
+
if (raw === undefined || raw === null)
|
|
12
|
+
return [];
|
|
13
|
+
if (!Array.isArray(raw)) {
|
|
14
|
+
throw new HttpError(400, 'steps must be an array of strings');
|
|
15
|
+
}
|
|
16
|
+
if (raw.length > 200) {
|
|
17
|
+
throw new HttpError(400, 'steps exceeds 200-step cap');
|
|
18
|
+
}
|
|
19
|
+
for (const item of raw) {
|
|
20
|
+
if (!isJsonString(item)) {
|
|
21
|
+
throw new HttpError(400, 'each step must be a string');
|
|
22
|
+
}
|
|
23
|
+
if (item.trim().length === 0) {
|
|
24
|
+
throw new HttpError(400, 'a step is empty');
|
|
25
|
+
}
|
|
26
|
+
if (item.length > 2000) {
|
|
27
|
+
throw new HttpError(400, 'a step exceeds the 2000-character cap');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// SAFETY: every item in raw was confirmed to be a string in the loop above.
|
|
31
|
+
return raw;
|
|
32
|
+
}
|
|
33
|
+
// ── processes (E2 first-class object) ──
|
|
34
|
+
//
|
|
35
|
+
// 5 routes: POST /v1/processes (new; body processName + steps[] + description),
|
|
36
|
+
// GET /v1/processes (list, status filter), GET /v1/processes/:id (show),
|
|
37
|
+
// POST /v1/processes/:id/supersede (active -> superseded by a new version; body
|
|
38
|
+
// steps[] + changeSummary + description; reuses the predecessor's name),
|
|
39
|
+
// POST /v1/processes/:id/close (active -> closed). Bearer-authed + tenant-scoped
|
|
40
|
+
// via buildContextWithAuth. status validated against VALID_PROCESS_STATES. DoS
|
|
41
|
+
// caps: processName/description/changeSummary 4096, steps 200x2000
|
|
42
|
+
// (validateProcessStepsBody). Mirrors /v1/decisions; the delta lifecycle is the
|
|
43
|
+
// decision supersede path.
|
|
44
|
+
export async function handleCreateProcess({ req, res, opts }) {
|
|
45
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
46
|
+
const body = await parseJsonBody(req, ctx);
|
|
47
|
+
const processName = body['processName'];
|
|
48
|
+
if (!isJsonString(processName) || processName.trim().length === 0) {
|
|
49
|
+
throw new HttpError(400, 'processName is required (non-empty string)');
|
|
50
|
+
}
|
|
51
|
+
if (processName.length > 4096) {
|
|
52
|
+
throw new HttpError(400, 'processName exceeds 4096-character cap');
|
|
53
|
+
}
|
|
54
|
+
const steps = validateProcessStepsBody(body['steps']);
|
|
55
|
+
const descriptionRaw = body['description'];
|
|
56
|
+
let description;
|
|
57
|
+
if (descriptionRaw !== undefined && descriptionRaw !== null) {
|
|
58
|
+
if (!isJsonString(descriptionRaw)) {
|
|
59
|
+
throw new HttpError(400, 'description must be a string');
|
|
60
|
+
}
|
|
61
|
+
if (descriptionRaw.length > 4096) {
|
|
62
|
+
throw new HttpError(400, 'description exceeds 4096-character cap');
|
|
63
|
+
}
|
|
64
|
+
description = descriptionRaw;
|
|
65
|
+
}
|
|
66
|
+
const process = saveProcess(opts.hippoRoot, ctx.tenantId, {
|
|
67
|
+
processName,
|
|
68
|
+
steps,
|
|
69
|
+
description,
|
|
70
|
+
}, ctx.actor.subject);
|
|
71
|
+
sendJson(res, 201, { process });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
export async function handleListProcesses({ req, res, opts, query }) {
|
|
75
|
+
const status = query.get('status') ?? 'all';
|
|
76
|
+
const limit = parseListLimit(query.get('limit'));
|
|
77
|
+
const after = parseCursor(query.get('cursor'), 'string', 'integer');
|
|
78
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
79
|
+
let processes;
|
|
80
|
+
if (status === 'all') {
|
|
81
|
+
processes = loadProcesses(opts.hippoRoot, ctx.tenantId, { limit: limit + 1, after });
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
if (!isSetMember(VALID_PROCESS_STATES, status)) {
|
|
85
|
+
throw new HttpError(400, `status must be one of: active | superseded | closed | all (got "${status}")`);
|
|
86
|
+
}
|
|
87
|
+
processes = loadProcesses(opts.hippoRoot, ctx.tenantId, {
|
|
88
|
+
status,
|
|
89
|
+
limit: limit + 1,
|
|
90
|
+
after,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const page = pageOf(processes, limit, byCreatedAt);
|
|
94
|
+
sendJson(res, 200, { processes: page.items, next_cursor: page.nextCursor });
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
export async function handleSupersedeProcess({ req, res, opts }, processSupersedeMatch) {
|
|
98
|
+
const id = parseInt(processSupersedeMatch[1], 10);
|
|
99
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
100
|
+
const body = await parseJsonBody(req, ctx);
|
|
101
|
+
const steps = validateProcessStepsBody(body['steps']);
|
|
102
|
+
if (steps.length === 0) {
|
|
103
|
+
throw new HttpError(400, 'steps is required (at least one step) for a supersession');
|
|
104
|
+
}
|
|
105
|
+
const changeRaw = body['changeSummary'];
|
|
106
|
+
let changeSummary;
|
|
107
|
+
if (changeRaw !== undefined && changeRaw !== null) {
|
|
108
|
+
if (!isJsonString(changeRaw)) {
|
|
109
|
+
throw new HttpError(400, 'changeSummary must be a string');
|
|
110
|
+
}
|
|
111
|
+
if (changeRaw.length > 4096) {
|
|
112
|
+
throw new HttpError(400, 'changeSummary exceeds 4096-character cap');
|
|
113
|
+
}
|
|
114
|
+
changeSummary = changeRaw;
|
|
115
|
+
}
|
|
116
|
+
const descRaw = body['description'];
|
|
117
|
+
let description;
|
|
118
|
+
if (descRaw !== undefined && descRaw !== null) {
|
|
119
|
+
if (!isJsonString(descRaw)) {
|
|
120
|
+
throw new HttpError(400, 'description must be a string');
|
|
121
|
+
}
|
|
122
|
+
if (descRaw.length > 4096) {
|
|
123
|
+
throw new HttpError(400, 'description exceeds 4096-character cap');
|
|
124
|
+
}
|
|
125
|
+
description = descRaw;
|
|
126
|
+
}
|
|
127
|
+
// A supersession is a new version of the SAME process: reuse the
|
|
128
|
+
// predecessor's name. 404 if the target does not exist; saveProcess's
|
|
129
|
+
// in-SAVEPOINT preflight is the authoritative active-state check (409).
|
|
130
|
+
const existing = loadProcessById(opts.hippoRoot, ctx.tenantId, id);
|
|
131
|
+
if (!existing) {
|
|
132
|
+
throw new HttpError(404, `process ${id} not found`);
|
|
133
|
+
}
|
|
134
|
+
const process = saveProcess(opts.hippoRoot, ctx.tenantId, {
|
|
135
|
+
processName: existing.processName,
|
|
136
|
+
steps,
|
|
137
|
+
description,
|
|
138
|
+
changeSummary,
|
|
139
|
+
supersedesProcessId: id,
|
|
140
|
+
}, ctx.actor.subject);
|
|
141
|
+
sendJson(res, 200, { process });
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
export async function handleCloseProcess({ req, res, opts }, processCloseMatch) {
|
|
145
|
+
const id = parseInt(processCloseMatch[1], 10);
|
|
146
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
147
|
+
const process = closeProcess(opts.hippoRoot, ctx.tenantId, id, ctx.actor.subject);
|
|
148
|
+
sendJson(res, 200, { process });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
export async function handleGetProcess({ req, res, opts }, processByIdMatch) {
|
|
152
|
+
const id = parseInt(processByIdMatch[1], 10);
|
|
153
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
154
|
+
const process = loadProcessById(opts.hippoRoot, ctx.tenantId, id);
|
|
155
|
+
if (!process) {
|
|
156
|
+
throw new HttpError(404, `process ${id} not found`);
|
|
157
|
+
}
|
|
158
|
+
sendJson(res, 200, { process });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=processes.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateProjectBrief({ req, res, opts }: RouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListProjectBriefs({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleRefreshProjectBrief({ req, res, opts }: RouteRequest): Promise<void>;
|
|
5
|
+
export declare function handleSupersedeProjectBrief({ req, res, opts }: RouteRequest, briefSupersedeMatch: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleCloseProjectBrief({ req, res, opts }: RouteRequest, briefCloseMatch: RegExpMatchArray): Promise<void>;
|
|
7
|
+
export declare function handleGetProjectBrief({ req, res, opts }: RouteRequest, briefByIdMatch: RegExpMatchArray): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=project-briefs.d.ts.map
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// /v1/project-briefs routes.
|
|
2
|
+
import { assembleBriefFromReceipts, closeProjectBrief, loadProjectBriefById, loadProjectBriefs, refreshBrief, saveProjectBrief, VALID_BRIEF_STATES } from '../../project-briefs.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
|
+
// ── E2 project_brief routes ──
|
|
8
|
+
//
|
|
9
|
+
// 6 routes: POST /v1/project-briefs (new; body repo + summary), GET
|
|
10
|
+
// /v1/project-briefs (list; status + repo filter; shared parseListLimit), POST
|
|
11
|
+
// /v1/project-briefs/refresh (body {repo, dryRun?} -> auto-assemble the brief
|
|
12
|
+
// from the repo's receipts; dryRun returns {markdown} without writing; ordered
|
|
13
|
+
// before /:id), GET /v1/project-briefs/:id, POST /v1/project-briefs/:id/supersede,
|
|
14
|
+
// POST /v1/project-briefs/:id/close. DoS caps: repo 256, summary 8192,
|
|
15
|
+
// changeSummary 4096. The store validates + throws; the boundary maps validation
|
|
16
|
+
// -> 400, not-found -> 404, not-active -> 409. Mirrors /v1/skills.
|
|
17
|
+
export async function handleCreateProjectBrief({ req, res, opts }) {
|
|
18
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
19
|
+
const body = await parseJsonBody(req, ctx);
|
|
20
|
+
const repo = body['repo'];
|
|
21
|
+
if (!isJsonString(repo) || repo.trim().length === 0) {
|
|
22
|
+
throw new HttpError(400, 'repo is required (non-empty string)');
|
|
23
|
+
}
|
|
24
|
+
if (repo.length > 256) {
|
|
25
|
+
throw new HttpError(400, 'repo exceeds 256-character cap');
|
|
26
|
+
}
|
|
27
|
+
const summary = body['summary'];
|
|
28
|
+
if (!isJsonString(summary) || summary.trim().length === 0) {
|
|
29
|
+
throw new HttpError(400, 'summary is required (non-empty string)');
|
|
30
|
+
}
|
|
31
|
+
if (summary.length > 8192) {
|
|
32
|
+
throw new HttpError(400, 'summary exceeds 8192-character cap');
|
|
33
|
+
}
|
|
34
|
+
const brief = saveProjectBrief(opts.hippoRoot, ctx.tenantId, {
|
|
35
|
+
repo,
|
|
36
|
+
summary,
|
|
37
|
+
}, ctx.actor.subject);
|
|
38
|
+
sendJson(res, 201, { brief });
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
export async function handleListProjectBriefs({ req, res, opts, query }) {
|
|
42
|
+
const status = query.get('status') ?? 'all';
|
|
43
|
+
const repoFilter = query.get('repo');
|
|
44
|
+
const limit = parseListLimit(query.get('limit'));
|
|
45
|
+
const after = parseCursor(query.get('cursor'), 'string', 'integer');
|
|
46
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
47
|
+
const listOpts = { limit: limit + 1, after };
|
|
48
|
+
if (repoFilter !== null && repoFilter.trim().length > 0) {
|
|
49
|
+
listOpts.repo = repoFilter.trim();
|
|
50
|
+
}
|
|
51
|
+
if (status !== 'all') {
|
|
52
|
+
if (!isSetMember(VALID_BRIEF_STATES, status)) {
|
|
53
|
+
throw new HttpError(400, `status must be one of: active | superseded | closed | all (got "${status}")`);
|
|
54
|
+
}
|
|
55
|
+
listOpts.status = status;
|
|
56
|
+
}
|
|
57
|
+
const briefs = loadProjectBriefs(opts.hippoRoot, ctx.tenantId, listOpts);
|
|
58
|
+
const page = pageOf(briefs, limit, byCreatedAt);
|
|
59
|
+
sendJson(res, 200, { briefs: page.items, next_cursor: page.nextCursor });
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// The refresh op: must precede the /:id routes (literal 'refresh' is non-numeric
|
|
63
|
+
// so the /(\d+)/ routes would not match it, but order it first).
|
|
64
|
+
export async function handleRefreshProjectBrief({ req, res, opts }) {
|
|
65
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
66
|
+
const body = await parseJsonBody(req, ctx);
|
|
67
|
+
const repo = body['repo'];
|
|
68
|
+
if (!isJsonString(repo) || repo.trim().length === 0) {
|
|
69
|
+
throw new HttpError(400, 'repo is required (non-empty string)');
|
|
70
|
+
}
|
|
71
|
+
if (repo.length > 256) {
|
|
72
|
+
throw new HttpError(400, 'repo exceeds 256-character cap');
|
|
73
|
+
}
|
|
74
|
+
const dryRun = body['dryRun'] === true;
|
|
75
|
+
if (dryRun) {
|
|
76
|
+
const { markdown, receiptCount } = assembleBriefFromReceipts(opts.hippoRoot, ctx.tenantId, repo);
|
|
77
|
+
sendJson(res, 200, { markdown, receiptCount });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const brief = refreshBrief(opts.hippoRoot, ctx.tenantId, repo, ctx.actor.subject);
|
|
81
|
+
sendJson(res, 200, { brief });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
export async function handleSupersedeProjectBrief({ req, res, opts }, briefSupersedeMatch) {
|
|
85
|
+
const id = parseInt(briefSupersedeMatch[1], 10);
|
|
86
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
87
|
+
const body = await parseJsonBody(req, ctx);
|
|
88
|
+
const summary = body['summary'];
|
|
89
|
+
if (!isJsonString(summary) || summary.trim().length === 0) {
|
|
90
|
+
throw new HttpError(400, 'summary is required (non-empty string)');
|
|
91
|
+
}
|
|
92
|
+
if (summary.length > 8192) {
|
|
93
|
+
throw new HttpError(400, 'summary exceeds 8192-character cap');
|
|
94
|
+
}
|
|
95
|
+
const changeRaw = body['changeSummary'];
|
|
96
|
+
let changeSummary;
|
|
97
|
+
if (changeRaw !== undefined && changeRaw !== null) {
|
|
98
|
+
if (!isJsonString(changeRaw)) {
|
|
99
|
+
throw new HttpError(400, 'changeSummary must be a string');
|
|
100
|
+
}
|
|
101
|
+
if (changeRaw.length > 4096) {
|
|
102
|
+
throw new HttpError(400, 'changeSummary exceeds 4096-character cap');
|
|
103
|
+
}
|
|
104
|
+
changeSummary = changeRaw;
|
|
105
|
+
}
|
|
106
|
+
const existing = loadProjectBriefById(opts.hippoRoot, ctx.tenantId, id);
|
|
107
|
+
if (!existing) {
|
|
108
|
+
throw new HttpError(404, `project brief ${id} not found`);
|
|
109
|
+
}
|
|
110
|
+
const brief = saveProjectBrief(opts.hippoRoot, ctx.tenantId, {
|
|
111
|
+
repo: existing.repo,
|
|
112
|
+
summary,
|
|
113
|
+
changeSummary,
|
|
114
|
+
supersedesBriefId: id,
|
|
115
|
+
}, ctx.actor.subject);
|
|
116
|
+
sendJson(res, 200, { brief });
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
export async function handleCloseProjectBrief({ req, res, opts }, briefCloseMatch) {
|
|
120
|
+
const id = parseInt(briefCloseMatch[1], 10);
|
|
121
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
122
|
+
const brief = closeProjectBrief(opts.hippoRoot, ctx.tenantId, id, ctx.actor.subject);
|
|
123
|
+
sendJson(res, 200, { brief });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
export async function handleGetProjectBrief({ req, res, opts }, briefByIdMatch) {
|
|
127
|
+
const id = parseInt(briefByIdMatch[1], 10);
|
|
128
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
129
|
+
const brief = loadProjectBriefById(opts.hippoRoot, ctx.tenantId, id);
|
|
130
|
+
if (!brief) {
|
|
131
|
+
throw new HttpError(404, `project brief ${id} not found`);
|
|
132
|
+
}
|
|
133
|
+
sendJson(res, 200, { brief });
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=project-briefs.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
/** Test-only: reset the module-level recall-history Map. Call from beforeEach. */
|
|
3
|
+
export declare function __resetSessionRecallHistoryHttp(): void;
|
|
4
|
+
export declare function handleRecallMemories({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
5
|
+
export declare function handleAssembleSession({ req, res, opts, query }: RouteRequest, assembleMatch: Record<string, string>): Promise<void>;
|
|
6
|
+
export declare function handleDrillRecall({ req, res, opts, query }: RouteRequest, drillMatch: Record<string, string>): Promise<void>;
|
|
7
|
+
export declare function handleGetContext({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=recall.d.ts.map
|
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// Recall routes: /v1/memories search, assemble, drill and /v1/context.
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { resolveProjectIdentity } from '../../project-identity.js';
|
|
4
|
+
import { assembleCost, contextCost, drillCost } from '../../context-render.js';
|
|
5
|
+
import { closeHippoDb, openHippoDb } from '../../db.js';
|
|
6
|
+
import { updateStats } from '../../store/index-and-stats.js';
|
|
7
|
+
import { appendRecall, biasHintEnabled, buildSessionKey, getOrCreateRing, hashQueryText, snapshotRing } from '../../recall-history.js';
|
|
8
|
+
import { appendAuditEvent, auditQueryFields } from '../../audit.js';
|
|
9
|
+
import { assemble, drillDown, getContext, recordTokens, retrieve } from '../../api.js';
|
|
10
|
+
import { HttpError, sendJson } from '../../http-util.js';
|
|
11
|
+
import { buildContextWithAuth } from '../auth.js';
|
|
12
|
+
import { parseListLimit, validateIdSegment } from '../validation.js';
|
|
13
|
+
// v0.33 / J1 — Module-level per-(tenant, session) recall-history ring map
|
|
14
|
+
// for the HTTP pipeline. Separate from CLI/MCP rings per plan v3 (per-
|
|
15
|
+
// pipeline rings; no IPC). HTTP is the only caller that threads its
|
|
16
|
+
// snapshot through opts.recallHistory to api.recall — api.recall's
|
|
17
|
+
// anchoringHint on the returned RecallResult IS the user-visible hint
|
|
18
|
+
// here (no separate compute needed).
|
|
19
|
+
const sessionRecallHistoryHttp = new Map();
|
|
20
|
+
/** Test-only: reset the module-level recall-history Map. Call from beforeEach. */
|
|
21
|
+
export function __resetSessionRecallHistoryHttp() {
|
|
22
|
+
sessionRecallHistoryHttp.clear();
|
|
23
|
+
}
|
|
24
|
+
// GET /v1/memories?q=...&limit=...&mode=...&scope=...&include_continuity=1
|
|
25
|
+
export async function handleRecallMemories({ req, res, opts, query }) {
|
|
26
|
+
const q = query.get('q');
|
|
27
|
+
if (!q) {
|
|
28
|
+
throw new HttpError(400, 'q is required');
|
|
29
|
+
}
|
|
30
|
+
const limitRaw = query.get('limit');
|
|
31
|
+
const limit = limitRaw === null ? undefined : parseListLimit(limitRaw);
|
|
32
|
+
const mode = query.get('mode');
|
|
33
|
+
if (mode !== null && mode !== 'bm25' && mode !== 'hybrid' && mode !== 'physics') {
|
|
34
|
+
throw new HttpError(400, "mode must be 'bm25', 'hybrid', or 'physics'");
|
|
35
|
+
}
|
|
36
|
+
const scope = query.get('scope');
|
|
37
|
+
const includeContinuityRaw = query.get('include_continuity');
|
|
38
|
+
const includeContinuity = includeContinuityRaw === '1'
|
|
39
|
+
|| includeContinuityRaw === 'true';
|
|
40
|
+
// v1.6.2: surface the v1.5.0/v1.5.2 RecallOpts additions to HTTP
|
|
41
|
+
// callers. Pre-v1.6.2 the route silently ignored these so the
|
|
42
|
+
// session-scoped fresh-tail and summary substitution were JS-only.
|
|
43
|
+
const freshTailCountRaw = query.get('fresh_tail_count');
|
|
44
|
+
const freshTailCount = freshTailCountRaw === null ? undefined : Number(freshTailCountRaw);
|
|
45
|
+
if (freshTailCount !== undefined && (!Number.isFinite(freshTailCount) || freshTailCount < 0)) {
|
|
46
|
+
throw new HttpError(400, 'fresh_tail_count must be a non-negative number');
|
|
47
|
+
}
|
|
48
|
+
// v1.6.3 senior-review P1-3: cap session_id length consistent with the
|
|
49
|
+
// rest of the API. Untrimmed strings round-trip through the SQL layer
|
|
50
|
+
// and through any downstream metric/log; 256 is generous for a session
|
|
51
|
+
// id and matches the rest of this file's id-shaped param parsers.
|
|
52
|
+
const freshTailSessionIdRaw = query.get('fresh_tail_session_id');
|
|
53
|
+
if (freshTailSessionIdRaw !== null && freshTailSessionIdRaw.length > 256) {
|
|
54
|
+
throw new HttpError(400, 'fresh_tail_session_id exceeds 256-character cap');
|
|
55
|
+
}
|
|
56
|
+
const freshTailSessionId = freshTailSessionIdRaw && freshTailSessionIdRaw.length > 0
|
|
57
|
+
? freshTailSessionIdRaw
|
|
58
|
+
: undefined;
|
|
59
|
+
// v1.6.3 senior-review P1-4: tighten parser to match the includeContinuity
|
|
60
|
+
// convention. Pre-v1.6.3 accepted any non-'0'/'false' value as `true`,
|
|
61
|
+
// so `?summarize_overflow=banana` and `?summarize_overflow=` both
|
|
62
|
+
// turned it on. Surface convention drift fixed.
|
|
63
|
+
const summarizeOverflowRaw = query.get('summarize_overflow');
|
|
64
|
+
const summarizeOverflow = summarizeOverflowRaw === null
|
|
65
|
+
? undefined
|
|
66
|
+
: (summarizeOverflowRaw === '1' || summarizeOverflowRaw === 'true');
|
|
67
|
+
// recall() owns the shape rule (NaN, 0 and negatives throw invalid_scorer_window); the transport caps remote cost.
|
|
68
|
+
const scorerWindowRaw = query.get('scorer_window');
|
|
69
|
+
const scorerWindow = scorerWindowRaw === null ? undefined : Number(scorerWindowRaw);
|
|
70
|
+
if (scorerWindow !== undefined && scorerWindow > 1000) {
|
|
71
|
+
throw new HttpError(400, 'scorer_window must be <= 1000');
|
|
72
|
+
}
|
|
73
|
+
// v1.7.4: session_id for the dlPFC goal-stack boost. 256-char cap mirrors
|
|
74
|
+
// fresh_tail_session_id (above). Trim then drop if empty so api.recall
|
|
75
|
+
// sees undefined when the param is omitted or whitespace-only.
|
|
76
|
+
const sessionIdRaw = query.get('session_id');
|
|
77
|
+
if (sessionIdRaw !== null && sessionIdRaw.length > 256) {
|
|
78
|
+
throw new HttpError(400, 'session_id exceeds 256-character cap');
|
|
79
|
+
}
|
|
80
|
+
const sessionId = sessionIdRaw && sessionIdRaw.trim().length > 0
|
|
81
|
+
? sessionIdRaw.trim()
|
|
82
|
+
: undefined;
|
|
83
|
+
// A7 recall-trace: opt-in explain flag. When set, api.recall attaches the
|
|
84
|
+
// lifecycle re-ranking trace (goal-boost step on the api pipeline) +
|
|
85
|
+
// rerankPipeline:'api' to each result item; the field then rides on the
|
|
86
|
+
// serialized RecallResult. Mirrors the include_continuity convention.
|
|
87
|
+
const explainRaw = query.get('explain');
|
|
88
|
+
const explain = explainRaw === '1' || explainRaw === 'true';
|
|
89
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
90
|
+
// v0.33 / J1 — HTTP per-pipeline anchoring detector. HTTP threads its
|
|
91
|
+
// ring snapshot via opts.recallHistory so api.recall's own
|
|
92
|
+
// anchoringHint compute path activates. Unlike CLI (which computes
|
|
93
|
+
// its own hint separately because cmdRecall runs its own physics/
|
|
94
|
+
// hybrid pipeline outside api.recall), HTTP's /v1/memories response
|
|
95
|
+
// body IS api.recall's result directly. So the api.recall-computed
|
|
96
|
+
// hint flows through. HIPPO_ANCHORING=off short-circuits.
|
|
97
|
+
let httpRecallHistory;
|
|
98
|
+
let httpRingKey;
|
|
99
|
+
if (biasHintEnabled('anchoring')) {
|
|
100
|
+
if (sessionId) {
|
|
101
|
+
// Codex round-5 P2 catch: do NOT mutate sessionRecallHistoryHttp
|
|
102
|
+
// before recall() preflight runs. A request with an invalid
|
|
103
|
+
// scorer_window / fresh_tail_count would create-or-touch the
|
|
104
|
+
// session ring (LRU-evicting valid sessions) even though recall
|
|
105
|
+
// throws 400. Snapshot the EXISTING ring if present; only
|
|
106
|
+
// create-or-touch after the recall returns successfully.
|
|
107
|
+
httpRingKey = buildSessionKey(ctx.tenantId, sessionId);
|
|
108
|
+
const existingRing = sessionRecallHistoryHttp.get(httpRingKey);
|
|
109
|
+
httpRecallHistory = existingRing ? snapshotRing(existingRing) : [];
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Telemetry: caller had no session_id so ring tracking skipped.
|
|
113
|
+
// Per the normal recall-audit convention (api.ts:854 stores
|
|
114
|
+
// SHA-256/16 hash of the query, NOT raw text), avoid retaining
|
|
115
|
+
// prompts in audit_log here too — query content can contain
|
|
116
|
+
// secrets, PII, or RTBF-restricted material. Codex round-2 P2
|
|
117
|
+
// catch: hashQueryText is a 32-bit FNV-1a designed for recall
|
|
118
|
+
// matching, NOT a privacy hash; brute-force trivial for low-
|
|
119
|
+
// entropy queries. Use the same SHA-256/16 truncation as the
|
|
120
|
+
// canonical recall audit.
|
|
121
|
+
const dbForAudit = openHippoDb(opts.hippoRoot);
|
|
122
|
+
try {
|
|
123
|
+
appendAuditEvent(dbForAudit, {
|
|
124
|
+
tenantId: ctx.tenantId,
|
|
125
|
+
actor: ctx.actor.subject,
|
|
126
|
+
op: 'recall_anchor_skipped_no_session',
|
|
127
|
+
targetId: undefined,
|
|
128
|
+
metadata: auditQueryFields(q),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
closeHippoDb(dbForAudit);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const recallExtra = {};
|
|
137
|
+
if (freshTailCount !== undefined)
|
|
138
|
+
recallExtra.freshTailCount = freshTailCount;
|
|
139
|
+
if (freshTailSessionId !== undefined)
|
|
140
|
+
recallExtra.freshTailSessionId = freshTailSessionId;
|
|
141
|
+
if (summarizeOverflow !== undefined)
|
|
142
|
+
recallExtra.summarizeOverflow = summarizeOverflow;
|
|
143
|
+
if (scorerWindow !== undefined)
|
|
144
|
+
recallExtra.scorerWindow = scorerWindow;
|
|
145
|
+
if (sessionId !== undefined)
|
|
146
|
+
recallExtra.sessionId = sessionId;
|
|
147
|
+
if (httpRecallHistory !== undefined)
|
|
148
|
+
recallExtra.recallHistory = httpRecallHistory;
|
|
149
|
+
if (explain)
|
|
150
|
+
recallExtra.explain = explain;
|
|
151
|
+
const result = await retrieve(ctx, {
|
|
152
|
+
query: q,
|
|
153
|
+
limit,
|
|
154
|
+
mode: mode ?? undefined,
|
|
155
|
+
scope: scope ?? undefined,
|
|
156
|
+
includeContinuity,
|
|
157
|
+
...recallExtra,
|
|
158
|
+
});
|
|
159
|
+
// v0.33 / J1 — append AFTER recall completes (snapshot was taken before
|
|
160
|
+
// recall() ran). anchoredOn carries the memoryId of any hint that fired
|
|
161
|
+
// (api.recall computed it from the same snapshot we passed in), feeding
|
|
162
|
+
// the cooldown logic for the NEXT recall on this session.
|
|
163
|
+
// Codex round-5 P2 fix: create-or-touch the ring ONLY HERE, after recall
|
|
164
|
+
// returns successfully. Invalid requests that throw 400 in recall()
|
|
165
|
+
// never reach this point, so they cannot LRU-evict valid sessions.
|
|
166
|
+
if (httpRingKey) {
|
|
167
|
+
const httpRing = getOrCreateRing(sessionRecallHistoryHttp, httpRingKey);
|
|
168
|
+
const topId = result.results[0]?.id ?? null;
|
|
169
|
+
appendRecall(httpRing, hashQueryText(q), topId, result.anchoringHint?.memoryId);
|
|
170
|
+
}
|
|
171
|
+
// Each recall surface counts its own hits; api.recall is no chokepoint,
|
|
172
|
+
// since the CLI never calls it and MCP shows the user a different band.
|
|
173
|
+
updateStats(opts.hippoRoot, { recalled: result.results.length });
|
|
174
|
+
// Continuity payloads should never be cached. The caller is asking for
|
|
175
|
+
// session-state-aware data; intermediaries must not reuse it across users.
|
|
176
|
+
if (includeContinuity) {
|
|
177
|
+
res.setHeader('Cache-Control', 'no-store');
|
|
178
|
+
}
|
|
179
|
+
recordTokens(ctx, 'http_recall', { items: result.results.length, tokens: result.tokens + (result.continuityTokens ?? 0), sessionId: sessionId ?? null });
|
|
180
|
+
sendJson(res, 200, result);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
// GET /v1/sessions/:id/assemble?budget=N&freshTail=N&summarizeOlder=0|1
|
|
184
|
+
// Phase 2 context-engine API. Returns ordered AssembledContextItem[]
|
|
185
|
+
// with fresh-tail raws + summary substitutions + bio-aware budget fit.
|
|
186
|
+
// Tenant scope from Bearer; default-deny on private rows.
|
|
187
|
+
export async function handleAssembleSession({ req, res, opts, query }, assembleMatch) {
|
|
188
|
+
validateIdSegment(assembleMatch.id, 'session id');
|
|
189
|
+
const budgetRaw = query.get('budget');
|
|
190
|
+
const budget = budgetRaw === null ? undefined : Number(budgetRaw);
|
|
191
|
+
if (budget !== undefined && (!Number.isFinite(budget) || budget <= 0)) {
|
|
192
|
+
throw new HttpError(400, 'budget must be a positive number');
|
|
193
|
+
}
|
|
194
|
+
const ftRaw = query.get('freshTail');
|
|
195
|
+
const freshTailCount = ftRaw === null ? undefined : Number(ftRaw);
|
|
196
|
+
if (freshTailCount !== undefined && (!Number.isFinite(freshTailCount) || freshTailCount < 0)) {
|
|
197
|
+
throw new HttpError(400, 'freshTail must be a non-negative number');
|
|
198
|
+
}
|
|
199
|
+
// v1.6.3 senior review P1: same strict-parse convention as the v1.6.3
|
|
200
|
+
// summarize_overflow tighten on /v1/memories. Pre-v1.6.3 accepted any
|
|
201
|
+
// non-'0'/'false' as true; ?summarizeOlder=banana now correctly returns
|
|
202
|
+
// false (matches includeContinuity convention).
|
|
203
|
+
const sumOlderRaw = query.get('summarizeOlder');
|
|
204
|
+
const summarizeOlder = sumOlderRaw === null
|
|
205
|
+
? undefined
|
|
206
|
+
: (sumOlderRaw === '1' || sumOlderRaw === 'true');
|
|
207
|
+
const scopeQ = query.get('scope');
|
|
208
|
+
const scope = scopeQ !== null && scopeQ.length > 0 ? scopeQ : undefined;
|
|
209
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
210
|
+
const assembleExtra = {};
|
|
211
|
+
if (budget !== undefined)
|
|
212
|
+
assembleExtra.budget = budget;
|
|
213
|
+
if (freshTailCount !== undefined)
|
|
214
|
+
assembleExtra.freshTailCount = freshTailCount;
|
|
215
|
+
if (summarizeOlder !== undefined)
|
|
216
|
+
assembleExtra.summarizeOlder = summarizeOlder;
|
|
217
|
+
if (scope !== undefined)
|
|
218
|
+
assembleExtra.scope = scope;
|
|
219
|
+
const result = assemble(ctx, assembleMatch.id, { ...assembleExtra, cost: assembleCost(assembleMatch.id) });
|
|
220
|
+
recordTokens(ctx, 'http_assemble', { items: result.items.length, tokens: result.tokens, sessionId: assembleMatch.id });
|
|
221
|
+
sendJson(res, 200, result);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// GET /v1/recall/drill/:id?limit=N&budget=N
|
|
225
|
+
// Companion to /v1/memories. When recall surfaces a level-2 summary in
|
|
226
|
+
// place of overflowed children (RecallResultItem.isSummary === true), the
|
|
227
|
+
// caller drills into the summary id to recover the originals. Tenant
|
|
228
|
+
// scoped via Bearer; default-deny on private scopes for both summary
|
|
229
|
+
// and children.
|
|
230
|
+
export async function handleDrillRecall({ req, res, opts, query }, drillMatch) {
|
|
231
|
+
validateIdSegment(drillMatch.id, 'summary id');
|
|
232
|
+
const limitRaw = query.get('limit');
|
|
233
|
+
const limit = limitRaw === null ? undefined : Number(limitRaw);
|
|
234
|
+
if (limit !== undefined && (!Number.isFinite(limit) || limit <= 0)) {
|
|
235
|
+
throw new HttpError(400, 'limit must be a positive number');
|
|
236
|
+
}
|
|
237
|
+
const budgetRaw = query.get('budget');
|
|
238
|
+
const budget = budgetRaw === null ? undefined : Number(budgetRaw);
|
|
239
|
+
if (budget !== undefined && (!Number.isFinite(budget) || budget <= 0)) {
|
|
240
|
+
throw new HttpError(400, 'budget must be a positive number');
|
|
241
|
+
}
|
|
242
|
+
// v0.30 / E5: depth query param walks N levels (default 1, hard cap 10).
|
|
243
|
+
const depthRaw = query.get('depth');
|
|
244
|
+
let depth;
|
|
245
|
+
if (depthRaw !== null) {
|
|
246
|
+
const parsed = Number(depthRaw);
|
|
247
|
+
// L4 fold: reject out-of-range explicitly (no silent clamp).
|
|
248
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 10) {
|
|
249
|
+
throw new HttpError(400, 'depth must be a positive integer between 1 and 10');
|
|
250
|
+
}
|
|
251
|
+
depth = parsed;
|
|
252
|
+
}
|
|
253
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
254
|
+
const drillExtra = {};
|
|
255
|
+
if (limit !== undefined)
|
|
256
|
+
drillExtra.limit = limit;
|
|
257
|
+
if (budget !== undefined)
|
|
258
|
+
drillExtra.budget = budget;
|
|
259
|
+
if (depth !== undefined)
|
|
260
|
+
drillExtra.depth = depth;
|
|
261
|
+
const result = drillDown(ctx, drillMatch.id, { ...drillExtra, cost: drillCost });
|
|
262
|
+
if ('failure' in result) {
|
|
263
|
+
// v1.6.4: leaf id maps to 422 (caller-actionable). Other cases stay
|
|
264
|
+
// as 404 to avoid leaking cross-tenant existence or scope grants.
|
|
265
|
+
if (result.failure === 'not_drillable') {
|
|
266
|
+
throw new HttpError(422, 'Id is a leaf row, not a level-2+ summary; nothing to drill into');
|
|
267
|
+
}
|
|
268
|
+
throw new HttpError(404, 'No drillable summary at this id');
|
|
269
|
+
}
|
|
270
|
+
sendJson(res, 200, result);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
// GET /v1/context — assemble a budget-bounded context bundle. Returns
|
|
274
|
+
// ContextResult JSON (entries + tokens + activeSnapshot + sessionHandoff
|
|
275
|
+
// + recentEvents). No server-side rendering; clients render. Tenant-scoped
|
|
276
|
+
// via the Bearer. Pinned-only + '*' fallback skip the recall audit emit
|
|
277
|
+
// (matches cmdContext); real-query hybrid search emits one 'recall' row.
|
|
278
|
+
export async function handleGetContext({ req, res, opts, query }) {
|
|
279
|
+
const q = query.get('q') ?? undefined;
|
|
280
|
+
// v1.11.5: DoS cap on q-param length. 1024 covers real multi-clause queries
|
|
281
|
+
// (pasted error messages, multi-stem searches) while bounding BM25
|
|
282
|
+
// tokenisation cost (~150 tokens worst case at 1024 chars).
|
|
283
|
+
if (q !== undefined && q.length > 1024) {
|
|
284
|
+
throw new HttpError(400, 'q exceeds 1024-character cap');
|
|
285
|
+
}
|
|
286
|
+
const budgetRaw = query.get('budget');
|
|
287
|
+
let budget;
|
|
288
|
+
if (budgetRaw !== null) {
|
|
289
|
+
budget = Number(budgetRaw);
|
|
290
|
+
if (!Number.isFinite(budget) || budget < 0) {
|
|
291
|
+
throw new HttpError(400, 'budget must be a non-negative number');
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const limitRaw = query.get('limit');
|
|
295
|
+
let limit;
|
|
296
|
+
if (limitRaw !== null) {
|
|
297
|
+
limit = Number(limitRaw);
|
|
298
|
+
if (!Number.isFinite(limit) || limit <= 0) {
|
|
299
|
+
throw new HttpError(400, 'limit must be a positive number');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const pinnedOnlyRaw = query.get('pinned_only');
|
|
303
|
+
const pinnedOnly = pinnedOnlyRaw === '1' || pinnedOnlyRaw === 'true';
|
|
304
|
+
const scopeRaw = query.get('scope');
|
|
305
|
+
if (scopeRaw !== null && scopeRaw.length > 256) {
|
|
306
|
+
throw new HttpError(400, 'scope exceeds 256-character cap');
|
|
307
|
+
}
|
|
308
|
+
const scope = scopeRaw === null ? undefined : scopeRaw;
|
|
309
|
+
const includeRecentRaw = query.get('include_recent');
|
|
310
|
+
let includeRecent;
|
|
311
|
+
if (includeRecentRaw !== null) {
|
|
312
|
+
includeRecent = Number(includeRecentRaw);
|
|
313
|
+
if (!Number.isFinite(includeRecent) || includeRecent < 0) {
|
|
314
|
+
throw new HttpError(400, 'include_recent must be a non-negative number');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
// v39 memory scope isolation: cross_project=1|true re-includes
|
|
318
|
+
// other-project rows (tagged category 'cross-project' in the response).
|
|
319
|
+
// The partition identity comes from the SERVED STORE's location, not the
|
|
320
|
+
// daemon's process cwd - a daemon started from anywhere still isolates
|
|
321
|
+
// the project it serves.
|
|
322
|
+
const crossProjectRaw = query.get('cross_project');
|
|
323
|
+
const crossProject = crossProjectRaw === '1' || crossProjectRaw === 'true';
|
|
324
|
+
const ctx = await buildContextWithAuth(req, opts);
|
|
325
|
+
const result = await getContext(ctx, {
|
|
326
|
+
q,
|
|
327
|
+
budget,
|
|
328
|
+
limit,
|
|
329
|
+
pinnedOnly,
|
|
330
|
+
scope,
|
|
331
|
+
includeRecent,
|
|
332
|
+
crossProject,
|
|
333
|
+
currentProject: resolveProjectIdentity(dirname(resolve(opts.hippoRoot))).name,
|
|
334
|
+
cost: contextCost('markdown', 'observe'), // clients render; the budget prices the block `hippo context` would print
|
|
335
|
+
});
|
|
336
|
+
recordTokens(ctx, 'http_context', { items: result.entries.length, tokens: result.tokens });
|
|
337
|
+
sendJson(res, 200, result);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
//# sourceMappingURL=recall.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RouteRequest } from '../types.js';
|
|
2
|
+
export declare function handleCreateSkill({ req, res, opts }: RouteRequest): Promise<void>;
|
|
3
|
+
export declare function handleListSkills({ req, res, opts, query }: RouteRequest): Promise<void>;
|
|
4
|
+
export declare function handleExportSkills({ req, res, opts }: RouteRequest): Promise<void>;
|
|
5
|
+
export declare function handleSupersedeSkill({ req, res, opts }: RouteRequest, skillSupersedeMatch: RegExpMatchArray): Promise<void>;
|
|
6
|
+
export declare function handleCloseSkill({ req, res, opts }: RouteRequest, skillCloseMatch: RegExpMatchArray): Promise<void>;
|
|
7
|
+
export declare function handleGetSkill({ req, res, opts }: RouteRequest, skillByIdMatch: RegExpMatchArray): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=skills.d.ts.map
|