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/ambient-store.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { type AmbientTallies } from './ambient.js';
|
|
|
2
2
|
/** The rows an ambient summary describes: a context read's envelope, origin partition and tag secret veto. */
|
|
3
3
|
export interface AmbientStoreFilter {
|
|
4
4
|
exactScope?: string;
|
|
5
|
-
/** Rows of
|
|
6
|
-
project?: string;
|
|
7
|
-
/** The reader's project: a secret-tagged row counts only inside its own non-empty origin project. */
|
|
8
|
-
currentProject: string;
|
|
5
|
+
/** Rows carrying one of these project names, and user-global rows, pass; absent admits every origin. */
|
|
6
|
+
project?: readonly string[];
|
|
7
|
+
/** The reader's project names: a secret-tagged row counts only inside its own non-empty origin project. */
|
|
8
|
+
currentProject: readonly string[];
|
|
9
9
|
now: Date;
|
|
10
10
|
}
|
|
11
11
|
/** Whole-store ambient tallies in one aggregate pass, no row loaded. Content-pattern secrets and session-local
|
package/dist/ambient-store.js
CHANGED
|
@@ -3,6 +3,7 @@ import { strengthSql } from './memory.js';
|
|
|
3
3
|
import { RECALL_DEFAULT_DENY_SCOPES } from './recall-scope.js';
|
|
4
4
|
import { SECRET_TAGS } from './secret-detect.js';
|
|
5
5
|
import { openStore } from './store/open.js';
|
|
6
|
+
import { originInSql } from './project-identity.js';
|
|
6
7
|
import { isErrorTagged } from './ambient.js';
|
|
7
8
|
// A malformed or non-array JSON list reads as empty, as parseJsonArray does, instead of failing json_each.
|
|
8
9
|
const jsonList = (column) => `(CASE WHEN json_valid(${column}) AND json_type(${column}) = 'array' THEN ${column} ELSE '[]' END)`;
|
|
@@ -19,8 +20,8 @@ function contextRowsWhere(tenantId, filter) {
|
|
|
19
20
|
params.push(...RECALL_DEFAULT_DENY_SCOPES);
|
|
20
21
|
}
|
|
21
22
|
if (filter.project !== undefined) {
|
|
22
|
-
where.push(`(origin_project = '' OR
|
|
23
|
-
params.push(filter.project);
|
|
23
|
+
where.push(`(origin_project = '' OR ${originInSql(filter.project)})`);
|
|
24
|
+
params.push(...filter.project);
|
|
24
25
|
}
|
|
25
26
|
return { where, params };
|
|
26
27
|
}
|
|
@@ -57,7 +58,7 @@ export function loadAmbientTallies(hippoRoot, tenantId, filter) {
|
|
|
57
58
|
'[' || COALESCE(group_concat(${jsonList('tags_json')}, ','), '') || ']' AS tagLists
|
|
58
59
|
FROM memories
|
|
59
60
|
WHERE ${where.join(' AND ')}
|
|
60
|
-
AND ((
|
|
61
|
+
AND ((${originInSql(filter.currentProject)} AND origin_project != '') OR NOT ${secret.sql})`).get(sevenDaysAgo, ...params, ...filter.currentProject, ...secret.params);
|
|
61
62
|
const tagCounts = new Map();
|
|
62
63
|
let errors = 0;
|
|
63
64
|
const lists = /* SAFETY: jsonList yields an array per row, joined into one array */ JSON.parse(row.tagLists);
|
package/dist/api/assemble.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Context } from './types.js';
|
|
2
|
+
export declare const DEFAULT_ASSEMBLE_BUDGET = 4000;
|
|
2
3
|
export interface AssembleOpts {
|
|
3
|
-
/** Token budget. Default
|
|
4
|
+
/** Token budget. Default DEFAULT_ASSEMBLE_BUDGET. */
|
|
4
5
|
budget?: number;
|
|
5
6
|
/** Recent raw rows always kept verbatim. Default 10. */
|
|
6
7
|
freshTailCount?: number;
|
|
@@ -8,7 +9,7 @@ export interface AssembleOpts {
|
|
|
8
9
|
* ancestor. Default true. */
|
|
9
10
|
summarizeOlder?: boolean;
|
|
10
11
|
/**
|
|
11
|
-
* Restrict to a specific scope
|
|
12
|
+
* Restrict to a specific scope, same rule as
|
|
12
13
|
* `recall`: when set, exact match required (so an authorised caller can
|
|
13
14
|
* assemble a `slack:private:CSEC` session by passing scope explicitly).
|
|
14
15
|
* When undefined, default-deny applies to ANY `<source>:private:*` and
|
|
@@ -49,19 +50,15 @@ export interface AssembleResult {
|
|
|
49
50
|
items: AssembledContextItem[];
|
|
50
51
|
tokens: number;
|
|
51
52
|
/**
|
|
52
|
-
* Tenant + scope-filtered raw row count for the session
|
|
53
|
-
*
|
|
54
|
-
* for all-private sessions); pre-v1.6.3 was capped (under-reported on
|
|
55
|
-
* sessions > rowCap). v1.6.3 reports the FULL post-filter count via a
|
|
56
|
-
* separate COUNT(*) query so consumers can render "session has N msgs"
|
|
57
|
-
* accurately even when items[] is the windowed view.
|
|
53
|
+
* Tenant + scope-filtered raw row count for the session, uncapped by `rowCap`, so
|
|
54
|
+
* "session has N msgs" stays accurate when items[] is the windowed view.
|
|
58
55
|
*/
|
|
59
56
|
totalRaw: number;
|
|
60
57
|
summarized: number;
|
|
61
58
|
evicted: number;
|
|
62
59
|
/**
|
|
63
|
-
* True when `rowCap` truncated the loaded window.
|
|
64
|
-
*
|
|
60
|
+
* True when `rowCap` truncated the loaded window. The cap keeps the NEWEST
|
|
61
|
+
* rows, so the items[] array represents the freshest tail of the session;
|
|
65
62
|
* older rows beyond the cap are silently absent. Use `totalRaw - items.length
|
|
66
63
|
* - summarized + ...` to estimate how much you didn't see, or widen `rowCap`.
|
|
67
64
|
*/
|
package/dist/api/assemble.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { loadEntriesByIds, loadSessionRawMemories, countSessionRawMemories } from '../store/entry-reads.js';
|
|
3
3
|
import { estimateTokens } from '../token-ledger.js';
|
|
4
4
|
import { passesScopeFilterForRecall, assertScopeRequestAllowed } from '../recall-scope.js';
|
|
5
|
+
export const DEFAULT_ASSEMBLE_BUDGET = 4000;
|
|
5
6
|
/**
|
|
6
7
|
* Build a chronologically-ordered context window for a session. Adapts the
|
|
7
8
|
* lossless-claw context-engine pattern to Hippo's score-ranked memory store.
|
|
@@ -26,7 +27,7 @@ import { passesScopeFilterForRecall, assertScopeRequestAllowed } from '../recall
|
|
|
26
27
|
*/
|
|
27
28
|
export function assemble(ctx, sessionId, opts = {}) {
|
|
28
29
|
assertScopeRequestAllowed(ctx.actor, opts.scope);
|
|
29
|
-
const budget = opts.budget ??
|
|
30
|
+
const budget = opts.budget ?? DEFAULT_ASSEMBLE_BUDGET;
|
|
30
31
|
const freshTailCount = opts.freshTailCount ?? 10;
|
|
31
32
|
const summarizeOlder = opts.summarizeOlder ?? true;
|
|
32
33
|
const rowCap = opts.rowCap ?? 5000;
|
|
@@ -35,17 +36,12 @@ export function assemble(ctx, sessionId, opts = {}) {
|
|
|
35
36
|
}
|
|
36
37
|
const rows = loadSessionRawMemories(ctx.hippoRoot, sessionId, ctx.tenantId, rowCap);
|
|
37
38
|
const truncated = rows.length === rowCap;
|
|
38
|
-
//
|
|
39
|
-
// when the cap windows the loaded set. Pre-v1.6.3 used `scoped.length`
|
|
40
|
-
// which under-reported on long sessions and made consumers render
|
|
41
|
-
// wrong "session has N msgs" UX.
|
|
39
|
+
// `scoped.length` under-counts a capped session, so totalRaw falls back to a COUNT below.
|
|
42
40
|
const scoped = rows.filter((r) => passesScopeFilterForRecall(r.scope ?? null, opts.scope));
|
|
43
41
|
let totalRaw;
|
|
44
42
|
if (truncated) {
|
|
45
|
-
//
|
|
46
|
-
//
|
|
47
|
-
// applies in TS, so a no-scope caller cannot infer private rows by
|
|
48
|
-
// comparing totalRaw to items.length on a truncated session.
|
|
43
|
+
// The COUNT applies the same default-deny scope rule in SQL, so a no-scope
|
|
44
|
+
// caller cannot infer private rows by comparing totalRaw to items.length.
|
|
49
45
|
totalRaw = countSessionRawMemories(ctx.hippoRoot, sessionId, ctx.tenantId, opts.scope);
|
|
50
46
|
}
|
|
51
47
|
else {
|
|
@@ -59,58 +55,9 @@ export function assemble(ctx, sessionId, opts = {}) {
|
|
|
59
55
|
const olderRows = scoped.slice(0, tailStartIdx);
|
|
60
56
|
const tailRows = scoped.slice(tailStartIdx);
|
|
61
57
|
// Substitute parent summaries for older rows that share one.
|
|
62
|
-
const olderItems =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const olderByParent = new Map();
|
|
66
|
-
for (const r of olderRows) {
|
|
67
|
-
if (!r.dag_parent_id)
|
|
68
|
-
continue;
|
|
69
|
-
const list = olderByParent.get(r.dag_parent_id) ?? [];
|
|
70
|
-
list.push(r);
|
|
71
|
-
olderByParent.set(r.dag_parent_id, list);
|
|
72
|
-
}
|
|
73
|
-
const eligibleParentIds = Array.from(olderByParent.keys()).filter((pid) => (olderByParent.get(pid)?.length ?? 0) >= 2);
|
|
74
|
-
const parents = eligibleParentIds.length > 0
|
|
75
|
-
? loadEntriesByIds(ctx.hippoRoot, eligibleParentIds, ctx.tenantId)
|
|
76
|
-
.filter((p) => (p.dag_level ?? 0) === 2 && !p.superseded_by)
|
|
77
|
-
.filter((p) => passesScopeFilterForRecall(p.scope ?? null, opts.scope))
|
|
78
|
-
: [];
|
|
79
|
-
const claimedRawIds = new Set();
|
|
80
|
-
for (const parent of parents) {
|
|
81
|
-
const claimed = (olderByParent.get(parent.id) ?? []).map((r) => r.id);
|
|
82
|
-
claimed.forEach((id) => claimedRawIds.add(id));
|
|
83
|
-
olderItems.push({
|
|
84
|
-
id: parent.id,
|
|
85
|
-
content: parent.content,
|
|
86
|
-
createdAt: parent.earliest_at ?? parent.created,
|
|
87
|
-
isSummary: true,
|
|
88
|
-
substitutedFor: claimed,
|
|
89
|
-
strength: parent.strength,
|
|
90
|
-
});
|
|
91
|
-
summarized += claimed.length;
|
|
92
|
-
}
|
|
93
|
-
for (const r of olderRows) {
|
|
94
|
-
if (claimedRawIds.has(r.id))
|
|
95
|
-
continue;
|
|
96
|
-
olderItems.push({
|
|
97
|
-
id: r.id,
|
|
98
|
-
content: r.content,
|
|
99
|
-
createdAt: r.created,
|
|
100
|
-
strength: r.strength,
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
for (const r of olderRows) {
|
|
106
|
-
olderItems.push({
|
|
107
|
-
id: r.id,
|
|
108
|
-
content: r.content,
|
|
109
|
-
createdAt: r.created,
|
|
110
|
-
strength: r.strength,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
58
|
+
const { olderItems, summarized } = summarizeOlder && olderRows.length > 0
|
|
59
|
+
? substituteSummaries(ctx, olderRows, opts.scope)
|
|
60
|
+
: { olderItems: olderRows.map(rawItem), summarized: 0 };
|
|
114
61
|
const tailItems = tailRows.map((r) => ({
|
|
115
62
|
id: r.id,
|
|
116
63
|
content: r.content,
|
|
@@ -118,15 +65,64 @@ export function assemble(ctx, sessionId, opts = {}) {
|
|
|
118
65
|
isFreshTail: true,
|
|
119
66
|
strength: r.strength,
|
|
120
67
|
}));
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
// documented in src/memory.ts above MemoryEntry.
|
|
68
|
+
// Byte compare is chronological for the fixed-form UTC ISO timestamps
|
|
69
|
+
// (invariant documented in src/memory.ts above MemoryEntry).
|
|
124
70
|
const cmpIso = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
125
71
|
olderItems.sort((a, b) => cmpIso(a.createdAt, b.createdAt));
|
|
126
72
|
tailItems.sort((a, b) => cmpIso(a.createdAt, b.createdAt));
|
|
127
|
-
let items = [...olderItems, ...tailItems];
|
|
128
73
|
const itemCost = opts.cost?.item ?? ((it) => estimateTokens(it.content));
|
|
129
74
|
const room = budget - (opts.cost?.fixed(Math.max(budget, totalRaw)) ?? 0);
|
|
75
|
+
const { items, tokens, evicted } = evictToBudget([...olderItems, ...tailItems], itemCost, room);
|
|
76
|
+
return { sessionId, items, tokens, totalRaw, summarized, evicted, truncated };
|
|
77
|
+
}
|
|
78
|
+
function rawItem(r) {
|
|
79
|
+
return {
|
|
80
|
+
id: r.id,
|
|
81
|
+
content: r.content,
|
|
82
|
+
createdAt: r.created,
|
|
83
|
+
strength: r.strength,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function substituteSummaries(ctx, olderRows, scope) {
|
|
87
|
+
const olderItems = [];
|
|
88
|
+
let summarized = 0;
|
|
89
|
+
const olderByParent = new Map();
|
|
90
|
+
for (const r of olderRows) {
|
|
91
|
+
if (!r.dag_parent_id)
|
|
92
|
+
continue;
|
|
93
|
+
const list = olderByParent.get(r.dag_parent_id) ?? [];
|
|
94
|
+
list.push(r);
|
|
95
|
+
olderByParent.set(r.dag_parent_id, list);
|
|
96
|
+
}
|
|
97
|
+
const eligibleParentIds = Array.from(olderByParent.keys()).filter((pid) => (olderByParent.get(pid)?.length ?? 0) >= 2);
|
|
98
|
+
const parents = eligibleParentIds.length > 0
|
|
99
|
+
? loadEntriesByIds(ctx.hippoRoot, eligibleParentIds, ctx.tenantId)
|
|
100
|
+
.filter((p) => (p.dag_level ?? 0) === 2 && !p.superseded_by)
|
|
101
|
+
.filter((p) => passesScopeFilterForRecall(p.scope ?? null, scope))
|
|
102
|
+
: [];
|
|
103
|
+
const claimedRawIds = new Set();
|
|
104
|
+
for (const parent of parents) {
|
|
105
|
+
const claimed = (olderByParent.get(parent.id) ?? []).map((r) => r.id);
|
|
106
|
+
claimed.forEach((id) => claimedRawIds.add(id));
|
|
107
|
+
olderItems.push({
|
|
108
|
+
id: parent.id,
|
|
109
|
+
content: parent.content,
|
|
110
|
+
createdAt: parent.earliest_at ?? parent.created,
|
|
111
|
+
isSummary: true,
|
|
112
|
+
substitutedFor: claimed,
|
|
113
|
+
strength: parent.strength,
|
|
114
|
+
});
|
|
115
|
+
summarized += claimed.length;
|
|
116
|
+
}
|
|
117
|
+
for (const r of olderRows) {
|
|
118
|
+
if (claimedRawIds.has(r.id))
|
|
119
|
+
continue;
|
|
120
|
+
olderItems.push(rawItem(r));
|
|
121
|
+
}
|
|
122
|
+
return { olderItems, summarized };
|
|
123
|
+
}
|
|
124
|
+
function evictToBudget(start, itemCost, room) {
|
|
125
|
+
let items = start;
|
|
130
126
|
let tokens = items.reduce((acc, it) => acc + itemCost(it), 0);
|
|
131
127
|
let evicted = 0;
|
|
132
128
|
while (tokens > room && items.length > 0) {
|
|
@@ -147,6 +143,6 @@ export function assemble(ctx, sessionId, opts = {}) {
|
|
|
147
143
|
tokens -= cost;
|
|
148
144
|
evicted++;
|
|
149
145
|
}
|
|
150
|
-
return {
|
|
146
|
+
return { items, tokens, evicted };
|
|
151
147
|
}
|
|
152
148
|
//# sourceMappingURL=assemble.js.map
|
package/dist/api/audit.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export interface AuditListOpts {
|
|
|
10
10
|
after?: KeysetPosition;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* Read audit events scoped to `ctx.tenantId`. Read-only
|
|
14
|
-
*
|
|
13
|
+
* Read audit events scoped to `ctx.tenantId`. Read-only, no audit emit (matches
|
|
14
|
+
* cmdAuditList, which does not record a 'recall'-style read event).
|
|
15
15
|
*/
|
|
16
16
|
export declare function auditList(ctx: Context, opts: AuditListOpts): AuditEvent[];
|
|
17
17
|
//# sourceMappingURL=audit.d.ts.map
|
package/dist/api/audit.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { openHippoDb, closeHippoDb } from '../db.js';
|
|
3
3
|
import { queryAuditEvents } from '../audit.js';
|
|
4
4
|
/**
|
|
5
|
-
* Read audit events scoped to `ctx.tenantId`. Read-only
|
|
6
|
-
*
|
|
5
|
+
* Read audit events scoped to `ctx.tenantId`. Read-only, no audit emit (matches
|
|
6
|
+
* cmdAuditList, which does not record a 'recall'-style read event).
|
|
7
7
|
*/
|
|
8
8
|
export function auditList(ctx, opts) {
|
|
9
9
|
const db = openHippoDb(ctx.hippoRoot);
|
package/dist/api/auth.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type { Context } from './types.js';
|
|
|
4
4
|
export interface AuthCreateOpts {
|
|
5
5
|
label?: string;
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
* back-compat with
|
|
7
|
+
* Authorization role for the new key. Defaults to `'admin'` for
|
|
8
|
+
* back-compat with keys minted before roles existed (the api_keys.role column DEFAULT also
|
|
9
9
|
* resolves to 'admin' if omitted from the INSERT). Member keys are
|
|
10
10
|
* 403-blocked from admin-gated routes (e.g. `POST /v1/sleep`).
|
|
11
11
|
*/
|
|
@@ -15,7 +15,7 @@ export interface AuthCreateResult {
|
|
|
15
15
|
keyId: string;
|
|
16
16
|
plaintext: string;
|
|
17
17
|
tenantId: string;
|
|
18
|
-
/**
|
|
18
|
+
/** The role bound to the new key (admin | member). */
|
|
19
19
|
role: 'admin' | 'member';
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
@@ -36,7 +36,7 @@ export declare function authCreate(ctx: Context, opts: AuthCreateOpts): AuthCrea
|
|
|
36
36
|
* Divergence from `cmdAuthList` in src/cli.ts: the CLI today returns ALL keys
|
|
37
37
|
* regardless of tenant (single-tenant deployments). The API surface is tenant-
|
|
38
38
|
* scoped because future multi-tenant deployments will share a hippoRoot, and
|
|
39
|
-
* tenant A must not see tenant B's keys. Read-only
|
|
39
|
+
* tenant A must not see tenant B's keys. Read-only, so no audit emit.
|
|
40
40
|
*/
|
|
41
41
|
export declare function authList(ctx: Context, opts: {
|
|
42
42
|
active: boolean;
|
|
@@ -55,7 +55,7 @@ export declare function authListRows(ctx: Context, opts: {
|
|
|
55
55
|
* revoke only its own key (checked first), so no caller can probe other key_ids.
|
|
56
56
|
*
|
|
57
57
|
* Audit: emits 'auth_revoke' with `tenantId` set to the KEY ROW's tenant_id
|
|
58
|
-
* (
|
|
58
|
+
* (mirrors src/cli.ts:cmdAuthRevoke). Skipped on no-op
|
|
59
59
|
* revoke (already revoked) so re-running doesn't pad the audit log.
|
|
60
60
|
*/
|
|
61
61
|
export interface AuthRevokeResult {
|
|
@@ -72,7 +72,7 @@ export declare function authKeyTenant(ctx: Context, keyId: string): string | und
|
|
|
72
72
|
export interface AuthGrantResult {
|
|
73
73
|
ok: true;
|
|
74
74
|
}
|
|
75
|
-
/** Grant `keyId` read access to one restricted `scope
|
|
75
|
+
/** Grant `keyId` read access to one restricted `scope`. Admin only. */
|
|
76
76
|
export declare function authGrant(ctx: Context, keyId: string, scope: string): AuthGrantResult;
|
|
77
77
|
/** Revoke `keyId`'s grant on `scope`. Same authorization and lookup rules as authGrant. */
|
|
78
78
|
export declare function authUngrant(ctx: Context, keyId: string, scope: string): AuthGrantResult;
|
package/dist/api/auth.js
CHANGED
|
@@ -27,10 +27,8 @@ export function authCreate(ctx, opts) {
|
|
|
27
27
|
try {
|
|
28
28
|
const role = opts.role ?? (ctx.actor.viaAuthResolver ? 'member' : 'admin');
|
|
29
29
|
const result = createApiKey(db, { tenantId: ctx.tenantId, label: opts.label, role });
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
// failure can't crash a successful mint. The plaintext is NEVER logged;
|
|
33
|
-
// metadata carries label + role + the keyId (which is non-secret).
|
|
30
|
+
// Same try/catch as authRevoke so audit failure can't crash a successful mint.
|
|
31
|
+
// The plaintext is NEVER logged; metadata carries label + role, keyId is non-secret.
|
|
34
32
|
try {
|
|
35
33
|
appendAuditEvent(db, {
|
|
36
34
|
tenantId: ctx.tenantId,
|
|
@@ -59,7 +57,7 @@ export function authCreate(ctx, opts) {
|
|
|
59
57
|
* Divergence from `cmdAuthList` in src/cli.ts: the CLI today returns ALL keys
|
|
60
58
|
* regardless of tenant (single-tenant deployments). The API surface is tenant-
|
|
61
59
|
* scoped because future multi-tenant deployments will share a hippoRoot, and
|
|
62
|
-
* tenant A must not see tenant B's keys. Read-only
|
|
60
|
+
* tenant A must not see tenant B's keys. Read-only, so no audit emit.
|
|
63
61
|
*/
|
|
64
62
|
export function authList(ctx, opts) {
|
|
65
63
|
return authListRows(ctx, opts).map((r) => r.key);
|
|
@@ -101,7 +99,7 @@ export function authRevoke(ctx, keyId) {
|
|
|
101
99
|
if (!alreadyRevoked) {
|
|
102
100
|
try {
|
|
103
101
|
appendAuditEvent(db, {
|
|
104
|
-
tenantId: row.tenantId, //
|
|
102
|
+
tenantId: row.tenantId, // KEY's tenant, not ctx.tenantId.
|
|
105
103
|
actor: ctx.actor.subject,
|
|
106
104
|
op: 'auth_revoke',
|
|
107
105
|
targetId: keyId,
|
|
@@ -134,7 +132,7 @@ export function authKeyTenant(ctx, keyId) {
|
|
|
134
132
|
closeHippoDb(db);
|
|
135
133
|
}
|
|
136
134
|
}
|
|
137
|
-
/** Grant `keyId` read access to one restricted `scope
|
|
135
|
+
/** Grant `keyId` read access to one restricted `scope`. Admin only. */
|
|
138
136
|
export function authGrant(ctx, keyId, scope) {
|
|
139
137
|
return changeScopeGrant(ctx, keyId, scope, 'auth_grant');
|
|
140
138
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { AmbientLoadResult } from '../store/candidates.js';
|
|
2
|
+
import { type MemoryEntry } from '../memory.js';
|
|
3
|
+
import { type HippoConfig } from '../config.js';
|
|
4
|
+
import type { ProjectRef } from '../project-identity.js';
|
|
5
|
+
import type { DeliveryObserver } from '../delivery-recorder.js';
|
|
6
|
+
import type { ContextCost, ContextOpts, ContextResultEntry } from './context-types.js';
|
|
7
|
+
import type { Context } from './types.js';
|
|
8
|
+
/** What getContext resolved from opts and config before it read a row. */
|
|
9
|
+
export interface ContextPlan {
|
|
10
|
+
pinnedOnly: boolean;
|
|
11
|
+
limit: number;
|
|
12
|
+
includeRecent: number;
|
|
13
|
+
activeScope: string;
|
|
14
|
+
exactScope: string | undefined;
|
|
15
|
+
query: string;
|
|
16
|
+
hasLocal: boolean;
|
|
17
|
+
hasGlobal: boolean;
|
|
18
|
+
globalRoot: string;
|
|
19
|
+
primaryIsGlobal: boolean;
|
|
20
|
+
hasLocalTaskState: boolean;
|
|
21
|
+
config: HippoConfig;
|
|
22
|
+
currentProject: ProjectRef;
|
|
23
|
+
includeCrossProject: boolean;
|
|
24
|
+
originProject: readonly string[] | undefined;
|
|
25
|
+
promptRecallPending: boolean;
|
|
26
|
+
cost: ContextCost | undefined;
|
|
27
|
+
price: (entry: MemoryEntry, isGlobal: boolean, promptRecall?: boolean) => number;
|
|
28
|
+
obs: DeliveryObserver | undefined;
|
|
29
|
+
}
|
|
30
|
+
/** The ambient admit rules; `digestHidden` is read late because a prompt-recall eligibility check can still set it. */
|
|
31
|
+
export interface ContextAdmission {
|
|
32
|
+
ambientAdmit: (e: MemoryEntry) => boolean;
|
|
33
|
+
admit: (e: MemoryEntry) => boolean;
|
|
34
|
+
/** What the two-store search admits: `admit` without the own-session compaction rule. */
|
|
35
|
+
bothStoresAdmit: (e: MemoryEntry) => boolean;
|
|
36
|
+
digestHidden: () => boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface ContextPools {
|
|
39
|
+
local: AmbientLoadResult;
|
|
40
|
+
global: AmbientLoadResult;
|
|
41
|
+
}
|
|
42
|
+
export declare function oneCopyPerMemory(local: readonly MemoryEntry[], global: readonly MemoryEntry[], now: Date): [MemoryEntry[], MemoryEntry[]];
|
|
43
|
+
export declare const finiteOr: (v: number, dflt: number, min: number) => number;
|
|
44
|
+
/** Pins plus the prompt-recall or recent-N backfill; null means the block is empty. */
|
|
45
|
+
export declare function selectPinned(opts: ContextOpts, plan: ContextPlan, left: number, pools: ContextPools, admission: ContextAdmission): ContextResultEntry[] | null;
|
|
46
|
+
/** No query: the strongest memories by strength, up to budget. */
|
|
47
|
+
export declare function selectStrongest(plan: ContextPlan, left: number, pools: ContextPools): ContextResultEntry[];
|
|
48
|
+
/** Real query: hybrid search over both stores, or physics/hybrid over the local rows; emits the 'recall' audit row. */
|
|
49
|
+
export declare function selectBySearch(ctx: Context, plan: ContextPlan, left: number, pools: ContextPools, admission: ContextAdmission): Promise<ContextResultEntry[]>;
|
|
50
|
+
//# sourceMappingURL=context-select.d.ts.map
|