hippo-memory 1.7.2 → 1.7.4
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 +26 -0
- package/dist/api.d.ts +17 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +142 -110
- package/dist/api.js.map +1 -1
- package/dist/cli.js +14 -126
- package/dist/cli.js.map +1 -1
- package/dist/goals.d.ts +56 -0
- package/dist/goals.d.ts.map +1 -1
- package/dist/goals.js +169 -36
- package/dist/goals.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +38 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +11 -0
- package/dist/server.js.map +1 -1
- package/dist/src/api.js +142 -110
- package/dist/src/api.js.map +1 -1
- package/dist/src/cli.js +14 -126
- package/dist/src/cli.js.map +1 -1
- package/dist/src/goals.js +169 -36
- package/dist/src/goals.js.map +1 -1
- package/dist/src/mcp/server.js +38 -1
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/server.js +11 -0
- package/dist/src/server.js.map +1 -1
- package/dist/src/store.js +17 -12
- package/dist/src/store.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/store.d.ts +8 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +17 -12
- package/dist/store.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/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 +1 -1
package/dist/cli.js
CHANGED
|
@@ -41,7 +41,7 @@ import { loadPhysicsState, resetAllPhysicsState } from './physics-state.js';
|
|
|
41
41
|
import { computeSystemEnergy, vecNorm } from './physics.js';
|
|
42
42
|
import { loadConfig } from './config.js';
|
|
43
43
|
import { openHippoDb, closeHippoDb } from './db.js';
|
|
44
|
-
import {
|
|
44
|
+
import { pushGoal, getActiveGoals, completeGoal, suspendGoal, resumeGoal, applyGoalStackBoost } from './goals.js';
|
|
45
45
|
import { rowToGoal } from './goals.js';
|
|
46
46
|
import { captureError, extractLessons, deduplicateLesson, runWatched, fetchGitLog, isGitRepo, } from './autolearn.js';
|
|
47
47
|
import { extractInvalidationTarget, invalidateMatching } from './invalidation.js';
|
|
@@ -825,137 +825,23 @@ async function cmdRecall(hippoRoot, query, flags) {
|
|
|
825
825
|
.map((r) => (r.entry.tags?.includes(goalTag) ? { ...r, score: r.score * 1.5 } : r))
|
|
826
826
|
.sort((a, b) => b.score - a.score);
|
|
827
827
|
}
|
|
828
|
-
// dlPFC depth (B3, v0.38
|
|
829
|
-
// --session-id flag) and the
|
|
830
|
-
//
|
|
831
|
-
//
|
|
832
|
-
//
|
|
833
|
-
//
|
|
834
|
-
// Runs AFTER the explicit `--goal <tag>` block so an explicit flag always
|
|
835
|
-
// wins: if the user passed `--goal X`, this block is skipped entirely
|
|
836
|
-
// (gated on `goalTag === ''`).
|
|
837
|
-
//
|
|
838
|
-
// db-handle note (plan-eng-review fix #5): the surrounding cmdRecall path
|
|
839
|
-
// does NOT keep an open db handle in scope at this point — earlier search
|
|
840
|
-
// helpers (loadSearchEntries, hybridSearch, ...) each open and close their
|
|
841
|
-
// own short-lived handles. Reusing isn't practical here; we open a fresh
|
|
842
|
-
// short-lived handle for this block, mirroring the existing CLI pattern
|
|
843
|
-
// (e.g. emitCliAudit). Closed in `finally`.
|
|
828
|
+
// dlPFC depth (B3, v0.38; lifted v1.7.4 into applyGoalStackBoost). When
|
|
829
|
+
// HIPPO_SESSION_ID is set (env or --session-id flag) and the
|
|
830
|
+
// (tenant, session) has active goals, the helper boosts memories whose tags
|
|
831
|
+
// overlap any active goal's name and logs (memory, goal) pairs into
|
|
832
|
+
// goal_recall_log. Runs AFTER the explicit `--goal <tag>` block so an
|
|
833
|
+
// explicit flag always wins (gated on `goalTag === ''`).
|
|
844
834
|
const sessionId = (flags['session-id'] !== undefined
|
|
845
835
|
? String(flags['session-id'])
|
|
846
836
|
: process.env.HIPPO_SESSION_ID ?? '').trim();
|
|
847
837
|
if (sessionId && goalTag === '') {
|
|
848
|
-
// Use the same tenant as the recall path — see cmdRecall:778.
|
|
849
|
-
const tenantIdForGoals = tenantId;
|
|
850
838
|
const dbForGoals = openHippoDb(hippoRoot);
|
|
851
839
|
try {
|
|
852
|
-
|
|
840
|
+
results = applyGoalStackBoost(dbForGoals, results, {
|
|
853
841
|
sessionId,
|
|
854
|
-
tenantId
|
|
842
|
+
tenantId,
|
|
843
|
+
limit,
|
|
855
844
|
});
|
|
856
|
-
if (active.length > 0) {
|
|
857
|
-
const goalsByTag = new Map(active.map((g) => [g.goalName, g]));
|
|
858
|
-
// Task 7: load retrieval_policy rows for active goals so per-policy
|
|
859
|
-
// multipliers can compose onto the base goal-tag boost. The composed
|
|
860
|
-
// result is hard-capped at MAX_FINAL_MULTIPLIER (3.0x) BEFORE applying
|
|
861
|
-
// to score — even an `errorPriority: 9.0` policy cannot exceed 3.0x.
|
|
862
|
-
const policiesByGoalId = new Map();
|
|
863
|
-
for (const g of active) {
|
|
864
|
-
if (!g.retrievalPolicyId)
|
|
865
|
-
continue;
|
|
866
|
-
const row = dbForGoals.prepare(`
|
|
867
|
-
SELECT id, goal_id, policy_type, weight_schema_fit, weight_recency, weight_outcome, error_priority
|
|
868
|
-
FROM retrieval_policy WHERE id = ?
|
|
869
|
-
`).get(g.retrievalPolicyId);
|
|
870
|
-
if (row) {
|
|
871
|
-
policiesByGoalId.set(g.id, {
|
|
872
|
-
id: row.id,
|
|
873
|
-
goalId: row.goal_id,
|
|
874
|
-
policyType: row.policy_type,
|
|
875
|
-
weightSchemaFit: row.weight_schema_fit,
|
|
876
|
-
weightRecency: row.weight_recency,
|
|
877
|
-
weightOutcome: row.weight_outcome,
|
|
878
|
-
errorPriority: row.error_priority,
|
|
879
|
-
});
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
results = results
|
|
883
|
-
.map((r) => {
|
|
884
|
-
const tags = r.entry.tags ?? [];
|
|
885
|
-
const matches = tags.filter((t) => goalsByTag.has(t));
|
|
886
|
-
if (matches.length === 0)
|
|
887
|
-
return r;
|
|
888
|
-
// Base 2.0x for first match, +0.5x per additional, capped at 3.0x.
|
|
889
|
-
let multiplier = Math.min(2.0 + 0.5 * (matches.length - 1), MAX_FINAL_MULTIPLIER);
|
|
890
|
-
// Compose per-policy multipliers per matched tag.
|
|
891
|
-
for (const tag of matches) {
|
|
892
|
-
const goal = goalsByTag.get(tag);
|
|
893
|
-
const policy = policiesByGoalId.get(goal.id);
|
|
894
|
-
if (!policy)
|
|
895
|
-
continue;
|
|
896
|
-
if (policy.policyType === 'error-prioritized' && tags.includes('error')) {
|
|
897
|
-
multiplier *= policy.errorPriority;
|
|
898
|
-
}
|
|
899
|
-
else if (policy.policyType === 'schema-fit-biased') {
|
|
900
|
-
// Linearly weight schema_fit in [0,1] up to (weightSchemaFit)x.
|
|
901
|
-
// Default 1.0 is a no-op.
|
|
902
|
-
multiplier *=
|
|
903
|
-
1.0 +
|
|
904
|
-
Math.max(0, policy.weightSchemaFit - 1.0) *
|
|
905
|
-
(r.entry.schema_fit ?? 0.5);
|
|
906
|
-
}
|
|
907
|
-
else if (policy.policyType === 'recency-first') {
|
|
908
|
-
multiplier *= policy.weightRecency;
|
|
909
|
-
}
|
|
910
|
-
else if (policy.policyType === 'hybrid') {
|
|
911
|
-
multiplier *= policy.weightOutcome;
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
// Hard cap AFTER all composition.
|
|
915
|
-
multiplier = Math.min(multiplier, MAX_FINAL_MULTIPLIER);
|
|
916
|
-
return {
|
|
917
|
-
...r,
|
|
918
|
-
score: r.score * multiplier,
|
|
919
|
-
_goalMatches: matches,
|
|
920
|
-
};
|
|
921
|
-
})
|
|
922
|
-
.sort((a, b) => b.score - a.score);
|
|
923
|
-
// Filter to local memories only — global memory IDs aren't in this
|
|
924
|
-
// DB's memories table, so the FK on goal_recall_log.memory_id would
|
|
925
|
-
// fail. dlPFC depth's outcome propagation is session-scoped to local;
|
|
926
|
-
// boost on ranking still applies to global results, just no log row
|
|
927
|
-
// -> no propagation.
|
|
928
|
-
const topKIds = results.slice(0, limit).map((r) => r.entry.id);
|
|
929
|
-
const localIds = new Set();
|
|
930
|
-
if (topKIds.length > 0) {
|
|
931
|
-
const placeholders = topKIds.map(() => '?').join(',');
|
|
932
|
-
const localRows = dbForGoals.prepare(`SELECT id FROM memories WHERE id IN (${placeholders})`).all(...topKIds);
|
|
933
|
-
for (const row of localRows)
|
|
934
|
-
localIds.add(row.id);
|
|
935
|
-
}
|
|
936
|
-
// Log top-K boosted recalls. INSERT OR IGNORE because
|
|
937
|
-
// UNIQUE(memory_id, goal_id) means a re-recall during the same goal
|
|
938
|
-
// life is a no-op for outcome attribution.
|
|
939
|
-
const recalledAt = new Date().toISOString();
|
|
940
|
-
const insertLog = dbForGoals.prepare(`
|
|
941
|
-
INSERT OR IGNORE INTO goal_recall_log
|
|
942
|
-
(goal_id, memory_id, tenant_id, session_id, recalled_at, score)
|
|
943
|
-
VALUES (?, ?, ?, ?, ?, ?)
|
|
944
|
-
`);
|
|
945
|
-
for (const r of results.slice(0, limit)) {
|
|
946
|
-
if (!localIds.has(r.entry.id))
|
|
947
|
-
continue; // global -> skip log insert
|
|
948
|
-
const matches = r._goalMatches;
|
|
949
|
-
if (!matches || matches.length === 0)
|
|
950
|
-
continue;
|
|
951
|
-
for (const tag of matches) {
|
|
952
|
-
const goal = goalsByTag.get(tag);
|
|
953
|
-
if (!goal)
|
|
954
|
-
continue;
|
|
955
|
-
insertLog.run(goal.id, r.entry.id, tenantIdForGoals, sessionId, recalledAt, r.score);
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
845
|
}
|
|
960
846
|
finally {
|
|
961
847
|
closeHippoDb(dbForGoals);
|
|
@@ -4481,7 +4367,7 @@ function cmdGoalList(hippoRoot, flags) {
|
|
|
4481
4367
|
function cmdGoalComplete(hippoRoot, args, flags) {
|
|
4482
4368
|
const id = args[0];
|
|
4483
4369
|
if (!id) {
|
|
4484
|
-
console.error('Usage: hippo goal complete <id> [--outcome <0..1>]');
|
|
4370
|
+
console.error('Usage: hippo goal complete <id> [--outcome <0..1>] [--no-propagate]');
|
|
4485
4371
|
process.exit(1);
|
|
4486
4372
|
}
|
|
4487
4373
|
let outcomeScore;
|
|
@@ -4498,7 +4384,8 @@ function cmdGoalComplete(hippoRoot, args, flags) {
|
|
|
4498
4384
|
}
|
|
4499
4385
|
outcomeScore = parsed;
|
|
4500
4386
|
}
|
|
4501
|
-
|
|
4387
|
+
const noPropagate = flags['no-propagate'] === true;
|
|
4388
|
+
completeGoal(hippoRoot, id, { outcomeScore, noPropagate });
|
|
4502
4389
|
console.log('ok');
|
|
4503
4390
|
}
|
|
4504
4391
|
function cmdGoalSuspend(hippoRoot, args) {
|
|
@@ -4961,6 +4848,7 @@ Commands:
|
|
|
4961
4848
|
--all Include suspended/completed goals
|
|
4962
4849
|
goal complete <id> Mark a goal completed
|
|
4963
4850
|
--outcome <0..1> Outcome score; >=0.7 boosts, <0.3 decays recalled mems
|
|
4851
|
+
--no-propagate Close the goal without applying strength side-effects
|
|
4964
4852
|
goal suspend <id> Move an active goal to suspended
|
|
4965
4853
|
goal resume <id> Move a suspended goal back to active (depth-capped)
|
|
4966
4854
|
auth <sub> Manage API keys (A5 stub auth)
|