hippo-memory 1.61.0 → 1.63.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 +37 -53
- package/dist/agent-memories/apply.d.ts +3 -1
- package/dist/agent-memories/apply.js +23 -1
- package/dist/agent-memories/claude-code.d.ts +4 -1
- package/dist/agent-memories/claude-code.js +53 -9
- package/dist/agent-memories/report.d.ts +1 -0
- package/dist/agent-memories/report.js +2 -2
- package/dist/agent-memories/sync.d.ts +3 -3
- package/dist/agent-memories/sync.js +46 -24
- package/dist/agent-memories/types.d.ts +0 -2
- package/dist/ambient-store.d.ts +4 -4
- package/dist/ambient-store.js +4 -3
- package/dist/api/assemble.d.ts +7 -10
- package/dist/api/assemble.js +62 -66
- package/dist/api/audit.d.ts +2 -2
- package/dist/api/audit.js +2 -2
- package/dist/api/auth.d.ts +6 -6
- package/dist/api/auth.js +5 -7
- package/dist/api/context-select.d.ts +50 -0
- package/dist/api/context-select.js +342 -0
- package/dist/api/context-types.d.ts +12 -17
- package/dist/api/context.d.ts +5 -4
- package/dist/api/context.js +208 -535
- package/dist/api/dormant.js +1 -1
- package/dist/api/drill-down.d.ts +4 -4
- package/dist/api/drill-down.js +56 -41
- package/dist/api/outcome.d.ts +8 -13
- package/dist/api/outcome.js +13 -17
- package/dist/api/promote.d.ts +5 -8
- package/dist/api/promote.js +55 -66
- package/dist/api/quarantine.js +3 -2
- package/dist/api/recall-types.d.ts +43 -55
- package/dist/api/recall.d.ts +3 -3
- package/dist/api/recall.js +310 -456
- package/dist/api/remember.d.ts +2 -2
- package/dist/api/sleep.d.ts +7 -35
- package/dist/api/sleep.js +206 -220
- package/dist/api/tokens.d.ts +2 -2
- package/dist/api/tokens.js +2 -2
- package/dist/api/types.d.ts +6 -10
- package/dist/api/types.js +2 -4
- package/dist/audit-prune.d.ts +4 -6
- package/dist/audit-prune.js +3 -5
- package/dist/audit.js +11 -33
- package/dist/auth.d.ts +8 -9
- package/dist/auth.js +5 -7
- package/dist/autolearn.d.ts +1 -1
- package/dist/autolearn.js +1 -1
- package/dist/availability.js +3 -5
- package/dist/capture/command.d.ts +5 -4
- package/dist/capture/command.js +8 -22
- package/dist/capture/compact.d.ts +2 -2
- package/dist/capture/compact.js +11 -15
- package/dist/capture/extract.js +37 -115
- package/dist/capture-error.d.ts +1 -1
- package/dist/capture-error.js +1 -1
- package/dist/churn-git.d.ts +1 -1
- package/dist/churn-git.js +1 -1
- package/dist/cli/audit.js +3 -4
- package/dist/cli/auth.js +3 -6
- package/dist/cli/briefs.js +324 -306
- package/dist/cli/context.js +44 -34
- package/dist/cli/continuity.js +283 -271
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +43 -58
- package/dist/cli/dag.js +5 -9
- package/dist/cli/decisions.js +334 -345
- package/dist/cli/explain.js +68 -61
- package/dist/cli/goals.js +1 -1
- package/dist/cli/init.js +1 -1
- package/dist/cli/maintenance.js +62 -51
- package/dist/cli/playbooks.js +391 -379
- package/dist/cli/projects.js +11 -6
- package/dist/cli/recall.js +30 -44
- package/dist/cli/remember.js +118 -87
- package/dist/cli/session-hooks.js +106 -115
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +267 -250
- package/dist/cli/shared.js +3 -3
- package/dist/cli/slack.js +1 -1
- package/dist/cli/sleep.js +27 -1
- package/dist/cli/status.d.ts +4 -4
- package/dist/cli/status.js +80 -76
- package/dist/cli/transfer.js +88 -107
- package/dist/cli/usage.js +9 -6
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +4 -9
- package/dist/compaction-record.d.ts +2 -2
- package/dist/compaction-record.js +89 -68
- package/dist/compare.d.ts +11 -16
- package/dist/compare.js +11 -16
- package/dist/config.d.ts +19 -18
- package/dist/config.js +90 -67
- package/dist/connectors/github/backfill.d.ts +2 -2
- package/dist/connectors/github/backfill.js +8 -15
- package/dist/connectors/github/cli-impl.js +3 -8
- package/dist/connectors/github/deletion.d.ts +5 -12
- package/dist/connectors/github/deletion.js +5 -12
- package/dist/connectors/github/dlq.d.ts +6 -9
- package/dist/connectors/github/dlq.js +2 -3
- package/dist/connectors/github/ingest.d.ts +5 -7
- package/dist/connectors/github/ingest.js +8 -12
- package/dist/connectors/github/octokit-client.d.ts +3 -5
- package/dist/connectors/github/octokit-client.js +5 -6
- package/dist/connectors/github/signature.d.ts +9 -39
- package/dist/connectors/github/signature.js +9 -39
- package/dist/connectors/github/tenant-routing.d.ts +1 -1
- package/dist/connectors/github/tenant-routing.js +1 -1
- package/dist/connectors/github/transform.js +2 -2
- package/dist/connectors/github/types.d.ts +2 -10
- package/dist/connectors/github/types.js +1 -3
- package/dist/connectors/slack/deletion.d.ts +3 -8
- package/dist/connectors/slack/deletion.js +3 -8
- package/dist/connectors/slack/dlq.d.ts +1 -1
- package/dist/connectors/slack/ingest.d.ts +1 -1
- package/dist/connectors/slack/ingest.js +7 -16
- package/dist/connectors/slack/signature.d.ts +1 -1
- package/dist/connectors/slack/tenant-routing.d.ts +3 -5
- package/dist/connectors/slack/tenant-routing.js +3 -5
- package/dist/connectors/slack/transform.d.ts +5 -6
- package/dist/connectors/slack/transform.js +5 -6
- package/dist/connectors/slack/types.d.ts +2 -6
- package/dist/connectors/slack/types.js +1 -3
- package/dist/connectors/slack/web-client.js +10 -3
- package/dist/connectors/slack/workspaces.d.ts +3 -5
- package/dist/connectors/slack/workspaces.js +3 -5
- package/dist/consolidate/conflicts.js +3 -14
- package/dist/consolidate/decay.js +9 -29
- package/dist/consolidate/llm-passes.js +4 -5
- package/dist/consolidate/merge.js +8 -23
- package/dist/consolidate/run.d.ts +1 -8
- package/dist/consolidate/run.js +3 -25
- package/dist/consolidate/sleep.js +5 -17
- package/dist/consolidate/traces.js +9 -21
- package/dist/customer-notes.d.ts +5 -7
- package/dist/customer-notes.js +82 -76
- package/dist/dag.d.ts +10 -21
- package/dist/dag.js +189 -203
- package/dist/db/continuity.js +2 -2
- package/dist/db/migrations/v14.js +1 -1
- package/dist/db/migrations/v15.js +1 -2
- package/dist/db/migrations/v16.js +3 -4
- package/dist/db/migrations/v17.js +2 -3
- package/dist/db/migrations/v19.js +1 -1
- package/dist/db/migrations/v20.js +1 -1
- package/dist/db/migrations/v21.js +2 -6
- package/dist/db/migrations/v22.js +2 -4
- package/dist/db/migrations/v23.js +1 -1
- package/dist/db/migrations/v24.js +4 -6
- package/dist/db/migrations/v25.js +2 -3
- package/dist/db/migrations/v26.js +3 -3
- package/dist/db/migrations/v27.js +2 -10
- package/dist/db/migrations/v28.js +5 -8
- package/dist/db/migrations/v29.js +3 -4
- package/dist/db/migrations/v30.js +2 -2
- package/dist/db/migrations/v31.js +1 -1
- package/dist/db/migrations/v32.js +1 -1
- package/dist/db/migrations/v33.js +3 -3
- package/dist/db/migrations/v34.js +1 -1
- package/dist/db/migrations/v35.js +3 -4
- package/dist/db/migrations/v36.js +3 -4
- package/dist/db/migrations/v37.js +5 -5
- package/dist/db/migrations/v38.js +7 -8
- package/dist/db/migrations/v39.js +1 -1
- package/dist/db/migrations/v40.js +4 -16
- package/dist/db/migrations/v41.js +3 -4
- package/dist/db/migrations/v42.js +3 -4
- package/dist/db/migrations/v45.js +1 -1
- package/dist/db/migrations/v46.js +1 -1
- package/dist/db/migrations/v47.js +1 -1
- package/dist/db/migrations/v48.js +1 -1
- package/dist/decisions.d.ts +2 -2
- package/dist/decisions.js +97 -80
- package/dist/dedupe.js +86 -61
- package/dist/delivery-recorder.js +154 -135
- package/dist/doctor.js +129 -110
- package/dist/dormant.js +1 -4
- package/dist/embedding-provider.d.ts +4 -8
- package/dist/embedding-provider.js +4 -8
- package/dist/embeddings.js +55 -47
- package/dist/env.d.ts +1 -1
- package/dist/env.js +12 -12
- package/dist/escape.d.ts +5 -0
- package/dist/escape.js +10 -0
- package/dist/eval-stats.d.ts +1 -2
- package/dist/eval-stats.js +1 -2
- package/dist/eval-suite.js +27 -21
- package/dist/extract.js +4 -9
- package/dist/failure-log.d.ts +3 -3
- package/dist/failure-log.js +1 -1
- package/dist/forward-claim-detector.d.ts +2 -4
- package/dist/forward-claim-detector.js +6 -11
- package/dist/goals.d.ts +3 -3
- package/dist/goals.js +103 -91
- package/dist/graph/read.d.ts +2 -2
- package/dist/graph/read.js +5 -6
- package/dist/graph/types.d.ts +8 -8
- package/dist/graph/write.d.ts +7 -14
- package/dist/graph/write.js +16 -23
- package/dist/graph-extract.d.ts +7 -8
- package/dist/graph-extract.js +62 -72
- package/dist/graph-recall.d.ts +2 -2
- package/dist/graph-recall.js +55 -49
- package/dist/graph-stream.d.ts +5 -6
- package/dist/graph-stream.js +66 -57
- package/dist/graph-view.d.ts +2 -2
- package/dist/graph-view.js +7 -7
- package/dist/half-life-migration.d.ts +1 -2
- package/dist/half-life-migration.js +2 -3
- package/dist/hooks/codex-session.js +1 -1
- package/dist/hooks/codex-wrapper.d.ts +1 -1
- package/dist/hooks/codex-wrapper.js +3 -2
- package/dist/hooks/json-hooks.d.ts +2 -2
- package/dist/hooks/json-hooks.js +5 -4
- package/dist/hooks/opencode.d.ts +1 -1
- package/dist/hooks/opencode.js +5 -4
- package/dist/hooks/shared.d.ts +3 -7
- package/dist/hooks/shared.js +1 -8
- package/dist/http-util.d.ts +2 -3
- package/dist/http-util.js +3 -0
- package/dist/importers/core.d.ts +2 -9
- package/dist/importers/core.js +15 -30
- package/dist/importers/sources.js +2 -1
- package/dist/importers/vault.js +2 -20
- package/dist/incidents.d.ts +1 -1
- package/dist/incidents.js +46 -39
- package/dist/instruction-detect.d.ts +1 -1
- package/dist/instruction-detect.js +1 -1
- package/dist/invalidation.d.ts +3 -0
- package/dist/invalidation.js +160 -114
- package/dist/json.d.ts +5 -0
- package/dist/json.js +4 -0
- package/dist/judgment.js +1 -2
- package/dist/local-embedding.js +1 -1
- package/dist/mcp/admin-tools.js +7 -17
- package/dist/mcp/format.js +1 -1
- package/dist/mcp/framing.js +3 -6
- package/dist/mcp/protocol.d.ts +2 -5
- package/dist/mcp/protocol.js +1 -3
- package/dist/mcp/recall-tools.js +12 -15
- package/dist/mcp/request.js +4 -3
- package/dist/mcp/session-state.js +2 -3
- package/dist/mcp/stdio.js +2 -1
- package/dist/mcp/tools.js +9 -6
- package/dist/memory-value-weights.d.ts +5 -8
- package/dist/memory-value-weights.js +5 -8
- package/dist/memory-value.d.ts +13 -13
- package/dist/memory-value.js +26 -37
- package/dist/memory.d.ts +20 -22
- package/dist/memory.js +24 -48
- package/dist/multihop.d.ts +1 -1
- package/dist/multihop.js +3 -2
- package/dist/owner-validation.d.ts +4 -5
- package/dist/owner-validation.js +4 -5
- package/dist/physics.d.ts +4 -4
- package/dist/physics.js +7 -9
- package/dist/policies.d.ts +9 -10
- package/dist/policies.js +96 -81
- package/dist/postinstall.js +3 -6
- package/dist/predictions/planning-fallacy.d.ts +9 -14
- package/dist/predictions/planning-fallacy.js +10 -16
- package/dist/predictions/store.d.ts +15 -23
- package/dist/predictions/store.js +36 -33
- package/dist/processes.d.ts +2 -7
- package/dist/processes.js +88 -72
- package/dist/project-briefs.d.ts +2 -3
- package/dist/project-briefs.js +141 -118
- package/dist/project-identity.d.ts +22 -9
- package/dist/project-identity.js +47 -12
- package/dist/project-merge.d.ts +28 -5
- package/dist/project-merge.js +213 -46
- package/dist/project-remote.d.ts +12 -0
- package/dist/project-remote.js +138 -0
- package/dist/prompt-recall.js +1 -2
- package/dist/rate-limit.d.ts +1 -1
- package/dist/rate-limit.js +1 -1
- package/dist/raw-archive.d.ts +9 -0
- package/dist/raw-archive.js +70 -53
- package/dist/recall-history.d.ts +19 -20
- package/dist/recall-history.js +24 -42
- package/dist/recall-pipeline.js +4 -28
- package/dist/recall-scope.d.ts +7 -8
- package/dist/recall-scope.js +7 -8
- package/dist/recall-trace.d.ts +5 -9
- package/dist/recall-trace.js +6 -10
- package/dist/refine-llm.d.ts +1 -1
- package/dist/refine-llm.js +2 -2
- package/dist/reject-flow.d.ts +3 -4
- package/dist/reject-flow.js +122 -117
- package/dist/rejection.d.ts +5 -6
- package/dist/rejection.js +7 -15
- package/dist/rerankers/clef.d.ts +1 -1
- package/dist/rerankers/jev.d.ts +1 -2
- package/dist/rerankers/jev.js +4 -5
- package/dist/rerankers/llm.d.ts +1 -2
- package/dist/rerankers/llm.js +1 -2
- package/dist/rerankers/types.d.ts +1 -2
- package/dist/rrf.d.ts +2 -2
- package/dist/rrf.js +2 -2
- package/dist/search/bm25-search.d.ts +1 -1
- package/dist/search/bm25-search.js +2 -1
- package/dist/search/boosts.js +2 -1
- package/dist/search/hybrid.d.ts +1 -1
- package/dist/search/hybrid.js +2 -1
- package/dist/search/physics-search.d.ts +1 -1
- package/dist/search/physics-search.js +2 -1
- package/dist/search/types.d.ts +2 -0
- package/dist/search/types.js +3 -1
- package/dist/secret-detect.d.ts +4 -5
- package/dist/secret-detect.js +6 -10
- package/dist/server/auth.js +5 -5
- package/dist/server/client-ip.js +1 -1
- package/dist/server/cursor.js +2 -1
- package/dist/server/mcp-http.js +4 -4
- package/dist/server/request.d.ts +3 -6
- package/dist/server/request.js +6 -7
- package/dist/server/routes/admin.js +5 -4
- package/dist/server/routes/customer-notes.js +6 -5
- package/dist/server/routes/decisions.js +4 -3
- package/dist/server/routes/incidents.js +7 -5
- package/dist/server/routes/memories.js +7 -7
- package/dist/server/routes/policies.js +3 -2
- package/dist/server/routes/predictions.js +12 -15
- package/dist/server/routes/processes.js +3 -2
- package/dist/server/routes/project-briefs.js +8 -7
- package/dist/server/routes/recall.js +95 -93
- package/dist/server/routes/skills.js +6 -5
- package/dist/server/types.d.ts +1 -1
- package/dist/server/validation.d.ts +1 -2
- package/dist/server/validation.js +7 -14
- package/dist/server-detect.js +72 -58
- package/dist/server.d.ts +2 -2
- package/dist/server.js +131 -117
- package/dist/shared.d.ts +26 -17
- package/dist/shared.js +102 -104
- package/dist/skills.d.ts +3 -3
- package/dist/skills.js +88 -72
- package/dist/store/audit-event.d.ts +2 -2
- package/dist/store/audit-event.js +1 -1
- package/dist/store/candidates.d.ts +2 -2
- package/dist/store/candidates.js +4 -3
- package/dist/store/conflicts.js +30 -22
- package/dist/store/delete-and-batch.d.ts +11 -14
- package/dist/store/delete-and-batch.js +40 -91
- package/dist/store/entry-reads.d.ts +17 -25
- package/dist/store/entry-reads.js +59 -40
- package/dist/store/entry-row.d.ts +6 -24
- package/dist/store/entry-row.js +6 -24
- package/dist/store/entry-writes.d.ts +6 -7
- package/dist/store/entry-writes.js +13 -11
- package/dist/store/handoffs.d.ts +1 -1
- package/dist/store/handoffs.js +7 -10
- package/dist/store/index-and-stats.d.ts +2 -6
- package/dist/store/index-and-stats.js +4 -10
- package/dist/store/mirrors.d.ts +6 -19
- package/dist/store/mirrors.js +14 -39
- package/dist/store/open.js +9 -31
- package/dist/store/rows.d.ts +5 -11
- package/dist/store/rows.js +6 -11
- package/dist/store/search-rows.d.ts +17 -34
- package/dist/store/search-rows.js +34 -56
- package/dist/store/sessions.d.ts +4 -5
- package/dist/store/sessions.js +5 -6
- package/dist/store/summaries.d.ts +13 -17
- package/dist/store/summaries.js +26 -70
- package/dist/support-bundle.js +4 -8
- package/dist/tenant.d.ts +1 -5
- package/dist/token-ledger.d.ts +1 -1
- package/dist/token-ledger.js +3 -5
- package/dist/trace.js +1 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/working-memory.d.ts +1 -1
- 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/api/remember.d.ts
CHANGED
|
@@ -10,14 +10,14 @@ export interface RememberOpts {
|
|
|
10
10
|
tags?: string[];
|
|
11
11
|
/**
|
|
12
12
|
* Optional hook invoked inside the same transaction as the underlying
|
|
13
|
-
* memories INSERT. Used by ingestion connectors
|
|
13
|
+
* memories INSERT. Used by ingestion connectors to stamp
|
|
14
14
|
* idempotency / cursor rows atomically with the memory row, so a crash
|
|
15
15
|
* mid-write cannot produce a memory without its corresponding side-effect
|
|
16
16
|
* log row (or vice versa). If the callback throws, the INSERT is rolled
|
|
17
17
|
* back and the error is rethrown.
|
|
18
18
|
*/
|
|
19
19
|
afterWrite?: (db: DatabaseSyncLike, memoryId: string) => void;
|
|
20
|
-
/**
|
|
20
|
+
/** Connector-ingested content an agent doesn't control; gates detectInstruction. CLI/HTTP/MCP never set this. */
|
|
21
21
|
untrusted?: boolean;
|
|
22
22
|
}
|
|
23
23
|
export interface RememberResult {
|
package/dist/api/sleep.d.ts
CHANGED
|
@@ -64,22 +64,21 @@ export interface SleepResult {
|
|
|
64
64
|
};
|
|
65
65
|
shared?: number;
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
67
|
+
* Count of memories the auto-share secret veto withheld this sleep
|
|
68
68
|
* — rows that passed every other admission gate (transfer score,
|
|
69
69
|
* not-already-global) and were blocked solely by `detectSecret`. Absent
|
|
70
70
|
* when 0 or when auto-share did not run.
|
|
71
71
|
*/
|
|
72
72
|
secretSkipped?: number;
|
|
73
73
|
/**
|
|
74
|
-
*
|
|
75
|
-
* tombstone refused this sleep
|
|
76
|
-
*
|
|
77
|
-
* batch). Absent when 0 or when auto-share did not run.
|
|
74
|
+
* Count of auto-share candidates the GLOBAL store's rejection
|
|
75
|
+
* tombstone refused this sleep; copy paths must not let one rejected
|
|
76
|
+
* candidate abort the batch. Absent when 0 or when auto-share did not run.
|
|
78
77
|
*/
|
|
79
78
|
rejectedSkipped?: number;
|
|
80
79
|
ambient?: AmbientState | null;
|
|
81
80
|
/**
|
|
82
|
-
*
|
|
81
|
+
* Graph re-extraction totals across the tenants rebuilt
|
|
83
82
|
* this sleep. Absent when no tenant was dirty, and under dryRun (the graph
|
|
84
83
|
* phase runs only on a real sleep). Cross-tenant aggregate, one reason
|
|
85
84
|
* /v1/sleep stays loopback-only.
|
|
@@ -91,35 +90,7 @@ export interface SleepResult {
|
|
|
91
90
|
};
|
|
92
91
|
details?: string[];
|
|
93
92
|
}
|
|
94
|
-
/**
|
|
95
|
-
* Run the pure-storage consolidation pipeline.
|
|
96
|
-
*
|
|
97
|
-
* Tenant scope note: sleep operates on the WHOLE hippoRoot (all tenants in
|
|
98
|
-
* it), matching the pre-refactor cmdSleepCore behavior. Correct for a CLI
|
|
99
|
-
* maintenance op invoked by the operator. Episode B (v1.11.4) exposed this
|
|
100
|
-
* over HTTP `/v1/sleep` with loopback-only enforcement (per-request guard
|
|
101
|
-
* in the handler plus serve()'s boot-time host check). The TODOS.md
|
|
102
|
-
* per-tenant scoping follow-up remains open for the day non-loopback
|
|
103
|
-
* serving lands — at that point the route will need an admin-role gate OR
|
|
104
|
-
* api.sleep itself will need to scope dedup / audit / delete by ctx.tenantId.
|
|
105
|
-
*
|
|
106
|
-
* Dedup and audit deletes each log a `forget` row with the ctx actor and a
|
|
107
|
-
* `metadata.reason`. Pinned, raw, kept and object-backing rows are never auto-deleted (AUTOMATIC_DELETE_SQL).
|
|
108
|
-
* dryRun previews consolidate, dedup and audit, then returns before share/ambient.
|
|
109
|
-
*/
|
|
110
|
-
/**
|
|
111
|
-
* v1.12.2: Test-only DI seam shape for `sleep`'s phase dependencies.
|
|
112
|
-
*
|
|
113
|
-
* Each field defaults to the real production implementation imported at the
|
|
114
|
-
* top of this file. Test files pass a `Partial<SleepPhases>` override via
|
|
115
|
-
* `SleepOpts.__phases` (note the `__` prefix — internal-only) to inject
|
|
116
|
-
* deterministic throws for mid-phase failure-path coverage (the
|
|
117
|
-
* `partial: true` + `errorMessage` audit-row branch at line ~2098).
|
|
118
|
-
*
|
|
119
|
-
* Production callers MUST NOT use `__phases`. The field exists solely so
|
|
120
|
-
* `tests/api-sleep-phase-faults.test.ts` can force each phase boundary to
|
|
121
|
-
* throw without depending on store-corruption fragility.
|
|
122
|
-
*/
|
|
93
|
+
/** Test-only seam: `SleepOpts.__phases` forces a phase to throw into emitSleepAudit's `partial: true` row; production never sets it. */
|
|
123
94
|
export interface SleepPhases {
|
|
124
95
|
consolidate: typeof consolidate;
|
|
125
96
|
deduplicateStore: typeof deduplicateStore;
|
|
@@ -132,5 +103,6 @@ export interface SleepPhases {
|
|
|
132
103
|
loadPendingExtractionTenants: typeof loadPendingExtractionTenants;
|
|
133
104
|
extractGraph: typeof extractGraph;
|
|
134
105
|
}
|
|
106
|
+
/** Sleeps the WHOLE hippoRoot, every tenant, so /v1/sleep stays loopback-only; never auto-deletes pinned, raw, kept or object-backing rows. */
|
|
135
107
|
export declare function sleep(ctx: Context, opts?: SleepOpts): Promise<SleepResult>;
|
|
136
108
|
//# sourceMappingURL=sleep.d.ts.map
|
package/dist/api/sleep.js
CHANGED
|
@@ -23,192 +23,19 @@ const DEFAULT_SLEEP_PHASES = {
|
|
|
23
23
|
loadPendingExtractionTenants,
|
|
24
24
|
extractGraph,
|
|
25
25
|
};
|
|
26
|
+
/** Sleeps the WHOLE hippoRoot, every tenant, so /v1/sleep stays loopback-only; never auto-deletes pinned, raw, kept or object-backing rows. */
|
|
26
27
|
export async function sleep(ctx, opts = {}) {
|
|
27
28
|
const dryRun = Boolean(opts.dryRun);
|
|
28
|
-
//
|
|
29
|
+
// Resolve phase dependencies, allowing test-only `__phases`
|
|
29
30
|
// override to inject deterministic throws for mid-phase failure coverage.
|
|
30
31
|
const phases = { ...DEFAULT_SLEEP_PHASES, ...(opts.__phases ?? {}) };
|
|
31
|
-
//
|
|
32
|
+
// Phase counters for the consolidate audit emit (in finally).
|
|
32
33
|
// Accumulated as each phase completes so partial-failure paths still report
|
|
33
34
|
// accurate "what got done before the failure" data.
|
|
34
|
-
|
|
35
|
-
let dedupCount = 0;
|
|
36
|
-
let auditDeletedCount = 0;
|
|
37
|
-
let ambientTotal = 0;
|
|
35
|
+
const counts = { consolidation: 0, dedup: 0, auditDeleted: 0, ambient: 0 };
|
|
38
36
|
let phaseError = null;
|
|
39
|
-
let graphSnapshotError = null;
|
|
40
|
-
let result = null;
|
|
41
37
|
try {
|
|
42
|
-
|
|
43
|
-
// dedup / audit). The graph_extraction_queue rows are FK'd to mirror
|
|
44
|
-
// memories with ON DELETE CASCADE, so a phase that deletes a queued mirror
|
|
45
|
-
// (e.g. dedup removing a near-duplicate superseding decision) would drop the
|
|
46
|
-
// tenant from a drain-time load and leave its graph stale (codex P1). The
|
|
47
|
-
// MAX(id) watermark captured here stays valid: arrivals during sleep get a
|
|
48
|
-
// higher id and remain pending.
|
|
49
|
-
//
|
|
50
|
-
// Fail-soft (codex P2): a queue-read failure here must NOT abort core sleep
|
|
51
|
-
// (consolidation / dedup / audit run regardless). On failure, skip graph
|
|
52
|
-
// refresh this sleep (recovered next sleep) and surface a detail once
|
|
53
|
-
// `result` exists (Phase 6).
|
|
54
|
-
let dirtyTenants = [];
|
|
55
|
-
if (!dryRun) {
|
|
56
|
-
try {
|
|
57
|
-
dirtyTenants = phases.loadPendingExtractionTenants(ctx.hippoRoot);
|
|
58
|
-
}
|
|
59
|
-
catch (snapErr) {
|
|
60
|
-
// SAFETY: this is a best-effort log message only; property access on
|
|
61
|
-
// any JS value is safe (undefined if absent), preserving the existing
|
|
62
|
-
// lenient formatting even when something non-Error was thrown.
|
|
63
|
-
graphSnapshotError = snapErr.message;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// Phase 1: Consolidation.
|
|
67
|
-
const consolidateResult = await phases.consolidate(ctx.hippoRoot, { dryRun });
|
|
68
|
-
consolidationCount = consolidateResult.semanticCreated + consolidateResult.merged;
|
|
69
|
-
result = {
|
|
70
|
-
active: consolidateResult.decayed,
|
|
71
|
-
removed: consolidateResult.removed,
|
|
72
|
-
mergedEpisodic: consolidateResult.merged,
|
|
73
|
-
newSemantic: consolidateResult.semanticCreated,
|
|
74
|
-
dryRun,
|
|
75
|
-
details: consolidateResult.details,
|
|
76
|
-
};
|
|
77
|
-
// Set only when non-zero, so a store without dormant memories gets a
|
|
78
|
-
// byte-identical result (HTTP /v1/sleep, the CLI render snapshot).
|
|
79
|
-
if (consolidateResult.dormant > 0) {
|
|
80
|
-
result.dormant = consolidateResult.dormant;
|
|
81
|
-
}
|
|
82
|
-
if (consolidateResult.dormantExpired > 0) {
|
|
83
|
-
result.dormantExpired = consolidateResult.dormantExpired;
|
|
84
|
-
}
|
|
85
|
-
// Phase 2: Dedup (post-consolidate near-duplicate cleanup).
|
|
86
|
-
const dedupResult = phases.deduplicateStore(ctx.hippoRoot, { dryRun, actor: ctx.actor.subject });
|
|
87
|
-
dedupCount = dedupResult.removed;
|
|
88
|
-
if (dedupResult.removed > 0) {
|
|
89
|
-
const semDups = dedupResult.pairs.filter((p) => p.keptLayer === 'semantic' && p.removedLayer === 'semantic').length;
|
|
90
|
-
const epiDups = dedupResult.pairs.filter((p) => p.keptLayer === 'episodic' && p.removedLayer === 'episodic').length;
|
|
91
|
-
const crossDups = dedupResult.pairs.filter((p) => p.keptLayer !== p.removedLayer).length;
|
|
92
|
-
result.deduped = {
|
|
93
|
-
removed: dedupResult.removed,
|
|
94
|
-
semDups,
|
|
95
|
-
epiDups,
|
|
96
|
-
crossDups,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
// Phase 3: Quality audit (remove junk, report warnings; a dry run skips rows earlier phases would remove).
|
|
100
|
-
const planned = new Set(dryRun ? [...(consolidateResult.removedIds ?? []), ...dedupResult.pairs.map((p) => p.removed)] : []);
|
|
101
|
-
const allEntries = phases.loadAllEntries(ctx.hippoRoot).filter((e) => !planned.has(e.id));
|
|
102
|
-
const auditOut = phases.auditMemories(allEntries, memoriesBackingObjects(ctx.hippoRoot));
|
|
103
|
-
if (auditOut.issues.length > 0) {
|
|
104
|
-
const errors = auditOut.issues.filter((i) => i.severity === 'error');
|
|
105
|
-
const warnings = auditOut.issues.filter((i) => i.severity === 'warning');
|
|
106
|
-
let removed = 0;
|
|
107
|
-
for (const issue of errors) {
|
|
108
|
-
const reason = `sleep-audit: ${issue.reason}`;
|
|
109
|
-
if (dryRun || phases.deleteEntry(ctx.hippoRoot, issue.memoryId, { actor: ctx.actor.subject, reason, automatic: true }))
|
|
110
|
-
removed++;
|
|
111
|
-
}
|
|
112
|
-
auditDeletedCount = removed;
|
|
113
|
-
if (removed > 0 || warnings.length > 0) {
|
|
114
|
-
result.audit = {
|
|
115
|
-
errorsRemoved: removed,
|
|
116
|
-
warningCount: warnings.length,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (dryRun)
|
|
121
|
-
return result;
|
|
122
|
-
// Phase 4: Auto-share high-transfer-score memories to global.
|
|
123
|
-
if (!opts.noShare) {
|
|
124
|
-
const sleepConfig = phases.loadConfig(ctx.hippoRoot);
|
|
125
|
-
if (sleepConfig.autoShareOnSleep) {
|
|
126
|
-
// v1.25.0: surface the secret-veto skip count (v39 follow-up #2) so
|
|
127
|
-
// the veto is observable instead of silent.
|
|
128
|
-
// AT1: rejectedSkipped is autoShare's sibling counter for candidates
|
|
129
|
-
// the global store's rejection tombstone refused (threaded the same
|
|
130
|
-
// way as secretSkipped just below).
|
|
131
|
-
const autoShareStats = { secretSkipped: 0, rejectedSkipped: 0 };
|
|
132
|
-
const shared = phases.autoShare(ctx.hippoRoot, { minScore: 0.6, stats: autoShareStats });
|
|
133
|
-
if (shared.length > 0) {
|
|
134
|
-
result.shared = shared.length;
|
|
135
|
-
}
|
|
136
|
-
if (autoShareStats.secretSkipped > 0) {
|
|
137
|
-
result.secretSkipped = autoShareStats.secretSkipped;
|
|
138
|
-
}
|
|
139
|
-
if (autoShareStats.rejectedSkipped > 0) {
|
|
140
|
-
result.rejectedSkipped = autoShareStats.rejectedSkipped;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
// Phase 5: Post-sleep ambient state summary.
|
|
145
|
-
const postSleepConfig = phases.loadConfig(ctx.hippoRoot);
|
|
146
|
-
if (postSleepConfig.ambient.enabled) {
|
|
147
|
-
const postSleepEntries = phases.loadAllEntries(ctx.hippoRoot).filter((e) => !e.superseded_by);
|
|
148
|
-
if (postSleepEntries.length > 0) {
|
|
149
|
-
result.ambient = phases.computeAmbientState(postSleepEntries);
|
|
150
|
-
ambientTotal = result.ambient.totalMemories;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Phase 6: Graph extraction drain (E3 sleep enqueue-hook). Rebuild the
|
|
154
|
-
// entity/relation graph for every tenant marked dirty (by markGraphDirty)
|
|
155
|
-
// since the last sleep, so `recall --hops` + cross-object `references` edges
|
|
156
|
-
// run on fresh data without a manual `hippo graph extract`. Fully
|
|
157
|
-
// fault-isolated: the consolidation work above has already committed, so a
|
|
158
|
-
// failure here must never abort sleep; a per-tenant extract failure leaves
|
|
159
|
-
// that tenant's queue items pending for the next sleep. (Skipped under
|
|
160
|
-
// dryRun via the early return above.)
|
|
161
|
-
try {
|
|
162
|
-
if (graphSnapshotError) {
|
|
163
|
-
// The dirty-tenant snapshot failed (codex P2 fail-soft). Core sleep
|
|
164
|
-
// already succeeded; surface the skipped graph refresh as a detail.
|
|
165
|
-
result.details = [
|
|
166
|
-
...(result.details ?? []),
|
|
167
|
-
`graph: dirty-tenant snapshot failed (skipped graph refresh): ${graphSnapshotError}`,
|
|
168
|
-
];
|
|
169
|
-
}
|
|
170
|
-
let gTenants = 0;
|
|
171
|
-
let gEntities = 0;
|
|
172
|
-
let gRelations = 0;
|
|
173
|
-
// dirtyTenants was snapshotted before the memory-deleting phases above.
|
|
174
|
-
for (const { tenantId, maxPendingId } of dirtyTenants) {
|
|
175
|
-
try {
|
|
176
|
-
const ext = phases.extractGraph(ctx.hippoRoot, tenantId);
|
|
177
|
-
// Count the rebuild as soon as it succeeds — it happened regardless of
|
|
178
|
-
// the drain-mark below.
|
|
179
|
-
gTenants += 1;
|
|
180
|
-
gEntities += ext.entities;
|
|
181
|
-
gRelations += ext.relations;
|
|
182
|
-
// Watermark drain: mark processed only items enqueued before this
|
|
183
|
-
// rebuild started (id <= maxPendingId). Arrivals during the rebuild
|
|
184
|
-
// keep pending status and are caught next sleep; rows whose mirror was
|
|
185
|
-
// cascade-deleted earlier this sleep are already gone (no-op).
|
|
186
|
-
markPendingProcessedUpTo(ctx.hippoRoot, tenantId, maxPendingId);
|
|
187
|
-
}
|
|
188
|
-
catch (tenantErr) {
|
|
189
|
-
// SAFETY: this is a best-effort log message only; property access
|
|
190
|
-
// on any JS value is safe (undefined if absent), preserving the
|
|
191
|
-
// existing lenient formatting even when something non-Error was thrown.
|
|
192
|
-
result.details = [
|
|
193
|
-
...(result.details ?? []),
|
|
194
|
-
`graph: extract failed for a dirty tenant (left pending): ${tenantErr.message}`,
|
|
195
|
-
];
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
if (gTenants > 0) {
|
|
199
|
-
result.graph = { tenants: gTenants, entities: gEntities, relations: gRelations };
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
catch (graphErr) {
|
|
203
|
-
// SAFETY: this is a best-effort log message only; property access on
|
|
204
|
-
// any JS value is safe (undefined if absent), preserving the existing
|
|
205
|
-
// lenient formatting even when something non-Error was thrown.
|
|
206
|
-
result.details = [
|
|
207
|
-
...(result.details ?? []),
|
|
208
|
-
`graph: drain phase failed (skipped): ${graphErr.message}`,
|
|
209
|
-
];
|
|
210
|
-
}
|
|
211
|
-
return result;
|
|
38
|
+
return await runSleepPhases(ctx, opts, phases, counts);
|
|
212
39
|
}
|
|
213
40
|
catch (err) {
|
|
214
41
|
// SAFETY: phaseError is read via phaseError.message / (phaseError !==
|
|
@@ -218,54 +45,213 @@ export async function sleep(ctx, opts = {}) {
|
|
|
218
45
|
throw err;
|
|
219
46
|
}
|
|
220
47
|
finally {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
48
|
+
emitSleepAudit(ctx, opts, dryRun, counts, phaseError);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function runSleepPhases(ctx, opts, phases, counts) {
|
|
52
|
+
const dryRun = Boolean(opts.dryRun);
|
|
53
|
+
const snapshot = snapshotDirtyTenants(ctx, phases, dryRun);
|
|
54
|
+
// Phase 1: Consolidation.
|
|
55
|
+
const consolidateResult = await phases.consolidate(ctx.hippoRoot, { dryRun });
|
|
56
|
+
counts.consolidation = consolidateResult.semanticCreated + consolidateResult.merged;
|
|
57
|
+
const result = sleepResultFrom(consolidateResult, dryRun);
|
|
58
|
+
// Phase 2: Dedup (post-consolidate near-duplicate cleanup).
|
|
59
|
+
const dedupResult = phases.deduplicateStore(ctx.hippoRoot, { dryRun, actor: ctx.actor.subject });
|
|
60
|
+
counts.dedup = dedupResult.removed;
|
|
61
|
+
if (dedupResult.removed > 0)
|
|
62
|
+
result.deduped = dedupSummary(dedupResult);
|
|
63
|
+
// Phase 3: Quality audit (remove junk, report warnings; a dry run skips rows earlier phases would remove).
|
|
64
|
+
counts.auditDeleted = runQualityAudit(ctx, phases, dryRun, consolidateResult, dedupResult, result);
|
|
65
|
+
if (dryRun)
|
|
66
|
+
return result;
|
|
67
|
+
// Phase 4: Auto-share high-transfer-score memories to global.
|
|
68
|
+
if (!opts.noShare)
|
|
69
|
+
shareOnSleep(ctx, phases, result);
|
|
70
|
+
// Phase 5: Post-sleep ambient state summary.
|
|
71
|
+
counts.ambient = summarizeAmbient(ctx, phases, result);
|
|
72
|
+
drainGraphQueue(ctx, phases, snapshot, result);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
// Taken before any memory-deleting phase: queue rows cascade-delete with their mirror, so a later read would miss
|
|
76
|
+
// tenants dedup touched. Fail-soft: a failed read skips the graph refresh this sleep and never aborts core sleep.
|
|
77
|
+
function snapshotDirtyTenants(ctx, phases, dryRun) {
|
|
78
|
+
const snapshot = { dirtyTenants: [], error: null };
|
|
79
|
+
if (!dryRun) {
|
|
239
80
|
try {
|
|
240
|
-
|
|
81
|
+
snapshot.dirtyTenants = phases.loadPendingExtractionTenants(ctx.hippoRoot);
|
|
82
|
+
}
|
|
83
|
+
catch (snapErr) {
|
|
84
|
+
// SAFETY: this is a best-effort log message only; property access on
|
|
85
|
+
// any JS value is safe (undefined if absent), preserving the existing
|
|
86
|
+
// lenient formatting even when something non-Error was thrown.
|
|
87
|
+
snapshot.error = snapErr.message;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return snapshot;
|
|
91
|
+
}
|
|
92
|
+
function sleepResultFrom(consolidateResult, dryRun) {
|
|
93
|
+
const result = {
|
|
94
|
+
active: consolidateResult.decayed,
|
|
95
|
+
removed: consolidateResult.removed,
|
|
96
|
+
mergedEpisodic: consolidateResult.merged,
|
|
97
|
+
newSemantic: consolidateResult.semanticCreated,
|
|
98
|
+
dryRun,
|
|
99
|
+
details: consolidateResult.details,
|
|
100
|
+
};
|
|
101
|
+
// Set only when non-zero, so a store without dormant memories gets a
|
|
102
|
+
// byte-identical result (HTTP /v1/sleep, the CLI render snapshot).
|
|
103
|
+
if (consolidateResult.dormant > 0) {
|
|
104
|
+
result.dormant = consolidateResult.dormant;
|
|
105
|
+
}
|
|
106
|
+
if (consolidateResult.dormantExpired > 0) {
|
|
107
|
+
result.dormantExpired = consolidateResult.dormantExpired;
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
function dedupSummary(dedupResult) {
|
|
112
|
+
const semDups = dedupResult.pairs.filter((p) => p.keptLayer === 'semantic' && p.removedLayer === 'semantic').length;
|
|
113
|
+
const epiDups = dedupResult.pairs.filter((p) => p.keptLayer === 'episodic' && p.removedLayer === 'episodic').length;
|
|
114
|
+
const crossDups = dedupResult.pairs.filter((p) => p.keptLayer !== p.removedLayer).length;
|
|
115
|
+
return {
|
|
116
|
+
removed: dedupResult.removed,
|
|
117
|
+
semDups,
|
|
118
|
+
epiDups,
|
|
119
|
+
crossDups,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** Returns how many audit errors were deleted, or would be under dryRun. */
|
|
123
|
+
function runQualityAudit(ctx, phases, dryRun, consolidateResult, dedupResult, result) {
|
|
124
|
+
const planned = new Set(dryRun ? [...(consolidateResult.removedIds ?? []), ...dedupResult.pairs.map((p) => p.removed)] : []);
|
|
125
|
+
const allEntries = phases.loadAllEntries(ctx.hippoRoot).filter((e) => !planned.has(e.id));
|
|
126
|
+
const auditOut = phases.auditMemories(allEntries, memoriesBackingObjects(ctx.hippoRoot));
|
|
127
|
+
if (auditOut.issues.length === 0)
|
|
128
|
+
return 0;
|
|
129
|
+
const errors = auditOut.issues.filter((i) => i.severity === 'error');
|
|
130
|
+
const warnings = auditOut.issues.filter((i) => i.severity === 'warning');
|
|
131
|
+
let removed = 0;
|
|
132
|
+
for (const issue of errors) {
|
|
133
|
+
const reason = `sleep-audit: ${issue.reason}`;
|
|
134
|
+
if (dryRun || phases.deleteEntry(ctx.hippoRoot, issue.memoryId, { actor: ctx.actor.subject, reason, automatic: true }))
|
|
135
|
+
removed++;
|
|
136
|
+
}
|
|
137
|
+
if (removed > 0 || warnings.length > 0) {
|
|
138
|
+
result.audit = {
|
|
139
|
+
errorsRemoved: removed,
|
|
140
|
+
warningCount: warnings.length,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return removed;
|
|
144
|
+
}
|
|
145
|
+
function shareOnSleep(ctx, phases, result) {
|
|
146
|
+
const sleepConfig = phases.loadConfig(ctx.hippoRoot);
|
|
147
|
+
if (!sleepConfig.autoShareOnSleep)
|
|
148
|
+
return;
|
|
149
|
+
// Both skip counters are surfaced so the secret veto and the rejection tombstone are observable, not silent.
|
|
150
|
+
const autoShareStats = { secretSkipped: 0, rejectedSkipped: 0 };
|
|
151
|
+
const shared = phases.autoShare(ctx.hippoRoot, { minScore: 0.6, stats: autoShareStats });
|
|
152
|
+
if (shared.length > 0) {
|
|
153
|
+
result.shared = shared.length;
|
|
154
|
+
}
|
|
155
|
+
if (autoShareStats.secretSkipped > 0) {
|
|
156
|
+
result.secretSkipped = autoShareStats.secretSkipped;
|
|
157
|
+
}
|
|
158
|
+
if (autoShareStats.rejectedSkipped > 0) {
|
|
159
|
+
result.rejectedSkipped = autoShareStats.rejectedSkipped;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** Returns the ambient total the audit row reports: 0 when ambient is off or no current row is left. */
|
|
163
|
+
function summarizeAmbient(ctx, phases, result) {
|
|
164
|
+
const postSleepConfig = phases.loadConfig(ctx.hippoRoot);
|
|
165
|
+
if (!postSleepConfig.ambient.enabled)
|
|
166
|
+
return 0;
|
|
167
|
+
const postSleepEntries = phases.loadAllEntries(ctx.hippoRoot).filter((e) => !e.superseded_by);
|
|
168
|
+
if (postSleepEntries.length === 0)
|
|
169
|
+
return 0;
|
|
170
|
+
result.ambient = phases.computeAmbientState(postSleepEntries);
|
|
171
|
+
return result.ambient.totalMemories;
|
|
172
|
+
}
|
|
173
|
+
// Phase 6: rebuild the graph of every tenant marked dirty since the last sleep, so graph recall runs on fresh data.
|
|
174
|
+
// Fault-isolated: consolidation has already committed, so no failure here aborts sleep; a failed tenant stays pending.
|
|
175
|
+
function drainGraphQueue(ctx, phases, snapshot, result) {
|
|
176
|
+
try {
|
|
177
|
+
if (snapshot.error) {
|
|
178
|
+
// Core sleep already succeeded; surface the skipped graph refresh as a detail.
|
|
179
|
+
result.details = [
|
|
180
|
+
...(result.details ?? []),
|
|
181
|
+
`graph: dirty-tenant snapshot failed (skipped graph refresh): ${snapshot.error}`,
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
let gTenants = 0;
|
|
185
|
+
let gEntities = 0;
|
|
186
|
+
let gRelations = 0;
|
|
187
|
+
// dirtyTenants was snapshotted before the memory-deleting phases above.
|
|
188
|
+
for (const { tenantId, maxPendingId } of snapshot.dirtyTenants) {
|
|
241
189
|
try {
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
triggeredByTenant: ctx.tenantId, // preserve for audit forensics
|
|
251
|
-
};
|
|
252
|
-
if (phaseError)
|
|
253
|
-
sleepAuditMetadata.errorMessage = phaseError.message;
|
|
254
|
-
appendAuditEvent(db, {
|
|
255
|
-
tenantId: '__host__',
|
|
256
|
-
actor: ctx.actor.subject,
|
|
257
|
-
op: 'consolidate',
|
|
258
|
-
metadata: { ...sleepAuditMetadata },
|
|
259
|
-
});
|
|
190
|
+
const ext = phases.extractGraph(ctx.hippoRoot, tenantId);
|
|
191
|
+
// Count the rebuild as soon as it succeeds — it happened regardless of
|
|
192
|
+
// the drain-mark below.
|
|
193
|
+
gTenants += 1;
|
|
194
|
+
gEntities += ext.entities;
|
|
195
|
+
gRelations += ext.relations;
|
|
196
|
+
// Watermark drain: only items enqueued before this rebuild started are marked; later arrivals stay pending.
|
|
197
|
+
markPendingProcessedUpTo(ctx.hippoRoot, tenantId, maxPendingId);
|
|
260
198
|
}
|
|
261
|
-
|
|
262
|
-
|
|
199
|
+
catch (tenantErr) {
|
|
200
|
+
// SAFETY: this is a best-effort log message only; property access
|
|
201
|
+
// on any JS value is safe (undefined if absent), preserving the
|
|
202
|
+
// existing lenient formatting even when something non-Error was thrown.
|
|
203
|
+
result.details = [
|
|
204
|
+
...(result.details ?? []),
|
|
205
|
+
`graph: extract failed for a dirty tenant (left pending): ${tenantErr.message}`,
|
|
206
|
+
];
|
|
263
207
|
}
|
|
264
208
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
reportAuditWriteFailure('consolidate', String(auditErr));
|
|
209
|
+
if (gTenants > 0) {
|
|
210
|
+
result.graph = { tenants: gTenants, entities: gEntities, relations: gRelations };
|
|
268
211
|
}
|
|
269
212
|
}
|
|
213
|
+
catch (graphErr) {
|
|
214
|
+
// SAFETY: this is a best-effort log message only; property access on
|
|
215
|
+
// any JS value is safe (undefined if absent), preserving the existing
|
|
216
|
+
// lenient formatting even when something non-Error was thrown.
|
|
217
|
+
result.details = [
|
|
218
|
+
...(result.details ?? []),
|
|
219
|
+
`graph: drain phase failed (skipped): ${graphErr.message}`,
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// One 'consolidate' row per sleep, emitted from finally so a partial failure still reports what got done.
|
|
224
|
+
// Its own handle; an audit failure is logged and never replaces the original phase error.
|
|
225
|
+
function emitSleepAudit(ctx, opts, dryRun, counts, phaseError) {
|
|
226
|
+
try {
|
|
227
|
+
const db = openHippoDb(ctx.hippoRoot);
|
|
228
|
+
try {
|
|
229
|
+
const sleepAuditMetadata = {
|
|
230
|
+
consolidationCount: counts.consolidation,
|
|
231
|
+
dedupCount: counts.dedup,
|
|
232
|
+
auditDeletedCount: counts.auditDeleted,
|
|
233
|
+
ambientTotal: counts.ambient,
|
|
234
|
+
dryRun,
|
|
235
|
+
noShare: opts.noShare ?? false,
|
|
236
|
+
partial: phaseError !== null,
|
|
237
|
+
triggeredByTenant: ctx.tenantId, // preserve for audit forensics
|
|
238
|
+
};
|
|
239
|
+
if (phaseError)
|
|
240
|
+
sleepAuditMetadata.errorMessage = phaseError.message;
|
|
241
|
+
appendAuditEvent(db, {
|
|
242
|
+
tenantId: '__host__',
|
|
243
|
+
actor: ctx.actor.subject,
|
|
244
|
+
op: 'consolidate',
|
|
245
|
+
metadata: { ...sleepAuditMetadata },
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
closeHippoDb(db);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
catch (auditErr) {
|
|
253
|
+
// Logged, never thrown: a second failure must not mask the original phaseError.
|
|
254
|
+
reportAuditWriteFailure('consolidate', String(auditErr));
|
|
255
|
+
}
|
|
270
256
|
}
|
|
271
257
|
//# sourceMappingURL=sleep.js.map
|
package/dist/api/tokens.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { type TokenSummary, type TokenSurface } from '../token-ledger.js';
|
|
|
2
2
|
import { type FailureSummary } from '../failure-log.js';
|
|
3
3
|
import type { Context } from './types.js';
|
|
4
4
|
/**
|
|
5
|
-
* Record memory text handed to an agent in the token ledger
|
|
5
|
+
* Record memory text handed to an agent in the token ledger.
|
|
6
6
|
* Best-effort: never throws, because a ledger failure must not fail the
|
|
7
7
|
* recall or context call that produced the text.
|
|
8
8
|
*/
|
|
@@ -19,7 +19,7 @@ export declare function recordTokens(ctx: Context, surface: TokenSurface, use: {
|
|
|
19
19
|
export declare function tokenSummary(ctx: Context, opts?: {
|
|
20
20
|
days?: number;
|
|
21
21
|
}): TokenSummary;
|
|
22
|
-
/** Failed tool calls by outcome, and repeats across sessions, over the last `days` days (default 30)
|
|
22
|
+
/** Failed tool calls by outcome, and repeats across sessions, over the last `days` days (default 30). */
|
|
23
23
|
export declare function failureSummary(ctx: Context, opts?: {
|
|
24
24
|
days?: number;
|
|
25
25
|
}): FailureSummary;
|
package/dist/api/tokens.js
CHANGED
|
@@ -4,7 +4,7 @@ import { recordTokenUse, summarizeTokenUse } from '../token-ledger.js';
|
|
|
4
4
|
import { summarizeFailures } from '../failure-log.js';
|
|
5
5
|
import { log } from '../log.js';
|
|
6
6
|
/**
|
|
7
|
-
* Record memory text handed to an agent in the token ledger
|
|
7
|
+
* Record memory text handed to an agent in the token ledger.
|
|
8
8
|
* Best-effort: never throws, because a ledger failure must not fail the
|
|
9
9
|
* recall or context call that produced the text.
|
|
10
10
|
*/
|
|
@@ -43,7 +43,7 @@ export function tokenSummary(ctx, opts = {}) {
|
|
|
43
43
|
closeHippoDb(db);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
/** Failed tool calls by outcome, and repeats across sessions, over the last `days` days (default 30)
|
|
46
|
+
/** Failed tool calls by outcome, and repeats across sessions, over the last `days` days (default 30). */
|
|
47
47
|
export function failureSummary(ctx, opts = {}) {
|
|
48
48
|
const db = openHippoDb(ctx.hippoRoot);
|
|
49
49
|
try {
|
package/dist/api/types.d.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { BadRequestError } from '../api-errors.js';
|
|
2
2
|
/**
|
|
3
|
-
* Actor identity + authorization role for a Context.
|
|
3
|
+
* Actor identity + authorization role for a Context.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* a role for /v1/sleep admin gating. Audit helpers continue accepting `string`
|
|
8
|
-
* — callers pass `ctx.actor.subject`. Role checks happen at the request
|
|
5
|
+
* Carries the audit-log subject plus a role for /v1/sleep admin gating. Audit
|
|
6
|
+
* helpers take the bare `string`, so callers pass `ctx.actor.subject`. Role checks happen at the request
|
|
9
7
|
* boundary (e.g. /v1/sleep), except in authCreate and authRevoke (ForbiddenError).
|
|
10
8
|
*/
|
|
11
9
|
export interface Actor {
|
|
12
10
|
/** 'cli' | 'localhost:cli' | 'api_key:<key_id>' | 'mcp' | 'connector:slack' | 'connector:github' */
|
|
13
11
|
subject: string;
|
|
14
12
|
role: 'admin' | 'member';
|
|
15
|
-
/**
|
|
13
|
+
/** Restricted scopes a member key may read (auth.ts grantScope). Unused for admin actors. */
|
|
16
14
|
scopes?: readonly string[];
|
|
17
15
|
/** An auth resolver vouched for this caller, so its admin role stops at its own tenant. */
|
|
18
16
|
viaAuthResolver?: true;
|
|
@@ -44,10 +42,8 @@ export declare function adminActor(subject: string): Actor;
|
|
|
44
42
|
* is opt-in so multi-session tenants can fail loud instead of silently
|
|
45
43
|
* surfacing cross-session rows tagged `isFreshTail=true`.
|
|
46
44
|
* - 'invalid_scorer_window' — `opts.scorerWindow` is set to a non-positive,
|
|
47
|
-
* non-integer, or non-finite value.
|
|
48
|
-
*
|
|
49
|
-
* full-store fallback (codex v1.7.0 diff-pass P1). Validated upfront
|
|
50
|
-
* so the contract holds.
|
|
45
|
+
* non-integer, or non-finite value. 0 would route through FTS/LIKE
|
|
46
|
+
* `LIMIT 0` and then an uncapped full-store fallback, so it is validated upfront.
|
|
51
47
|
*/
|
|
52
48
|
export declare class RecallContractError extends BadRequestError {
|
|
53
49
|
readonly code: 'fresh_tail_requires_session_id' | 'invalid_scorer_window';
|
package/dist/api/types.js
CHANGED
|
@@ -22,10 +22,8 @@ export function adminActor(subject) {
|
|
|
22
22
|
* is opt-in so multi-session tenants can fail loud instead of silently
|
|
23
23
|
* surfacing cross-session rows tagged `isFreshTail=true`.
|
|
24
24
|
* - 'invalid_scorer_window' — `opts.scorerWindow` is set to a non-positive,
|
|
25
|
-
* non-integer, or non-finite value.
|
|
26
|
-
*
|
|
27
|
-
* full-store fallback (codex v1.7.0 diff-pass P1). Validated upfront
|
|
28
|
-
* so the contract holds.
|
|
25
|
+
* non-integer, or non-finite value. 0 would route through FTS/LIKE
|
|
26
|
+
* `LIMIT 0` and then an uncapped full-store fallback, so it is validated upfront.
|
|
29
27
|
*/
|
|
30
28
|
export class RecallContractError extends BadRequestError {
|
|
31
29
|
code;
|