blun-king-cli 9.1.179 → 9.1.181

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.
@@ -18,6 +18,7 @@ const {
18
18
  const { installManagedTelegramPlugin } = require('./plugin-bootstrap');
19
19
  const {
20
20
  availableStandardToolNames,
21
+ seedConfiguredMnemoMcp,
21
22
  seedStandardSkills,
22
23
  seedStandardTools,
23
24
  } = require('./standard-tools-bootstrap');
@@ -352,6 +353,15 @@ async function superviseProtectedCore(args, env, cwd, releaseNotice, options = {
352
353
  },
353
354
  });
354
355
  const loaded = await core.loaded;
356
+ if (loaded && !runtimeReady) {
357
+ // Core load is an independent readiness signal. Start the download even
358
+ // when the later TUI-ready IPC message is lost; handoff still waits for
359
+ // the TUI's fully idle boundary.
360
+ runtimeReady = true;
361
+ refreshRunningUpdateMode();
362
+ if (automaticMode()) startPreparation(core.child);
363
+ else scheduleNextPreparation(core.child);
364
+ }
355
365
  await releaseNotice();
356
366
  const result = await core.completed;
357
367
  clearRunningUpdatePoll();
@@ -674,6 +684,7 @@ async function runLauncher(options = {}) {
674
684
  blunDir,
675
685
  names: standardMcpNames,
676
686
  });
687
+ seedConfiguredMnemoMcp({ blunDir, env: process.env });
677
688
 
678
689
  // --- 4. Eigenes BLUN-Grunddesign als einzigen Standard-Skill installieren
679
690
  seedStandardSkills({ packageRoot: PKG, blunDir: privatePaths.sharedHome });
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ const LONG_DUPLICATE_MIN_CHARS = 512;
4
+
5
+ function userMessageText(message) {
6
+ if (
7
+ message?.role !== 'user'
8
+ || message.origin?.kind !== 'user'
9
+ || !Array.isArray(message.content)
10
+ ) return '';
11
+
12
+ const textParts = message.content
13
+ .filter((part) => part?.type === 'text' && typeof part.text === 'string')
14
+ .map((part) => part.text);
15
+ return textParts.length > 0 ? textParts.join('\n') : '';
16
+ }
17
+
18
+ function channelAttribute(attributes, name) {
19
+ const match = String(attributes).match(new RegExp(`(?:^|\\s)${name}="([^"]+)"`, 'u'));
20
+ return match?.[1] ?? '';
21
+ }
22
+
23
+ function telegramDeliveryIdentity(text) {
24
+ const channel = String(text).match(/<channel\b([^>]*)>/u);
25
+ if (channel === null) return '';
26
+
27
+ const source = channelAttribute(channel[1], 'source');
28
+ const chatId = channelAttribute(channel[1], 'chat_id');
29
+ const messageId = channelAttribute(channel[1], 'message_id');
30
+ if (source !== 'telegram' || !chatId || !messageId) return '';
31
+ return `${chatId}:${messageId}`;
32
+ }
33
+
34
+ function repeatedUserMessageKey(message) {
35
+ const text = userMessageText(message);
36
+ if (!text) return '';
37
+
38
+ const telegramIdentity = telegramDeliveryIdentity(text);
39
+ if (telegramIdentity) return `telegram:${telegramIdentity}`;
40
+ return text.length >= LONG_DUPLICATE_MIN_CHARS ? `text:${text}` : '';
41
+ }
42
+
43
+ function dedupeRepeatedUserMessages(messages) {
44
+ if (!Array.isArray(messages) || messages.length < 2) return messages;
45
+
46
+ const lastIndexByKey = new Map();
47
+ const keys = messages.map((message, index) => {
48
+ const key = repeatedUserMessageKey(message);
49
+ if (key) lastIndexByKey.set(key, index);
50
+ return key;
51
+ });
52
+
53
+ let changed = false;
54
+ const projected = messages.filter((message, index) => {
55
+ const key = keys[index];
56
+ const keep = !key || lastIndexByKey.get(key) === index;
57
+ if (!keep) changed = true;
58
+ return keep;
59
+ });
60
+ return changed ? projected : messages;
61
+ }
62
+
63
+ module.exports = {
64
+ LONG_DUPLICATE_MIN_CHARS,
65
+ dedupeRepeatedUserMessages,
66
+ telegramDeliveryIdentity,
67
+ userMessageText,
68
+ };
@@ -255,6 +255,44 @@ function seedStandardTools({
255
255
  return { added, updated, configPath };
256
256
  }
257
257
 
258
+ function seedConfiguredMnemoMcp({
259
+ blunDir,
260
+ env = process.env,
261
+ execPath = process.execPath,
262
+ }) {
263
+ const configPath = path.join(blunDir, 'mcp.json');
264
+ const entry = typeof env.BLUN_MNEMO_MCP === 'string' ? env.BLUN_MNEMO_MCP.trim() : '';
265
+ const agent = typeof env.BLUN_MNEMO_AGENT === 'string' ? env.BLUN_MNEMO_AGENT.trim() : '';
266
+ if (entry.length === 0 || agent.length === 0) {
267
+ return { added: false, reason: 'not_configured', configPath };
268
+ }
269
+ if (!fs.existsSync(entry)) return { added: false, reason: 'entry_missing', configPath };
270
+
271
+ ensurePrivateDirectory(blunDir);
272
+ if (fs.existsSync(configPath)) securePrivateFile(configPath);
273
+ const document = readMcpDocument(configPath);
274
+ const servers = { ...document.mcpServers };
275
+ const equivalent = Object.values(servers).some((config) => (
276
+ isObject(config)
277
+ && Array.isArray(config.args)
278
+ && config.args.some((argument) => argument === entry)
279
+ ));
280
+ if (Object.hasOwn(servers, 'mnemo') || equivalent) {
281
+ return { added: false, reason: 'already_configured', configPath };
282
+ }
283
+
284
+ const configuredNode = typeof env.BLUN_MNEMO_NODE === 'string'
285
+ ? env.BLUN_MNEMO_NODE.trim()
286
+ : '';
287
+ servers.mnemo = {
288
+ command: configuredNode || execPath,
289
+ args: [entry],
290
+ env: { MNEMO_AGENT: agent },
291
+ };
292
+ writeMcpDocument(configPath, { ...document, mcpServers: servers });
293
+ return { added: true, reason: 'added', configPath };
294
+ }
295
+
258
296
  function seedStandardSkills({ packageRoot, blunDir }) {
259
297
  const sourceRoot = path.join(packageRoot, 'standard-skills');
260
298
  const sourceRootStat = fs.lstatSync(sourceRoot);
@@ -344,6 +382,7 @@ function seedStandardDesignSkill(options) {
344
382
  module.exports = {
345
383
  availableStandardToolNames,
346
384
  readCatalogue,
385
+ seedConfiguredMnemoMcp,
347
386
  seedStandardDesignSkill,
348
387
  seedStandardSkills,
349
388
  seedStandardTools,
package/blun.mjs CHANGED
@@ -75985,11 +75985,12 @@ var init_full = __esmMin((() => {
75985
75985
  }));
75986
75986
  //#endregion
75987
75987
  //#region ../../packages/agent-core/src/agent/compaction/micro.ts
75988
- var selectMicroCompactionCutoff, MICRO_COMPACTION_RECENT_MESSAGES, MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED, MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS, isPersistedToolResultReference, projectHistoricalUnaddressedTelegramMessages, compactHistoricalSkillActivations, dedupeRecurringCronWakeups, dedupeRepeatedInjections, DEFAULT_CONFIG, MicroCompaction;
75988
+ var selectMicroCompactionCutoff, MICRO_COMPACTION_RECENT_MESSAGES, MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED, MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS, isPersistedToolResultReference, projectHistoricalUnaddressedTelegramMessages, dedupeRepeatedUserMessages, compactHistoricalSkillActivations, dedupeRecurringCronWakeups, dedupeRepeatedInjections, DEFAULT_CONFIG, MicroCompaction;
75989
75989
  var init_micro = __esmMin((() => {
75990
75990
  ({ selectMicroCompactionCutoff, MICRO_COMPACTION_RECENT_MESSAGES, MICRO_COMPACTION_TOOL_ARGUMENTS_ENABLED, MICRO_COMPACTION_TOOL_ARGUMENT_MIN_TOKENS } = createRequire(import.meta.url)("./bin/micro-compaction-policy.cjs"));
75991
75991
  ({ isPersistedToolResultReference } = createRequire(import.meta.url)("./bin/tool-result-offload-policy.cjs"));
75992
75992
  ({ projectHistoricalUnaddressedTelegramMessages } = createRequire(import.meta.url)("./bin/telegram-context-projection-policy.cjs"));
75993
+ ({ dedupeRepeatedUserMessages } = createRequire(import.meta.url)("./bin/repeated-user-message-projection.cjs"));
75993
75994
  ({ compactHistoricalSkillActivations } = createRequire(import.meta.url)("./bin/skill-activation-performance-policy.cjs"));
75994
75995
  ({ dedupeRecurringCronWakeups, dedupeRepeatedInjections } = createRequire(import.meta.url)("./bin/repeated-injection-projection.cjs"));
75995
75996
  init_tokens();
@@ -78967,7 +78968,8 @@ var init_context$2 = __esmMin((() => {
78967
78968
  const anomalies = [];
78968
78969
  const userOffloaded = this.agent.userMessageOffload.compact(messages);
78969
78970
  const historicalUserReferencesProjected = compactHistoricalPersistedUserMessageReferences(userOffloaded);
78970
- const historicalTelegramProjected = projectHistoricalUnaddressedTelegramMessages(historicalUserReferencesProjected);
78971
+ const duplicateUserMessagesProjected = dedupeRepeatedUserMessages(historicalUserReferencesProjected);
78972
+ const historicalTelegramProjected = projectHistoricalUnaddressedTelegramMessages(duplicateUserMessagesProjected);
78971
78973
  const result = project(this.agent.assistantMessageOffload.compact(this.agent.microCompaction.compact(compactHistoricalSuccessfulToolResults(this.agent.toolResultBatchOffload.compact(dedupeRecurringCronWakeups(dedupeRepeatedInjections(compactHistoricalSkillActivations(compactBaselineSkillInjections(historicalTelegramProjected)))))))), {
78972
78974
  ...options,
78973
78975
  onAnomaly: (anomaly) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.179",
3
+ "version": "9.1.181",
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": {