blun-king-cli 9.1.259 → 9.1.260
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,6 +2,7 @@ const fs = require('node:fs');
|
|
|
2
2
|
const os = require('node:os');
|
|
3
3
|
const path = require('node:path');
|
|
4
4
|
const { recordIdentityJournalCandidate } = require('./identity-journal-policy.cjs');
|
|
5
|
+
const { personalityContextEnabled } = require('./personality-mode.cjs');
|
|
5
6
|
|
|
6
7
|
const MAX_FILE_BYTES = 64 * 1024;
|
|
7
8
|
const DEFAULT_MAX_CHARS = 1800;
|
|
@@ -11,10 +12,6 @@ const SAFE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u;
|
|
|
11
12
|
const TELEGRAM_SUBJECT_RE = /^\d{1,32}$/u;
|
|
12
13
|
const TELEGRAM_CHAT_RE = /^-?\d{1,32}$/u;
|
|
13
14
|
|
|
14
|
-
function enabled(env) {
|
|
15
|
-
return /^(?:1|true)$/iu.test(String(env.BLUN_IDENTITY_CONTEXT ?? '').trim());
|
|
16
|
-
}
|
|
17
|
-
|
|
18
15
|
function autoGraphEnabled(env) {
|
|
19
16
|
return /^(?:1|true)$/iu.test(String(env.BLUN_IDENTITY_AUTO_GRAPH ?? '').trim());
|
|
20
17
|
}
|
|
@@ -158,7 +155,7 @@ function trustedTimestamp(value) {
|
|
|
158
155
|
}
|
|
159
156
|
|
|
160
157
|
function recordChannelIdentity(envelope, env = process.env) {
|
|
161
|
-
if (!autoGraphEnabled(env) || envelope?.source !== 'telegram') return undefined;
|
|
158
|
+
if (!personalityContextEnabled(env) || !autoGraphEnabled(env) || envelope?.source !== 'telegram') return undefined;
|
|
162
159
|
const meta = envelope?.meta;
|
|
163
160
|
if (!meta || typeof meta !== 'object') return undefined;
|
|
164
161
|
const subjectId = String(meta.user_id ?? '').trim();
|
|
@@ -226,7 +223,7 @@ function recordChannelIdentity(envelope, env = process.env) {
|
|
|
226
223
|
}
|
|
227
224
|
|
|
228
225
|
function identitySystemBlock(env = process.env) {
|
|
229
|
-
if (!
|
|
226
|
+
if (!personalityContextEnabled(env)) return '';
|
|
230
227
|
const root = resolveRoot(env);
|
|
231
228
|
if (!root) return '';
|
|
232
229
|
const manifest = readJson(root, ['manifest.json']);
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { personalityContextEnabled } = require('./personality-mode.cjs');
|
|
4
|
+
|
|
3
5
|
const NATURAL_PRESENCE_BLOCK = `## Natural presence
|
|
4
6
|
|
|
5
7
|
Keep the loaded soul intact and let it shape the voice. Speak like an ongoing teammate, using only real shared context; never invent history or feelings. During active work, the current task and evidence come first. Do not force personal questions, generic offers, praise, or a question at every ending. Silence and a clean ending are valid.`;
|
|
6
8
|
|
|
7
9
|
const PERSONALITY_CURIOSITY_BLOCK = `When personality context is enabled and the conversation is relaxed rather than task-focused, show genuine curiosity: if it fits, ask one natural, optional personal question about their partner, family, work, home, interests, or what matters to them now. Never turn the conversation into an interview or stack questions. Do not repeat an unanswered question or infer an answer. During active work, do not interrupt the task; wait for a natural opening.`;
|
|
8
10
|
|
|
9
|
-
function personalityContextEnabled(env) {
|
|
10
|
-
return /^(?:1|true)$/iu.test(String(env.BLUN_IDENTITY_CONTEXT ?? '').trim());
|
|
11
|
-
}
|
|
12
|
-
|
|
13
11
|
function naturalPresenceSystemBlock(env = process.env) {
|
|
14
12
|
if (!personalityContextEnabled(env)) return NATURAL_PRESENCE_BLOCK;
|
|
15
13
|
return `${NATURAL_PRESENCE_BLOCK}\n\n${PERSONALITY_CURIOSITY_BLOCK}`;
|
|
@@ -0,0 +1,35 @@
|
|
|
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 MAX_PERSONA_BYTES = 64 * 1024;
|
|
8
|
+
|
|
9
|
+
function resolvedHome(env) {
|
|
10
|
+
const configured = String(env.BLUN_SHARED_HOME ?? env.BLUN_HOME ?? '').trim();
|
|
11
|
+
return path.resolve(configured || path.join(os.homedir(), '.blun'));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function persistedPersonalityChoice(env) {
|
|
15
|
+
const personaPath = path.join(resolvedHome(env), 'persona.json');
|
|
16
|
+
try {
|
|
17
|
+
const stat = fs.lstatSync(personaPath);
|
|
18
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_PERSONA_BYTES) return undefined;
|
|
19
|
+
const persona = JSON.parse(fs.readFileSync(personaPath, 'utf8'));
|
|
20
|
+
return typeof persona?.personalityEnabled === 'boolean' ? persona.personalityEnabled : undefined;
|
|
21
|
+
} catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function personalityContextEnabled(env = process.env) {
|
|
27
|
+
const persisted = persistedPersonalityChoice(env);
|
|
28
|
+
if (persisted !== undefined) return persisted;
|
|
29
|
+
return /^(?:1|true)$/iu.test(String(env.BLUN_IDENTITY_CONTEXT ?? '').trim());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = {
|
|
33
|
+
personalityContextEnabled,
|
|
34
|
+
};
|
|
35
|
+
|
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 { personalityContextEnabled } = createRequire(import.meta.url)("./bin/personality-mode.cjs");
|
|
21443
21444
|
var { projectSoulText } = createRequire(import.meta.url)("./bin/soul-organization-policy.cjs");
|
|
21444
21445
|
var { soulFileInstruction } = createRequire(import.meta.url)("./bin/soul-preservation-policy.cjs");
|
|
21445
21446
|
async function prepareSystemPromptContext(kaos, brandHome, options) {
|
|
@@ -413851,6 +413852,10 @@ registerUiCatalogFragment({
|
|
|
413851
413852
|
"swarmPermission.manual.description": "Keep approvals on. BLUN may stop and wait for you during the swarm task.",
|
|
413852
413853
|
"settings.actionStyle.label": "Output style",
|
|
413853
413854
|
"settings.actionStyle.description": "Choose how BLUN responds and presents its work.",
|
|
413855
|
+
"settings.personality.label": "Personality",
|
|
413856
|
+
"settings.personality.description": "Controls relationship context, journal, and natural curiosity.",
|
|
413857
|
+
"personality.on.description": "Uses relationships and the journal and asks at most one personal question when it fits.",
|
|
413858
|
+
"personality.off.description": "Keeps Soul, agent rules, and task focus without relationship or curiosity additions.",
|
|
413854
413859
|
"actionStyle.title": "Preferred output style",
|
|
413855
413860
|
"actionStyle.scope": "This setting changes how BLUN responds. Plan and permission rules still take priority.",
|
|
413856
413861
|
"actionStyle.default.label": "Default",
|
|
@@ -413927,6 +413932,10 @@ registerUiCatalogFragment({
|
|
|
413927
413932
|
"swarmPermission.manual.description": "Freigaben beibehalten. BLUN kann den Swarm-Auftrag anhalten und auf dich warten.",
|
|
413928
413933
|
"settings.actionStyle.label": "Ausgabestil",
|
|
413929
413934
|
"settings.actionStyle.description": "Lege fest, wie BLUN antwortet und seine Arbeit darstellt.",
|
|
413935
|
+
"settings.personality.label": "Persönlichkeit",
|
|
413936
|
+
"settings.personality.description": "Steuert Beziehungskontext, Journal und natürliche Neugier.",
|
|
413937
|
+
"personality.on.description": "Bezieht Beziehungen und Journal ein und stellt bei passender Gelegenheit höchstens eine persönliche Frage.",
|
|
413938
|
+
"personality.off.description": "Behält Seele, Agentenregeln und Arbeitsfokus bei, ohne Beziehungs- oder Neugierzusätze.",
|
|
413930
413939
|
"actionStyle.title": "Bevorzugter Ausgabestil",
|
|
413931
413940
|
"actionStyle.scope": "Diese Einstellung bestimmt, wie BLUN antwortet. Plan- und Berechtigungsregeln haben weiterhin Vorrang.",
|
|
413932
413941
|
"actionStyle.default.label": "Standard",
|
|
@@ -414003,6 +414012,10 @@ registerUiCatalogFragment({
|
|
|
414003
414012
|
"swarmPermission.manual.description": "Mantener activadas las aprobaciones. BLUN puede detenerse y esperar tu intervención durante la tarea de Swarm.",
|
|
414004
414013
|
"settings.actionStyle.label": "Estilo de salida",
|
|
414005
414014
|
"settings.actionStyle.description": "Elige cómo responde BLUN y cómo presenta su trabajo.",
|
|
414015
|
+
"settings.personality.label": "Personalidad",
|
|
414016
|
+
"settings.personality.description": "Controla el contexto de las relaciones, el diario y la curiosidad natural.",
|
|
414017
|
+
"personality.on.description": "Tiene en cuenta las relaciones y el diario, y hace como máximo una pregunta personal cuando encaja.",
|
|
414018
|
+
"personality.off.description": "Mantiene el alma, las reglas del agente y el foco en la tarea, sin añadidos de relaciones ni curiosidad.",
|
|
414006
414019
|
"actionStyle.title": "Estilo de salida preferido",
|
|
414007
414020
|
"actionStyle.scope": "Esta opción determina cómo responde BLUN. Las reglas del plan y de permisos siguen teniendo prioridad.",
|
|
414008
414021
|
"actionStyle.default.label": "Predeterminado",
|
|
@@ -414079,6 +414092,10 @@ registerUiCatalogFragment({
|
|
|
414079
414092
|
"swarmPermission.manual.description": "Conserver les approbations. BLUN peut s’arrêter et attendre votre réponse pendant la tâche en essaim.",
|
|
414080
414093
|
"settings.actionStyle.label": "Style de réponse",
|
|
414081
414094
|
"settings.actionStyle.description": "Choisissez la manière dont BLUN répond et présente son travail.",
|
|
414095
|
+
"settings.personality.label": "Personnalité",
|
|
414096
|
+
"settings.personality.description": "Contrôle le contexte relationnel, le journal et la curiosité naturelle.",
|
|
414097
|
+
"personality.on.description": "Prend en compte les relations et le journal, et pose au plus une question personnelle lorsque le contexte s’y prête.",
|
|
414098
|
+
"personality.off.description": "Conserve l’âme, les règles de l’agent et l’attention portée à la tâche, sans ajout relationnel ni curiosité.",
|
|
414082
414099
|
"actionStyle.title": "Style de réponse préféré",
|
|
414083
414100
|
"actionStyle.scope": "Ce réglage détermine la manière dont BLUN répond. Les règles du plan et des autorisations restent prioritaires.",
|
|
414084
414101
|
"actionStyle.default.label": "Par défaut",
|
|
@@ -414155,6 +414172,10 @@ registerUiCatalogFragment({
|
|
|
414155
414172
|
"swarmPermission.manual.description": "Behåll godkännanden aktiverade. BLUN kan stanna och vänta på dig under Swarm-uppgiften.",
|
|
414156
414173
|
"settings.actionStyle.label": "Svarsstil",
|
|
414157
414174
|
"settings.actionStyle.description": "Välj hur BLUN svarar och presenterar sitt arbete.",
|
|
414175
|
+
"settings.personality.label": "Personlighet",
|
|
414176
|
+
"settings.personality.description": "Styr relationssammanhang, journal och naturlig nyfikenhet.",
|
|
414177
|
+
"personality.on.description": "Tar hänsyn till relationer och journalen och ställer högst en personlig fråga när det passar.",
|
|
414178
|
+
"personality.off.description": "Behåller själ, agentregler och uppgiftsfokus utan tillägg för relationer eller nyfikenhet.",
|
|
414158
414179
|
"actionStyle.title": "Önskad svarsstil",
|
|
414159
414180
|
"actionStyle.scope": "Den här inställningen styr hur BLUN svarar. Plan- och behörighetsregler har fortfarande företräde.",
|
|
414160
414181
|
"actionStyle.default.label": "Standard",
|
|
@@ -414231,6 +414252,10 @@ registerUiCatalogFragment({
|
|
|
414231
414252
|
"swarmPermission.manual.description": "Ponechte schválení zapnuto. BLUN se může během úlohy roje zastavit a čekat na vás.",
|
|
414232
414253
|
"settings.actionStyle.label": "Styl odpovědí",
|
|
414233
414254
|
"settings.actionStyle.description": "Zvolte, jak BLUN odpovídá a jak prezentuje svou práci.",
|
|
414255
|
+
"settings.personality.label": "Osobnost",
|
|
414256
|
+
"settings.personality.description": "Řídí kontext vztahů, deník a přirozenou zvídavost.",
|
|
414257
|
+
"personality.on.description": "Zohledňuje vztahy a deník a ve vhodnou chvíli položí nejvýše jednu osobní otázku.",
|
|
414258
|
+
"personality.off.description": "Zachová duši, pravidla agenta a soustředění na úkol bez vztahových či zvídavých doplňků.",
|
|
414234
414259
|
"actionStyle.title": "Preferovaný styl odpovědí",
|
|
414235
414260
|
"actionStyle.scope": "Toto nastavení určuje, jak BLUN odpovídá. Pravidla plánu a oprávnění mají i nadále přednost.",
|
|
414236
414261
|
"actionStyle.default.label": "Výchozí",
|
|
@@ -416513,6 +416538,30 @@ var PermissionSelectorComponent = class extends ChoicePickerComponent {
|
|
|
416513
416538
|
}
|
|
416514
416539
|
};
|
|
416515
416540
|
//#endregion
|
|
416541
|
+
//#region src/tui/components/dialogs/personality-selector.ts
|
|
416542
|
+
var PersonalitySelectorComponent = class extends ChoicePickerComponent {
|
|
416543
|
+
constructor(opts) {
|
|
416544
|
+
super({
|
|
416545
|
+
title: uiText("settings.personality.label"),
|
|
416546
|
+
options: [
|
|
416547
|
+
{
|
|
416548
|
+
value: "on",
|
|
416549
|
+
label: uiText("updates.on.label"),
|
|
416550
|
+
description: uiText("personality.on.description")
|
|
416551
|
+
},
|
|
416552
|
+
{
|
|
416553
|
+
value: "off",
|
|
416554
|
+
label: uiText("updates.off.label"),
|
|
416555
|
+
description: uiText("personality.off.description")
|
|
416556
|
+
}
|
|
416557
|
+
],
|
|
416558
|
+
currentValue: opts.currentValue,
|
|
416559
|
+
onSelect: opts.onSelect,
|
|
416560
|
+
onCancel: opts.onCancel
|
|
416561
|
+
});
|
|
416562
|
+
}
|
|
416563
|
+
};
|
|
416564
|
+
//#endregion
|
|
416516
416565
|
//#region src/tui/components/dialogs/settings-selector.ts
|
|
416517
416566
|
function settingsOptions() {
|
|
416518
416567
|
return [
|
|
@@ -416531,6 +416580,11 @@ function settingsOptions() {
|
|
|
416531
416580
|
label: uiText("settings.actionStyle.label"),
|
|
416532
416581
|
description: uiText("settings.actionStyle.description")
|
|
416533
416582
|
},
|
|
416583
|
+
{
|
|
416584
|
+
value: "personality",
|
|
416585
|
+
label: uiText("settings.personality.label"),
|
|
416586
|
+
description: uiText("settings.personality.description")
|
|
416587
|
+
},
|
|
416534
416588
|
{
|
|
416535
416589
|
value: "permission",
|
|
416536
416590
|
label: uiText("settings.permission.label"),
|
|
@@ -416564,7 +416618,7 @@ function settingsOptions() {
|
|
|
416564
416618
|
];
|
|
416565
416619
|
}
|
|
416566
416620
|
function isSettingsSelection(value) {
|
|
416567
|
-
return value === "effort" || value === "action-style" || value === "theme" || value === "appearance" || value === "editor" || value === "permission" || value === "experiments" || value === "usage" || value === "inline-suggest";
|
|
416621
|
+
return value === "effort" || value === "action-style" || value === "personality" || value === "theme" || value === "appearance" || value === "editor" || value === "permission" || value === "experiments" || value === "usage" || value === "inline-suggest";
|
|
416568
416622
|
}
|
|
416569
416623
|
var SettingsSelectorComponent = class extends ChoicePickerComponent {
|
|
416570
416624
|
constructor(opts) {
|
|
@@ -420398,6 +420452,28 @@ function showOutputStylePicker(host) {
|
|
|
420398
420452
|
}
|
|
420399
420453
|
}));
|
|
420400
420454
|
}
|
|
420455
|
+
function showPersonalityPicker(host) {
|
|
420456
|
+
host.mountEditorReplacement(new PersonalitySelectorComponent({
|
|
420457
|
+
currentValue: personalityContextEnabled() ? "on" : "off",
|
|
420458
|
+
onSelect: (value) => {
|
|
420459
|
+
host.restoreEditorAfter(() => applyPersonalityChoice(host, value === "on"));
|
|
420460
|
+
},
|
|
420461
|
+
onCancel: () => {
|
|
420462
|
+
host.restoreEditor();
|
|
420463
|
+
}
|
|
420464
|
+
}));
|
|
420465
|
+
}
|
|
420466
|
+
async function applyPersonalityChoice(host, enabled) {
|
|
420467
|
+
try {
|
|
420468
|
+
setPersonalityEnabled(enabled);
|
|
420469
|
+
await refreshPersonaInSession(host);
|
|
420470
|
+
} catch (error) {
|
|
420471
|
+
host.showError(uiText("session.persona.note.saveFailed", { error: formatErrorMessage$2(error) }));
|
|
420472
|
+
return;
|
|
420473
|
+
}
|
|
420474
|
+
const state = enabled ? uiText("updates.on.label") : uiText("updates.off.label");
|
|
420475
|
+
host.showStatus(`${uiText("settings.personality.label")}: ${state}`, "success");
|
|
420476
|
+
}
|
|
420401
420477
|
async function applyActionStyleChoice(host, style) {
|
|
420402
420478
|
const previous = host.state.appState.actionStyle ?? "default";
|
|
420403
420479
|
const session = host.requireSession();
|
|
@@ -420493,6 +420569,9 @@ function handleSettingsSelection(host, value) {
|
|
|
420493
420569
|
case "action-style":
|
|
420494
420570
|
showOutputStylePicker(host);
|
|
420495
420571
|
return;
|
|
420572
|
+
case "personality":
|
|
420573
|
+
showPersonalityPicker(host);
|
|
420574
|
+
return;
|
|
420496
420575
|
case "permission":
|
|
420497
420576
|
showPermissionPicker(host);
|
|
420498
420577
|
return;
|
|
@@ -426838,6 +426917,14 @@ function setLanguage(language) {
|
|
|
426838
426917
|
mkdirSync(getDataDir(), { recursive: true });
|
|
426839
426918
|
writeFileSync(personaFilePath(), `${JSON.stringify(next, null, 2)}\n`, "utf8");
|
|
426840
426919
|
}
|
|
426920
|
+
function setPersonalityEnabled(enabled) {
|
|
426921
|
+
const next = {
|
|
426922
|
+
...readPersona(),
|
|
426923
|
+
personalityEnabled: enabled
|
|
426924
|
+
};
|
|
426925
|
+
mkdirSync(getDataDir(), { recursive: true });
|
|
426926
|
+
writeFileSync(personaFilePath(), `${JSON.stringify(next, null, 2)}\n`, "utf8");
|
|
426927
|
+
}
|
|
426841
426928
|
/** Append a note about how the user likes the agent to be (persona growth). */
|
|
426842
426929
|
function addPersonaNote(note) {
|
|
426843
426930
|
const current = readPersona();
|