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
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { envHomeDir, processEnv } from '../env.js';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
/** JSON-value string check. `constructor` narrows a primitive via its boxed wrapper
|
|
6
|
+
* instead of inspecting the `typeof` tag (anti-slop/no-runtime-typeof); equivalent to
|
|
7
|
+
* `typeof value === 'string'` for every value JSON.parse can ever produce. */
|
|
8
|
+
export function isJsonString(value) {
|
|
9
|
+
return value !== undefined && value !== null && value.constructor === String;
|
|
10
|
+
}
|
|
11
|
+
/** JSON-value plain-object check (excludes arrays and null), typeof-free for the same
|
|
12
|
+
* reason as isJsonString above. */
|
|
13
|
+
export function isJsonObject(value) {
|
|
14
|
+
return value !== undefined && value !== null && !Array.isArray(value) && value.constructor === Object;
|
|
15
|
+
}
|
|
16
|
+
export const HIPPO_SLEEP_MARKER = 'hippo sleep';
|
|
17
|
+
export const HIPPO_LAST_SLEEP_MARKER = 'hippo last-sleep';
|
|
18
|
+
export const HIPPO_CAPTURE_MARKER = 'hippo capture --last-session';
|
|
19
|
+
export const HIPPO_SESSION_END_MARKER = 'hippo session-end';
|
|
20
|
+
export const HIPPO_PINNED_INJECT_MARKER = 'hippo context --pinned-only';
|
|
21
|
+
export const HIPPO_PINNED_INJECT_COMMAND = 'hippo context --pinned-only --include-recent 5 --format additional-context';
|
|
22
|
+
export const HIPPO_CODEX_WRAPPER_MARKER = 'hippo codex wrapper';
|
|
23
|
+
export const HIPPO_PRE_COMPACT_MARKER = 'hippo pre-compact';
|
|
24
|
+
export const HIPPO_COMPACT_RESUME_MARKER = 'hippo compact-resume';
|
|
25
|
+
export const HIPPO_CAPTURE_ERROR_MARKER = 'hippo capture-error';
|
|
26
|
+
export const HIPPO_POST_COMPACT_MARKER = 'hippo post-compact';
|
|
27
|
+
export function homeDir() {
|
|
28
|
+
return envHomeDir() || os.homedir();
|
|
29
|
+
}
|
|
30
|
+
/** Codex's config folder: $CODEX_HOME, else ~/.codex, as the Codex hooks docs describe. */
|
|
31
|
+
export function codexHomeDir(home = homeDir(), env = processEnv()) {
|
|
32
|
+
return env.CODEX_HOME || path.join(home, '.codex');
|
|
33
|
+
}
|
|
34
|
+
/** Codex counts as installed only when its config folder exists: Codex itself refuses a CODEX_HOME that is not a folder. */
|
|
35
|
+
export function isCodexPresent(home = homeDir()) {
|
|
36
|
+
return fs.statSync(codexHomeDir(home), { throwIfNoEntry: false })?.isDirectory() === true;
|
|
37
|
+
}
|
|
38
|
+
/** Codex hashes each hook and skips new or changed ones until the user reviews them in `/hooks`, so the reminder says what they would trust. */
|
|
39
|
+
export const CODEX_TRUST_LINE = "The per-prompt hook sends your pinned memories plus up to 5 that match the prompt. Codex runs hippo's hooks only after you trust them once in `/hooks`.";
|
|
40
|
+
/**
|
|
41
|
+
* Default log path consumed by `hippo last-sleep`. Shared fallback when
|
|
42
|
+
* a caller doesn't pass --path explicitly.
|
|
43
|
+
*/
|
|
44
|
+
export function defaultSleepLogPath() {
|
|
45
|
+
return path.join(homeDir(), '.hippo', 'logs', 'last-sleep.log');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Diagnostic-only log path for `hippo pre-compact`. Deliberately separate
|
|
49
|
+
* from the SessionEnd sleep log: `hippo last-sleep` truncates that file on
|
|
50
|
+
* every SessionStart, which would wipe pre-compact lines before anyone
|
|
51
|
+
* could read them. Nothing consumes this file programmatically — it exists
|
|
52
|
+
* for manual troubleshooting only. Overridden by `--log-file`.
|
|
53
|
+
*/
|
|
54
|
+
export function defaultPreCompactLogPath() {
|
|
55
|
+
return path.join(homeDir(), '.hippo', 'logs', 'pre-compact.log');
|
|
56
|
+
}
|
|
57
|
+
export function ensureDir(dir) {
|
|
58
|
+
if (!fs.existsSync(dir))
|
|
59
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Detect which AI coding tools are installed based on config directory presence.
|
|
63
|
+
* Used by `hippo setup` to decide which JSON-hook installs to run.
|
|
64
|
+
*/
|
|
65
|
+
export function detectInstalledTools() {
|
|
66
|
+
const home = homeDir();
|
|
67
|
+
const exists = (...parts) => fs.existsSync(path.join(home, ...parts));
|
|
68
|
+
return [
|
|
69
|
+
{ name: 'claude-code', configDir: '~/.claude', detected: exists('.claude'), kind: 'json-hook' },
|
|
70
|
+
{ name: 'opencode', configDir: '~/.config/opencode', detected: exists('.config', 'opencode'), kind: 'plugin', notes: 'installs a TS plugin at ~/.config/opencode/plugins/hippo.ts' },
|
|
71
|
+
{ name: 'openclaw', configDir: '~/.openclaw', detected: exists('.openclaw'), kind: 'plugin', notes: 'install via `openclaw plugins install hippo-memory`' },
|
|
72
|
+
{ name: 'codex', configDir: '~/.codex', detected: isCodexPresent(home), kind: 'wrapper', notes: 'memory hooks in hooks.json, and wraps the detected codex launcher for session-end consolidation' },
|
|
73
|
+
{ name: 'cursor', configDir: '~/.cursor', detected: exists('.cursor'), kind: 'markdown-instruction', notes: 'no hook API - patches AGENTS.md in the project' },
|
|
74
|
+
{ name: 'pi', configDir: '~/.pi', detected: exists('.pi'), kind: 'markdown-instruction', notes: 'no hook API - patches AGENTS.md in the project' },
|
|
75
|
+
];
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=shared.js.map
|
package/dist/http-retry.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface RetryPolicy {
|
|
|
7
7
|
baseDelayMs?: number;
|
|
8
8
|
/** A Retry-After longer than this hands the response back, so a caller with its own long pause keeps it. */
|
|
9
9
|
maxDelayMs?: number;
|
|
10
|
+
/** Which responses to retry; defaults to 429 and 5xx. A write narrows it to answers that prove nothing committed. */
|
|
11
|
+
retryOn?: (res: Response) => boolean;
|
|
10
12
|
fetchFn?: typeof fetch;
|
|
11
13
|
sleep?: (ms: number) => Promise<void>;
|
|
12
14
|
random?: () => number;
|
package/dist/http-retry.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/** One retry policy for outbound HTTP: a timeout on every attempt, and backoff on 429 and 5xx only. */
|
|
2
|
+
import { envLlmTimeoutMs } from './env.js';
|
|
2
3
|
const DEFAULT_ATTEMPTS = 3;
|
|
3
4
|
const DEFAULT_BASE_DELAY_MS = 250;
|
|
4
5
|
const DEFAULT_MAX_DELAY_MS = 8_000;
|
|
5
6
|
const DEFAULT_LLM_TIMEOUT_MS = 60_000;
|
|
6
7
|
/** LLM calls (consolidation refine, DAG summaries, fact extraction) share one budget; `HIPPO_LLM_TIMEOUT_MS` overrides it. */
|
|
7
8
|
export function llmTimeoutMs() {
|
|
8
|
-
|
|
9
|
-
return parsed > 0 ? parsed : DEFAULT_LLM_TIMEOUT_MS;
|
|
9
|
+
return envLlmTimeoutMs() ?? DEFAULT_LLM_TIMEOUT_MS;
|
|
10
10
|
}
|
|
11
11
|
export function isRetryableStatus(status) {
|
|
12
12
|
return status === 429 || (status >= 500 && status <= 599);
|
|
@@ -30,11 +30,12 @@ export async function fetchWithRetry(url, init, policy) {
|
|
|
30
30
|
const maxDelayMs = policy.maxDelayMs ?? DEFAULT_MAX_DELAY_MS;
|
|
31
31
|
const sleep = policy.sleep ?? realSleep;
|
|
32
32
|
const random = policy.random ?? Math.random;
|
|
33
|
+
const retryOn = policy.retryOn ?? ((res) => isRetryableStatus(res.status));
|
|
33
34
|
for (let attempt = 1;; attempt++) {
|
|
34
35
|
const timeout = AbortSignal.timeout(policy.timeoutMs);
|
|
35
36
|
const signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;
|
|
36
37
|
const res = await fetchFn(url, { ...init, signal });
|
|
37
|
-
if (!
|
|
38
|
+
if (!retryOn(res) || attempt >= attempts)
|
|
38
39
|
return res;
|
|
39
40
|
const retryAfter = parseRetryAfterMs(res.headers.get('retry-after'));
|
|
40
41
|
if (retryAfter !== null && retryAfter > maxDelayMs)
|
package/dist/http-util.d.ts
CHANGED
|
@@ -28,6 +28,9 @@ export declare function sendJson<T>(res: ServerResponse, status: number, body: T
|
|
|
28
28
|
* mid-stream so we don't wait for an attacker to finish before erroring out.
|
|
29
29
|
*/
|
|
30
30
|
export declare function readBody(req: IncomingMessage): Promise<string>;
|
|
31
|
+
export declare const LOOPBACK_HOST_HEADER: RegExp;
|
|
32
|
+
/** A browser request sent by another site. Non-browser clients send neither header and pass. */
|
|
33
|
+
export declare function isCrossSite(req: IncomingMessage): boolean;
|
|
31
34
|
/** Per-request values a connector webhook receiver reads; ServeOpts and the /v1 RouteRequest both satisfy it. */
|
|
32
35
|
export interface WebhookRequest {
|
|
33
36
|
req: IncomingMessage;
|
package/dist/http-util.js
CHANGED
|
@@ -53,4 +53,14 @@ export async function readBody(req) {
|
|
|
53
53
|
}
|
|
54
54
|
return Buffer.concat(chunks).toString('utf8');
|
|
55
55
|
}
|
|
56
|
+
// Any other Host on a loopback socket is DNS rebinding: a hostile page resolved to 127.0.0.1.
|
|
57
|
+
export const LOOPBACK_HOST_HEADER = /^(localhost|127\.0\.0\.1|\[::1\])(:\d+)?$/i;
|
|
58
|
+
/** A browser request sent by another site. Non-browser clients send neither header and pass. */
|
|
59
|
+
export function isCrossSite(req) {
|
|
60
|
+
const site = req.headers['sec-fetch-site'];
|
|
61
|
+
if (site !== undefined && site !== 'same-origin' && site !== 'none')
|
|
62
|
+
return true;
|
|
63
|
+
const origin = req.headers.origin;
|
|
64
|
+
return origin !== undefined && origin !== `http://${req.headers.host}`;
|
|
65
|
+
}
|
|
56
66
|
//# sourceMappingURL=http-util.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Memory importers for Hippo.
|
|
3
3
|
* Imports memories from ChatGPT, Claude, Cursor, generic files, and structured markdown.
|
|
4
4
|
*/
|
|
5
|
-
import { MemoryEntry } from '
|
|
5
|
+
import { MemoryEntry } from '../memory.js';
|
|
6
6
|
export interface ImportResult {
|
|
7
7
|
total: number;
|
|
8
8
|
imported: number;
|
|
@@ -58,19 +58,15 @@ export interface ImportOptions {
|
|
|
58
58
|
* create MemoryEntry objects, write them (unless dry-run), and return a result.
|
|
59
59
|
*/
|
|
60
60
|
export declare function importEntries(chunks: string[], source: string, tags: string[], options: ImportOptions): ImportResult;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
export
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
* sequential writer; same caveat applies here).
|
|
74
|
-
*/
|
|
75
|
-
export declare function importVault(folderPath: string, options: ImportOptions): ImportResult;
|
|
76
|
-
//# sourceMappingURL=importers.d.ts.map
|
|
61
|
+
/** The full value space `JSON.parse` can produce. Boundary-guard functions in
|
|
62
|
+
* this file accept `JsonValue` (never `unknown`) so a value's origin as
|
|
63
|
+
* unparsed external JSON stays visible in its type, then narrow it via the
|
|
64
|
+
* `isJson*` predicates below. */
|
|
65
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
66
|
+
[key: string]: JsonValue;
|
|
67
|
+
};
|
|
68
|
+
export declare function isJsonString(x: JsonValue): x is string;
|
|
69
|
+
export declare function isJsonPlainObject(x: JsonValue): x is {
|
|
70
|
+
[key: string]: JsonValue;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=core.d.ts.map
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory importers for Hippo.
|
|
3
|
+
* Imports memories from ChatGPT, Claude, Cursor, generic files, and structured markdown.
|
|
4
|
+
*/
|
|
5
|
+
import { createMemory, Layer } from '../memory.js';
|
|
6
|
+
import { writeEntry } from '../store/entry-writes.js';
|
|
7
|
+
import { loadAllEntries } from '../store/entry-reads.js';
|
|
8
|
+
import { duplicateKey, storedTextKeys } from '../same-text.js';
|
|
9
|
+
import { getGlobalRoot, initGlobal } from '../shared.js';
|
|
10
|
+
import { openHippoDb, closeHippoDb } from '../db.js';
|
|
11
|
+
import { RejectedValueError, checkRejectionGuard } from '../rejection.js';
|
|
12
|
+
import { loadConfig } from '../config.js';
|
|
13
|
+
import { vetSecrets } from '../secret-detect.js';
|
|
14
|
+
import { log } from '../log.js';
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Shared core: dedup + write
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Given an array of raw text chunks, deduplicate against existing memories,
|
|
20
|
+
* create MemoryEntry objects, write them (unless dry-run), and return a result.
|
|
21
|
+
*/
|
|
22
|
+
export function importEntries(chunks, source, tags, options) {
|
|
23
|
+
const targetRoot = options.global ? getGlobalRoot() : options.hippoRoot;
|
|
24
|
+
// Ensure store is ready
|
|
25
|
+
if (options.global) {
|
|
26
|
+
initGlobal();
|
|
27
|
+
}
|
|
28
|
+
const keys = storedTextKeys(loadAllEntries(targetRoot, options.global ? undefined : options.tenantId));
|
|
29
|
+
const allTags = [...new Set([...tags, ...(options.extraTags ?? [])])];
|
|
30
|
+
const baseHalfLifeDays = loadConfig(targetRoot).defaultHalfLifeDays;
|
|
31
|
+
let total = 0;
|
|
32
|
+
let imported = 0;
|
|
33
|
+
let skipped = 0;
|
|
34
|
+
let rejected = 0;
|
|
35
|
+
let redacted = 0;
|
|
36
|
+
const entries = [];
|
|
37
|
+
// AT1 P2 fix: a dry-run preview never called writeEntry, so it never
|
|
38
|
+
// checked tombstones either — every non-duplicate chunk counted as
|
|
39
|
+
// `imported` even when a real run would refuse it, making the preview's
|
|
40
|
+
// `rejected` count silently 0. Probe (read-only) via the same guard
|
|
41
|
+
// writeEntry uses internally, without ever writing.
|
|
42
|
+
const dryRunDb = options.dryRun ? openHippoDb(targetRoot) : null;
|
|
43
|
+
try {
|
|
44
|
+
for (const raw of chunks) {
|
|
45
|
+
const { chunk, wasRedacted } = prepareImportChunk(raw, allTags);
|
|
46
|
+
// Skip empty or too-short chunks
|
|
47
|
+
if (!chunk || chunk.length < 10) {
|
|
48
|
+
skipped++;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
total++;
|
|
52
|
+
// Dedup check: skip only when the same text is already stored
|
|
53
|
+
if (keys.has(duplicateKey(chunk))) {
|
|
54
|
+
skipped++;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const entry = createImportEntry(chunk, source, allTags, options, baseHalfLifeDays);
|
|
58
|
+
if (!writeOrProbeImport(targetRoot, entry, options, dryRunDb)) {
|
|
59
|
+
rejected++;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// Add to existing so subsequent chunks dedup against freshly imported ones
|
|
63
|
+
if (!options.dryRun)
|
|
64
|
+
keys.add(duplicateKey(chunk));
|
|
65
|
+
entries.push(entry);
|
|
66
|
+
imported++;
|
|
67
|
+
if (wasRedacted)
|
|
68
|
+
redacted++;
|
|
69
|
+
}
|
|
70
|
+
return { total, imported, skipped, rejected, redacted, entries };
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
if (dryRunDb)
|
|
74
|
+
closeHippoDb(dryRunDb);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** The secret-vetted chunk capped at 1000 chars, and whether vetting changed it. */
|
|
78
|
+
function prepareImportChunk(raw, allTags) {
|
|
79
|
+
const original = raw.trim();
|
|
80
|
+
const trimmed = vetSecrets(original, allTags, true).content;
|
|
81
|
+
const wasRedacted = trimmed !== original;
|
|
82
|
+
if (trimmed.length > 1000) {
|
|
83
|
+
log.warn(`imported memory truncated from ${trimmed.length} to 1000 chars`);
|
|
84
|
+
}
|
|
85
|
+
return { chunk: trimmed.slice(0, 1000), wasRedacted };
|
|
86
|
+
}
|
|
87
|
+
function createImportEntry(chunk, source, allTags, options, baseHalfLifeDays) {
|
|
88
|
+
// A3: kind defaults to 'distilled'. ChatGPT/Claude/Cursor exports are curated
|
|
89
|
+
// user pastes, not raw transcripts from a system of record, so distilled is
|
|
90
|
+
// correct here. E1.3 (Slack ingestion) shipped 2026-04-29 in src/connectors/slack/
|
|
91
|
+
// and sets kind: 'raw' + routes deletions through archiveRawMemory() — these
|
|
92
|
+
// importers stay 'distilled' per the original reasoning. See MEMORY_ENVELOPE.md.
|
|
93
|
+
// L9: the dedup read above is scoped by options.tenantId — the WRITE
|
|
94
|
+
// must match, or scoped-dedup-passes-then-default-tenant-write breaks
|
|
95
|
+
// the per-tenant contract. Mirror the dedup-read guard: global=true
|
|
96
|
+
// → host-wide write to global store (tenantId irrelevant, createMemory
|
|
97
|
+
// defaults to 'default'). global=false → write to the same tenant as
|
|
98
|
+
// the dedup read.
|
|
99
|
+
return createMemory(chunk, {
|
|
100
|
+
layer: Layer.Episodic,
|
|
101
|
+
tags: allTags,
|
|
102
|
+
source,
|
|
103
|
+
confidence: 'observed',
|
|
104
|
+
tenantId: options.global ? undefined : options.tenantId,
|
|
105
|
+
baseHalfLifeDays,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** Writes the entry, or on a dry run only probes the guard; false when a rejected value refuses it. */
|
|
109
|
+
function writeOrProbeImport(targetRoot, entry, options, dryRunDb) {
|
|
110
|
+
if (options.dryRun) {
|
|
111
|
+
if (dryRunDb) {
|
|
112
|
+
try {
|
|
113
|
+
checkRejectionGuard(dryRunDb, entry.tenantId ?? 'default', entry.id, entry.content);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
if (err instanceof RejectedValueError)
|
|
117
|
+
return false;
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
// AT1 (plan §3 containment): a rejection refuses one CHUNK, not the
|
|
124
|
+
// whole import batch. Caught per-item so siblings still land.
|
|
125
|
+
try {
|
|
126
|
+
writeEntry(targetRoot, entry);
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
if (err instanceof RejectedValueError)
|
|
130
|
+
return false;
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
export function isJsonString(x) {
|
|
136
|
+
return typeof x === 'string';
|
|
137
|
+
}
|
|
138
|
+
export function isJsonPlainObject(x) {
|
|
139
|
+
return x !== null && !Array.isArray(x) && typeof x === 'object';
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Minimal inline frontmatter split. Recognises a leading `---\n…\n---\n`
|
|
2
|
+
* block (no YAML dep). Returns the parsed key→value map plus the body with the
|
|
3
|
+
* block removed. When no well-formed block is present, `fm` is empty and
|
|
4
|
+
* `body` is the original content. */
|
|
5
|
+
interface FrontmatterParseResult {
|
|
6
|
+
fm: Record<string, string>;
|
|
7
|
+
body: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseFrontmatter(raw: string): FrontmatterParseResult;
|
|
10
|
+
/** Pull a frontmatter field that may be a YAML flow list (`[a, b]`), a
|
|
11
|
+
* comma-separated scalar (`a, b`), or a single token, into a string[]. Quotes
|
|
12
|
+
* and surrounding brackets are stripped; empty entries dropped. */
|
|
13
|
+
export declare function frontmatterList(value: string | undefined): string[];
|
|
14
|
+
/** Parse `[[wikilinks]]` from body text. `[[target]]` and `[[target|alias]]`
|
|
15
|
+
* both yield `target` (alias dropped). Returns de-duplicated, order-preserving
|
|
16
|
+
* target strings (trimmed). Embeds (`![[…]]`) are intentionally matched too —
|
|
17
|
+
* the leading `!` is not part of the `[[…]]` capture, so an embed contributes
|
|
18
|
+
* its target as a candidate, which is the desired no-crash baseline behaviour. */
|
|
19
|
+
export declare function parseWikilinks(body: string): string[];
|
|
20
|
+
/** Recursively collect files whose name matches `match` (`*.md` by default) under `root`,
|
|
21
|
+
* as paths relative to `root` with forward-slash separators (stable artifactRef keys across OSes).
|
|
22
|
+
* Symlinks are not followed. Skips dot-directories (the default `.hippo` store,
|
|
23
|
+
* `.git`, `.obsidian`, `.trash`) AND the canonicalized Hippo store path during
|
|
24
|
+
* the walk, so re-importing a vault that CONTAINS the store never ingests its own
|
|
25
|
+
* markdown mirror files (codex R5 P1: `hippo import --vault .` after `hippo
|
|
26
|
+
* init` in the vault would otherwise self-import its mirror rows and grow on
|
|
27
|
+
* every run). The root-IS-the-store case is handled one level up in
|
|
28
|
+
* importVault (a no-op early return), NOT here: returning [] for it would feed
|
|
29
|
+
* the deletion-sync an empty scan that mass-archives every live row (codex R8). */
|
|
30
|
+
export declare function collectMarkdownFiles(root: string, hippoRoot: string, match?: RegExp): string[];
|
|
31
|
+
/** Canonicalize a path for the self-store comparison: dereference symlinks /
|
|
32
|
+
* junctions and normalize case (Windows) via the OS realpath, so a junction or
|
|
33
|
+
* a case-variant path to the store is still recognized as self-store (codex R9
|
|
34
|
+
* P2: path.resolve does neither, so an aliased store path slipped past the
|
|
35
|
+
* guard and triggered the mass-archive). Falls back to path.resolve when the
|
|
36
|
+
* path does not exist yet - an uninitialized store or a typo'd vault path
|
|
37
|
+
* cannot be a live self-store, and a non-existent vault folder fails later in
|
|
38
|
+
* the walk (readdirSync) before deletion-sync can archive anything. */
|
|
39
|
+
export declare function realpathOrResolve(p: string): string;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=markdown-parse.d.ts.map
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { log } from '../log.js';
|
|
4
|
+
export function parseFrontmatter(raw) {
|
|
5
|
+
// Must start with `---` on its own line. Accept CRLF or LF.
|
|
6
|
+
const m = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
7
|
+
if (!m)
|
|
8
|
+
return { fm: {}, body: raw };
|
|
9
|
+
const block = m[1];
|
|
10
|
+
const body = raw.slice(m[0].length);
|
|
11
|
+
const fm = {};
|
|
12
|
+
const lines = block.split(/\r?\n/);
|
|
13
|
+
for (let i = 0; i < lines.length; i++) {
|
|
14
|
+
const kv = lines[i].match(/^([A-Za-z0-9_-]+)\s*:\s*(.*)$/);
|
|
15
|
+
if (!kv)
|
|
16
|
+
continue;
|
|
17
|
+
let val = kv[2].trim();
|
|
18
|
+
if (val === '') {
|
|
19
|
+
// YAML block-style list: `key:` followed by indented `- item` lines
|
|
20
|
+
// (common in Obsidian/Dendron frontmatter). Collect them into a
|
|
21
|
+
// comma-joined value so frontmatterList parses them (codex P2).
|
|
22
|
+
const items = [];
|
|
23
|
+
let j = i + 1;
|
|
24
|
+
let item;
|
|
25
|
+
while (j < lines.length && (item = lines[j].match(/^\s+-\s+(.+?)\s*$/)) !== null) {
|
|
26
|
+
items.push(item[1].replace(/^['"]|['"]$/g, '').trim());
|
|
27
|
+
j++;
|
|
28
|
+
}
|
|
29
|
+
if (items.length) {
|
|
30
|
+
val = items.join(', ');
|
|
31
|
+
i = j - 1;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
fm[kv[1]] = val;
|
|
35
|
+
}
|
|
36
|
+
return { fm, body };
|
|
37
|
+
}
|
|
38
|
+
/** Pull a frontmatter field that may be a YAML flow list (`[a, b]`), a
|
|
39
|
+
* comma-separated scalar (`a, b`), or a single token, into a string[]. Quotes
|
|
40
|
+
* and surrounding brackets are stripped; empty entries dropped. */
|
|
41
|
+
export function frontmatterList(value) {
|
|
42
|
+
if (!value)
|
|
43
|
+
return [];
|
|
44
|
+
let v = value.trim();
|
|
45
|
+
if (v.startsWith('[') && v.endsWith(']'))
|
|
46
|
+
v = v.slice(1, -1);
|
|
47
|
+
return v
|
|
48
|
+
.split(',')
|
|
49
|
+
.map((s) => s.trim().replace(/^['"]|['"]$/g, '').trim())
|
|
50
|
+
.filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
/** Parse `[[wikilinks]]` from body text. `[[target]]` and `[[target|alias]]`
|
|
53
|
+
* both yield `target` (alias dropped). Returns de-duplicated, order-preserving
|
|
54
|
+
* target strings (trimmed). Embeds (`![[…]]`) are intentionally matched too —
|
|
55
|
+
* the leading `!` is not part of the `[[…]]` capture, so an embed contributes
|
|
56
|
+
* its target as a candidate, which is the desired no-crash baseline behaviour. */
|
|
57
|
+
export function parseWikilinks(body) {
|
|
58
|
+
const out = [];
|
|
59
|
+
const seen = new Set();
|
|
60
|
+
const re = /\[\[([^\]]+?)\]\]/g;
|
|
61
|
+
let match;
|
|
62
|
+
while ((match = re.exec(body)) !== null) {
|
|
63
|
+
const inner = match[1];
|
|
64
|
+
const target = (inner.split('|')[0] ?? '').trim();
|
|
65
|
+
if (!target)
|
|
66
|
+
continue;
|
|
67
|
+
if (seen.has(target))
|
|
68
|
+
continue;
|
|
69
|
+
seen.add(target);
|
|
70
|
+
out.push(target);
|
|
71
|
+
}
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
/** Recursively collect files whose name matches `match` (`*.md` by default) under `root`,
|
|
75
|
+
* as paths relative to `root` with forward-slash separators (stable artifactRef keys across OSes).
|
|
76
|
+
* Symlinks are not followed. Skips dot-directories (the default `.hippo` store,
|
|
77
|
+
* `.git`, `.obsidian`, `.trash`) AND the canonicalized Hippo store path during
|
|
78
|
+
* the walk, so re-importing a vault that CONTAINS the store never ingests its own
|
|
79
|
+
* markdown mirror files (codex R5 P1: `hippo import --vault .` after `hippo
|
|
80
|
+
* init` in the vault would otherwise self-import its mirror rows and grow on
|
|
81
|
+
* every run). The root-IS-the-store case is handled one level up in
|
|
82
|
+
* importVault (a no-op early return), NOT here: returning [] for it would feed
|
|
83
|
+
* the deletion-sync an empty scan that mass-archives every live row (codex R8). */
|
|
84
|
+
export function collectMarkdownFiles(root, hippoRoot, match = /\.md$/i) {
|
|
85
|
+
const out = [];
|
|
86
|
+
// Canonicalize (realpath) so a non-dot HIPPO_HOME store nested in the vault is
|
|
87
|
+
// skipped even when hippoRoot is an aliased path (junction / Windows case
|
|
88
|
+
// variant); path.resolve would miss it and self-import the store's mirror
|
|
89
|
+
// files (codex R9 follow-up: same gap as the importVault guard, sibling site).
|
|
90
|
+
const resolvedHippoRoot = realpathOrResolve(hippoRoot);
|
|
91
|
+
const walk = (dir) => {
|
|
92
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
93
|
+
for (const ent of entries) {
|
|
94
|
+
if (ent.isSymbolicLink())
|
|
95
|
+
continue;
|
|
96
|
+
const abs = path.join(dir, ent.name);
|
|
97
|
+
if (ent.isDirectory()) {
|
|
98
|
+
// Skip dot-dirs (config/system, incl. the default `.hippo` store) and
|
|
99
|
+
// the canonicalized store path (covers a HIPPO_HOME outside `.hippo`).
|
|
100
|
+
if (ent.name.startsWith('.'))
|
|
101
|
+
continue;
|
|
102
|
+
if (realpathOrResolve(abs) === resolvedHippoRoot)
|
|
103
|
+
continue;
|
|
104
|
+
walk(abs);
|
|
105
|
+
}
|
|
106
|
+
else if (ent.isFile() && match.test(ent.name)) {
|
|
107
|
+
out.push(path.relative(root, abs).split(path.sep).join('/'));
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
walk(root);
|
|
112
|
+
out.sort();
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
/** Canonicalize a path for the self-store comparison: dereference symlinks /
|
|
116
|
+
* junctions and normalize case (Windows) via the OS realpath, so a junction or
|
|
117
|
+
* a case-variant path to the store is still recognized as self-store (codex R9
|
|
118
|
+
* P2: path.resolve does neither, so an aliased store path slipped past the
|
|
119
|
+
* guard and triggered the mass-archive). Falls back to path.resolve when the
|
|
120
|
+
* path does not exist yet - an uninitialized store or a typo'd vault path
|
|
121
|
+
* cannot be a live self-store, and a non-existent vault folder fails later in
|
|
122
|
+
* the walk (readdirSync) before deletion-sync can archive anything. */
|
|
123
|
+
export function realpathOrResolve(p) {
|
|
124
|
+
try {
|
|
125
|
+
return fs.realpathSync.native(p);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
log.debug(`import: realpath fell back to resolve for ${p}: ${err instanceof Error ? err.message : String(err)}`);
|
|
129
|
+
return path.resolve(p);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=markdown-parse.js.map
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { importEntries } from './core.js';
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Structured markdown importer (MEMORY.md / AGENTS.md format)
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
/**
|
|
7
|
+
* Slugify a heading for use as a tag.
|
|
8
|
+
* "Data Pipeline & Cache" -> "data-pipeline-cache"
|
|
9
|
+
*/
|
|
10
|
+
function slugify(heading) {
|
|
11
|
+
return heading
|
|
12
|
+
.toLowerCase()
|
|
13
|
+
.replace(/[^a-z0-9\s-]/g, ' ')
|
|
14
|
+
.trim()
|
|
15
|
+
.replace(/\s+/g, '-')
|
|
16
|
+
.replace(/-+/g, '-')
|
|
17
|
+
.slice(0, 50);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parse structured markdown into {content, sectionSlug} pairs.
|
|
21
|
+
* Each heading starts a new section. Bullet points / numbered items under
|
|
22
|
+
* the heading become individual memories tagged with the section slug.
|
|
23
|
+
*/
|
|
24
|
+
function parseStructuredMarkdown(raw) {
|
|
25
|
+
const results = [];
|
|
26
|
+
const lines = raw.split('\n');
|
|
27
|
+
let currentSection = '';
|
|
28
|
+
let currentSlug = '';
|
|
29
|
+
let pendingText = '';
|
|
30
|
+
function flush() {
|
|
31
|
+
if (!pendingText.trim())
|
|
32
|
+
return;
|
|
33
|
+
results.push({ content: pendingText.trim(), sectionSlug: currentSlug });
|
|
34
|
+
pendingText = '';
|
|
35
|
+
}
|
|
36
|
+
for (const line of lines) {
|
|
37
|
+
const trimmed = line.trim();
|
|
38
|
+
// Heading
|
|
39
|
+
const headingMatch = trimmed.match(/^(#{1,6})\s+(.+)/);
|
|
40
|
+
if (headingMatch) {
|
|
41
|
+
flush();
|
|
42
|
+
currentSection = headingMatch[2].trim();
|
|
43
|
+
currentSlug = slugify(currentSection);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
// Bullet or numbered item: flush previous, start new
|
|
47
|
+
if (/^[-*+]\s+/.test(trimmed) || /^\d+\.\s+/.test(trimmed)) {
|
|
48
|
+
flush();
|
|
49
|
+
const itemText = trimmed.replace(/^[-*+]\s+/, '').replace(/^\d+\.\s+/, '').trim();
|
|
50
|
+
pendingText = itemText;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// Empty line: flush current pending
|
|
54
|
+
if (!trimmed) {
|
|
55
|
+
flush();
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Continuation of current item
|
|
59
|
+
pendingText = pendingText ? pendingText + ' ' + trimmed : trimmed;
|
|
60
|
+
}
|
|
61
|
+
flush();
|
|
62
|
+
return results.filter((r) => r.content.length > 0);
|
|
63
|
+
}
|
|
64
|
+
export function importMarkdown(filePath, options) {
|
|
65
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
66
|
+
const parsed = parseStructuredMarkdown(raw);
|
|
67
|
+
// Group by section slug so we can pass per-chunk tags
|
|
68
|
+
// We call importEntries per unique slug to get the right tags per section
|
|
69
|
+
const bySlug = new Map();
|
|
70
|
+
for (const { content, sectionSlug } of parsed) {
|
|
71
|
+
const list = bySlug.get(sectionSlug) ?? [];
|
|
72
|
+
list.push(content);
|
|
73
|
+
bySlug.set(sectionSlug, list);
|
|
74
|
+
}
|
|
75
|
+
let totalResult = { total: 0, imported: 0, skipped: 0, rejected: 0, entries: [] };
|
|
76
|
+
for (const [slug, chunks] of bySlug.entries()) {
|
|
77
|
+
const sectionTags = slug ? ['imported', slug] : ['imported'];
|
|
78
|
+
const result = importEntries(chunks, 'import:markdown', sectionTags, options);
|
|
79
|
+
totalResult = {
|
|
80
|
+
total: totalResult.total + result.total,
|
|
81
|
+
imported: totalResult.imported + result.imported,
|
|
82
|
+
skipped: totalResult.skipped + result.skipped,
|
|
83
|
+
// AT1 P2 fix: `rejected` is now optional on ImportResult (compat) — tolerate
|
|
84
|
+
// undefined on either side of the accumulation.
|
|
85
|
+
rejected: (totalResult.rejected ?? 0) + (result.rejected ?? 0),
|
|
86
|
+
redacted: (totalResult.redacted ?? 0) + (result.redacted ?? 0),
|
|
87
|
+
entries: [...totalResult.entries, ...result.entries],
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return totalResult;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ImportResult, type ImportOptions } from './core.js';
|
|
2
|
+
export declare function importChatGPT(filePath: string, options: ImportOptions): ImportResult;
|
|
3
|
+
export declare function importClaude(filePath: string, options: ImportOptions): ImportResult;
|
|
4
|
+
/** Import `.cursorrules`, one rule file, or a `.cursor/rules` tree of `.mdc` and `.md` rules. */
|
|
5
|
+
export declare function importCursor(sourcePath: string, options: ImportOptions): ImportResult;
|
|
6
|
+
export declare function importGenericFile(filePath: string, options: ImportOptions): ImportResult;
|
|
7
|
+
//# sourceMappingURL=sources.d.ts.map
|