blun-king-cli 9.1.417 → 9.1.419
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.
- package/LIESMICH.txt +15 -0
- package/README.md +15 -0
- package/bin/cognitive-goal-autostart-policy.cjs +22 -0
- package/bin/identity-context-policy.cjs +61 -3
- package/blun.mjs +27 -1
- package/package.json +1 -1
- package/telegram-plugin/dist/bridge.mjs +1 -0
package/LIESMICH.txt
CHANGED
|
@@ -75,6 +75,21 @@ sämtliche zurückgegebenen Nachrichten-IDs zusammen mit dem vollständigen Text
|
|
|
75
75
|
Schlägt ein Teil fehl, endet die Zustellung an dieser Stelle, statt die Antwort
|
|
76
76
|
fälschlich als vollständig zu melden.
|
|
77
77
|
|
|
78
|
+
Ab BLUN King 9.1.418 übernimmt der Identitätsgraph die von Telegram bestätigte
|
|
79
|
+
Unterscheidung zwischen Menschen und Bots. Bereits vorhandene
|
|
80
|
+
Telegram-Kontakte, die mangels dieses Merkmals als Menschen angelegt wurden,
|
|
81
|
+
werden bei der nächsten eindeutig als Bot bestätigten Nachricht einmalig als
|
|
82
|
+
Agent korrigiert. Alle Rollen, Zuständigkeiten, Beziehungsnotizen und sonstigen
|
|
83
|
+
Felder bleiben unverändert. Ein Agent wird niemals zu einer Person
|
|
84
|
+
zurückgestuft; Namen oder Benutzernamen dienen nicht als Beweis.
|
|
85
|
+
|
|
86
|
+
Ab BLUN King 9.1.419 setzt eine natürlich fortgesetzte Sitzung ein bereits
|
|
87
|
+
aktives Ziel selbstständig fort, wenn dessen gespeicherter nächster Auslöser
|
|
88
|
+
ausdrücklich sofort gilt und Auto- oder God-Modus aktiv ist. Die Fortsetzung
|
|
89
|
+
erscheint nicht als erfundene Benutzernachricht und wird pro Sitzung nur einmal
|
|
90
|
+
angestoßen. Wartende, pausierte und blockierte Ziele sowie manuelle
|
|
91
|
+
Berechtigungsmodi starten weiterhin nicht selbstständig.
|
|
92
|
+
|
|
78
93
|
Zuverlässiger King-Start
|
|
79
94
|
-----------------------
|
|
80
95
|
Bei einer ausdrücklich als wiederholbar gekennzeichneten Serverüberlastung
|
package/README.md
CHANGED
|
@@ -90,10 +90,25 @@ sämtliche zurückgegebenen Nachrichten-IDs zusammen mit dem vollständigen Text
|
|
|
90
90
|
Schlägt ein Teil fehl, endet die Zustellung an dieser Stelle, statt die Antwort
|
|
91
91
|
fälschlich als vollständig zu melden.
|
|
92
92
|
|
|
93
|
+
Ab BLUN King 9.1.418 übernimmt der Identitätsgraph die von Telegram bestätigte
|
|
94
|
+
Unterscheidung zwischen Menschen und Bots. Bereits vorhandene
|
|
95
|
+
Telegram-Kontakte, die mangels dieses Merkmals als Menschen angelegt wurden,
|
|
96
|
+
werden bei der nächsten eindeutig als Bot bestätigten Nachricht einmalig als
|
|
97
|
+
Agent korrigiert. Alle Rollen, Zuständigkeiten, Beziehungsnotizen und sonstigen
|
|
98
|
+
Felder bleiben unverändert. Ein Agent wird niemals zu einer Person
|
|
99
|
+
zurückgestuft; Namen oder Benutzernamen dienen nicht als Beweis.
|
|
100
|
+
|
|
93
101
|
`Strg+C` und `Esc` brechen einen aktiven Zug zuverlässig ab, ohne den bereits
|
|
94
102
|
geschriebenen Entwurf zu löschen. Das gilt auch bei Autovervollständigung,
|
|
95
103
|
Geistervorschlägen, Bash-Eingabe und einer noch offenen Mehrzeileneingabe.
|
|
96
104
|
|
|
105
|
+
Ab BLUN King 9.1.419 setzt eine natürlich fortgesetzte Sitzung ein bereits
|
|
106
|
+
aktives Ziel selbstständig fort, wenn dessen gespeicherter nächster Auslöser
|
|
107
|
+
ausdrücklich sofort gilt und Auto- oder God-Modus aktiv ist. Die Fortsetzung
|
|
108
|
+
erscheint nicht als erfundene Benutzernachricht und wird pro Sitzung nur einmal
|
|
109
|
+
angestoßen. Wartende, pausierte und blockierte Ziele sowie manuelle
|
|
110
|
+
Berechtigungsmodi starten weiterhin nicht selbstständig.
|
|
111
|
+
|
|
97
112
|
## Zuverlässiger King-Start
|
|
98
113
|
|
|
99
114
|
Bei einer vom Server ausdrücklich als wiederholbar gekennzeichneten
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const AUTONOMOUS_PERMISSION_MODES = new Set(['auto', 'yolo']);
|
|
4
|
+
const ACTIVE_PHASES = new Set(['orient', 'plan', 'act', 'verify', 'learn']);
|
|
5
|
+
const START = Object.freeze({ kind: 'start', trigger: 'immediate' });
|
|
6
|
+
const WAIT = Object.freeze({ kind: 'wait' });
|
|
7
|
+
|
|
8
|
+
function goalAutostartDecision({ goal, permissionMode } = {}) {
|
|
9
|
+
if (!goal || typeof goal !== 'object' || Array.isArray(goal)) return WAIT;
|
|
10
|
+
if (goal.status !== 'active' || !AUTONOMOUS_PERMISSION_MODES.has(permissionMode)) return WAIT;
|
|
11
|
+
|
|
12
|
+
const checkpoint = goal.actionCheckpoint;
|
|
13
|
+
if (!checkpoint || typeof checkpoint !== 'object' || Array.isArray(checkpoint)) return WAIT;
|
|
14
|
+
if (!ACTIVE_PHASES.has(checkpoint.phase)) return WAIT;
|
|
15
|
+
const trigger = checkpoint.nextTrigger;
|
|
16
|
+
if (!trigger || typeof trigger !== 'object' || Array.isArray(trigger)) return WAIT;
|
|
17
|
+
if (trigger.kind !== 'immediate') return WAIT;
|
|
18
|
+
if (typeof trigger.condition !== 'string' || trigger.condition.trim().length === 0) return WAIT;
|
|
19
|
+
return START;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { goalAutostartDecision };
|
|
@@ -93,6 +93,51 @@ function createJsonOnce(root, segments, value) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
function updateJsonAtomically(root, segments, update) {
|
|
97
|
+
const target = path.resolve(root, ...segments);
|
|
98
|
+
if (!isInside(root, target)) return false;
|
|
99
|
+
let handle;
|
|
100
|
+
let temp = '';
|
|
101
|
+
try {
|
|
102
|
+
const stat = fs.lstatSync(target);
|
|
103
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.size > MAX_FILE_BYTES) return false;
|
|
104
|
+
const original = fs.readFileSync(target, 'utf8');
|
|
105
|
+
const current = JSON.parse(original);
|
|
106
|
+
if (!current || typeof current !== 'object' || Array.isArray(current)) return false;
|
|
107
|
+
const next = update(current);
|
|
108
|
+
if (!next || typeof next !== 'object' || Array.isArray(next)) return false;
|
|
109
|
+
const serialized = `${JSON.stringify(next, null, 2)}\n`;
|
|
110
|
+
if (Buffer.byteLength(serialized, 'utf8') > MAX_FILE_BYTES) return false;
|
|
111
|
+
|
|
112
|
+
const parent = path.dirname(target);
|
|
113
|
+
const realParent = fs.realpathSync(parent);
|
|
114
|
+
if (!isInside(root, realParent)) return false;
|
|
115
|
+
temp = path.join(parent, `.${path.basename(target)}.${process.pid}.${Date.now()}.tmp`);
|
|
116
|
+
handle = fs.openSync(temp, 'wx', 0o600);
|
|
117
|
+
fs.writeFileSync(handle, serialized, 'utf8');
|
|
118
|
+
fs.fsyncSync(handle);
|
|
119
|
+
fs.closeSync(handle);
|
|
120
|
+
handle = undefined;
|
|
121
|
+
|
|
122
|
+
const currentStat = fs.lstatSync(target);
|
|
123
|
+
if (!currentStat.isFile() || currentStat.isSymbolicLink() || fs.readFileSync(target, 'utf8') !== original) return false;
|
|
124
|
+
fs.renameSync(temp, target);
|
|
125
|
+
temp = '';
|
|
126
|
+
return true;
|
|
127
|
+
} catch {
|
|
128
|
+
return false;
|
|
129
|
+
} finally {
|
|
130
|
+
if (handle !== undefined) fs.closeSync(handle);
|
|
131
|
+
if (temp) {
|
|
132
|
+
try { fs.rmSync(temp, { force: true }); } catch {}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function isExplicitTelegramBot(meta) {
|
|
138
|
+
return meta?.is_bot === true || String(meta?.is_bot ?? '').toLowerCase() === 'true';
|
|
139
|
+
}
|
|
140
|
+
|
|
96
141
|
function cleanText(value, maxChars = 240) {
|
|
97
142
|
if (typeof value !== 'string') return '';
|
|
98
143
|
return value.replace(/[\u0000-\u001f\u007f]+/gu, ' ').replace(/\s+/gu, ' ').trim().slice(0, maxChars);
|
|
@@ -485,19 +530,31 @@ function recordChannelIdentity(envelope, env = process.env) {
|
|
|
485
530
|
const firstSeenAt = trustedTimestamp(meta.ts);
|
|
486
531
|
const receivedAt = trustedTimestamp(meta.received_at) || firstSeenAt;
|
|
487
532
|
const created = [];
|
|
488
|
-
|
|
533
|
+
const updated = [];
|
|
534
|
+
const actorSegments = ['actors', `${actorId}.json`];
|
|
535
|
+
const actorCreated = createJsonOnce(root, actorSegments, {
|
|
489
536
|
version: 1,
|
|
490
537
|
actor_id: actorId,
|
|
491
538
|
provider: 'telegram',
|
|
492
539
|
provider_subject_id: subjectId,
|
|
493
540
|
display_name: displayName,
|
|
494
|
-
kind:
|
|
541
|
+
kind: isExplicitTelegramBot(meta) ? 'agent' : 'person',
|
|
495
542
|
role: '',
|
|
496
543
|
responsibilities: [],
|
|
497
544
|
traits: [],
|
|
498
545
|
aliases: [],
|
|
499
546
|
...(firstSeenAt ? { first_seen_at: firstSeenAt } : {}),
|
|
500
|
-
})
|
|
547
|
+
});
|
|
548
|
+
if (actorCreated) created.push('actor');
|
|
549
|
+
else if (isExplicitTelegramBot(meta) && updateJsonAtomically(root, actorSegments, (actor) => (
|
|
550
|
+
actor.version === 1
|
|
551
|
+
&& actor.actor_id === actorId
|
|
552
|
+
&& actor.provider === 'telegram'
|
|
553
|
+
&& actor.provider_subject_id === subjectId
|
|
554
|
+
&& actor.kind === 'person'
|
|
555
|
+
? { ...actor, kind: 'agent' }
|
|
556
|
+
: undefined
|
|
557
|
+
))) updated.push('actor_kind');
|
|
501
558
|
if (createJsonOnce(root, ['agents', agentId, 'relationships', `${actorId}.json`], {
|
|
502
559
|
version: 1,
|
|
503
560
|
actor_id: actorId,
|
|
@@ -621,6 +678,7 @@ function recordChannelIdentity(envelope, env = process.env) {
|
|
|
621
678
|
actor_id: actorId,
|
|
622
679
|
...(groupId ? { group_id: groupId } : {}),
|
|
623
680
|
created,
|
|
681
|
+
updated,
|
|
624
682
|
...(learning ? { learning } : {}),
|
|
625
683
|
...(journal ? { journal } : {}),
|
|
626
684
|
model_context: modelContext,
|
package/blun.mjs
CHANGED
|
@@ -6,6 +6,7 @@ const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
|
6
6
|
const __dirname = __cjsShimDirname(__filename);
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import telegramConsoleStatusPolicy from "./bin/telegram-console-status-policy.cjs";
|
|
9
|
+
import cognitiveGoalAutostartPolicy from "./bin/cognitive-goal-autostart-policy.cjs";
|
|
9
10
|
import crypto$1, { createHash, randomBytes, randomInt, randomUUID, timingSafeEqual } from "node:crypto";
|
|
10
11
|
import * as fs$16 from "node:fs";
|
|
11
12
|
import Kt, { accessSync, appendFileSync, chmodSync, closeSync, constants, copyFileSync, createReadStream, createWriteStream, existsSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, promises, readFileSync, readSync, readdirSync, realpathSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
@@ -36,6 +37,7 @@ import * as win32Path from "node:path/win32";
|
|
|
36
37
|
import { createServer } from "node:http";
|
|
37
38
|
import { pipeline as pipeline$1 } from "node:stream/promises";
|
|
38
39
|
const { writeTelegramConsoleStatus } = telegramConsoleStatusPolicy;
|
|
40
|
+
const { goalAutostartDecision } = cognitiveGoalAutostartPolicy;
|
|
39
41
|
import { EventEmitter as EventEmitter$1 } from "node:events";
|
|
40
42
|
import { StringDecoder } from "node:string_decoder";
|
|
41
43
|
import co from "node:assert";
|
|
@@ -516666,8 +516668,32 @@ var BlunTUI = class {
|
|
|
516666
516668
|
async promptStartupResumeGoalIfNeeded() {
|
|
516667
516669
|
const session = this.session;
|
|
516668
516670
|
const goal = this.state.appState.goal;
|
|
516669
|
-
if (session === void 0 || goal === null || goal === void 0 ||
|
|
516671
|
+
if (session === void 0 || goal === null || goal === void 0 || this.startupGoalPromptedSessionId === session.id) return;
|
|
516670
516672
|
const sessionId = session.id;
|
|
516673
|
+
const autostart = goalAutostartDecision({
|
|
516674
|
+
goal,
|
|
516675
|
+
permissionMode: this.state.appState.permissionMode
|
|
516676
|
+
});
|
|
516677
|
+
if (autostart.kind === "start") {
|
|
516678
|
+
this.startupGoalPromptedSessionId = sessionId;
|
|
516679
|
+
this.beginSessionRequest();
|
|
516680
|
+
this.setAppState({
|
|
516681
|
+
model: BLUN_KING_MODEL_ALIAS,
|
|
516682
|
+
modelFallbackAllowed: false
|
|
516683
|
+
});
|
|
516684
|
+
try {
|
|
516685
|
+
const result = await session.promptAccepted(GOAL_CONTINUATION_PROMPT);
|
|
516686
|
+
if (!result.accepted && this.session?.id === sessionId) {
|
|
516687
|
+
this.setAppState({ streamingPhase: "idle" });
|
|
516688
|
+
this.resetLivePane();
|
|
516689
|
+
this.track("goal_autostart", { outcome: "not_accepted" });
|
|
516690
|
+
}
|
|
516691
|
+
} catch (error) {
|
|
516692
|
+
if (this.session?.id === sessionId) this.failSessionRequest(uiText("blunTui.session.sendFailed", { error: formatErrorMessage$2(error) }));
|
|
516693
|
+
}
|
|
516694
|
+
return;
|
|
516695
|
+
}
|
|
516696
|
+
if (goal.status !== "paused" && goal.status !== "blocked") return;
|
|
516671
516697
|
this.startupGoalPromptedSessionId = sessionId;
|
|
516672
516698
|
const choice = await promptStartupResumeGoal(this, goal.objective, startupResumeGoalPromptCopy());
|
|
516673
516699
|
if (this.aborted || this.session?.id !== sessionId) return;
|
package/package.json
CHANGED
|
@@ -4702,6 +4702,7 @@ async function handleInbound(event) {
|
|
|
4702
4702
|
...msgId !== void 0 ? { message_id: String(msgId) } : {},
|
|
4703
4703
|
addressed: String(addressed),
|
|
4704
4704
|
user: ctx.from?.username ?? String(ctx.from?.id),
|
|
4705
|
+
is_bot: String(ctx.from?.is_bot === true),
|
|
4705
4706
|
user_id: String(ctx.from?.id),
|
|
4706
4707
|
ts: (/* @__PURE__ */ new Date((ctx.date ?? 0) * 1e3)).toISOString(),
|
|
4707
4708
|
...imagePath !== void 0 ? { image_path: imagePath } : {},
|