blun-king-cli 9.1.358 → 9.1.359

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.
@@ -36,6 +36,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
36
36
  if (scopes === null || !Number.isSafeInteger(maxItems) || maxItems < 1 || maxItems > 8
37
37
  || !Number.isSafeInteger(maxChars) || maxChars < 320 || maxChars > 1600
38
38
  || !Array.isArray(state?.observations)) return null;
39
+ if (scopes.length === 0) return null;
39
40
 
40
41
  const groups = new Map();
41
42
  state.observations.forEach((item, index) => {
@@ -48,7 +49,7 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
48
49
  if (!FOCUS_DOMAINS.has(domain) || !key || !value || !scope || scope === 'runtime'
49
50
  || !Number.isFinite(confidence) || confidence < 0.5 || confidence > 1
50
51
  || !Number.isFinite(occurredAt)) return;
51
- const groupKey = `${domain}\0${key}`;
52
+ const groupKey = `${scope}\0${domain}\0${key}`;
52
53
  const existing = groups.get(groupKey) ?? [];
53
54
  existing.push({ domain, key, value, scope, confidence, occurredAt, index });
54
55
  groups.set(groupKey, existing);
@@ -58,12 +59,12 @@ function buildCognitiveFocusProjection(state, { focusScopes, maxItems = 6, maxCh
58
59
  for (const entries of groups.values()) {
59
60
  entries.sort((left, right) => left.occurredAt - right.occurredAt || left.index - right.index);
60
61
  const latest = entries.at(-1);
62
+ if (!scopes.includes(latest.scope)) continue;
61
63
  const revised = entries.some((item) => item.value !== latest.value);
62
- const scopeScore = scopes.includes(latest.scope) ? 100 : 0;
63
64
  ranked.push({
64
65
  ...latest,
65
66
  revised,
66
- score: scopeScore + DOMAIN_WEIGHTS.get(latest.domain) + latest.confidence * 10,
67
+ score: DOMAIN_WEIGHTS.get(latest.domain) + latest.confidence * 10,
67
68
  });
68
69
  }
69
70
  ranked.sort((left, right) => right.score - left.score
@@ -0,0 +1,37 @@
1
+ 'use strict';
2
+
3
+ const CHANNEL_RE = /<channel\b([^>]*)>[\s\S]*?<\/channel>/giu;
4
+ const TELEGRAM_SOURCE_RE = /\bsource\s*=\s*["']telegram["']/iu;
5
+ const CHAT_ID_RE = /\bchat_id\s*=\s*["'](-?\d+)["']/iu;
6
+ const USER_ID_RE = /\buser_id\s*=\s*["'](\d+)["']/iu;
7
+ const DM_MARKER_RE = /^#?\s*\[tg\s+dm\b[^\]]*\bchat_id\s*=\s*(\d+)[^\]]*\]/gimu;
8
+
9
+ function inputText(input) {
10
+ if (!Array.isArray(input)) return '';
11
+ return input
12
+ .filter((part) => part?.type === 'text' && typeof part.text === 'string')
13
+ .map((part) => part.text)
14
+ .join('\n');
15
+ }
16
+
17
+ function relationshipScope(subjectId) {
18
+ return `relationship:telegram-${subjectId}:private`;
19
+ }
20
+
21
+ function cognitiveFocusScopesForTurn(input) {
22
+ const text = inputText(input);
23
+ if (!text) return [];
24
+ const scopes = [];
25
+ for (const match of text.matchAll(CHANNEL_RE)) {
26
+ const attributes = match[1] ?? '';
27
+ if (!TELEGRAM_SOURCE_RE.test(attributes)) continue;
28
+ const chatId = CHAT_ID_RE.exec(attributes)?.[1];
29
+ if (!chatId || chatId.startsWith('-')) continue;
30
+ const subjectId = USER_ID_RE.exec(attributes)?.[1] ?? chatId;
31
+ scopes.push(relationshipScope(subjectId));
32
+ }
33
+ for (const match of text.matchAll(DM_MARKER_RE)) scopes.push(relationshipScope(match[1]));
34
+ return [...new Set(scopes)].slice(0, 8);
35
+ }
36
+
37
+ module.exports = { cognitiveFocusScopesForTurn };
@@ -1,6 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  const crypto = require('node:crypto');
4
+ const fs = require('node:fs');
5
+ const path = require('node:path');
4
6
  const { openCognitiveStateStore } = require('./cognitive-state-store.cjs');
5
7
  const { buildCognitiveContextProjection } = require('./cognitive-context-projection.cjs');
6
8
  const { buildCognitiveFocusProjection } = require('./cognitive-focus-projection.cjs');
@@ -45,6 +47,25 @@ function digestId(prefix, values) {
45
47
  return `${prefix}-${digest}`;
46
48
  }
47
49
 
50
+ function identityFromManifest(home) {
51
+ const root = fs.realpathSync(path.resolve(String(home ?? '')));
52
+ const identityRoot = path.join(root, 'identity');
53
+ const manifestPath = path.join(identityRoot, 'manifest.json');
54
+ try {
55
+ const identityStat = fs.lstatSync(identityRoot);
56
+ const manifestStat = fs.lstatSync(manifestPath);
57
+ if (!identityStat.isDirectory() || identityStat.isSymbolicLink()
58
+ || !manifestStat.isFile() || manifestStat.isSymbolicLink() || manifestStat.size > 64 * 1024) return null;
59
+ if (fs.realpathSync(identityRoot) !== identityRoot || fs.realpathSync(manifestPath) !== manifestPath) return null;
60
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
61
+ const tenantId = safeId(manifest?.tenant_id);
62
+ const agentId = safeId(manifest?.active_agent_id);
63
+ return manifest?.version === 1 && tenantId && agentId ? { tenantId, agentId } : null;
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+
48
69
  function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now = () => new Date().toISOString() } = {}) {
49
70
  const tenant = safeId(tenantId);
50
71
  const agent = safeId(agentId);
@@ -281,14 +302,25 @@ function createCognitiveTurnLifecycle({ home, tenantId, agentId, runtimeId, now
281
302
  };
282
303
  }
283
304
 
284
- function createRuntimeCognitiveTurnLifecycle({ home, agentName, runtimeId, now } = {}) {
305
+ function createRuntimeCognitiveTurnLifecycle({ home, agentName, tenantId, agentId, runtimeId, now } = {}) {
285
306
  const resolvedHome = String(home ?? '').trim();
286
307
  const resolvedAgent = String(agentName ?? '').trim();
287
308
  if (!resolvedHome || !resolvedAgent) fail('COGNITIVE_LIFECYCLE_INVALID');
309
+ const explicitTenant = tenantId === undefined ? '' : safeId(tenantId);
310
+ const explicitAgent = agentId === undefined ? '' : safeId(agentId);
311
+ if ((tenantId !== undefined && !explicitTenant) || (agentId !== undefined && !explicitAgent)) {
312
+ fail('COGNITIVE_LIFECYCLE_INVALID');
313
+ }
314
+ const manifestIdentity = identityFromManifest(resolvedHome);
315
+ const identity = {
316
+ tenantId: explicitTenant || manifestIdentity?.tenantId || '',
317
+ agentId: explicitAgent || manifestIdentity?.agentId || '',
318
+ };
319
+ const hasSharedIdentity = Boolean(identity.tenantId && identity.agentId);
288
320
  return createCognitiveTurnLifecycle({
289
321
  home: resolvedHome,
290
- tenantId: digestId('home', [resolvedHome.toLowerCase()]),
291
- agentId: digestId('agent', [resolvedAgent.toLowerCase()]),
322
+ tenantId: hasSharedIdentity ? identity.tenantId : digestId('home', [resolvedHome.toLowerCase()]),
323
+ agentId: hasSharedIdentity ? identity.agentId : digestId('agent', [resolvedAgent.toLowerCase()]),
292
324
  runtimeId,
293
325
  now,
294
326
  });
package/blun.mjs CHANGED
@@ -261464,7 +261464,7 @@ function toolResultText(result) {
261464
261464
  function abandonedToolResultOutput(ended) {
261465
261465
  return `Tool call did not complete: ${ended.reason === "cancelled" ? "the turn was cancelled" : ended.reason === "failed" ? `the turn failed${ended.error !== void 0 ? ` (${ended.error.message})` : ""}` : "the turn ended"} before its result was recorded. Do not assume the tool completed successfully.`;
261466
261466
  }
261467
- var BLUN_CORE_TOOL_NAMES, BLUN_LEAN_TOOL_NAMES, BLUN_ATTACHMENT_MARKER_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TELEGRAM_CHANNEL_RE, BLUN_TOOL_BUDGET_RATIO, createDeferredToolLoader, mediaGenerationToolNamesForText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens, projectRecurringCronHistory, TelegramDeliveryLedger, createRuntimeCognitiveTurnLifecycle, buildAttentionQueueItem, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
261467
+ var BLUN_CORE_TOOL_NAMES, BLUN_LEAN_TOOL_NAMES, BLUN_ATTACHMENT_MARKER_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TELEGRAM_CHANNEL_RE, BLUN_TOOL_BUDGET_RATIO, createDeferredToolLoader, mediaGenerationToolNamesForText, rememberDeferredToolAfterNotFound, toolSchemaBudgetTokens, projectRecurringCronHistory, TelegramDeliveryLedger, createRuntimeCognitiveTurnLifecycle, cognitiveFocusScopesForTurn, buildAttentionQueueItem, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
261468
261468
  var init_turn = __esmMin((() => {
261469
261469
  init_dist$4();
261470
261470
  init_src$4();
@@ -261485,6 +261485,7 @@ var init_turn = __esmMin((() => {
261485
261485
  ({ projectRecurringCronHistory } = createRequire(import.meta.url)("./bin/recurring-cron-history-policy.cjs"));
261486
261486
  ({ TelegramDeliveryLedger } = createRequire(import.meta.url)("./bin/repeated-user-message-projection.cjs"));
261487
261487
  ({ createRuntimeCognitiveTurnLifecycle } = createRequire(import.meta.url)("./bin/cognitive-turn-lifecycle.cjs"));
261488
+ ({ cognitiveFocusScopesForTurn } = createRequire(import.meta.url)("./bin/cognitive-focus-scope.cjs"));
261488
261489
  ({ buildAttentionQueueItem } = createRequire(import.meta.url)("./bin/cognitive-attention-delivery.cjs"));
261489
261490
  BLUN_LEAN_TOOL_NAMES = new Set(BLUN_CORE_TOOL_NAMES);
261490
261491
  BLUN_ATTACHMENT_MARKER_RE = /\b(?:attachment_file_id|telegram-anhang|telegram attachment)\b/i;
@@ -261568,7 +261569,9 @@ var init_turn = __esmMin((() => {
261568
261569
  try {
261569
261570
  this.cognitiveLifecycle = createRuntimeCognitiveTurnLifecycle({
261570
261571
  home,
261571
- agentName: this.agent.activeProfile?.name ?? this.agent.type
261572
+ agentName: this.agent.activeProfile?.name ?? this.agent.type,
261573
+ tenantId: process.env.BLUN_IDENTITY_TENANT_ID,
261574
+ agentId: process.env.BLUN_AGENT_ID
261572
261575
  });
261573
261576
  return this.cognitiveLifecycle;
261574
261577
  } catch (error) {
@@ -261618,9 +261621,10 @@ var init_turn = __esmMin((() => {
261618
261621
  this.recordCognitiveStage("recordToolPolicy", policy);
261619
261622
  }
261620
261623
  }
261621
- projectCognitiveState(turnId) {
261624
+ projectCognitiveState(turnId, input) {
261622
261625
  try {
261623
- return this.getCognitiveLifecycle()?.projectForTurn({ turnId }) ?? null;
261626
+ const focusScopes = cognitiveFocusScopesForTurn(input);
261627
+ return this.getCognitiveLifecycle()?.projectForTurn({ turnId, focusScopes }) ?? null;
261624
261628
  } catch (error) {
261625
261629
  this.agent.telemetry.track("cognitive_lifecycle_error", { stage: "projectForTurn", error_type: error?.code ?? error?.name ?? "Error" });
261626
261630
  return null;
@@ -262178,7 +262182,7 @@ var init_turn = __esmMin((() => {
262178
262182
  if (blunTurnNeedsInitialMcp(input, origin)) await this.agent.mcp?.waitForInitialLoad(signal);
262179
262183
  const personalMemoryRecall = await this.agent.injection.injectPersonalMemoryForTurn(turnId, input, origin, signal);
262180
262184
  await this.agent.injection.injectGoal();
262181
- const cognitiveProjection = this.projectCognitiveState(turnId);
262185
+ const cognitiveProjection = this.projectCognitiveState(turnId, input);
262182
262186
  if (cognitiveProjection !== null) this.agent.context.appendSystemReminder(cognitiveProjection, {
262183
262187
  kind: "injection",
262184
262188
  variant: "cognitive_continuity"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.358",
3
+ "version": "9.1.359",
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": {