hippo-memory 1.72.0 → 2.0.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 +6 -4
- package/dist/agent-memories/apply.js +5 -5
- package/dist/api/assemble.js +2 -1
- package/dist/api/audit.d.ts +7 -7
- package/dist/api/audit.js +19 -17
- package/dist/api/auth.d.ts +5 -6
- package/dist/api/auth.js +28 -33
- package/dist/api/conflicts.js +1 -1
- package/dist/api/context-auto.js +4 -2
- package/dist/api/context-select.js +8 -20
- package/dist/api/context.js +12 -10
- package/dist/api/drill-down.js +2 -1
- package/dist/api/forget.d.ts +2 -2
- package/dist/api/forget.js +6 -7
- package/dist/api/graph.js +2 -1
- package/dist/api/learn.d.ts +1 -1
- package/dist/api/learn.js +45 -44
- package/dist/api/memories.d.ts +4 -2
- package/dist/api/memories.js +16 -5
- package/dist/api/objects.js +2 -1
- package/dist/api/outcome.d.ts +5 -5
- package/dist/api/outcome.js +16 -15
- package/dist/api/predictions.js +2 -1
- package/dist/api/promote.d.ts +3 -3
- package/dist/api/promote.js +25 -27
- package/dist/api/prompt-hook.d.ts +3 -1
- package/dist/api/prompt-hook.js +1 -0
- package/dist/api/quarantine.js +2 -1
- package/dist/api/recall-core.js +8 -3
- package/dist/api/recall-pipeline.js +17 -17
- package/dist/api/recall-types.d.ts +3 -1
- package/dist/api/recall.js +32 -29
- package/dist/api/remember-local.d.ts +5 -2
- package/dist/api/remember-local.js +14 -6
- package/dist/api/remember.d.ts +5 -2
- package/dist/api/remember.js +16 -14
- package/dist/api/session-end.d.ts +24 -0
- package/dist/api/session-end.js +31 -1
- package/dist/api/sleep-run.js +5 -4
- package/dist/api/sleep.js +4 -3
- package/dist/api/tokens.js +1 -1
- package/dist/api/types.d.ts +1 -7
- package/dist/capture/command.js +1 -1
- package/dist/capture/compaction-spool.d.ts +3 -5
- package/dist/capture/compaction-spool.js +41 -46
- package/dist/capture/session-end-caller.js +1 -1
- package/dist/capture/session-worker.js +19 -6
- package/dist/cli/audit.js +10 -10
- package/dist/cli/auth.js +4 -4
- package/dist/cli/client.d.ts +1 -2
- package/dist/cli/client.js +13 -13
- package/dist/cli/context.js +1 -1
- package/dist/cli/curate.d.ts +1 -1
- package/dist/cli/curate.js +9 -9
- package/dist/cli/decisions.js +4 -5
- package/dist/cli/hook-runtime.d.ts +3 -1
- package/dist/cli/hook-runtime.js +2 -2
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.js +9 -9
- package/dist/cli/object-verbs.d.ts +2 -2
- package/dist/cli/object-verbs.js +4 -4
- package/dist/cli/predictions.js +2 -3
- package/dist/cli/quality-repair-once.d.ts +1 -1
- package/dist/cli/quality-repair-once.js +2 -2
- package/dist/cli/refine-llm.js +2 -1
- package/dist/cli/remember.js +5 -5
- package/dist/cli/serve.js +9 -4
- package/dist/cli/session-hooks.d.ts +0 -4
- package/dist/cli/session-hooks.js +57 -66
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.js +2 -2
- package/dist/cli/shared.d.ts +1 -1
- package/dist/cli/shared.js +2 -2
- package/dist/cli/sleep.js +2 -2
- package/dist/cli/transfer.d.ts +3 -3
- package/dist/cli/transfer.js +34 -15
- package/dist/cli/usage.d.ts +1 -1
- package/dist/cli/usage.js +1 -1
- package/dist/cli/verb-row.d.ts +2 -0
- package/dist/cli/verbs/health.js +2 -0
- package/dist/cli/verbs/memory.js +43 -51
- package/dist/cli/verbs/objects.js +6 -3
- package/dist/cli/verbs/sessions.js +4 -2
- package/dist/cli.js +1 -2
- package/dist/connectors/dlq.js +2 -1
- package/dist/connectors/github/deletion.js +2 -1
- package/dist/connectors/github/ingest.js +2 -1
- package/dist/connectors/github/tenant-routing.js +2 -1
- package/dist/connectors/github/webhook.js +4 -2
- package/dist/connectors/ingest.js +2 -1
- package/dist/connectors/slack/deletion.js +2 -1
- package/dist/connectors/slack/ingest.js +2 -1
- package/dist/connectors/slack/tenant-routing.js +2 -1
- package/dist/consolidate/conflicts.js +1 -1
- package/dist/consolidate/dag.js +14 -9
- package/dist/consolidate/dedupe.js +1 -1
- package/dist/consolidate/memory-value.js +1 -1
- package/dist/consolidate/merge.js +6 -6
- package/dist/consolidate/sleep.js +1 -1
- package/dist/consolidate/traces.js +2 -2
- package/dist/core/config.js +15 -16
- package/dist/core/markdown.js +2 -2
- package/dist/core/memory.d.ts +4 -4
- package/dist/core/memory.js +10 -5
- package/dist/core/physics.d.ts +3 -1
- package/dist/core/physics.js +17 -2
- package/dist/core/project-identity.js +2 -1
- package/dist/core/search-types.d.ts +1 -1
- package/dist/dashboard/dashboard-actions.d.ts +2 -2
- package/dist/dashboard/dashboard-actions.js +5 -5
- package/dist/dashboard/dashboard-queries.js +2 -7
- package/dist/dashboard/dashboard-snapshot.js +1 -3
- package/dist/dashboard/dashboard.js +16 -5
- package/dist/db/connect.d.ts +2 -1
- package/dist/db/connect.js +2 -1
- package/dist/db/migrate.js +14 -7
- package/dist/db/migrations/v11.js +1 -0
- package/dist/db/migrations/v14.js +1 -0
- package/dist/db/physics-state.d.ts +0 -4
- package/dist/db/physics-state.js +5 -31
- package/dist/db/request-stores.d.ts +1 -0
- package/dist/db/request-stores.js +2 -1
- package/dist/db/vector-store.js +2 -1
- package/dist/doctor.d.ts +3 -0
- package/dist/doctor.js +7 -7
- package/dist/embeddings/local.js +2 -2
- package/dist/embeddings/provider.js +1 -10
- package/dist/entry/store-kit.d.ts +37 -0
- package/dist/entry/store-kit.js +25 -0
- package/dist/entry/testing.d.ts +6 -0
- package/dist/entry/testing.js +7 -0
- package/dist/eval/judgment.js +1 -1
- package/dist/hooks/json-hooks.js +6 -2
- package/dist/importers/core.js +3 -3
- package/dist/importers/vault.d.ts +1 -1
- package/dist/importers/vault.js +18 -18
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/learn/autolearn.d.ts +6 -2
- package/dist/learn/autolearn.js +8 -6
- package/dist/learn/extract.js +1 -1
- package/dist/learn/invalidation.d.ts +2 -1
- package/dist/learn/invalidation.js +10 -5
- package/dist/mcp/memory-tools.d.ts +1 -1
- package/dist/mcp/memory-tools.js +6 -9
- package/dist/mcp/request.js +20 -19
- package/dist/mcp/stdio.js +13 -8
- package/dist/rerankers/cross-encoder.js +10 -3
- package/dist/search/embed-memories.d.ts +5 -2
- package/dist/search/embed-memories.js +40 -28
- package/dist/search/engine.d.ts +8 -0
- package/dist/search/engine.js +10 -0
- package/dist/search/vector.js +5 -5
- package/dist/server/auth.d.ts +1 -1
- package/dist/server/auth.js +7 -8
- package/dist/server/boot.d.ts +2 -1
- package/dist/server/boot.js +28 -19
- package/dist/server/client-ip.d.ts +9 -4
- package/dist/server/client-ip.js +35 -17
- package/dist/server/route-table.js +5 -6
- package/dist/server/routes/memories.js +4 -2
- package/dist/server/sleep-offload.js +3 -3
- package/dist/server/tls.d.ts +7 -2
- package/dist/server/tls.js +17 -5
- package/dist/server/types.d.ts +7 -2
- package/dist/server.d.ts +4 -41
- package/dist/server.js +3 -30
- package/dist/sharing/global-store.d.ts +4 -5
- package/dist/sharing/global-store.js +6 -11
- package/dist/sharing/global-sync.js +1 -1
- package/dist/sharing/search-both.js +9 -2
- package/dist/sharing/share.js +2 -4
- package/dist/store/ambient.js +2 -1
- package/dist/store/candidates.js +18 -8
- package/dist/store/cards.js +5 -4
- package/dist/store/compactions-record.js +8 -7
- package/dist/store/conflicts.d.ts +7 -1
- package/dist/store/conflicts.js +6 -5
- package/dist/store/connectors/dlq.js +2 -1
- package/dist/store/connectors/event-log.d.ts +13 -0
- package/dist/store/connectors/event-log.js +24 -0
- package/dist/store/connectors/github.js +6 -8
- package/dist/store/connectors/slack.js +6 -10
- package/dist/store/dashboard-reads.js +1 -0
- package/dist/store/delete-and-batch.js +5 -4
- package/dist/store/delivery-recorder.d.ts +2 -2
- package/dist/store/delivery-recorder.js +1 -6
- package/dist/store/descendant-page.js +2 -1
- package/dist/store/dormant.js +7 -3
- package/dist/store/entry-reads.d.ts +25 -3
- package/dist/store/entry-reads.js +43 -12
- package/dist/store/entry-row.js +9 -2
- package/dist/store/entry-writes.d.ts +10 -7
- package/dist/store/entry-writes.js +23 -11
- package/dist/store/goals.js +3 -2
- package/dist/store/graph-reads.js +5 -4
- package/dist/store/graph-view-rows.js +2 -1
- package/dist/store/half-life.js +2 -2
- package/dist/store/handoffs.d.ts +9 -3
- package/dist/store/handoffs.js +4 -3
- package/dist/store/index.d.ts +2 -2
- package/dist/store/index.js +1 -1
- package/dist/store/mirrors.js +9 -4
- package/dist/store/open.d.ts +2 -1
- package/dist/store/open.js +2 -1
- package/dist/store/port.d.ts +59 -3
- package/dist/store/quality-repair.js +1 -1
- package/dist/store/recall-trace.js +2 -1
- package/dist/store/rejected-values.js +14 -9
- package/dist/store/rows.js +2 -2
- package/dist/store/rule-sql.d.ts +2 -0
- package/dist/store/rule-sql.js +12 -6
- package/dist/store/search-rows.d.ts +5 -5
- package/dist/store/search-rows.js +9 -12
- package/dist/store/set-aside.js +1 -1
- package/dist/store/sqlite/connector-writes-group.js +3 -1
- package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
- package/dist/store/sqlite/entry-writes-group.js +1 -1
- package/dist/store/sqlite/held-connection.d.ts +2 -0
- package/dist/store/sqlite/held-connection.js +1 -1
- package/dist/store/sqlite/last-recall-group.d.ts +13 -0
- package/dist/store/sqlite/last-recall-group.js +57 -0
- package/dist/store/sqlite/local.d.ts +0 -17
- package/dist/store/sqlite/local.js +0 -31
- package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
- package/dist/store/sqlite/maintenance-groups.js +60 -0
- package/dist/store/sqlite/objects-group.js +14 -6
- package/dist/store/sqlite/store.d.ts +1 -8
- package/dist/store/sqlite/store.js +13 -24
- package/dist/store/summaries.d.ts +7 -0
- package/dist/store/summaries.js +49 -7
- package/dist/store/token-ledger-rows.js +3 -2
- package/dist/store/vector-index.js +5 -2
- package/dist/util/anthropic-messages.d.ts +3 -1
- package/dist/util/anthropic-messages.js +4 -2
- package/dist/util/atomic-write.d.ts +5 -2
- package/dist/util/atomic-write.js +12 -8
- package/dist/util/env.d.ts +10 -1
- package/dist/util/env.js +10 -1
- package/dist/util/format.d.ts +2 -0
- package/dist/util/format.js +4 -0
- package/dist/util/request-scope.d.ts +6 -2
- package/dist/util/request-scope.js +7 -3
- package/dist/util/spawn-argv.d.ts +9 -0
- package/dist/util/spawn-argv.js +57 -0
- package/dist/util/sql.d.ts +3 -0
- package/dist/util/sql.js +6 -0
- package/dist/util/vector-codec.d.ts +4 -0
- package/dist/util/vector-codec.js +15 -0
- package/dist/util/version.d.ts +1 -1
- package/dist/util/version.js +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 +3 -1
- package/dist/api/on-store.d.ts +0 -16
- package/dist/api/on-store.js +0 -38
- package/dist/cli/lenient-id.d.ts +0 -2
- package/dist/cli/lenient-id.js +0 -13
package/README.md
CHANGED
|
@@ -675,11 +675,13 @@ hippo sleep
|
|
|
675
675
|
Wrap any command with `hippo watch` to auto-learn from failures:
|
|
676
676
|
|
|
677
677
|
```bash
|
|
678
|
-
hippo watch
|
|
678
|
+
hippo watch -- npm run build
|
|
679
679
|
# if it fails, Hippo captures the error automatically
|
|
680
680
|
# next time an agent asks about build issues, the memory is there
|
|
681
681
|
```
|
|
682
682
|
|
|
683
|
+
The command runs with no shell, so each argument reaches the program as written. To run a shell line with pipes or `&&`, pass it as one string after `--shell`: `hippo watch --shell "npm test && npm run build"`.
|
|
684
|
+
|
|
683
685
|
---
|
|
684
686
|
|
|
685
687
|
## CLI Reference
|
|
@@ -736,7 +738,7 @@ hippo watch "npm run build"
|
|
|
736
738
|
| `hippo failures [--days n]` | Failed tool calls the capture-error hook saw, by outcome, and how many errors first happened in another session |
|
|
737
739
|
| `hippo embed` | Embed all memories for semantic search |
|
|
738
740
|
| `hippo embed --status` | Show embedding coverage |
|
|
739
|
-
| `hippo watch
|
|
741
|
+
| `hippo watch -- <command> [args...]` | Run command with no shell, auto-learn from failures (`--shell "<line>"` runs one line through the shell) |
|
|
740
742
|
| `hippo learn --git` | Scan recent git commits for lessons |
|
|
741
743
|
| `hippo learn --git --days <n>` | Scan N days back (default: 7) |
|
|
742
744
|
| `hippo learn --git --repos <paths>` | Scan multiple repos (comma-separated) |
|
|
@@ -784,8 +786,8 @@ hippo watch "npm run build"
|
|
|
784
786
|
| `hippo dashboard` | Open web dashboard at localhost:3333 (memory health by project, and the card board); open the printed URL, which carries a per-start access token |
|
|
785
787
|
| `hippo dashboard --port <n>` | Use custom port |
|
|
786
788
|
| `hippo mcp` | Start MCP server (stdio transport) |
|
|
787
|
-
| `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as host admin; `HIPPO_REQUIRE_AUTH=1` wins over it |
|
|
788
|
-
| `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind
|
|
789
|
+
| `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as a member (`HIPPO_KEYLESS_LOCAL_ROLE=admin` makes them host admin, for sleep and the quarantine routes); `HIPPO_REQUIRE_AUTH=1` wins over it. Each caller gets 20 requests a second, burst 40 (`HIPPO_CALLER_RPS`; `0` turns it off). See [Security defaults](docs/UPGRADING-2.0.md#security-defaults) |
|
|
790
|
+
| `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind refuses to start, since API keys and memory text would travel in cleartext; behind a TLS-terminating proxy, pass `--allow-cleartext` (or set `HIPPO_ALLOW_CLEARTEXT=1`) |
|
|
789
791
|
|
|
790
792
|
On `heartbeat`, `block`, `review` and `complete`, a given `--run` is checked against the card's live run and the command is refused, unchanged, if the two do not match.
|
|
791
793
|
|
|
@@ -84,7 +84,7 @@ class ContainerRun {
|
|
|
84
84
|
continue;
|
|
85
85
|
const source = itemSource(this.w.prefix, key, item.text);
|
|
86
86
|
for (const row of rows) {
|
|
87
|
-
if (renameEntrySourceAt(this.s.db, row.
|
|
87
|
+
if (renameEntrySourceAt(this.s.db, row.tenant_id, row.id, row.source, source) === 0)
|
|
88
88
|
continue;
|
|
89
89
|
this.tally.adopted++;
|
|
90
90
|
this.mirror.push({ ...row, source });
|
|
@@ -97,7 +97,7 @@ class ContainerRun {
|
|
|
97
97
|
let moved = 0;
|
|
98
98
|
for (const row of selectLiveEntriesBySourcePrefix(this.s.db, this.s.tenantId, old)) {
|
|
99
99
|
const source = this.w.prefix + row.source.slice(old.length);
|
|
100
|
-
if (renameEntrySourceAndOriginAt(this.s.db, row.
|
|
100
|
+
if (renameEntrySourceAndOriginAt(this.s.db, row.tenant_id, row.id, { from: row.source, to: source, origin }) === 0)
|
|
101
101
|
continue;
|
|
102
102
|
moved++;
|
|
103
103
|
this.mirror.push({ ...row, source, origin_project: origin ?? row.origin_project });
|
|
@@ -150,11 +150,11 @@ class ContainerRun {
|
|
|
150
150
|
}
|
|
151
151
|
/** api.supersede's steps on this transaction; false when another writer superseded the row first. */
|
|
152
152
|
supersede(old, newId) {
|
|
153
|
-
if (!supersedeEntryAt(this.s.db, old.
|
|
153
|
+
if (!supersedeEntryAt(this.s.db, old.tenant_id, old.id, newId))
|
|
154
154
|
return false;
|
|
155
155
|
if (old.dag_parent_id)
|
|
156
|
-
markSummaryDirtyInTx(this.s.db, old.dag_parent_id, old.
|
|
157
|
-
appendAuditEvent(this.s.db, { tenantId: old.
|
|
156
|
+
markSummaryDirtyInTx(this.s.db, old.dag_parent_id, old.tenant_id, SYNC_ACTOR);
|
|
157
|
+
appendAuditEvent(this.s.db, { tenantId: old.tenant_id, actor: SYNC_ACTOR, op: 'supersede', targetId: old.id, metadata: { newId } });
|
|
158
158
|
this.mirror.push({ ...old, superseded_by: newId });
|
|
159
159
|
return true;
|
|
160
160
|
}
|
package/dist/api/assemble.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Session context assembly under a token budget.
|
|
2
|
-
import { requireGroup
|
|
2
|
+
import { requireGroup } from '../store/index.js';
|
|
3
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
3
4
|
import { estimateTokens } from '../util/token-text.js';
|
|
4
5
|
import { passesScopeFilterForRecall, assertScopeRequestAllowed, personalScopeOf } from '../core/recall-scope.js';
|
|
5
6
|
import { classifyOriginProject, projectNames } from '../core/project-identity.js';
|
package/dist/api/audit.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AuditEvent, AuditOp } from '../store/audit.js';
|
|
2
2
|
import { type AuditIssue, type AuditResult } from '../core/memory-audit.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { QualityRepairResult } from '../store/quality-repair.js';
|
|
4
4
|
import type { KeysetPosition } from '../util/keyset.js';
|
|
5
5
|
import type { Context } from './types.js';
|
|
6
6
|
export interface AuditListOpts {
|
|
@@ -16,13 +16,13 @@ export declare function auditList(ctx: Context, opts: AuditListOpts): Promise<Au
|
|
|
16
16
|
/** The pass that removes audit errors; it leads the reason on each forget row. */
|
|
17
17
|
export type AuditPass = 'audit --fix' | 'sleep-audit';
|
|
18
18
|
/** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
|
|
19
|
-
export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): string[]
|
|
19
|
+
export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): Promise<string[]>;
|
|
20
20
|
/** The caller's memories run through the quality audit; a memory that backs an object is never marked for removal. */
|
|
21
|
-
export declare function auditMemoryQuality(ctx: Context): AuditResult
|
|
21
|
+
export declare function auditMemoryQuality(ctx: Context): Promise<AuditResult>;
|
|
22
22
|
/** Audit repair for the caller's tenant: a preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
|
|
23
|
-
export declare function repairMemoryQuality(ctx: Context, apply: boolean): QualityRepairResult
|
|
23
|
+
export declare function repairMemoryQuality(ctx: Context, apply: boolean): Promise<QualityRepairResult>;
|
|
24
24
|
/** The repair sleep and the daily runner apply once per store after an upgrade; null when it already ran there. */
|
|
25
|
-
export declare function repairMemoryQualityOnce(ctx: Context): QualityRepairResult | null
|
|
25
|
+
export declare function repairMemoryQualityOnce(ctx: Context): Promise<QualityRepairResult | null>;
|
|
26
26
|
export interface PruneAuditOpts {
|
|
27
27
|
/** Cutoff in days. Rows with `ts < (now - N days)` are deleted. */
|
|
28
28
|
olderThanDays: number;
|
|
@@ -42,5 +42,5 @@ export declare function computeCutoff(days: number, now?: Date): string;
|
|
|
42
42
|
/** Delete the caller's tenant's audit_log rows older than `olderThanDays`, then record an `audit_prune` row as `ctx.actor`; opt-in, since
|
|
43
43
|
* retention floors (HIPAA, SOX, GDPR) apply. The row is written after the DELETE, so a call never prunes its own record.
|
|
44
44
|
* Throws on non-positive days or an empty tenant. */
|
|
45
|
-
export declare function pruneAuditLog(ctx: Context, opts: PruneAuditOpts): PruneAuditResult
|
|
45
|
+
export declare function pruneAuditLog(ctx: Context, opts: PruneAuditOpts): Promise<PruneAuditResult>;
|
|
46
46
|
//# sourceMappingURL=audit.d.ts.map
|
package/dist/api/audit.js
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
1
|
// Audit log queries and retention, and the memory-quality audit with its repair passes.
|
|
2
|
-
import { pruneAuditRows } from '../store/audit.js';
|
|
3
2
|
import { auditMemories } from '../core/memory-audit.js';
|
|
4
|
-
import { deleteEntriesAutomatically, memoriesBackingObjects } from '../store/delete-and-batch.js';
|
|
5
|
-
import { loadAllEntries } from '../store/entry-reads.js';
|
|
6
|
-
import { repairAutomaticMemories, repairQualityOnce } from '../store/quality-repair.js';
|
|
7
3
|
import { DAY_MS } from '../util/time.js';
|
|
8
|
-
import { requireGroup
|
|
4
|
+
import { requireGroup } from '../store/index.js';
|
|
5
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
9
6
|
/** Read audit events scoped to `ctx.tenantId` on the store the request runs on. Read-only, no audit emit. */
|
|
10
7
|
export async function auditList(ctx, opts) {
|
|
11
8
|
return requireGroup(storeFor(ctx), 'auditLog').listAuditEvents({
|
|
12
9
|
tenantId: ctx.tenantId, op: opts.op, since: opts.since, limit: opts.limit, after: opts.after,
|
|
13
10
|
});
|
|
14
11
|
}
|
|
12
|
+
function maintenanceOf(ctx) {
|
|
13
|
+
return requireGroup(storeFor(ctx), 'auditMaintenance');
|
|
14
|
+
}
|
|
15
15
|
/** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
|
|
16
|
-
export function removeAuditErrors(ctx, pass, issues) {
|
|
16
|
+
export async function removeAuditErrors(ctx, pass, issues) {
|
|
17
17
|
const removals = issues
|
|
18
18
|
.filter((issue) => issue.severity === 'error')
|
|
19
19
|
.map((issue) => ({ id: issue.memoryId, reason: `${pass}: ${issue.reason}` }));
|
|
20
|
-
|
|
20
|
+
if (removals.length === 0)
|
|
21
|
+
return [];
|
|
22
|
+
return maintenanceOf(ctx).deleteAutomatically(removals, ctx.actor.subject);
|
|
21
23
|
}
|
|
22
|
-
// SHORTCUT: hippo.db only, as the port has no whole-tenant read, backing-object read or automatic delete with a reason; another store kind
|
|
23
|
-
// answers 501 at the open. Port groups for them once a served store must audit.
|
|
24
24
|
/** The caller's memories run through the quality audit; a memory that backs an object is never marked for removal. */
|
|
25
|
-
export function auditMemoryQuality(ctx) {
|
|
26
|
-
|
|
25
|
+
export async function auditMemoryQuality(ctx) {
|
|
26
|
+
const maintenance = maintenanceOf(ctx);
|
|
27
|
+
return auditMemories(await maintenance.tenantEntries(ctx.tenantId), await maintenance.objectBackedIds());
|
|
27
28
|
}
|
|
28
29
|
/** Audit repair for the caller's tenant: a preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
|
|
29
|
-
export function repairMemoryQuality(ctx, apply) {
|
|
30
|
-
return
|
|
30
|
+
export async function repairMemoryQuality(ctx, apply) {
|
|
31
|
+
return maintenanceOf(ctx).repairQuality(ctx.tenantId, apply);
|
|
31
32
|
}
|
|
32
33
|
/** The repair sleep and the daily runner apply once per store after an upgrade; null when it already ran there. */
|
|
33
|
-
export function repairMemoryQualityOnce(ctx) {
|
|
34
|
-
return
|
|
34
|
+
export async function repairMemoryQualityOnce(ctx) {
|
|
35
|
+
return maintenanceOf(ctx).repairQualityOnce(ctx.tenantId);
|
|
35
36
|
}
|
|
36
37
|
/** Cutoff ISO timestamp for N days ago; exported so tests can pin "now" without mocking Date. */
|
|
37
38
|
export function computeCutoff(days, now = new Date()) {
|
|
@@ -41,7 +42,7 @@ export function computeCutoff(days, now = new Date()) {
|
|
|
41
42
|
/** Delete the caller's tenant's audit_log rows older than `olderThanDays`, then record an `audit_prune` row as `ctx.actor`; opt-in, since
|
|
42
43
|
* retention floors (HIPAA, SOX, GDPR) apply. The row is written after the DELETE, so a call never prunes its own record.
|
|
43
44
|
* Throws on non-positive days or an empty tenant. */
|
|
44
|
-
export function pruneAuditLog(ctx, opts) {
|
|
45
|
+
export async function pruneAuditLog(ctx, opts) {
|
|
45
46
|
if (!Number.isFinite(opts.olderThanDays) || opts.olderThanDays <= 0) {
|
|
46
47
|
throw new Error(`pruneAuditLog: olderThanDays must be a positive number, got ${opts.olderThanDays}`);
|
|
47
48
|
}
|
|
@@ -50,7 +51,8 @@ export function pruneAuditLog(ctx, opts) {
|
|
|
50
51
|
}
|
|
51
52
|
const dryRun = opts.dryRun === true;
|
|
52
53
|
const cutoff = computeCutoff(opts.olderThanDays);
|
|
53
|
-
const
|
|
54
|
+
const prune = { tenantId: ctx.tenantId, cutoff, actor: ctx.actor.subject, olderThanDays: opts.olderThanDays, dryRun };
|
|
55
|
+
const count = await maintenanceOf(ctx).pruneAuditRows(prune);
|
|
54
56
|
return { cutoff, count, dryRun };
|
|
55
57
|
}
|
|
56
58
|
//# sourceMappingURL=audit.js.map
|
package/dist/api/auth.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DEFAULT_KEY_TTL_DAYS, type ApiKeyListItem, type ApiKeyListRow } from '../store/auth.js';
|
|
2
2
|
import type { KeysetPosition } from '../util/keyset.js';
|
|
3
|
-
import { type Context
|
|
3
|
+
import { type Context } from './types.js';
|
|
4
4
|
export interface AuthCreateOpts {
|
|
5
5
|
label?: string;
|
|
6
6
|
/** Defaults to `'member'`, which admin-gated routes such as `POST /v1/sleep` refuse; an admin key has to be asked for by name. */
|
|
@@ -21,7 +21,7 @@ export interface AuthCreateResult {
|
|
|
21
21
|
}
|
|
22
22
|
/** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
|
|
23
23
|
* Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
|
|
24
|
-
export declare function authCreate
|
|
24
|
+
export declare function authCreate(ctx: Context, opts: AuthCreateOpts): Promise<AuthCreateResult>;
|
|
25
25
|
export { DEFAULT_KEY_TTL_DAYS };
|
|
26
26
|
export declare const MAX_TTL_DAYS = 3650;
|
|
27
27
|
export interface AuthCreateSelfOpts {
|
|
@@ -37,24 +37,23 @@ export interface AuthCreateSelfResult extends AuthCreateResult {
|
|
|
37
37
|
}
|
|
38
38
|
/** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
|
|
39
39
|
* binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
|
|
40
|
-
export declare function authCreateSelf
|
|
40
|
+
export declare function authCreateSelf(ctx: Context, opts: AuthCreateSelfOpts): Promise<AuthCreateSelfResult>;
|
|
41
41
|
type KeyListOpts = {
|
|
42
42
|
active: boolean;
|
|
43
43
|
limit?: number;
|
|
44
44
|
after?: KeysetPosition;
|
|
45
45
|
};
|
|
46
46
|
/** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
|
|
47
|
-
export declare function authListRows
|
|
47
|
+
export declare function authListRows(ctx: Context, opts: KeyListOpts): Promise<ApiKeyListRow[]>;
|
|
48
48
|
/** Every tenant's keys in the store, live ones only unless `active` is false; the host's own view, so the host admin only. */
|
|
49
49
|
export declare function authListAllTenants(ctx: Context, active: boolean): ApiKeyListItem[];
|
|
50
50
|
export interface AuthRevokeResult {
|
|
51
51
|
ok: true;
|
|
52
52
|
revokedAt: string;
|
|
53
53
|
}
|
|
54
|
-
export type AuthRevokeReply<C extends Context> = StoreReply<C, AuthRevokeResult>;
|
|
55
54
|
/** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
|
|
56
55
|
* The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
|
|
57
|
-
export declare function authRevoke
|
|
56
|
+
export declare function authRevoke(ctx: Context, keyId: string): Promise<AuthRevokeResult>;
|
|
58
57
|
/** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
|
|
59
58
|
* so the local CLI can run revoke and grant in the key's own tenant. */
|
|
60
59
|
export declare function authKeyTenant(ctx: Context, keyId: string): Promise<string | undefined>;
|
package/dist/api/auth.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// API key management: create, list, revoke, and grant or ungrant restricted scopes.
|
|
2
2
|
import { BadRequestError, ForbiddenError, NotFoundError } from '../core/api-errors.js';
|
|
3
3
|
import { DEFAULT_KEY_TTL_DAYS, listApiKeys, mintApiKey, } from '../store/auth.js';
|
|
4
|
-
import {
|
|
4
|
+
import { requireGroup } from '../store/index.js';
|
|
5
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
5
6
|
import { changeScopeGrant } from '../store/sqlite/local.js';
|
|
6
7
|
import { DAY_MS } from '../util/time.js';
|
|
7
|
-
import { andThen, notPorted, onStore } from './on-store.js';
|
|
8
8
|
import { requireHostAdmin } from './types.js';
|
|
9
9
|
const API_KEY_SUBJECT = 'api_key:';
|
|
10
10
|
/** The key id an API-key actor's subject names, or null for any other actor. */
|
|
@@ -13,13 +13,12 @@ function keyIdOfSubject(subject) {
|
|
|
13
13
|
}
|
|
14
14
|
/** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
|
|
15
15
|
* Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
|
|
16
|
-
export function authCreate(ctx, opts) {
|
|
17
|
-
// The key and its auth_create row commit together on
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
});
|
|
16
|
+
export async function authCreate(ctx, opts) {
|
|
17
|
+
// The key and its auth_create row commit together on every store, so a failed audit write leaves no key.
|
|
18
|
+
const keyWrites = requireGroup(storeFor(ctx), 'keyWrites');
|
|
19
|
+
const { plaintext, mint } = adminKeyMint(ctx, opts);
|
|
20
|
+
await keyWrites.createApiKey(mint);
|
|
21
|
+
return createResult(mint, plaintext);
|
|
23
22
|
}
|
|
24
23
|
/** A key row in the caller's tenant, made here so only its hash ever reaches a store. */
|
|
25
24
|
function newKey(ctx, fields) {
|
|
@@ -70,12 +69,11 @@ function assertSelfMintOpts({ ttlDays, perSubject }) {
|
|
|
70
69
|
}
|
|
71
70
|
/** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
|
|
72
71
|
* binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
|
|
73
|
-
export function authCreateSelf(ctx, opts) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
72
|
+
export async function authCreateSelf(ctx, opts) {
|
|
73
|
+
const keyWrites = requireGroup(storeFor(ctx), 'keyWrites');
|
|
74
|
+
const { plaintext, mint } = selfKeyMint(ctx, opts);
|
|
75
|
+
await keyWrites.createSelfApiKey(mint);
|
|
76
|
+
return selfResult(mint, plaintext);
|
|
79
77
|
}
|
|
80
78
|
function selfKeyMint(ctx, opts) {
|
|
81
79
|
if (!ctx.actor.viaAuthResolver) {
|
|
@@ -97,21 +95,20 @@ function selfResult({ key }, plaintext) {
|
|
|
97
95
|
return { keyId: key.keyId, plaintext, tenantId: key.tenantId, role: 'member', expiresAt: key.expiresAt };
|
|
98
96
|
}
|
|
99
97
|
/** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
|
|
100
|
-
export function authListRows(ctx, opts) {
|
|
101
|
-
return
|
|
98
|
+
export async function authListRows(ctx, opts) {
|
|
99
|
+
return listRows(ctx, storeFor(ctx), opts);
|
|
102
100
|
}
|
|
103
101
|
/** Every tenant's keys in the store, live ones only unless `active` is false; the host's own view, so the host admin only. */
|
|
104
102
|
export function authListAllTenants(ctx, active) {
|
|
105
103
|
requireHostAdmin(ctx, "Listing every tenant's keys");
|
|
106
104
|
return listApiKeys(ctx.hippoRoot, { active });
|
|
107
105
|
}
|
|
108
|
-
function listRows(ctx,
|
|
109
|
-
const keyWrites =
|
|
106
|
+
async function listRows(ctx, store, opts) {
|
|
107
|
+
const keyWrites = requireGroup(store, 'keyWrites');
|
|
110
108
|
const keyId = memberKeyIdOf(ctx.actor);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
});
|
|
109
|
+
const record = keyId === null ? undefined : await store.findApiKey(keyId);
|
|
110
|
+
const filter = memberListFilter(ctx.actor, record?.ownerSubject);
|
|
111
|
+
return filter === null ? [] : keyWrites.listApiKeys({ ...opts, tenantId: ctx.tenantId, ...filter });
|
|
115
112
|
}
|
|
116
113
|
/** The key id of a member API key caller, whose owner decides what it lists; null for any other caller. */
|
|
117
114
|
function memberKeyIdOf(actor) {
|
|
@@ -144,16 +141,14 @@ function assertMayRevoke(ctx, keyId, row) {
|
|
|
144
141
|
}
|
|
145
142
|
/** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
|
|
146
143
|
* The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
|
|
147
|
-
export function authRevoke(ctx, keyId) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
});
|
|
156
|
-
});
|
|
144
|
+
export async function authRevoke(ctx, keyId) {
|
|
145
|
+
const store = storeFor(ctx);
|
|
146
|
+
const keyAudit = requireGroup(store, 'keyAudit');
|
|
147
|
+
assertMemberKeyRevokesSelf(ctx, keyId);
|
|
148
|
+
const record = await store.findApiKey(keyId);
|
|
149
|
+
assertMayRevoke(ctx, keyId, keyOwnerOf(record));
|
|
150
|
+
const revoke = { tenantId: ctx.tenantId, keyId, actor: ctx.actor.subject, at: new Date().toISOString() };
|
|
151
|
+
return { ok: true, revokedAt: await keyAudit.revokeApiKey(revoke) };
|
|
157
152
|
}
|
|
158
153
|
function assertMemberKeyRevokesSelf(ctx, keyId) {
|
|
159
154
|
if (ctx.actor.role !== 'admin' && !ctx.actor.viaAuthResolver && keyIdOfSubject(ctx.actor.subject) !== keyId) {
|
package/dist/api/conflicts.js
CHANGED
|
@@ -26,7 +26,7 @@ export function resolveMemoryConflict(ctx, conflictId, opts) {
|
|
|
26
26
|
if (loadEntriesByIds(ctx.hippoRoot, pair, ctx.tenantId).filter(isLive).length < pair.length) {
|
|
27
27
|
throw new NotFoundError(`conflict ${conflictId} names a memory that is superseded, archived or quarantined`);
|
|
28
28
|
}
|
|
29
|
-
const resolved = resolveConflict(ctx.hippoRoot, conflictId, opts.keepId, opts.forget === true, ctx.tenantId, {
|
|
29
|
+
const resolved = resolveConflict(ctx.hippoRoot, { conflictId, keepId: opts.keepId, forgetLoser: opts.forget === true, tenantId: ctx.tenantId }, {
|
|
30
30
|
rejectLoserValue: opts.rejectLoser === true,
|
|
31
31
|
reason: opts.reason,
|
|
32
32
|
rejectedBy: ctx.actor.subject,
|
package/dist/api/context-auto.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'child_process';
|
|
2
|
+
import { errorFields, log } from '../util/log.js';
|
|
2
3
|
const MAX_DIFF_TERMS = 10;
|
|
3
4
|
const SKIPPED_PATH_TERMS = ['src', 'dist', 'test', 'tests', 'node_modules', 'index'];
|
|
4
5
|
// stderr is dropped because git's warnings (line-ending notices, for one) would otherwise become query terms.
|
|
@@ -23,8 +24,9 @@ export function autoDetectContext() {
|
|
|
23
24
|
return branch.replace(/[-_/]/g, ' ');
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
catch {
|
|
27
|
-
// Not a git repo or
|
|
27
|
+
catch (err) {
|
|
28
|
+
// Not a git repo, git missing or a timeout: no query, so the caller lists by strength.
|
|
29
|
+
log.debug('auto context: no git-derived query', errorFields(err));
|
|
28
30
|
}
|
|
29
31
|
return '';
|
|
30
32
|
}
|
|
@@ -6,8 +6,7 @@ import { auditQueryFields, recordAuditEvent } from '../store/audit.js';
|
|
|
6
6
|
import { isWorthSurfacing } from '../core/memory-quality.js';
|
|
7
7
|
import { rankBothStores } from '../sharing/search-both.js';
|
|
8
8
|
import { evalNow, strengthAblation } from '../core/ablation.js';
|
|
9
|
-
import {
|
|
10
|
-
import { physicsSearchIn } from '../search/physics-search.js';
|
|
9
|
+
import { searchByEngine } from '../search/engine.js';
|
|
11
10
|
import { DEFAULT_LOCAL_BUMP } from '../core/search-types.js';
|
|
12
11
|
import { compareScoredResults } from '../core/compare.js';
|
|
13
12
|
import { scopeMatch } from '../core/active-scope.js';
|
|
@@ -279,24 +278,13 @@ async function searchLocalRows(ctx, plan, options) {
|
|
|
279
278
|
const localCost = cost && ((r) => price(r.entry, primaryIsGlobal));
|
|
280
279
|
const vectorCandidates = contextVectorSpec(ctx, plan, admit);
|
|
281
280
|
const store = plan.local.store;
|
|
282
|
-
const ctxResults = usePhysicsCtx
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
vectorCandidates,
|
|
290
|
-
})
|
|
291
|
-
: await hybridSearch(query, localEntries, {
|
|
292
|
-
budget: left,
|
|
293
|
-
minResults,
|
|
294
|
-
cost: localCost,
|
|
295
|
-
hippoRoot: ctx.hippoRoot,
|
|
296
|
-
scope: plan.activeScope,
|
|
297
|
-
vectorCandidates,
|
|
298
|
-
store,
|
|
299
|
-
});
|
|
281
|
+
const ctxResults = await searchByEngine({ root: ctx.hippoRoot, store }, query, localEntries, usePhysicsCtx ? ctxConfig.physics : null, {
|
|
282
|
+
budget: left,
|
|
283
|
+
minResults,
|
|
284
|
+
cost: localCost,
|
|
285
|
+
scope: plan.activeScope,
|
|
286
|
+
vectorCandidates,
|
|
287
|
+
});
|
|
300
288
|
return ctxResults.map((r) => ({
|
|
301
289
|
entry: r.entry,
|
|
302
290
|
score: r.score,
|
package/dist/api/context.js
CHANGED
|
@@ -16,10 +16,10 @@ import { promptTokens } from '../core/prompt-recall.js';
|
|
|
16
16
|
import { detectSecret } from '../util/secret-detect.js';
|
|
17
17
|
import { isSessionDigestRow } from '../core/session-digest-row.js';
|
|
18
18
|
import { addAmbientTallies, ambientStateFromTallies } from '../core/ambient.js';
|
|
19
|
-
import { requireGroup, sqliteStore
|
|
19
|
+
import { hasGroup, requireGroup, sqliteStore } from '../store/index.js';
|
|
20
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
20
21
|
import { passesScopeFilterForRecall, assertScopeRequestAllowed, personalScopeOf } from '../core/recall-scope.js';
|
|
21
22
|
import { finiteOr, selectBySearch, selectPinned, selectStrongest, } from './context-select.js';
|
|
22
|
-
import { andThen, onStore } from './on-store.js';
|
|
23
23
|
import { strengthenOf } from './recall-record.js';
|
|
24
24
|
import { ownerOrSubject } from './types.js';
|
|
25
25
|
export { oneCopyPerMemory } from './context-select.js';
|
|
@@ -54,7 +54,7 @@ function sourceOf(store) {
|
|
|
54
54
|
// The pinned-only branch needs pins and recent-N candidates, not the corpus.
|
|
55
55
|
async function loadAmbientEntries(source, tenantId, options) {
|
|
56
56
|
const { pinnedOnly, recent, admit, recheck, window, recall, onQualityDrop } = options;
|
|
57
|
-
const ownTenant = (e) => e.
|
|
57
|
+
const ownTenant = (e) => e.tenant_id === tenantId;
|
|
58
58
|
if (!pinnedOnly) {
|
|
59
59
|
const rows = 'query' in window
|
|
60
60
|
? await source.store.searchRecallEntries(window.query, {
|
|
@@ -139,7 +139,7 @@ function warnIsolationIgnored(hippoRoot) {
|
|
|
139
139
|
}
|
|
140
140
|
/** Which stores this read can draw on, and what kind the primary one is. */
|
|
141
141
|
function storesInReach(ctx, opts, local) {
|
|
142
|
-
const other = local.store
|
|
142
|
+
const other = hasGroup(local.store, 'localFiles') ? undefined : local.store;
|
|
143
143
|
// Global memories do not establish a project boundary for task state.
|
|
144
144
|
const hasLocal = other !== undefined || isInitialized(ctx.hippoRoot);
|
|
145
145
|
const globalRoot = getGlobalRoot();
|
|
@@ -363,7 +363,7 @@ async function traceEmptyContext(ctx, opts, plan) {
|
|
|
363
363
|
};
|
|
364
364
|
// The empty reply is already decided, so a lost trace is logged and the call still answers.
|
|
365
365
|
try {
|
|
366
|
-
await
|
|
366
|
+
await storeFor(ctx).finishRecall({ goalLog: [], audit: [], trace });
|
|
367
367
|
}
|
|
368
368
|
catch (error) {
|
|
369
369
|
rethrowIfSqliteBlocked(error);
|
|
@@ -387,11 +387,13 @@ async function recordRetrieval(ctx, opts, plan, selected, activeSnapshot) {
|
|
|
387
387
|
})),
|
|
388
388
|
};
|
|
389
389
|
const writes = { goalLog: [], audit: [], trace, strengthen: strengthenOf(ctx, retrievedIds) };
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
390
|
+
// The last recall feeds only outcomeForLastRecall, so a store that keeps none still finishes the recall without one.
|
|
391
|
+
const store = storeFor(ctx);
|
|
392
|
+
const traceId = store.lastRecall
|
|
393
|
+
? await store.lastRecall.finishRecall(writes, plan.hasGlobal ? plan.globalRoot : undefined)
|
|
394
|
+
: await store.finishRecall(writes).then(() => null);
|
|
395
|
+
plan.obs?.traced(traceId);
|
|
396
|
+
await store.bumpRecallStats(selected.length);
|
|
395
397
|
// Replace selectedItems entries with markRetrieved-updated copies so
|
|
396
398
|
// the returned ContextResult reflects post-recall state.
|
|
397
399
|
const items = selected.map((s) => ({
|
package/dist/api/drill-down.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// DAG drill-down from a summary to its children.
|
|
2
|
-
import { requireGroup
|
|
2
|
+
import { requireGroup } from '../store/index.js';
|
|
3
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
3
4
|
import { estimateTokens } from '../util/token-text.js';
|
|
4
5
|
import { passesScopeFilterForRecall, personalScopeOf } from '../core/recall-scope.js';
|
|
5
6
|
import { classifyOriginProject } from '../core/project-identity.js';
|
package/dist/api/forget.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type RejectFlowResult } from '../trust/reject-flow.js';
|
|
2
|
-
import { type Context
|
|
2
|
+
import { type Context } from './types.js';
|
|
3
3
|
/** Delete a memory by id. Reach is checked inside the delete's write scope, and a
|
|
4
4
|
* row out of reach answers as not found, so a caller learns nothing about it. */
|
|
5
5
|
export interface ForgetResult {
|
|
6
6
|
ok: true;
|
|
7
7
|
id: string;
|
|
8
8
|
}
|
|
9
|
-
export declare function forget
|
|
9
|
+
export declare function forget(ctx: Context, id: string): Promise<ForgetResult>;
|
|
10
10
|
export interface RejectOpts {
|
|
11
11
|
/** By-id form: reject the CURRENT content of an existing memory. */
|
|
12
12
|
memoryId?: string;
|
package/dist/api/forget.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
// Forget a memory, and reject or unreject a value so it cannot be stored again.
|
|
2
2
|
import { BadRequestError, NotFoundError } from '../core/api-errors.js';
|
|
3
3
|
import { rejectValue, unrejectValue } from '../trust/reject-flow.js';
|
|
4
|
-
import {
|
|
4
|
+
import { requireGroup } from '../store/index.js';
|
|
5
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
5
6
|
import { requireHostAdmin } from './types.js';
|
|
6
7
|
import { getMemory } from './memories.js';
|
|
7
8
|
import { canTouchScope, personalScopeOf } from '../core/recall-scope.js';
|
|
8
|
-
export function forget(ctx, id) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return andThen(entryWrites.forget(removal), () => ({ ok: true, id }));
|
|
13
|
-
});
|
|
9
|
+
export async function forget(ctx, id) {
|
|
10
|
+
const entryWrites = requireGroup(storeFor(ctx), 'entryWrites');
|
|
11
|
+
await entryWrites.forget({ tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), id });
|
|
12
|
+
return { ok: true, id };
|
|
14
13
|
}
|
|
15
14
|
/** Tombstones a value's normalized digest so a matching write is refused everywhere until `unreject`; pass exactly one of `memoryId` or `value`.
|
|
16
15
|
* `memoryId` also removes every live tenant row with that digest (not others' personal rows); `reason` is required. Throws on an unknown id or both/neither. */
|
package/dist/api/graph.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { requireGroup
|
|
1
|
+
import { requireGroup } from '../store/index.js';
|
|
2
|
+
import { storeFor } from '../store/sqlite/store.js';
|
|
2
3
|
/** The entity/relation rows behind GET /v1/graph, as the caller's role, scopes and owner may see them. */
|
|
3
4
|
export async function graphRows(ctx, query) {
|
|
4
5
|
const { role, scopes, owner } = ctx.actor;
|
package/dist/api/learn.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ export interface LearnResult {
|
|
|
28
28
|
}>;
|
|
29
29
|
}
|
|
30
30
|
/** Learn from `repoPath`'s last `days` of commits into the caller's tenant. Host admin only. */
|
|
31
|
-
export declare function learn(ctx: Context, opts: LearnOpts): LearnResult
|
|
31
|
+
export declare function learn(ctx: Context, opts: LearnOpts): Promise<LearnResult>;
|
|
32
32
|
export type { InvalidationOptions, InvalidationResult, InvalidationTarget };
|
|
33
33
|
/** `hippo invalidate`: weakens the caller's tenant's memories that reference `target.from`, or only the one `options.onlyId` names. */
|
|
34
34
|
export declare function invalidateMemories(ctx: Context, target: InvalidationTarget, options: InvalidationOptions): InvalidationResult;
|