hippo-memory 1.59.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 -1260
- package/dist/api.js +25 -2711
- package/dist/audit.d.ts +3 -0
- package/dist/audit.js +7 -3
- package/dist/auth.d.ts +45 -4
- package/dist/auth.js +125 -48
- package/dist/autolearn.js +7 -4
- 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 +319 -13
- package/dist/cli.js +436 -8580
- package/dist/client.js +15 -8
- package/dist/compaction-record.js +12 -9
- package/dist/config.js +12 -11
- package/dist/connectors/github/backfill.js +94 -87
- package/dist/connectors/github/cli-impl.js +5 -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 +13 -12
- 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 +231 -203
- 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 -3036
- package/dist/decisions.d.ts +4 -1
- package/dist/decisions.js +9 -7
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +5 -1
- package/dist/doctor.js +4 -3
- package/dist/dormant.js +1 -0
- package/dist/embedding-provider.d.ts +1 -1
- package/dist/embedding-provider.js +7 -5
- package/dist/embeddings.d.ts +9 -52
- package/dist/embeddings.js +47 -298
- 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 +5 -4
- 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} +8 -391
- 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/handoff.js +3 -0
- 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 +8 -5
- package/dist/index.d.ts +25 -6
- package/dist/index.js +23 -6
- package/dist/invalidation.js +2 -1
- package/dist/judgment.js +7 -3
- 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 -70
- package/dist/mcp/server.js +8 -1172
- 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 +8 -3
- 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 +8 -5
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +7 -5
- package/dist/project-identity.d.ts +1 -1
- package/dist/project-identity.js +12 -6
- package/dist/project-merge.js +3 -1
- package/dist/quarantine.d.ts +2 -1
- package/dist/quarantine.js +8 -5
- package/dist/raw-archive-mirror-cleanup.js +2 -1
- 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 +3 -3
- package/dist/recall-trace.js +10 -14
- package/dist/refine-llm.js +20 -11
- package/dist/reject-flow.js +6 -1
- package/dist/rerankers/clef.d.ts +2 -2
- package/dist/rerankers/clef.js +72 -30
- package/dist/rerankers/cross-encoder.js +6 -4
- package/dist/rerankers/jev.d.ts +4 -2
- package/dist/rerankers/jev.js +24 -19
- package/dist/rerankers/llm.d.ts +4 -2
- package/dist/rerankers/llm.js +61 -41
- package/dist/rerankers/types.d.ts +1 -1
- package/dist/salience.js +1 -1
- package/dist/same-text.d.ts +2 -0
- package/dist/same-text.js +4 -0
- package/dist/scheduler.d.ts +1 -0
- package/dist/scheduler.js +26 -3
- 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 +3 -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 +92 -2368
- 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 +46 -40
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +7 -5
- package/dist/stdin.js +3 -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/token-ledger.js +1 -0
- 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 +2 -1
- package/dist/capture.d.ts +0 -155
- package/dist/capture.js +0 -1293
- package/dist/consolidate.d.ts +0 -58
- package/dist/consolidate.js +0 -1123
- package/dist/graph.d.ts +0 -245
- package/dist/hooks.d.ts +0 -208
- package/dist/hooks.js +0 -1073
- package/dist/importers.js +0 -897
- package/dist/predictions.js +0 -620
- package/dist/search.d.ts +0 -320
- package/dist/search.js +0 -968
- package/dist/store.d.ts +0 -744
- package/dist/store.js +0 -3372
- 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
package/dist/client.js
CHANGED
|
@@ -13,8 +13,19 @@
|
|
|
13
13
|
* Network errors (ECONNREFUSED on a stale pidfile, etc.) propagate as the
|
|
14
14
|
* native fetch failure so the caller can detect them and self-heal.
|
|
15
15
|
*/
|
|
16
|
+
import { fetchWithRetry } from './http-retry.js';
|
|
16
17
|
/** A write the local server has not answered in this long is stuck; the caller treats it as delivery-unknown. */
|
|
17
18
|
const SERVER_TIMEOUT_MS = 30_000;
|
|
19
|
+
/** Five tries at the server's 1 s Retry-After keeps the roughly 5 s wait the CLI had before the server answered busy with 503. */
|
|
20
|
+
const STORE_BUSY_ATTEMPTS = 5;
|
|
21
|
+
/** The server sets Retry-After on a 503 only for a held write lock (server.ts replyFor); the auth-provider 503 has none. */
|
|
22
|
+
function isStoreBusy(res) {
|
|
23
|
+
return res.status === 503 && res.headers.has('retry-after');
|
|
24
|
+
}
|
|
25
|
+
/** Replaying is safe because each routed write commits in one transaction and anything after it is best-effort, so a busy 503 means nothing landed. */
|
|
26
|
+
function sendWrite(url, init) {
|
|
27
|
+
return fetchWithRetry(url, init, { timeoutMs: SERVER_TIMEOUT_MS, attempts: STORE_BUSY_ATTEMPTS, retryOn: isStoreBusy });
|
|
28
|
+
}
|
|
18
29
|
function buildHeaders(apiKey, withBody) {
|
|
19
30
|
const headers = {};
|
|
20
31
|
if (withBody)
|
|
@@ -57,10 +68,9 @@ async function throwForStatus(res) {
|
|
|
57
68
|
throw new HttpResponseError(message, res.status);
|
|
58
69
|
}
|
|
59
70
|
export async function remember(serverUrl, apiKey, opts) {
|
|
60
|
-
const res = await
|
|
71
|
+
const res = await sendWrite(`${serverUrl}/v1/memories`, {
|
|
61
72
|
method: 'POST',
|
|
62
73
|
headers: buildHeaders(apiKey, true),
|
|
63
|
-
signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
|
|
64
74
|
body: JSON.stringify(opts),
|
|
65
75
|
});
|
|
66
76
|
if (!res.ok)
|
|
@@ -69,10 +79,9 @@ export async function remember(serverUrl, apiKey, opts) {
|
|
|
69
79
|
return result;
|
|
70
80
|
}
|
|
71
81
|
export async function forget(serverUrl, apiKey, id) {
|
|
72
|
-
const res = await
|
|
82
|
+
const res = await sendWrite(`${serverUrl}/v1/memories/${encodeURIComponent(id)}`, {
|
|
73
83
|
method: 'DELETE',
|
|
74
84
|
headers: buildHeaders(apiKey, false),
|
|
75
|
-
signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
|
|
76
85
|
});
|
|
77
86
|
if (!res.ok)
|
|
78
87
|
await throwForStatus(res);
|
|
@@ -80,10 +89,9 @@ export async function forget(serverUrl, apiKey, id) {
|
|
|
80
89
|
return result;
|
|
81
90
|
}
|
|
82
91
|
export async function promote(serverUrl, apiKey, id) {
|
|
83
|
-
const res = await
|
|
92
|
+
const res = await sendWrite(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/promote`, {
|
|
84
93
|
method: 'POST',
|
|
85
94
|
headers: buildHeaders(apiKey, false),
|
|
86
|
-
signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
|
|
87
95
|
});
|
|
88
96
|
if (!res.ok)
|
|
89
97
|
await throwForStatus(res);
|
|
@@ -91,10 +99,9 @@ export async function promote(serverUrl, apiKey, id) {
|
|
|
91
99
|
return result;
|
|
92
100
|
}
|
|
93
101
|
export async function archiveRaw(serverUrl, apiKey, id, reason) {
|
|
94
|
-
const res = await
|
|
102
|
+
const res = await sendWrite(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/archive`, {
|
|
95
103
|
method: 'POST',
|
|
96
104
|
headers: buildHeaders(apiKey, true),
|
|
97
|
-
signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
|
|
98
105
|
body: JSON.stringify({ reason }),
|
|
99
106
|
});
|
|
100
107
|
if (!res.ok)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// One record per Claude Code compaction, and what turns its summary into kept memories.
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
-
import { errorMessage, readTranscriptTail, truncateCodePointSafe } from './capture.js';
|
|
5
4
|
import { isObjectLike, isStringValue } from './capture-contract.js';
|
|
6
5
|
import { compactSummaryBody, parseCompactionItems, selectItemRows } from './compaction-items.js';
|
|
7
6
|
import { loadConfig } from './config.js';
|
|
@@ -10,8 +9,12 @@ import { gatedWrite } from './gated-write.js';
|
|
|
10
9
|
import { COMPACTION_MEMORY_TAG, COMPACTION_SOURCE_PREFIX, Layer, createMemory, generateId } from './memory.js';
|
|
11
10
|
import { deriveOriginProject, isGlobalStoreRoot } from './project-identity.js';
|
|
12
11
|
import { maskEmails, redactSecretsStrict } from './secret-detect.js';
|
|
13
|
-
import { strengthenRetrievedOn,
|
|
12
|
+
import { strengthenRetrievedOn, writeEntryMirrors } from './store/entry-writes.js';
|
|
13
|
+
import { isRecallBoostAblated } from './ablation.js';
|
|
14
|
+
import { updateStats } from './store/index-and-stats.js';
|
|
14
15
|
import { resolveTenantId } from './tenant.js';
|
|
16
|
+
import { errorMessage, log as logger } from './log.js';
|
|
17
|
+
import { readTranscriptTail, truncateCodePointSafe } from './transcript-tail.js';
|
|
15
18
|
/** PostCompact has 10 s in all (PreCompact 30 s), so a locked store must be given up on early. */
|
|
16
19
|
export const COMPACTION_DB_WAIT_MS = 2000;
|
|
17
20
|
/** Tested verbatim: Claude Code hands PreCompact stdout to the summariser as instructions. */
|
|
@@ -225,7 +228,7 @@ export function saveItems(db, hippoRoot, ctx, log) {
|
|
|
225
228
|
}
|
|
226
229
|
}
|
|
227
230
|
// Said again by another session is the same signal as being recalled; the same session carrying it forward is not.
|
|
228
|
-
strengthenRetrievedOn(db, [...restated], ctx.tenantId);
|
|
231
|
+
strengthenRetrievedOn(db, [...restated], { tenantId: ctx.tenantId, recallBoostAblated: isRecallBoostAblated() });
|
|
229
232
|
if (ctx.recordId !== null) {
|
|
230
233
|
db.prepare(`UPDATE compactions SET items_written = ?, status = 'done' WHERE tenant_id = ? AND id = ?`).run(written.length, ctx.tenantId, ctx.recordId);
|
|
231
234
|
}
|
|
@@ -262,7 +265,7 @@ export function parsePostCompactPayload(stdinText) {
|
|
|
262
265
|
raw = JSON.parse((stdinText ?? '').trim());
|
|
263
266
|
}
|
|
264
267
|
catch {
|
|
265
|
-
return null;
|
|
268
|
+
return null; // non-JSON stdin is not a PostCompact payload; the caller skips it
|
|
266
269
|
}
|
|
267
270
|
if (!isObjectLike(raw) || !('session_id' in raw) || !isStringValue(raw.session_id) || raw.session_id === '')
|
|
268
271
|
return null;
|
|
@@ -309,7 +312,7 @@ export function saveCompaction(hippoRoot, payload, log) {
|
|
|
309
312
|
if (isSqliteBusy(err))
|
|
310
313
|
throw err;
|
|
311
314
|
log(`record step failed: ${errorMessage(err)}`);
|
|
312
|
-
|
|
315
|
+
logger.error(`post-compact: record step failed: ${errorMessage(err)}`);
|
|
313
316
|
}
|
|
314
317
|
try {
|
|
315
318
|
result.written = saveItems(db, hippoRoot, {
|
|
@@ -337,12 +340,12 @@ export function saveCompaction(hippoRoot, payload, log) {
|
|
|
337
340
|
}
|
|
338
341
|
catch (spoolErr) {
|
|
339
342
|
log(`spool failed: ${errorMessage(spoolErr)}`);
|
|
340
|
-
|
|
343
|
+
logger.error(`post-compact: spool failed: ${errorMessage(spoolErr)}`);
|
|
341
344
|
}
|
|
342
345
|
}
|
|
343
346
|
else {
|
|
344
347
|
log(`items step failed: ${errorMessage(err)}`);
|
|
345
|
-
|
|
348
|
+
logger.error(`post-compact: items step failed: ${errorMessage(err)}`);
|
|
346
349
|
}
|
|
347
350
|
}
|
|
348
351
|
finally {
|
|
@@ -380,7 +383,7 @@ function transcriptSummary(transcriptPath, afterMs, beforeMs) {
|
|
|
380
383
|
lines.push(JSON.parse(raw));
|
|
381
384
|
}
|
|
382
385
|
catch {
|
|
383
|
-
continue;
|
|
386
|
+
continue; // the tail can start mid-line; a torn line holds no summary
|
|
384
387
|
}
|
|
385
388
|
}
|
|
386
389
|
const stamp = (line) => (isStringValue(line.timestamp) ? Date.parse(line.timestamp) : Number.NaN);
|
|
@@ -409,7 +412,7 @@ function readSpooled(file, fallbackTenantId) {
|
|
|
409
412
|
raw = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
410
413
|
}
|
|
411
414
|
catch {
|
|
412
|
-
return null;
|
|
415
|
+
return null; // a half-written or vanished spool file is skipped; the caller treats null as unreadable
|
|
413
416
|
}
|
|
414
417
|
if (!isObjectLike(raw) || !('sessionId' in raw) || !isStringValue(raw.sessionId) || !('summary' in raw) || !isStringValue(raw.summary))
|
|
415
418
|
return null;
|
package/dist/config.js
CHANGED
|
@@ -5,6 +5,7 @@ import * as fs from 'fs';
|
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import { DEFAULT_PHYSICS_CONFIG, mergePhysicsConfig } from './physics-config.js';
|
|
7
7
|
import { DEFAULT_HALF_LIFE_DAYS } from './memory.js';
|
|
8
|
+
import { log } from './log.js';
|
|
8
9
|
const DEFAULT_CONFIG = {
|
|
9
10
|
defaultHalfLifeDays: DEFAULT_HALF_LIFE_DAYS,
|
|
10
11
|
defaultBudget: 4000,
|
|
@@ -114,7 +115,7 @@ function deliveryLedgerEnabled(value) {
|
|
|
114
115
|
return enabled;
|
|
115
116
|
if (isObject && enabled === undefined)
|
|
116
117
|
return false;
|
|
117
|
-
|
|
118
|
+
log.warn(`config.json's "deliveryLedger" must be an object like {"enabled": true} ` +
|
|
118
119
|
`(got ${JSON.stringify(value)}) - using false.`);
|
|
119
120
|
return false;
|
|
120
121
|
}
|
|
@@ -127,7 +128,7 @@ function pilotHoldoutRate(value) {
|
|
|
127
128
|
return 0;
|
|
128
129
|
if (Number.isInteger(rate) && rate >= 0 && rate <= 10000)
|
|
129
130
|
return rate;
|
|
130
|
-
|
|
131
|
+
log.warn(`config.json's "pilot" must be an object like {"holdoutRateBp": 2000}, an integer from 0 to 10000 ` +
|
|
131
132
|
`(got ${JSON.stringify(value)}) - using 0 (pilot off).`);
|
|
132
133
|
return 0;
|
|
133
134
|
}
|
|
@@ -136,7 +137,7 @@ function agentMemoryTools(value) {
|
|
|
136
137
|
return null;
|
|
137
138
|
if (Array.isArray(value) && value.every((t) => String(t) === t))
|
|
138
139
|
return value;
|
|
139
|
-
|
|
140
|
+
log.warn(`config.json's "agentMemories.tools" must be a list of tool ids like ["claude-code", "codex"] ` +
|
|
140
141
|
`(got ${JSON.stringify(value)}) - importing none.`);
|
|
141
142
|
return [];
|
|
142
143
|
}
|
|
@@ -158,7 +159,7 @@ export function loadConfig(hippoRoot) {
|
|
|
158
159
|
const memoryValueRaw = raw.memoryValue;
|
|
159
160
|
const validMemoryValueConfig = memoryValueRaw === undefined || isMemoryValueConfig(memoryValueRaw);
|
|
160
161
|
if (!validMemoryValueConfig) {
|
|
161
|
-
|
|
162
|
+
log.warn(`config.json's "memoryValue" must be an object like {"enabled": true} ` +
|
|
162
163
|
`(got ${JSON.stringify(memoryValueRaw)}) - using defaults.`);
|
|
163
164
|
}
|
|
164
165
|
const memoryValueOverride = memoryValueRaw !== undefined && isMemoryValueConfig(memoryValueRaw) ? memoryValueRaw : {};
|
|
@@ -167,20 +168,20 @@ export function loadConfig(hippoRoot) {
|
|
|
167
168
|
// warns and falls back to the default, which keeps faded memories.
|
|
168
169
|
const dormantRaw = raw.dormant;
|
|
169
170
|
if (dormantRaw !== undefined && !isDormantConfig(dormantRaw)) {
|
|
170
|
-
|
|
171
|
+
log.warn(`config.json's "dormant" must be an object like {"enabled": false} ` +
|
|
171
172
|
`(got ${JSON.stringify(dormantRaw)}) - using the default (faded memories kept dormant).`);
|
|
172
173
|
}
|
|
173
174
|
const dormantOverride = dormantRaw !== undefined && isDormantConfig(dormantRaw) ? dormantRaw : {};
|
|
174
175
|
// Only a real boolean counts: {"enabled": "false"} is a truthy string.
|
|
175
176
|
let dormantEnabled = dormantOverride.enabled ?? DEFAULT_CONFIG.dormant.enabled;
|
|
176
177
|
if (dormantEnabled !== true && dormantEnabled !== false) {
|
|
177
|
-
|
|
178
|
+
log.warn(`config.json's "dormant.enabled" must be true or false ` +
|
|
178
179
|
`(got ${JSON.stringify(dormantEnabled)}) - using the default (faded memories kept dormant).`);
|
|
179
180
|
dormantEnabled = DEFAULT_CONFIG.dormant.enabled;
|
|
180
181
|
}
|
|
181
182
|
let dormantRetentionDays = dormantOverride.retentionDays ?? DEFAULT_CONFIG.dormant.retentionDays;
|
|
182
183
|
if (!Number.isFinite(dormantRetentionDays) || dormantRetentionDays < 0) {
|
|
183
|
-
|
|
184
|
+
log.warn(`config.json's "dormant.retentionDays" must be a number of days, 0 or more ` +
|
|
184
185
|
`(got ${JSON.stringify(dormantRetentionDays)}) - using ${DEFAULT_CONFIG.dormant.retentionDays}.`);
|
|
185
186
|
dormantRetentionDays = DEFAULT_CONFIG.dormant.retentionDays;
|
|
186
187
|
}
|
|
@@ -188,21 +189,21 @@ export function loadConfig(hippoRoot) {
|
|
|
188
189
|
const churnStalenessRaw = raw.churnStaleness;
|
|
189
190
|
const validChurnStalenessConfig = churnStalenessRaw === undefined || isChurnStalenessConfig(churnStalenessRaw);
|
|
190
191
|
if (!validChurnStalenessConfig) {
|
|
191
|
-
|
|
192
|
+
log.warn(`config.json's "churnStaleness" must be an object like {"enabled": true} ` +
|
|
192
193
|
`(got ${JSON.stringify(churnStalenessRaw)}) - using defaults.`);
|
|
193
194
|
}
|
|
194
195
|
let churnStalenessEnabled = churnStalenessRaw !== undefined && isChurnStalenessConfig(churnStalenessRaw)
|
|
195
196
|
? churnStalenessRaw.enabled
|
|
196
197
|
: DEFAULT_CONFIG.churnStaleness.enabled;
|
|
197
198
|
if (churnStalenessEnabled !== true && churnStalenessEnabled !== false) {
|
|
198
|
-
|
|
199
|
+
log.warn(`config.json's "churnStaleness.enabled" must be true or false ` +
|
|
199
200
|
`(got ${JSON.stringify(churnStalenessEnabled)}) - using false.`);
|
|
200
201
|
churnStalenessEnabled = false;
|
|
201
202
|
}
|
|
202
203
|
// Every writer starts a memory on this, and a zero or negative half-life scores zero strength, so sleep would retire it.
|
|
203
204
|
let defaultHalfLifeDays = raw.defaultHalfLifeDays ?? DEFAULT_CONFIG.defaultHalfLifeDays;
|
|
204
205
|
if (!Number.isFinite(defaultHalfLifeDays) || defaultHalfLifeDays <= 0) {
|
|
205
|
-
|
|
206
|
+
log.warn(`config.json's "defaultHalfLifeDays" must be a number of days above 0 ` +
|
|
206
207
|
`(got ${JSON.stringify(defaultHalfLifeDays)}) - using ${DEFAULT_CONFIG.defaultHalfLifeDays}.`);
|
|
207
208
|
defaultHalfLifeDays = DEFAULT_CONFIG.defaultHalfLifeDays;
|
|
208
209
|
}
|
|
@@ -247,7 +248,7 @@ export function loadConfig(hippoRoot) {
|
|
|
247
248
|
}
|
|
248
249
|
catch (err) {
|
|
249
250
|
if (fs.existsSync(configPath)) {
|
|
250
|
-
|
|
251
|
+
log.warn(`failed to parse ${configPath}: ${err instanceof Error ? err.message : err}`);
|
|
251
252
|
}
|
|
252
253
|
return { ...DEFAULT_CONFIG };
|
|
253
254
|
}
|
|
@@ -172,6 +172,82 @@ async function drainStream(ctx, url0, toIngestEvent, fetcher, token, sleep, maxI
|
|
|
172
172
|
}
|
|
173
173
|
return { ingested, pages, maxUpdatedAt, drained: true };
|
|
174
174
|
}
|
|
175
|
+
function issueItemToEvent(item, repository) {
|
|
176
|
+
if (!isIssuesItem(item))
|
|
177
|
+
return null;
|
|
178
|
+
// Codex P1 #2: /issues returns PRs too — skip them.
|
|
179
|
+
if (item.pull_request)
|
|
180
|
+
return null;
|
|
181
|
+
const payload = {
|
|
182
|
+
action: 'opened',
|
|
183
|
+
repository,
|
|
184
|
+
issue: {
|
|
185
|
+
number: item.number,
|
|
186
|
+
title: item.title,
|
|
187
|
+
body: item.body ?? null,
|
|
188
|
+
user: { login: item.user.login, id: item.user.id },
|
|
189
|
+
updated_at: item.updated_at,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
return { eventName: 'issues', payload };
|
|
193
|
+
}
|
|
194
|
+
function issueCommentItemToEvent(item, repository) {
|
|
195
|
+
if (!isCommentItem(item))
|
|
196
|
+
return null;
|
|
197
|
+
// SAFETY: this closure only runs against the /issues/comments stream,
|
|
198
|
+
// so every item isCommentItem validates here is genuinely an
|
|
199
|
+
// IssueCommentItem; a missing issue_url is handled defensively below.
|
|
200
|
+
const c = item;
|
|
201
|
+
const issueNumber = parseTrailingNumber(c.issue_url);
|
|
202
|
+
if (issueNumber === null)
|
|
203
|
+
return null;
|
|
204
|
+
const payload = {
|
|
205
|
+
action: 'created',
|
|
206
|
+
repository,
|
|
207
|
+
issue: { number: issueNumber },
|
|
208
|
+
comment: {
|
|
209
|
+
id: c.id,
|
|
210
|
+
body: c.body ?? null,
|
|
211
|
+
user: { login: c.user.login, id: c.user.id },
|
|
212
|
+
updated_at: c.updated_at,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
return { eventName: 'issue_comment', payload };
|
|
216
|
+
}
|
|
217
|
+
function prReviewCommentItemToEvent(item, repository) {
|
|
218
|
+
if (!isCommentItem(item))
|
|
219
|
+
return null;
|
|
220
|
+
// SAFETY: this closure only runs against the /pulls/comments stream,
|
|
221
|
+
// so every item isCommentItem validates here is genuinely a
|
|
222
|
+
// PrReviewCommentItem; a missing pull_request_url is handled below.
|
|
223
|
+
const c = item;
|
|
224
|
+
const prNumber = parseTrailingNumber(c.pull_request_url);
|
|
225
|
+
if (prNumber === null)
|
|
226
|
+
return null;
|
|
227
|
+
const payload = {
|
|
228
|
+
action: 'created',
|
|
229
|
+
repository,
|
|
230
|
+
pull_request: { number: prNumber },
|
|
231
|
+
comment: {
|
|
232
|
+
id: c.id,
|
|
233
|
+
body: c.body ?? null,
|
|
234
|
+
user: { login: c.user.login, id: c.user.id },
|
|
235
|
+
updated_at: c.updated_at,
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
return { eventName: 'pull_request_review_comment', payload };
|
|
239
|
+
}
|
|
240
|
+
/** Drains one stream, then persists its HWM only when the stream ran to the end. */
|
|
241
|
+
async function backfillStream(ctx, opts, sleep, stream) {
|
|
242
|
+
const res = await drainStream(ctx, stream.url, stream.toIngestEvent, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
243
|
+
// v1.3.1: only advance HWM when the stream actually drained. A capped run
|
|
244
|
+
// (--max) must leave the HWM at its previous value so the next invocation
|
|
245
|
+
// re-fetches the unprocessed tail.
|
|
246
|
+
if (res.drained && res.maxUpdatedAt) {
|
|
247
|
+
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, stream.column, res.maxUpdatedAt);
|
|
248
|
+
}
|
|
249
|
+
return { ingested: res.ingested, pages: res.pages };
|
|
250
|
+
}
|
|
175
251
|
export async function backfillRepo(ctx, opts) {
|
|
176
252
|
const sleep = opts.sleepMs ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
177
253
|
const cursors = readCursor(ctx.hippoRoot, ctx.tenantId, opts.repoFullName);
|
|
@@ -181,101 +257,32 @@ export async function backfillRepo(ctx, opts) {
|
|
|
181
257
|
pages: { issues: 0, issueComments: 0, prReviewComments: 0 },
|
|
182
258
|
};
|
|
183
259
|
// ---------- Stream 1: issues (skip PRs) ----------
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
if (item.pull_request)
|
|
191
|
-
return null;
|
|
192
|
-
const payload = {
|
|
193
|
-
action: 'opened',
|
|
194
|
-
repository,
|
|
195
|
-
issue: {
|
|
196
|
-
number: item.number,
|
|
197
|
-
title: item.title,
|
|
198
|
-
body: item.body ?? null,
|
|
199
|
-
user: { login: item.user.login, id: item.user.id },
|
|
200
|
-
updated_at: item.updated_at,
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
return { eventName: 'issues', payload };
|
|
204
|
-
}, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
260
|
+
const issuesRes = await backfillStream(ctx, opts, sleep, {
|
|
261
|
+
url: `${API}/repos/${opts.repoFullName}/issues?state=all&per_page=100` +
|
|
262
|
+
(cursors.issues ? `&since=${encodeURIComponent(cursors.issues)}` : ''),
|
|
263
|
+
column: 'issues_hwm',
|
|
264
|
+
toIngestEvent: (item) => issueItemToEvent(item, repository),
|
|
265
|
+
});
|
|
205
266
|
result.ingested.issues = issuesRes.ingested;
|
|
206
267
|
result.pages.issues = issuesRes.pages;
|
|
207
|
-
// v1.3.1: only advance HWM when the stream actually drained. A capped run
|
|
208
|
-
// (--max) must leave the HWM at its previous value so the next invocation
|
|
209
|
-
// re-fetches the unprocessed tail.
|
|
210
|
-
if (issuesRes.drained && issuesRes.maxUpdatedAt) {
|
|
211
|
-
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'issues_hwm', issuesRes.maxUpdatedAt);
|
|
212
|
-
}
|
|
213
268
|
// ---------- Stream 2: repo-level issue comments ----------
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
? `&since=${encodeURIComponent(cursors.issueComments)}`
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
return null;
|
|
221
|
-
// SAFETY: this closure only runs against the /issues/comments stream,
|
|
222
|
-
// so every item isCommentItem validates here is genuinely an
|
|
223
|
-
// IssueCommentItem; a missing issue_url is handled defensively below.
|
|
224
|
-
const c = item;
|
|
225
|
-
const issueNumber = parseTrailingNumber(c.issue_url);
|
|
226
|
-
if (issueNumber === null)
|
|
227
|
-
return null;
|
|
228
|
-
const payload = {
|
|
229
|
-
action: 'created',
|
|
230
|
-
repository,
|
|
231
|
-
issue: { number: issueNumber },
|
|
232
|
-
comment: {
|
|
233
|
-
id: c.id,
|
|
234
|
-
body: c.body ?? null,
|
|
235
|
-
user: { login: c.user.login, id: c.user.id },
|
|
236
|
-
updated_at: c.updated_at,
|
|
237
|
-
},
|
|
238
|
-
};
|
|
239
|
-
return { eventName: 'issue_comment', payload };
|
|
240
|
-
}, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
269
|
+
const commentsRes = await backfillStream(ctx, opts, sleep, {
|
|
270
|
+
url: `${API}/repos/${opts.repoFullName}/issues/comments?per_page=100` +
|
|
271
|
+
(cursors.issueComments ? `&since=${encodeURIComponent(cursors.issueComments)}` : ''),
|
|
272
|
+
column: 'issue_comments_hwm',
|
|
273
|
+
toIngestEvent: (item) => issueCommentItemToEvent(item, repository),
|
|
274
|
+
});
|
|
241
275
|
result.ingested.issueComments = commentsRes.ingested;
|
|
242
276
|
result.pages.issueComments = commentsRes.pages;
|
|
243
|
-
if (commentsRes.drained && commentsRes.maxUpdatedAt) {
|
|
244
|
-
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'issue_comments_hwm', commentsRes.maxUpdatedAt);
|
|
245
|
-
}
|
|
246
277
|
// ---------- Stream 3: repo-level PR review comments ----------
|
|
247
|
-
const
|
|
248
|
-
|
|
249
|
-
? `&since=${encodeURIComponent(cursors.prReviewComments)}`
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return null;
|
|
254
|
-
// SAFETY: this closure only runs against the /pulls/comments stream,
|
|
255
|
-
// so every item isCommentItem validates here is genuinely a
|
|
256
|
-
// PrReviewCommentItem; a missing pull_request_url is handled below.
|
|
257
|
-
const c = item;
|
|
258
|
-
const prNumber = parseTrailingNumber(c.pull_request_url);
|
|
259
|
-
if (prNumber === null)
|
|
260
|
-
return null;
|
|
261
|
-
const payload = {
|
|
262
|
-
action: 'created',
|
|
263
|
-
repository,
|
|
264
|
-
pull_request: { number: prNumber },
|
|
265
|
-
comment: {
|
|
266
|
-
id: c.id,
|
|
267
|
-
body: c.body ?? null,
|
|
268
|
-
user: { login: c.user.login, id: c.user.id },
|
|
269
|
-
updated_at: c.updated_at,
|
|
270
|
-
},
|
|
271
|
-
};
|
|
272
|
-
return { eventName: 'pull_request_review_comment', payload };
|
|
273
|
-
}, opts.fetcher, opts.token, sleep, opts.maxPerStream);
|
|
278
|
+
const prCommentsRes = await backfillStream(ctx, opts, sleep, {
|
|
279
|
+
url: `${API}/repos/${opts.repoFullName}/pulls/comments?per_page=100` +
|
|
280
|
+
(cursors.prReviewComments ? `&since=${encodeURIComponent(cursors.prReviewComments)}` : ''),
|
|
281
|
+
column: 'pr_review_comments_hwm',
|
|
282
|
+
toIngestEvent: (item) => prReviewCommentItemToEvent(item, repository),
|
|
283
|
+
});
|
|
274
284
|
result.ingested.prReviewComments = prCommentsRes.ingested;
|
|
275
285
|
result.pages.prReviewComments = prCommentsRes.pages;
|
|
276
|
-
if (prCommentsRes.drained && prCommentsRes.maxUpdatedAt) {
|
|
277
|
-
writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'pr_review_comments_hwm', prCommentsRes.maxUpdatedAt);
|
|
278
|
-
}
|
|
279
286
|
return result;
|
|
280
287
|
}
|
|
281
288
|
//# sourceMappingURL=backfill.js.map
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* - hippo github dlq list
|
|
10
10
|
* - hippo github dlq replay <id> [--force]
|
|
11
11
|
*/
|
|
12
|
+
import { envGithubToken, envGithubWebhookSecret, envGithubWebhookSecretPrevious } from '../../env.js';
|
|
12
13
|
import { adminActor } from '../../api.js';
|
|
13
14
|
import { openHippoDb, closeHippoDb } from '../../db.js';
|
|
14
15
|
import { resolveTenantId } from '../../tenant.js';
|
|
@@ -52,6 +53,7 @@ function parsedToIngestEvent(parsed, eventName) {
|
|
|
52
53
|
}
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
56
|
+
// Console lines below are the `hippo github` command's printed result and usage text, so they stay off the logger.
|
|
55
57
|
export function printGithubBackfillUsage() {
|
|
56
58
|
console.log('hippo github backfill --repo <owner/name> [--since ISO] [--max <N>]');
|
|
57
59
|
console.log(' --repo GitHub repository in owner/name format (required, e.g. acme/widgets)');
|
|
@@ -69,7 +71,7 @@ export async function cmdGithubBackfill(hippoRoot, flags, fetcher = realGitHubFe
|
|
|
69
71
|
printGithubBackfillUsage();
|
|
70
72
|
process.exit(2);
|
|
71
73
|
}
|
|
72
|
-
const token =
|
|
74
|
+
const token = envGithubToken();
|
|
73
75
|
if (!token) {
|
|
74
76
|
console.error('GITHUB_TOKEN is not set. Backfill requires a personal access token with repo read scope.');
|
|
75
77
|
process.exit(2);
|
|
@@ -165,8 +167,8 @@ export async function cmdGithubDlqReplay(hippoRoot, args, flags) {
|
|
|
165
167
|
// real hook so `replay` actually re-runs the ingest path.
|
|
166
168
|
const result = await replayDlqEntry(ctx, id, {
|
|
167
169
|
force,
|
|
168
|
-
webhookSecret:
|
|
169
|
-
previousSecret:
|
|
170
|
+
webhookSecret: envGithubWebhookSecret(),
|
|
171
|
+
previousSecret: envGithubWebhookSecretPrevious(),
|
|
170
172
|
ingestHook: async (innerCtx, args) => {
|
|
171
173
|
const parsed = JSON.parse(args.rawPayload);
|
|
172
174
|
const event = parsedToIngestEvent(parsed, args.eventName);
|
|
@@ -104,61 +104,13 @@ export async function replayDlqEntry(ctx, id, opts = {}) {
|
|
|
104
104
|
}
|
|
105
105
|
// Signature verification (current secret, not the one in effect when DLQed).
|
|
106
106
|
if (!opts.force && opts.webhookSecret) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
status: 'sig_missing',
|
|
111
|
-
memoryId: null,
|
|
112
|
-
retryCount: row.retryCount,
|
|
113
|
-
reason: 'row has no signature (legacy, or redacted before storing); pass --force to replay',
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
const sigOk = verifyGitHubSignature({
|
|
117
|
-
rawBody: row.rawPayload,
|
|
118
|
-
signature: row.signature,
|
|
119
|
-
webhookSecret: opts.webhookSecret,
|
|
120
|
-
previousSecret: opts.previousSecret,
|
|
121
|
-
});
|
|
122
|
-
if (!sigOk) {
|
|
123
|
-
bumpRetryCount(ctx.hippoRoot, id);
|
|
124
|
-
return {
|
|
125
|
-
ok: false,
|
|
126
|
-
status: 'sig_fail',
|
|
127
|
-
memoryId: null,
|
|
128
|
-
retryCount: row.retryCount + 1,
|
|
129
|
-
reason: 'signature did not verify against current GITHUB_WEBHOOK_SECRET; pass --force to replay anyway',
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// Parse + envelope guard.
|
|
134
|
-
let parsed;
|
|
135
|
-
try {
|
|
136
|
-
parsed = JSON.parse(row.rawPayload);
|
|
137
|
-
}
|
|
138
|
-
catch (e) {
|
|
139
|
-
bumpRetryCount(ctx.hippoRoot, id);
|
|
140
|
-
// SAFETY: this is a best-effort error message only; property access on
|
|
141
|
-
// any JS value is safe (undefined if absent), preserving the existing
|
|
142
|
-
// lenient formatting even when something non-Error was thrown.
|
|
143
|
-
const message = e.message;
|
|
144
|
-
return {
|
|
145
|
-
ok: false,
|
|
146
|
-
status: 'parse_error',
|
|
147
|
-
memoryId: null,
|
|
148
|
-
retryCount: row.retryCount + 1,
|
|
149
|
-
reason: `still unparseable: ${message}`,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
if (!isGitHubWebhookEnvelope(parsed)) {
|
|
153
|
-
bumpRetryCount(ctx.hippoRoot, id);
|
|
154
|
-
return {
|
|
155
|
-
ok: false,
|
|
156
|
-
status: 'unhandled',
|
|
157
|
-
memoryId: null,
|
|
158
|
-
retryCount: row.retryCount + 1,
|
|
159
|
-
reason: 'not a GitHub webhook envelope',
|
|
160
|
-
};
|
|
107
|
+
const sigFailure = checkReplaySignature(ctx.hippoRoot, id, row, opts.webhookSecret, opts.previousSecret);
|
|
108
|
+
if (sigFailure)
|
|
109
|
+
return sigFailure;
|
|
161
110
|
}
|
|
111
|
+
const envelopeFailure = checkReplayEnvelope(ctx.hippoRoot, id, row);
|
|
112
|
+
if (envelopeFailure)
|
|
113
|
+
return envelopeFailure;
|
|
162
114
|
// Without an ingest hook this is a dry-run validation. Bump and report.
|
|
163
115
|
if (!opts.ingestHook) {
|
|
164
116
|
bumpRetryCount(ctx.hippoRoot, id);
|
|
@@ -190,4 +142,65 @@ export async function replayDlqEntry(ctx, id, opts = {}) {
|
|
|
190
142
|
retryCount: row.retryCount + 1,
|
|
191
143
|
};
|
|
192
144
|
}
|
|
145
|
+
/** The failure result when the row cannot pass the signature gate, else null. */
|
|
146
|
+
function checkReplaySignature(hippoRoot, id, row, webhookSecret, previousSecret) {
|
|
147
|
+
if (!row.signature) {
|
|
148
|
+
return {
|
|
149
|
+
ok: false,
|
|
150
|
+
status: 'sig_missing',
|
|
151
|
+
memoryId: null,
|
|
152
|
+
retryCount: row.retryCount,
|
|
153
|
+
reason: 'row has no signature (legacy, or redacted before storing); pass --force to replay',
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
const sigOk = verifyGitHubSignature({
|
|
157
|
+
rawBody: row.rawPayload,
|
|
158
|
+
signature: row.signature,
|
|
159
|
+
webhookSecret,
|
|
160
|
+
previousSecret,
|
|
161
|
+
});
|
|
162
|
+
if (!sigOk) {
|
|
163
|
+
bumpRetryCount(hippoRoot, id);
|
|
164
|
+
return {
|
|
165
|
+
ok: false,
|
|
166
|
+
status: 'sig_fail',
|
|
167
|
+
memoryId: null,
|
|
168
|
+
retryCount: row.retryCount + 1,
|
|
169
|
+
reason: 'signature did not verify against current GITHUB_WEBHOOK_SECRET; pass --force to replay anyway',
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
/** Parse + envelope guard; the failure result after bumping the count, else null. */
|
|
175
|
+
function checkReplayEnvelope(hippoRoot, id, row) {
|
|
176
|
+
let parsed;
|
|
177
|
+
try {
|
|
178
|
+
parsed = JSON.parse(row.rawPayload);
|
|
179
|
+
}
|
|
180
|
+
catch (e) {
|
|
181
|
+
bumpRetryCount(hippoRoot, id);
|
|
182
|
+
// SAFETY: this is a best-effort error message only; property access on
|
|
183
|
+
// any JS value is safe (undefined if absent), preserving the existing
|
|
184
|
+
// lenient formatting even when something non-Error was thrown.
|
|
185
|
+
const message = e.message;
|
|
186
|
+
return {
|
|
187
|
+
ok: false,
|
|
188
|
+
status: 'parse_error',
|
|
189
|
+
memoryId: null,
|
|
190
|
+
retryCount: row.retryCount + 1,
|
|
191
|
+
reason: `still unparseable: ${message}`,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
if (!isGitHubWebhookEnvelope(parsed)) {
|
|
195
|
+
bumpRetryCount(hippoRoot, id);
|
|
196
|
+
return {
|
|
197
|
+
ok: false,
|
|
198
|
+
status: 'unhandled',
|
|
199
|
+
memoryId: null,
|
|
200
|
+
retryCount: row.retryCount + 1,
|
|
201
|
+
reason: 'not a GitHub webhook envelope',
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
193
206
|
//# sourceMappingURL=dlq.js.map
|