blun-king-cli 9.1.389 → 9.1.391

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,13 +2,25 @@
2
2
 
3
3
  const { openCognitiveStateStore } = require('./cognitive-state-store.cjs');
4
4
 
5
- const COGNITIVE_MEMORY_ADAPTER_VERSION = 4;
5
+ const COGNITIVE_MEMORY_ADAPTER_VERSION = 6;
6
6
  const KIND_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
7
- const ACCESS_KEYS = Object.freeze([
7
+ const RETENTION_CLASSES = new Set(['operational', 'durable', 'relationship', 'audit']);
8
+ const ACCESS_REQUIRED_KEYS = Object.freeze([
8
9
  'actorId', 'agentId', 'channelId', 'conversationId', 'permissionContext',
9
10
  'portalId', 'requestedScope', 'tenantId', 'userId',
10
11
  ]);
11
- const PERMISSION_KEYS = Object.freeze(['authority', 'decision', 'receiptId']);
12
+ const ACCESS_OPTIONAL_KEYS = Object.freeze(['identityLink']);
13
+ const PERMISSION_REQUIRED_KEYS = Object.freeze(['authority', 'decision', 'receiptId']);
14
+ const PERMISSION_OPTIONAL_KEYS = Object.freeze(['identityReceiptId']);
15
+ const IDENTITY_LINK_KEYS = Object.freeze([
16
+ 'authority', 'canonicalUserId', 'confirmedAt', 'method', 'receiptId',
17
+ 'sourcePortal', 'sourceSubjectId', 'status', 'tenantId', 'version',
18
+ ]);
19
+ const IDENTITY_LINK_AUTHORITIES = new Map([
20
+ ['verified_oauth', 'oauth_verifier'],
21
+ ['secure_account_link', 'account_link_service'],
22
+ ['explicit_confirmed', 'identity_confirmation_service'],
23
+ ]);
12
24
  const REQUIRED_METHODS = Object.freeze([
13
25
  'commit',
14
26
  'read',
@@ -30,13 +42,70 @@ function exactKeys(value, expected) {
30
42
  && Object.keys(value).sort().join('\0') === [...expected].sort().join('\0');
31
43
  }
32
44
 
45
+ function requiredAndOptionalKeys(value, required, optional) {
46
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
47
+ const allowed = new Set([...required, ...optional]);
48
+ return required.every((key) => Object.prototype.hasOwnProperty.call(value, key))
49
+ && Object.keys(value).every((key) => allowed.has(key));
50
+ }
51
+
33
52
  function safeId(value) {
34
53
  const text = String(value ?? '').trim();
35
54
  return KIND_RE.test(text) ? text : '';
36
55
  }
37
56
 
57
+ function normalizeIdentityLink(access, normalized) {
58
+ const link = access.identityLink;
59
+ const identityReceiptId = normalized.permissionContext.identityReceiptId;
60
+ if (normalized.userId === normalized.actorId) {
61
+ if (link !== undefined || identityReceiptId !== undefined) fail('COGNITIVE_IDENTITY_LINK_INVALID');
62
+ return undefined;
63
+ }
64
+ if (link === undefined || link === null) fail('COGNITIVE_IDENTITY_LINK_REQUIRED');
65
+ if (!exactKeys(link, IDENTITY_LINK_KEYS)) fail('COGNITIVE_IDENTITY_LINK_INVALID');
66
+ if (String(link.status ?? '') === 'revoked') fail('COGNITIVE_IDENTITY_LINK_REVOKED');
67
+ const method = String(link.method ?? '');
68
+ const normalizedLink = {
69
+ version: Number(link.version),
70
+ tenantId: safeId(link.tenantId),
71
+ canonicalUserId: safeId(link.canonicalUserId),
72
+ sourcePortal: safeId(link.sourcePortal),
73
+ sourceSubjectId: safeId(link.sourceSubjectId),
74
+ method,
75
+ status: String(link.status ?? ''),
76
+ confirmedAt: String(link.confirmedAt ?? '').trim(),
77
+ authority: safeId(link.authority),
78
+ receiptId: safeId(link.receiptId),
79
+ };
80
+ if (normalizedLink.version !== 1 || normalizedLink.status !== 'active'
81
+ || Number.isNaN(Date.parse(normalizedLink.confirmedAt))
82
+ || IDENTITY_LINK_AUTHORITIES.get(method) !== normalizedLink.authority
83
+ || normalizedLink.tenantId !== normalized.tenantId
84
+ || normalizedLink.canonicalUserId !== normalized.userId
85
+ || normalizedLink.sourcePortal !== normalized.portalId
86
+ || normalizedLink.sourceSubjectId !== normalized.actorId
87
+ || !identityReceiptId || normalizedLink.receiptId !== identityReceiptId) {
88
+ fail('COGNITIVE_IDENTITY_LINK_INVALID');
89
+ }
90
+ const canonicalScope = `relationship:${normalized.userId}:private`;
91
+ const personalScope = `user:${normalized.userId}:private`;
92
+ if ((normalized.requestedScope.startsWith('relationship:') && normalized.requestedScope !== canonicalScope)
93
+ || (normalized.requestedScope.startsWith('user:') && normalized.requestedScope !== personalScope)) {
94
+ fail('COGNITIVE_IDENTITY_SCOPE_MISMATCH');
95
+ }
96
+ return Object.freeze({
97
+ ...normalizedLink,
98
+ confirmedAt: new Date(normalizedLink.confirmedAt).toISOString(),
99
+ });
100
+ }
101
+
38
102
  function normalizeMemoryAccess(access, request) {
39
- if (!exactKeys(access, ACCESS_KEYS) || !exactKeys(access.permissionContext, PERMISSION_KEYS)) {
103
+ if (!requiredAndOptionalKeys(access, ACCESS_REQUIRED_KEYS, ACCESS_OPTIONAL_KEYS)
104
+ || !requiredAndOptionalKeys(
105
+ access.permissionContext,
106
+ PERMISSION_REQUIRED_KEYS,
107
+ PERMISSION_OPTIONAL_KEYS,
108
+ )) {
40
109
  fail('COGNITIVE_MEMORY_ACCESS_INVALID');
41
110
  }
42
111
  const normalized = {
@@ -52,6 +121,9 @@ function normalizeMemoryAccess(access, request) {
52
121
  authority: safeId(access.permissionContext.authority),
53
122
  decision: String(access.permissionContext.decision ?? ''),
54
123
  receiptId: safeId(access.permissionContext.receiptId),
124
+ ...(Object.prototype.hasOwnProperty.call(access.permissionContext, 'identityReceiptId')
125
+ ? { identityReceiptId: safeId(access.permissionContext.identityReceiptId) }
126
+ : {}),
55
127
  },
56
128
  };
57
129
  if (!normalized.tenantId || !normalized.userId || !normalized.actorId || !normalized.agentId
@@ -65,6 +137,8 @@ function normalizeMemoryAccess(access, request) {
65
137
  || requestTenant !== normalized.tenantId || requestAgent !== normalized.agentId) {
66
138
  fail('COGNITIVE_MEMORY_ACCESS_SCOPE_MISMATCH');
67
139
  }
140
+ const identityLink = normalizeIdentityLink(access, normalized);
141
+ if (identityLink) normalized.identityLink = identityLink;
68
142
  normalized.permissionContext = Object.freeze(normalized.permissionContext);
69
143
  return Object.freeze(normalized);
70
144
  }
@@ -86,6 +160,11 @@ function assertVisibleScope(scope, access) {
86
160
  }
87
161
 
88
162
  function assertCommitAccess(input, access) {
163
+ if (Number.isNaN(Date.parse(String(input?.occurredAt ?? '')))
164
+ || Number.isNaN(Date.parse(String(input?.receivedAt ?? '')))
165
+ || !RETENTION_CLASSES.has(String(input?.retentionClass ?? ''))) {
166
+ fail('COGNITIVE_MEMORY_EVENT_ENVELOPE_INVALID');
167
+ }
89
168
  if (isInternalAgentAccess(access)) return;
90
169
  if (!Array.isArray(input?.observations) || input.observations.length < 1) {
91
170
  fail('COGNITIVE_MEMORY_VISIBILITY_DENIED');
@@ -10,6 +10,7 @@ const DOMAINS = new Set(['self', 'world', 'team', 'goal', 'open_thread', 'assump
10
10
  const EPISTEMIC_STATES = new Set([
11
11
  'verified', 'credible_unverified', 'hypothesis', 'uncertain_memory', 'stale', 'unknown', 'legacy_unknown',
12
12
  ]);
13
+ const RETENTION_CLASSES = new Set(['operational', 'durable', 'relationship', 'audit']);
13
14
  const FORBIDDEN_KEY_RE = /(?:^|_)(?:acl|api_key|capability|password|permission|secret|token)(?:_|$)/iu;
14
15
  const MAX_EVENT_BYTES = 64 * 1024;
15
16
  const MAX_OBSERVATIONS = 32;
@@ -90,13 +91,21 @@ function normalizeObservation(value) {
90
91
  }
91
92
 
92
93
  function normalizeEvent(input) {
94
+ const allowed = new Set([
95
+ 'tenantId', 'agentId', 'eventId', 'expectedVersion', 'occurredAt', 'receivedAt',
96
+ 'retentionClass', 'source', 'observations',
97
+ ]);
98
+ if (!exactKeys(input, allowed) || hasForbiddenKey(input)) fail('COGNITIVE_FORBIDDEN_FIELD');
93
99
  const tenantId = safeId(input.tenantId);
94
100
  const agentId = safeId(input.agentId);
95
101
  const eventId = safeId(input.eventId);
96
102
  const expectedVersion = Number(input.expectedVersion);
97
103
  const occurredAt = String(input.occurredAt ?? '').trim();
104
+ const receivedAt = String(input.receivedAt ?? '').trim();
105
+ const retentionClass = String(input.retentionClass ?? '').trim();
98
106
  if (!tenantId || !agentId || !eventId || !Number.isSafeInteger(expectedVersion)
99
107
  || expectedVersion < 0 || Number.isNaN(Date.parse(occurredAt))
108
+ || Number.isNaN(Date.parse(receivedAt)) || !RETENTION_CLASSES.has(retentionClass)
100
109
  || !Array.isArray(input.observations) || input.observations.length < 1
101
110
  || input.observations.length > MAX_OBSERVATIONS) fail('COGNITIVE_INVALID_EVENT');
102
111
  const normalized = {
@@ -104,7 +113,9 @@ function normalizeEvent(input) {
104
113
  agent_id: agentId,
105
114
  event_id: eventId,
106
115
  expected_version: expectedVersion,
107
- occurred_at: occurredAt,
116
+ occurred_at: new Date(occurredAt).toISOString(),
117
+ received_at: new Date(receivedAt).toISOString(),
118
+ retention_class: retentionClass,
108
119
  source: normalizeSource(input.source),
109
120
  observations: input.observations.map(normalizeObservation),
110
121
  };
@@ -146,6 +157,8 @@ function initialize(db) {
146
157
  expected_version INTEGER NOT NULL,
147
158
  new_version INTEGER NOT NULL,
148
159
  occurred_at TEXT NOT NULL,
160
+ received_at TEXT NOT NULL,
161
+ retention_class TEXT NOT NULL,
149
162
  payload_json TEXT NOT NULL,
150
163
  previous_hash TEXT NOT NULL,
151
164
  event_hash TEXT NOT NULL UNIQUE
@@ -163,6 +176,8 @@ function initialize(db) {
163
176
  scope TEXT NOT NULL,
164
177
  source_json TEXT NOT NULL,
165
178
  occurred_at TEXT NOT NULL,
179
+ received_at TEXT NOT NULL,
180
+ retention_class TEXT NOT NULL,
166
181
  supersedes_observation_id TEXT,
167
182
  withdraws_observation_id TEXT
168
183
  );
@@ -200,6 +215,19 @@ function initialize(db) {
200
215
  if (!observationColumns.some((column) => column.name === 'epistemic_state')) {
201
216
  db.exec("ALTER TABLE cognitive_observations ADD COLUMN epistemic_state TEXT NOT NULL DEFAULT 'legacy_unknown'");
202
217
  }
218
+ if (!observationColumns.some((column) => column.name === 'received_at')) {
219
+ db.exec("ALTER TABLE cognitive_observations ADD COLUMN received_at TEXT NOT NULL DEFAULT ''");
220
+ }
221
+ if (!observationColumns.some((column) => column.name === 'retention_class')) {
222
+ db.exec("ALTER TABLE cognitive_observations ADD COLUMN retention_class TEXT NOT NULL DEFAULT 'legacy_unknown'");
223
+ }
224
+ const eventColumns = db.prepare('PRAGMA table_info(cognitive_events)').all();
225
+ if (!eventColumns.some((column) => column.name === 'received_at')) {
226
+ db.exec("ALTER TABLE cognitive_events ADD COLUMN received_at TEXT NOT NULL DEFAULT ''");
227
+ }
228
+ if (!eventColumns.some((column) => column.name === 'retention_class')) {
229
+ db.exec("ALTER TABLE cognitive_events ADD COLUMN retention_class TEXT NOT NULL DEFAULT 'legacy_unknown'");
230
+ }
203
231
  }
204
232
 
205
233
  function openCognitiveStateStore({ home } = {}) {
@@ -227,12 +255,13 @@ function openCognitiveStateStore({ home } = {}) {
227
255
  const eventHash = crypto.createHash('sha256').update(`${previousHash}\0${payload}`).digest('hex');
228
256
  const newVersion = actualVersion + 1;
229
257
  db.prepare(`INSERT INTO cognitive_events
230
- (event_id, tenant_id, agent_id, expected_version, new_version, occurred_at, payload_json, previous_hash, event_hash)
231
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
232
- .run(normalized.event_id, normalized.tenant_id, normalized.agent_id, actualVersion, newVersion, normalized.occurred_at, payload, previousHash, eventHash);
258
+ (event_id, tenant_id, agent_id, expected_version, new_version, occurred_at, received_at, retention_class, payload_json, previous_hash, event_hash)
259
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
260
+ .run(normalized.event_id, normalized.tenant_id, normalized.agent_id, actualVersion, newVersion,
261
+ normalized.occurred_at, normalized.received_at, normalized.retention_class, payload, previousHash, eventHash);
233
262
  const insertObservation = db.prepare(`INSERT INTO cognitive_observations
234
- (observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, supersedes_observation_id, withdraws_observation_id)
235
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
263
+ (observation_id, event_id, tenant_id, agent_id, domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, received_at, retention_class, supersedes_observation_id, withdraws_observation_id)
264
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
236
265
  const sourceJson = JSON.stringify(normalized.source);
237
266
  for (const observation of normalized.observations) {
238
267
  if (observation.supersedes) {
@@ -252,7 +281,8 @@ function openCognitiveStateStore({ home } = {}) {
252
281
  insertObservation.run(observation.observation_id, normalized.event_id, normalized.tenant_id, normalized.agent_id,
253
282
  observation.domain, observation.key, observation.value, observation.confidence, observation.epistemic_state,
254
283
  observation.scope, sourceJson,
255
- normalized.occurred_at, observation.supersedes ?? null, observation.withdraws ?? null);
284
+ normalized.occurred_at, normalized.received_at, normalized.retention_class,
285
+ observation.supersedes ?? null, observation.withdraws ?? null);
256
286
  }
257
287
  db.prepare(`INSERT INTO cognitive_streams (tenant_id, agent_id, version, updated_at) VALUES (?, ?, ?, ?)
258
288
  ON CONFLICT(tenant_id, agent_id) DO UPDATE SET version = excluded.version, updated_at = excluded.updated_at`)
@@ -273,7 +303,8 @@ function openCognitiveStateStore({ home } = {}) {
273
303
  fail('COGNITIVE_INVALID_EVENT');
274
304
  }
275
305
  const stream = db.prepare('SELECT version, updated_at FROM cognitive_streams WHERE tenant_id = ? AND agent_id = ?').get(tenant, agent);
276
- const select = `SELECT domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, observation_id,
306
+ const select = `SELECT domain, fact_key, value_text, confidence, epistemic_state, scope, source_json, occurred_at, received_at,
307
+ retention_class, observation_id,
277
308
  supersedes_observation_id, withdraws_observation_id FROM cognitive_observations`;
278
309
  const rows = requestedVisibility && requestedVisibility !== 'agent:memory'
279
310
  ? db.prepare(`${select} WHERE tenant_id = ? AND agent_id = ? AND scope = ? ORDER BY occurred_at, rowid`)
@@ -292,6 +323,8 @@ function openCognitiveStateStore({ home } = {}) {
292
323
  scope: row.scope,
293
324
  source: JSON.parse(row.source_json),
294
325
  occurred_at: row.occurred_at,
326
+ received_at: row.received_at || row.occurred_at,
327
+ retention_class: row.retention_class || 'legacy_unknown',
295
328
  supersedes: row.supersedes_observation_id ?? null,
296
329
  withdraws: row.withdraws_observation_id ?? null,
297
330
  })),
@@ -127,6 +127,8 @@ function createCognitiveTurnLifecycle({
127
127
  eventId,
128
128
  expectedVersion,
129
129
  occurredAt,
130
+ receivedAt: occurredAt,
131
+ retentionClass: 'operational',
130
132
  source: {
131
133
  provider: 'runtime',
132
134
  channel_id: 'runtime',
@@ -176,6 +178,8 @@ function createCognitiveTurnLifecycle({
176
178
  eventId,
177
179
  expectedVersion,
178
180
  occurredAt,
181
+ receivedAt: occurredAt,
182
+ retentionClass: 'durable',
179
183
  source: {
180
184
  provider: 'runtime',
181
185
  channel_id: 'runtime',
@@ -310,6 +314,7 @@ function createCognitiveTurnLifecycle({
310
314
  ...(correction ? { supersedes: targetObservationId } : { withdraws: targetObservationId }),
311
315
  };
312
316
  const normalizedOccurredAt = new Date(occurredAt).toISOString();
317
+ const receivedAt = stageTime(`revision:${kind}:${requestId}`);
313
318
  const revisionMemoryAccess = {
314
319
  tenantId: tenant,
315
320
  userId: normalizedSource.actor_id,
@@ -353,6 +358,8 @@ function createCognitiveTurnLifecycle({
353
358
  eventId,
354
359
  expectedVersion: current.version,
355
360
  occurredAt: normalizedOccurredAt,
361
+ receivedAt,
362
+ retentionClass: 'durable',
356
363
  source: normalizedSource,
357
364
  observations: [observation],
358
365
  }, revisionMemoryAccess);
@@ -466,7 +473,7 @@ function createCognitiveTurnLifecycle({
466
473
  const authorization = input?.authorization;
467
474
  const memoryAccess = {
468
475
  tenantId: tenant,
469
- userId: String(candidate?.subject_id ?? ''),
476
+ userId: agent,
470
477
  actorId: agent,
471
478
  agentId: agent,
472
479
  portalId: 'cli',
@@ -462,6 +462,7 @@ function recordChannelIdentity(envelope, env = process.env) {
462
462
  const groupId = chatId.startsWith('-') ? `telegram-chat-${chatId.slice(1)}` : undefined;
463
463
  const displayName = cleanText(meta.user, 120) || actorId;
464
464
  const firstSeenAt = trustedTimestamp(meta.ts);
465
+ const receivedAt = trustedTimestamp(meta.received_at) || firstSeenAt;
465
466
  const created = [];
466
467
  if (createJsonOnce(root, ['actors', `${actorId}.json`], {
467
468
  version: 1,
@@ -517,6 +518,7 @@ function recordChannelIdentity(envelope, env = process.env) {
517
518
  sourceChannel: groupId ? 'group' : 'direct',
518
519
  conversationId: groupId || `telegram-dm-${chatId}`,
519
520
  messageId: safeId(meta.message_id),
521
+ receivedAt,
520
522
  });
521
523
  if (firstSeenAt) recordInteractionActivity(root, agentId, actorId, firstSeenAt);
522
524
  const modelContext = renderIdentityContext({
@@ -9,7 +9,7 @@ const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
9
9
  const SENSITIVITIES = new Set(['low', 'medium']);
10
10
  const INPUT_KEYS = [
11
11
  'actorId', 'agentId', 'conversationId', 'cooldownMs', 'messageId', 'occurredAt',
12
- 'sensitivity', 'sourceChannel', 'sourcePortal', 'tenantId', 'topic',
12
+ 'receivedAt', 'sensitivity', 'sourceChannel', 'sourcePortal', 'tenantId', 'topic',
13
13
  ];
14
14
  const MAX_COOLDOWN_MS = 90 * 24 * 60 * 60 * 1000;
15
15
 
@@ -49,6 +49,7 @@ function normalizePresentation(input) {
49
49
  conversationId: safeId(input.conversationId),
50
50
  messageId: safeId(input.messageId),
51
51
  occurredAt: String(input.occurredAt ?? '').trim(),
52
+ receivedAt: String(input.receivedAt ?? '').trim(),
52
53
  topic: safeId(input.topic),
53
54
  sensitivity: String(input.sensitivity ?? ''),
54
55
  cooldownMs: Number(input.cooldownMs),
@@ -57,11 +58,13 @@ function normalizePresentation(input) {
57
58
  || !normalized.sourcePortal || !normalized.sourceChannel || !normalized.conversationId
58
59
  || !normalized.messageId || !normalized.topic || !SENSITIVITIES.has(normalized.sensitivity)
59
60
  || Number.isNaN(Date.parse(normalized.occurredAt))
61
+ || Number.isNaN(Date.parse(normalized.receivedAt))
60
62
  || !Number.isSafeInteger(normalized.cooldownMs) || normalized.cooldownMs < 1000
61
63
  || normalized.cooldownMs > MAX_COOLDOWN_MS) {
62
64
  fail('PERSONALITY_MEMORY_INVALID_INPUT');
63
65
  }
64
66
  normalized.occurredAt = new Date(normalized.occurredAt).toISOString();
67
+ normalized.receivedAt = new Date(normalized.receivedAt).toISOString();
65
68
  return normalized;
66
69
  }
67
70
 
@@ -138,6 +141,8 @@ function createPersonalityMemoryAdapter({ identityRoot, memoryAdapter } = {}) {
138
141
  eventId,
139
142
  expectedVersion: current.version,
140
143
  occurredAt: value.occurredAt,
144
+ receivedAt: value.receivedAt,
145
+ retentionClass: 'relationship',
141
146
  source: {
142
147
  provider: value.sourcePortal,
143
148
  channel_id: value.sourceChannel,
@@ -64,11 +64,12 @@ function prepareCuriosityOpportunity(input = {}) {
64
64
  const agentId = safeId(input.agentId);
65
65
  const actorId = safeId(input.actorId);
66
66
  const occurredAt = trustedTimestamp(input.occurredAt);
67
+ const receivedAt = trustedTimestamp(input.receivedAt);
67
68
  const sourcePortal = safeId(input.sourcePortal) || 'telegram';
68
69
  const sourceChannel = safeId(input.sourceChannel) || 'direct';
69
70
  const conversationId = safeId(input.conversationId) || digestId('conversation', [actorId]);
70
71
  const cue = curiosityCue(input.text);
71
- if (!tenantId || !agentId || !actorId || !occurredAt || !cue) return undefined;
72
+ if (!tenantId || !agentId || !actorId || !occurredAt || !receivedAt || !cue) return undefined;
72
73
  const messageId = safeId(input.messageId) || digestId('message', [
73
74
  sourcePortal, sourceChannel, conversationId, actorId, occurredAt, normalizedText(input.text),
74
75
  ]);
@@ -88,6 +89,7 @@ function prepareCuriosityOpportunity(input = {}) {
88
89
  conversationId,
89
90
  messageId,
90
91
  occurredAt,
92
+ receivedAt,
91
93
  topic: cue.topic,
92
94
  sensitivity: cue.sensitivity,
93
95
  cooldownMs: COOLDOWN_MS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.389",
3
+ "version": "9.1.391",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {