blun-king-cli 9.1.385 → 9.1.387
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.
|
@@ -20,7 +20,7 @@ function safeId(value) {
|
|
|
20
20
|
return SAFE_ID_RE.test(text) ? text : '';
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
function authorizeAttentionCandidate({ store, tenantId, currentAgent, now, input } = {}) {
|
|
23
|
+
function authorizeAttentionCandidate({ store, tenantId, currentAgent, now, input, memoryAccess } = {}) {
|
|
24
24
|
if (!store || typeof store.authorizeAttention !== 'function' || typeof now !== 'function'
|
|
25
25
|
|| !exactKeys(input, new Set(['candidate', 'channel', 'authorization']))) fail();
|
|
26
26
|
const tenant = safeId(tenantId);
|
|
@@ -61,7 +61,7 @@ function authorizeAttentionCandidate({ store, tenantId, currentAgent, now, input
|
|
|
61
61
|
receiptId,
|
|
62
62
|
authority,
|
|
63
63
|
authorizedAt: new Date(issuedAtMs).toISOString(),
|
|
64
|
-
});
|
|
64
|
+
}, memoryAccess);
|
|
65
65
|
if (!admitted.claimed) {
|
|
66
66
|
return {
|
|
67
67
|
accepted: false,
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { openCognitiveStateStore } = require('./cognitive-state-store.cjs');
|
|
4
|
+
|
|
5
|
+
const COGNITIVE_MEMORY_ADAPTER_VERSION = 2;
|
|
6
|
+
const KIND_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
7
|
+
const ACCESS_KEYS = Object.freeze([
|
|
8
|
+
'actorId', 'agentId', 'channelId', 'conversationId', 'permissionContext',
|
|
9
|
+
'portalId', 'requestedScope', 'tenantId', 'userId',
|
|
10
|
+
]);
|
|
11
|
+
const PERMISSION_KEYS = Object.freeze(['authority', 'decision', 'receiptId']);
|
|
12
|
+
const REQUIRED_METHODS = Object.freeze([
|
|
13
|
+
'commit',
|
|
14
|
+
'read',
|
|
15
|
+
'hasEvent',
|
|
16
|
+
'verify',
|
|
17
|
+
'claimAttention',
|
|
18
|
+
'authorizeAttention',
|
|
19
|
+
'close',
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
function fail(code) {
|
|
23
|
+
const error = new Error(code);
|
|
24
|
+
error.code = code;
|
|
25
|
+
throw error;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function exactKeys(value, expected) {
|
|
29
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
30
|
+
&& Object.keys(value).sort().join('\0') === [...expected].sort().join('\0');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function safeId(value) {
|
|
34
|
+
const text = String(value ?? '').trim();
|
|
35
|
+
return KIND_RE.test(text) ? text : '';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function normalizeMemoryAccess(access, request) {
|
|
39
|
+
if (!exactKeys(access, ACCESS_KEYS) || !exactKeys(access.permissionContext, PERMISSION_KEYS)) {
|
|
40
|
+
fail('COGNITIVE_MEMORY_ACCESS_INVALID');
|
|
41
|
+
}
|
|
42
|
+
const normalized = {
|
|
43
|
+
tenantId: safeId(access.tenantId),
|
|
44
|
+
userId: safeId(access.userId),
|
|
45
|
+
actorId: safeId(access.actorId),
|
|
46
|
+
agentId: safeId(access.agentId),
|
|
47
|
+
portalId: safeId(access.portalId),
|
|
48
|
+
channelId: safeId(access.channelId),
|
|
49
|
+
conversationId: safeId(access.conversationId),
|
|
50
|
+
requestedScope: safeId(access.requestedScope),
|
|
51
|
+
permissionContext: {
|
|
52
|
+
authority: safeId(access.permissionContext.authority),
|
|
53
|
+
decision: String(access.permissionContext.decision ?? ''),
|
|
54
|
+
receiptId: safeId(access.permissionContext.receiptId),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
if (!normalized.tenantId || !normalized.userId || !normalized.actorId || !normalized.agentId
|
|
58
|
+
|| !normalized.portalId || !normalized.channelId || !normalized.conversationId
|
|
59
|
+
|| !normalized.requestedScope || !normalized.permissionContext.authority
|
|
60
|
+
|| !normalized.permissionContext.receiptId) fail('COGNITIVE_MEMORY_ACCESS_INVALID');
|
|
61
|
+
if (normalized.permissionContext.decision !== 'passed') fail('COGNITIVE_MEMORY_ACCESS_DENIED');
|
|
62
|
+
const requestTenant = safeId(request?.tenantId);
|
|
63
|
+
const requestAgent = safeId(request?.agentId ?? request?.candidate?.responsible_agent ?? request?.claimedBy);
|
|
64
|
+
if (!requestTenant || !requestAgent
|
|
65
|
+
|| requestTenant !== normalized.tenantId || requestAgent !== normalized.agentId) {
|
|
66
|
+
fail('COGNITIVE_MEMORY_ACCESS_SCOPE_MISMATCH');
|
|
67
|
+
}
|
|
68
|
+
normalized.permissionContext = Object.freeze(normalized.permissionContext);
|
|
69
|
+
return Object.freeze(normalized);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function assertCognitiveMemoryAdapter(adapter) {
|
|
73
|
+
if (!adapter || typeof adapter !== 'object' || Array.isArray(adapter)) {
|
|
74
|
+
fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
75
|
+
}
|
|
76
|
+
if (adapter.contractVersion !== COGNITIVE_MEMORY_ADAPTER_VERSION) {
|
|
77
|
+
fail('COGNITIVE_MEMORY_ADAPTER_VERSION_UNSUPPORTED');
|
|
78
|
+
}
|
|
79
|
+
if (!KIND_RE.test(String(adapter.kind ?? ''))
|
|
80
|
+
|| REQUIRED_METHODS.some((method) => typeof adapter[method] !== 'function')) {
|
|
81
|
+
fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
82
|
+
}
|
|
83
|
+
return adapter;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function guardCognitiveMemoryAdapter(adapter) {
|
|
87
|
+
const raw = assertCognitiveMemoryAdapter(adapter);
|
|
88
|
+
const guarded = {
|
|
89
|
+
contractVersion: raw.contractVersion,
|
|
90
|
+
kind: raw.kind,
|
|
91
|
+
commit: (input, access) => raw.commit(input, normalizeMemoryAccess(access, input)),
|
|
92
|
+
read: (input, access) => raw.read(input, normalizeMemoryAccess(access, input)),
|
|
93
|
+
hasEvent: (input, access) => {
|
|
94
|
+
if (!exactKeys(input, ['agentId', 'eventId', 'tenantId']) || !safeId(input.eventId)) {
|
|
95
|
+
fail('COGNITIVE_MEMORY_ACCESS_INVALID');
|
|
96
|
+
}
|
|
97
|
+
return raw.hasEvent(input, normalizeMemoryAccess(access, input));
|
|
98
|
+
},
|
|
99
|
+
verify: (input, access) => raw.verify(input, normalizeMemoryAccess(access, input)),
|
|
100
|
+
claimAttention: (input, access) => raw.claimAttention(input, normalizeMemoryAccess(access, input)),
|
|
101
|
+
authorizeAttention: (input, access) => raw.authorizeAttention(input, normalizeMemoryAccess(access, input)),
|
|
102
|
+
close: () => raw.close(),
|
|
103
|
+
};
|
|
104
|
+
return Object.freeze(guarded);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function createLocalCognitiveMemoryAdapter({ home } = {}) {
|
|
108
|
+
const store = openCognitiveStateStore({ home });
|
|
109
|
+
return guardCognitiveMemoryAdapter({
|
|
110
|
+
contractVersion: COGNITIVE_MEMORY_ADAPTER_VERSION,
|
|
111
|
+
kind: 'local-cognitive-event-store',
|
|
112
|
+
commit: (input) => store.commit(input),
|
|
113
|
+
read: (input) => store.read(input),
|
|
114
|
+
hasEvent: (input) => store.hasEvent(input),
|
|
115
|
+
verify: (input) => store.verify(input),
|
|
116
|
+
claimAttention: (input) => store.claimAttention(input),
|
|
117
|
+
authorizeAttention: (input) => store.authorizeAttention(input),
|
|
118
|
+
close: () => store.close(),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function openCognitiveMemoryAdapter({ home, adapter } = {}) {
|
|
123
|
+
return adapter === undefined
|
|
124
|
+
? createLocalCognitiveMemoryAdapter({ home })
|
|
125
|
+
: guardCognitiveMemoryAdapter(adapter);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
module.exports = {
|
|
129
|
+
COGNITIVE_MEMORY_ADAPTER_VERSION,
|
|
130
|
+
REQUIRED_METHODS,
|
|
131
|
+
assertCognitiveMemoryAdapter,
|
|
132
|
+
createLocalCognitiveMemoryAdapter,
|
|
133
|
+
normalizeMemoryAccess,
|
|
134
|
+
openCognitiveMemoryAdapter,
|
|
135
|
+
};
|
|
@@ -289,8 +289,18 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
289
289
|
};
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
function hasEvent(
|
|
293
|
-
|
|
292
|
+
function hasEvent(input) {
|
|
293
|
+
if (input && typeof input === 'object' && !Array.isArray(input)) {
|
|
294
|
+
const keys = Object.keys(input);
|
|
295
|
+
const event = safeId(input.eventId);
|
|
296
|
+
const tenant = safeId(input.tenantId);
|
|
297
|
+
const agent = safeId(input.agentId);
|
|
298
|
+
if (keys.length !== 3 || !keys.every((key) => ['agentId', 'eventId', 'tenantId'].includes(key))
|
|
299
|
+
|| !event || !tenant || !agent) fail('COGNITIVE_INVALID_EVENT');
|
|
300
|
+
return Boolean(db.prepare(`SELECT 1 AS found FROM cognitive_events
|
|
301
|
+
WHERE event_id = ? AND tenant_id = ? AND agent_id = ?`).get(event, tenant, agent));
|
|
302
|
+
}
|
|
303
|
+
const event = safeId(input);
|
|
294
304
|
if (!event) fail('COGNITIVE_INVALID_EVENT');
|
|
295
305
|
return Boolean(db.prepare('SELECT 1 AS found FROM cognitive_events WHERE event_id = ?').get(event));
|
|
296
306
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const crypto = require('node:crypto');
|
|
4
4
|
const fs = require('node:fs');
|
|
5
5
|
const path = require('node:path');
|
|
6
|
-
const {
|
|
6
|
+
const { openCognitiveMemoryAdapter } = require('./cognitive-memory-adapter.cjs');
|
|
7
7
|
const { buildCognitiveContextProjection } = require('./cognitive-context-projection.cjs');
|
|
8
8
|
const { buildCognitiveFocusProjection } = require('./cognitive-focus-projection.cjs');
|
|
9
9
|
const { authorizeAttentionCandidate } = require('./cognitive-attention-runtime.cjs');
|
|
@@ -69,12 +69,34 @@ function identityFromManifest(home) {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
function createCognitiveTurnLifecycle({
|
|
72
|
+
function createCognitiveTurnLifecycle({
|
|
73
|
+
home,
|
|
74
|
+
tenantId,
|
|
75
|
+
agentId,
|
|
76
|
+
runtimeId,
|
|
77
|
+
memoryAdapter,
|
|
78
|
+
now = () => new Date().toISOString(),
|
|
79
|
+
} = {}) {
|
|
73
80
|
const tenant = safeId(tenantId);
|
|
74
81
|
const agent = safeId(agentId);
|
|
75
82
|
const runtime = safeId(runtimeId ?? `runtime-${process.pid}-${Date.now()}`);
|
|
76
83
|
if (!tenant || !agent || !runtime || typeof now !== 'function') fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
77
|
-
const store =
|
|
84
|
+
const store = openCognitiveMemoryAdapter({ home, adapter: memoryAdapter });
|
|
85
|
+
const internalMemoryAccess = Object.freeze({
|
|
86
|
+
tenantId: tenant,
|
|
87
|
+
userId: agent,
|
|
88
|
+
actorId: agent,
|
|
89
|
+
agentId: agent,
|
|
90
|
+
portalId: 'cli',
|
|
91
|
+
channelId: 'runtime',
|
|
92
|
+
conversationId: runtime,
|
|
93
|
+
requestedScope: 'agent:memory',
|
|
94
|
+
permissionContext: Object.freeze({
|
|
95
|
+
authority: 'runtime_internal',
|
|
96
|
+
decision: 'passed',
|
|
97
|
+
receiptId: runtime,
|
|
98
|
+
}),
|
|
99
|
+
});
|
|
78
100
|
const stageTimes = new Map();
|
|
79
101
|
const stageResults = new Map();
|
|
80
102
|
|
|
@@ -97,7 +119,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
97
119
|
...item,
|
|
98
120
|
}));
|
|
99
121
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
100
|
-
const expectedVersion = store.read({ tenantId: tenant, agentId: agent }).version;
|
|
122
|
+
const expectedVersion = store.read({ tenantId: tenant, agentId: agent }, internalMemoryAccess).version;
|
|
101
123
|
try {
|
|
102
124
|
const result = store.commit({
|
|
103
125
|
tenantId: tenant,
|
|
@@ -112,7 +134,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
112
134
|
message_id: stageKey,
|
|
113
135
|
},
|
|
114
136
|
observations: normalized,
|
|
115
|
-
});
|
|
137
|
+
}, internalMemoryAccess);
|
|
116
138
|
stageResults.set(stageKey, result);
|
|
117
139
|
return result;
|
|
118
140
|
} catch (error) {
|
|
@@ -125,7 +147,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
125
147
|
function commitDurableStage(stageKey, observations) {
|
|
126
148
|
if (stageResults.has(stageKey)) return { ...stageResults.get(stageKey), idempotent: true };
|
|
127
149
|
const eventId = digestId('durable', [tenant, agent, stageKey]);
|
|
128
|
-
if (store.hasEvent(eventId)) {
|
|
150
|
+
if (store.hasEvent({ eventId, tenantId: tenant, agentId: agent }, internalMemoryAccess)) {
|
|
129
151
|
const result = { idempotent: true };
|
|
130
152
|
stageResults.set(stageKey, result);
|
|
131
153
|
return result;
|
|
@@ -136,12 +158,12 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
136
158
|
...item,
|
|
137
159
|
}));
|
|
138
160
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
139
|
-
if (store.hasEvent(eventId)) {
|
|
161
|
+
if (store.hasEvent({ eventId, tenantId: tenant, agentId: agent }, internalMemoryAccess)) {
|
|
140
162
|
const result = { idempotent: true };
|
|
141
163
|
stageResults.set(stageKey, result);
|
|
142
164
|
return result;
|
|
143
165
|
}
|
|
144
|
-
const expectedVersion = store.read({ tenantId: tenant, agentId: agent }).version;
|
|
166
|
+
const expectedVersion = store.read({ tenantId: tenant, agentId: agent }, internalMemoryAccess).version;
|
|
145
167
|
try {
|
|
146
168
|
const result = store.commit({
|
|
147
169
|
tenantId: tenant,
|
|
@@ -156,7 +178,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
156
178
|
message_id: stageKey,
|
|
157
179
|
},
|
|
158
180
|
observations: normalized,
|
|
159
|
-
});
|
|
181
|
+
}, internalMemoryAccess);
|
|
160
182
|
stageResults.set(stageKey, result);
|
|
161
183
|
return result;
|
|
162
184
|
} catch (error) {
|
|
@@ -281,8 +303,23 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
281
303
|
...(correction ? { supersedes: targetObservationId } : { withdraws: targetObservationId }),
|
|
282
304
|
};
|
|
283
305
|
const normalizedOccurredAt = new Date(occurredAt).toISOString();
|
|
306
|
+
const revisionMemoryAccess = {
|
|
307
|
+
tenantId: tenant,
|
|
308
|
+
userId: normalizedSource.actor_id,
|
|
309
|
+
actorId: normalizedSource.actor_id,
|
|
310
|
+
agentId: agent,
|
|
311
|
+
portalId: normalizedSource.provider,
|
|
312
|
+
channelId: normalizedSource.provider,
|
|
313
|
+
conversationId: normalizedSource.context_id,
|
|
314
|
+
requestedScope: scope,
|
|
315
|
+
permissionContext: {
|
|
316
|
+
authority: input.authority,
|
|
317
|
+
decision: 'passed',
|
|
318
|
+
receiptId: requestId,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
284
321
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
285
|
-
const current = store.read({ tenantId: tenant, agentId: agent });
|
|
322
|
+
const current = store.read({ tenantId: tenant, agentId: agent }, revisionMemoryAccess);
|
|
286
323
|
const existing = current.observations.find((item) => item.observation_id === observationId);
|
|
287
324
|
if (existing) {
|
|
288
325
|
const matches = existing.domain === observation.domain && existing.key === observation.key
|
|
@@ -310,7 +347,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
310
347
|
occurredAt: normalizedOccurredAt,
|
|
311
348
|
source: normalizedSource,
|
|
312
349
|
observations: [observation],
|
|
313
|
-
});
|
|
350
|
+
}, revisionMemoryAccess);
|
|
314
351
|
} catch (error) {
|
|
315
352
|
if (error?.code !== 'COGNITIVE_VERSION_CONFLICT' || attempt === 3) throw error;
|
|
316
353
|
}
|
|
@@ -407,7 +444,7 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
407
444
|
if (!exactKeys(input, new Set(['turnId', 'focusScopes']))) fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
408
445
|
const turnId = safeTurnId(input.turnId);
|
|
409
446
|
if (turnId === null) fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
410
|
-
const state = store.read({ tenantId: tenant, agentId: agent });
|
|
447
|
+
const state = store.read({ tenantId: tenant, agentId: agent }, internalMemoryAccess);
|
|
411
448
|
const continuity = buildCognitiveContextProjection(state, {
|
|
412
449
|
currentTurnId: turnId,
|
|
413
450
|
currentRuntimeId: runtime,
|
|
@@ -417,12 +454,30 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
417
454
|
}
|
|
418
455
|
|
|
419
456
|
function authorizeAttention(input) {
|
|
457
|
+
const candidate = input?.candidate;
|
|
458
|
+
const authorization = input?.authorization;
|
|
459
|
+
const memoryAccess = {
|
|
460
|
+
tenantId: tenant,
|
|
461
|
+
userId: String(candidate?.subject_id ?? ''),
|
|
462
|
+
actorId: agent,
|
|
463
|
+
agentId: agent,
|
|
464
|
+
portalId: 'cli',
|
|
465
|
+
channelId: String(input?.channel ?? ''),
|
|
466
|
+
conversationId: runtime,
|
|
467
|
+
requestedScope: String(candidate?.evidence_scope ?? ''),
|
|
468
|
+
permissionContext: {
|
|
469
|
+
authority: String(authorization?.authority ?? ''),
|
|
470
|
+
decision: authorization?.decision === 'passed' ? 'passed' : 'blocked',
|
|
471
|
+
receiptId: String(authorization?.receiptId ?? ''),
|
|
472
|
+
},
|
|
473
|
+
};
|
|
420
474
|
return authorizeAttentionCandidate({
|
|
421
475
|
store,
|
|
422
476
|
tenantId: tenant,
|
|
423
477
|
currentAgent: agent,
|
|
424
478
|
now,
|
|
425
479
|
input,
|
|
480
|
+
memoryAccess,
|
|
426
481
|
});
|
|
427
482
|
}
|
|
428
483
|
|
|
@@ -438,13 +493,21 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
|
|
|
438
493
|
authorizeAttention,
|
|
439
494
|
projectForTurn,
|
|
440
495
|
endTurn,
|
|
441
|
-
read: () => store.read({ tenantId: tenant, agentId: agent }),
|
|
442
|
-
verify: () => store.verify({ tenantId: tenant, agentId: agent }),
|
|
496
|
+
read: () => store.read({ tenantId: tenant, agentId: agent }, internalMemoryAccess),
|
|
497
|
+
verify: () => store.verify({ tenantId: tenant, agentId: agent }, internalMemoryAccess),
|
|
443
498
|
close: () => store.close(),
|
|
444
499
|
};
|
|
445
500
|
}
|
|
446
501
|
|
|
447
|
-
function createRuntimeCognitiveTurnLifecycle({
|
|
502
|
+
function createRuntimeCognitiveTurnLifecycle({
|
|
503
|
+
home,
|
|
504
|
+
agentName,
|
|
505
|
+
tenantId,
|
|
506
|
+
agentId,
|
|
507
|
+
runtimeId,
|
|
508
|
+
memoryAdapter,
|
|
509
|
+
now,
|
|
510
|
+
} = {}) {
|
|
448
511
|
const resolvedHome = String(home ?? '').trim();
|
|
449
512
|
const resolvedAgent = String(agentName ?? '').trim();
|
|
450
513
|
if (!resolvedHome || !resolvedAgent) fail('COGNITIVE_LIFECYCLE_INVALID');
|
|
@@ -464,6 +527,7 @@ function createRuntimeCognitiveTurnLifecycle({ home, agentName, tenantId, agentI
|
|
|
464
527
|
tenantId: hasSharedIdentity ? identity.tenantId : digestId('home', [resolvedHome.toLowerCase()]),
|
|
465
528
|
agentId: hasSharedIdentity ? identity.agentId : digestId('agent', [resolvedAgent.toLowerCase()]),
|
|
466
529
|
runtimeId,
|
|
530
|
+
memoryAdapter,
|
|
467
531
|
now,
|
|
468
532
|
});
|
|
469
533
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const crypto = require('node:crypto');
|
|
4
4
|
const fs = require('node:fs');
|
|
5
5
|
const path = require('node:path');
|
|
6
|
-
const {
|
|
6
|
+
const { openCognitiveMemoryAdapter } = require('./cognitive-memory-adapter.cjs');
|
|
7
7
|
|
|
8
8
|
const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
9
9
|
const SENSITIVITIES = new Set(['low', 'medium']);
|
|
@@ -65,7 +65,7 @@ function normalizePresentation(input) {
|
|
|
65
65
|
return normalized;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
function createPersonalityMemoryAdapter({ identityRoot } = {}) {
|
|
68
|
+
function createPersonalityMemoryAdapter({ identityRoot, memoryAdapter } = {}) {
|
|
69
69
|
const root = path.resolve(String(identityRoot ?? ''));
|
|
70
70
|
try {
|
|
71
71
|
const stat = fs.lstatSync(root);
|
|
@@ -78,7 +78,7 @@ function createPersonalityMemoryAdapter({ identityRoot } = {}) {
|
|
|
78
78
|
}
|
|
79
79
|
const realRoot = fs.realpathSync(root);
|
|
80
80
|
const home = path.dirname(realRoot);
|
|
81
|
-
const store =
|
|
81
|
+
const store = openCognitiveMemoryAdapter({ home, adapter: memoryAdapter });
|
|
82
82
|
|
|
83
83
|
function claimCuriosityPresentation(input) {
|
|
84
84
|
const value = normalizePresentation(input);
|
|
@@ -87,7 +87,24 @@ function createPersonalityMemoryAdapter({ identityRoot } = {}) {
|
|
|
87
87
|
value.tenantId, value.agentId, value.actorId, value.sourcePortal, value.sourceChannel,
|
|
88
88
|
value.conversationId, value.messageId, value.occurredAt, value.topic,
|
|
89
89
|
]);
|
|
90
|
-
|
|
90
|
+
const memoryAccess = {
|
|
91
|
+
tenantId: value.tenantId,
|
|
92
|
+
userId: value.actorId,
|
|
93
|
+
actorId: value.actorId,
|
|
94
|
+
agentId: value.agentId,
|
|
95
|
+
portalId: value.sourcePortal,
|
|
96
|
+
channelId: value.sourceChannel,
|
|
97
|
+
conversationId: value.conversationId,
|
|
98
|
+
requestedScope: relationshipScope(value.actorId),
|
|
99
|
+
permissionContext: {
|
|
100
|
+
authority: 'runtime_personality_policy',
|
|
101
|
+
decision: 'passed',
|
|
102
|
+
receiptId: eventId,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
if (store.hasEvent({ eventId, tenantId: value.tenantId, agentId: value.agentId }, memoryAccess)) {
|
|
106
|
+
return { claimed: true, idempotent: true };
|
|
107
|
+
}
|
|
91
108
|
const claim = store.claimAttention({
|
|
92
109
|
tenantId: value.tenantId,
|
|
93
110
|
candidate: {
|
|
@@ -107,10 +124,10 @@ function createPersonalityMemoryAdapter({ identityRoot } = {}) {
|
|
|
107
124
|
},
|
|
108
125
|
claimedBy: value.agentId,
|
|
109
126
|
claimedAt: value.occurredAt,
|
|
110
|
-
});
|
|
127
|
+
}, memoryAccess);
|
|
111
128
|
if (!claim.claimed) return { claimed: false, next_allowed_at: claim.next_allowed_at };
|
|
112
129
|
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
113
|
-
const current = store.read({ tenantId: value.tenantId, agentId: value.agentId });
|
|
130
|
+
const current = store.read({ tenantId: value.tenantId, agentId: value.agentId }, memoryAccess);
|
|
114
131
|
try {
|
|
115
132
|
store.commit({
|
|
116
133
|
tenantId: value.tenantId,
|
|
@@ -133,7 +150,7 @@ function createPersonalityMemoryAdapter({ identityRoot } = {}) {
|
|
|
133
150
|
epistemic_state: 'verified',
|
|
134
151
|
scope: relationshipScope(value.actorId),
|
|
135
152
|
}],
|
|
136
|
-
});
|
|
153
|
+
}, memoryAccess);
|
|
137
154
|
return { claimed: true, idempotent: false };
|
|
138
155
|
} catch (error) {
|
|
139
156
|
if (error?.code !== 'COGNITIVE_VERSION_CONFLICT' || attempt === 2) throw error;
|