blun-king-cli 9.1.387 → 9.1.388
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.
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { openCognitiveStateStore } = require('./cognitive-state-store.cjs');
|
|
4
4
|
|
|
5
|
-
const COGNITIVE_MEMORY_ADAPTER_VERSION =
|
|
5
|
+
const COGNITIVE_MEMORY_ADAPTER_VERSION = 3;
|
|
6
6
|
const KIND_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
|
|
7
7
|
const ACCESS_KEYS = Object.freeze([
|
|
8
8
|
'actorId', 'agentId', 'channelId', 'conversationId', 'permissionContext',
|
|
@@ -69,6 +69,46 @@ function normalizeMemoryAccess(access, request) {
|
|
|
69
69
|
return Object.freeze(normalized);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
function isInternalAgentAccess(access) {
|
|
73
|
+
return access.userId === access.agentId
|
|
74
|
+
&& access.actorId === access.agentId
|
|
75
|
+
&& access.portalId === 'cli'
|
|
76
|
+
&& access.channelId === 'runtime'
|
|
77
|
+
&& access.requestedScope === 'agent:memory'
|
|
78
|
+
&& access.permissionContext.authority === 'runtime_internal'
|
|
79
|
+
&& access.permissionContext.receiptId === access.conversationId;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function assertVisibleScope(scope, access) {
|
|
83
|
+
if (!isInternalAgentAccess(access) && safeId(scope) !== access.requestedScope) {
|
|
84
|
+
fail('COGNITIVE_MEMORY_VISIBILITY_DENIED');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function assertCommitAccess(input, access) {
|
|
89
|
+
if (isInternalAgentAccess(access)) return;
|
|
90
|
+
if (!Array.isArray(input?.observations) || input.observations.length < 1) {
|
|
91
|
+
fail('COGNITIVE_MEMORY_VISIBILITY_DENIED');
|
|
92
|
+
}
|
|
93
|
+
for (const observation of input.observations) assertVisibleScope(observation?.scope, access);
|
|
94
|
+
if (safeId(input?.source?.provider) !== access.portalId
|
|
95
|
+
|| safeId(input?.source?.actor_id) !== access.actorId
|
|
96
|
+
|| safeId(input?.source?.context_id) !== access.conversationId) {
|
|
97
|
+
fail('COGNITIVE_MEMORY_SOURCE_MISMATCH');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function projectReadableState(state, access) {
|
|
102
|
+
if (isInternalAgentAccess(access)) return state;
|
|
103
|
+
if (!state || typeof state !== 'object' || !Array.isArray(state.observations)) {
|
|
104
|
+
fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
...state,
|
|
108
|
+
observations: state.observations.filter((item) => safeId(item?.scope) === access.requestedScope),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
72
112
|
function assertCognitiveMemoryAdapter(adapter) {
|
|
73
113
|
if (!adapter || typeof adapter !== 'object' || Array.isArray(adapter)) {
|
|
74
114
|
fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
@@ -88,17 +128,41 @@ function guardCognitiveMemoryAdapter(adapter) {
|
|
|
88
128
|
const guarded = {
|
|
89
129
|
contractVersion: raw.contractVersion,
|
|
90
130
|
kind: raw.kind,
|
|
91
|
-
commit: (input, access) =>
|
|
92
|
-
|
|
131
|
+
commit: (input, access) => {
|
|
132
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
133
|
+
assertCommitAccess(input, normalizedAccess);
|
|
134
|
+
return raw.commit(input, normalizedAccess);
|
|
135
|
+
},
|
|
136
|
+
read: (input, access) => {
|
|
137
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
138
|
+
return projectReadableState(raw.read(input, normalizedAccess), normalizedAccess);
|
|
139
|
+
},
|
|
93
140
|
hasEvent: (input, access) => {
|
|
94
|
-
if (!exactKeys(input, ['agentId', 'eventId', 'tenantId'])
|
|
141
|
+
if (!exactKeys(input, ['agentId', 'eventId', 'tenantId', 'visibilityScope'])
|
|
142
|
+
|| !safeId(input.eventId) || !safeId(input.visibilityScope)) {
|
|
95
143
|
fail('COGNITIVE_MEMORY_ACCESS_INVALID');
|
|
96
144
|
}
|
|
97
|
-
|
|
145
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
146
|
+
assertVisibleScope(input.visibilityScope, normalizedAccess);
|
|
147
|
+
return raw.hasEvent(input, normalizedAccess);
|
|
148
|
+
},
|
|
149
|
+
verify: (input, access) => {
|
|
150
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
151
|
+
const result = raw.verify(input, normalizedAccess);
|
|
152
|
+
if (isInternalAgentAccess(normalizedAccess)) return result;
|
|
153
|
+
if (!result || typeof result.valid !== 'boolean') fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
154
|
+
return { valid: result.valid };
|
|
155
|
+
},
|
|
156
|
+
claimAttention: (input, access) => {
|
|
157
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
158
|
+
assertVisibleScope(input?.candidate?.evidence_scope, normalizedAccess);
|
|
159
|
+
return raw.claimAttention(input, normalizedAccess);
|
|
160
|
+
},
|
|
161
|
+
authorizeAttention: (input, access) => {
|
|
162
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
163
|
+
assertVisibleScope(input?.candidate?.evidence_scope, normalizedAccess);
|
|
164
|
+
return raw.authorizeAttention(input, normalizedAccess);
|
|
98
165
|
},
|
|
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
166
|
close: () => raw.close(),
|
|
103
167
|
};
|
|
104
168
|
return Object.freeze(guarded);
|
|
@@ -110,7 +174,10 @@ function createLocalCognitiveMemoryAdapter({ home } = {}) {
|
|
|
110
174
|
contractVersion: COGNITIVE_MEMORY_ADAPTER_VERSION,
|
|
111
175
|
kind: 'local-cognitive-event-store',
|
|
112
176
|
commit: (input) => store.commit(input),
|
|
113
|
-
read: (input) => store.read(
|
|
177
|
+
read: (input, access) => store.read({
|
|
178
|
+
...input,
|
|
179
|
+
visibilityScope: isInternalAgentAccess(access) ? 'agent:memory' : access.requestedScope,
|
|
180
|
+
}),
|
|
114
181
|
hasEvent: (input) => store.hasEvent(input),
|
|
115
182
|
verify: (input) => store.verify(input),
|
|
116
183
|
claimAttention: (input) => store.claimAttention(input),
|
|
@@ -167,6 +167,8 @@ function initialize(db) {
|
|
|
167
167
|
);
|
|
168
168
|
CREATE INDEX IF NOT EXISTS cognitive_observations_stream
|
|
169
169
|
ON cognitive_observations (tenant_id, agent_id, occurred_at, observation_id);
|
|
170
|
+
CREATE INDEX IF NOT EXISTS cognitive_observations_visibility
|
|
171
|
+
ON cognitive_observations (tenant_id, agent_id, scope, occurred_at, observation_id);
|
|
170
172
|
CREATE TABLE IF NOT EXISTS cognitive_attention_claims (
|
|
171
173
|
tenant_id TEXT NOT NULL,
|
|
172
174
|
candidate_id TEXT NOT NULL,
|
|
@@ -262,14 +264,20 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
265
|
-
function read({ tenantId, agentId } = {}) {
|
|
267
|
+
function read({ tenantId, agentId, visibilityScope } = {}) {
|
|
266
268
|
const tenant = safeId(tenantId);
|
|
267
269
|
const agent = safeId(agentId);
|
|
268
|
-
|
|
270
|
+
const requestedVisibility = visibilityScope === undefined ? '' : safeId(visibilityScope);
|
|
271
|
+
if (!tenant || !agent || (visibilityScope !== undefined && !requestedVisibility)) {
|
|
272
|
+
fail('COGNITIVE_INVALID_EVENT');
|
|
273
|
+
}
|
|
269
274
|
const stream = db.prepare('SELECT version, updated_at FROM cognitive_streams WHERE tenant_id = ? AND agent_id = ?').get(tenant, agent);
|
|
270
|
-
const
|
|
271
|
-
supersedes_observation_id, withdraws_observation_id
|
|
272
|
-
|
|
275
|
+
const select = `SELECT domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, observation_id,
|
|
276
|
+
supersedes_observation_id, withdraws_observation_id FROM cognitive_observations`;
|
|
277
|
+
const rows = requestedVisibility && requestedVisibility !== 'agent:memory'
|
|
278
|
+
? db.prepare(`${select} WHERE tenant_id = ? AND agent_id = ? AND scope = ? ORDER BY occurred_at, rowid`)
|
|
279
|
+
.all(tenant, agent, requestedVisibility)
|
|
280
|
+
: db.prepare(`${select} WHERE tenant_id = ? AND agent_id = ? ORDER BY occurred_at, rowid`).all(tenant, agent);
|
|
273
281
|
return {
|
|
274
282
|
version: Number(stream?.version ?? 0),
|
|
275
283
|
...(stream?.updated_at ? { updated_at: stream.updated_at } : {}),
|
|
@@ -295,8 +303,16 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
295
303
|
const event = safeId(input.eventId);
|
|
296
304
|
const tenant = safeId(input.tenantId);
|
|
297
305
|
const agent = safeId(input.agentId);
|
|
298
|
-
|
|
299
|
-
|
|
306
|
+
const visibilityScope = safeId(input.visibilityScope);
|
|
307
|
+
if (keys.length !== 4
|
|
308
|
+
|| !keys.every((key) => ['agentId', 'eventId', 'tenantId', 'visibilityScope'].includes(key))
|
|
309
|
+
|| !event || !tenant || !agent || !visibilityScope) fail('COGNITIVE_INVALID_EVENT');
|
|
310
|
+
if (visibilityScope !== 'agent:memory') {
|
|
311
|
+
return Boolean(db.prepare(`SELECT 1 AS found FROM cognitive_events AS event
|
|
312
|
+
INNER JOIN cognitive_observations AS observation ON observation.event_id = event.event_id
|
|
313
|
+
WHERE event.event_id = ? AND event.tenant_id = ? AND event.agent_id = ? AND observation.scope = ?
|
|
314
|
+
LIMIT 1`).get(event, tenant, agent, visibilityScope));
|
|
315
|
+
}
|
|
300
316
|
return Boolean(db.prepare(`SELECT 1 AS found FROM cognitive_events
|
|
301
317
|
WHERE event_id = ? AND tenant_id = ? AND agent_id = ?`).get(event, tenant, agent));
|
|
302
318
|
}
|
|
@@ -147,7 +147,9 @@ function createCognitiveTurnLifecycle({
|
|
|
147
147
|
function commitDurableStage(stageKey, observations) {
|
|
148
148
|
if (stageResults.has(stageKey)) return { ...stageResults.get(stageKey), idempotent: true };
|
|
149
149
|
const eventId = digestId('durable', [tenant, agent, stageKey]);
|
|
150
|
-
if (store.hasEvent({
|
|
150
|
+
if (store.hasEvent({
|
|
151
|
+
eventId, tenantId: tenant, agentId: agent, visibilityScope: 'agent:memory',
|
|
152
|
+
}, internalMemoryAccess)) {
|
|
151
153
|
const result = { idempotent: true };
|
|
152
154
|
stageResults.set(stageKey, result);
|
|
153
155
|
return result;
|
|
@@ -158,7 +160,9 @@ function createCognitiveTurnLifecycle({
|
|
|
158
160
|
...item,
|
|
159
161
|
}));
|
|
160
162
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
161
|
-
if (store.hasEvent({
|
|
163
|
+
if (store.hasEvent({
|
|
164
|
+
eventId, tenantId: tenant, agentId: agent, visibilityScope: 'agent:memory',
|
|
165
|
+
}, internalMemoryAccess)) {
|
|
162
166
|
const result = { idempotent: true };
|
|
163
167
|
stageResults.set(stageKey, result);
|
|
164
168
|
return result;
|
|
@@ -102,7 +102,10 @@ function createPersonalityMemoryAdapter({ identityRoot, memoryAdapter } = {}) {
|
|
|
102
102
|
receiptId: eventId,
|
|
103
103
|
},
|
|
104
104
|
};
|
|
105
|
-
if (store.hasEvent({
|
|
105
|
+
if (store.hasEvent({
|
|
106
|
+
eventId, tenantId: value.tenantId, agentId: value.agentId,
|
|
107
|
+
visibilityScope: relationshipScope(value.actorId),
|
|
108
|
+
}, memoryAccess)) {
|
|
106
109
|
return { claimed: true, idempotent: true };
|
|
107
110
|
}
|
|
108
111
|
const claim = store.claimAttention({
|