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/dist/cli/decisions.js
CHANGED
|
@@ -7,7 +7,6 @@ import { nonEmptyStringFlag, flagIsTrue, stringFlag } from './flag-values.js';
|
|
|
7
7
|
import { requireInit } from './shared.js';
|
|
8
8
|
import { cliApiContext } from './api-context.js';
|
|
9
9
|
import { closeObject, foundOrExit, idArgOrExit, listObjects, printLifecycleTail } from './object-verbs.js';
|
|
10
|
-
import { parseObjectId } from './lenient-id.js';
|
|
11
10
|
import { errorMessage } from '../util/log.js';
|
|
12
11
|
import { CliExit } from './exit.js';
|
|
13
12
|
const DECISION = { cmd: 'decide', noun: 'Decision', idLabel: 'decision' };
|
|
@@ -27,7 +26,7 @@ function decideList(hippoRoot, tenantId, flags) {
|
|
|
27
26
|
});
|
|
28
27
|
}
|
|
29
28
|
function decideGet(hippoRoot, tenantId, args) {
|
|
30
|
-
const id = idArgOrExit(args, 'Usage: hippo decide get <id>', DECISION.idLabel
|
|
29
|
+
const id = idArgOrExit(args, 'Usage: hippo decide get <id>', DECISION.idLabel);
|
|
31
30
|
const decision = foundOrExit(decisionsModule.loadDecisionById(hippoRoot, tenantId, id), DECISION.noun, id);
|
|
32
31
|
console.log(`Decision #${decision.id}`);
|
|
33
32
|
console.log(` status: ${decision.status}`);
|
|
@@ -37,7 +36,7 @@ function decideGet(hippoRoot, tenantId, args) {
|
|
|
37
36
|
printLifecycleTail(decision);
|
|
38
37
|
}
|
|
39
38
|
function decideClose(hippoRoot, tenantId, args) {
|
|
40
|
-
closeObject(args, DECISION, (id) => decisionsModule.closeDecision(hippoRoot, tenantId, id)
|
|
39
|
+
closeObject(args, DECISION, (id) => decisionsModule.closeDecision(hippoRoot, tenantId, id));
|
|
41
40
|
}
|
|
42
41
|
export async function handleDecide({ hippoRoot, tenantId, args, flags }) {
|
|
43
42
|
requireInit(hippoRoot);
|
|
@@ -83,7 +82,7 @@ async function decideCreate(hippoRoot, tenantId, decisionText, flags) {
|
|
|
83
82
|
extraTags: decisionPathTags,
|
|
84
83
|
});
|
|
85
84
|
if (oldEntry)
|
|
86
|
-
|
|
85
|
+
weakenOrWarn(hippoRoot, oldEntry, supersedesMemId);
|
|
87
86
|
console.log(`Decision recorded: #${created.id}`);
|
|
88
87
|
if (created.memoryId)
|
|
89
88
|
console.log(` memory: ${created.memoryId}`);
|
|
@@ -97,7 +96,7 @@ function exitWithDecideUsage() {
|
|
|
97
96
|
printError(' hippo decide close <id>');
|
|
98
97
|
throw new CliExit(1);
|
|
99
98
|
}
|
|
100
|
-
function
|
|
99
|
+
function weakenOrWarn(hippoRoot, oldEntry, supersedesMemId) {
|
|
101
100
|
// Best-effort and last: saveDecision already committed. Failing here would make a retry find no active
|
|
102
101
|
// decision for the old memory and create a duplicate active successor, so warn instead.
|
|
103
102
|
try {
|
|
@@ -25,5 +25,7 @@ export declare function payloadCwdRoot(hippoRoot: string, stdinText: string | un
|
|
|
25
25
|
* work with one warning, exit 0. */
|
|
26
26
|
export declare function runHookWithStores<T>(fn: () => T | Promise<T>): Promise<T | undefined>;
|
|
27
27
|
/** Whether this session sits in the pilot's holdout arm; off at rate 0 and with no session id. */
|
|
28
|
-
export declare function inPilotHoldout(hippoRoot: string, tenantId: string, sessionId: string | undefined,
|
|
28
|
+
export declare function inPilotHoldout(hippoRoot: string, tenantId: string, sessionId: string | undefined, opts: {
|
|
29
|
+
write: boolean;
|
|
30
|
+
}): boolean;
|
|
29
31
|
//# sourceMappingURL=hook-runtime.d.ts.map
|
package/dist/cli/hook-runtime.js
CHANGED
|
@@ -106,7 +106,7 @@ export async function runHookWithStores(fn) {
|
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
/** Whether this session sits in the pilot's holdout arm; off at rate 0 and with no session id. */
|
|
109
|
-
export function inPilotHoldout(hippoRoot, tenantId, sessionId,
|
|
110
|
-
return sessionPilotArm(hippoRoot, tenantId, sessionId, write) === 'holdout';
|
|
109
|
+
export function inPilotHoldout(hippoRoot, tenantId, sessionId, opts) {
|
|
110
|
+
return sessionPilotArm(hippoRoot, tenantId, sessionId, opts.write) === 'holdout';
|
|
111
111
|
}
|
|
112
112
|
//# sourceMappingURL=hook-runtime.js.map
|
package/dist/cli/init.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { type CommandContext } from './flag-values.js';
|
|
2
|
-
export declare function handleInit({ hippoRoot, tenantId, flags }: CommandContext): void
|
|
2
|
+
export declare function handleInit({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
|
|
3
3
|
//# sourceMappingURL=init.d.ts.map
|
package/dist/cli/init.js
CHANGED
|
@@ -68,12 +68,12 @@ function initScannedRepo(repo, tenantId, globalRoot) {
|
|
|
68
68
|
return alreadyExists;
|
|
69
69
|
}
|
|
70
70
|
/** Seeds one scanned repo from git history and its agents' notes, unless --no-learn. */
|
|
71
|
-
function learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport) {
|
|
71
|
+
async function learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport) {
|
|
72
72
|
const repoHippo = path.join(repo, '.hippo');
|
|
73
73
|
let added = 0;
|
|
74
74
|
let lowInfo = 0;
|
|
75
75
|
if (learn && isGitRepo(repo)) {
|
|
76
|
-
const result = learnFromRepo(repoHippo, tenantId, repo, seedDays, path.basename(repo));
|
|
76
|
+
const result = await learnFromRepo(repoHippo, tenantId, repo, seedDays, path.basename(repo));
|
|
77
77
|
added = result.added;
|
|
78
78
|
lowInfo = result.lowInfo;
|
|
79
79
|
}
|
|
@@ -102,7 +102,7 @@ function printScanSummary(repoCount, totalLessons, totalLowInfo) {
|
|
|
102
102
|
(totalLowInfo > 0 ? `, ${totalLowInfo} low-information subject(s) dropped` : '') +
|
|
103
103
|
'.');
|
|
104
104
|
}
|
|
105
|
-
function cmdInitScan(scanDir, tenantId, flags) {
|
|
105
|
+
async function cmdInitScan(scanDir, tenantId, flags) {
|
|
106
106
|
const resolved = path.resolve(scanDir);
|
|
107
107
|
console.log(`Scanning ${resolved} for git repositories...\n`);
|
|
108
108
|
const repos = scanForGitRepos(resolved);
|
|
@@ -121,7 +121,7 @@ function cmdInitScan(scanDir, tenantId, flags) {
|
|
|
121
121
|
const learn = !flags['no-learn'];
|
|
122
122
|
for (const repo of repos) {
|
|
123
123
|
const alreadyExists = initScannedRepo(repo, tenantId, globalRoot);
|
|
124
|
-
const { added, lowInfo } = learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport);
|
|
124
|
+
const { added, lowInfo } = await learnScannedRepo(repo, tenantId, seedDays, learn, machine, agentImport);
|
|
125
125
|
totalLessons += added;
|
|
126
126
|
totalLowInfo += lowInfo;
|
|
127
127
|
const status = alreadyExists ? 'existing' : 'new';
|
|
@@ -153,12 +153,12 @@ function initGlobalOnly(flags) {
|
|
|
153
153
|
if (!flags['no-learn'])
|
|
154
154
|
printAgentImport(importUserMemories(globalRoot, { machine: currentMachine() }));
|
|
155
155
|
}
|
|
156
|
-
function seedFromGitHistory(hippoRoot, tenantId) {
|
|
156
|
+
async function seedFromGitHistory(hippoRoot, tenantId) {
|
|
157
157
|
if (!isGitRepo(process.cwd()))
|
|
158
158
|
return;
|
|
159
159
|
const seedDays = 30;
|
|
160
160
|
console.log(`\n Seeding memories from last ${seedDays} days of git history...`);
|
|
161
|
-
const { added, skipped } = learnFromRepo(hippoRoot, tenantId, process.cwd(), seedDays);
|
|
161
|
+
const { added, skipped } = await learnFromRepo(hippoRoot, tenantId, process.cwd(), seedDays);
|
|
162
162
|
if (added > 0) {
|
|
163
163
|
console.log(` Learned ${added} lessons from git (${skipped} duplicates skipped).`);
|
|
164
164
|
}
|
|
@@ -166,11 +166,11 @@ function seedFromGitHistory(hippoRoot, tenantId) {
|
|
|
166
166
|
console.log(` No matching commits found in git history.`);
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
|
-
export function handleInit({ hippoRoot, tenantId, flags }) {
|
|
169
|
+
export async function handleInit({ hippoRoot, tenantId, flags }) {
|
|
170
170
|
// Handle --scan mode
|
|
171
171
|
if (flags['scan']) {
|
|
172
172
|
const scanDir = stringFlag(flags, 'scan') ?? os.homedir();
|
|
173
|
-
cmdInitScan(scanDir, tenantId, flags);
|
|
173
|
+
await cmdInitScan(scanDir, tenantId, flags);
|
|
174
174
|
return;
|
|
175
175
|
}
|
|
176
176
|
if (flags['global']) {
|
|
@@ -199,7 +199,7 @@ export function handleInit({ hippoRoot, tenantId, flags }) {
|
|
|
199
199
|
const learn = !flags['no-learn'] && !skipLearnOnSharedStore(hippoRoot);
|
|
200
200
|
// Seed with git history on first init (unless --no-learn)
|
|
201
201
|
if (!alreadyExists && learn && !flags['global'])
|
|
202
|
-
seedFromGitHistory(hippoRoot, tenantId);
|
|
202
|
+
await seedFromGitHistory(hippoRoot, tenantId);
|
|
203
203
|
// Every run, not only the first: an agent's notes change between inits.
|
|
204
204
|
if (learn)
|
|
205
205
|
printAgentImport(importForStore(hippoRoot, { machine: currentMachine() }));
|
|
@@ -14,7 +14,7 @@ export interface ObjectListSpec<O, S extends string> {
|
|
|
14
14
|
}
|
|
15
15
|
export declare function listObjects<O, S extends string>(flags: CliFlags, spec: ObjectListSpec<O, S>): void;
|
|
16
16
|
/** The `<id>` after the subcommand; prints `usage` and exits 1 when it is missing. */
|
|
17
|
-
export declare function idArgOrExit(args: string[], usage: string, label: string
|
|
17
|
+
export declare function idArgOrExit(args: string[], usage: string, label: string): number;
|
|
18
18
|
export declare function foundOrExit<O>(found: O | null | undefined, noun: string, id: number): O;
|
|
19
19
|
/** How a kind is named in usage lines (`cmd`), in messages (`noun`) and in the invalid-id error (`idLabel`). */
|
|
20
20
|
export interface ObjectNames {
|
|
@@ -25,7 +25,7 @@ export interface ObjectNames {
|
|
|
25
25
|
/** `hippo <cmd> close <id>` for a kind whose close call returns the closed row. */
|
|
26
26
|
export declare function closeObject(args: string[], names: ObjectNames, close: (id: number) => {
|
|
27
27
|
id: number;
|
|
28
|
-
}
|
|
28
|
+
}): void;
|
|
29
29
|
interface LifecycleTail {
|
|
30
30
|
readonly changeSummary?: string | null;
|
|
31
31
|
readonly supersededBy: number | null;
|
package/dist/cli/object-verbs.js
CHANGED
|
@@ -29,13 +29,13 @@ export function listObjects(flags, spec) {
|
|
|
29
29
|
spec.printRow(o);
|
|
30
30
|
}
|
|
31
31
|
/** The `<id>` after the subcommand; prints `usage` and exits 1 when it is missing. */
|
|
32
|
-
export function idArgOrExit(args, usage, label
|
|
32
|
+
export function idArgOrExit(args, usage, label) {
|
|
33
33
|
const idRaw = args[1];
|
|
34
34
|
if (!idRaw) {
|
|
35
35
|
printError(usage);
|
|
36
36
|
throw new CliExit(1);
|
|
37
37
|
}
|
|
38
|
-
return
|
|
38
|
+
return parsePositiveId(idRaw, label);
|
|
39
39
|
}
|
|
40
40
|
export function foundOrExit(found, noun, id) {
|
|
41
41
|
if (!found) {
|
|
@@ -45,8 +45,8 @@ export function foundOrExit(found, noun, id) {
|
|
|
45
45
|
return found;
|
|
46
46
|
}
|
|
47
47
|
/** `hippo <cmd> close <id>` for a kind whose close call returns the closed row. */
|
|
48
|
-
export function closeObject(args, names, close
|
|
49
|
-
const id = idArgOrExit(args, `Usage: hippo ${names.cmd} close <id>`, names.idLabel
|
|
48
|
+
export function closeObject(args, names, close) {
|
|
49
|
+
const id = idArgOrExit(args, `Usage: hippo ${names.cmd} close <id>`, names.idLabel);
|
|
50
50
|
console.log(`${names.noun} #${close(id).id} closed.`);
|
|
51
51
|
}
|
|
52
52
|
/** The detail lines every `get` ends with. */
|
package/dist/cli/predictions.js
CHANGED
|
@@ -6,12 +6,11 @@ import { printError } from './output.js';
|
|
|
6
6
|
import { parseListLimit, stringFlag } from './flag-values.js';
|
|
7
7
|
import { requireInit } from './shared.js';
|
|
8
8
|
import { foundOrExit, idArgOrExit, requireStatus } from './object-verbs.js';
|
|
9
|
-
import { parseObjectId } from './lenient-id.js';
|
|
10
9
|
import { CliExit } from './exit.js';
|
|
11
10
|
const BASERATE_DECIMALS = 3;
|
|
12
11
|
const PREDICTION_NOUN = 'Prediction';
|
|
13
12
|
async function predictClose(ctx, args, flags) {
|
|
14
|
-
const id = idArgOrExit(args, 'Usage: hippo predict close <id> --state <closed|closed-unknown> [--actual <v>] [--note "..."]', 'prediction'
|
|
13
|
+
const id = idArgOrExit(args, 'Usage: hippo predict close <id> --state <closed|closed-unknown> [--actual <v>] [--note "..."]', 'prediction');
|
|
15
14
|
const stateRaw = (stringFlag(flags, 'state') ?? '').trim();
|
|
16
15
|
// SAFETY: Set.has only compares by value, so a string outside the closure states is a plain miss.
|
|
17
16
|
if (!VALID_CLOSURE_STATES.has(stateRaw) || stateRaw === 'open') {
|
|
@@ -77,7 +76,7 @@ async function predictList(ctx, flags) {
|
|
|
77
76
|
}
|
|
78
77
|
}
|
|
79
78
|
async function predictShow(ctx, args) {
|
|
80
|
-
const id = idArgOrExit(args, 'Usage: hippo predict show <id>', 'prediction'
|
|
79
|
+
const id = idArgOrExit(args, 'Usage: hippo predict show <id>', 'prediction');
|
|
81
80
|
const pred = foundOrExit(await predictionsApi.predictionById(ctx, id), PREDICTION_NOUN, id);
|
|
82
81
|
console.log(`Prediction #${pred.id}`);
|
|
83
82
|
console.log(` class: ${pred.classTag}`);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/** Fault-isolated like the project tag repair: a failure warns, leaves the store unmarked and runs again next time. */
|
|
2
|
-
export declare function repairQualityOnceAt(root: string, tenantId: string): void
|
|
2
|
+
export declare function repairQualityOnceAt(root: string, tenantId: string): Promise<void>;
|
|
3
3
|
//# sourceMappingURL=quality-repair-once.d.ts.map
|
|
@@ -5,9 +5,9 @@ import { getGlobalRoot } from '../sharing/global-store.js';
|
|
|
5
5
|
import { repairMemoryQualityOnce } from '../api/audit.js';
|
|
6
6
|
import { cliApiContext } from './api-context.js';
|
|
7
7
|
/** Fault-isolated like the project tag repair: a failure warns, leaves the store unmarked and runs again next time. */
|
|
8
|
-
export function repairQualityOnceAt(root, tenantId) {
|
|
8
|
+
export async function repairQualityOnceAt(root, tenantId) {
|
|
9
9
|
try {
|
|
10
|
-
const result = repairMemoryQualityOnce(cliApiContext(root, tenantId));
|
|
10
|
+
const result = await repairMemoryQualityOnce(cliApiContext(root, tenantId));
|
|
11
11
|
if (result === null)
|
|
12
12
|
return;
|
|
13
13
|
if (!result.supported) {
|
package/dist/cli/refine-llm.js
CHANGED
|
@@ -61,6 +61,7 @@ function describeRefineFailure(failure) {
|
|
|
61
61
|
case 'request': return `refine: request failed: ${failure.message}`;
|
|
62
62
|
case 'http': return `refine: API answered HTTP ${failure.status}${failure.detail ? `: ${failure.detail}` : ''}`;
|
|
63
63
|
case 'unreadable': return `refine: unreadable response: ${failure.message}`;
|
|
64
|
+
case 'empty': return 'refine: response held no text';
|
|
64
65
|
}
|
|
65
66
|
}
|
|
66
67
|
function isConsolidated(entry) {
|
|
@@ -121,7 +122,7 @@ async function refineOneEntry(ctx, reach, entry, opts, result) {
|
|
|
121
122
|
result.details.push({ id: entry.id, status: 'refined', reason: 'dry-run (no write)' });
|
|
122
123
|
return;
|
|
123
124
|
}
|
|
124
|
-
storeRefinement(cliApiContext(ctx.hippoRoot, entry.
|
|
125
|
+
storeRefinement(cliApiContext(ctx.hippoRoot, entry.tenant_id), entry, refined);
|
|
125
126
|
result.refined++;
|
|
126
127
|
result.details.push({ id: entry.id, status: 'refined' });
|
|
127
128
|
}
|
package/dist/cli/remember.js
CHANGED
|
@@ -97,7 +97,7 @@ async function cmdRemember(hippoRoot, tenantId, text, flags) {
|
|
|
97
97
|
const { requested: requestedTags, all: allTags } = rememberTags(flags, process.cwd());
|
|
98
98
|
const envelope = parseRememberEnvelope(flags);
|
|
99
99
|
const ctx = cliApiContext(targetRoot, tenantId);
|
|
100
|
-
const outcome = api.rememberLocally(ctx, {
|
|
100
|
+
const outcome = await api.rememberLocally(ctx, {
|
|
101
101
|
content: text,
|
|
102
102
|
kind: envelope.kind,
|
|
103
103
|
scope: envelope.scope ?? undefined,
|
|
@@ -173,7 +173,7 @@ async function cmdSupersede(hippoRoot, tenantId, oldId, newContent, flags) {
|
|
|
173
173
|
};
|
|
174
174
|
let newId;
|
|
175
175
|
try {
|
|
176
|
-
({ newId } = api.supersede(cliApiContext(hippoRoot, tenantId), oldId, newContent, overrides));
|
|
176
|
+
({ newId } = await api.supersede(cliApiContext(hippoRoot, tenantId), oldId, newContent, overrides));
|
|
177
177
|
}
|
|
178
178
|
catch (err) {
|
|
179
179
|
if (err instanceof NotFoundError)
|
|
@@ -205,7 +205,7 @@ function traceTags(flags) {
|
|
|
205
205
|
? [String(rawTags)]
|
|
206
206
|
: [];
|
|
207
207
|
}
|
|
208
|
-
function cmdTraceRecord(hippoRoot, tenantId, flags) {
|
|
208
|
+
async function cmdTraceRecord(hippoRoot, tenantId, flags) {
|
|
209
209
|
requireInit(hippoRoot);
|
|
210
210
|
const task = String(flags['task'] ?? '').trim();
|
|
211
211
|
const stepsJson = String(flags['steps'] ?? '').trim();
|
|
@@ -227,7 +227,7 @@ function cmdTraceRecord(hippoRoot, tenantId, flags) {
|
|
|
227
227
|
steps,
|
|
228
228
|
outcome,
|
|
229
229
|
});
|
|
230
|
-
const { id } = api.remember(cliApiContext(hippoRoot, tenantId), {
|
|
230
|
+
const { id } = await api.remember(cliApiContext(hippoRoot, tenantId), {
|
|
231
231
|
content,
|
|
232
232
|
tags,
|
|
233
233
|
local: {
|
|
@@ -427,7 +427,7 @@ export async function handleSupersede({ hippoRoot, tenantId, args, flags }) {
|
|
|
427
427
|
export async function handleTrace({ hippoRoot, tenantId, args, flags }) {
|
|
428
428
|
const sub = args[0] ? String(args[0]) : '';
|
|
429
429
|
if (sub === 'record') {
|
|
430
|
-
cmdTraceRecord(hippoRoot, tenantId, flags);
|
|
430
|
+
await cmdTraceRecord(hippoRoot, tenantId, flags);
|
|
431
431
|
return;
|
|
432
432
|
}
|
|
433
433
|
if (!sub) {
|
package/dist/cli/serve.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// Long-running verbs: `hippo dashboard`, `hippo mcp` and `hippo serve`.
|
|
2
2
|
import { installCrashHandlers } from '../util/crash-handlers.js';
|
|
3
|
-
import { envAllowKeylessLocal, envPort, envRequireAuth, envTlsCert, envTlsKey } from '../util/env.js';
|
|
3
|
+
import { envAllowKeylessLocal, envKeylessLocalRole, envPort, envRequireAuth, envTlsCert, envTlsKey } from '../util/env.js';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import { printError } from './output.js';
|
|
7
|
-
import { stringFlagOrExit, stringFlag, numberFlag } from './flag-values.js';
|
|
7
|
+
import { flagIsTrue, stringFlagOrExit, stringFlag, numberFlag } from './flag-values.js';
|
|
8
8
|
import { requireInit } from './shared.js';
|
|
9
9
|
import { errorMessage } from '../util/log.js';
|
|
10
10
|
import { CliExit } from './exit.js';
|
|
@@ -52,7 +52,10 @@ function keyRuleLine() {
|
|
|
52
52
|
if (envRequireAuth())
|
|
53
53
|
return 'every request needs an API key (HIPPO_REQUIRE_AUTH=1)';
|
|
54
54
|
if (envAllowKeylessLocal()) {
|
|
55
|
-
|
|
55
|
+
const role = envKeylessLocalRole() === 'admin'
|
|
56
|
+
? 'act as host admin (HIPPO_ALLOW_KEYLESS_LOCAL=1, HIPPO_KEYLESS_LOCAL_ROLE=admin)'
|
|
57
|
+
: 'act as a member (HIPPO_ALLOW_KEYLESS_LOCAL=1; HIPPO_KEYLESS_LOCAL_ROLE=admin opens sleep and the quarantine routes)';
|
|
58
|
+
return `requests from this machine need no API key and ${role}; unset HIPPO_ALLOW_KEYLESS_LOCAL to require a key on every request`;
|
|
56
59
|
}
|
|
57
60
|
return 'every request needs an API key: mint one with `hippo auth create` and send it as "Authorization: Bearer <key>" ' +
|
|
58
61
|
'(the hippo CLI reads HIPPO_API_KEY). To let requests from this machine in without a key, start with HIPPO_ALLOW_KEYLESS_LOCAL=1';
|
|
@@ -68,7 +71,9 @@ export async function handleServe({ hippoRoot, flags }) {
|
|
|
68
71
|
const host = stringFlag(flags, 'host') ?? DEFAULT_SERVER_HOST;
|
|
69
72
|
const tls = readTlsFiles(flags);
|
|
70
73
|
const { serve } = await import('../server.js');
|
|
71
|
-
|
|
74
|
+
// Unset rather than false without the flag, so HIPPO_ALLOW_CLEARTEXT=1 still applies.
|
|
75
|
+
const allowCleartext = flagIsTrue(flags, 'allow-cleartext') || undefined;
|
|
76
|
+
const handle = await serve({ hippoRoot, port, host, handleSignals: true, tls, allowCleartext });
|
|
72
77
|
console.log(`hippo serve listening on ${handle.url} (pid ${process.pid})`);
|
|
73
78
|
console.log(keyRuleLine());
|
|
74
79
|
console.log(`pidfile: ${path.join(hippoRoot, 'server.pid')}`);
|
|
@@ -3,10 +3,6 @@ import { type CliFlags, type CommandContext } from './flag-values.js';
|
|
|
3
3
|
* The child logs to a file that the next SessionStart reads via `hippo last-sleep`. */
|
|
4
4
|
export declare function handleSessionEnd({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
|
|
5
5
|
export declare function handleSessionEndWorker({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
|
|
6
|
-
/** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
|
|
7
|
-
export declare function quoteCmdArg(arg: string): string;
|
|
8
|
-
/** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
|
|
9
|
-
export declare function cmdShimArgs(shimPath: string, forwardArgs: readonly string[]): string[];
|
|
10
6
|
export declare function handleCodexRun({ hippoRoot, tenantId, args }: CommandContext): void;
|
|
11
7
|
export declare function cmdCodexSessionEndWorker(hippoRoot: string, tenantId: string, flags: CliFlags): Promise<void>;
|
|
12
8
|
export declare function handleCodexSessionEndWorker({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
|
|
@@ -21,9 +21,10 @@ import { isStringValue, readSessionEnd, readVscodeStop } from '../core/capture-c
|
|
|
21
21
|
import { loadConfig } from '../core/config.js';
|
|
22
22
|
import { autoSleepDue } from '../api/auto-sleep.js';
|
|
23
23
|
import { COMPACTION_DB_WAIT_MS } from '../core/compaction-timing.js';
|
|
24
|
-
import {
|
|
24
|
+
import { compactResumeBlock, sessionEndWork as runSessionEnd } from '../api/session-end.js';
|
|
25
25
|
import { normaliseHookPayload, readHookStdin, readStdinBounded } from './stdin.js';
|
|
26
26
|
import { errorMessage, log } from '../util/log.js';
|
|
27
|
+
import { cmdShimArgs } from '../util/spawn-argv.js';
|
|
27
28
|
import { bookLedgerTurn } from '../api/ledger-db.js';
|
|
28
29
|
import { flushDeliveryRecorder, startDeliveryRecorder, startToolFailureRecorder } from '../api/prompt-hook.js';
|
|
29
30
|
import { printError } from './output.js';
|
|
@@ -52,7 +53,7 @@ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
|
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
// A compaction follows a prompt or SessionStart that booked the arm, so this only reads it.
|
|
55
|
-
if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, false)) {
|
|
56
|
+
if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, { write: false })) {
|
|
56
57
|
suppressOutput = true;
|
|
57
58
|
rec?.disabled();
|
|
58
59
|
}
|
|
@@ -75,8 +76,7 @@ function restoreCompactSnapshot(hippoRoot, tenantId, payloadSessionId, rec) {
|
|
|
75
76
|
return;
|
|
76
77
|
// Printed in one write so the ledger books exactly the text the model is handed.
|
|
77
78
|
console.log(text);
|
|
78
|
-
rec?.delivered({ state: 'sent', emittedText: `${text}
|
|
79
|
-
` });
|
|
79
|
+
rec?.delivered({ state: 'sent', emittedText: `${text}\n` });
|
|
80
80
|
bookLedgerTurn(hippoRoot, {
|
|
81
81
|
uses: [{
|
|
82
82
|
tenantId, sessionId: payloadSessionId, surface: 'compact_resume', event: 'inject', items: 1, tokens: estimateTokens(text),
|
|
@@ -111,20 +111,15 @@ export async function handleSessionEnd({ hippoRoot, tenantId, flags }) {
|
|
|
111
111
|
const named = input?.transcriptPath ?? null;
|
|
112
112
|
const transcriptPath = (named !== null && fs.existsSync(named) ? named : null)
|
|
113
113
|
?? (runtime === 'copilot' && sessionId ? copilotTranscriptFor(sessionId) : null);
|
|
114
|
+
const worker = { logFile, transcriptPath, sessionId, turn };
|
|
114
115
|
try {
|
|
115
|
-
spawnSessionEndWorker(sessionEndWorkerArgs(
|
|
116
|
+
spawnSessionEndWorker(sessionEndWorkerArgs(worker));
|
|
116
117
|
}
|
|
117
118
|
catch (err) {
|
|
118
119
|
log.debug(`session-end: the worker did not spawn, running inline: ${errorMessage(err)}`);
|
|
119
120
|
// Inline is the last resort, handed what the child's argv would have carried.
|
|
120
|
-
if (logFile)
|
|
121
|
-
flags['log-file'] = logFile;
|
|
122
|
-
if (transcriptPath)
|
|
123
|
-
flags['transcript'] = transcriptPath;
|
|
124
|
-
if (sessionId)
|
|
125
|
-
flags['session-id'] = sessionId;
|
|
126
121
|
try {
|
|
127
|
-
await cmdSessionEndWorker(root, tenantId, flags);
|
|
122
|
+
await cmdSessionEndWorker(root, tenantId, inlineWorkerFlags(flags, worker));
|
|
128
123
|
}
|
|
129
124
|
finally {
|
|
130
125
|
await runHookWithStores(() => flushDeliveryRecorder(rec));
|
|
@@ -142,7 +137,8 @@ function sessionEndInput(stdinText, timedOut, runtime) {
|
|
|
142
137
|
log.debug(`session-end: ${receipt.reason}`);
|
|
143
138
|
return null;
|
|
144
139
|
}
|
|
145
|
-
function sessionEndWorkerArgs(
|
|
140
|
+
function sessionEndWorkerArgs(o) {
|
|
141
|
+
const { logFile, transcriptPath, sessionId, turn } = o;
|
|
146
142
|
const workerArgs = [process.argv[1], '__session-end-worker'];
|
|
147
143
|
if (logFile)
|
|
148
144
|
workerArgs.push('--log-file', logFile);
|
|
@@ -154,6 +150,26 @@ function sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn) {
|
|
|
154
150
|
workerArgs.push('--turn');
|
|
155
151
|
return workerArgs;
|
|
156
152
|
}
|
|
153
|
+
/** The flags the detached worker would parse from its argv, so the inline run sees what the child would have; the hook's own flags fill the gaps. */
|
|
154
|
+
function inlineWorkerFlags(flags, w) {
|
|
155
|
+
const out = {};
|
|
156
|
+
const keep = (name, value) => {
|
|
157
|
+
if (value)
|
|
158
|
+
out[name] = value;
|
|
159
|
+
};
|
|
160
|
+
keep('log-file', w.logFile ?? flags['log-file']);
|
|
161
|
+
keep('transcript', w.transcriptPath ?? flags['transcript']);
|
|
162
|
+
keep('session-id', w.sessionId ?? flags['session-id']);
|
|
163
|
+
if (flagIsTrue(flags, 'turn'))
|
|
164
|
+
out['turn'] = true;
|
|
165
|
+
if (flagIsTrue(flags, 'dry-run'))
|
|
166
|
+
out['dry-run'] = true;
|
|
167
|
+
if (flagIsTrue(flags, 'no-learn'))
|
|
168
|
+
out['no-learn'] = true;
|
|
169
|
+
if (flagIsTrue(flags, 'no-share'))
|
|
170
|
+
out['no-share'] = true;
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
157
173
|
function spawnSessionEndWorker(workerArgs) {
|
|
158
174
|
const child = spawn(process.execPath, workerArgs, {
|
|
159
175
|
detached: true,
|
|
@@ -176,48 +192,37 @@ async function cmdSessionEndWorker(hippoRoot, tenantId, flags) {
|
|
|
176
192
|
export function handleSessionEndWorker({ hippoRoot, tenantId, flags }) {
|
|
177
193
|
return cmdSessionEndWorker(hippoRoot, tenantId, flags);
|
|
178
194
|
}
|
|
179
|
-
|
|
195
|
+
function sessionEndWork(hippoRoot, tenantId, flags, mode) {
|
|
180
196
|
const transcriptPath = stringFlag(flags, 'transcript');
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const flushRereadLog = () => { for (const line of rereadLog.splice(0))
|
|
187
|
-
appendSessionEndCloseLog(closeLogFile, line); };
|
|
188
|
-
process.once('exit', flushRereadLog);
|
|
189
|
-
// Like the other hooks: project store, else global; a folder with neither must not get one made.
|
|
190
|
-
const store = hookStoreRoot(hippoRoot);
|
|
191
|
-
if (!isInitialized(store)) {
|
|
192
|
-
appendSessionEndCloseLog(closeLogFile, 'skip: no hippo store for this folder or globally', { startFresh: true });
|
|
193
|
-
flushRereadLog();
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
if (mode === 'turn' && closeSessionId)
|
|
197
|
-
await sleepIfDue(hippoRoot, tenantId, flags, closeLogFile, transcriptPath, closeSessionId);
|
|
198
|
-
else
|
|
199
|
-
await sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
|
|
200
|
-
flushRereadLog();
|
|
201
|
-
const digestLog = (message) => appendSessionEndCloseLog(closeLogFile, message);
|
|
202
|
-
const scan = transcriptPath ? readSessionScan(transcriptPath, digestLog) : null;
|
|
203
|
-
const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
|
|
204
|
-
if (mode === 'turn')
|
|
205
|
-
captureNewTurns(transcriptPath, closeSessionId, scan, capture, digestLog);
|
|
206
|
-
else
|
|
207
|
-
capture(scan?.turns);
|
|
208
|
-
recordSessionDigest(hippoRoot, scan, {
|
|
209
|
-
key: closeSessionId || path.basename(transcriptPath ?? '', '.jsonl'),
|
|
197
|
+
const logFile = stringFlag(flags, 'log-file') ?? null;
|
|
198
|
+
const sessionId = stringFlag(flags, 'session-id') ?? null;
|
|
199
|
+
return runSessionEnd({
|
|
200
|
+
mode,
|
|
201
|
+
hippoRoot,
|
|
210
202
|
tenantId,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
203
|
+
sessionId,
|
|
204
|
+
transcriptPath,
|
|
205
|
+
contextFor: (root) => cliApiContext(root, tenantId),
|
|
206
|
+
storeRoot: () => hookStoreRoot(hippoRoot),
|
|
207
|
+
log: (line, opts) => appendSessionEndCloseLog(logFile, line, opts),
|
|
208
|
+
sleep: () => (mode === 'turn' && sessionId
|
|
209
|
+
? sleepIfDue(hippoRoot, tenantId, flags, logFile, transcriptPath, sessionId)
|
|
210
|
+
: sleepProjectStore(hippoRoot, tenantId, flags, logFile, transcriptPath)),
|
|
211
|
+
readScan: (log) => (transcriptPath ? readSessionScan(transcriptPath, log) : null),
|
|
212
|
+
capture: (store, scan) => {
|
|
213
|
+
const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
|
|
214
|
+
if (mode === 'turn')
|
|
215
|
+
captureNewTurns(transcriptPath, sessionId, scan, capture, (line) => appendSessionEndCloseLog(logFile, line));
|
|
216
|
+
else
|
|
217
|
+
capture(scan?.turns);
|
|
218
|
+
},
|
|
219
|
+
digest: (scan, log) => recordSessionDigest(hippoRoot, scan, {
|
|
220
|
+
key: sessionId || path.basename(transcriptPath ?? '', '.jsonl'),
|
|
221
|
+
tenantId,
|
|
222
|
+
log,
|
|
223
|
+
}),
|
|
224
|
+
workingState: (log) => (transcriptPath ? transcriptWorkingState(transcriptPath, log) : null),
|
|
219
225
|
evidence: () => collectHandoffEvidence(process.cwd(), 'unknown'),
|
|
220
|
-
log: closeLog,
|
|
221
226
|
});
|
|
222
227
|
}
|
|
223
228
|
async function sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath) {
|
|
@@ -304,20 +309,6 @@ function loadCodexWrapperMetadata() {
|
|
|
304
309
|
// SAFETY: the file is the one installCodexWrapper wrote; handleCodexRun reads only logFile and realCodexPath from it.
|
|
305
310
|
return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
|
|
306
311
|
}
|
|
307
|
-
/** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
|
|
308
|
-
export function quoteCmdArg(arg) {
|
|
309
|
-
if (arg.length === 0)
|
|
310
|
-
return '""';
|
|
311
|
-
if (!/[ \t"&()^<>|%!]/.test(arg))
|
|
312
|
-
return arg;
|
|
313
|
-
return `"${arg.replace(/"/g, '""').replace(/%/g, '"^%"')}"`;
|
|
314
|
-
}
|
|
315
|
-
/** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
|
|
316
|
-
export function cmdShimArgs(shimPath, forwardArgs) {
|
|
317
|
-
const command = `"${shimPath}"${forwardArgs.length > 0 ? ` ${forwardArgs.map(quoteCmdArg).join(' ')}` : ''}`;
|
|
318
|
-
// The line is already quoted for cmd.exe, so Node must not quote it again; /s strips the outer pair.
|
|
319
|
-
return ['/d', '/v:off', '/s', '/c', `"${command}"`];
|
|
320
|
-
}
|
|
321
312
|
function spawnRealCodex(realCodexPath, forwardArgs, cwd) {
|
|
322
313
|
const ext = path.extname(realCodexPath).toLowerCase();
|
|
323
314
|
if (process.platform === 'win32' && ext === '.ps1') {
|
package/dist/cli/setup.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CommandContext } from './flag-values.js';
|
|
2
2
|
export declare function handleHook({ args }: CommandContext): void;
|
|
3
3
|
export declare function handleSetup({ flags }: CommandContext): void;
|
|
4
|
-
export declare function handleDailyRunner({ tenantId }: CommandContext): void
|
|
4
|
+
export declare function handleDailyRunner({ tenantId }: CommandContext): Promise<void>;
|
|
5
5
|
//# sourceMappingURL=setup.d.ts.map
|
package/dist/cli/setup.js
CHANGED
|
@@ -486,14 +486,14 @@ function dailyStepFailure(err, timeoutMs) {
|
|
|
486
486
|
return `timed out after ${timeoutMs} ms and was stopped`;
|
|
487
487
|
return errorMessage(err);
|
|
488
488
|
}
|
|
489
|
-
export function handleDailyRunner({ tenantId }) {
|
|
489
|
+
export async function handleDailyRunner({ tenantId }) {
|
|
490
490
|
const globalRoot = getGlobalRoot();
|
|
491
491
|
// No workspace sleep ever opens the global store, yet hooks in folders without a store compact into it.
|
|
492
492
|
if (isInitialized(globalRoot)) {
|
|
493
493
|
const finished = replayCompactionsAt(globalRoot, (message) => log.warn(`compaction replay: ${message}`));
|
|
494
494
|
if (finished > 0)
|
|
495
495
|
console.log(`Finished saving ${finished} compaction${finished === 1 ? '' : 's'} left over in the global store.`);
|
|
496
|
-
repairQualityOnceAt(globalRoot, tenantId);
|
|
496
|
+
await repairQualityOnceAt(globalRoot, tenantId);
|
|
497
497
|
}
|
|
498
498
|
printAgentImport(importUserMemories(globalRoot, { machine: currentMachine() }), '');
|
|
499
499
|
const workspaces = listRegisteredWorkspaces(globalRoot);
|
package/dist/cli/shared.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ interface LearnFromRepoResult {
|
|
|
17
17
|
skipped: number;
|
|
18
18
|
lowInfo: number;
|
|
19
19
|
}
|
|
20
|
-
export declare function learnFromRepo(hippoRoot: string, tenantId: string, repoPath: string, days: number, label?: string): LearnFromRepoResult
|
|
20
|
+
export declare function learnFromRepo(hippoRoot: string, tenantId: string, repoPath: string, days: number, label?: string): Promise<LearnFromRepoResult>;
|
|
21
21
|
export declare function resolveAuthRoot(hippoRoot: string, flags: CliFlags): string;
|
|
22
22
|
export {};
|
|
23
23
|
//# sourceMappingURL=shared.d.ts.map
|
package/dist/cli/shared.js
CHANGED
|
@@ -83,9 +83,9 @@ export function skipLearnOnSharedStore(hippoRoot) {
|
|
|
83
83
|
console.log("Shared store: skipped learning from this account's git commits and coding agents' own memories.");
|
|
84
84
|
return true;
|
|
85
85
|
}
|
|
86
|
-
export function learnFromRepo(hippoRoot, tenantId, repoPath, days, label) {
|
|
86
|
+
export async function learnFromRepo(hippoRoot, tenantId, repoPath, days, label) {
|
|
87
87
|
const prefix = label ? `[${label}] ` : '';
|
|
88
|
-
const result = learn(cliApiContext(hippoRoot, tenantId), { repoPath, days, profile: CLI_LEARN });
|
|
88
|
+
const result = await learn(cliApiContext(hippoRoot, tenantId), { repoPath, days, profile: CLI_LEARN });
|
|
89
89
|
if (result.status === 'not-a-repo') {
|
|
90
90
|
console.log(`${prefix}No git history found (or not a git repository).`);
|
|
91
91
|
return { added: 0, skipped: 0, lowInfo: 0 };
|
package/dist/cli/sleep.js
CHANGED
|
@@ -80,7 +80,7 @@ async function cmdSleepCore(hippoRoot, tenantId, flags) {
|
|
|
80
80
|
else if (learn) {
|
|
81
81
|
const config = loadConfig(hippoRoot);
|
|
82
82
|
if (config.autoLearnOnSleep && isGitRepo(process.cwd())) {
|
|
83
|
-
const { added } = learnFromRepo(hippoRoot, tenantId, process.cwd(), 1);
|
|
83
|
+
const { added } = await learnFromRepo(hippoRoot, tenantId, process.cwd(), 1);
|
|
84
84
|
if (added > 0)
|
|
85
85
|
console.log(`Auto-learned ${added} lessons from today's git commits.`);
|
|
86
86
|
}
|
|
@@ -101,7 +101,7 @@ async function cmdSleepCore(hippoRoot, tenantId, flags) {
|
|
|
101
101
|
if (finished > 0)
|
|
102
102
|
console.log(`Finished saving ${finished} compaction${finished === 1 ? '' : 's'} left over from earlier sessions.`);
|
|
103
103
|
repairProjectTagsOnce(hippoRoot, tenantId);
|
|
104
|
-
repairQualityOnceAt(hippoRoot, tenantId);
|
|
104
|
+
await repairQualityOnceAt(hippoRoot, tenantId);
|
|
105
105
|
}
|
|
106
106
|
// Phase 2-6: Pure-storage pipeline (consolidate + dedup + audit + share + ambient).
|
|
107
107
|
const ctx = cliApiContext(hippoRoot, tenantId);
|
package/dist/cli/transfer.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type CommandContext } from './flag-values.js';
|
|
2
|
-
export declare function handleLearn({ hippoRoot, tenantId, flags }: CommandContext): void
|
|
3
|
-
export declare function handleImport({ hippoRoot, tenantId, args, flags }: CommandContext): void
|
|
2
|
+
export declare function handleLearn({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
|
|
3
|
+
export declare function handleImport({ hippoRoot, tenantId, args, flags }: CommandContext): Promise<void>;
|
|
4
4
|
export declare function handleSync({ hippoRoot, flags }: CommandContext): void;
|
|
5
|
-
export declare function handleWatch({ hippoRoot, tenantId, args }: CommandContext): Promise<void>;
|
|
5
|
+
export declare function handleWatch({ hippoRoot, tenantId, args, flags }: CommandContext): Promise<void>;
|
|
6
6
|
export declare function handlePromote({ hippoRoot, tenantId, args }: CommandContext): Promise<void>;
|
|
7
7
|
export declare function handleShare({ hippoRoot, tenantId, args, flags }: CommandContext): Promise<void>;
|
|
8
8
|
export declare function handlePeers({ tenantId, flags }: CommandContext): void;
|