@shadowforge0/aquifer-memory 1.8.0 → 1.9.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/.env.example +1 -0
- package/README.md +49 -22
- package/README_CN.md +24 -22
- package/README_TW.md +20 -22
- package/aquifer.config.example.json +2 -1
- package/consumers/cli.js +560 -4
- package/consumers/codex.js +1 -1
- package/consumers/mcp.js +3 -0
- package/consumers/openclaw-ext/index.js +64 -6
- package/consumers/openclaw-ext/openclaw.plugin.json +1 -1
- package/consumers/openclaw-ext/package.json +1 -1
- package/consumers/openclaw-install.js +326 -0
- package/consumers/openclaw-plugin.js +39 -1
- package/consumers/shared/config.js +2 -0
- package/core/aquifer.js +180 -33
- package/core/backends/local.js +109 -0
- package/core/doctor.js +924 -0
- package/core/finalization-inspector.js +164 -0
- package/core/memory-explain.js +624 -0
- package/core/memory-recall.js +49 -23
- package/core/memory-records.js +16 -5
- package/core/memory-review.js +891 -0
- package/core/memory-serving.js +61 -4
- package/core/operator-observability.js +249 -0
- package/core/postgres-migrations.js +13 -0
- package/core/session-finalization.js +76 -1
- package/core/storage.js +124 -8
- package/docs/getting-started.md +34 -1
- package/docs/setup.md +102 -22
- package/package.json +5 -4
- package/schema/019-v1-memory-review-resolutions.sql +53 -0
- package/scripts/codex-checkpoint-commands.js +28 -0
- package/scripts/codex-checkpoint-runtime.js +109 -0
- package/scripts/codex-recovery.js +16 -4
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function parseJsonObject(value, fallback = {}) {
|
|
4
|
+
if (value === null || value === undefined) return fallback;
|
|
5
|
+
if (typeof value === 'string') {
|
|
6
|
+
try {
|
|
7
|
+
const parsed = JSON.parse(value);
|
|
8
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : fallback;
|
|
9
|
+
} catch {
|
|
10
|
+
return fallback;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : fallback;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function uniquePresent(values) {
|
|
17
|
+
return [...new Set(values.filter(value => value !== null && value !== undefined && value !== ''))];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function hashPrefix(value) {
|
|
21
|
+
if (!value) return null;
|
|
22
|
+
return String(value).slice(0, 12);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function countBy(rows = [], field, fallback = 'unknown') {
|
|
26
|
+
const counts = {};
|
|
27
|
+
for (const row of rows) {
|
|
28
|
+
const key = (row && row[field]) || fallback;
|
|
29
|
+
counts[key] = (counts[key] || 0) + 1;
|
|
30
|
+
}
|
|
31
|
+
return counts;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function countEvidenceRefs(candidateRows = [], envelope = {}) {
|
|
35
|
+
let total = 0;
|
|
36
|
+
for (const row of candidateRows) {
|
|
37
|
+
const provenance = parseJsonObject(row.provenance, {});
|
|
38
|
+
const refs = provenance.evidenceRefs || provenance.evidence_refs;
|
|
39
|
+
if (Array.isArray(refs)) total += refs.length;
|
|
40
|
+
}
|
|
41
|
+
const envelopeCandidates = Array.isArray(envelope.candidates) ? envelope.candidates : [];
|
|
42
|
+
for (const candidate of envelopeCandidates) {
|
|
43
|
+
const refs = candidate && (candidate.evidenceRefs || candidate.evidence_refs);
|
|
44
|
+
if (Array.isArray(refs)) total += refs.length;
|
|
45
|
+
}
|
|
46
|
+
return total;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function summarizeFinalizationListRow(row = {}) {
|
|
50
|
+
const envelope = parseJsonObject(row.candidate_envelope, {});
|
|
51
|
+
const candidateCount = Number.isFinite(row.candidate_count)
|
|
52
|
+
? row.candidate_count
|
|
53
|
+
: (Array.isArray(envelope.candidates) ? envelope.candidates.length : 0);
|
|
54
|
+
return {
|
|
55
|
+
id: row.id,
|
|
56
|
+
status: row.status,
|
|
57
|
+
sessionId: row.session_id,
|
|
58
|
+
agentId: row.agent_id,
|
|
59
|
+
source: row.source,
|
|
60
|
+
host: row.host,
|
|
61
|
+
mode: row.mode,
|
|
62
|
+
phase: row.phase,
|
|
63
|
+
transcriptHashPrefix: hashPrefix(row.transcript_hash),
|
|
64
|
+
finalizerModel: row.finalizer_model || null,
|
|
65
|
+
scopeKind: row.scope_kind || null,
|
|
66
|
+
scopeKey: row.scope_key || null,
|
|
67
|
+
contextKey: row.context_key || null,
|
|
68
|
+
topicKey: row.topic_key || null,
|
|
69
|
+
candidateEnvelopeHash: row.candidate_envelope_hash || null,
|
|
70
|
+
candidateEnvelopeVersion: row.candidate_envelope_version || envelope.version || null,
|
|
71
|
+
candidateCount,
|
|
72
|
+
error: row.error || null,
|
|
73
|
+
claimedAt: row.claimed_at || null,
|
|
74
|
+
finalizedAt: row.finalized_at || null,
|
|
75
|
+
createdAt: row.created_at || null,
|
|
76
|
+
updatedAt: row.updated_at || null,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function summarizeCandidateRow(row = {}) {
|
|
81
|
+
return {
|
|
82
|
+
id: row.id,
|
|
83
|
+
index: row.candidate_index,
|
|
84
|
+
action: row.action,
|
|
85
|
+
reason: row.reason || null,
|
|
86
|
+
memoryType: row.memory_type || null,
|
|
87
|
+
canonicalKey: row.canonical_key || null,
|
|
88
|
+
summary: row.summary || null,
|
|
89
|
+
memoryRecordId: row.memory_record_id || null,
|
|
90
|
+
factAssertionId: row.fact_assertion_id || null,
|
|
91
|
+
candidateHash: row.candidate_hash || null,
|
|
92
|
+
createdAt: row.created_at || null,
|
|
93
|
+
updatedAt: row.updated_at || null,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function summarizeCandidateCounts(candidateRows = [], envelope = {}) {
|
|
98
|
+
const counts = countBy(candidateRows, 'action');
|
|
99
|
+
const envelopeCandidateCount = Array.isArray(envelope.candidates) ? envelope.candidates.length : 0;
|
|
100
|
+
return {
|
|
101
|
+
total: candidateRows.length || envelopeCandidateCount,
|
|
102
|
+
promote: counts.promote || 0,
|
|
103
|
+
quarantine: counts.quarantine || 0,
|
|
104
|
+
skip: (counts.skip || 0) + (counts.skipped || 0),
|
|
105
|
+
supersede: counts.supersede || 0,
|
|
106
|
+
error: counts.error || 0,
|
|
107
|
+
actionCounts: counts,
|
|
108
|
+
reasons: countBy(candidateRows, 'reason'),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function buildFinalizationInspection(row = {}, candidateRows = [], lineageSummary = {}) {
|
|
113
|
+
const envelope = parseJsonObject(row.candidate_envelope, {});
|
|
114
|
+
const memoryResult = parseJsonObject(row.memory_result, {});
|
|
115
|
+
const coverage = parseJsonObject(row.coverage, {});
|
|
116
|
+
const metadata = parseJsonObject(row.metadata, {});
|
|
117
|
+
const candidates = candidateRows.map(summarizeCandidateRow);
|
|
118
|
+
const memoryRecordIds = uniquePresent([
|
|
119
|
+
...(Array.isArray(lineageSummary.memoryRecordIds) ? lineageSummary.memoryRecordIds : []),
|
|
120
|
+
...candidates.map(candidate => candidate.memoryRecordId),
|
|
121
|
+
]);
|
|
122
|
+
const factAssertionIds = uniquePresent([
|
|
123
|
+
...(Array.isArray(lineageSummary.factAssertionIds) ? lineageSummary.factAssertionIds : []),
|
|
124
|
+
...candidates.map(candidate => candidate.factAssertionId),
|
|
125
|
+
]);
|
|
126
|
+
const evidenceRefCount = Number.isFinite(lineageSummary.evidenceRefCount)
|
|
127
|
+
? lineageSummary.evidenceRefCount
|
|
128
|
+
: countEvidenceRefs(candidateRows, envelope);
|
|
129
|
+
const evidenceItemCount = Number.isFinite(lineageSummary.evidenceItemCount)
|
|
130
|
+
? lineageSummary.evidenceItemCount
|
|
131
|
+
: 0;
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
readOnly: true,
|
|
135
|
+
finalization: summarizeFinalizationListRow(row),
|
|
136
|
+
review: {
|
|
137
|
+
humanReviewText: row.human_review_text || '',
|
|
138
|
+
sessionStartText: row.session_start_text || '',
|
|
139
|
+
},
|
|
140
|
+
memoryResult,
|
|
141
|
+
candidateEnvelope: {
|
|
142
|
+
version: row.candidate_envelope_version || envelope.version || null,
|
|
143
|
+
hash: row.candidate_envelope_hash || null,
|
|
144
|
+
candidateCount: Array.isArray(envelope.candidates) ? envelope.candidates.length : 0,
|
|
145
|
+
coverage,
|
|
146
|
+
},
|
|
147
|
+
candidateSummary: summarizeCandidateCounts(candidateRows, envelope),
|
|
148
|
+
lineage: {
|
|
149
|
+
memoryRecordIds,
|
|
150
|
+
factAssertionIds,
|
|
151
|
+
evidenceRefCount,
|
|
152
|
+
evidenceItemCount,
|
|
153
|
+
},
|
|
154
|
+
safety: {
|
|
155
|
+
safetyGate: metadata.safetyGate || metadata.safety_gate || null,
|
|
156
|
+
},
|
|
157
|
+
candidates,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
module.exports = {
|
|
162
|
+
buildFinalizationInspection,
|
|
163
|
+
summarizeFinalizationListRow,
|
|
164
|
+
};
|