blun-king-cli 9.1.75 → 9.1.76
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 +10 -0
- package/README.md +9 -0
- package/bin/pending-media-policy.cjs +43 -0
- package/blun.mjs +43 -20
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
|
@@ -43,6 +43,11 @@ einen aktiven Zug ab, ohne den geschriebenen Entwurf zu löschen. Das gilt auch
|
|
|
43
43
|
bei Autovervollständigung, Geistervorschlägen, Bash-Eingabe und einer offenen
|
|
44
44
|
Mehrzeileneingabe.
|
|
45
45
|
|
|
46
|
+
Telegram-Nachrichten, die bei bereits aktivem Kernzug eintreffen, werden ohne
|
|
47
|
+
konkurrierenden Start zurückgewiesen und bleiben an der Spitze der
|
|
48
|
+
FIFO-Warteschlange. Für diesen normalen Wartestatus erscheint kein
|
|
49
|
+
`turn.agent_busy`-Fehler.
|
|
50
|
+
|
|
46
51
|
Zuverlässiger King-Start
|
|
47
52
|
-----------------------
|
|
48
53
|
Der Windows-Hilfsprozess für private Pfade übernimmt TEMP und TMP aus der
|
|
@@ -175,6 +180,11 @@ Marmor“ oder „Animiere das letzte Bild als ruhige Kamerafahrt von sechs Seku
|
|
|
175
180
|
genügt. King wählt den passenden Medienweg und kann das asynchrone Ergebnis mit
|
|
176
181
|
GetMedia abrufen.
|
|
177
182
|
|
|
183
|
+
Ein angenommener Medienauftrag bleibt über Verdichtungen und schnelle
|
|
184
|
+
Folgeturns hinweg gespeichert. Solange er offen ist, bleibt `GetMedia`
|
|
185
|
+
verfügbar; King prüft den tatsächlichen Status, statt fälschlich zu behaupten,
|
|
186
|
+
die Medienerzeugung sei nicht verfügbar.
|
|
187
|
+
|
|
178
188
|
Angehängte Bilder werden weiterhin mit ReadMediaFile gelesen. Bild-, Video- und
|
|
179
189
|
Spracherzeugung laufen asynchron, sodass die Konsole während der Verarbeitung
|
|
180
190
|
nutzbar bleibt. GenerateVideo kann außerdem einen abgeschlossenen Bildauftrag
|
package/README.md
CHANGED
|
@@ -62,6 +62,10 @@ blun tools enable context7
|
|
|
62
62
|
Telegram-Nachrichten werden in Eingangsreihenfolge verarbeitet. Trifft eine
|
|
63
63
|
Nachricht im Leerlauf ein, startet die Warteschlange selbstständig; während
|
|
64
64
|
eines Werkzeuglaufs wird sie am nächsten geschützten Übergabepunkt eingefügt.
|
|
65
|
+
Telegram-Nachrichten, die bei bereits aktivem Kernzug eintreffen, werden ohne
|
|
66
|
+
konkurrierenden Start zurückgewiesen und bleiben an der Spitze der
|
|
67
|
+
FIFO-Warteschlange. Für diesen normalen Wartestatus erscheint kein
|
|
68
|
+
`turn.agent_busy`-Fehler.
|
|
65
69
|
`Strg+C` und `Esc` brechen einen aktiven Zug zuverlässig ab, ohne den bereits
|
|
66
70
|
geschriebenen Entwurf zu löschen. Das gilt auch bei Autovervollständigung,
|
|
67
71
|
Geistervorschlägen, Bash-Eingabe und einer noch offenen Mehrzeileneingabe.
|
|
@@ -203,6 +207,11 @@ Marmor“ oder „Animiere das letzte Bild als ruhige Kamerafahrt von sechs Seku
|
|
|
203
207
|
genügt. King wählt den passenden Medienweg und kann das asynchrone Ergebnis mit
|
|
204
208
|
`GetMedia` abrufen.
|
|
205
209
|
|
|
210
|
+
Ein angenommener Medienauftrag bleibt über Verdichtungen und schnelle
|
|
211
|
+
Folgeturns hinweg gespeichert. Solange er offen ist, bleibt `GetMedia`
|
|
212
|
+
verfügbar; King prüft den tatsächlichen Status, statt fälschlich zu behaupten,
|
|
213
|
+
die Medienerzeugung sei nicht verfügbar.
|
|
214
|
+
|
|
206
215
|
Angehängte Bilder werden weiterhin mit `ReadMediaFile` gelesen. Bild-, Video-
|
|
207
216
|
und Spracherzeugung laufen asynchron, sodass die Konsole während der Verarbeitung
|
|
208
217
|
nutzbar bleibt. `GenerateVideo` kann außerdem einen abgeschlossenen Bildauftrag
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const TERMINAL_STATUSES = new Set([
|
|
4
|
+
'blocked',
|
|
5
|
+
'cancelled',
|
|
6
|
+
'canceled',
|
|
7
|
+
'complete',
|
|
8
|
+
'completed',
|
|
9
|
+
'expired',
|
|
10
|
+
'failed',
|
|
11
|
+
'succeeded',
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
function validMediaId(value) {
|
|
15
|
+
return typeof value === 'string' && value.length > 0 && value.length <= 200
|
|
16
|
+
&& /^[A-Za-z0-9_-]+$/.test(value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function terminalStatus(value) {
|
|
20
|
+
return typeof value === 'string' && TERMINAL_STATUSES.has(value.trim().toLowerCase());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createPendingMediaTracker() {
|
|
24
|
+
const pending = new Set();
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
observeSubmission(job) {
|
|
28
|
+
if (!validMediaId(job?.id)) return;
|
|
29
|
+
if (terminalStatus(job?.status)) pending.delete(job.id);
|
|
30
|
+
else pending.add(job.id);
|
|
31
|
+
},
|
|
32
|
+
observeLookup(result) {
|
|
33
|
+
if (!validMediaId(result?.id)) return;
|
|
34
|
+
if (result.kind !== 'status' || terminalStatus(result.status)) pending.delete(result.id);
|
|
35
|
+
else pending.add(result.id);
|
|
36
|
+
},
|
|
37
|
+
ids() {
|
|
38
|
+
return [...pending];
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
module.exports = { createPendingMediaTracker };
|
package/blun.mjs
CHANGED
|
@@ -259942,9 +259942,14 @@ function blunToolsForOrigin(tools, origin) {
|
|
|
259942
259942
|
if (origin.kind !== "system_trigger" && origin.kind !== "injection") return tools;
|
|
259943
259943
|
return tools.filter((tool) => !BLUN_TELEGRAM_OUTBOUND_TOOL_RE.test(tool.name));
|
|
259944
259944
|
}
|
|
259945
|
-
function
|
|
259946
|
-
if (
|
|
259947
|
-
return
|
|
259945
|
+
function blunPendingMediaSystemPrompt(systemPrompt, pendingMediaJobIds) {
|
|
259946
|
+
if (pendingMediaJobIds.length === 0) return systemPrompt;
|
|
259947
|
+
return `${systemPrompt}\n\n## Pending BLUN media\n\nThe following media jobs were already accepted and are still pending: ${pendingMediaJobIds.join(", ")}. Call GetMedia exactly once for each listed id before replying. If a job is still processing, report that status truthfully and wait for a later turn; do not claim that media tools are unavailable.`;
|
|
259948
|
+
}
|
|
259949
|
+
function blunFastConversationTools(tools, input, pendingMediaJobIds = []) {
|
|
259950
|
+
const telegramTurn = BLUN_TELEGRAM_CHANNEL_RE.test(blunExtractText(input));
|
|
259951
|
+
const mediaPending = pendingMediaJobIds.length > 0;
|
|
259952
|
+
return tools.filter((tool) => telegramTurn && BLUN_TELEGRAM_OUTBOUND_TOOL_RE.test(tool.name) || mediaPending && tool.name === "GetMedia");
|
|
259948
259953
|
}
|
|
259949
259954
|
/**
|
|
259950
259955
|
* Keep frequently used native tools resident and expose every other tool by
|
|
@@ -260281,11 +260286,15 @@ var init_turn = __esmMin((() => {
|
|
|
260281
260286
|
input,
|
|
260282
260287
|
origin
|
|
260283
260288
|
});
|
|
260284
|
-
|
|
260285
|
-
|
|
260289
|
+
if (this.activeTurn !== null) return {
|
|
260290
|
+
accepted: false,
|
|
260291
|
+
buffered: false,
|
|
260292
|
+
turnId: null
|
|
260293
|
+
};
|
|
260294
|
+
const buffered = this.agent.fullCompaction.isCompacting;
|
|
260286
260295
|
const turnId = this.launch(input, origin);
|
|
260287
260296
|
return {
|
|
260288
|
-
accepted:
|
|
260297
|
+
accepted: true,
|
|
260289
260298
|
buffered,
|
|
260290
260299
|
turnId
|
|
260291
260300
|
};
|
|
@@ -260773,7 +260782,9 @@ var init_turn = __esmMin((() => {
|
|
|
260773
260782
|
const turnHasAttachment = blunTurnHasAttachment(input);
|
|
260774
260783
|
const turnThinkingEffort = turnHasAttachment ? void 0 : selectThinkingEffortForTurn(blunExtractText(blunThinkingIntentInput(input)), origin.kind);
|
|
260775
260784
|
const fastConversation = turnThinkingEffort === "off" || turnThinkingEffort === "low";
|
|
260776
|
-
const
|
|
260785
|
+
const pendingMediaJobIds = this.agent.toolServices?.media?.pendingMediaJobIds?.() ?? [];
|
|
260786
|
+
const turnSystemPrompt = pendingMediaJobIds.length > 0 ? blunPendingMediaSystemPrompt(fastConversation ? this.agent.fastConversationSystemPrompt : this.agent.effectiveSystemPrompt, pendingMediaJobIds) : fastConversation ? this.agent.fastConversationSystemPrompt : void 0;
|
|
260787
|
+
const turnLLM = this.agent.llmForTurn(turnThinkingEffort, turnSystemPrompt);
|
|
260777
260788
|
let previousStepToolOutcome = "initial";
|
|
260778
260789
|
let currentStepHadTool = false;
|
|
260779
260790
|
let currentStepHadFailure = false;
|
|
@@ -260785,7 +260796,7 @@ var init_turn = __esmMin((() => {
|
|
|
260785
260796
|
try {
|
|
260786
260797
|
const eligibleTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools), origin);
|
|
260787
260798
|
const toolSelection = fastConversation ? {
|
|
260788
|
-
tools: [...blunFastConversationTools(eligibleTools, input)],
|
|
260799
|
+
tools: [...blunFastConversationTools(eligibleTools, input, pendingMediaJobIds)],
|
|
260789
260800
|
deferredToolCount: 0
|
|
260790
260801
|
} : turnNeedsTools ? blunSelectTurnTools(eligibleTools, this.agent.config.modelCapabilities?.max_context_tokens, this.loadedToolNames) : {
|
|
260791
260802
|
tools: [],
|
|
@@ -260849,8 +260860,9 @@ var init_turn = __esmMin((() => {
|
|
|
260849
260860
|
if (steerEfforts.some((effort) => effort === void 0)) return;
|
|
260850
260861
|
const steerInput = pendingSteers.flatMap((steer) => [...steer.input]);
|
|
260851
260862
|
const steerThinkingEffort = "low";
|
|
260852
|
-
const
|
|
260853
|
-
const
|
|
260863
|
+
const steerPendingMediaJobIds = this.agent.toolServices?.media?.pendingMediaJobIds?.() ?? [];
|
|
260864
|
+
const steerLLM = this.agent.llmForTurn(steerThinkingEffort, blunPendingMediaSystemPrompt(this.agent.fastConversationSystemPrompt, steerPendingMediaJobIds));
|
|
260865
|
+
const steerTools = [...blunFastConversationTools(eligibleTools, steerInput, steerPendingMediaJobIds)];
|
|
260854
260866
|
const steerHistory = () => blunFastConversationHistory(this.agent.context.history);
|
|
260855
260867
|
const buildSteerMessages = () => this.agent.context.project(steerHistory(), { dropOrphanResults: true });
|
|
260856
260868
|
const buildSteerMessagesStrict = () => this.agent.context.project(steerHistory(), {
|
|
@@ -311242,8 +311254,9 @@ async function assertSuccess(response, operation) {
|
|
|
311242
311254
|
} catch {}
|
|
311243
311255
|
throw new Error(`${operation} failed: HTTP ${String(response.status)}${detail ? `: ${detail}` : ""}`);
|
|
311244
311256
|
}
|
|
311245
|
-
var BlunMediaService;
|
|
311257
|
+
var createPendingMediaTracker, BlunMediaService;
|
|
311246
311258
|
var init_blun_media = __esmMin((() => {
|
|
311259
|
+
({ createPendingMediaTracker } = createRequire(import.meta.url)("./bin/pending-media-policy.cjs"));
|
|
311247
311260
|
BlunMediaService = class {
|
|
311248
311261
|
tokenProvider;
|
|
311249
311262
|
apiKey;
|
|
@@ -311251,6 +311264,7 @@ var init_blun_media = __esmMin((() => {
|
|
|
311251
311264
|
defaultHeaders;
|
|
311252
311265
|
customHeaders;
|
|
311253
311266
|
fetchImpl;
|
|
311267
|
+
pendingMedia = createPendingMediaTracker();
|
|
311254
311268
|
constructor(options) {
|
|
311255
311269
|
this.tokenProvider = options.tokenProvider;
|
|
311256
311270
|
this.apiKey = options.apiKey;
|
|
@@ -311303,28 +311317,28 @@ var init_blun_media = __esmMin((() => {
|
|
|
311303
311317
|
}
|
|
311304
311318
|
async getMedia(id, options) {
|
|
311305
311319
|
const response = await this.request(`/media/${encodeURIComponent(id)}`, { method: "GET" }, options);
|
|
311306
|
-
if (response.status === 409) return parseBlockedStatus(response, id);
|
|
311307
|
-
if (response.status === 410) return {
|
|
311320
|
+
if (response.status === 409) return this.trackMediaLookup(parseBlockedStatus(response, id));
|
|
311321
|
+
if (response.status === 410) return this.trackMediaLookup({
|
|
311308
311322
|
kind: "status",
|
|
311309
311323
|
id,
|
|
311310
311324
|
status: "expired"
|
|
311311
|
-
};
|
|
311325
|
+
});
|
|
311312
311326
|
await assertSuccess(response, "Media lookup");
|
|
311313
311327
|
const mimeType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() ?? "";
|
|
311314
|
-
if (mimeType === "application/json" || mimeType.endsWith("+json")) return parseStatus(await response.json(), id);
|
|
311315
|
-
if (mimeType === "text/plain") return {
|
|
311328
|
+
if (mimeType === "application/json" || mimeType.endsWith("+json")) return this.trackMediaLookup(parseStatus(await response.json(), id));
|
|
311329
|
+
if (mimeType === "text/plain") return this.trackMediaLookup({
|
|
311316
311330
|
kind: "text",
|
|
311317
311331
|
id,
|
|
311318
311332
|
mimeType,
|
|
311319
311333
|
text: await response.text()
|
|
311320
|
-
};
|
|
311334
|
+
});
|
|
311321
311335
|
if (!mimeType.startsWith("image/") && !mimeType.startsWith("audio/") && !mimeType.startsWith("video/")) throw new Error(`Media lookup returned unsupported content type ${mimeType || "(missing)"}`);
|
|
311322
|
-
return {
|
|
311336
|
+
return this.trackMediaLookup({
|
|
311323
311337
|
kind: "file",
|
|
311324
311338
|
id,
|
|
311325
311339
|
mimeType,
|
|
311326
311340
|
data: new Uint8Array(await response.arrayBuffer())
|
|
311327
|
-
};
|
|
311341
|
+
});
|
|
311328
311342
|
}
|
|
311329
311343
|
async submit(path, body, options) {
|
|
311330
311344
|
const response = await this.request(path, {
|
|
@@ -311333,7 +311347,16 @@ var init_blun_media = __esmMin((() => {
|
|
|
311333
311347
|
}, options);
|
|
311334
311348
|
if (response.status === 409) throw await blockedSubmissionError(response);
|
|
311335
311349
|
await assertSuccess(response, "Media request");
|
|
311336
|
-
|
|
311350
|
+
const job = parseJob(await response.json());
|
|
311351
|
+
this.pendingMedia.observeSubmission(job);
|
|
311352
|
+
return job;
|
|
311353
|
+
}
|
|
311354
|
+
trackMediaLookup(result) {
|
|
311355
|
+
this.pendingMedia.observeLookup(result);
|
|
311356
|
+
return result;
|
|
311357
|
+
}
|
|
311358
|
+
pendingMediaJobIds() {
|
|
311359
|
+
return this.pendingMedia.ids();
|
|
311337
311360
|
}
|
|
311338
311361
|
async request(path, init, options) {
|
|
311339
311362
|
const firstToken = await this.resolveToken(false);
|