hippo-memory 1.60.0 → 1.62.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 +29 -54
- package/dist/ablation.js +9 -27
- package/dist/agent-memories/apply.d.ts +1 -1
- package/dist/agent-memories/apply.js +4 -1
- package/dist/agent-memories/claude-code.d.ts +3 -1
- package/dist/agent-memories/claude-code.js +54 -10
- 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.d.ts +3 -3
- package/dist/agent-memories/sync.js +22 -9
- package/dist/agent-memories/types.d.ts +0 -2
- 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 +153 -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-select.d.ts +49 -0
- package/dist/api/context-select.js +344 -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 +378 -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 +126 -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 +192 -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 +499 -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 +256 -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 +453 -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 +376 -0
- package/dist/cli/continuity.d.ts +6 -0
- package/dist/cli/continuity.js +457 -0
- package/dist/cli/curate.d.ts +19 -0
- package/dist/cli/curate.js +556 -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 +156 -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 +190 -0
- package/dist/cli/playbooks.d.ts +4 -0
- package/dist/cli/playbooks.js +573 -0
- package/dist/cli/projects.js +9 -6
- package/dist/cli/recall.d.ts +7 -0
- package/dist/cli/recall.js +582 -0
- package/dist/cli/remember.d.ts +5 -0
- package/dist/cli/remember.js +485 -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 +647 -0
- package/dist/cli/setup.d.ts +4 -0
- package/dist/cli/setup.js +397 -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 +409 -0
- package/dist/cli/transfer.d.ts +10 -0
- package/dist/cli/transfer.js +424 -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.d.ts +0 -2
- package/dist/compaction-record.js +7 -5
- 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 +83 -72
- package/dist/dag.js +225 -188
- 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 +102 -83
- package/dist/dedupe.js +3 -2
- package/dist/delivery-recorder.js +4 -1
- package/dist/doctor.js +14 -10
- 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 +117 -86
- 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 +52 -43
- 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 +93 -74
- 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 +94 -76
- package/dist/project-briefs.d.ts +3 -0
- package/dist/project-briefs.js +142 -113
- package/dist/project-identity.js +3 -2
- package/dist/project-merge.d.ts +12 -4
- package/dist/project-merge.js +132 -45
- 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 +12 -1
- package/dist/shared.js +33 -27
- package/dist/skills.d.ts +3 -0
- package/dist/skills.js +88 -70
- 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 +260 -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
|
@@ -54,57 +54,64 @@ export function ingestMessage(ctx, input) {
|
|
|
54
54
|
// together. Slack's 1-minute retry window can no longer produce a duplicate
|
|
55
55
|
// via the crash-between-handles race.
|
|
56
56
|
try {
|
|
57
|
-
|
|
58
|
-
// provided by server.ts:1039 which constructs it with the connector subject.
|
|
59
|
-
// Under the new object-shaped Context.actor, an OR-fallback would evaluate
|
|
60
|
-
// an object as truthy and skip the fallback anyway (logic bug if ctx were
|
|
61
|
-
// ever missing); explicit reliance on the caller is safer.
|
|
62
|
-
const result = remember(ctx, {
|
|
63
|
-
...opts,
|
|
64
|
-
untrusted: true,
|
|
65
|
-
afterWrite: (innerDb, memoryId) => {
|
|
66
|
-
const inserted = innerDb
|
|
67
|
-
.prepare(`INSERT OR IGNORE INTO slack_event_log (event_id, ingested_at, memory_id) VALUES (?, ?, ?)`)
|
|
68
|
-
.run(input.eventId, new Date().toISOString(), memoryId);
|
|
69
|
-
if ((Number(inserted.changes ?? 0)) === 0) {
|
|
70
|
-
// Two-worker race: another writer reserved this event_id between
|
|
71
|
-
// the pre-check and the write. Throw to roll back the SAVEPOINT
|
|
72
|
-
// in writeEntry — the memory row gets discarded, idempotency
|
|
73
|
-
// holds, exactly one memory exists for this event_id.
|
|
74
|
-
throw new DuplicateEventError(input.eventId);
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
return { status: 'ingested', memoryId: result.id };
|
|
57
|
+
return rememberWithEventLog(ctx, input.eventId, opts);
|
|
79
58
|
}
|
|
80
59
|
catch (e) {
|
|
81
|
-
if (e instanceof DuplicateEventError)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
const cachedId = lookupMemoryByEvent(db3, input.eventId);
|
|
87
|
-
return { status: 'skipped_duplicate', memoryId: cachedId };
|
|
88
|
-
}
|
|
89
|
-
finally {
|
|
90
|
-
closeHippoDb(db3);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (e instanceof RejectedValueError) {
|
|
94
|
-
// AT1 (plan §3 containment): a tombstone hit is a PERMANENT skip, not
|
|
95
|
-
// a transient failure — never DLQ-retry it (retrying would just hit
|
|
96
|
-
// the same refusal forever). Mark the event seen exactly like the
|
|
97
|
-
// empty-body branch above so a Slack retry acks as done, not error.
|
|
98
|
-
const db4 = openHippoDb(ctx.hippoRoot);
|
|
99
|
-
try {
|
|
100
|
-
markEventSeen(db4, input.eventId, null);
|
|
101
|
-
}
|
|
102
|
-
finally {
|
|
103
|
-
closeHippoDb(db4);
|
|
104
|
-
}
|
|
105
|
-
return { status: 'skipped', memoryId: null };
|
|
106
|
-
}
|
|
60
|
+
if (e instanceof DuplicateEventError)
|
|
61
|
+
return lostRaceResult(ctx, input.eventId);
|
|
62
|
+
if (e instanceof RejectedValueError)
|
|
63
|
+
return rejectedValueResult(ctx, input.eventId);
|
|
107
64
|
throw e;
|
|
108
65
|
}
|
|
109
66
|
}
|
|
67
|
+
function rememberWithEventLog(ctx, eventId, opts) {
|
|
68
|
+
// v1.12.0: drop the legacy `|| 'connector:slack'` fallback — ctx is always
|
|
69
|
+
// provided by server.ts:1039 which constructs it with the connector subject.
|
|
70
|
+
// Under the new object-shaped Context.actor, an OR-fallback would evaluate
|
|
71
|
+
// an object as truthy and skip the fallback anyway (logic bug if ctx were
|
|
72
|
+
// ever missing); explicit reliance on the caller is safer.
|
|
73
|
+
const result = remember(ctx, {
|
|
74
|
+
...opts,
|
|
75
|
+
untrusted: true,
|
|
76
|
+
afterWrite: (innerDb, memoryId) => {
|
|
77
|
+
const inserted = innerDb
|
|
78
|
+
.prepare(`INSERT OR IGNORE INTO slack_event_log (event_id, ingested_at, memory_id) VALUES (?, ?, ?)`)
|
|
79
|
+
.run(eventId, new Date().toISOString(), memoryId);
|
|
80
|
+
if ((Number(inserted.changes ?? 0)) === 0) {
|
|
81
|
+
// Two-worker race: another writer reserved this event_id between
|
|
82
|
+
// the pre-check and the write. Throw to roll back the SAVEPOINT
|
|
83
|
+
// in writeEntry — the memory row gets discarded, idempotency
|
|
84
|
+
// holds, exactly one memory exists for this event_id.
|
|
85
|
+
throw new DuplicateEventError(eventId);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
return { status: 'ingested', memoryId: result.id };
|
|
90
|
+
}
|
|
91
|
+
function lostRaceResult(ctx, eventId) {
|
|
92
|
+
// The other worker's memory row is already committed. Return its id
|
|
93
|
+
// so the caller behaves identically to the fast-path 'duplicate' branch.
|
|
94
|
+
const db3 = openHippoDb(ctx.hippoRoot);
|
|
95
|
+
try {
|
|
96
|
+
const cachedId = lookupMemoryByEvent(db3, eventId);
|
|
97
|
+
return { status: 'skipped_duplicate', memoryId: cachedId };
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
closeHippoDb(db3);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function rejectedValueResult(ctx, eventId) {
|
|
104
|
+
// AT1 (plan §3 containment): a tombstone hit is a PERMANENT skip, not
|
|
105
|
+
// a transient failure — never DLQ-retry it (retrying would just hit
|
|
106
|
+
// the same refusal forever). Mark the event seen exactly like the
|
|
107
|
+
// empty-body branch above so a Slack retry acks as done, not error.
|
|
108
|
+
const db4 = openHippoDb(ctx.hippoRoot);
|
|
109
|
+
try {
|
|
110
|
+
markEventSeen(db4, eventId, null);
|
|
111
|
+
}
|
|
112
|
+
finally {
|
|
113
|
+
closeHippoDb(db4);
|
|
114
|
+
}
|
|
115
|
+
return { status: 'skipped', memoryId: null };
|
|
116
|
+
}
|
|
110
117
|
//# sourceMappingURL=ingest.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { envSlackAllowUnknownTeamFallback, envTenant } from '../../env.js';
|
|
1
2
|
/**
|
|
2
3
|
* Look up the tenant_id for a Slack team_id.
|
|
3
4
|
*
|
|
@@ -31,10 +32,10 @@ export function resolveTenantForTeam(db, teamId) {
|
|
|
31
32
|
.get().c;
|
|
32
33
|
if (Number(total) === 0) {
|
|
33
34
|
// Single-workspace install: env fallback is safe.
|
|
34
|
-
return
|
|
35
|
+
return envTenant();
|
|
35
36
|
}
|
|
36
|
-
if (
|
|
37
|
-
return
|
|
37
|
+
if (envSlackAllowUnknownTeamFallback()) {
|
|
38
|
+
return envTenant();
|
|
38
39
|
}
|
|
39
40
|
return null; // fail closed
|
|
40
41
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { envSlackSigningSecret, envSlackSigningSecretPrevious } from '../../env.js';
|
|
1
2
|
import { verifySlackSignature } from './signature.js';
|
|
2
3
|
import { isSlackEventEnvelope, isSlackMessageEvent } from './types.js';
|
|
3
4
|
import { ingestMessage } from './ingest.js';
|
|
@@ -6,7 +7,6 @@ import { writeToDlq } from './dlq.js';
|
|
|
6
7
|
import { resolveTenantForTeam } from './tenant-routing.js';
|
|
7
8
|
import { resolveTenantId } from '../../tenant.js';
|
|
8
9
|
import { openHippoDb, closeHippoDb } from '../../db.js';
|
|
9
|
-
import { adminActor } from '../../api.js';
|
|
10
10
|
import { HttpError, JSON_HEADERS, isHeaderString, isJsonObjectRecord, readBody, sendJson, } from '../../http-util.js';
|
|
11
11
|
/**
|
|
12
12
|
* Slack Events API webhook. Auth is signature-based (HMAC over the raw
|
|
@@ -29,13 +29,13 @@ import { HttpError, JSON_HEADERS, isHeaderString, isJsonObjectRecord, readBody,
|
|
|
29
29
|
*/
|
|
30
30
|
export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
31
31
|
const rawBody = await readBody(req);
|
|
32
|
-
const secret =
|
|
32
|
+
const secret = envSlackSigningSecret();
|
|
33
33
|
if (!secret) {
|
|
34
34
|
res.writeHead(404, JSON_HEADERS);
|
|
35
35
|
res.end(JSON.stringify({ error: 'not found' }));
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
|
-
const previousSecret =
|
|
38
|
+
const previousSecret = envSlackSigningSecretPrevious();
|
|
39
39
|
const sig = req.headers['x-slack-signature'];
|
|
40
40
|
const tsHdr = req.headers['x-slack-request-timestamp'];
|
|
41
41
|
const sigStr = isHeaderString(sig) ? sig : null;
|
|
@@ -51,6 +51,28 @@ export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
|
51
51
|
})) {
|
|
52
52
|
throw new HttpError(401, 'invalid Slack signature');
|
|
53
53
|
}
|
|
54
|
+
routeSignedSlackPayload({ hippoRoot: opts.hippoRoot, res, rawBody, signature: sigStr, slackTimestamp: tsStr });
|
|
55
|
+
}
|
|
56
|
+
function parkInDlq(d, park) {
|
|
57
|
+
const db = openHippoDb(d.hippoRoot);
|
|
58
|
+
try {
|
|
59
|
+
writeToDlq(db, {
|
|
60
|
+
tenantId: park.tenantId,
|
|
61
|
+
teamId: park.teamId,
|
|
62
|
+
rawPayload: d.rawBody,
|
|
63
|
+
error: park.error,
|
|
64
|
+
bucket: park.bucket,
|
|
65
|
+
signature: d.signature,
|
|
66
|
+
slackTimestamp: d.slackTimestamp,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
closeHippoDb(db);
|
|
71
|
+
}
|
|
72
|
+
sendJson(d.res, 200, { ok: true, status: 'dlq' });
|
|
73
|
+
}
|
|
74
|
+
function routeSignedSlackPayload(d) {
|
|
75
|
+
const { rawBody, res } = d;
|
|
54
76
|
// Cheap regex extracts team_id from a (possibly malformed) raw body so the
|
|
55
77
|
// DLQ row carries it for triage even when JSON.parse fails.
|
|
56
78
|
const teamIdFromRaw = (() => {
|
|
@@ -62,25 +84,7 @@ export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
|
62
84
|
body = JSON.parse(rawBody);
|
|
63
85
|
}
|
|
64
86
|
catch {
|
|
65
|
-
|
|
66
|
-
// team_id; a null or unknown team writes tenantId=null, which lands as '__unroutable__'.
|
|
67
|
-
const db = openHippoDb(opts.hippoRoot);
|
|
68
|
-
try {
|
|
69
|
-
const parseFailTenant = teamIdFromRaw !== null ? resolveTenantForTeam(db, teamIdFromRaw) : null;
|
|
70
|
-
writeToDlq(db, {
|
|
71
|
-
tenantId: parseFailTenant, // null → '__unroutable__' sentinel
|
|
72
|
-
teamId: teamIdFromRaw,
|
|
73
|
-
rawPayload: rawBody,
|
|
74
|
-
error: 'invalid JSON',
|
|
75
|
-
bucket: 'parse_error',
|
|
76
|
-
signature: sigStr,
|
|
77
|
-
slackTimestamp: tsStr,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
finally {
|
|
81
|
-
closeHippoDb(db);
|
|
82
|
-
}
|
|
83
|
-
sendJson(res, 200, { ok: true, status: 'dlq' });
|
|
87
|
+
parkUnparseable(d, teamIdFromRaw);
|
|
84
88
|
return;
|
|
85
89
|
}
|
|
86
90
|
if (isJsonObjectRecord(body)) {
|
|
@@ -98,7 +102,7 @@ export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
|
98
102
|
// 200 so Slack stops retrying; do NOT call ingest.
|
|
99
103
|
let resolvedTenant = null;
|
|
100
104
|
if (body !== undefined && isSlackEventEnvelope(body)) {
|
|
101
|
-
const db = openHippoDb(
|
|
105
|
+
const db = openHippoDb(d.hippoRoot);
|
|
102
106
|
try {
|
|
103
107
|
resolvedTenant = resolveTenantForTeam(db, body.team_id);
|
|
104
108
|
}
|
|
@@ -106,22 +110,12 @@ export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
|
106
110
|
closeHippoDb(db);
|
|
107
111
|
}
|
|
108
112
|
if (resolvedTenant === null) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
error: `unroutable team_id: ${body.team_id}`,
|
|
116
|
-
bucket: 'unroutable',
|
|
117
|
-
signature: sigStr,
|
|
118
|
-
slackTimestamp: tsStr,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
finally {
|
|
122
|
-
closeHippoDb(db2);
|
|
123
|
-
}
|
|
124
|
-
sendJson(res, 200, { ok: true, status: 'dlq' });
|
|
113
|
+
parkInDlq(d, {
|
|
114
|
+
tenantId: null, // unroutable - stored as '__unroutable__'
|
|
115
|
+
teamId: body.team_id,
|
|
116
|
+
error: `unroutable team_id: ${body.team_id}`,
|
|
117
|
+
bucket: 'unroutable',
|
|
118
|
+
});
|
|
125
119
|
return;
|
|
126
120
|
}
|
|
127
121
|
}
|
|
@@ -130,29 +124,44 @@ export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
|
130
124
|
resolvedTenant = resolveTenantId({});
|
|
131
125
|
}
|
|
132
126
|
const ctx = {
|
|
133
|
-
hippoRoot:
|
|
127
|
+
hippoRoot: d.hippoRoot,
|
|
134
128
|
tenantId: resolvedTenant,
|
|
135
|
-
actor:
|
|
129
|
+
actor: { subject: 'connector:slack', role: 'admin' },
|
|
136
130
|
};
|
|
137
131
|
if (body === undefined || !isSlackEventEnvelope(body)) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
error: 'not an event_callback envelope',
|
|
145
|
-
bucket: 'parse_error',
|
|
146
|
-
signature: sigStr,
|
|
147
|
-
slackTimestamp: tsStr,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
finally {
|
|
151
|
-
closeHippoDb(db);
|
|
152
|
-
}
|
|
153
|
-
sendJson(res, 200, { ok: true, status: 'dlq' });
|
|
132
|
+
parkInDlq(d, {
|
|
133
|
+
tenantId: ctx.tenantId,
|
|
134
|
+
teamId: teamIdFromRaw,
|
|
135
|
+
error: 'not an event_callback envelope',
|
|
136
|
+
bucket: 'parse_error',
|
|
137
|
+
});
|
|
154
138
|
return;
|
|
155
139
|
}
|
|
140
|
+
dispatchSlackEvent(d, ctx, body);
|
|
141
|
+
}
|
|
142
|
+
function parkUnparseable(d, teamIdFromRaw) {
|
|
143
|
+
// Attribute the parse failure to the originating workspace via the regex-extracted
|
|
144
|
+
// team_id; a null or unknown team writes tenantId=null, which lands as '__unroutable__'.
|
|
145
|
+
const db = openHippoDb(d.hippoRoot);
|
|
146
|
+
try {
|
|
147
|
+
const parseFailTenant = teamIdFromRaw !== null ? resolveTenantForTeam(db, teamIdFromRaw) : null;
|
|
148
|
+
writeToDlq(db, {
|
|
149
|
+
tenantId: parseFailTenant, // null → '__unroutable__' sentinel
|
|
150
|
+
teamId: teamIdFromRaw,
|
|
151
|
+
rawPayload: d.rawBody,
|
|
152
|
+
error: 'invalid JSON',
|
|
153
|
+
bucket: 'parse_error',
|
|
154
|
+
signature: d.signature,
|
|
155
|
+
slackTimestamp: d.slackTimestamp,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
closeHippoDb(db);
|
|
160
|
+
}
|
|
161
|
+
sendJson(d.res, 200, { ok: true, status: 'dlq' });
|
|
162
|
+
}
|
|
163
|
+
function dispatchSlackEvent(d, ctx, body) {
|
|
164
|
+
const { res } = d;
|
|
156
165
|
const inner = body.event;
|
|
157
166
|
if (isSlackMessageEvent(inner)) {
|
|
158
167
|
if (inner.subtype === 'message_deleted' && inner.deleted_ts) {
|
|
@@ -182,22 +191,11 @@ export async function handleSlackEventsWebhook({ req, res, opts }) {
|
|
|
182
191
|
sendJson(res, 200, { ok: true, status: r.status, memoryId: r.memoryId });
|
|
183
192
|
return;
|
|
184
193
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
error: `unhandled event type: ${inner.type ?? 'unknown'}`,
|
|
192
|
-
bucket: 'parse_error',
|
|
193
|
-
signature: sigStr,
|
|
194
|
-
slackTimestamp: tsStr,
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
finally {
|
|
198
|
-
closeHippoDb(db);
|
|
199
|
-
}
|
|
200
|
-
sendJson(res, 200, { ok: true, status: 'dlq' });
|
|
201
|
-
return;
|
|
194
|
+
parkInDlq(d, {
|
|
195
|
+
tenantId: ctx.tenantId,
|
|
196
|
+
teamId: body.team_id,
|
|
197
|
+
error: `unhandled event type: ${inner.type ?? 'unknown'}`,
|
|
198
|
+
bucket: 'parse_error',
|
|
199
|
+
});
|
|
202
200
|
}
|
|
203
201
|
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { MemoryEntry, type DecayOptions } from '../memory.js';
|
|
2
|
+
/** Pairs of live non-semantic memories that contradict each other, in survivor order. */
|
|
3
|
+
export declare function detectConflicts(entries: MemoryEntry[], now: Date, decayOpts?: DecayOptions, rescuedIds?: Set<string>): Array<{
|
|
4
|
+
memory_a_id: string;
|
|
5
|
+
memory_b_id: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
score: number;
|
|
8
|
+
}>;
|
|
9
|
+
export declare function jaccardSets(a: Set<string>, b: Set<string>): number;
|
|
10
|
+
//# sourceMappingURL=conflicts.d.ts.map
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { Layer, calculateStrength } from '../memory.js';
|
|
2
|
+
import { jaccardMinShared, overlapPartners } from '../overlap-index.js';
|
|
3
|
+
import { isQuarantineScope } from '../quarantine.js';
|
|
4
|
+
import { DECAY_THRESHOLD } from './decay.js';
|
|
5
|
+
// Contradictions should be gated by content overlap, not shared tags. Tags like
|
|
6
|
+
// `feedback` / `policy` are too coarse and can make unrelated rules look like
|
|
7
|
+
// conflicts before the polarity heuristics run.
|
|
8
|
+
// Jaccard threshold on stopword-filtered tokens. Only applied after a polarity
|
|
9
|
+
// signal has already been detected (explicit pair or inferred negation), so
|
|
10
|
+
// this just filters out drive-by topic similarity, not semantic drift.
|
|
11
|
+
const CONFLICT_OVERLAP_THRESHOLD = 0.5;
|
|
12
|
+
// Minimum distinctive shared tokens before we trust an overlap score. Filters
|
|
13
|
+
// out cases where two memories share only common English + a project name.
|
|
14
|
+
const CONFLICT_MIN_RARE_SHARED = 2;
|
|
15
|
+
// Polarity is detected on the first N words only. A stray "not" in the middle
|
|
16
|
+
// of a long memory shouldn't flip the whole thing negative.
|
|
17
|
+
const POLARITY_WINDOW_WORDS = 40;
|
|
18
|
+
const CONFLICT_STOPWORDS = new Set([
|
|
19
|
+
'the', 'a', 'an', 'is', 'was', 'are', 'were', 'be', 'been', 'being', 'to', 'of', 'in',
|
|
20
|
+
'for', 'on', 'with', 'at', 'by', 'from', 'it', 'this', 'that', 'and', 'or', 'but', 'so',
|
|
21
|
+
'if', 'as', 'we', 'i', 'you', 'they', 'he', 'she', 'my', 'our', 'your', 'its', 'his',
|
|
22
|
+
'her', 'their', 'up', 'out', 'just', 'also', 'then', 'than', 'some', 'all', 'any',
|
|
23
|
+
'each', 'very', 'too', 'do', 'did', 'does', 'has', 'had', 'have', 'will', 'would',
|
|
24
|
+
'could', 'should', 'may', 'might', 'can', 'shall', 'when', 'where', 'what', 'which',
|
|
25
|
+
'who', 'how', 'why', 'there', 'here', 'about', 'into', 'over', 'after', 'before',
|
|
26
|
+
'between', 'through', 'during', 'against', 'within', 'without', 'toward', 'upon',
|
|
27
|
+
'more', 'most', 'less', 'least', 'other', 'such', 'same', 'new', 'old', 'one', 'two',
|
|
28
|
+
]);
|
|
29
|
+
/** Pairs of live non-semantic memories that contradict each other, in survivor order. */
|
|
30
|
+
export function detectConflicts(entries, now, decayOpts = {},
|
|
31
|
+
// LC2-E3 (opt-in, default off): ids rescued by this cycle's decay pass.
|
|
32
|
+
// detectConflicts recomputes its own strength>=DECAY_THRESHOLD survivor
|
|
33
|
+
// filter independently of the decay pass above; without this bypass,
|
|
34
|
+
// rescued entries would be silently re-excluded from conflict detection
|
|
35
|
+
// every cycle even though the decay pass just decided to keep them.
|
|
36
|
+
// Default empty set: flag-off behavior is unchanged.
|
|
37
|
+
rescuedIds = new Set()) {
|
|
38
|
+
const survivors = entries.filter((entry) => entry.layer !== Layer.Semantic
|
|
39
|
+
// CD5: an unreviewed quarantined row must not taint a visible memory as conflicted.
|
|
40
|
+
&& !isQuarantineScope(entry.scope ?? null)
|
|
41
|
+
&& (rescuedIds.has(entry.id) || calculateStrength(entry, now, decayOpts) >= DECAY_THRESHOLD));
|
|
42
|
+
const detected = [];
|
|
43
|
+
const profiles = survivors.map((entry) => conflictProfile(entry.content));
|
|
44
|
+
const partnersOf = overlapPartners(profiles.map((p) => p.distinct), jaccardMinShared(CONFLICT_OVERLAP_THRESHOLD, CONFLICT_MIN_RARE_SHARED));
|
|
45
|
+
for (let i = 0; i < survivors.length; i++) {
|
|
46
|
+
for (const j of partnersOf(i)) {
|
|
47
|
+
// Traces are variants of each other, not contradictions. Two
|
|
48
|
+
// strategies for the same task can both be valid; conflict detection
|
|
49
|
+
// exists for stated-rule disagreement, not strategy diversity.
|
|
50
|
+
if (survivors[i].layer === Layer.Trace && survivors[j].layer === Layer.Trace)
|
|
51
|
+
continue;
|
|
52
|
+
if (survivors[i].superseded_by || survivors[j].superseded_by)
|
|
53
|
+
continue;
|
|
54
|
+
if (!recalledTogether(survivors[i], survivors[j]))
|
|
55
|
+
continue;
|
|
56
|
+
if ([survivors[i], survivors[j]].some((e) => e.tags.includes('extracted') || e.tags.includes('session-digest')))
|
|
57
|
+
continue;
|
|
58
|
+
const reasonAndScore = describeConflict(profiles[i], profiles[j]);
|
|
59
|
+
if (!reasonAndScore)
|
|
60
|
+
continue;
|
|
61
|
+
detected.push({
|
|
62
|
+
memory_a_id: survivors[i].id,
|
|
63
|
+
memory_b_id: survivors[j].id,
|
|
64
|
+
reason: reasonAndScore.reason,
|
|
65
|
+
score: reasonAndScore.score,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return detected;
|
|
70
|
+
}
|
|
71
|
+
/** One project's ambient context can show both: same tenant, and the same project or a user-global row beside a project's. */
|
|
72
|
+
function recalledTogether(a, b) {
|
|
73
|
+
if (a.tenantId !== b.tenantId)
|
|
74
|
+
return false;
|
|
75
|
+
const [x, y] = [a.origin_project ?? null, b.origin_project ?? null];
|
|
76
|
+
return x === y || (x === '' && y !== null) || (y === '' && x !== null);
|
|
77
|
+
}
|
|
78
|
+
function conflictProfile(text) {
|
|
79
|
+
const opening = openingWindow(text);
|
|
80
|
+
// Polarity is measured only in the first POLARITY_WINDOW_WORDS, so a stray
|
|
81
|
+
// negation deep in a prose memory doesn't flip the intent.
|
|
82
|
+
// Pad with spaces so space-delimited patterns match words at the start/end.
|
|
83
|
+
return { distinct: distinctiveTokens(text), polarity: inferConflictPolarity(opening), window: ' ' + opening.toLowerCase() + ' ' };
|
|
84
|
+
}
|
|
85
|
+
function describeConflict(a, b) {
|
|
86
|
+
// Jaccard on stopword-stripped tokens. Defer the threshold check until we
|
|
87
|
+
// know whether an explicit polarity pair is present (lower bar for those).
|
|
88
|
+
const overlapScore = jaccardSets(a.distinct, b.distinct);
|
|
89
|
+
// Require at least N shared distinctive tokens so two short memories sharing
|
|
90
|
+
// only "the project name" don't register.
|
|
91
|
+
let shared = 0;
|
|
92
|
+
for (const t of a.distinct)
|
|
93
|
+
if (b.distinct.has(t))
|
|
94
|
+
shared++;
|
|
95
|
+
if (shared < CONFLICT_MIN_RARE_SHARED)
|
|
96
|
+
return null;
|
|
97
|
+
const conflictType = classifyConflictType(a.window, b.window, a.polarity, b.polarity);
|
|
98
|
+
if (!conflictType)
|
|
99
|
+
return null;
|
|
100
|
+
if (overlapScore < CONFLICT_OVERLAP_THRESHOLD)
|
|
101
|
+
return null;
|
|
102
|
+
return {
|
|
103
|
+
reason: conflictType,
|
|
104
|
+
score: overlapScore,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function distinctiveTokens(text) {
|
|
108
|
+
return new Set(text
|
|
109
|
+
.toLowerCase()
|
|
110
|
+
.replace(/[^\w\s]/g, ' ')
|
|
111
|
+
.split(/\s+/)
|
|
112
|
+
.filter((t) => t.length > 2 && !CONFLICT_STOPWORDS.has(t)));
|
|
113
|
+
}
|
|
114
|
+
export function jaccardSets(a, b) {
|
|
115
|
+
if (a.size === 0 && b.size === 0)
|
|
116
|
+
return 1;
|
|
117
|
+
if (a.size === 0 || b.size === 0)
|
|
118
|
+
return 0;
|
|
119
|
+
let inter = 0;
|
|
120
|
+
for (const t of a)
|
|
121
|
+
if (b.has(t))
|
|
122
|
+
inter++;
|
|
123
|
+
const union = a.size + b.size - inter;
|
|
124
|
+
return union === 0 ? 0 : inter / union;
|
|
125
|
+
}
|
|
126
|
+
function openingWindow(text) {
|
|
127
|
+
return text.split(/\s+/).slice(0, POLARITY_WINDOW_WORDS).join(' ');
|
|
128
|
+
}
|
|
129
|
+
// Takes opening windows only, so " on " and " off " as prepositions deep in long prose don't read as enabled/disabled.
|
|
130
|
+
function classifyConflictType(a, b, aPolarity, bPolarity) {
|
|
131
|
+
// Tightened tokens: require whole-word boundaries so " on " alone doesn't
|
|
132
|
+
// match "on/off". Pair only `enabled` ↔ `disabled` and explicit on/off in
|
|
133
|
+
// imperative context.
|
|
134
|
+
const enabledDisabled = (containsAny(a, [' enabled ', ' enable ']) && containsAny(b, [' disabled ', ' disable ']))
|
|
135
|
+
|| (containsAny(b, [' enabled ', ' enable ']) && containsAny(a, [' disabled ', ' disable ']));
|
|
136
|
+
if (enabledDisabled)
|
|
137
|
+
return 'enabled/disabled mismatch on overlapping statement';
|
|
138
|
+
const trueFalse = (containsAny(a, [' true ', ' true.', ' true,', ' yes ']) && containsAny(b, [' false ', ' false.', ' false,', ' no ']))
|
|
139
|
+
|| (containsAny(b, [' true ', ' true.', ' true,', ' yes ']) && containsAny(a, [' false ', ' false.', ' false,', ' no ']));
|
|
140
|
+
if (trueFalse)
|
|
141
|
+
return 'true/false mismatch on overlapping statement';
|
|
142
|
+
const alwaysNever = (containsAny(a, [' always ', ' must ']) && containsAny(b, [' never ', ' must not ']))
|
|
143
|
+
|| (containsAny(b, [' always ', ' must ']) && containsAny(a, [' never ', ' must not ']));
|
|
144
|
+
if (alwaysNever)
|
|
145
|
+
return 'always/never mismatch on overlapping statement';
|
|
146
|
+
if ((aPolarity === 'positive' && bPolarity === 'negative') || (aPolarity === 'negative' && bPolarity === 'positive')) {
|
|
147
|
+
return 'negation polarity mismatch on overlapping statement';
|
|
148
|
+
}
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
function inferConflictPolarity(text) {
|
|
152
|
+
const lowered = ` ${text.toLowerCase()} `;
|
|
153
|
+
const negativePatterns = [
|
|
154
|
+
' not ', ' never ', ' no ', " don't ", ' do not ', " doesn't ", ' does not ',
|
|
155
|
+
" can't ", ' cannot ', " shouldn't ", ' should not ', ' disabled ', ' disable ', ' off ',
|
|
156
|
+
' false ', ' missing ', ' broken ', ' failed ',
|
|
157
|
+
];
|
|
158
|
+
const positivePatterns = [
|
|
159
|
+
' enabled ', ' enable ', ' works ', ' working ', ' true ', ' available ', ' present ', ' on ',
|
|
160
|
+
' always ', ' must ',
|
|
161
|
+
];
|
|
162
|
+
if (containsAny(lowered, negativePatterns))
|
|
163
|
+
return 'negative';
|
|
164
|
+
if (containsAny(lowered, positivePatterns))
|
|
165
|
+
return 'positive';
|
|
166
|
+
return 'neutral';
|
|
167
|
+
}
|
|
168
|
+
function stripConflictPolarity(text) {
|
|
169
|
+
return text
|
|
170
|
+
.toLowerCase()
|
|
171
|
+
.replace(/\b(?:not|never|no|don['’]?t|do\s+not|doesn['’]?t|does\s+not|can['’]?t|cannot|shouldn['’]?t|should\s+not|enabled|enable|disabled|disable|on|off|true|false|always|must|must\s+not|works?|working|missing|broken|failed|available|present)\b/g, ' ')
|
|
172
|
+
.replace(/\s+/g, ' ')
|
|
173
|
+
.trim();
|
|
174
|
+
}
|
|
175
|
+
function containsAny(text, needles) {
|
|
176
|
+
return needles.some((needle) => text.includes(needle));
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=conflicts.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { MemoryEntry } from '../memory.js';
|
|
2
|
+
import { type MvRankInfo } from '../memory-value.js';
|
|
3
|
+
import type { SleepRun } from './run.js';
|
|
4
|
+
export declare const DECAY_THRESHOLD = 0.05;
|
|
5
|
+
/** What the decay pass hands to the conflict check and the rescue audit at the end of the run. */
|
|
6
|
+
export interface DecayOutcome {
|
|
7
|
+
rescuedIds: Set<string>;
|
|
8
|
+
rescuedEntries: MemoryEntry[];
|
|
9
|
+
rankById: Map<string, MvRankInfo>;
|
|
10
|
+
}
|
|
11
|
+
export declare function decayPass(run: SleepRun): DecayOutcome;
|
|
12
|
+
//# sourceMappingURL=decay.d.ts.map
|