blun-king-cli 9.1.256 → 9.1.257

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.
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ const IDENTITY_HEADING_RE = /(?:soul|seele|who i am|how i am|wie ich|wer ich|personality|persoenlichkeit|persönlichkeit|voice|stimme|values|werte|relationship|beziehung|relationships|odnos|ko sam|kakav sam|preferences|vorlieben|goals|ziele)/iu;
4
+ const PROJECTION_MARKER = '... (soul projected from the complete unchanged source file)';
5
+
6
+ function splitSoul(text) {
7
+ const matches = [...text.matchAll(/^##\s+.+$/gmu)];
8
+ if (matches.length === 0) return { preamble: text, sections: [] };
9
+ const preamble = text.slice(0, matches[0].index).trimEnd();
10
+ const sections = matches.map((match, index) => {
11
+ const start = match.index;
12
+ const end = matches[index + 1]?.index ?? text.length;
13
+ const raw = text.slice(start, end).trim();
14
+ const newline = raw.indexOf('\n');
15
+ return {
16
+ heading: newline === -1 ? raw : raw.slice(0, newline).trimEnd(),
17
+ body: newline === -1 ? '' : raw.slice(newline + 1).trim(),
18
+ identity: IDENTITY_HEADING_RE.test(match[0]),
19
+ index,
20
+ };
21
+ });
22
+ return { preamble, sections };
23
+ }
24
+
25
+ function allocateBodies(sections, budget) {
26
+ if (budget <= 0) return sections.map(() => '');
27
+ const weights = sections.map((section) => section.identity ? 3 : 1);
28
+ const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
29
+ let remaining = budget;
30
+ return sections.map((section, index) => {
31
+ const remainingWeight = weights.slice(index).reduce((sum, weight) => sum + weight, 0);
32
+ const fairShare = index === sections.length - 1
33
+ ? remaining
34
+ : Math.floor(remaining * weights[index] / remainingWeight);
35
+ const take = Math.min(section.body.length, Math.max(0, fairShare));
36
+ remaining -= take;
37
+ return section.body.slice(0, take).trimEnd();
38
+ });
39
+ }
40
+
41
+ function projectSoulText(value, maxChars = 4000) {
42
+ const text = typeof value === 'string' ? value : '';
43
+ const limit = Number.isFinite(maxChars) ? Math.max(0, Math.floor(maxChars)) : 4000;
44
+ if (text.length <= limit) return text;
45
+ if (limit === 0) return '';
46
+
47
+ const { preamble, sections } = splitSoul(text);
48
+ if (sections.length === 0) return `${text.slice(0, Math.max(0, limit - 1)).trimEnd()}…`.slice(0, limit);
49
+
50
+ const ordered = [
51
+ ...sections.filter((section) => section.identity),
52
+ ...sections.filter((section) => !section.identity),
53
+ ];
54
+ const separatorCost = Math.max(0, ordered.length) * 2;
55
+ const headingCost = ordered.reduce((sum, section) => sum + section.heading.length + 1, 0);
56
+ const markerCost = PROJECTION_MARKER.length + 2;
57
+ const preambleLimit = Math.min(preamble.length, Math.max(160, Math.floor(limit * 0.2)));
58
+ const fixedWithoutPreamble = separatorCost + headingCost + markerCost;
59
+ const preambleBudget = Math.max(0, Math.min(preambleLimit, limit - fixedWithoutPreamble));
60
+ const projectedPreamble = preamble.slice(0, preambleBudget).trimEnd();
61
+ const bodyBudget = Math.max(0, limit - fixedWithoutPreamble - projectedPreamble.length);
62
+ const bodies = allocateBodies(ordered, bodyBudget);
63
+ const parts = [];
64
+ if (projectedPreamble) parts.push(projectedPreamble);
65
+ for (let index = 0; index < ordered.length; index += 1) {
66
+ parts.push(bodies[index] ? `${ordered[index].heading}\n${bodies[index]}` : ordered[index].heading);
67
+ }
68
+ parts.push(PROJECTION_MARKER);
69
+ return parts.join('\n\n').slice(0, limit).trimEnd();
70
+ }
71
+
72
+ module.exports = {
73
+ projectSoulText,
74
+ };
package/blun.mjs CHANGED
@@ -21440,6 +21440,7 @@ var init_list_directory = __esmMin((() => {
21440
21440
  var { boundSystemPromptDirectoryListing, compactRepeatedConductSections, fingerprintSystemPromptContext, refreshedSystemPromptContext, resolveStableSystemPromptTimestamp } = createRequire(import.meta.url)("./bin/system-prompt-context-policy.cjs");
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
+ var { projectSoulText } = createRequire(import.meta.url)("./bin/soul-organization-policy.cjs");
21443
21444
  var { soulFileInstruction } = createRequire(import.meta.url)("./bin/soul-preservation-policy.cjs");
21444
21445
  async function prepareSystemPromptContext(kaos, brandHome, options) {
21445
21446
  const additionalDirs = normalizeAdditionalDirs(options?.additionalDirs ?? []);
@@ -28275,7 +28276,7 @@ function soulSystemBlock(env = process.env) {
28275
28276
  try {
28276
28277
  if (existsSync(path)) {
28277
28278
  soul = readFileSync(path, "utf8").trim();
28278
- if (soul.length > SOUL_MAX_CHARS) soul = soul.slice(0, SOUL_MAX_CHARS) + "\n… (soul truncated)";
28279
+ soul = projectSoulText(soul, SOUL_MAX_CHARS);
28279
28280
  }
28280
28281
  } catch {
28281
28282
  soul = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.256",
3
+ "version": "9.1.257",
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": {