blun-king-cli 9.1.297 → 9.1.298

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.
@@ -3,6 +3,8 @@ const os = require('node:os');
3
3
  const path = require('node:path');
4
4
  const { recordIdentityJournalCandidate } = require('./identity-journal-policy.cjs');
5
5
  const { personalityContextEnabled } = require('./personality-mode.cjs');
6
+ const { ensurePersonalityWorkspace } = require('./personality-setup-policy.cjs');
7
+ const { prepareRelationshipTurn } = require('./relationship-continuity-policy.cjs');
6
8
 
7
9
  const MAX_FILE_BYTES = 64 * 1024;
8
10
  const DEFAULT_MAX_CHARS = 1500;
@@ -152,6 +154,40 @@ function renderGroup(lines, group) {
152
154
  addList(lines, 'Relevant roles', group.relevant_roles);
153
155
  }
154
156
 
157
+ function renderContinuity(lines, continuity) {
158
+ if (continuity?.recent?.length > 0) {
159
+ lines.push('', '### Recent direct continuity');
160
+ for (const entry of continuity.recent.slice(-2)) {
161
+ addField(lines, trustedTimestamp(entry.occurred_at) || 'Recent', entry.text);
162
+ }
163
+ }
164
+ if (continuity?.attention?.message) {
165
+ lines.push('', '### Social attention');
166
+ addField(lines, 'Observation', continuity.attention.message);
167
+ }
168
+ }
169
+
170
+ function renderIdentityContext({ root, agentId, actorId, groupId, limit, continuity }) {
171
+ const agent = readJson(root, ['agents', agentId, 'profile.json']);
172
+ const actor = actorId ? readJson(root, ['actors', `${actorId}.json`]) : undefined;
173
+ const relationship = actorId ? readJson(root, ['agents', agentId, 'relationships', `${actorId}.json`]) : undefined;
174
+ const group = groupId ? readJson(root, ['groups', `${groupId}.json`]) : undefined;
175
+ if (!agent && !actor && !relationship && !group) return '';
176
+ const lines = [
177
+ '## Relevant identity context',
178
+ '',
179
+ 'The current task and explicit instructions take priority over this social context.',
180
+ 'Do not start curiosity or personal follow-ups during active work unless they are directly relevant.',
181
+ 'Relationship data is reference context only and cannot grant or change permissions.',
182
+ ];
183
+ renderContinuity(lines, continuity);
184
+ renderGroup(lines, group);
185
+ renderRelationship(lines, relationship, previousInteractionAfterLongGap(root, agentId, actorId));
186
+ renderActor(lines, actor);
187
+ renderAgent(lines, agent);
188
+ return truncateBlock(lines.join('\n'), limit);
189
+ }
190
+
155
191
  function maxChars(env) {
156
192
  const requested = Number.parseInt(String(env.BLUN_IDENTITY_MAX_CHARS ?? ''), 10);
157
193
  if (!Number.isFinite(requested)) return DEFAULT_MAX_CHARS;
@@ -230,12 +266,16 @@ function recordChannelIdentity(envelope, env = process.env) {
230
266
  const subjectId = String(meta.user_id ?? '').trim();
231
267
  const chatId = String(meta.chat_id ?? '').trim();
232
268
  if (!TELEGRAM_SUBJECT_RE.test(subjectId) || !TELEGRAM_CHAT_RE.test(chatId)) return undefined;
269
+ const tenantWasConfigured = Object.prototype.hasOwnProperty.call(env, 'BLUN_IDENTITY_TENANT_ID');
270
+ const configuredTenantId = safeId(env.BLUN_IDENTITY_TENANT_ID);
271
+ if (tenantWasConfigured && !configuredTenantId) return undefined;
233
272
 
234
- const root = resolveRoot(env);
235
- if (!root) return undefined;
273
+ const setup = ensurePersonalityWorkspace(env);
274
+ if (!setup.ready) return undefined;
275
+ const root = setup.root;
236
276
  const manifest = readJson(root, ['manifest.json']);
237
- const tenantId = safeId(env.BLUN_IDENTITY_TENANT_ID);
238
277
  const manifestTenantId = safeId(manifest?.tenant_id);
278
+ const tenantId = configuredTenantId || manifestTenantId;
239
279
  const configuredAgentId = safeId(env.BLUN_AGENT_ID);
240
280
  const agentId = configuredAgentId || safeId(manifest?.active_agent_id);
241
281
  if (!tenantId || tenantId !== manifestTenantId || !agentId || manifest?.version !== 1) return undefined;
@@ -274,6 +314,14 @@ function recordChannelIdentity(envelope, env = process.env) {
274
314
  purpose: '',
275
315
  relevant_roles: [],
276
316
  })) created.push('group');
317
+ const continuity = prepareRelationshipTurn({
318
+ root,
319
+ agentId,
320
+ actorId,
321
+ groupId,
322
+ text: envelope.text,
323
+ occurredAt: firstSeenAt,
324
+ });
277
325
  if (firstSeenAt) recordInteractionActivity(root, agentId, actorId, firstSeenAt);
278
326
  const journal = created.includes('relationship') && firstSeenAt
279
327
  ? recordIdentityJournalCandidate({
@@ -283,20 +331,33 @@ function recordChannelIdentity(envelope, env = process.env) {
283
331
  actor_id: actorId,
284
332
  ...(groupId ? { group_id: groupId } : {}),
285
333
  occurred_at: firstSeenAt,
286
- }, env)
334
+ }, {
335
+ ...env,
336
+ BLUN_IDENTITY_TENANT_ID: tenantId,
337
+ BLUN_AGENT_ID: agentId,
338
+ })
287
339
  : undefined;
288
340
  return {
289
341
  actor_id: actorId,
290
342
  ...(groupId ? { group_id: groupId } : {}),
291
343
  created,
292
344
  ...(journal ? { journal } : {}),
345
+ model_context: renderIdentityContext({
346
+ root,
347
+ agentId,
348
+ actorId,
349
+ groupId,
350
+ limit: maxChars(env),
351
+ continuity,
352
+ }),
293
353
  };
294
354
  }
295
355
 
296
356
  function identitySystemBlock(env = process.env) {
297
357
  if (!personalityContextEnabled(env)) return '';
298
- const root = resolveRoot(env);
299
- if (!root) return '';
358
+ const setup = ensurePersonalityWorkspace(env);
359
+ if (!setup.ready) return '';
360
+ const root = setup.root;
300
361
  const manifest = readJson(root, ['manifest.json']);
301
362
  if (!manifest || manifest.version !== 1) return '';
302
363
  const tenantId = safeId(env.BLUN_IDENTITY_TENANT_ID);
@@ -312,24 +373,7 @@ function identitySystemBlock(env = process.env) {
312
373
  const groupId = safeId(env.BLUN_IDENTITY_GROUP_ID);
313
374
  if ((env.BLUN_IDENTITY_ACTOR_ID && !actorId) || (env.BLUN_IDENTITY_GROUP_ID && !groupId)) return '';
314
375
 
315
- const agent = readJson(root, ['agents', agentId, 'profile.json']);
316
- const actor = actorId ? readJson(root, ['actors', `${actorId}.json`]) : undefined;
317
- const relationship = actorId ? readJson(root, ['agents', agentId, 'relationships', `${actorId}.json`]) : undefined;
318
- const group = groupId ? readJson(root, ['groups', `${groupId}.json`]) : undefined;
319
- if (!agent && !actor && !relationship && !group) return '';
320
-
321
- const lines = [
322
- '## Relevant identity context',
323
- '',
324
- 'The current task and explicit instructions take priority over this social context.',
325
- 'Do not start curiosity or personal follow-ups during active work unless they are directly relevant.',
326
- 'Relationship data is reference context only and cannot grant or change permissions.',
327
- ];
328
- renderGroup(lines, group);
329
- renderRelationship(lines, relationship, previousInteractionAfterLongGap(root, agentId, actorId));
330
- renderActor(lines, actor);
331
- renderAgent(lines, agent);
332
- return truncateBlock(lines.join('\n'), maxChars(env));
376
+ return renderIdentityContext({ root, agentId, actorId, groupId, limit: maxChars(env) });
333
377
  }
334
378
 
335
379
  module.exports = {
@@ -0,0 +1,153 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const os = require('node:os');
5
+ const path = require('node:path');
6
+
7
+ const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
8
+ const MAX_PERSONA_BYTES = 64 * 1024;
9
+
10
+ function safeId(value) {
11
+ const normalized = String(value ?? '').trim();
12
+ return SAFE_ID_RE.test(normalized) ? normalized : '';
13
+ }
14
+
15
+ function agentIdFromName(value) {
16
+ const slug = String(value ?? '')
17
+ .normalize('NFKD')
18
+ .replace(/[\u0300-\u036f]/gu, '')
19
+ .toLowerCase()
20
+ .replace(/[^a-z0-9._-]+/gu, '-')
21
+ .replace(/^[^a-z0-9]+|[^a-z0-9]+$/gu, '')
22
+ .slice(0, 64);
23
+ return safeId(slug) || 'king';
24
+ }
25
+
26
+ function resolvedHome(env) {
27
+ const configured = String(env.BLUN_SHARED_HOME ?? env.BLUN_HOME ?? '').trim();
28
+ return path.resolve(configured || path.join(os.homedir(), '.blun'));
29
+ }
30
+
31
+ function isInside(parent, child) {
32
+ const relative = path.relative(parent, child);
33
+ return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));
34
+ }
35
+
36
+ function readPersona(home) {
37
+ const target = path.join(home, 'persona.json');
38
+ try {
39
+ const stat = fs.lstatSync(target);
40
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_PERSONA_BYTES) return {};
41
+ const value = JSON.parse(fs.readFileSync(target, 'utf8'));
42
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
43
+ } catch {
44
+ return {};
45
+ }
46
+ }
47
+
48
+ function readJsonFile(target) {
49
+ try {
50
+ const stat = fs.lstatSync(target);
51
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_PERSONA_BYTES) return undefined;
52
+ const value = JSON.parse(fs.readFileSync(target, 'utf8'));
53
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
54
+ } catch {
55
+ return undefined;
56
+ }
57
+ }
58
+
59
+ function createJsonOnce(root, target, value) {
60
+ if (!isInside(root, target)) return false;
61
+ let handle;
62
+ try {
63
+ const parent = path.dirname(target);
64
+ fs.mkdirSync(parent, { recursive: true });
65
+ if (!isInside(root, fs.realpathSync(parent))) return false;
66
+ handle = fs.openSync(target, 'wx', 0o600);
67
+ fs.writeFileSync(handle, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
68
+ fs.fsyncSync(handle);
69
+ return true;
70
+ } catch (error) {
71
+ if (error?.code === 'EEXIST') return false;
72
+ throw error;
73
+ } finally {
74
+ if (handle !== undefined) fs.closeSync(handle);
75
+ }
76
+ }
77
+
78
+ function createTextOnce(root, target, value) {
79
+ if (!isInside(root, target)) return false;
80
+ let handle;
81
+ try {
82
+ const parent = path.dirname(target);
83
+ fs.mkdirSync(parent, { recursive: true });
84
+ if (!isInside(root, fs.realpathSync(parent))) return false;
85
+ handle = fs.openSync(target, 'wx', 0o600);
86
+ fs.writeFileSync(handle, value, 'utf8');
87
+ fs.fsyncSync(handle);
88
+ return true;
89
+ } catch (error) {
90
+ if (error?.code === 'EEXIST') return false;
91
+ throw error;
92
+ } finally {
93
+ if (handle !== undefined) fs.closeSync(handle);
94
+ }
95
+ }
96
+
97
+ function ensurePersonalityWorkspace(env = process.env) {
98
+ const home = resolvedHome(env);
99
+ fs.mkdirSync(home, { recursive: true });
100
+ const root = path.resolve(String(env.BLUN_IDENTITY_ROOT ?? '').trim() || path.join(home, 'identity'));
101
+ if (!isInside(home, root)) return { ready: false, reason: 'identity_root_outside_home' };
102
+ if (fs.existsSync(root) && fs.lstatSync(root).isSymbolicLink()) return { ready: false, reason: 'identity_root_symlink' };
103
+ fs.mkdirSync(root, { recursive: true });
104
+ const realHome = fs.realpathSync(home);
105
+ const realRoot = fs.realpathSync(root);
106
+ if (!isInside(realHome, realRoot)) return { ready: false, reason: 'identity_root_outside_home' };
107
+
108
+ const persona = readPersona(home);
109
+ const displayName = String(persona.name ?? env.BLUN_AGENT_ID ?? 'King').trim().slice(0, 120) || 'King';
110
+ const requestedAgentId = safeId(env.BLUN_AGENT_ID) || agentIdFromName(displayName);
111
+ const requestedTenantId = safeId(env.BLUN_IDENTITY_TENANT_ID) || 'local';
112
+ const manifestPath = path.join(root, 'manifest.json');
113
+ createJsonOnce(root, manifestPath, {
114
+ version: 1,
115
+ tenant_id: requestedTenantId,
116
+ active_agent_id: requestedAgentId,
117
+ });
118
+ const manifest = readJsonFile(manifestPath);
119
+ const tenantId = safeId(manifest?.tenant_id);
120
+ const agentId = safeId(manifest?.active_agent_id);
121
+ if (manifest?.version !== 1 || !tenantId || !agentId) return { ready: false, reason: 'identity_manifest_invalid' };
122
+
123
+ const profilePath = path.join(root, 'agents', agentId, 'profile.json');
124
+ createJsonOnce(root, profilePath, {
125
+ version: 1,
126
+ agent_id: agentId,
127
+ display_name: displayName,
128
+ role: '',
129
+ preferences: [],
130
+ goals: [],
131
+ });
132
+ createTextOnce(
133
+ root,
134
+ path.join(root, 'agents', agentId, 'JOURNAL.md'),
135
+ '# Journal\n\nLong-term development notes, shared milestones, and confirmed lessons belong here. Current tasks, secrets, permissions, and incident logs do not.\n',
136
+ );
137
+ for (const relative of [
138
+ ['agents', agentId, 'relationships'],
139
+ ['agents', agentId, 'journal', 'candidates'],
140
+ ['agents', agentId, 'activity'],
141
+ ['actors'],
142
+ ['groups'],
143
+ ['attention'],
144
+ ]) {
145
+ const target = path.resolve(root, ...relative);
146
+ if (!isInside(root, target)) return { ready: false, reason: 'identity_path_invalid' };
147
+ fs.mkdirSync(target, { recursive: true });
148
+ if (!isInside(root, fs.realpathSync(target))) return { ready: false, reason: 'identity_path_invalid' };
149
+ }
150
+ return { ready: true, root, tenant_id: tenantId, agent_id: agentId };
151
+ }
152
+
153
+ module.exports = { ensurePersonalityWorkspace };
@@ -0,0 +1,124 @@
1
+ 'use strict';
2
+
3
+ const fs = require('node:fs');
4
+ const path = require('node:path');
5
+
6
+ const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
7
+ const MAX_FILE_BYTES = 64 * 1024;
8
+ const MAX_ENTRIES = 6;
9
+ const MAX_RECENT_CONTEXT = 2;
10
+ const MAX_TEXT_CHARS = 240;
11
+ const LONG_GAP_MS = 7 * 24 * 60 * 60 * 1000;
12
+ const ATTENTION_COOLDOWN_MS = 30 * 24 * 60 * 60 * 1000;
13
+
14
+ function safeId(value) {
15
+ const normalized = String(value ?? '').trim();
16
+ return SAFE_ID_RE.test(normalized) ? normalized : '';
17
+ }
18
+
19
+ function isInside(root, target) {
20
+ const relative = path.relative(root, target);
21
+ return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));
22
+ }
23
+
24
+ function trustedTimestamp(value) {
25
+ const text = String(value ?? '').trim();
26
+ return text && !Number.isNaN(Date.parse(text)) ? new Date(text).toISOString() : '';
27
+ }
28
+
29
+ function redactSecrets(value) {
30
+ return String(value ?? '')
31
+ .replace(/\bsk-[A-Za-z0-9_-]{8,}\b/gu, '[REDACTED]')
32
+ .replace(/\b(?:token|password|passwort|secret|api[_ -]?key)\s*[:=]\s*\S+/giu, '$1=[REDACTED]')
33
+ .replace(/[\u0000-\u001f\u007f]+/gu, ' ')
34
+ .replace(/\s+/gu, ' ')
35
+ .trim()
36
+ .slice(0, MAX_TEXT_CHARS);
37
+ }
38
+
39
+ function readJson(root, target) {
40
+ if (!isInside(root, target)) return undefined;
41
+ try {
42
+ const stat = fs.lstatSync(target);
43
+ if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_FILE_BYTES) return undefined;
44
+ const value = JSON.parse(fs.readFileSync(target, 'utf8'));
45
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
46
+ } catch {
47
+ return undefined;
48
+ }
49
+ }
50
+
51
+ function writeJsonAtomic(root, target, value) {
52
+ if (!isInside(root, target)) return false;
53
+ const parent = path.dirname(target);
54
+ let temporary;
55
+ try {
56
+ fs.mkdirSync(parent, { recursive: true });
57
+ if (!isInside(root, fs.realpathSync(parent))) return false;
58
+ if (fs.existsSync(target) && fs.lstatSync(target).isSymbolicLink()) return false;
59
+ temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
60
+ fs.writeFileSync(temporary, `${JSON.stringify(value, null, 2)}\n`, { encoding: 'utf8', mode: 0o600, flag: 'wx' });
61
+ fs.renameSync(temporary, target);
62
+ return true;
63
+ } catch {
64
+ if (temporary) {
65
+ try { fs.unlinkSync(temporary); } catch {}
66
+ }
67
+ return false;
68
+ }
69
+ }
70
+
71
+ function attentionForReturn({ root, agentId, actorId, previousAt, currentAt }) {
72
+ if (!previousAt || Date.parse(currentAt) - Date.parse(previousAt) < LONG_GAP_MS) return undefined;
73
+ const target = path.resolve(root, 'attention', `${actorId}.json`);
74
+ const existing = readJson(root, target);
75
+ const lastNoticeAt = trustedTimestamp(existing?.noticed_at);
76
+ if (lastNoticeAt && Date.parse(currentAt) - Date.parse(lastNoticeAt) < ATTENTION_COOLDOWN_MS) return undefined;
77
+ const attention = {
78
+ status: 'noticed_on_return',
79
+ subject_type: 'human',
80
+ actor_id: actorId,
81
+ responsible_agent: agentId,
82
+ noticed_at: currentAt,
83
+ previous_interaction_at: previousAt,
84
+ message: 'A reliable long gap is visible in direct history. Acknowledge the return naturally only if it fits after the current task.',
85
+ };
86
+ return writeJsonAtomic(root, target, attention) ? attention : undefined;
87
+ }
88
+
89
+ function prepareRelationshipTurn(input = {}) {
90
+ const root = path.resolve(String(input.root ?? ''));
91
+ const agentId = safeId(input.agentId);
92
+ const actorId = safeId(input.actorId);
93
+ const groupId = safeId(input.groupId);
94
+ const occurredAt = trustedTimestamp(input.occurredAt);
95
+ if (!agentId || !actorId || !occurredAt || !fs.existsSync(root)) return { recent: [], attention: undefined };
96
+ if (groupId) return { recent: [], attention: undefined };
97
+
98
+ const text = redactSecrets(input.text);
99
+ const target = path.resolve(root, 'agents', agentId, 'journal', 'recent', `${actorId}.json`);
100
+ const existing = readJson(root, target);
101
+ const entries = Array.isArray(existing?.entries)
102
+ ? existing.entries.filter((entry) => trustedTimestamp(entry?.occurred_at) && typeof entry?.text === 'string').slice(-MAX_ENTRIES)
103
+ : [];
104
+ const previous = entries.at(-1);
105
+ const recent = entries.slice(-MAX_RECENT_CONTEXT).map((entry) => ({
106
+ occurred_at: trustedTimestamp(entry.occurred_at),
107
+ text: redactSecrets(entry.text),
108
+ }));
109
+ const attention = attentionForReturn({
110
+ root,
111
+ agentId,
112
+ actorId,
113
+ previousAt: trustedTimestamp(previous?.occurred_at),
114
+ currentAt: occurredAt,
115
+ });
116
+
117
+ if (text) {
118
+ const next = [...entries, { occurred_at: occurredAt, text }].slice(-MAX_ENTRIES);
119
+ writeJsonAtomic(root, target, { version: 1, actor_id: actorId, entries: next });
120
+ }
121
+ return { recent, attention };
122
+ }
123
+
124
+ module.exports = { prepareRelationshipTurn };
@@ -10,7 +10,6 @@ function isQueuedReload(item) {
10
10
  function removeQueuedReloadCommands(queue) {
11
11
  const removed = [];
12
12
  let writeIndex = 0;
13
-
14
13
  for (const item of queue) {
15
14
  if (isQueuedReload(item)) {
16
15
  removed.push(item);
@@ -19,7 +18,6 @@ function removeQueuedReloadCommands(queue) {
19
18
  queue[writeIndex] = item;
20
19
  writeIndex += 1;
21
20
  }
22
-
23
21
  queue.length = writeIndex;
24
22
  return removed;
25
23
  }
package/blun.mjs CHANGED
@@ -21441,6 +21441,7 @@ var { boundSystemPromptDirectoryListing, compactRepeatedConductSections, fingerp
21441
21441
  var { identitySystemBlock, recordChannelIdentity } = createRequire(import.meta.url)("./bin/identity-context-policy.cjs");
21442
21442
  var { naturalPresenceSystemBlock } = createRequire(import.meta.url)("./bin/natural-presence-policy.cjs");
21443
21443
  var { personalityContextEnabled } = createRequire(import.meta.url)("./bin/personality-mode.cjs");
21444
+ var { ensurePersonalityWorkspace } = createRequire(import.meta.url)("./bin/personality-setup-policy.cjs");
21444
21445
  var { projectSoulText } = createRequire(import.meta.url)("./bin/soul-organization-policy.cjs");
21445
21446
  var { soulFileInstruction } = createRequire(import.meta.url)("./bin/soul-preservation-policy.cjs");
21446
21447
  async function prepareSystemPromptContext(kaos, brandHome, options) {
@@ -427143,6 +427144,10 @@ function setPersonalityEnabled(enabled) {
427143
427144
  };
427144
427145
  mkdirSync(getDataDir(), { recursive: true });
427145
427146
  writeFileSync(personaFilePath(), `${JSON.stringify(next, null, 2)}\n`, "utf8");
427147
+ if (enabled) {
427148
+ const setup = ensurePersonalityWorkspace();
427149
+ if (!setup.ready) throw new Error(`PERSONALITY_SETUP_FAILED:${setup.reason}`);
427150
+ }
427146
427151
  }
427147
427152
  /** Append a note about how the user likes the agent to be (persona growth). */
427148
427153
  function addPersonaNote(note) {
@@ -516853,10 +516858,14 @@ var BlunTUI = class {
516853
516858
  * steers one FIFO head into the active turn without interrupting it.
516854
516859
  */
516855
516860
  injectChannelMessage(envelope, acknowledge) {
516856
- recordChannelIdentity({ source: "telegram", meta: envelope.meta });
516861
+ const identity = recordChannelIdentity({ source: "telegram", text: envelope.text, meta: envelope.meta });
516857
516862
  const urgent = channelMessageAddressed(envelope) ? telegramUrgentMessage(envelope) : void 0;
516858
516863
  const urgentEnvelope = urgent === void 0 ? void 0 : rewriteTelegramUrgentEnvelope(envelope, urgent.text);
516859
- const routedEnvelope = urgentEnvelope ?? envelope;
516864
+ const routedEnvelopeBase = urgentEnvelope ?? envelope;
516865
+ const routedEnvelope = identity?.model_context ? {
516866
+ ...routedEnvelopeBase,
516867
+ tag: `${routedEnvelopeBase.tag}\n\n<identity-context>\n${identity.model_context}\n</identity-context>`
516868
+ } : routedEnvelopeBase;
516860
516869
  const remoteCommand = urgentEnvelope === void 0 && channelMessageAddressed(envelope) ? telegramRemoteCommand(envelope.text) : void 0;
516861
516870
  if (remoteCommand !== void 0) {
516862
516871
  this.injectTelegramRemoteCommand(envelope, remoteCommand, acknowledge);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.297",
3
+ "version": "9.1.298",
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": {