blun-king-cli 9.1.387 → 9.1.389
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 = 4;
|
|
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,47 @@ 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?.channel_id) !== access.channelId
|
|
96
|
+
|| safeId(input?.source?.actor_id) !== access.actorId
|
|
97
|
+
|| safeId(input?.source?.context_id) !== access.conversationId) {
|
|
98
|
+
fail('COGNITIVE_MEMORY_SOURCE_MISMATCH');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function projectReadableState(state, access) {
|
|
103
|
+
if (isInternalAgentAccess(access)) return state;
|
|
104
|
+
if (!state || typeof state !== 'object' || !Array.isArray(state.observations)) {
|
|
105
|
+
fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
...state,
|
|
109
|
+
observations: state.observations.filter((item) => safeId(item?.scope) === access.requestedScope),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
72
113
|
function assertCognitiveMemoryAdapter(adapter) {
|
|
73
114
|
if (!adapter || typeof adapter !== 'object' || Array.isArray(adapter)) {
|
|
74
115
|
fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
@@ -88,17 +129,41 @@ function guardCognitiveMemoryAdapter(adapter) {
|
|
|
88
129
|
const guarded = {
|
|
89
130
|
contractVersion: raw.contractVersion,
|
|
90
131
|
kind: raw.kind,
|
|
91
|
-
commit: (input, access) =>
|
|
92
|
-
|
|
132
|
+
commit: (input, access) => {
|
|
133
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
134
|
+
assertCommitAccess(input, normalizedAccess);
|
|
135
|
+
return raw.commit(input, normalizedAccess);
|
|
136
|
+
},
|
|
137
|
+
read: (input, access) => {
|
|
138
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
139
|
+
return projectReadableState(raw.read(input, normalizedAccess), normalizedAccess);
|
|
140
|
+
},
|
|
93
141
|
hasEvent: (input, access) => {
|
|
94
|
-
if (!exactKeys(input, ['agentId', 'eventId', 'tenantId'])
|
|
142
|
+
if (!exactKeys(input, ['agentId', 'eventId', 'tenantId', 'visibilityScope'])
|
|
143
|
+
|| !safeId(input.eventId) || !safeId(input.visibilityScope)) {
|
|
95
144
|
fail('COGNITIVE_MEMORY_ACCESS_INVALID');
|
|
96
145
|
}
|
|
97
|
-
|
|
146
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
147
|
+
assertVisibleScope(input.visibilityScope, normalizedAccess);
|
|
148
|
+
return raw.hasEvent(input, normalizedAccess);
|
|
149
|
+
},
|
|
150
|
+
verify: (input, access) => {
|
|
151
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
152
|
+
const result = raw.verify(input, normalizedAccess);
|
|
153
|
+
if (isInternalAgentAccess(normalizedAccess)) return result;
|
|
154
|
+
if (!result || typeof result.valid !== 'boolean') fail('COGNITIVE_MEMORY_ADAPTER_INVALID');
|
|
155
|
+
return { valid: result.valid };
|
|
156
|
+
},
|
|
157
|
+
claimAttention: (input, access) => {
|
|
158
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
159
|
+
assertVisibleScope(input?.candidate?.evidence_scope, normalizedAccess);
|
|
160
|
+
return raw.claimAttention(input, normalizedAccess);
|
|
161
|
+
},
|
|
162
|
+
authorizeAttention: (input, access) => {
|
|
163
|
+
const normalizedAccess = normalizeMemoryAccess(access, input);
|
|
164
|
+
assertVisibleScope(input?.candidate?.evidence_scope, normalizedAccess);
|
|
165
|
+
return raw.authorizeAttention(input, normalizedAccess);
|
|
98
166
|
},
|
|
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
167
|
close: () => raw.close(),
|
|
103
168
|
};
|
|
104
169
|
return Object.freeze(guarded);
|
|
@@ -110,7 +175,10 @@ function createLocalCognitiveMemoryAdapter({ home } = {}) {
|
|
|
110
175
|
contractVersion: COGNITIVE_MEMORY_ADAPTER_VERSION,
|
|
111
176
|
kind: 'local-cognitive-event-store',
|
|
112
177
|
commit: (input) => store.commit(input),
|
|
113
|
-
read: (input) => store.read(
|
|
178
|
+
read: (input, access) => store.read({
|
|
179
|
+
...input,
|
|
180
|
+
visibilityScope: isInternalAgentAccess(access) ? 'agent:memory' : access.requestedScope,
|
|
181
|
+
}),
|
|
114
182
|
hasEvent: (input) => store.hasEvent(input),
|
|
115
183
|
verify: (input) => store.verify(input),
|
|
116
184
|
claimAttention: (input) => store.claimAttention(input),
|
|
@@ -110,6 +110,7 @@ function matchesRevisionReplay(items, target, command, commandSource) {
|
|
|
110
110
|
: item.withdraws === target.observationId && item.value === 'withdrawn';
|
|
111
111
|
return linked
|
|
112
112
|
&& item.source?.provider === commandSource.source.provider
|
|
113
|
+
&& item.source?.channel_id === commandSource.source.channelId
|
|
113
114
|
&& item.source?.actor_id === commandSource.source.actorId
|
|
114
115
|
&& item.source?.context_id === commandSource.source.contextId
|
|
115
116
|
&& item.source?.message_id === commandSource.source.messageId
|
|
@@ -133,6 +134,7 @@ function normalizeTelegramSource(source) {
|
|
|
133
134
|
occurredAt: timestamp,
|
|
134
135
|
source: {
|
|
135
136
|
provider: 'telegram',
|
|
137
|
+
channelId: 'direct',
|
|
136
138
|
actorId: `tg_user_${userId}`,
|
|
137
139
|
contextId: `tg_chat_${chatId}`,
|
|
138
140
|
messageId: `tg_message_${messageId}`,
|
|
@@ -153,6 +155,7 @@ function localSource({ env, sessionId, occurredAt, nonce }) {
|
|
|
153
155
|
occurredAt,
|
|
154
156
|
source: {
|
|
155
157
|
provider: 'cli',
|
|
158
|
+
channelId: 'terminal',
|
|
156
159
|
actorId: digestId('localuser', [actor]),
|
|
157
160
|
contextId: digestId('clisession', [session]),
|
|
158
161
|
messageId: digestId('cliinput', [unique]),
|
|
@@ -42,10 +42,11 @@ function exactKeys(value, keys) {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function normalizeSource(source) {
|
|
45
|
-
const allowed = new Set(['provider', 'actor_id', 'context_id', 'message_id']);
|
|
45
|
+
const allowed = new Set(['provider', 'channel_id', 'actor_id', 'context_id', 'message_id']);
|
|
46
46
|
if (!exactKeys(source, allowed) || hasForbiddenKey(source)) fail('COGNITIVE_FORBIDDEN_FIELD');
|
|
47
47
|
const normalized = {
|
|
48
48
|
provider: safeId(source.provider),
|
|
49
|
+
channel_id: safeId(source.channel_id),
|
|
49
50
|
actor_id: safeId(source.actor_id),
|
|
50
51
|
context_id: safeId(source.context_id),
|
|
51
52
|
message_id: safeId(source.message_id),
|
|
@@ -167,6 +168,8 @@ function initialize(db) {
|
|
|
167
168
|
);
|
|
168
169
|
CREATE INDEX IF NOT EXISTS cognitive_observations_stream
|
|
169
170
|
ON cognitive_observations (tenant_id, agent_id, occurred_at, observation_id);
|
|
171
|
+
CREATE INDEX IF NOT EXISTS cognitive_observations_visibility
|
|
172
|
+
ON cognitive_observations (tenant_id, agent_id, scope, occurred_at, observation_id);
|
|
170
173
|
CREATE TABLE IF NOT EXISTS cognitive_attention_claims (
|
|
171
174
|
tenant_id TEXT NOT NULL,
|
|
172
175
|
candidate_id TEXT NOT NULL,
|
|
@@ -262,14 +265,20 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
262
265
|
}
|
|
263
266
|
}
|
|
264
267
|
|
|
265
|
-
function read({ tenantId, agentId } = {}) {
|
|
268
|
+
function read({ tenantId, agentId, visibilityScope } = {}) {
|
|
266
269
|
const tenant = safeId(tenantId);
|
|
267
270
|
const agent = safeId(agentId);
|
|
268
|
-
|
|
271
|
+
const requestedVisibility = visibilityScope === undefined ? '' : safeId(visibilityScope);
|
|
272
|
+
if (!tenant || !agent || (visibilityScope !== undefined && !requestedVisibility)) {
|
|
273
|
+
fail('COGNITIVE_INVALID_EVENT');
|
|
274
|
+
}
|
|
269
275
|
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
|
-
|
|
276
|
+
const select = `SELECT domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, observation_id,
|
|
277
|
+
supersedes_observation_id, withdraws_observation_id FROM cognitive_observations`;
|
|
278
|
+
const rows = requestedVisibility && requestedVisibility !== 'agent:memory'
|
|
279
|
+
? db.prepare(`${select} WHERE tenant_id = ? AND agent_id = ? AND scope = ? ORDER BY occurred_at, rowid`)
|
|
280
|
+
.all(tenant, agent, requestedVisibility)
|
|
281
|
+
: db.prepare(`${select} WHERE tenant_id = ? AND agent_id = ? ORDER BY occurred_at, rowid`).all(tenant, agent);
|
|
273
282
|
return {
|
|
274
283
|
version: Number(stream?.version ?? 0),
|
|
275
284
|
...(stream?.updated_at ? { updated_at: stream.updated_at } : {}),
|
|
@@ -295,8 +304,16 @@ function openCognitiveStateStore({ home } = {}) {
|
|
|
295
304
|
const event = safeId(input.eventId);
|
|
296
305
|
const tenant = safeId(input.tenantId);
|
|
297
306
|
const agent = safeId(input.agentId);
|
|
298
|
-
|
|
299
|
-
|
|
307
|
+
const visibilityScope = safeId(input.visibilityScope);
|
|
308
|
+
if (keys.length !== 4
|
|
309
|
+
|| !keys.every((key) => ['agentId', 'eventId', 'tenantId', 'visibilityScope'].includes(key))
|
|
310
|
+
|| !event || !tenant || !agent || !visibilityScope) fail('COGNITIVE_INVALID_EVENT');
|
|
311
|
+
if (visibilityScope !== 'agent:memory') {
|
|
312
|
+
return Boolean(db.prepare(`SELECT 1 AS found FROM cognitive_events AS event
|
|
313
|
+
INNER JOIN cognitive_observations AS observation ON observation.event_id = event.event_id
|
|
314
|
+
WHERE event.event_id = ? AND event.tenant_id = ? AND event.agent_id = ? AND observation.scope = ?
|
|
315
|
+
LIMIT 1`).get(event, tenant, agent, visibilityScope));
|
|
316
|
+
}
|
|
300
317
|
return Boolean(db.prepare(`SELECT 1 AS found FROM cognitive_events
|
|
301
318
|
WHERE event_id = ? AND tenant_id = ? AND agent_id = ?`).get(event, tenant, agent));
|
|
302
319
|
}
|
|
@@ -129,6 +129,7 @@ function createCognitiveTurnLifecycle({
|
|
|
129
129
|
occurredAt,
|
|
130
130
|
source: {
|
|
131
131
|
provider: 'runtime',
|
|
132
|
+
channel_id: 'runtime',
|
|
132
133
|
actor_id: agent,
|
|
133
134
|
context_id: runtime,
|
|
134
135
|
message_id: stageKey,
|
|
@@ -147,7 +148,9 @@ function createCognitiveTurnLifecycle({
|
|
|
147
148
|
function commitDurableStage(stageKey, observations) {
|
|
148
149
|
if (stageResults.has(stageKey)) return { ...stageResults.get(stageKey), idempotent: true };
|
|
149
150
|
const eventId = digestId('durable', [tenant, agent, stageKey]);
|
|
150
|
-
if (store.hasEvent({
|
|
151
|
+
if (store.hasEvent({
|
|
152
|
+
eventId, tenantId: tenant, agentId: agent, visibilityScope: 'agent:memory',
|
|
153
|
+
}, internalMemoryAccess)) {
|
|
151
154
|
const result = { idempotent: true };
|
|
152
155
|
stageResults.set(stageKey, result);
|
|
153
156
|
return result;
|
|
@@ -158,7 +161,9 @@ function createCognitiveTurnLifecycle({
|
|
|
158
161
|
...item,
|
|
159
162
|
}));
|
|
160
163
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
161
|
-
if (store.hasEvent({
|
|
164
|
+
if (store.hasEvent({
|
|
165
|
+
eventId, tenantId: tenant, agentId: agent, visibilityScope: 'agent:memory',
|
|
166
|
+
}, internalMemoryAccess)) {
|
|
162
167
|
const result = { idempotent: true };
|
|
163
168
|
stageResults.set(stageKey, result);
|
|
164
169
|
return result;
|
|
@@ -173,6 +178,7 @@ function createCognitiveTurnLifecycle({
|
|
|
173
178
|
occurredAt,
|
|
174
179
|
source: {
|
|
175
180
|
provider: 'runtime',
|
|
181
|
+
channel_id: 'runtime',
|
|
176
182
|
actor_id: agent,
|
|
177
183
|
context_id: 'durable-focus',
|
|
178
184
|
message_id: stageKey,
|
|
@@ -278,11 +284,12 @@ function createCognitiveTurnLifecycle({
|
|
|
278
284
|
if (!requestId || !targetObservationId || !FOCUS_DOMAINS.has(domain) || !key
|
|
279
285
|
|| AUTHORITY_KEY_RE.test(key) || !scope || scope === 'runtime'
|
|
280
286
|
|| Number.isNaN(Date.parse(occurredAt))
|
|
281
|
-
|| !exactKeys(source, new Set(['provider', 'actorId', 'contextId', 'messageId']))) {
|
|
287
|
+
|| !exactKeys(source, new Set(['provider', 'channelId', 'actorId', 'contextId', 'messageId']))) {
|
|
282
288
|
fail('COGNITIVE_REVISION_INVALID');
|
|
283
289
|
}
|
|
284
290
|
const normalizedSource = {
|
|
285
291
|
provider: safeId(source.provider),
|
|
292
|
+
channel_id: safeId(source.channelId),
|
|
286
293
|
actor_id: safeId(source.actorId),
|
|
287
294
|
context_id: safeId(source.contextId),
|
|
288
295
|
message_id: safeId(source.messageId),
|
|
@@ -309,7 +316,7 @@ function createCognitiveTurnLifecycle({
|
|
|
309
316
|
actorId: normalizedSource.actor_id,
|
|
310
317
|
agentId: agent,
|
|
311
318
|
portalId: normalizedSource.provider,
|
|
312
|
-
channelId: normalizedSource.
|
|
319
|
+
channelId: normalizedSource.channel_id,
|
|
313
320
|
conversationId: normalizedSource.context_id,
|
|
314
321
|
requestedScope: scope,
|
|
315
322
|
permissionContext: {
|
|
@@ -328,6 +335,7 @@ function createCognitiveTurnLifecycle({
|
|
|
328
335
|
&& existing.supersedes === (observation.supersedes ?? null)
|
|
329
336
|
&& existing.withdraws === (observation.withdraws ?? null)
|
|
330
337
|
&& existing.source.provider === normalizedSource.provider
|
|
338
|
+
&& existing.source.channel_id === normalizedSource.channel_id
|
|
331
339
|
&& existing.source.actor_id === normalizedSource.actor_id
|
|
332
340
|
&& existing.source.context_id === normalizedSource.context_id
|
|
333
341
|
&& existing.source.message_id === normalizedSource.message_id;
|
|
@@ -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({
|
|
@@ -137,6 +140,7 @@ function createPersonalityMemoryAdapter({ identityRoot, memoryAdapter } = {}) {
|
|
|
137
140
|
occurredAt: value.occurredAt,
|
|
138
141
|
source: {
|
|
139
142
|
provider: value.sourcePortal,
|
|
143
|
+
channel_id: value.sourceChannel,
|
|
140
144
|
actor_id: value.actorId,
|
|
141
145
|
context_id: value.conversationId,
|
|
142
146
|
message_id: value.messageId,
|