@shadowforge0/aquifer-memory 1.8.1 → 1.9.1
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 +82 -26
- package/README_CN.md +33 -23
- package/README_TW.md +25 -24
- package/aquifer.config.example.json +2 -1
- package/consumers/cli.js +587 -33
- package/consumers/codex-active-checkpoint.js +3 -1
- package/consumers/codex-current-memory.js +10 -6
- package/consumers/codex.js +6 -3
- package/consumers/default/daily-entries.js +2 -2
- package/consumers/default/index.js +40 -30
- package/consumers/default/prompts/summary.js +2 -2
- package/consumers/mcp.js +56 -46
- package/consumers/openclaw-ext/index.js +65 -7
- 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 +105 -24
- package/consumers/shared/compat-recall.js +101 -0
- package/consumers/shared/config.js +2 -0
- package/consumers/shared/openclaw-product-tools.js +130 -0
- package/consumers/shared/recall-format.js +2 -2
- package/core/aquifer.js +553 -41
- package/core/backends/local.js +169 -1
- package/core/doctor.js +924 -0
- package/core/finalization-inspector.js +164 -0
- package/core/finalization-review.js +88 -42
- package/core/interface.js +629 -0
- package/core/mcp-manifest.js +11 -3
- package/core/memory-bootstrap.js +25 -27
- package/core/memory-consolidation.js +564 -42
- package/core/memory-explain.js +593 -0
- package/core/memory-promotion.js +392 -55
- package/core/memory-recall.js +75 -71
- package/core/memory-records.js +107 -108
- package/core/memory-review.js +891 -0
- package/core/memory-serving.js +61 -4
- package/core/memory-type-policy.js +298 -0
- package/core/operator-observability.js +249 -0
- package/core/postgres-migrations.js +22 -0
- package/core/session-checkpoint-producer.js +3 -1
- package/core/session-checkpoints.js +1 -1
- package/core/session-finalization.js +78 -3
- package/core/storage.js +124 -8
- package/docs/getting-started.md +50 -4
- package/docs/setup.md +163 -24
- package/package.json +5 -4
- package/schema/004-completion.sql +4 -4
- package/schema/010-v1-finalization-review.sql +72 -0
- package/schema/019-v1-memory-review-resolutions.sql +53 -0
- package/schema/020-v1-assistant-shaping-memory.sql +30 -0
- package/scripts/backfill-canonical-key.js +1 -1
- package/scripts/codex-checkpoint-commands.js +28 -0
- package/scripts/codex-checkpoint-runtime.js +109 -0
- package/scripts/codex-recovery.js +16 -4
- package/scripts/diagnose-fts-zh.js +1 -1
- package/scripts/extract-insights-from-recent-sessions.js +4 -4
package/core/memory-records.js
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
4
|
const { resolveApplicableRecords } = require('./memory-bootstrap');
|
|
5
|
+
const { assertAllowedScopeRequest } = require('./memory-serving');
|
|
6
|
+
const {
|
|
7
|
+
authoritySortPriority,
|
|
8
|
+
authoritySortPrioritySql,
|
|
9
|
+
feedbackWeightSql,
|
|
10
|
+
memoryTypeBootstrapPriority,
|
|
11
|
+
memoryTypeBootstrapPrioritySql,
|
|
12
|
+
memoryTypeRuntimeContract,
|
|
13
|
+
} = require('./memory-type-policy');
|
|
5
14
|
|
|
6
15
|
function requireField(obj, field) {
|
|
7
16
|
if (!obj || obj[field] === undefined || obj[field] === null || obj[field] === '') {
|
|
@@ -30,57 +39,33 @@ function advisoryLockKeys(namespace, value) {
|
|
|
30
39
|
return [digest.readInt32BE(0), digest.readInt32BE(4)];
|
|
31
40
|
}
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
WHEN 'decision' THEN 3
|
|
39
|
-
WHEN 'preference' THEN 4
|
|
40
|
-
WHEN 'fact' THEN 5
|
|
41
|
-
WHEN 'conclusion' THEN 6
|
|
42
|
-
WHEN 'entity_note' THEN 7
|
|
43
|
-
ELSE 99
|
|
44
|
-
END ASC,
|
|
45
|
-
CASE m.authority
|
|
46
|
-
WHEN 'user_explicit' THEN 0
|
|
47
|
-
WHEN 'executable_evidence' THEN 1
|
|
48
|
-
WHEN 'manual' THEN 2
|
|
49
|
-
WHEN 'system' THEN 3
|
|
50
|
-
WHEN 'verified_summary' THEN 4
|
|
51
|
-
WHEN 'llm_inference' THEN 5
|
|
52
|
-
WHEN 'raw_transcript' THEN 6
|
|
53
|
-
ELSE 99
|
|
54
|
-
END ASC,
|
|
42
|
+
function bootstrapOrderSql(feedbackScoreExpr = '0') {
|
|
43
|
+
return `
|
|
44
|
+
${memoryTypeBootstrapPrioritySql('m.memory_type')} ASC,
|
|
45
|
+
${authoritySortPrioritySql('m.authority')} ASC,
|
|
46
|
+
COALESCE((${feedbackScoreExpr}), 0) DESC,
|
|
55
47
|
m.accepted_at DESC NULLS LAST,
|
|
56
48
|
m.id ASC`;
|
|
57
|
-
|
|
58
|
-
const CURRENT_TYPE_PRIORITY = {
|
|
59
|
-
constraint: 0,
|
|
60
|
-
state: 1,
|
|
61
|
-
open_loop: 2,
|
|
62
|
-
decision: 3,
|
|
63
|
-
preference: 4,
|
|
64
|
-
fact: 5,
|
|
65
|
-
conclusion: 6,
|
|
66
|
-
entity_note: 7,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const CURRENT_AUTHORITY_PRIORITY = {
|
|
70
|
-
user_explicit: 0,
|
|
71
|
-
executable_evidence: 1,
|
|
72
|
-
manual: 2,
|
|
73
|
-
system: 3,
|
|
74
|
-
verified_summary: 4,
|
|
75
|
-
llm_inference: 5,
|
|
76
|
-
raw_transcript: 6,
|
|
77
|
-
};
|
|
49
|
+
}
|
|
78
50
|
|
|
79
51
|
function parseTime(value) {
|
|
80
52
|
const parsed = Date.parse(value || '');
|
|
81
53
|
return Number.isFinite(parsed) ? parsed : null;
|
|
82
54
|
}
|
|
83
55
|
|
|
56
|
+
function memoryFeedbackScoreSql(feedbackTable, feedbackTableAlias = 'f') {
|
|
57
|
+
return `
|
|
58
|
+
COALESCE((
|
|
59
|
+
SELECT SUM(
|
|
60
|
+
${feedbackWeightSql(`${feedbackTableAlias}.feedback_type`)}
|
|
61
|
+
)
|
|
62
|
+
FROM ${feedbackTable} ${feedbackTableAlias}
|
|
63
|
+
WHERE ${feedbackTableAlias}.tenant_id = m.tenant_id
|
|
64
|
+
AND ${feedbackTableAlias}.target_kind = 'memory_record'
|
|
65
|
+
AND ${feedbackTableAlias}.target_id = m.id::text
|
|
66
|
+
), 0)`;
|
|
67
|
+
}
|
|
68
|
+
|
|
84
69
|
function normalizeScopePath(activeScopePath, activeScopeKey) {
|
|
85
70
|
const source = Array.isArray(activeScopePath)
|
|
86
71
|
? activeScopePath
|
|
@@ -127,6 +112,7 @@ function normalizeCurrentMemoryRow(row = {}) {
|
|
|
127
112
|
inheritanceMode: row.inheritanceMode ?? row.inheritance_mode ?? row.scope_inheritance_mode ?? null,
|
|
128
113
|
visibleInBootstrap: row.visibleInBootstrap ?? row.visible_in_bootstrap ?? false,
|
|
129
114
|
visibleInRecall: row.visibleInRecall ?? row.visible_in_recall ?? false,
|
|
115
|
+
feedbackScore: Number(row.feedbackScore ?? row.feedback_score) || 0,
|
|
130
116
|
acceptedAt: row.acceptedAt ?? row.accepted_at ?? null,
|
|
131
117
|
validFrom: row.validFrom ?? row.valid_from ?? null,
|
|
132
118
|
validTo: row.validTo ?? row.valid_to ?? null,
|
|
@@ -141,18 +127,26 @@ function currentScopePriority(record, positions) {
|
|
|
141
127
|
}
|
|
142
128
|
|
|
143
129
|
function sortCurrentMemoryRecords(a, b, positions) {
|
|
130
|
+
const leftRuntimeContract = memoryTypeRuntimeContract(a.memoryType ?? a.memory_type);
|
|
131
|
+
const rightRuntimeContract = memoryTypeRuntimeContract(b.memoryType ?? b.memory_type);
|
|
132
|
+
if (leftRuntimeContract !== rightRuntimeContract) return leftRuntimeContract ? -1 : 1;
|
|
133
|
+
|
|
144
134
|
const leftScope = currentScopePriority(a, positions);
|
|
145
135
|
const rightScope = currentScopePriority(b, positions);
|
|
146
136
|
if (rightScope !== leftScope) return rightScope - leftScope;
|
|
147
137
|
|
|
148
|
-
const leftType =
|
|
149
|
-
const rightType =
|
|
138
|
+
const leftType = memoryTypeBootstrapPriority(a.memoryType ?? a.memory_type);
|
|
139
|
+
const rightType = memoryTypeBootstrapPriority(b.memoryType ?? b.memory_type);
|
|
150
140
|
if (leftType !== rightType) return leftType - rightType;
|
|
151
141
|
|
|
152
|
-
const leftAuthority =
|
|
153
|
-
const rightAuthority =
|
|
142
|
+
const leftAuthority = authoritySortPriority(a.authority);
|
|
143
|
+
const rightAuthority = authoritySortPriority(b.authority);
|
|
154
144
|
if (leftAuthority !== rightAuthority) return leftAuthority - rightAuthority;
|
|
155
145
|
|
|
146
|
+
const leftFeedback = Number(a.feedbackScore ?? a.feedback_score) || 0;
|
|
147
|
+
const rightFeedback = Number(b.feedbackScore ?? b.feedback_score) || 0;
|
|
148
|
+
if (leftFeedback !== rightFeedback) return rightFeedback - leftFeedback;
|
|
149
|
+
|
|
156
150
|
const leftAccepted = parseTime(a.acceptedAt ?? a.accepted_at);
|
|
157
151
|
const rightAccepted = parseTime(b.acceptedAt ?? b.accepted_at);
|
|
158
152
|
if (leftAccepted !== rightAccepted) return (rightAccepted ?? 0) - (leftAccepted ?? 0);
|
|
@@ -269,29 +263,7 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
269
263
|
COALESCE($10,'candidate'),COALESCE($11,'llm_inference'),$12,$13,$14,$15,
|
|
270
264
|
$16,$17,$18,$19,$20,$21,COALESCE($22,false),COALESCE($23,false),COALESCE($24::jsonb,'{}'::jsonb),$25,$26,$27::vector
|
|
271
265
|
)
|
|
272
|
-
ON CONFLICT (tenant_id, canonical_key) WHERE status = 'active' DO
|
|
273
|
-
scope_id = EXCLUDED.scope_id,
|
|
274
|
-
context_key = COALESCE(EXCLUDED.context_key, ${memories}.context_key),
|
|
275
|
-
topic_key = COALESCE(EXCLUDED.topic_key, ${memories}.topic_key),
|
|
276
|
-
title = COALESCE(EXCLUDED.title, ${memories}.title),
|
|
277
|
-
summary = COALESCE(NULLIF(EXCLUDED.summary, ''), ${memories}.summary),
|
|
278
|
-
payload = COALESCE(NULLIF(EXCLUDED.payload, '{}'::jsonb), ${memories}.payload),
|
|
279
|
-
authority = EXCLUDED.authority,
|
|
280
|
-
accepted_at = COALESCE(EXCLUDED.accepted_at, ${memories}.accepted_at),
|
|
281
|
-
valid_from = COALESCE(EXCLUDED.valid_from, ${memories}.valid_from),
|
|
282
|
-
valid_to = COALESCE(EXCLUDED.valid_to, ${memories}.valid_to),
|
|
283
|
-
stale_after = COALESCE(EXCLUDED.stale_after, ${memories}.stale_after),
|
|
284
|
-
version_id = COALESCE(EXCLUDED.version_id, ${memories}.version_id),
|
|
285
|
-
backing_fact_id = COALESCE(EXCLUDED.backing_fact_id, ${memories}.backing_fact_id),
|
|
286
|
-
observed_at = COALESCE(EXCLUDED.observed_at, ${memories}.observed_at),
|
|
287
|
-
revoked_at = COALESCE(EXCLUDED.revoked_at, ${memories}.revoked_at),
|
|
288
|
-
superseded_at = COALESCE(EXCLUDED.superseded_at, ${memories}.superseded_at),
|
|
289
|
-
visible_in_bootstrap = EXCLUDED.visible_in_bootstrap,
|
|
290
|
-
visible_in_recall = EXCLUDED.visible_in_recall,
|
|
291
|
-
rank_features = COALESCE(NULLIF(EXCLUDED.rank_features, '{}'::jsonb), ${memories}.rank_features),
|
|
292
|
-
created_by_finalization_id = COALESCE(${memories}.created_by_finalization_id, EXCLUDED.created_by_finalization_id),
|
|
293
|
-
created_by_compaction_run_id = COALESCE(${memories}.created_by_compaction_run_id, EXCLUDED.created_by_compaction_run_id),
|
|
294
|
-
embedding = COALESCE(EXCLUDED.embedding, ${memories}.embedding)
|
|
266
|
+
ON CONFLICT (tenant_id, canonical_key) WHERE status = 'active' DO NOTHING
|
|
295
267
|
RETURNING *`,
|
|
296
268
|
[
|
|
297
269
|
tenantId,
|
|
@@ -348,28 +320,7 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
348
320
|
$10,$11,$12,$13,$14,$15,$16,COALESCE($17,'active'),COALESCE($18,'verified_summary'),
|
|
349
321
|
$19,$20,$21,COALESCE($22::jsonb,'{}'::jsonb),$23,$24
|
|
350
322
|
)
|
|
351
|
-
ON CONFLICT (tenant_id, canonical_key) WHERE status = 'active' DO
|
|
352
|
-
scope_id = EXCLUDED.scope_id,
|
|
353
|
-
subject_entity_id = COALESCE(EXCLUDED.subject_entity_id, ${factAssertions}.subject_entity_id),
|
|
354
|
-
predicate = EXCLUDED.predicate,
|
|
355
|
-
object_kind = EXCLUDED.object_kind,
|
|
356
|
-
object_entity_id = COALESCE(EXCLUDED.object_entity_id, ${factAssertions}.object_entity_id),
|
|
357
|
-
object_value_json = EXCLUDED.object_value_json,
|
|
358
|
-
qualifiers_json = COALESCE(NULLIF(EXCLUDED.qualifiers_json, '{}'::jsonb), ${factAssertions}.qualifiers_json),
|
|
359
|
-
valid_from = COALESCE(EXCLUDED.valid_from, ${factAssertions}.valid_from),
|
|
360
|
-
valid_to = COALESCE(EXCLUDED.valid_to, ${factAssertions}.valid_to),
|
|
361
|
-
observed_at = COALESCE(EXCLUDED.observed_at, ${factAssertions}.observed_at),
|
|
362
|
-
stale_after = COALESCE(EXCLUDED.stale_after, ${factAssertions}.stale_after),
|
|
363
|
-
accepted_at = COALESCE(EXCLUDED.accepted_at, ${factAssertions}.accepted_at),
|
|
364
|
-
revoked_at = COALESCE(EXCLUDED.revoked_at, ${factAssertions}.revoked_at),
|
|
365
|
-
superseded_at = COALESCE(EXCLUDED.superseded_at, ${factAssertions}.superseded_at),
|
|
366
|
-
authority = EXCLUDED.authority,
|
|
367
|
-
assertion_hash = EXCLUDED.assertion_hash,
|
|
368
|
-
version_id = COALESCE(EXCLUDED.version_id, ${factAssertions}.version_id),
|
|
369
|
-
metadata = COALESCE(NULLIF(EXCLUDED.metadata, '{}'::jsonb), ${factAssertions}.metadata),
|
|
370
|
-
created_by_finalization_id = COALESCE(${factAssertions}.created_by_finalization_id, EXCLUDED.created_by_finalization_id),
|
|
371
|
-
created_by_compaction_run_id = COALESCE(${factAssertions}.created_by_compaction_run_id, EXCLUDED.created_by_compaction_run_id),
|
|
372
|
-
updated_at = now()
|
|
323
|
+
ON CONFLICT (tenant_id, canonical_key) WHERE status = 'active' DO NOTHING
|
|
373
324
|
RETURNING *`,
|
|
374
325
|
[
|
|
375
326
|
tenantId,
|
|
@@ -523,10 +474,13 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
523
474
|
const result = await pool.query(
|
|
524
475
|
`SELECT m.*, s.scope_kind, s.scope_key, s.inheritance_mode AS scope_inheritance_mode
|
|
525
476
|
FROM ${memories} m
|
|
526
|
-
JOIN ${scopes} s ON s.id = m.scope_id
|
|
477
|
+
JOIN ${scopes} s ON s.tenant_id = m.tenant_id AND s.id = m.scope_id
|
|
527
478
|
WHERE m.tenant_id = $1
|
|
528
479
|
AND m.canonical_key = $2
|
|
529
480
|
AND m.status = 'active'
|
|
481
|
+
AND m.revoked_at IS NULL
|
|
482
|
+
AND m.superseded_at IS NULL
|
|
483
|
+
AND m.superseded_by IS NULL
|
|
530
484
|
ORDER BY m.accepted_at DESC NULLS LAST, m.id ASC
|
|
531
485
|
${lockClause}`,
|
|
532
486
|
[tenantId, input.canonicalKey]
|
|
@@ -541,10 +495,13 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
541
495
|
const result = await pool.query(
|
|
542
496
|
`SELECT f.*, s.scope_kind, s.scope_key, s.inheritance_mode AS scope_inheritance_mode
|
|
543
497
|
FROM ${factAssertions} f
|
|
544
|
-
JOIN ${scopes} s ON s.id = f.scope_id
|
|
498
|
+
JOIN ${scopes} s ON s.tenant_id = f.tenant_id AND s.id = f.scope_id
|
|
545
499
|
WHERE f.tenant_id = $1
|
|
546
500
|
AND f.canonical_key = $2
|
|
547
501
|
AND f.status = 'active'
|
|
502
|
+
AND f.revoked_at IS NULL
|
|
503
|
+
AND f.superseded_at IS NULL
|
|
504
|
+
AND f.superseded_by IS NULL
|
|
548
505
|
ORDER BY f.accepted_at DESC NULLS LAST, f.id ASC
|
|
549
506
|
${lockClause}`,
|
|
550
507
|
[tenantId, input.canonicalKey]
|
|
@@ -571,14 +528,19 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
571
528
|
const result = await pool.query(
|
|
572
529
|
`UPDATE ${memories}
|
|
573
530
|
SET status = $3,
|
|
574
|
-
superseded_by =
|
|
531
|
+
superseded_by = CASE
|
|
532
|
+
WHEN $3 = 'active' THEN NULL
|
|
533
|
+
ELSE COALESCE($4, superseded_by)
|
|
534
|
+
END,
|
|
575
535
|
valid_to = COALESCE($5, valid_to),
|
|
576
536
|
superseded_at = CASE
|
|
577
537
|
WHEN $3 = 'superseded' THEN COALESCE($8, superseded_at, now())
|
|
538
|
+
WHEN $3 = 'active' THEN NULL
|
|
578
539
|
ELSE superseded_at
|
|
579
540
|
END,
|
|
580
541
|
revoked_at = CASE
|
|
581
542
|
WHEN $3 = 'revoked' THEN COALESCE($9, revoked_at, now())
|
|
543
|
+
WHEN $3 = 'active' THEN NULL
|
|
582
544
|
ELSE revoked_at
|
|
583
545
|
END,
|
|
584
546
|
visible_in_bootstrap = $6,
|
|
@@ -611,14 +573,19 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
611
573
|
const result = await pool.query(
|
|
612
574
|
`UPDATE ${memories}
|
|
613
575
|
SET status = $4,
|
|
614
|
-
superseded_by =
|
|
576
|
+
superseded_by = CASE
|
|
577
|
+
WHEN $4 = 'active' THEN NULL
|
|
578
|
+
ELSE COALESCE($5, superseded_by)
|
|
579
|
+
END,
|
|
615
580
|
valid_to = COALESCE($6, valid_to),
|
|
616
581
|
superseded_at = CASE
|
|
617
582
|
WHEN $4 = 'superseded' THEN COALESCE($9, superseded_at, now())
|
|
583
|
+
WHEN $4 = 'active' THEN NULL
|
|
618
584
|
ELSE superseded_at
|
|
619
585
|
END,
|
|
620
586
|
revoked_at = CASE
|
|
621
587
|
WHEN $4 = 'revoked' THEN COALESCE($10, revoked_at, now())
|
|
588
|
+
WHEN $4 = 'active' THEN NULL
|
|
622
589
|
ELSE revoked_at
|
|
623
590
|
END,
|
|
624
591
|
visible_in_bootstrap = $7,
|
|
@@ -649,14 +616,19 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
649
616
|
const result = await pool.query(
|
|
650
617
|
`UPDATE ${factAssertions}
|
|
651
618
|
SET status = $3,
|
|
652
|
-
superseded_by =
|
|
619
|
+
superseded_by = CASE
|
|
620
|
+
WHEN $3 = 'active' THEN NULL
|
|
621
|
+
ELSE COALESCE($4, superseded_by)
|
|
622
|
+
END,
|
|
653
623
|
valid_to = COALESCE($5, valid_to),
|
|
654
624
|
superseded_at = CASE
|
|
655
625
|
WHEN $3 = 'superseded' THEN COALESCE($6, superseded_at, now())
|
|
626
|
+
WHEN $3 = 'active' THEN NULL
|
|
656
627
|
ELSE superseded_at
|
|
657
628
|
END,
|
|
658
629
|
revoked_at = CASE
|
|
659
630
|
WHEN $3 = 'revoked' THEN COALESCE($7, revoked_at, now())
|
|
631
|
+
WHEN $3 = 'active' THEN NULL
|
|
660
632
|
ELSE revoked_at
|
|
661
633
|
END,
|
|
662
634
|
updated_at = now()
|
|
@@ -678,7 +650,13 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
678
650
|
async function listActive(input = {}) {
|
|
679
651
|
const tenantId = input.tenantId || defaultTenantId;
|
|
680
652
|
const params = [tenantId];
|
|
681
|
-
const where = [
|
|
653
|
+
const where = [
|
|
654
|
+
`m.tenant_id = $1`,
|
|
655
|
+
`m.status = 'active'`,
|
|
656
|
+
`m.revoked_at IS NULL`,
|
|
657
|
+
`m.superseded_at IS NULL`,
|
|
658
|
+
`m.superseded_by IS NULL`,
|
|
659
|
+
];
|
|
682
660
|
if (input.asOf) {
|
|
683
661
|
params.push(input.asOf);
|
|
684
662
|
const at = `$${params.length}::timestamptz`;
|
|
@@ -706,13 +684,18 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
706
684
|
where.push(`m.embedding IS NULL`);
|
|
707
685
|
}
|
|
708
686
|
params.push(Math.max(1, Math.min(200, input.limit || 50)));
|
|
687
|
+
const feedbackScoreExpr = input.includeFeedbackScore === true
|
|
688
|
+
? memoryFeedbackScoreSql(feedback)
|
|
689
|
+
: '0';
|
|
690
|
+
const feedbackScoreSelect = `${feedbackScoreExpr}::real AS feedback_score`;
|
|
709
691
|
const orderBy = input.visibleInBootstrap === true
|
|
710
|
-
?
|
|
692
|
+
? bootstrapOrderSql(feedbackScoreExpr)
|
|
711
693
|
: `m.accepted_at DESC NULLS LAST, m.id ASC`;
|
|
712
694
|
const result = await pool.query(
|
|
713
|
-
`SELECT m.*, s.scope_kind, s.scope_key, s.inheritance_mode AS scope_inheritance_mode
|
|
695
|
+
`SELECT m.*, s.scope_kind, s.scope_key, s.inheritance_mode AS scope_inheritance_mode,
|
|
696
|
+
${feedbackScoreSelect}
|
|
714
697
|
FROM ${memories} m
|
|
715
|
-
JOIN ${scopes} s ON s.id = m.scope_id
|
|
698
|
+
JOIN ${scopes} s ON s.tenant_id = m.tenant_id AND s.id = m.scope_id
|
|
716
699
|
WHERE ${where.join(' AND ')}
|
|
717
700
|
ORDER BY ${orderBy}
|
|
718
701
|
LIMIT $${params.length}`,
|
|
@@ -773,17 +756,27 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
773
756
|
const tenantId = input.tenantId || defaultTenantId;
|
|
774
757
|
let activeScopePath = normalizeScopePath(input.activeScopePath, input.activeScopeKey);
|
|
775
758
|
let activeScopeKey = input.activeScopeKey || activeScopePath[activeScopePath.length - 1] || null;
|
|
776
|
-
|
|
759
|
+
let resolvedScopeKey = null;
|
|
760
|
+
if (input.scopeId) {
|
|
777
761
|
const scopeResult = await pool.query(
|
|
778
762
|
`SELECT scope_key FROM ${scopes} WHERE tenant_id = $1 AND id = $2 LIMIT 1`,
|
|
779
763
|
[tenantId, input.scopeId],
|
|
780
764
|
);
|
|
781
|
-
|
|
782
|
-
if (
|
|
783
|
-
activeScopePath = [
|
|
784
|
-
activeScopeKey =
|
|
765
|
+
resolvedScopeKey = scopeResult.rows[0]?.scope_key || null;
|
|
766
|
+
if (resolvedScopeKey && !input.activeScopeKey && !input.activeScopePath) {
|
|
767
|
+
activeScopePath = [resolvedScopeKey];
|
|
768
|
+
activeScopeKey = resolvedScopeKey;
|
|
785
769
|
}
|
|
786
770
|
}
|
|
771
|
+
assertAllowedScopeRequest({
|
|
772
|
+
...input,
|
|
773
|
+
activeScopeKey,
|
|
774
|
+
activeScopePath,
|
|
775
|
+
resolvedScopeKey,
|
|
776
|
+
});
|
|
777
|
+
if (input.includeEvidenceRefs === true && input.operator !== true && input.internal !== true) {
|
|
778
|
+
throw new Error('memory.current includeEvidenceRefs requires operator=true or internal=true');
|
|
779
|
+
}
|
|
787
780
|
const limit = Math.max(1, Math.min(100, input.limit || 50));
|
|
788
781
|
const fetchLimit = Math.max(limit + 1, Math.min(200, Math.max(limit * 4, 40)));
|
|
789
782
|
const asOf = input.asOf || new Date().toISOString();
|
|
@@ -791,6 +784,9 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
791
784
|
const where = [
|
|
792
785
|
`m.tenant_id = $1`,
|
|
793
786
|
`m.status = 'active'`,
|
|
787
|
+
`m.revoked_at IS NULL`,
|
|
788
|
+
`m.superseded_at IS NULL`,
|
|
789
|
+
`m.superseded_by IS NULL`,
|
|
794
790
|
`s.scope_key = ANY($2::text[])`,
|
|
795
791
|
`(m.visible_in_bootstrap = true OR m.visible_in_recall = true)`,
|
|
796
792
|
`(m.valid_from IS NULL OR m.valid_from <= $3::timestamptz)`,
|
|
@@ -825,18 +821,21 @@ function createMemoryRecords({ pool, schema, defaultTenantId, inTransaction = fa
|
|
|
825
821
|
), '[]'::jsonb)`
|
|
826
822
|
: `'[]'::jsonb`;
|
|
827
823
|
|
|
824
|
+
const feedbackScoreExpr = memoryFeedbackScoreSql(feedback);
|
|
825
|
+
const feedbackScoreSelect = `${feedbackScoreExpr}::real AS feedback_score`;
|
|
828
826
|
const result = await pool.query(
|
|
829
827
|
`SELECT
|
|
830
828
|
m.*,
|
|
831
829
|
s.scope_kind,
|
|
832
830
|
s.scope_key,
|
|
833
831
|
s.inheritance_mode AS scope_inheritance_mode,
|
|
832
|
+
${feedbackScoreSelect},
|
|
834
833
|
${evidenceRefsSelect} AS evidence_refs
|
|
835
834
|
FROM ${memories} m
|
|
836
|
-
JOIN ${scopes} s ON s.id = m.scope_id
|
|
835
|
+
JOIN ${scopes} s ON s.tenant_id = m.tenant_id AND s.id = m.scope_id
|
|
837
836
|
WHERE ${where.join(' AND ')}
|
|
838
837
|
ORDER BY array_position($2::text[], s.scope_key) DESC NULLS LAST,
|
|
839
|
-
${
|
|
838
|
+
${bootstrapOrderSql(feedbackScoreExpr)}
|
|
840
839
|
LIMIT ${limitParam}`,
|
|
841
840
|
params,
|
|
842
841
|
);
|