blun-king-cli 9.1.32 → 9.1.34
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/README.md +1 -1
- package/blun.mjs +1026 -514
- package/package.json +1 -1
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:ec5eb56eb8addc29b2ddab22ca4987f2156e16b88a8f468ce3248d312afa717f
|
|
3
3
|
import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
|
|
4
4
|
import { dirname as __cjsShimDirname } from 'node:path';
|
|
5
5
|
const __filename = __cjsShimFileURLToPath(import.meta.url);
|
|
@@ -569,6 +569,7 @@ var init_codes = __esmMin((() => {
|
|
|
569
569
|
GOAL_NOT_RESUMABLE: "goal.not_resumable",
|
|
570
570
|
MODEL_NOT_CONFIGURED: "model.not_configured",
|
|
571
571
|
MODEL_CONFIG_INVALID: "model.config_invalid",
|
|
572
|
+
MODEL_EMPTY_RESPONSE: "model.empty_response",
|
|
572
573
|
AUTH_LOGIN_REQUIRED: "auth.login_required",
|
|
573
574
|
CONTEXT_OVERFLOW: "context.overflow",
|
|
574
575
|
LOOP_ALREADY_EXISTS: "loop.already_exists",
|
|
@@ -613,6 +614,12 @@ var init_codes = __esmMin((() => {
|
|
|
613
614
|
public: true,
|
|
614
615
|
action: "Check config.toml and provider/model settings."
|
|
615
616
|
},
|
|
617
|
+
"model.empty_response": {
|
|
618
|
+
title: "Model returned no content",
|
|
619
|
+
retryable: true,
|
|
620
|
+
public: true,
|
|
621
|
+
action: "Send the message again."
|
|
622
|
+
},
|
|
616
623
|
"session.not_found": {
|
|
617
624
|
title: "Session not found",
|
|
618
625
|
retryable: false,
|
|
@@ -1663,14 +1670,35 @@ var init_errors$10 = __esmMin((() => {
|
|
|
1663
1670
|
this.retryAfterMs = typeof metadata.retryAfterMs === "number" && Number.isFinite(metadata.retryAfterMs) && metadata.retryAfterMs >= 0 ? metadata.retryAfterMs : null;
|
|
1664
1671
|
}
|
|
1665
1672
|
};
|
|
1666
|
-
APIEmptyResponseError = class extends ChatProviderError {
|
|
1673
|
+
APIEmptyResponseError = class APIEmptyResponseError extends ChatProviderError {
|
|
1667
1674
|
finishReason;
|
|
1668
1675
|
rawFinishReason;
|
|
1676
|
+
emptyResponseKind;
|
|
1677
|
+
completionTokens;
|
|
1678
|
+
reasoningLength;
|
|
1679
|
+
maxCompletionTokens;
|
|
1680
|
+
attempts;
|
|
1669
1681
|
constructor(message, options = {}) {
|
|
1670
1682
|
super(message);
|
|
1671
1683
|
this.name = "APIEmptyResponseError";
|
|
1672
1684
|
this.finishReason = options.finishReason ?? null;
|
|
1673
1685
|
this.rawFinishReason = options.rawFinishReason ?? null;
|
|
1686
|
+
this.emptyResponseKind = options.emptyResponseKind ?? "other";
|
|
1687
|
+
this.completionTokens = options.completionTokens ?? null;
|
|
1688
|
+
this.reasoningLength = options.reasoningLength ?? 0;
|
|
1689
|
+
this.maxCompletionTokens = options.maxCompletionTokens ?? null;
|
|
1690
|
+
this.attempts = options.attempts ?? 1;
|
|
1691
|
+
}
|
|
1692
|
+
withMetadata(options) {
|
|
1693
|
+
return new APIEmptyResponseError(this.message, {
|
|
1694
|
+
finishReason: this.finishReason,
|
|
1695
|
+
rawFinishReason: this.rawFinishReason,
|
|
1696
|
+
emptyResponseKind: this.emptyResponseKind,
|
|
1697
|
+
completionTokens: this.completionTokens,
|
|
1698
|
+
reasoningLength: this.reasoningLength,
|
|
1699
|
+
maxCompletionTokens: options.maxCompletionTokens ?? this.maxCompletionTokens,
|
|
1700
|
+
attempts: options.attempts ?? this.attempts
|
|
1701
|
+
});
|
|
1674
1702
|
}
|
|
1675
1703
|
};
|
|
1676
1704
|
CompactionStallError$1 = class extends ChatProviderError {
|
|
@@ -2996,14 +3024,19 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
|
|
|
2996
3024
|
if (pendingPart !== null) flushPart(message, pendingPart, toolCallIndexMap);
|
|
2997
3025
|
if (message.content.length === 0 && message.toolCalls.length === 0) throw new APIEmptyResponseError("The API returned an empty response (no content, no tool calls)." + formatFinishReasonHint(stream) + ` Provider: ${provider.name}, model: ${provider.modelName}`, {
|
|
2998
3026
|
finishReason: stream.finishReason,
|
|
2999
|
-
rawFinishReason: stream.rawFinishReason
|
|
3027
|
+
rawFinishReason: stream.rawFinishReason,
|
|
3028
|
+
emptyResponseKind: classifyEmptyResponse(stream),
|
|
3029
|
+
completionTokens: stream.usage?.output ?? null
|
|
3000
3030
|
});
|
|
3001
3031
|
const hasThink = message.content.some((p) => p.type === "think");
|
|
3002
3032
|
const hasText = message.content.some((p) => p.type === "text" && p.text.trim().length > 0);
|
|
3003
3033
|
const hasToolCalls = message.toolCalls.length > 0;
|
|
3004
3034
|
if (hasThink && !hasText && !hasToolCalls) throw new APIEmptyResponseError("The API returned a response containing only thinking content without any text or tool calls. This usually indicates the stream was interrupted or the output token budget was exhausted during reasoning." + formatFinishReasonHint(stream) + ` Provider: ${provider.name}, model: ${provider.modelName}`, {
|
|
3005
3035
|
finishReason: stream.finishReason,
|
|
3006
|
-
rawFinishReason: stream.rawFinishReason
|
|
3036
|
+
rawFinishReason: stream.rawFinishReason,
|
|
3037
|
+
emptyResponseKind: classifyEmptyResponse(stream),
|
|
3038
|
+
completionTokens: stream.usage?.output ?? null,
|
|
3039
|
+
reasoningLength: message.content.reduce((total, part) => total + (part.type === "think" ? part.think.length : 0), 0)
|
|
3007
3040
|
});
|
|
3008
3041
|
if (callbacks?.onToolCall !== void 0) for (const toolCall of message.toolCalls) {
|
|
3009
3042
|
await throwIfAborted$2(signal, stream);
|
|
@@ -3022,6 +3055,14 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
|
|
|
3022
3055
|
signal?.removeEventListener("abort", abortListener);
|
|
3023
3056
|
}
|
|
3024
3057
|
}
|
|
3058
|
+
function classifyEmptyResponse(stream) {
|
|
3059
|
+
if (stream.finishReason === "truncated") return "length";
|
|
3060
|
+
if (stream.finishReason === "completed") return "stop";
|
|
3061
|
+
const raw = stream.rawFinishReason?.toLowerCase() ?? "";
|
|
3062
|
+
if (raw === "length" || raw.includes("max_token") || raw.includes("max_output")) return "length";
|
|
3063
|
+
if (raw === "stop" || raw === "completed") return "stop";
|
|
3064
|
+
return "other";
|
|
3065
|
+
}
|
|
3025
3066
|
function throwAbortError() {
|
|
3026
3067
|
throw new DOMException("The operation was aborted.", "AbortError");
|
|
3027
3068
|
}
|
|
@@ -3255,16 +3296,24 @@ function toBlunErrorPayload(error) {
|
|
|
3255
3296
|
name: error.name,
|
|
3256
3297
|
retryable: BLUN_ERROR_INFO[ErrorCodes.PROVIDER_CONNECTION_ERROR].retryable
|
|
3257
3298
|
};
|
|
3258
|
-
if (error instanceof APIEmptyResponseError)
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3299
|
+
if (error instanceof APIEmptyResponseError) {
|
|
3300
|
+
const isRepeatedStop = error.emptyResponseKind === "stop" && error.attempts >= 2;
|
|
3301
|
+
const code = isRepeatedStop ? ErrorCodes.MODEL_EMPTY_RESPONSE : ErrorCodes.PROVIDER_API_ERROR;
|
|
3302
|
+
return {
|
|
3303
|
+
code,
|
|
3304
|
+
message: isRepeatedStop ? "King ended twice without producing content. Please send the message again." : error.message,
|
|
3305
|
+
name: error.name,
|
|
3306
|
+
details: {
|
|
3307
|
+
finishReason: error.finishReason,
|
|
3308
|
+
rawFinishReason: error.rawFinishReason,
|
|
3309
|
+
emptyResponseKind: error.emptyResponseKind,
|
|
3310
|
+
attempts: error.attempts,
|
|
3311
|
+
completionTokens: error.completionTokens,
|
|
3312
|
+
maxCompletionTokens: error.maxCompletionTokens
|
|
3313
|
+
},
|
|
3314
|
+
retryable: BLUN_ERROR_INFO[code].retryable
|
|
3315
|
+
};
|
|
3316
|
+
}
|
|
3268
3317
|
if (error instanceof ChatProviderError) return {
|
|
3269
3318
|
code: ErrorCodes.PROVIDER_API_ERROR,
|
|
3270
3319
|
message: error.message,
|
|
@@ -9923,6 +9972,7 @@ var init_schema = __esmMin((() => {
|
|
|
9923
9972
|
]);
|
|
9924
9973
|
ActionStyleSchema = _enum([
|
|
9925
9974
|
"default",
|
|
9975
|
+
"concise",
|
|
9926
9976
|
"proactive",
|
|
9927
9977
|
"explanatory",
|
|
9928
9978
|
"learning"
|
|
@@ -30052,9 +30102,38 @@ async function chatWithRetry(input) {
|
|
|
30052
30102
|
}
|
|
30053
30103
|
}
|
|
30054
30104
|
const delays = retryBackoffDelays(maxAttempts);
|
|
30105
|
+
let completionBudgetRetry;
|
|
30106
|
+
let emptyRetryStarted = false;
|
|
30055
30107
|
for (let attempt = 1;; attempt += 1) try {
|
|
30056
|
-
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts));
|
|
30108
|
+
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry));
|
|
30057
30109
|
} catch (error) {
|
|
30110
|
+
if (error instanceof APIEmptyResponseError && (emptyRetryStarted || error.emptyResponseKind === "length" || error.emptyResponseKind === "stop")) {
|
|
30111
|
+
const emptyAttemptLimit = Math.min(maxAttempts, 2);
|
|
30112
|
+
logEmptyResponse(input, error, attempt);
|
|
30113
|
+
if (attempt >= emptyAttemptLimit) {
|
|
30114
|
+
const terminal = error.withMetadata({ attempts: attempt });
|
|
30115
|
+
logRequestFailure(input, terminal, attempt, emptyAttemptLimit);
|
|
30116
|
+
throw terminal;
|
|
30117
|
+
}
|
|
30118
|
+
completionBudgetRetry = error.emptyResponseKind === "length" ? {
|
|
30119
|
+
minimumCompletionTokens: 1024,
|
|
30120
|
+
multiplier: 2
|
|
30121
|
+
} : void 0;
|
|
30122
|
+
emptyRetryStarted = true;
|
|
30123
|
+
input.params.signal.throwIfAborted();
|
|
30124
|
+
input.dispatchEvent({
|
|
30125
|
+
type: "step.retrying",
|
|
30126
|
+
turnId: input.turnId,
|
|
30127
|
+
step: input.currentStep,
|
|
30128
|
+
stepUuid: input.stepUuid,
|
|
30129
|
+
failedAttempt: attempt,
|
|
30130
|
+
nextAttempt: attempt + 1,
|
|
30131
|
+
maxAttempts: emptyAttemptLimit,
|
|
30132
|
+
delayMs: 0,
|
|
30133
|
+
...retryErrorFields(error)
|
|
30134
|
+
});
|
|
30135
|
+
continue;
|
|
30136
|
+
}
|
|
30058
30137
|
if (attempt >= maxAttempts || !input.llm.isRetryableError(error)) {
|
|
30059
30138
|
logRequestFailure(input, error, attempt, maxAttempts);
|
|
30060
30139
|
throw error;
|
|
@@ -30084,16 +30163,26 @@ function logRequestFailure(input, error, attempt, maxAttempts) {
|
|
|
30084
30163
|
...retryErrorFields(error)
|
|
30085
30164
|
});
|
|
30086
30165
|
}
|
|
30087
|
-
function paramsForAttempt(input, attempt, maxAttempts) {
|
|
30166
|
+
function paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry) {
|
|
30088
30167
|
const turnStep = `${input.turnId}.${String(input.currentStep)}`;
|
|
30089
30168
|
return {
|
|
30090
30169
|
...input.params,
|
|
30170
|
+
completionBudgetRetry,
|
|
30091
30171
|
requestLogFields: attempt === 1 ? { turnStep } : {
|
|
30092
30172
|
turnStep,
|
|
30093
30173
|
attempt: `${String(attempt)}/${String(maxAttempts)}`
|
|
30094
30174
|
}
|
|
30095
30175
|
};
|
|
30096
30176
|
}
|
|
30177
|
+
function logEmptyResponse(input, error, attempt) {
|
|
30178
|
+
input.log?.warn(`[leer] fall=${error.emptyResponseKind}`, {
|
|
30179
|
+
turnStep: `${input.turnId}.${String(input.currentStep)}`,
|
|
30180
|
+
attempt,
|
|
30181
|
+
budget: error.maxCompletionTokens,
|
|
30182
|
+
completion: error.completionTokens,
|
|
30183
|
+
reasoningLength: error.reasoningLength
|
|
30184
|
+
});
|
|
30185
|
+
}
|
|
30097
30186
|
function retryBackoffDelays(maxAttempts) {
|
|
30098
30187
|
return import_retry$1.timeouts({
|
|
30099
30188
|
retries: Math.max(maxAttempts - 1, 0),
|
|
@@ -30122,6 +30211,7 @@ function maybeStatusCode(error) {
|
|
|
30122
30211
|
var import_retry$1, RETRY_MIN_TIMEOUT_MS, RETRY_MAX_TIMEOUT_MS, RETRY_FACTOR;
|
|
30123
30212
|
var init_retry = __esmMin((() => {
|
|
30124
30213
|
init_dist$4();
|
|
30214
|
+
init_src$4();
|
|
30125
30215
|
import_retry$1 = /* @__PURE__ */ __toESM(require_retry$1(), 1);
|
|
30126
30216
|
init_abort();
|
|
30127
30217
|
init_errors$4();
|
|
@@ -30783,18 +30873,25 @@ function computeCompletionBudgetCap(args) {
|
|
|
30783
30873
|
* in `BlunChatProvider._clone()`.
|
|
30784
30874
|
*/
|
|
30785
30875
|
function applyCompletionBudget(args) {
|
|
30786
|
-
|
|
30787
|
-
|
|
30876
|
+
return applyCompletionBudgetWithDetails(args).provider;
|
|
30877
|
+
}
|
|
30878
|
+
function applyCompletionBudgetWithDetails(args) {
|
|
30879
|
+
if (args.budget === void 0) return { provider: args.provider };
|
|
30880
|
+
if (args.provider.withMaxCompletionTokens === void 0) return { provider: args.provider };
|
|
30788
30881
|
let cap = computeCompletionBudgetCap({
|
|
30789
30882
|
budget: args.budget,
|
|
30790
30883
|
capability: args.capability
|
|
30791
30884
|
});
|
|
30885
|
+
if (args.retry !== void 0) cap = Math.max(args.retry.minimumCompletionTokens, Math.ceil(cap * args.retry.multiplier));
|
|
30792
30886
|
const maxContextTokens = args.capability?.max_context_tokens;
|
|
30793
30887
|
if (args.usedContextTokens !== void 0 && maxContextTokens !== void 0 && maxContextTokens > 0) cap = Math.max(MIN_FLOOR, Math.min(cap, maxContextTokens - args.usedContextTokens));
|
|
30794
|
-
return
|
|
30795
|
-
|
|
30796
|
-
|
|
30797
|
-
|
|
30888
|
+
return {
|
|
30889
|
+
provider: args.provider.withMaxCompletionTokens(cap, {
|
|
30890
|
+
usedContextTokens: args.usedContextTokens,
|
|
30891
|
+
maxContextTokens
|
|
30892
|
+
}),
|
|
30893
|
+
maxCompletionTokens: cap
|
|
30894
|
+
};
|
|
30798
30895
|
}
|
|
30799
30896
|
var MIN_FLOOR, DEFAULT_UNKNOWN_CONTEXT_FALLBACK;
|
|
30800
30897
|
var init_completion_budget = __esmMin((() => {
|
|
@@ -74499,6 +74596,7 @@ var init_kosong_llm = __esmMin((() => {
|
|
|
74499
74596
|
requestLogFields: params.requestLogFields
|
|
74500
74597
|
};
|
|
74501
74598
|
let result;
|
|
74599
|
+
let completionBudget;
|
|
74502
74600
|
try {
|
|
74503
74601
|
const enrichedMessages = this.visionReader === void 0 ? params.messages : await enrichMessagesWithVision(params.messages, this.visionReader, params.signal, this.onVisionUsage);
|
|
74504
74602
|
const tools = [...params.tools];
|
|
@@ -74508,14 +74606,16 @@ var init_kosong_llm = __esmMin((() => {
|
|
|
74508
74606
|
const outgoingRequestTokens = estimateTokens$1(this.systemPrompt) + estimateTokensForTools(tools) + estimateTokensForMessages(outgoingMessages);
|
|
74509
74607
|
const reportedContextTokens = this.reportedContextTokens?.() ?? 0;
|
|
74510
74608
|
const usedContextTokens = Math.max(outgoingRequestTokens, reportedContextTokens);
|
|
74511
|
-
|
|
74609
|
+
completionBudget = applyCompletionBudgetWithDetails({
|
|
74512
74610
|
provider: this.provider,
|
|
74513
74611
|
budget: this.completionBudgetConfig,
|
|
74514
74612
|
capability: this.capability,
|
|
74515
|
-
usedContextTokens
|
|
74613
|
+
usedContextTokens,
|
|
74614
|
+
retry: params.completionBudgetRetry
|
|
74516
74615
|
});
|
|
74517
|
-
result = await this.generate(
|
|
74616
|
+
result = await this.generate(completionBudget.provider, this.systemPrompt, tools, outgoingMessages, callbacks, options);
|
|
74518
74617
|
} catch (error) {
|
|
74618
|
+
if (error instanceof APIEmptyResponseError) throw error.withMetadata({ maxCompletionTokens: completionBudget === void 0 ? null : completionBudget.maxCompletionTokens ?? null });
|
|
74519
74619
|
if (error instanceof APIPaymentRequiredError) {
|
|
74520
74620
|
const accountQuotaExhausted = error.statusCode === 429 && error.apiCode === "quota_exhausted";
|
|
74521
74621
|
throw new BlunError(ErrorCodes.PROVIDER_QUOTA_EXHAUSTED, accountQuotaExhausted ? "Das Kontingent ist aufgebraucht." : "Das Modell-Guthaben ist erschöpft. Bitte lade dein Konto beim Anbieter nach und versuche es erneut.", {
|
|
@@ -74630,8 +74730,8 @@ var init_compaction_instruction = __esmMin((() => {
|
|
|
74630
74730
|
var DEFAULT_COMPACTION_CONFIG, DefaultCompactionStrategy;
|
|
74631
74731
|
var init_strategy = __esmMin((() => {
|
|
74632
74732
|
DEFAULT_COMPACTION_CONFIG = {
|
|
74633
|
-
triggerRatio: .
|
|
74634
|
-
blockRatio: .
|
|
74733
|
+
triggerRatio: .9,
|
|
74734
|
+
blockRatio: .95,
|
|
74635
74735
|
reservedContextSize: 1e4,
|
|
74636
74736
|
maxCompactionPerTurn: Infinity,
|
|
74637
74737
|
maxOverflowCompactionAttempts: 3
|
|
@@ -74919,6 +75019,35 @@ function isModelFallbackStatus(error) {
|
|
|
74919
75019
|
function compactionTimingKey(provider) {
|
|
74920
75020
|
return `${provider.name}\u0000${provider.modelName}`;
|
|
74921
75021
|
}
|
|
75022
|
+
function estimateCompactionProgressPercent(initialInputTokens, currentInputTokens) {
|
|
75023
|
+
if (initialInputTokens <= 0) return 0;
|
|
75024
|
+
const reducedTokens = Math.max(0, initialInputTokens - currentInputTokens);
|
|
75025
|
+
return Math.min(99, Math.floor(reducedTokens / initialInputTokens * 100));
|
|
75026
|
+
}
|
|
75027
|
+
function selectHierarchicalCompactionChunk(history, targetRequestTokens, hardRequestLimit, build) {
|
|
75028
|
+
const safeEnds = [];
|
|
75029
|
+
for (let end = 1; end < history.length; end++) if (history[end]?.role !== "tool") safeEnds.push(end);
|
|
75030
|
+
if (safeEnds.length === 0) return void 0;
|
|
75031
|
+
const pickLargestWithin = (limit) => {
|
|
75032
|
+
let low = 0;
|
|
75033
|
+
let high = safeEnds.length - 1;
|
|
75034
|
+
let best;
|
|
75035
|
+
while (low <= high) {
|
|
75036
|
+
const middle = Math.floor((low + high) / 2);
|
|
75037
|
+
const end = safeEnds[middle];
|
|
75038
|
+
const request = build(history.slice(0, end));
|
|
75039
|
+
if (request.estimatedTokens < limit) {
|
|
75040
|
+
best = {
|
|
75041
|
+
end,
|
|
75042
|
+
...request
|
|
75043
|
+
};
|
|
75044
|
+
low = middle + 1;
|
|
75045
|
+
} else high = middle - 1;
|
|
75046
|
+
}
|
|
75047
|
+
return best;
|
|
75048
|
+
};
|
|
75049
|
+
return pickLargestWithin(targetRequestTokens) ?? pickLargestWithin(hardRequestLimit);
|
|
75050
|
+
}
|
|
74922
75051
|
function shrinkCompactionHistoryAfterOverflow(messages, attempt) {
|
|
74923
75052
|
if (messages.length <= 1) return messages.slice();
|
|
74924
75053
|
const ratio = COMPACTION_OVERFLOW_SHRINK_RATIOS[Math.min(attempt - 1, COMPACTION_OVERFLOW_SHRINK_RATIOS.length - 1)];
|
|
@@ -75002,7 +75131,7 @@ function extractCompactionSummary(response) {
|
|
|
75002
75131
|
if (summary.trim().length === 0) throw new APIEmptyResponseError("The compaction response did not contain a non-empty summary.");
|
|
75003
75132
|
return summary;
|
|
75004
75133
|
}
|
|
75005
|
-
var DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS, CompactionTruncatedError, CompactionStallError, COMPACTION_STALL_MEASUREMENT_MULTIPLIER, REBUILT_AFTER_COMPACTION_INJECTION_VARIANTS, FullCompaction, MAX_COMPACTION_OVERFLOW_SHRINK_ATTEMPTS, COMPACTION_OVERFLOW_SHRINK_RATIOS;
|
|
75134
|
+
var DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS, COMPACTION_SUMMARY_RESERVE_RATIO, MAX_HIERARCHICAL_COMPACTION_PASSES, HIERARCHICAL_COMPACTION_PREFIX, CompactionTruncatedError, CompactionStallError, COMPACTION_STALL_MEASUREMENT_MULTIPLIER, REBUILT_AFTER_COMPACTION_INJECTION_VARIANTS, FullCompaction, MAX_COMPACTION_OVERFLOW_SHRINK_ATTEMPTS, COMPACTION_OVERFLOW_SHRINK_RATIOS;
|
|
75006
75135
|
var init_full = __esmMin((() => {
|
|
75007
75136
|
init_errors$8();
|
|
75008
75137
|
init_src$4();
|
|
@@ -75018,6 +75147,9 @@ var init_full = __esmMin((() => {
|
|
|
75018
75147
|
init_strategy();
|
|
75019
75148
|
init_handoff();
|
|
75020
75149
|
DEFAULT_COMPACTION_MAX_COMPLETION_TOKENS = 128 * 1024;
|
|
75150
|
+
COMPACTION_SUMMARY_RESERVE_RATIO = .1;
|
|
75151
|
+
MAX_HIERARCHICAL_COMPACTION_PASSES = 64;
|
|
75152
|
+
HIERARCHICAL_COMPACTION_PREFIX = "This is a complete summary of an earlier chronological segment. Preserve it as source material when merging it with the following conversation:";
|
|
75021
75153
|
CompactionTruncatedError = class extends Error {
|
|
75022
75154
|
constructor() {
|
|
75023
75155
|
super("Compaction response was truncated before producing a complete summary.");
|
|
@@ -75067,7 +75199,7 @@ var init_full = __esmMin((() => {
|
|
|
75067
75199
|
...DEFAULT_COMPACTION_CONFIG,
|
|
75068
75200
|
reservedContextSize,
|
|
75069
75201
|
triggerRatio,
|
|
75070
|
-
blockRatio: triggerRatio
|
|
75202
|
+
blockRatio: Math.max(triggerRatio, DEFAULT_COMPACTION_CONFIG.blockRatio)
|
|
75071
75203
|
});
|
|
75072
75204
|
}
|
|
75073
75205
|
get isCompacting() {
|
|
@@ -75236,8 +75368,9 @@ var init_full = __esmMin((() => {
|
|
|
75236
75368
|
}
|
|
75237
75369
|
async compactionWorker(signal, data) {
|
|
75238
75370
|
try {
|
|
75239
|
-
const
|
|
75240
|
-
if (!
|
|
75371
|
+
const output = await this.compactionRound(signal, data);
|
|
75372
|
+
if (!output) return;
|
|
75373
|
+
const { result, stageCount } = output;
|
|
75241
75374
|
try {
|
|
75242
75375
|
await this.agent.refreshSystemPrompt();
|
|
75243
75376
|
} catch (error) {
|
|
@@ -75255,7 +75388,8 @@ var init_full = __esmMin((() => {
|
|
|
75255
75388
|
this.agent.emitEvent({
|
|
75256
75389
|
type: "compaction.completed",
|
|
75257
75390
|
result: eventResult,
|
|
75258
|
-
projectedContextTokens
|
|
75391
|
+
projectedContextTokens,
|
|
75392
|
+
...stageCount > 1 ? { stageCount } : {}
|
|
75259
75393
|
});
|
|
75260
75394
|
this.triggerPostCompactHook(data, result);
|
|
75261
75395
|
} catch (error) {
|
|
@@ -75320,35 +75454,72 @@ var init_full = __esmMin((() => {
|
|
|
75320
75454
|
let droppedCount = 0;
|
|
75321
75455
|
let overflowShrinkCount = 0;
|
|
75322
75456
|
let emptyOrTruncatedShrinkCount = 0;
|
|
75457
|
+
let hierarchicalPassCount = 0;
|
|
75323
75458
|
const typicalDurationMs = readTypicalCompactionDuration(provider.name, provider.modelName, this.agent.blunHomeDir)?.typicalDurationMs;
|
|
75324
75459
|
let attemptCount = 0;
|
|
75325
75460
|
let charsReceived = 0;
|
|
75326
75461
|
let lastProgressEmitAt = 0;
|
|
75462
|
+
let initialCompactionRequestTokens;
|
|
75327
75463
|
const compactionTools = [];
|
|
75328
|
-
|
|
75329
|
-
|
|
75330
|
-
const messages = stripMediaForCompaction(downgradeUnsupportedMedia([...this.agent.context.project(historyForModel, {
|
|
75464
|
+
const buildRequestMessages = (history, requestInstruction) => {
|
|
75465
|
+
return stripMediaForCompaction(downgradeUnsupportedMedia([...this.agent.context.project(history, {
|
|
75331
75466
|
synthesizeMissing: true,
|
|
75332
75467
|
dropOrphanResults: true
|
|
75333
|
-
}), createUserMessage(
|
|
75334
|
-
|
|
75335
|
-
|
|
75336
|
-
|
|
75337
|
-
|
|
75338
|
-
|
|
75339
|
-
|
|
75340
|
-
|
|
75341
|
-
|
|
75468
|
+
}), createUserMessage(requestInstruction)], capability));
|
|
75469
|
+
};
|
|
75470
|
+
while (true) {
|
|
75471
|
+
const compactionRequestLimit = this.getEffectiveMaxContextTokens();
|
|
75472
|
+
const safeCompactionRequestLimit = compactionRequestLimit > 0 ? Math.max(1, Math.floor(compactionRequestLimit * (1 - COMPACTION_SUMMARY_RESERVE_RATIO))) : compactionRequestLimit;
|
|
75473
|
+
let messages = buildRequestMessages(historyForModel, instruction);
|
|
75474
|
+
let estimatedCompactionRequestTokens = this.estimateRequestTokens(messages, this.agent.effectiveSystemPrompt, compactionTools);
|
|
75475
|
+
initialCompactionRequestTokens ??= estimatedCompactionRequestTokens;
|
|
75476
|
+
let hierarchicalChunkEnd;
|
|
75477
|
+
if (safeCompactionRequestLimit > 0 && estimatedCompactionRequestTokens >= safeCompactionRequestLimit) {
|
|
75478
|
+
if (historyForModel.length > 1) {
|
|
75479
|
+
const chunkInstruction = `${instruction}\n\nThis request contains only the oldest chronological segment. Summarize every fact needed by a later merge pass. Do not assume later messages are visible.`;
|
|
75480
|
+
const chunk = selectHierarchicalCompactionChunk(historyForModel, safeCompactionRequestLimit, safeCompactionRequestLimit, (candidate) => {
|
|
75481
|
+
const candidateMessages = buildRequestMessages(candidate, chunkInstruction);
|
|
75482
|
+
return {
|
|
75483
|
+
messages: candidateMessages,
|
|
75484
|
+
estimatedTokens: this.estimateRequestTokens(candidateMessages, this.agent.effectiveSystemPrompt, compactionTools)
|
|
75485
|
+
};
|
|
75486
|
+
});
|
|
75487
|
+
if (chunk !== void 0) {
|
|
75488
|
+
hierarchicalChunkEnd = chunk.end;
|
|
75489
|
+
messages = chunk.messages;
|
|
75490
|
+
estimatedCompactionRequestTokens = chunk.estimatedTokens;
|
|
75491
|
+
}
|
|
75492
|
+
}
|
|
75493
|
+
if (hierarchicalChunkEnd === void 0) throw new BlunError(ErrorCodes.CONTEXT_OVERFLOW, `Compaction stopped before upload: the conversation (${String(tokensBefore)} tokens) could not be divided into a request below the active model window (${String(compactionRequestLimit)} tokens).`, { details: {
|
|
75494
|
+
contextBrakeBlocked: true,
|
|
75495
|
+
estimatedRequestTokens: estimatedCompactionRequestTokens,
|
|
75496
|
+
maxContextTokens: compactionRequestLimit,
|
|
75497
|
+
requestBudgetTokens: safeCompactionRequestLimit,
|
|
75498
|
+
summaryReserveTokens: compactionRequestLimit - safeCompactionRequestLimit,
|
|
75499
|
+
contextUnchanged: true
|
|
75500
|
+
} });
|
|
75501
|
+
}
|
|
75342
75502
|
provider = buildCompactionProvider(estimatedCompactionRequestTokens);
|
|
75343
75503
|
attemptCount += 1;
|
|
75344
75504
|
charsReceived = 0;
|
|
75505
|
+
const estimatedProgressPercent = estimateCompactionProgressPercent(initialCompactionRequestTokens, estimatedCompactionRequestTokens);
|
|
75506
|
+
this.agent.log.info("compaction stage request", {
|
|
75507
|
+
source: data.source,
|
|
75508
|
+
stage: hierarchicalPassCount + 1,
|
|
75509
|
+
activeContextTokens: this.estimateProjectedRequestTokens(),
|
|
75510
|
+
estimatedInputTokens: estimatedCompactionRequestTokens,
|
|
75511
|
+
safeInputLimitTokens: safeCompactionRequestLimit,
|
|
75512
|
+
maxContextTokens: compactionRequestLimit
|
|
75513
|
+
});
|
|
75345
75514
|
const emitCompactionProgress = (force = false) => {
|
|
75346
75515
|
const now = Date.now();
|
|
75347
75516
|
if (!force && now - lastProgressEmitAt < 150) return;
|
|
75348
75517
|
lastProgressEmitAt = now;
|
|
75349
75518
|
this.agent.emitEvent({
|
|
75350
75519
|
type: "compaction.progress",
|
|
75520
|
+
stage: hierarchicalPassCount + 1,
|
|
75351
75521
|
estimatedInputTokens: estimatedCompactionRequestTokens,
|
|
75522
|
+
estimatedProgressPercent,
|
|
75352
75523
|
charsReceived,
|
|
75353
75524
|
attempt: attemptCount,
|
|
75354
75525
|
...typicalDurationMs !== void 0 ? { typicalDurationMs } : {}
|
|
@@ -75389,9 +75560,29 @@ var init_full = __esmMin((() => {
|
|
|
75389
75560
|
if (stalled && !signal.aborted && stallPolicy !== void 0) throw new CompactionStallError(stallPolicy.timeoutMs, stallPolicy.measuredIdleMs);
|
|
75390
75561
|
maxObservedIdleMs = Math.max(maxObservedIdleMs, Date.now() - lastProgressAt);
|
|
75391
75562
|
if (response.finishReason === "truncated") throw new CompactionTruncatedError();
|
|
75392
|
-
usage = response.usage;
|
|
75393
|
-
|
|
75563
|
+
if (response.usage !== null) usage = usage === null ? response.usage : addUsage$1(usage, response.usage);
|
|
75564
|
+
const extractedSummary = extractCompactionSummary(response);
|
|
75394
75565
|
this.observeCompactionTiming(timingKey, maxObservedIdleMs);
|
|
75566
|
+
if (hierarchicalChunkEnd !== void 0) {
|
|
75567
|
+
hierarchicalPassCount += 1;
|
|
75568
|
+
if (hierarchicalPassCount > MAX_HIERARCHICAL_COMPACTION_PASSES) throw new BlunError(ErrorCodes.COMPACTION_FAILED, `Compaction stopped after ${String(MAX_HIERARCHICAL_COMPACTION_PASSES)} staged requests without reaching a final summary. The conversation history was not changed.`, { details: {
|
|
75569
|
+
contextUnchanged: true,
|
|
75570
|
+
hierarchicalPassCount
|
|
75571
|
+
} });
|
|
75572
|
+
const previousTokens = estimateTokensForMessages(historyForModel);
|
|
75573
|
+
const nextHistory = [createUserMessage(`${HIERARCHICAL_COMPACTION_PREFIX}\n${extractedSummary}`), ...historyForModel.slice(hierarchicalChunkEnd)];
|
|
75574
|
+
const nextTokens = estimateTokensForMessages(nextHistory);
|
|
75575
|
+
if (nextTokens >= previousTokens) throw new BlunError(ErrorCodes.COMPACTION_FAILED, "A staged compaction response did not reduce the pending history. The conversation history was not changed.", { details: {
|
|
75576
|
+
contextUnchanged: true,
|
|
75577
|
+
hierarchicalPassCount,
|
|
75578
|
+
previousTokens,
|
|
75579
|
+
nextTokens
|
|
75580
|
+
} });
|
|
75581
|
+
historyForModel = nextHistory;
|
|
75582
|
+
retryCount = 0;
|
|
75583
|
+
continue;
|
|
75584
|
+
}
|
|
75585
|
+
summary = extractedSummary;
|
|
75395
75586
|
appendCompactionTiming({
|
|
75396
75587
|
ts: Date.now(),
|
|
75397
75588
|
provider: provider.name,
|
|
@@ -75408,6 +75599,10 @@ var init_full = __esmMin((() => {
|
|
|
75408
75599
|
if (isContextOverflow && historyForModel.length > 1) {
|
|
75409
75600
|
if (data.source === "auto") {
|
|
75410
75601
|
const learnedMaxContextTokens = this.getEffectiveMaxContextTokens();
|
|
75602
|
+
if (learnedMaxContextTokens > 0 && learnedMaxContextTokens < compactionRequestLimit) {
|
|
75603
|
+
retryCount = 0;
|
|
75604
|
+
continue;
|
|
75605
|
+
}
|
|
75411
75606
|
throw new BlunError(ErrorCodes.CONTEXT_OVERFLOW, "The active model rejected the full compaction request; refusing to drop unsummarized history.", {
|
|
75412
75607
|
cause: error,
|
|
75413
75608
|
details: {
|
|
@@ -75486,7 +75681,10 @@ var init_full = __esmMin((() => {
|
|
|
75486
75681
|
output_tokens: usage.output
|
|
75487
75682
|
}
|
|
75488
75683
|
});
|
|
75489
|
-
return
|
|
75684
|
+
return {
|
|
75685
|
+
result,
|
|
75686
|
+
stageCount: hierarchicalPassCount + 1
|
|
75687
|
+
};
|
|
75490
75688
|
} catch (error) {
|
|
75491
75689
|
if (isAbortError$4(error) || signal.aborted) return void 0;
|
|
75492
75690
|
this.agent.telemetry.track("compaction_failed", {
|
|
@@ -75520,6 +75718,15 @@ var init_full = __esmMin((() => {
|
|
|
75520
75718
|
contextUnchanged: true
|
|
75521
75719
|
}
|
|
75522
75720
|
});
|
|
75721
|
+
if (error instanceof APIStatusError && error.statusCode === 408) throw new BlunError(ErrorCodes.COMPACTION_FAILED, `Compaction stopped: the conversation (${String(tokensBefore)} tokens) could not be sent completely. The conversation history was not changed.`, {
|
|
75722
|
+
cause: error,
|
|
75723
|
+
details: {
|
|
75724
|
+
statusCode: error.statusCode,
|
|
75725
|
+
requestId: error.requestId,
|
|
75726
|
+
estimatedHistoryTokens: tokensBefore,
|
|
75727
|
+
contextUnchanged: true
|
|
75728
|
+
}
|
|
75729
|
+
});
|
|
75523
75730
|
throw new BlunError(ErrorCodes.COMPACTION_FAILED, String(error), { cause: error });
|
|
75524
75731
|
}
|
|
75525
75732
|
}
|
|
@@ -230311,6 +230518,7 @@ var init_action_style = __esmMin((() => {
|
|
|
230311
230518
|
init_injector();
|
|
230312
230519
|
STYLE_GUIDANCE = {
|
|
230313
230520
|
default: "Complete coding tasks efficiently. Keep responses concise while still reporting concrete results, blockers, and decisions.",
|
|
230521
|
+
concise: "Answer briefly and directly. Include only the information needed to act, while still reporting concrete results, blockers, and decisions.",
|
|
230314
230522
|
proactive: "Act immediately when the path is safe and clear. Minimize interruptions, continue through ordinary implementation decisions, and ask only when missing information or a higher-priority rule makes it necessary.",
|
|
230315
230523
|
explanatory: "Explain implementation choices and relevant codebase patterns while you work. Keep the explanation tied to the concrete task and avoid delaying safe progress.",
|
|
230316
230524
|
learning: "Create hands-on learning moments by inviting the user to write small, useful pieces of code. Do this only when the higher-priority rules allow a pause and it will not obstruct the requested result."
|
|
@@ -244836,6 +245044,7 @@ var init_events$1 = __esmMin((() => {
|
|
|
244836
245044
|
"goal.not_resumable",
|
|
244837
245045
|
"model.not_configured",
|
|
244838
245046
|
"model.config_invalid",
|
|
245047
|
+
"model.empty_response",
|
|
244839
245048
|
"auth.login_required",
|
|
244840
245049
|
"context.overflow",
|
|
244841
245050
|
"loop.already_exists",
|
|
@@ -245186,6 +245395,8 @@ var init_events$1 = __esmMin((() => {
|
|
|
245186
245395
|
compactionCancelledEventSchema = object({ type: literal("compaction.cancelled") });
|
|
245187
245396
|
compactionProgressEventSchema = object({
|
|
245188
245397
|
type: literal("compaction.progress"),
|
|
245398
|
+
stage: number$1().int().positive().optional(),
|
|
245399
|
+
estimatedProgressPercent: number$1().int().min(0).max(99).optional(),
|
|
245189
245400
|
estimatedInputTokens: number$1().optional(),
|
|
245190
245401
|
charsReceived: number$1(),
|
|
245191
245402
|
attempt: number$1(),
|
|
@@ -245194,7 +245405,8 @@ var init_events$1 = __esmMin((() => {
|
|
|
245194
245405
|
compactionCompletedEventSchema = object({
|
|
245195
245406
|
type: literal("compaction.completed"),
|
|
245196
245407
|
result: compactionResultSchema,
|
|
245197
|
-
projectedContextTokens: number$1().optional()
|
|
245408
|
+
projectedContextTokens: number$1().optional(),
|
|
245409
|
+
stageCount: number$1().int().positive().optional()
|
|
245198
245410
|
});
|
|
245199
245411
|
backgroundTaskStartedEventSchema = object({
|
|
245200
245412
|
type: literal("background.task.started"),
|
|
@@ -261611,7 +261823,7 @@ var init_blun_media$1 = __esmMin((() => {
|
|
|
261611
261823
|
return {
|
|
261612
261824
|
output: [{
|
|
261613
261825
|
type: "text",
|
|
261614
|
-
text: `Media job ${result.id} is complete. Local file: ${localPath}.
|
|
261826
|
+
text: `Media job ${result.id} is complete. Local file: ${localPath}. The BLUN host automatically delivers this file for channel-origin turns; do not attach it again. Outside a channel-origin turn, use this local path as needed.`
|
|
261615
261827
|
}, mediaPart],
|
|
261616
261828
|
isError: false
|
|
261617
261829
|
};
|
|
@@ -399828,6 +400040,7 @@ registerUiCatalogFragment({
|
|
|
399828
400040
|
"command.auto.description": "Toggle auto permission mode",
|
|
399829
400041
|
"command.permission.description": "Select permission mode",
|
|
399830
400042
|
"command.settings.description": "Open TUI settings",
|
|
400043
|
+
"command.outputStyle.description": "Choose the preferred way BLUN responds",
|
|
399831
400044
|
"command.plan.description": "Toggle plan mode",
|
|
399832
400045
|
"command.swarm.description": "Toggle swarm mode or run one task in swarm mode",
|
|
399833
400046
|
"command.model.description": "Switch LLM model",
|
|
@@ -399884,6 +400097,7 @@ registerUiCatalogFragment({
|
|
|
399884
400097
|
"command.auto.description": "Automatischen Berechtigungsmodus umschalten",
|
|
399885
400098
|
"command.permission.description": "Berechtigungsmodus auswählen",
|
|
399886
400099
|
"command.settings.description": "TUI-Einstellungen öffnen",
|
|
400100
|
+
"command.outputStyle.description": "Gewünschte Antwortweise für BLUN wählen",
|
|
399887
400101
|
"command.plan.description": "Planmodus umschalten",
|
|
399888
400102
|
"command.swarm.description": "Swarm-Modus umschalten oder eine Aufgabe im Swarm ausführen",
|
|
399889
400103
|
"command.model.description": "LLM-Modell wechseln",
|
|
@@ -399940,6 +400154,7 @@ registerUiCatalogFragment({
|
|
|
399940
400154
|
"command.auto.description": "Activar o desactivar el modo automático de permisos",
|
|
399941
400155
|
"command.permission.description": "Seleccionar el modo de permisos",
|
|
399942
400156
|
"command.settings.description": "Abrir los ajustes de la TUI",
|
|
400157
|
+
"command.outputStyle.description": "Elegir cómo debe responder BLUN",
|
|
399943
400158
|
"command.plan.description": "Activar o desactivar el modo de planificación",
|
|
399944
400159
|
"command.swarm.description": "Activar o desactivar el modo Swarm o ejecutar una tarea en ese modo",
|
|
399945
400160
|
"command.model.description": "Cambiar el modelo LLM",
|
|
@@ -399996,6 +400211,7 @@ registerUiCatalogFragment({
|
|
|
399996
400211
|
"command.auto.description": "Activer ou désactiver le mode d’autorisation automatique",
|
|
399997
400212
|
"command.permission.description": "Choisir le mode d’autorisation",
|
|
399998
400213
|
"command.settings.description": "Ouvrir les paramètres de la TUI",
|
|
400214
|
+
"command.outputStyle.description": "Choisir la manière dont BLUN doit répondre",
|
|
399999
400215
|
"command.plan.description": "Activer ou désactiver le mode Plan",
|
|
400000
400216
|
"command.swarm.description": "Activer ou désactiver le mode essaim, ou exécuter une tâche dans ce mode",
|
|
400001
400217
|
"command.model.description": "Changer de modèle LLM",
|
|
@@ -400052,6 +400268,7 @@ registerUiCatalogFragment({
|
|
|
400052
400268
|
"command.auto.description": "Slå på eller av automatiskt behörighetsläge",
|
|
400053
400269
|
"command.permission.description": "Välj behörighetsläge",
|
|
400054
400270
|
"command.settings.description": "Öppna TUI-inställningarna",
|
|
400271
|
+
"command.outputStyle.description": "Välj hur BLUN ska svara",
|
|
400055
400272
|
"command.plan.description": "Slå på eller av planläget",
|
|
400056
400273
|
"command.swarm.description": "Slå på eller av Swarm-läget eller kör en uppgift i Swarm-läge",
|
|
400057
400274
|
"command.model.description": "Byt LLM-modell",
|
|
@@ -400108,6 +400325,7 @@ registerUiCatalogFragment({
|
|
|
400108
400325
|
"command.auto.description": "Přepnout režim automatického oprávnění",
|
|
400109
400326
|
"command.permission.description": "Vybrat režim oprávnění",
|
|
400110
400327
|
"command.settings.description": "Otevřít nastavení TUI",
|
|
400328
|
+
"command.outputStyle.description": "Zvolit, jak má BLUN odpovídat",
|
|
400111
400329
|
"command.plan.description": "Přepnout režim plánu",
|
|
400112
400330
|
"command.swarm.description": "Přepnout režim swarm nebo spustit jednu úlohu v režimu swarm",
|
|
400113
400331
|
"command.model.description": "Přepnout model LLM",
|
|
@@ -400391,6 +400609,13 @@ const BUILTIN_SLASH_COMMAND_DEFINITIONS = [
|
|
|
400391
400609
|
priority: 100,
|
|
400392
400610
|
availability: "always"
|
|
400393
400611
|
},
|
|
400612
|
+
{
|
|
400613
|
+
name: "output-style",
|
|
400614
|
+
aliases: ["style"],
|
|
400615
|
+
descriptionKey: "command.outputStyle.description",
|
|
400616
|
+
priority: 100,
|
|
400617
|
+
availability: "always"
|
|
400618
|
+
},
|
|
400394
400619
|
{
|
|
400395
400620
|
name: "plan",
|
|
400396
400621
|
aliases: [],
|
|
@@ -410941,12 +411166,30 @@ const STREAMING_ARGS_PREVIEW_MAX_CHARS = 64 * 1024;
|
|
|
410941
411166
|
//#endregion
|
|
410942
411167
|
//#region src/tui/utils/event-payload.copy.ts
|
|
410943
411168
|
registerUiCatalogFragment({
|
|
410944
|
-
en: {
|
|
410945
|
-
|
|
410946
|
-
|
|
410947
|
-
|
|
410948
|
-
|
|
410949
|
-
|
|
411169
|
+
en: {
|
|
411170
|
+
"eventPayload.providerFiltered": "Provider filtered the response before visible output (finishReason={finishReason}{raw}).",
|
|
411171
|
+
"eventPayload.modelEmptyResponse": "King ended twice without producing content. Please send the message again."
|
|
411172
|
+
},
|
|
411173
|
+
de: {
|
|
411174
|
+
"eventPayload.providerFiltered": "Der Anbieter hat die Antwort vor der sichtbaren Ausgabe gefiltert (finishReason={finishReason}{raw}).",
|
|
411175
|
+
"eventPayload.modelEmptyResponse": "King hat die Antwort zweimal ohne Inhalt beendet. Bitte sende die Nachricht noch einmal."
|
|
411176
|
+
},
|
|
411177
|
+
es: {
|
|
411178
|
+
"eventPayload.providerFiltered": "El proveedor filtró la respuesta antes de que se mostrara la salida (finishReason={finishReason}{raw}).",
|
|
411179
|
+
"eventPayload.modelEmptyResponse": "King terminó dos veces sin generar contenido. Envía el mensaje de nuevo."
|
|
411180
|
+
},
|
|
411181
|
+
fr: {
|
|
411182
|
+
"eventPayload.providerFiltered": "Le fournisseur a filtré la réponse avant l’affichage de la sortie (finishReason={finishReason}{raw}).",
|
|
411183
|
+
"eventPayload.modelEmptyResponse": "King a terminé deux fois sans produire de contenu. Envoyez à nouveau le message."
|
|
411184
|
+
},
|
|
411185
|
+
sv: {
|
|
411186
|
+
"eventPayload.providerFiltered": "Leverantören filtrerade svaret innan någon utdata visades (finishReason={finishReason}{raw}).",
|
|
411187
|
+
"eventPayload.modelEmptyResponse": "King avslutade två gånger utan att skapa något innehåll. Skicka meddelandet igen."
|
|
411188
|
+
},
|
|
411189
|
+
cs: {
|
|
411190
|
+
"eventPayload.providerFiltered": "Poskytovatel filtroval odpověď před viditelným výstupem (finishReason={finishReason}{raw}).",
|
|
411191
|
+
"eventPayload.modelEmptyResponse": "King dvakrát ukončil odpověď bez obsahu. Odešlete zprávu znovu."
|
|
411192
|
+
}
|
|
410950
411193
|
});
|
|
410951
411194
|
//#endregion
|
|
410952
411195
|
//#region src/tui/utils/event-payload.ts
|
|
@@ -411019,6 +411262,7 @@ function formatErrorMessage$2(error) {
|
|
|
411019
411262
|
return projectBlunIdentity(error instanceof Error ? error.message : String(error));
|
|
411020
411263
|
}
|
|
411021
411264
|
function formatErrorPayload(error) {
|
|
411265
|
+
if (error.code === "model.empty_response") return uiText("eventPayload.modelEmptyResponse");
|
|
411022
411266
|
const filteredMessage = formatProviderFilteredMessage(error.details);
|
|
411023
411267
|
if (filteredMessage !== void 0) return projectBlunIdentity(`[${error.code}] ${filteredMessage}`);
|
|
411024
411268
|
return projectBlunIdentity(`[${error.code}] ${error.message}`);
|
|
@@ -411101,20 +411345,22 @@ registerUiCatalogFragment({
|
|
|
411101
411345
|
"swarmPermission.god.description": "Tools and plan changes are approved automatically. BLUN may still ask you questions.",
|
|
411102
411346
|
"swarmPermission.manual.label": "Start in Manual",
|
|
411103
411347
|
"swarmPermission.manual.description": "Keep approvals on. BLUN may stop and wait for you during the swarm task.",
|
|
411104
|
-
"settings.actionStyle.label": "
|
|
411105
|
-
"settings.actionStyle.description": "Choose how BLUN
|
|
411106
|
-
"actionStyle.title": "Preferred
|
|
411107
|
-
"actionStyle.scope": "This setting changes how BLUN
|
|
411348
|
+
"settings.actionStyle.label": "Output style",
|
|
411349
|
+
"settings.actionStyle.description": "Choose how BLUN responds and presents its work.",
|
|
411350
|
+
"actionStyle.title": "Preferred output style",
|
|
411351
|
+
"actionStyle.scope": "This setting changes how BLUN responds. Plan and permission rules still take priority.",
|
|
411108
411352
|
"actionStyle.default.label": "Default",
|
|
411109
411353
|
"actionStyle.default.description": "Completes coding tasks efficiently and keeps responses concise.",
|
|
411354
|
+
"actionStyle.concise.label": "Concise",
|
|
411355
|
+
"actionStyle.concise.description": "Answers briefly and directly, including only the information needed to act.",
|
|
411110
411356
|
"actionStyle.proactive.label": "Proactive",
|
|
411111
411357
|
"actionStyle.proactive.description": "Acts immediately when the path is clear, minimizes interruptions, and asks only when necessary.",
|
|
411112
411358
|
"actionStyle.explanatory.label": "Explanatory",
|
|
411113
411359
|
"actionStyle.explanatory.description": "Explains implementation choices and relevant codebase patterns while working.",
|
|
411114
411360
|
"actionStyle.learning.label": "Learning",
|
|
411115
411361
|
"actionStyle.learning.description": "Pauses at useful points and invites you to write small pieces of code for hands-on practice.",
|
|
411116
|
-
"actionStyle.saved": "
|
|
411117
|
-
"actionStyle.saveFailed": "Could not save
|
|
411362
|
+
"actionStyle.saved": "Output style set to {style}.",
|
|
411363
|
+
"actionStyle.saveFailed": "Could not save output style: {error}"
|
|
411118
411364
|
},
|
|
411119
411365
|
de: {
|
|
411120
411366
|
"permission.title": "Berechtigungsmodus auswählen",
|
|
@@ -411175,20 +411421,22 @@ registerUiCatalogFragment({
|
|
|
411175
411421
|
"swarmPermission.god.description": "Werkzeuge und Planwechsel werden automatisch freigegeben. BLUN kann dir weiterhin Fragen stellen.",
|
|
411176
411422
|
"swarmPermission.manual.label": "Manuell starten",
|
|
411177
411423
|
"swarmPermission.manual.description": "Freigaben beibehalten. BLUN kann den Swarm-Auftrag anhalten und auf dich warten.",
|
|
411178
|
-
"settings.actionStyle.label": "
|
|
411179
|
-
"settings.actionStyle.description": "Lege fest, wie BLUN
|
|
411180
|
-
"actionStyle.title": "Bevorzugter
|
|
411181
|
-
"actionStyle.scope": "Diese Einstellung bestimmt, wie BLUN
|
|
411424
|
+
"settings.actionStyle.label": "Ausgabestil",
|
|
411425
|
+
"settings.actionStyle.description": "Lege fest, wie BLUN antwortet und seine Arbeit darstellt.",
|
|
411426
|
+
"actionStyle.title": "Bevorzugter Ausgabestil",
|
|
411427
|
+
"actionStyle.scope": "Diese Einstellung bestimmt, wie BLUN antwortet. Plan- und Berechtigungsregeln haben weiterhin Vorrang.",
|
|
411182
411428
|
"actionStyle.default.label": "Standard",
|
|
411183
411429
|
"actionStyle.default.description": "Erledigt Programmieraufgaben effizient und hält Antworten knapp.",
|
|
411430
|
+
"actionStyle.concise.label": "Knapp",
|
|
411431
|
+
"actionStyle.concise.description": "Antwortet kurz und direkt und nennt nur die Informationen, die zum Handeln nötig sind.",
|
|
411184
411432
|
"actionStyle.proactive.label": "Proaktiv",
|
|
411185
411433
|
"actionStyle.proactive.description": "Handelt sofort, wenn der Weg klar ist, unterbricht dich so selten wie möglich und fragt nur nach, wenn es nötig ist.",
|
|
411186
411434
|
"actionStyle.explanatory.label": "Erklärend",
|
|
411187
411435
|
"actionStyle.explanatory.description": "Erläutert während der Arbeit Implementierungsentscheidungen und relevante Muster im Codebestand.",
|
|
411188
411436
|
"actionStyle.learning.label": "Lernorientiert",
|
|
411189
411437
|
"actionStyle.learning.description": "Hält an sinnvollen Stellen inne und lädt dich dazu ein, kleine Programmteile selbst zu schreiben und praktisch zu üben.",
|
|
411190
|
-
"actionStyle.saved": "
|
|
411191
|
-
"actionStyle.saveFailed": "
|
|
411438
|
+
"actionStyle.saved": "Ausgabestil auf {style} gesetzt.",
|
|
411439
|
+
"actionStyle.saveFailed": "Ausgabestil konnte nicht gespeichert werden: {error}"
|
|
411192
411440
|
},
|
|
411193
411441
|
es: {
|
|
411194
411442
|
"permission.title": "Seleccionar el modo de permisos",
|
|
@@ -411249,20 +411497,22 @@ registerUiCatalogFragment({
|
|
|
411249
411497
|
"swarmPermission.god.description": "Las herramientas y los cambios del plan se aprueban automáticamente. BLUN todavía puede hacerte preguntas.",
|
|
411250
411498
|
"swarmPermission.manual.label": "Iniciar en modo Manual",
|
|
411251
411499
|
"swarmPermission.manual.description": "Mantener activadas las aprobaciones. BLUN puede detenerse y esperar tu intervención durante la tarea de Swarm.",
|
|
411252
|
-
"settings.actionStyle.label": "Estilo de
|
|
411253
|
-
"settings.actionStyle.description": "Elige cómo
|
|
411254
|
-
"actionStyle.title": "Estilo de
|
|
411255
|
-
"actionStyle.scope": "Esta opción determina cómo
|
|
411500
|
+
"settings.actionStyle.label": "Estilo de salida",
|
|
411501
|
+
"settings.actionStyle.description": "Elige cómo responde BLUN y cómo presenta su trabajo.",
|
|
411502
|
+
"actionStyle.title": "Estilo de salida preferido",
|
|
411503
|
+
"actionStyle.scope": "Esta opción determina cómo responde BLUN. Las reglas del plan y de permisos siguen teniendo prioridad.",
|
|
411256
411504
|
"actionStyle.default.label": "Predeterminado",
|
|
411257
411505
|
"actionStyle.default.description": "Completa las tareas de programación con eficiencia y mantiene las respuestas concisas.",
|
|
411506
|
+
"actionStyle.concise.label": "Conciso",
|
|
411507
|
+
"actionStyle.concise.description": "Responde de forma breve y directa e incluye solo la información necesaria para actuar.",
|
|
411258
411508
|
"actionStyle.proactive.label": "Proactivo",
|
|
411259
411509
|
"actionStyle.proactive.description": "Actúa de inmediato cuando el camino está claro, reduce al mínimo las interrupciones y solo pregunta cuando es necesario.",
|
|
411260
411510
|
"actionStyle.explanatory.label": "Explicativo",
|
|
411261
411511
|
"actionStyle.explanatory.description": "Explica mientras trabaja las decisiones de implementación y los patrones relevantes del código.",
|
|
411262
411512
|
"actionStyle.learning.label": "Aprendizaje",
|
|
411263
411513
|
"actionStyle.learning.description": "Se detiene en momentos útiles y te invita a escribir pequeños fragmentos de código para practicar.",
|
|
411264
|
-
"actionStyle.saved": "Estilo de
|
|
411265
|
-
"actionStyle.saveFailed": "No se ha podido guardar el estilo de
|
|
411514
|
+
"actionStyle.saved": "Estilo de salida establecido en {style}.",
|
|
411515
|
+
"actionStyle.saveFailed": "No se ha podido guardar el estilo de salida: {error}"
|
|
411266
411516
|
},
|
|
411267
411517
|
fr: {
|
|
411268
411518
|
"permission.title": "Choisir le mode d’autorisation",
|
|
@@ -411323,20 +411573,22 @@ registerUiCatalogFragment({
|
|
|
411323
411573
|
"swarmPermission.god.description": "Les outils et les changements de plan sont approuvés automatiquement. BLUN peut toujours vous poser des questions.",
|
|
411324
411574
|
"swarmPermission.manual.label": "Lancer en mode Manuel",
|
|
411325
411575
|
"swarmPermission.manual.description": "Conserver les approbations. BLUN peut s’arrêter et attendre votre réponse pendant la tâche en essaim.",
|
|
411326
|
-
"settings.actionStyle.label": "Style
|
|
411327
|
-
"settings.actionStyle.description": "Choisissez
|
|
411328
|
-
"actionStyle.title": "Style
|
|
411329
|
-
"actionStyle.scope": "Ce réglage détermine la manière dont BLUN
|
|
411576
|
+
"settings.actionStyle.label": "Style de réponse",
|
|
411577
|
+
"settings.actionStyle.description": "Choisissez la manière dont BLUN répond et présente son travail.",
|
|
411578
|
+
"actionStyle.title": "Style de réponse préféré",
|
|
411579
|
+
"actionStyle.scope": "Ce réglage détermine la manière dont BLUN répond. Les règles du plan et des autorisations restent prioritaires.",
|
|
411330
411580
|
"actionStyle.default.label": "Par défaut",
|
|
411331
411581
|
"actionStyle.default.description": "Réalise efficacement les tâches de programmation et fournit des réponses concises.",
|
|
411582
|
+
"actionStyle.concise.label": "Concis",
|
|
411583
|
+
"actionStyle.concise.description": "Répond brièvement et directement, en indiquant uniquement les informations nécessaires pour agir.",
|
|
411332
411584
|
"actionStyle.proactive.label": "Proactif",
|
|
411333
411585
|
"actionStyle.proactive.description": "Agit immédiatement lorsque la marche à suivre est claire, réduit les interruptions au minimum et ne pose une question que si nécessaire.",
|
|
411334
411586
|
"actionStyle.explanatory.label": "Explicatif",
|
|
411335
411587
|
"actionStyle.explanatory.description": "Explique ses choix d’implémentation et les éléments pertinents du code pendant son travail.",
|
|
411336
411588
|
"actionStyle.learning.label": "Apprentissage",
|
|
411337
411589
|
"actionStyle.learning.description": "S’arrête aux moments utiles et vous invite à écrire de petits extraits de code pour apprendre par la pratique.",
|
|
411338
|
-
"actionStyle.saved": "Style
|
|
411339
|
-
"actionStyle.saveFailed": "Impossible d’enregistrer le style
|
|
411590
|
+
"actionStyle.saved": "Style de réponse défini sur {style}.",
|
|
411591
|
+
"actionStyle.saveFailed": "Impossible d’enregistrer le style de réponse : {error}"
|
|
411340
411592
|
},
|
|
411341
411593
|
sv: {
|
|
411342
411594
|
"permission.title": "Välj behörighetsläge",
|
|
@@ -411397,20 +411649,22 @@ registerUiCatalogFragment({
|
|
|
411397
411649
|
"swarmPermission.god.description": "Verktyg och planändringar godkänns automatiskt. BLUN kan fortfarande ställa frågor.",
|
|
411398
411650
|
"swarmPermission.manual.label": "Starta i manuellt läge",
|
|
411399
411651
|
"swarmPermission.manual.description": "Behåll godkännanden aktiverade. BLUN kan stanna och vänta på dig under Swarm-uppgiften.",
|
|
411400
|
-
"settings.actionStyle.label": "
|
|
411401
|
-
"settings.actionStyle.description": "Välj hur BLUN
|
|
411402
|
-
"actionStyle.title": "Önskad
|
|
411403
|
-
"actionStyle.scope": "Den här inställningen styr hur BLUN
|
|
411652
|
+
"settings.actionStyle.label": "Svarsstil",
|
|
411653
|
+
"settings.actionStyle.description": "Välj hur BLUN svarar och presenterar sitt arbete.",
|
|
411654
|
+
"actionStyle.title": "Önskad svarsstil",
|
|
411655
|
+
"actionStyle.scope": "Den här inställningen styr hur BLUN svarar. Plan- och behörighetsregler har fortfarande företräde.",
|
|
411404
411656
|
"actionStyle.default.label": "Standard",
|
|
411405
411657
|
"actionStyle.default.description": "Slutför programmeringsuppgifter effektivt och håller svaren kortfattade.",
|
|
411658
|
+
"actionStyle.concise.label": "Kortfattad",
|
|
411659
|
+
"actionStyle.concise.description": "Svarar kort och direkt och tar bara med den information som behövs för att agera.",
|
|
411406
411660
|
"actionStyle.proactive.label": "Proaktiv",
|
|
411407
411661
|
"actionStyle.proactive.description": "Agerar direkt när vägen framåt är tydlig, minimerar avbrott och frågar bara när det behövs.",
|
|
411408
411662
|
"actionStyle.explanatory.label": "Förklarande",
|
|
411409
411663
|
"actionStyle.explanatory.description": "Förklarar implementeringsval och relevanta mönster i kodbasen under arbetets gång.",
|
|
411410
411664
|
"actionStyle.learning.label": "Lärande",
|
|
411411
411665
|
"actionStyle.learning.description": "Stannar upp vid lämpliga tillfällen och bjuder in dig att skriva små kodavsnitt för praktisk övning.",
|
|
411412
|
-
"actionStyle.saved": "
|
|
411413
|
-
"actionStyle.saveFailed": "Det gick inte att spara
|
|
411666
|
+
"actionStyle.saved": "Svarsstilen har ställts in på {style}.",
|
|
411667
|
+
"actionStyle.saveFailed": "Det gick inte att spara svarsstilen: {error}"
|
|
411414
411668
|
},
|
|
411415
411669
|
cs: {
|
|
411416
411670
|
"permission.title": "Vybrat režim oprávnění",
|
|
@@ -411471,20 +411725,22 @@ registerUiCatalogFragment({
|
|
|
411471
411725
|
"swarmPermission.god.description": "Nástroje a změny plánu se schvalují automaticky. BLUN vám přesto může položit otázku.",
|
|
411472
411726
|
"swarmPermission.manual.label": "Spustit v ručním režimu",
|
|
411473
411727
|
"swarmPermission.manual.description": "Ponechte schválení zapnuto. BLUN se může během úlohy roje zastavit a čekat na vás.",
|
|
411474
|
-
"settings.actionStyle.label": "Styl
|
|
411475
|
-
"settings.actionStyle.description": "Zvolte, jak BLUN
|
|
411476
|
-
"actionStyle.title": "Preferovaný styl
|
|
411477
|
-
"actionStyle.scope": "Toto nastavení určuje, jak
|
|
411728
|
+
"settings.actionStyle.label": "Styl odpovědí",
|
|
411729
|
+
"settings.actionStyle.description": "Zvolte, jak BLUN odpovídá a jak prezentuje svou práci.",
|
|
411730
|
+
"actionStyle.title": "Preferovaný styl odpovědí",
|
|
411731
|
+
"actionStyle.scope": "Toto nastavení určuje, jak BLUN odpovídá. Pravidla plánu a oprávnění mají i nadále přednost.",
|
|
411478
411732
|
"actionStyle.default.label": "Výchozí",
|
|
411479
411733
|
"actionStyle.default.description": "Efektivně plní programátorské úkoly a odpovídá stručně.",
|
|
411734
|
+
"actionStyle.concise.label": "Stručný",
|
|
411735
|
+
"actionStyle.concise.description": "Odpovídá krátce a přímo a uvádí pouze informace potřebné k dalšímu postupu.",
|
|
411480
411736
|
"actionStyle.proactive.label": "Proaktivní",
|
|
411481
411737
|
"actionStyle.proactive.description": "Jedná okamžitě, když je další postup jasný, omezuje vyrušování na minimum a ptá se jen tehdy, když je to nutné.",
|
|
411482
411738
|
"actionStyle.explanatory.label": "Vysvětlující",
|
|
411483
411739
|
"actionStyle.explanatory.description": "Během práce vysvětluje implementační rozhodnutí a relevantní vzory v kódu.",
|
|
411484
411740
|
"actionStyle.learning.label": "Výukový",
|
|
411485
411741
|
"actionStyle.learning.description": "Na vhodných místech se zastaví a vyzve vás, abyste si pro praktické procvičení napsali malé části kódu.",
|
|
411486
|
-
"actionStyle.saved": "Styl
|
|
411487
|
-
"actionStyle.saveFailed": "Styl
|
|
411742
|
+
"actionStyle.saved": "Styl odpovědí byl nastaven na {style}.",
|
|
411743
|
+
"actionStyle.saveFailed": "Styl odpovědí se nepodařilo uložit: {error}"
|
|
411488
411744
|
}
|
|
411489
411745
|
});
|
|
411490
411746
|
//#endregion
|
|
@@ -412407,6 +412663,8 @@ registerUiCatalogFragment({
|
|
|
412407
412663
|
"btw.error.send": "Failed to send /btw prompt: {error}",
|
|
412408
412664
|
"btw.error.cancel": "Failed to cancel /btw: {error}",
|
|
412409
412665
|
"btw.busy": "Wait for /btw to finish before sending another question.",
|
|
412666
|
+
"btw.retrying": "BTW did not send any activity for two minutes. Retrying once...",
|
|
412667
|
+
"btw.timeout": "BTW did not respond after the automatic retry. Press Esc to close it and send the question again.",
|
|
412410
412668
|
"btw.turn.cancelled": "Interrupted by user",
|
|
412411
412669
|
"btw.turn.filtered": "Provider safety policy blocked the response.",
|
|
412412
412670
|
"btw.turn.ended": "BTW turn ended with reason: {reason}"
|
|
@@ -412416,6 +412674,8 @@ registerUiCatalogFragment({
|
|
|
412416
412674
|
"btw.error.send": "Die /btw-Frage konnte nicht übermittelt werden: {error}",
|
|
412417
412675
|
"btw.error.cancel": "/btw konnte nicht abgebrochen werden: {error}",
|
|
412418
412676
|
"btw.busy": "Warte, bis /btw beendet ist, bevor du eine weitere Frage sendest.",
|
|
412677
|
+
"btw.retrying": "BTW hat zwei Minuten lang keine Aktivität gesendet. Ein automatischer Wiederholungsversuch wird gestartet ...",
|
|
412678
|
+
"btw.timeout": "BTW hat auch nach dem automatischen Wiederholungsversuch nicht geantwortet. Drücke Esc, um das Fenster zu schließen, und sende die Frage erneut.",
|
|
412419
412679
|
"btw.turn.cancelled": "Vom Benutzer unterbrochen",
|
|
412420
412680
|
"btw.turn.filtered": "Die Sicherheitsrichtlinie des Anbieters hat die Antwort blockiert.",
|
|
412421
412681
|
"btw.turn.ended": "Die BTW-Runde wurde mit folgendem Grund beendet: {reason}"
|
|
@@ -412425,6 +412685,8 @@ registerUiCatalogFragment({
|
|
|
412425
412685
|
"btw.error.send": "No se pudo enviar la pregunta de /btw: {error}",
|
|
412426
412686
|
"btw.error.cancel": "No se pudo cancelar /btw: {error}",
|
|
412427
412687
|
"btw.busy": "Espera a que termine /btw antes de enviar otra pregunta.",
|
|
412688
|
+
"btw.retrying": "BTW no ha enviado ninguna actividad durante dos minutos. Se realizará un reintento automático...",
|
|
412689
|
+
"btw.timeout": "BTW tampoco ha respondido tras el reintento automático. Pulsa Esc para cerrar el panel y vuelve a enviar la pregunta.",
|
|
412428
412690
|
"btw.turn.cancelled": "Interrumpido por el usuario",
|
|
412429
412691
|
"btw.turn.filtered": "La política de seguridad del proveedor bloqueó la respuesta.",
|
|
412430
412692
|
"btw.turn.ended": "El turno de BTW terminó por este motivo: {reason}"
|
|
@@ -412434,6 +412696,8 @@ registerUiCatalogFragment({
|
|
|
412434
412696
|
"btw.error.send": "Impossible d’envoyer la question /btw : {error}",
|
|
412435
412697
|
"btw.error.cancel": "Impossible d’annuler /btw : {error}",
|
|
412436
412698
|
"btw.busy": "Attendez la fin de /btw avant d’envoyer une autre question.",
|
|
412699
|
+
"btw.retrying": "BTW n’a envoyé aucune activité pendant deux minutes. Une nouvelle tentative automatique va être effectuée…",
|
|
412700
|
+
"btw.timeout": "BTW n’a toujours pas répondu après la nouvelle tentative automatique. Appuyez sur Échap pour fermer le panneau, puis renvoyez la question.",
|
|
412437
412701
|
"btw.turn.cancelled": "Interrompu par l’utilisateur",
|
|
412438
412702
|
"btw.turn.filtered": "La politique de sécurité du fournisseur a bloqué la réponse.",
|
|
412439
412703
|
"btw.turn.ended": "Le tour BTW s’est terminé pour la raison suivante : {reason}"
|
|
@@ -412443,6 +412707,8 @@ registerUiCatalogFragment({
|
|
|
412443
412707
|
"btw.error.send": "Det gick inte att skicka /btw-frågan: {error}",
|
|
412444
412708
|
"btw.error.cancel": "Det gick inte att avbryta /btw: {error}",
|
|
412445
412709
|
"btw.busy": "Vänta tills /btw är klart innan du skickar en ny fråga.",
|
|
412710
|
+
"btw.retrying": "BTW har inte skickat någon aktivitet på två minuter. Ett automatiskt nytt försök görs ...",
|
|
412711
|
+
"btw.timeout": "BTW svarade inte heller efter det automatiska försöket. Tryck på Esc för att stänga panelen och skicka frågan igen.",
|
|
412446
412712
|
"btw.turn.cancelled": "Avbröts av användaren",
|
|
412447
412713
|
"btw.turn.filtered": "Leverantörens säkerhetspolicy blockerade svaret.",
|
|
412448
412714
|
"btw.turn.ended": "BTW-rundan avslutades av följande orsak: {reason}"
|
|
@@ -412452,6 +412718,8 @@ registerUiCatalogFragment({
|
|
|
412452
412718
|
"btw.error.send": "Odeslání dotazu /btw selhalo: {error}",
|
|
412453
412719
|
"btw.error.cancel": "Nepodařilo se zrušit /btw: {error}",
|
|
412454
412720
|
"btw.busy": "Než odešlete další otázku, počkejte na dokončení /btw.",
|
|
412721
|
+
"btw.retrying": "BTW dvě minuty nevykázal žádnou aktivitu. Proběhne jeden automatický opakovaný pokus…",
|
|
412722
|
+
"btw.timeout": "BTW neodpověděl ani po automatickém opakovaném pokusu. Stisknutím Esc panel zavřete a poté otázku odešlete znovu.",
|
|
412455
412723
|
"btw.turn.cancelled": "Přerušeno uživatelem",
|
|
412456
412724
|
"btw.turn.filtered": "Bezpečnostní zásada poskytovatele zablokovala odpověď.",
|
|
412457
412725
|
"btw.turn.ended": "Kolo BTW skončilo z důvodu: {reason}"
|
|
@@ -413272,6 +413540,7 @@ var EffortSelectorComponent = class extends Container {
|
|
|
413272
413540
|
//#region src/tui/components/dialogs/action-style-selector.ts
|
|
413273
413541
|
const ACTION_STYLES = [
|
|
413274
413542
|
"default",
|
|
413543
|
+
"concise",
|
|
413275
413544
|
"proactive",
|
|
413276
413545
|
"explanatory",
|
|
413277
413546
|
"learning"
|
|
@@ -417523,7 +417792,7 @@ function showPermissionPicker(host) {
|
|
|
417523
417792
|
}
|
|
417524
417793
|
}));
|
|
417525
417794
|
}
|
|
417526
|
-
function
|
|
417795
|
+
function showOutputStylePicker(host) {
|
|
417527
417796
|
host.mountEditorReplacement(new ActionStyleSelectorComponent({
|
|
417528
417797
|
currentValue: host.state.appState.actionStyle ?? "default",
|
|
417529
417798
|
onSelect: (value) => {
|
|
@@ -417627,7 +417896,7 @@ function handleSettingsSelection(host, value) {
|
|
|
417627
417896
|
handleEffortCommand(host, "");
|
|
417628
417897
|
return;
|
|
417629
417898
|
case "action-style":
|
|
417630
|
-
|
|
417899
|
+
showOutputStylePicker(host);
|
|
417631
417900
|
return;
|
|
417632
417901
|
case "permission":
|
|
417633
417902
|
showPermissionPicker(host);
|
|
@@ -425477,6 +425746,9 @@ var CompactionComponent = class extends Container {
|
|
|
425477
425746
|
tokensAfter;
|
|
425478
425747
|
estimatedInputTokens;
|
|
425479
425748
|
attempt = 1;
|
|
425749
|
+
stage = 1;
|
|
425750
|
+
stageCount;
|
|
425751
|
+
estimatedProgressPercent;
|
|
425480
425752
|
constructor(ui, instruction, tip, showRunning = true) {
|
|
425481
425753
|
super();
|
|
425482
425754
|
this.showRunning = showRunning;
|
|
@@ -425498,11 +425770,12 @@ var CompactionComponent = class extends Container {
|
|
|
425498
425770
|
if (!this.showRunning && !this.done && !this.canceled && !this.failed) return [];
|
|
425499
425771
|
return super.render(width);
|
|
425500
425772
|
}
|
|
425501
|
-
markDone(tokensBefore, tokensAfter) {
|
|
425773
|
+
markDone(tokensBefore, tokensAfter, stageCount) {
|
|
425502
425774
|
if (this.done || this.canceled || this.failed) return;
|
|
425503
425775
|
this.done = true;
|
|
425504
425776
|
this.tokensBefore = tokensBefore;
|
|
425505
425777
|
this.tokensAfter = tokensAfter;
|
|
425778
|
+
this.stageCount = stageCount;
|
|
425506
425779
|
this.stopTicking();
|
|
425507
425780
|
this.statusText.setText(this.buildStatusLine());
|
|
425508
425781
|
this.ui?.requestRender();
|
|
@@ -425529,6 +425802,8 @@ var CompactionComponent = class extends Container {
|
|
|
425529
425802
|
if (progress.estimatedInputTokens !== void 0) this.estimatedInputTokens = progress.estimatedInputTokens;
|
|
425530
425803
|
if (progress.attempt !== this.attempt) this.attemptStartedAtMs = Date.now();
|
|
425531
425804
|
this.attempt = progress.attempt;
|
|
425805
|
+
this.stage = progress.stage ?? this.stage;
|
|
425806
|
+
this.estimatedProgressPercent = progress.estimatedProgressPercent;
|
|
425532
425807
|
this.statusText.setText(this.buildStatusLine());
|
|
425533
425808
|
if (this.showRunning) this.ui?.requestRender();
|
|
425534
425809
|
}
|
|
@@ -425539,16 +425814,21 @@ var CompactionComponent = class extends Container {
|
|
|
425539
425814
|
return Math.max(0, Math.round((Date.now() - this.startedAtMs) / 1e3));
|
|
425540
425815
|
}
|
|
425541
425816
|
buildStatusLine() {
|
|
425542
|
-
if (this.done)
|
|
425543
|
-
|
|
425544
|
-
|
|
425545
|
-
|
|
425817
|
+
if (this.done) {
|
|
425818
|
+
const bar = currentTheme.fg("success", `[█${"█".repeat(BAR_WIDTH - 1)}]`);
|
|
425819
|
+
const completeText = `${uiText("compaction.complete")}${this.stageCount === void 0 ? "" : ` · ${String(this.stageCount)}/${String(this.stageCount)}`}`;
|
|
425820
|
+
return `${bar} ${currentTheme.boldFg("success", `${completeText} 100 %`)}${this.tokensBefore !== void 0 && this.tokensAfter !== void 0 ? currentTheme.dim(uiText("compaction.tokens", {
|
|
425821
|
+
before: this.tokensBefore.toLocaleString(getCurrentUiLocale()),
|
|
425822
|
+
after: this.tokensAfter.toLocaleString(getCurrentUiLocale())
|
|
425823
|
+
})) : ""}`;
|
|
425824
|
+
}
|
|
425546
425825
|
if (this.failed) return `${currentTheme.fg("error", STATUS_BULLET)}${currentTheme.boldFg("error", this.failureTitle ?? uiText("compaction.failed"))}${currentTheme.fg("textDim", ` · ${this.failureDetail ?? uiText("compaction.failureDetail")}`)}`;
|
|
425547
425826
|
if (this.canceled) return `${currentTheme.fg("warning", STATUS_BULLET)}${currentTheme.boldFg("warning", uiText("compaction.canceled"))}`;
|
|
425548
|
-
const
|
|
425827
|
+
const elapsedMs = Math.max(0, Date.now() - this.attemptStartedAtMs);
|
|
425828
|
+
const percent = this.estimatedProgressPercent ?? estimateCompactionPercent(elapsedMs, this.estimatedInputTokens);
|
|
425549
425829
|
const filled = Math.round(percent / 100 * BAR_WIDTH);
|
|
425550
425830
|
const bar = `[${"█".repeat(filled)}${"░".repeat(BAR_WIDTH - filled)}]`;
|
|
425551
|
-
const runningText = formatCompactionRunningText(this.estimatedInputTokens)
|
|
425831
|
+
const runningText = `${formatCompactionRunningText(this.estimatedInputTokens)} · ${String(this.stage)}/?`;
|
|
425552
425832
|
return `${currentTheme.fg("primary", bar)} ${currentTheme.boldFg("primary", runningText)}${currentTheme.fg("textDim", ` ~${String(percent)} %`)}${currentTheme.fg("textDim", ` · ${String(this.elapsedSeconds())}s`)}${this.attempt > 1 ? currentTheme.fg("textDim", uiText("compaction.attempt", { attempt: this.attempt })) : ""}${currentTheme.fg("textDim", ` · ${uiText("compaction.cancelHint")}`)}${this.instruction ? currentTheme.fg("textDim", ` · ${this.instruction}`) : ""}${this.tip ? currentTheme.fg("textDim", ` · ${this.tip}`) : ""}`;
|
|
425553
425833
|
}
|
|
425554
425834
|
startTicking() {
|
|
@@ -492031,6 +492311,9 @@ async function handleBuiltInSlashCommand(host, name, args) {
|
|
|
492031
492311
|
case "effort":
|
|
492032
492312
|
await handleEffortCommand(host, args);
|
|
492033
492313
|
return;
|
|
492314
|
+
case "output-style":
|
|
492315
|
+
showOutputStylePicker(host);
|
|
492316
|
+
return;
|
|
492034
492317
|
case "permission":
|
|
492035
492318
|
showPermissionPicker(host);
|
|
492036
492319
|
return;
|
|
@@ -498091,6 +498374,406 @@ registerUiCatalogFragment({
|
|
|
498091
498374
|
}
|
|
498092
498375
|
});
|
|
498093
498376
|
//#endregion
|
|
498377
|
+
//#region src/tui/blun-tui.copy.ts
|
|
498378
|
+
registerUiCatalogFragment({
|
|
498379
|
+
en: {
|
|
498380
|
+
"blunTui.provider.modelAdded.one": "{providerName} · +{count} model.",
|
|
498381
|
+
"blunTui.provider.modelAdded.other": "{providerName} · +{count} models.",
|
|
498382
|
+
"blunTui.provider.refreshSkipped": "Skipped refreshing {provider}: {reason}",
|
|
498383
|
+
"blunTui.warning": "Warning: {warning}",
|
|
498384
|
+
"blunTui.startup.sessionNotFound": "Session \"{sessionId}\" not found.",
|
|
498385
|
+
"blunTui.startup.sessionDifferentDirectory": "Session \"{sessionId}\" was created under a different directory.",
|
|
498386
|
+
"blunTui.startup.noSessionsToContinue": "No sessions to continue under \"{workDir}\"; starting a fresh session.",
|
|
498387
|
+
"blunTui.startup.sessionNotInitialized": "Startup session was not initialized.",
|
|
498388
|
+
"blunTui.input.replayBlocked": "Cannot send input while session history is replaying.",
|
|
498389
|
+
"blunTui.shell.noSession": "No active session for shell command.",
|
|
498390
|
+
"blunTui.shell.runFailed": "Shell command failed: {error}",
|
|
498391
|
+
"blunTui.shell.cancelFailed": "Failed to cancel shell command: {error}",
|
|
498392
|
+
"blunTui.channel.steerFailed": "Failed to steer channel message: {error}",
|
|
498393
|
+
"blunTui.session.sendFailed": "Failed to send: {error}",
|
|
498394
|
+
"blunTui.media.imageUnsupported": "Current model does not support image input.",
|
|
498395
|
+
"blunTui.media.videoUnsupported": "Current model does not support video input.",
|
|
498396
|
+
"blunTui.skill.failed": "Skill \"{skillName}\" failed: {error}",
|
|
498397
|
+
"blunTui.pluginCommand.failed": "Command \"{command}\" failed: {error}",
|
|
498398
|
+
"blunTui.steer.failed": "Failed to steer: {error}",
|
|
498399
|
+
"blunTui.session.otherWorkDir": "Current session is in a different working directory.",
|
|
498400
|
+
"blunTui.session.resumeCommand": "To resume, run: {command}",
|
|
498401
|
+
"blunTui.clipboard.commandCopied": "Command copied to clipboard",
|
|
498402
|
+
"blunTui.clipboard.commandCopyFailed": "Failed to copy command to clipboard",
|
|
498403
|
+
"blunTui.session.alreadyCurrent": "Already on this session.",
|
|
498404
|
+
"blunTui.session.switchStreamingBlocked": "Cannot switch sessions while streaming — press Esc or Ctrl-C first.",
|
|
498405
|
+
"blunTui.session.switchReplayBlocked": "Cannot switch sessions while history is replaying.",
|
|
498406
|
+
"blunTui.session.resumeFailed": "Failed to resume session {sessionId}: {error}",
|
|
498407
|
+
"blunTui.session.resumed": "Resumed session ({sessionId}).",
|
|
498408
|
+
"blunTui.session.replayFailed": "Failed to replay session history: {error}",
|
|
498409
|
+
"blunTui.session.createReplayBlocked": "Cannot start a new session while history is replaying.",
|
|
498410
|
+
"blunTui.session.createFailed": "Failed to start a new session: {error}",
|
|
498411
|
+
"blunTui.session.postCreateFailed": "Post-create setup failed: {error}",
|
|
498412
|
+
"blunTui.session.started": "Started a new session ({sessionId}).",
|
|
498413
|
+
"blunTui.error": "Error: {message}",
|
|
498414
|
+
"blunTui.login.title": "Sign in to BLUN",
|
|
498415
|
+
"blunTui.login.hint": "Press Ctrl-C to cancel",
|
|
498416
|
+
"blunTui.login.waiting": "Waiting for authorization…",
|
|
498417
|
+
"blunTui.detach.noShell": "No shell command running.",
|
|
498418
|
+
"blunTui.detach.shellStarting": "Command is still starting — try again.",
|
|
498419
|
+
"blunTui.detach.shellFinished": "Command already finished.",
|
|
498420
|
+
"blunTui.detach.moveFailed": "Failed to move to background: {error}",
|
|
498421
|
+
"blunTui.detach.movedTranscript": "Moved to background.",
|
|
498422
|
+
"blunTui.detach.movedView": "Moved to background. /tasks to view.",
|
|
498423
|
+
"blunTui.detach.noForeground": "No foreground task running.",
|
|
498424
|
+
"blunTui.detach.listFailed": "Failed to list tasks: {error}",
|
|
498425
|
+
"blunTui.detach.taskFailed": "Failed to detach {taskId}: {error}",
|
|
498426
|
+
"blunTui.detach.finished.one": "Task already finished.",
|
|
498427
|
+
"blunTui.detach.finished.other": "Tasks already finished.",
|
|
498428
|
+
"blunTui.detach.moved.one": "Moved {count} task to background.",
|
|
498429
|
+
"blunTui.detach.moved.other": "Moved {count} tasks to background.",
|
|
498430
|
+
"blunTui.detach.partial": "Moved {detached} of {total} tasks to background.",
|
|
498431
|
+
"blunTui.detach.viewSuffix": "/tasks to view.",
|
|
498432
|
+
"blunTui.startup.flagsFailed": "Failed to apply startup flags: {error}",
|
|
498433
|
+
"blunTui.notification.approvalRequired": "BLUN approval required",
|
|
498434
|
+
"blunTui.notification.answerRequired": "BLUN needs your answer",
|
|
498435
|
+
"blunTui.telegram.fallbackDelivered": "Reply delivered to Telegram automatically (fallback).",
|
|
498436
|
+
"blunTui.telegram.attachDisabled": "Telegram attachment disabled by BLUN_TELEGRAM_ATTACH=off — headless mode active.",
|
|
498437
|
+
"blunTui.telegram.noToken": "Telegram attachment: no token detected — headless mode active.",
|
|
498438
|
+
"blunTui.telegram.attached": "Telegram channel attached (lease PID {pid}) — messages appear in this window.",
|
|
498439
|
+
"blunTui.auto.status": "Auto: {label}",
|
|
498440
|
+
"blunTui.activity.thinking": "{name} is thinking…",
|
|
498441
|
+
"blunTui.activity.working": "{name} is working…",
|
|
498442
|
+
"blunTui.activity.composing": "working...",
|
|
498443
|
+
"blunTui.activity.tokens": "Tokens"
|
|
498444
|
+
},
|
|
498445
|
+
de: {
|
|
498446
|
+
"blunTui.provider.modelAdded.one": "{providerName} · +{count} Modell.",
|
|
498447
|
+
"blunTui.provider.modelAdded.other": "{providerName} · +{count} Modelle.",
|
|
498448
|
+
"blunTui.provider.refreshSkipped": "Aktualisierung von {provider} übersprungen: {reason}",
|
|
498449
|
+
"blunTui.warning": "Warnung: {warning}",
|
|
498450
|
+
"blunTui.startup.sessionNotFound": "Sitzung „{sessionId}“ wurde nicht gefunden.",
|
|
498451
|
+
"blunTui.startup.sessionDifferentDirectory": "Sitzung „{sessionId}“ wurde in einem anderen Arbeitsverzeichnis erstellt.",
|
|
498452
|
+
"blunTui.startup.noSessionsToContinue": "Unter „{workDir}“ gibt es keine Sitzung zum Fortsetzen; eine neue Sitzung wird gestartet.",
|
|
498453
|
+
"blunTui.startup.sessionNotInitialized": "Die Sitzung konnte beim Start nicht initialisiert werden.",
|
|
498454
|
+
"blunTui.input.replayBlocked": "Während der Wiedergabe des Sitzungsverlaufs können keine Eingaben gesendet werden.",
|
|
498455
|
+
"blunTui.shell.noSession": "Keine aktive Sitzung für den Shell-Befehl.",
|
|
498456
|
+
"blunTui.shell.runFailed": "Shell-Befehl fehlgeschlagen: {error}",
|
|
498457
|
+
"blunTui.shell.cancelFailed": "Shell-Befehl konnte nicht abgebrochen werden: {error}",
|
|
498458
|
+
"blunTui.channel.steerFailed": "Die Kanalnachricht konnte nicht zur laufenden Antwort hinzugefügt werden: {error}",
|
|
498459
|
+
"blunTui.session.sendFailed": "Senden fehlgeschlagen: {error}",
|
|
498460
|
+
"blunTui.media.imageUnsupported": "Das aktuelle Modell unterstützt keine Bildeingaben.",
|
|
498461
|
+
"blunTui.media.videoUnsupported": "Das aktuelle Modell unterstützt keine Videoeingaben.",
|
|
498462
|
+
"blunTui.skill.failed": "Skill „{skillName}“ fehlgeschlagen: {error}",
|
|
498463
|
+
"blunTui.pluginCommand.failed": "Befehl „{command}“ fehlgeschlagen: {error}",
|
|
498464
|
+
"blunTui.steer.failed": "Nachsteuern fehlgeschlagen: {error}",
|
|
498465
|
+
"blunTui.session.otherWorkDir": "Die aktuelle Sitzung befindet sich in einem anderen Arbeitsverzeichnis.",
|
|
498466
|
+
"blunTui.session.resumeCommand": "Zum Fortsetzen ausführen: {command}",
|
|
498467
|
+
"blunTui.clipboard.commandCopied": "Befehl in die Zwischenablage kopiert",
|
|
498468
|
+
"blunTui.clipboard.commandCopyFailed": "Befehl konnte nicht in die Zwischenablage kopiert werden",
|
|
498469
|
+
"blunTui.session.alreadyCurrent": "Diese Sitzung ist bereits aktiv.",
|
|
498470
|
+
"blunTui.session.switchStreamingBlocked": "Während einer laufenden Antwort kann die Sitzung nicht gewechselt werden. Drücke zuerst Esc oder Ctrl-C.",
|
|
498471
|
+
"blunTui.session.switchReplayBlocked": "Während der Wiedergabe des Sitzungsverlaufs kann die Sitzung nicht gewechselt werden.",
|
|
498472
|
+
"blunTui.session.resumeFailed": "Sitzung {sessionId} konnte nicht fortgesetzt werden: {error}",
|
|
498473
|
+
"blunTui.session.resumed": "Sitzung fortgesetzt ({sessionId}).",
|
|
498474
|
+
"blunTui.session.replayFailed": "Der Sitzungsverlauf konnte nicht wiedergegeben werden: {error}",
|
|
498475
|
+
"blunTui.session.createReplayBlocked": "Während der Wiedergabe des Sitzungsverlaufs kann keine neue Sitzung gestartet werden.",
|
|
498476
|
+
"blunTui.session.createFailed": "Neue Sitzung konnte nicht gestartet werden: {error}",
|
|
498477
|
+
"blunTui.session.postCreateFailed": "Die neue Sitzung konnte nicht eingerichtet werden: {error}",
|
|
498478
|
+
"blunTui.session.started": "Neue Sitzung gestartet ({sessionId}).",
|
|
498479
|
+
"blunTui.error": "Fehler: {message}",
|
|
498480
|
+
"blunTui.login.title": "Bei BLUN anmelden",
|
|
498481
|
+
"blunTui.login.hint": "Zum Abbrechen Ctrl-C drücken",
|
|
498482
|
+
"blunTui.login.waiting": "Warten auf Autorisierung…",
|
|
498483
|
+
"blunTui.detach.noShell": "Es wird kein Shell-Befehl ausgeführt.",
|
|
498484
|
+
"blunTui.detach.shellStarting": "Der Befehl wird noch gestartet — versuche es erneut.",
|
|
498485
|
+
"blunTui.detach.shellFinished": "Der Befehl ist bereits beendet.",
|
|
498486
|
+
"blunTui.detach.moveFailed": "Verschieben in den Hintergrund fehlgeschlagen: {error}",
|
|
498487
|
+
"blunTui.detach.movedTranscript": "In den Hintergrund verschoben.",
|
|
498488
|
+
"blunTui.detach.movedView": "In den Hintergrund verschoben. Mit /tasks anzeigen.",
|
|
498489
|
+
"blunTui.detach.noForeground": "Es wird keine Aufgabe im Vordergrund ausgeführt.",
|
|
498490
|
+
"blunTui.detach.listFailed": "Aufgaben konnten nicht aufgelistet werden: {error}",
|
|
498491
|
+
"blunTui.detach.taskFailed": "Aufgabe {taskId} konnte nicht in den Hintergrund verschoben werden: {error}",
|
|
498492
|
+
"blunTui.detach.finished.one": "Aufgabe ist bereits beendet.",
|
|
498493
|
+
"blunTui.detach.finished.other": "Aufgaben sind bereits beendet.",
|
|
498494
|
+
"blunTui.detach.moved.one": "{count} Aufgabe in den Hintergrund verschoben.",
|
|
498495
|
+
"blunTui.detach.moved.other": "{count} Aufgaben in den Hintergrund verschoben.",
|
|
498496
|
+
"blunTui.detach.partial": "{detached} von {total} Aufgaben in den Hintergrund verschoben.",
|
|
498497
|
+
"blunTui.detach.viewSuffix": "Mit /tasks anzeigen.",
|
|
498498
|
+
"blunTui.startup.flagsFailed": "Startoptionen konnten nicht angewendet werden: {error}",
|
|
498499
|
+
"blunTui.notification.approvalRequired": "BLUN-Genehmigung erforderlich",
|
|
498500
|
+
"blunTui.notification.answerRequired": "BLUN benötigt deine Antwort",
|
|
498501
|
+
"blunTui.telegram.fallbackDelivered": "Antwort automatisch nach Telegram zugestellt (Fallback).",
|
|
498502
|
+
"blunTui.telegram.attachDisabled": "Telegram-Anbindung durch BLUN_TELEGRAM_ATTACH=off deaktiviert — Headless-Modus aktiv.",
|
|
498503
|
+
"blunTui.telegram.noToken": "Telegram-Anbindung: kein Token erkannt — Headless-Modus aktiv.",
|
|
498504
|
+
"blunTui.telegram.attached": "Telegram-Kanal angebunden (Lease-PID {pid}) — Nachrichten erscheinen in diesem Fenster.",
|
|
498505
|
+
"blunTui.auto.status": "Auto: {label}",
|
|
498506
|
+
"blunTui.activity.thinking": "{name} denkt…",
|
|
498507
|
+
"blunTui.activity.working": "{name} arbeitet…",
|
|
498508
|
+
"blunTui.activity.composing": "arbeitet...",
|
|
498509
|
+
"blunTui.activity.tokens": "Token"
|
|
498510
|
+
},
|
|
498511
|
+
es: {
|
|
498512
|
+
"blunTui.provider.modelAdded.one": "{providerName} · +{count} modelo.",
|
|
498513
|
+
"blunTui.provider.modelAdded.other": "{providerName} · +{count} modelos.",
|
|
498514
|
+
"blunTui.provider.refreshSkipped": "Se omitió la actualización de {provider}: {reason}",
|
|
498515
|
+
"blunTui.warning": "Advertencia: {warning}",
|
|
498516
|
+
"blunTui.startup.sessionNotFound": "No se encontró la sesión «{sessionId}».",
|
|
498517
|
+
"blunTui.startup.sessionDifferentDirectory": "La sesión «{sessionId}» se creó en otro directorio de trabajo.",
|
|
498518
|
+
"blunTui.startup.noSessionsToContinue": "No hay sesiones que reanudar en «{workDir}»; se iniciará una sesión nueva.",
|
|
498519
|
+
"blunTui.startup.sessionNotInitialized": "No se pudo inicializar la sesión durante el arranque.",
|
|
498520
|
+
"blunTui.input.replayBlocked": "No se puede enviar ninguna entrada mientras se reproduce el historial de la sesión.",
|
|
498521
|
+
"blunTui.shell.noSession": "No hay ninguna sesión activa para el comando de shell.",
|
|
498522
|
+
"blunTui.shell.runFailed": "El comando de shell falló: {error}",
|
|
498523
|
+
"blunTui.shell.cancelFailed": "No se pudo cancelar el comando de shell: {error}",
|
|
498524
|
+
"blunTui.channel.steerFailed": "No se pudo añadir el mensaje del canal a la respuesta en curso: {error}",
|
|
498525
|
+
"blunTui.session.sendFailed": "No se pudo enviar: {error}",
|
|
498526
|
+
"blunTui.media.imageUnsupported": "El modelo actual no admite entradas de imagen.",
|
|
498527
|
+
"blunTui.media.videoUnsupported": "El modelo actual no admite entradas de vídeo.",
|
|
498528
|
+
"blunTui.skill.failed": "El skill «{skillName}» falló: {error}",
|
|
498529
|
+
"blunTui.pluginCommand.failed": "El comando «{command}» falló: {error}",
|
|
498530
|
+
"blunTui.steer.failed": "No se pudo reorientar la respuesta: {error}",
|
|
498531
|
+
"blunTui.session.otherWorkDir": "La sesión actual se encuentra en otro directorio de trabajo.",
|
|
498532
|
+
"blunTui.session.resumeCommand": "Para reanudarla, ejecuta: {command}",
|
|
498533
|
+
"blunTui.clipboard.commandCopied": "Comando copiado al portapapeles",
|
|
498534
|
+
"blunTui.clipboard.commandCopyFailed": "No se pudo copiar el comando al portapapeles",
|
|
498535
|
+
"blunTui.session.alreadyCurrent": "Esta sesión ya está activa.",
|
|
498536
|
+
"blunTui.session.switchStreamingBlocked": "No se puede cambiar de sesión mientras se genera una respuesta. Pulsa primero Esc o Ctrl-C.",
|
|
498537
|
+
"blunTui.session.switchReplayBlocked": "No se puede cambiar de sesión mientras se reproduce el historial.",
|
|
498538
|
+
"blunTui.session.resumeFailed": "No se pudo reanudar la sesión {sessionId}: {error}",
|
|
498539
|
+
"blunTui.session.resumed": "Sesión reanudada ({sessionId}).",
|
|
498540
|
+
"blunTui.session.replayFailed": "No se pudo reproducir el historial de la sesión: {error}",
|
|
498541
|
+
"blunTui.session.createReplayBlocked": "No se puede iniciar una sesión nueva mientras se reproduce el historial.",
|
|
498542
|
+
"blunTui.session.createFailed": "No se pudo iniciar una sesión nueva: {error}",
|
|
498543
|
+
"blunTui.session.postCreateFailed": "No se pudo configurar la sesión recién creada: {error}",
|
|
498544
|
+
"blunTui.session.started": "Se inició una sesión nueva ({sessionId}).",
|
|
498545
|
+
"blunTui.error": "Error: {message}",
|
|
498546
|
+
"blunTui.login.title": "Iniciar sesión en BLUN",
|
|
498547
|
+
"blunTui.login.hint": "Pulsa Ctrl-C para cancelar",
|
|
498548
|
+
"blunTui.login.waiting": "Esperando autorización…",
|
|
498549
|
+
"blunTui.detach.noShell": "No hay ningún comando de shell en ejecución.",
|
|
498550
|
+
"blunTui.detach.shellStarting": "El comando todavía se está iniciando; inténtalo de nuevo.",
|
|
498551
|
+
"blunTui.detach.shellFinished": "El comando ya ha finalizado.",
|
|
498552
|
+
"blunTui.detach.moveFailed": "No se pudo mover a segundo plano: {error}",
|
|
498553
|
+
"blunTui.detach.movedTranscript": "Se movió a segundo plano.",
|
|
498554
|
+
"blunTui.detach.movedView": "Se movió a segundo plano. Consulta /tasks.",
|
|
498555
|
+
"blunTui.detach.noForeground": "No hay ninguna tarea en ejecución en primer plano.",
|
|
498556
|
+
"blunTui.detach.listFailed": "No se pudieron obtener las tareas: {error}",
|
|
498557
|
+
"blunTui.detach.taskFailed": "No se pudo mover la tarea {taskId} a segundo plano: {error}",
|
|
498558
|
+
"blunTui.detach.finished.one": "La tarea ya ha finalizado.",
|
|
498559
|
+
"blunTui.detach.finished.other": "Las tareas ya han finalizado.",
|
|
498560
|
+
"blunTui.detach.moved.one": "Se ha movido {count} tarea a segundo plano.",
|
|
498561
|
+
"blunTui.detach.moved.other": "Se han movido {count} tareas a segundo plano.",
|
|
498562
|
+
"blunTui.detach.partial": "Se han movido {detached} de {total} tareas a segundo plano.",
|
|
498563
|
+
"blunTui.detach.viewSuffix": "Consulta /tasks.",
|
|
498564
|
+
"blunTui.startup.flagsFailed": "No se pudieron aplicar las opciones de inicio: {error}",
|
|
498565
|
+
"blunTui.notification.approvalRequired": "Se requiere aprobación de BLUN",
|
|
498566
|
+
"blunTui.notification.answerRequired": "BLUN necesita tu respuesta",
|
|
498567
|
+
"blunTui.telegram.fallbackDelivered": "La respuesta se envió automáticamente a Telegram (modo alternativo).",
|
|
498568
|
+
"blunTui.telegram.attachDisabled": "Conexión con Telegram desactivada mediante BLUN_TELEGRAM_ATTACH=off — modo headless activo.",
|
|
498569
|
+
"blunTui.telegram.noToken": "Conexión con Telegram: no se detectó ningún token — modo headless activo.",
|
|
498570
|
+
"blunTui.telegram.attached": "Canal de Telegram conectado (PID de lease {pid}) — los mensajes aparecen en esta ventana.",
|
|
498571
|
+
"blunTui.auto.status": "Automático: {label}",
|
|
498572
|
+
"blunTui.activity.thinking": "{name} está pensando…",
|
|
498573
|
+
"blunTui.activity.working": "{name} está trabajando…",
|
|
498574
|
+
"blunTui.activity.composing": "trabajando...",
|
|
498575
|
+
"blunTui.activity.tokens": "tokens"
|
|
498576
|
+
},
|
|
498577
|
+
fr: {
|
|
498578
|
+
"blunTui.provider.modelAdded.one": "{providerName} · +{count} modèle.",
|
|
498579
|
+
"blunTui.provider.modelAdded.other": "{providerName} · +{count} modèles.",
|
|
498580
|
+
"blunTui.provider.refreshSkipped": "Actualisation de {provider} ignorée : {reason}",
|
|
498581
|
+
"blunTui.warning": "Avertissement : {warning}",
|
|
498582
|
+
"blunTui.startup.sessionNotFound": "Session « {sessionId} » introuvable.",
|
|
498583
|
+
"blunTui.startup.sessionDifferentDirectory": "La session « {sessionId} » a été créée dans un autre répertoire de travail.",
|
|
498584
|
+
"blunTui.startup.noSessionsToContinue": "Aucune session à reprendre dans « {workDir} » ; démarrage d’une nouvelle session.",
|
|
498585
|
+
"blunTui.startup.sessionNotInitialized": "La session de démarrage n’a pas été initialisée.",
|
|
498586
|
+
"blunTui.input.replayBlocked": "Impossible d’envoyer une saisie pendant la relecture de l’historique de la session.",
|
|
498587
|
+
"blunTui.shell.noSession": "Aucune session active pour la commande shell.",
|
|
498588
|
+
"blunTui.shell.runFailed": "Échec de la commande shell : {error}",
|
|
498589
|
+
"blunTui.shell.cancelFailed": "Impossible d’annuler la commande shell : {error}",
|
|
498590
|
+
"blunTui.channel.steerFailed": "Impossible d’ajouter le message du canal à la réponse en cours : {error}",
|
|
498591
|
+
"blunTui.session.sendFailed": "Échec de l’envoi : {error}",
|
|
498592
|
+
"blunTui.media.imageUnsupported": "Le modèle actuel ne prend pas en charge les images en entrée.",
|
|
498593
|
+
"blunTui.media.videoUnsupported": "Le modèle actuel ne prend pas en charge les vidéos en entrée.",
|
|
498594
|
+
"blunTui.skill.failed": "Échec du skill « {skillName} » : {error}",
|
|
498595
|
+
"blunTui.pluginCommand.failed": "Échec de la commande « {command} » : {error}",
|
|
498596
|
+
"blunTui.steer.failed": "Impossible de réorienter la réponse : {error}",
|
|
498597
|
+
"blunTui.session.otherWorkDir": "La session actuelle se trouve dans un autre répertoire de travail.",
|
|
498598
|
+
"blunTui.session.resumeCommand": "Pour la reprendre, exécutez : {command}",
|
|
498599
|
+
"blunTui.clipboard.commandCopied": "Commande copiée dans le presse-papiers",
|
|
498600
|
+
"blunTui.clipboard.commandCopyFailed": "Impossible de copier la commande dans le presse-papiers",
|
|
498601
|
+
"blunTui.session.alreadyCurrent": "Cette session est déjà active.",
|
|
498602
|
+
"blunTui.session.switchStreamingBlocked": "Impossible de changer de session pendant la génération d’une réponse. Appuyez d’abord sur Esc ou Ctrl-C.",
|
|
498603
|
+
"blunTui.session.switchReplayBlocked": "Impossible de changer de session pendant la relecture de l’historique.",
|
|
498604
|
+
"blunTui.session.resumeFailed": "Impossible de reprendre la session {sessionId} : {error}",
|
|
498605
|
+
"blunTui.session.resumed": "Session reprise ({sessionId}).",
|
|
498606
|
+
"blunTui.session.replayFailed": "Impossible de relire l’historique de la session : {error}",
|
|
498607
|
+
"blunTui.session.createReplayBlocked": "Impossible de démarrer une nouvelle session pendant la relecture de l’historique.",
|
|
498608
|
+
"blunTui.session.createFailed": "Impossible de démarrer une nouvelle session : {error}",
|
|
498609
|
+
"blunTui.session.postCreateFailed": "Impossible de configurer la nouvelle session : {error}",
|
|
498610
|
+
"blunTui.session.started": "Nouvelle session démarrée ({sessionId}).",
|
|
498611
|
+
"blunTui.error": "Erreur : {message}",
|
|
498612
|
+
"blunTui.login.title": "Se connecter à BLUN",
|
|
498613
|
+
"blunTui.login.hint": "Appuyez sur Ctrl-C pour annuler",
|
|
498614
|
+
"blunTui.login.waiting": "En attente de l’autorisation…",
|
|
498615
|
+
"blunTui.detach.noShell": "Aucune commande shell en cours.",
|
|
498616
|
+
"blunTui.detach.shellStarting": "La commande est encore en cours de démarrage — réessayez.",
|
|
498617
|
+
"blunTui.detach.shellFinished": "La commande est déjà terminée.",
|
|
498618
|
+
"blunTui.detach.moveFailed": "Impossible de passer la commande en arrière-plan : {error}",
|
|
498619
|
+
"blunTui.detach.movedTranscript": "Commande passée en arrière-plan.",
|
|
498620
|
+
"blunTui.detach.movedView": "Commande passée en arrière-plan. Consultez /tasks.",
|
|
498621
|
+
"blunTui.detach.noForeground": "Aucune tâche en cours au premier plan.",
|
|
498622
|
+
"blunTui.detach.listFailed": "Impossible de répertorier les tâches : {error}",
|
|
498623
|
+
"blunTui.detach.taskFailed": "Impossible de passer la tâche {taskId} en arrière-plan : {error}",
|
|
498624
|
+
"blunTui.detach.finished.one": "La tâche est déjà terminée.",
|
|
498625
|
+
"blunTui.detach.finished.other": "Les tâches sont déjà terminées.",
|
|
498626
|
+
"blunTui.detach.moved.one": "{count} tâche passée en arrière-plan.",
|
|
498627
|
+
"blunTui.detach.moved.other": "{count} tâches passées en arrière-plan.",
|
|
498628
|
+
"blunTui.detach.partial": "{detached} tâches sur {total} passées en arrière-plan.",
|
|
498629
|
+
"blunTui.detach.viewSuffix": "Consultez /tasks.",
|
|
498630
|
+
"blunTui.startup.flagsFailed": "Impossible d’appliquer les options de démarrage : {error}",
|
|
498631
|
+
"blunTui.notification.approvalRequired": "Approbation BLUN requise",
|
|
498632
|
+
"blunTui.notification.answerRequired": "BLUN attend votre réponse",
|
|
498633
|
+
"blunTui.telegram.fallbackDelivered": "Réponse envoyée automatiquement sur Telegram (solution de secours).",
|
|
498634
|
+
"blunTui.telegram.attachDisabled": "Connexion à Telegram désactivée via BLUN_TELEGRAM_ATTACH=off — mode headless actif.",
|
|
498635
|
+
"blunTui.telegram.noToken": "Connexion à Telegram\xA0: aucun jeton détecté — mode headless actif.",
|
|
498636
|
+
"blunTui.telegram.attached": "Canal Telegram connecté (PID de lease\xA0: {pid}) — les messages apparaissent dans cette fenêtre.",
|
|
498637
|
+
"blunTui.auto.status": "Auto\xA0: {label}",
|
|
498638
|
+
"blunTui.activity.thinking": "{name} réfléchit…",
|
|
498639
|
+
"blunTui.activity.working": "{name} travaille…",
|
|
498640
|
+
"blunTui.activity.composing": "travail en cours...",
|
|
498641
|
+
"blunTui.activity.tokens": "jetons"
|
|
498642
|
+
},
|
|
498643
|
+
sv: {
|
|
498644
|
+
"blunTui.provider.modelAdded.one": "{providerName} · +{count} modell.",
|
|
498645
|
+
"blunTui.provider.modelAdded.other": "{providerName} · +{count} modeller.",
|
|
498646
|
+
"blunTui.provider.refreshSkipped": "Uppdateringen av {provider} hoppades över: {reason}",
|
|
498647
|
+
"blunTui.warning": "Varning: {warning}",
|
|
498648
|
+
"blunTui.startup.sessionNotFound": "Sessionen ”{sessionId}” hittades inte.",
|
|
498649
|
+
"blunTui.startup.sessionDifferentDirectory": "Sessionen ”{sessionId}” skapades i en annan arbetskatalog.",
|
|
498650
|
+
"blunTui.startup.noSessionsToContinue": "Det finns inga sessioner att återuppta i ”{workDir}”; en ny session startas.",
|
|
498651
|
+
"blunTui.startup.sessionNotInitialized": "Sessionen initierades inte vid start.",
|
|
498652
|
+
"blunTui.input.replayBlocked": "Det går inte att skicka indata medan sessionshistoriken spelas upp.",
|
|
498653
|
+
"blunTui.shell.noSession": "Det finns ingen aktiv session för skalkommandot.",
|
|
498654
|
+
"blunTui.shell.runFailed": "Skalkommandot misslyckades: {error}",
|
|
498655
|
+
"blunTui.shell.cancelFailed": "Det gick inte att avbryta skalkommandot: {error}",
|
|
498656
|
+
"blunTui.channel.steerFailed": "Det gick inte att lägga till kanalmeddelandet i det pågående svaret: {error}",
|
|
498657
|
+
"blunTui.session.sendFailed": "Det gick inte att skicka: {error}",
|
|
498658
|
+
"blunTui.media.imageUnsupported": "Den aktuella modellen stöder inte bildindata.",
|
|
498659
|
+
"blunTui.media.videoUnsupported": "Den aktuella modellen stöder inte videoindata.",
|
|
498660
|
+
"blunTui.skill.failed": "Skill ”{skillName}” misslyckades: {error}",
|
|
498661
|
+
"blunTui.pluginCommand.failed": "Kommandot ”{command}” misslyckades: {error}",
|
|
498662
|
+
"blunTui.steer.failed": "Det gick inte att styra om svaret: {error}",
|
|
498663
|
+
"blunTui.session.otherWorkDir": "Den aktuella sessionen finns i en annan arbetskatalog.",
|
|
498664
|
+
"blunTui.session.resumeCommand": "Kör följande för att återuppta den: {command}",
|
|
498665
|
+
"blunTui.clipboard.commandCopied": "Kommandot kopierades till urklipp",
|
|
498666
|
+
"blunTui.clipboard.commandCopyFailed": "Det gick inte att kopiera kommandot till urklipp",
|
|
498667
|
+
"blunTui.session.alreadyCurrent": "Den här sessionen är redan aktiv.",
|
|
498668
|
+
"blunTui.session.switchStreamingBlocked": "Det går inte att byta session medan ett svar genereras. Tryck först på Esc eller Ctrl-C.",
|
|
498669
|
+
"blunTui.session.switchReplayBlocked": "Det går inte att byta session medan historiken spelas upp.",
|
|
498670
|
+
"blunTui.session.resumeFailed": "Det gick inte att återuppta sessionen {sessionId}: {error}",
|
|
498671
|
+
"blunTui.session.resumed": "Sessionen återupptogs ({sessionId}).",
|
|
498672
|
+
"blunTui.session.replayFailed": "Det gick inte att spela upp sessionshistoriken: {error}",
|
|
498673
|
+
"blunTui.session.createReplayBlocked": "Det går inte att starta en ny session medan historiken spelas upp.",
|
|
498674
|
+
"blunTui.session.createFailed": "Det gick inte att starta en ny session: {error}",
|
|
498675
|
+
"blunTui.session.postCreateFailed": "Det gick inte att konfigurera den nya sessionen: {error}",
|
|
498676
|
+
"blunTui.session.started": "En ny session startades ({sessionId}).",
|
|
498677
|
+
"blunTui.error": "Fel: {message}",
|
|
498678
|
+
"blunTui.login.title": "Logga in på BLUN",
|
|
498679
|
+
"blunTui.login.hint": "Tryck på Ctrl-C för att avbryta",
|
|
498680
|
+
"blunTui.login.waiting": "Väntar på auktorisering…",
|
|
498681
|
+
"blunTui.detach.noShell": "Inget skalkommando körs.",
|
|
498682
|
+
"blunTui.detach.shellStarting": "Kommandot håller fortfarande på att startas – försök igen.",
|
|
498683
|
+
"blunTui.detach.shellFinished": "Kommandot är redan slutfört.",
|
|
498684
|
+
"blunTui.detach.moveFailed": "Det gick inte att flytta kommandot till bakgrunden: {error}",
|
|
498685
|
+
"blunTui.detach.movedTranscript": "Flyttades till bakgrunden.",
|
|
498686
|
+
"blunTui.detach.movedView": "Flyttades till bakgrunden. Visa med /tasks.",
|
|
498687
|
+
"blunTui.detach.noForeground": "Ingen uppgift körs i förgrunden.",
|
|
498688
|
+
"blunTui.detach.listFailed": "Det gick inte att lista uppgifterna: {error}",
|
|
498689
|
+
"blunTui.detach.taskFailed": "Det gick inte att flytta uppgiften {taskId} till bakgrunden: {error}",
|
|
498690
|
+
"blunTui.detach.finished.one": "Uppgiften är redan slutförd.",
|
|
498691
|
+
"blunTui.detach.finished.other": "Uppgifterna är redan slutförda.",
|
|
498692
|
+
"blunTui.detach.moved.one": "{count} uppgift flyttades till bakgrunden.",
|
|
498693
|
+
"blunTui.detach.moved.other": "{count} uppgifter flyttades till bakgrunden.",
|
|
498694
|
+
"blunTui.detach.partial": "{detached} av {total} uppgifter flyttades till bakgrunden.",
|
|
498695
|
+
"blunTui.detach.viewSuffix": "Visa med /tasks.",
|
|
498696
|
+
"blunTui.startup.flagsFailed": "Det gick inte att tillämpa startalternativen: {error}",
|
|
498697
|
+
"blunTui.notification.approvalRequired": "BLUN-godkännande krävs",
|
|
498698
|
+
"blunTui.notification.answerRequired": "BLUN behöver ditt svar",
|
|
498699
|
+
"blunTui.telegram.fallbackDelivered": "Svaret skickades automatiskt till Telegram (reservlösning).",
|
|
498700
|
+
"blunTui.telegram.attachDisabled": "Telegram-anslutningen inaktiverades via BLUN_TELEGRAM_ATTACH=off — headless-läget är aktivt.",
|
|
498701
|
+
"blunTui.telegram.noToken": "Telegram-anslutning: ingen token hittades — headless-läget är aktivt.",
|
|
498702
|
+
"blunTui.telegram.attached": "Telegram-kanalen är ansluten (lease-PID {pid}) — meddelanden visas i det här fönstret.",
|
|
498703
|
+
"blunTui.auto.status": "Automatiskt: {label}",
|
|
498704
|
+
"blunTui.activity.thinking": "{name} tänker…",
|
|
498705
|
+
"blunTui.activity.working": "{name} arbetar…",
|
|
498706
|
+
"blunTui.activity.composing": "arbetar...",
|
|
498707
|
+
"blunTui.activity.tokens": "token"
|
|
498708
|
+
},
|
|
498709
|
+
cs: {
|
|
498710
|
+
"blunTui.provider.modelAdded.one": "{providerName} · +{count} model.",
|
|
498711
|
+
"blunTui.provider.modelAdded.other": "{providerName} · nové modely: +{count}.",
|
|
498712
|
+
"blunTui.provider.refreshSkipped": "Přeskočeno obnovení {provider}: {reason}",
|
|
498713
|
+
"blunTui.warning": "Upozornění: {warning}",
|
|
498714
|
+
"blunTui.startup.sessionNotFound": "Relace \"{sessionId}\" nebyla nalezena.",
|
|
498715
|
+
"blunTui.startup.sessionDifferentDirectory": "Relace \"{sessionId}\" byla vytvořena v jiném adresáři.",
|
|
498716
|
+
"blunTui.startup.noSessionsToContinue": "V adresáři \"{workDir}\" nejsou žádné relace, ve kterých by bylo možné pokračovat; spouští se nová relace.",
|
|
498717
|
+
"blunTui.startup.sessionNotInitialized": "Relace při spuštění nebyla inicializována.",
|
|
498718
|
+
"blunTui.input.replayBlocked": "Nelze odeslat vstup během přehrávání historie relace.",
|
|
498719
|
+
"blunTui.shell.noSession": "Žádná aktivní relace pro příkaz shellu.",
|
|
498720
|
+
"blunTui.shell.runFailed": "Příkaz shellu selhal: {error}",
|
|
498721
|
+
"blunTui.shell.cancelFailed": "Selhalo zrušení příkazu shellu: {error}",
|
|
498722
|
+
"blunTui.channel.steerFailed": "Předání zprávy z kanálu do probíhající odpovědi selhalo: {error}",
|
|
498723
|
+
"blunTui.session.sendFailed": "Selhalo odeslání: {error}",
|
|
498724
|
+
"blunTui.media.imageUnsupported": "Aktuální model nepodporuje vstup obrázku.",
|
|
498725
|
+
"blunTui.media.videoUnsupported": "Aktuální model nepodporuje vstup videa.",
|
|
498726
|
+
"blunTui.skill.failed": "Dovednost \"{skillName}\" selhala: {error}",
|
|
498727
|
+
"blunTui.pluginCommand.failed": "Příkaz \"{command}\" selhal: {error}",
|
|
498728
|
+
"blunTui.steer.failed": "Doplnění pokynu selhalo: {error}",
|
|
498729
|
+
"blunTui.session.otherWorkDir": "Aktuální relace je v jiném pracovním adresáři.",
|
|
498730
|
+
"blunTui.session.resumeCommand": "Chcete-li pokračovat, spusťte: {command}",
|
|
498731
|
+
"blunTui.clipboard.commandCopied": "Příkaz zkopírován do schránky",
|
|
498732
|
+
"blunTui.clipboard.commandCopyFailed": "Selhalo kopírování příkazu do schránky",
|
|
498733
|
+
"blunTui.session.alreadyCurrent": "Již jste v této relaci.",
|
|
498734
|
+
"blunTui.session.switchStreamingBlocked": "Nelze přepínat relace během streamování — nejdříve stiskněte Esc nebo Ctrl-C.",
|
|
498735
|
+
"blunTui.session.switchReplayBlocked": "Nelze přepínat relace během přehrávání historie.",
|
|
498736
|
+
"blunTui.session.resumeFailed": "Selhalo obnovení relace {sessionId}: {error}",
|
|
498737
|
+
"blunTui.session.resumed": "Obnovena relace ({sessionId}).",
|
|
498738
|
+
"blunTui.session.replayFailed": "Selhalo přehrávání historie relace: {error}",
|
|
498739
|
+
"blunTui.session.createReplayBlocked": "Nelze spustit novou relaci během přehrávání historie.",
|
|
498740
|
+
"blunTui.session.createFailed": "Selhalo spuštění nové relace: {error}",
|
|
498741
|
+
"blunTui.session.postCreateFailed": "Selhalo nastavení po vytvoření: {error}",
|
|
498742
|
+
"blunTui.session.started": "Spuštěna nová relace ({sessionId}).",
|
|
498743
|
+
"blunTui.error": "Chyba: {message}",
|
|
498744
|
+
"blunTui.login.title": "Přihlaste se do BLUN",
|
|
498745
|
+
"blunTui.login.hint": "Stiskněte Ctrl-C pro zrušení",
|
|
498746
|
+
"blunTui.login.waiting": "Čekání na autorizaci…",
|
|
498747
|
+
"blunTui.detach.noShell": "Žádný příkaz shellu není spuštěn.",
|
|
498748
|
+
"blunTui.detach.shellStarting": "Příkaz se stále spouští — zkuste znovu.",
|
|
498749
|
+
"blunTui.detach.shellFinished": "Příkaz již skončil.",
|
|
498750
|
+
"blunTui.detach.moveFailed": "Selhalo přesunutí na pozadí: {error}",
|
|
498751
|
+
"blunTui.detach.movedTranscript": "Přesunuto na pozadí.",
|
|
498752
|
+
"blunTui.detach.movedView": "Přesunuto na pozadí. Zobrazíte příkazem /tasks.",
|
|
498753
|
+
"blunTui.detach.noForeground": "Žádný úkol na popředí není spuštěn.",
|
|
498754
|
+
"blunTui.detach.listFailed": "Selhalo vypsání úkolů: {error}",
|
|
498755
|
+
"blunTui.detach.taskFailed": "Přesunutí úlohy {taskId} na pozadí selhalo: {error}",
|
|
498756
|
+
"blunTui.detach.finished.one": "Úkol již skončil.",
|
|
498757
|
+
"blunTui.detach.finished.other": "Úkoly již skončily.",
|
|
498758
|
+
"blunTui.detach.moved.one": "Přesunut {count} úkol na pozadí.",
|
|
498759
|
+
"blunTui.detach.moved.other": "Úkoly přesunuté na pozadí: {count}.",
|
|
498760
|
+
"blunTui.detach.partial": "Přesunuto {detached} z {total} úkolů na pozadí.",
|
|
498761
|
+
"blunTui.detach.viewSuffix": "/tasks k zobrazení.",
|
|
498762
|
+
"blunTui.startup.flagsFailed": "Nepodařilo se použít spouštěcí příznaky: {error}",
|
|
498763
|
+
"blunTui.notification.approvalRequired": "Vyžadováno schválení BLUN",
|
|
498764
|
+
"blunTui.notification.answerRequired": "BLUN potřebuje vaši odpověď",
|
|
498765
|
+
"blunTui.telegram.fallbackDelivered": "Odpověď byla automaticky doručena do Telegramu (náhradním způsobem).",
|
|
498766
|
+
"blunTui.telegram.attachDisabled": "Připojení Telegramu je zakázáno nastavením BLUN_TELEGRAM_ATTACH=off — aktivní je režim bez uživatelského rozhraní.",
|
|
498767
|
+
"blunTui.telegram.noToken": "Připojení Telegramu: nebyl nalezen žádný token — aktivní je režim bez uživatelského rozhraní.",
|
|
498768
|
+
"blunTui.telegram.attached": "Kanál Telegramu je připojen (PID držitele připojení {pid}) — zprávy se zobrazují v tomto okně.",
|
|
498769
|
+
"blunTui.auto.status": "Automaticky: {label}",
|
|
498770
|
+
"blunTui.activity.thinking": "{name} přemýšlí…",
|
|
498771
|
+
"blunTui.activity.working": "{name} pracuje…",
|
|
498772
|
+
"blunTui.activity.composing": "pracuje…",
|
|
498773
|
+
"blunTui.activity.tokens": "Tokeny"
|
|
498774
|
+
}
|
|
498775
|
+
});
|
|
498776
|
+
//#endregion
|
|
498094
498777
|
//#region src/tui/components/panes/btw-panel.ts
|
|
498095
498778
|
const MIN_COLLAPSED_PANEL_LINES = 3;
|
|
498096
498779
|
var BtwPanelComponent = class {
|
|
@@ -498101,6 +498784,8 @@ var BtwPanelComponent = class {
|
|
|
498101
498784
|
followTail = true;
|
|
498102
498785
|
scrollTop = 0;
|
|
498103
498786
|
maxScrollTop = 0;
|
|
498787
|
+
spinnerFrame = 0;
|
|
498788
|
+
liveStatusTimer;
|
|
498104
498789
|
constructor(options) {
|
|
498105
498790
|
this.options = options;
|
|
498106
498791
|
}
|
|
@@ -498112,10 +498797,12 @@ var BtwPanelComponent = class {
|
|
|
498112
498797
|
this.transientNotices.length = 0;
|
|
498113
498798
|
this.turns.push({
|
|
498114
498799
|
prompt: normalized,
|
|
498800
|
+
startedAtMs: Date.now(),
|
|
498115
498801
|
answer: "",
|
|
498116
498802
|
thinking: "",
|
|
498117
498803
|
phase: "running"
|
|
498118
498804
|
});
|
|
498805
|
+
this.startLiveStatusTimer();
|
|
498119
498806
|
this.options.onPrompt(normalized);
|
|
498120
498807
|
}
|
|
498121
498808
|
addTransientNotice(message) {
|
|
@@ -498132,31 +498819,48 @@ var BtwPanelComponent = class {
|
|
|
498132
498819
|
if (turn === void 0) return;
|
|
498133
498820
|
turn.thinking += delta;
|
|
498134
498821
|
}
|
|
498822
|
+
restartCurrentTurn(notice) {
|
|
498823
|
+
const turn = this.currentTurn();
|
|
498824
|
+
if (turn === void 0 || turn.phase !== "running") return;
|
|
498825
|
+
turn.startedAtMs = Date.now();
|
|
498826
|
+
turn.answer = "";
|
|
498827
|
+
turn.thinking = "";
|
|
498828
|
+
turn.error = void 0;
|
|
498829
|
+
this.transientNotices.length = 0;
|
|
498830
|
+
this.transientNotices.push(notice);
|
|
498831
|
+
}
|
|
498135
498832
|
markDone(resultSummary) {
|
|
498136
498833
|
const turn = this.currentTurn();
|
|
498137
498834
|
if (turn === void 0) return;
|
|
498138
498835
|
if (turn.answer.trim().length === 0 && resultSummary !== void 0) turn.answer = resultSummary;
|
|
498139
498836
|
this.transientNotices.length = 0;
|
|
498140
498837
|
turn.phase = "done";
|
|
498838
|
+
this.stopLiveStatusTimer();
|
|
498141
498839
|
}
|
|
498142
498840
|
markFailed(error) {
|
|
498143
498841
|
const turn = this.currentTurn();
|
|
498144
498842
|
if (turn === void 0 || turn.phase !== "running") {
|
|
498145
498843
|
this.turns.push({
|
|
498146
498844
|
prompt: "",
|
|
498845
|
+
startedAtMs: Date.now(),
|
|
498147
498846
|
answer: "",
|
|
498148
498847
|
thinking: "",
|
|
498149
498848
|
error,
|
|
498150
498849
|
phase: "failed"
|
|
498151
498850
|
});
|
|
498152
498851
|
this.transientNotices.length = 0;
|
|
498852
|
+
this.stopLiveStatusTimer();
|
|
498153
498853
|
return;
|
|
498154
498854
|
}
|
|
498155
498855
|
turn.error = error;
|
|
498156
498856
|
this.transientNotices.length = 0;
|
|
498157
498857
|
turn.phase = "failed";
|
|
498858
|
+
this.stopLiveStatusTimer();
|
|
498158
498859
|
}
|
|
498159
498860
|
invalidate() {}
|
|
498861
|
+
dispose() {
|
|
498862
|
+
this.stopLiveStatusTimer();
|
|
498863
|
+
}
|
|
498160
498864
|
render(width) {
|
|
498161
498865
|
const safeWidth = Math.max(4, width);
|
|
498162
498866
|
const contentWidth = Math.max(1, safeWidth - 4);
|
|
@@ -498229,7 +498933,8 @@ var BtwPanelComponent = class {
|
|
|
498229
498933
|
const thinkingLines = new Text(chalk.hex(currentTheme.palette.textDim)(thinking), 0, 0).render(width);
|
|
498230
498934
|
const visibleThinking = thinkingLines.length > 2 ? thinkingLines.slice(thinkingLines.length - 2) : thinkingLines;
|
|
498231
498935
|
lines.push(...visibleThinking);
|
|
498232
|
-
}
|
|
498936
|
+
}
|
|
498937
|
+
if (turn.phase === "running" && turn.error === void 0) lines.push(this.renderLiveStatus(turn));
|
|
498233
498938
|
if (turn.error !== void 0) {
|
|
498234
498939
|
const error = chalk.hex(currentTheme.palette.error)(turn.error);
|
|
498235
498940
|
lines.push(...new Text(error, 0, 0).render(width));
|
|
@@ -498246,6 +498951,26 @@ var BtwPanelComponent = class {
|
|
|
498246
498951
|
currentTurn() {
|
|
498247
498952
|
return this.turns.at(-1);
|
|
498248
498953
|
}
|
|
498954
|
+
renderLiveStatus(turn) {
|
|
498955
|
+
const elapsedSeconds = Math.max(0, Math.floor((Date.now() - turn.startedAtMs) / 1e3));
|
|
498956
|
+
const outputTokens = estimateLiveOutputTokens(turn.thinking + turn.answer);
|
|
498957
|
+
const frame = BLUN_SPINNER_FRAMES[this.spinnerFrame] ?? BLUN_SPINNER_FRAMES[0];
|
|
498958
|
+
const label = uiText("blunTui.activity.thinking", { name: "BTW" });
|
|
498959
|
+
const metrics = `(${formatLiveElapsed(elapsedSeconds)} · ↓ ~${formatLiveTokenCount(outputTokens)} ${uiText("blunTui.activity.tokens")})`;
|
|
498960
|
+
return chalk.hex(currentTheme.palette.accent)(`${frame} `) + chalk.hex(currentTheme.palette.accent).bold(label) + " " + chalk.hex(currentTheme.palette.text)(metrics);
|
|
498961
|
+
}
|
|
498962
|
+
startLiveStatusTimer() {
|
|
498963
|
+
if (this.liveStatusTimer !== void 0) return;
|
|
498964
|
+
this.liveStatusTimer = setInterval(() => {
|
|
498965
|
+
this.spinnerFrame = (this.spinnerFrame + 1) % BLUN_SPINNER_FRAMES.length;
|
|
498966
|
+
this.options.requestRender();
|
|
498967
|
+
}, 120);
|
|
498968
|
+
}
|
|
498969
|
+
stopLiveStatusTimer() {
|
|
498970
|
+
if (this.liveStatusTimer === void 0) return;
|
|
498971
|
+
clearInterval(this.liveStatusTimer);
|
|
498972
|
+
this.liveStatusTimer = void 0;
|
|
498973
|
+
}
|
|
498249
498974
|
isRunning() {
|
|
498250
498975
|
return this.currentTurn()?.phase === "running";
|
|
498251
498976
|
}
|
|
@@ -498312,6 +499037,7 @@ function formatHookResultBody(event) {
|
|
|
498312
499037
|
}
|
|
498313
499038
|
//#endregion
|
|
498314
499039
|
//#region src/tui/controllers/btw-panel.ts
|
|
499040
|
+
const BTW_INACTIVITY_TIMEOUT_MS = 12e4;
|
|
498315
499041
|
var BtwPanelController = class {
|
|
498316
499042
|
host;
|
|
498317
499043
|
active;
|
|
@@ -498325,13 +499051,16 @@ var BtwPanelController = class {
|
|
|
498325
499051
|
markdownTheme: createMarkdownTheme(),
|
|
498326
499052
|
canUseScrollKeys: () => this.host.state.editor.getText().length === 0,
|
|
498327
499053
|
terminalRows: () => this.host.state.terminal.rows,
|
|
499054
|
+
requestRender: () => this.host.state.ui.requestRender(),
|
|
498328
499055
|
onPrompt: (prompt) => {
|
|
498329
|
-
this.
|
|
499056
|
+
this.promptPanel(panel, prompt);
|
|
498330
499057
|
}
|
|
498331
499058
|
});
|
|
498332
499059
|
this.active = {
|
|
498333
499060
|
agentId,
|
|
498334
|
-
panel
|
|
499061
|
+
panel,
|
|
499062
|
+
prompt: "",
|
|
499063
|
+
retryCount: 0
|
|
498335
499064
|
};
|
|
498336
499065
|
this.panelsByAgentId.set(agentId, panel);
|
|
498337
499066
|
this.mount(panel);
|
|
@@ -498340,6 +499069,8 @@ var BtwPanelController = class {
|
|
|
498340
499069
|
clear() {
|
|
498341
499070
|
const active = this.active;
|
|
498342
499071
|
if (active !== void 0 && this.shouldCancelOnUnmount(active.panel)) this.cancelAgent(active.agentId);
|
|
499072
|
+
for (const panel of this.panelsByAgentId.values()) panel.dispose();
|
|
499073
|
+
this.clearInactivityTimer(active);
|
|
498343
499074
|
this.active = void 0;
|
|
498344
499075
|
this.panelsByAgentId.clear();
|
|
498345
499076
|
this.host.state.btwPanelContainer.clear();
|
|
@@ -498382,19 +499113,23 @@ var BtwPanelController = class {
|
|
|
498382
499113
|
if (panel === void 0) return false;
|
|
498383
499114
|
switch (event.type) {
|
|
498384
499115
|
case "assistant.delta":
|
|
499116
|
+
this.clearInactivityTimer(this.activeForAgent(event.agentId));
|
|
498385
499117
|
panel.appendAnswer(event.delta);
|
|
498386
499118
|
this.host.state.ui.requestRender();
|
|
498387
499119
|
return true;
|
|
498388
499120
|
case "thinking.delta":
|
|
498389
499121
|
panel.appendThinking(event.delta);
|
|
499122
|
+
this.armInactivityTimer(this.activeForAgent(event.agentId));
|
|
498390
499123
|
this.host.state.ui.requestRender();
|
|
498391
499124
|
return true;
|
|
498392
499125
|
case "hook.result":
|
|
499126
|
+
this.clearInactivityTimer(this.activeForAgent(event.agentId));
|
|
498393
499127
|
panel.appendAnswer(formatHookResultPlain(event));
|
|
498394
499128
|
this.host.state.ui.requestRender();
|
|
498395
499129
|
return true;
|
|
498396
499130
|
case "turn.ended":
|
|
498397
|
-
|
|
499131
|
+
this.clearInactivityTimer(this.activeForAgent(event.agentId));
|
|
499132
|
+
if (event.reason === "completed") panel.markDone(uiText("eventPayload.modelEmptyResponse"));
|
|
498398
499133
|
else panel.markFailed(formatBtwTurnEnd(event));
|
|
498399
499134
|
this.host.state.ui.requestRender();
|
|
498400
499135
|
return true;
|
|
@@ -498411,7 +499146,9 @@ var BtwPanelController = class {
|
|
|
498411
499146
|
}
|
|
498412
499147
|
close(panel) {
|
|
498413
499148
|
if (!this.host.state.btwPanelContainer.children.includes(panel)) return;
|
|
499149
|
+
this.clearInactivityTimer(this.active?.panel === panel ? this.active : void 0);
|
|
498414
499150
|
this.unregister(panel);
|
|
499151
|
+
panel.dispose();
|
|
498415
499152
|
this.host.state.btwPanelContainer.clear();
|
|
498416
499153
|
this.host.state.editor.connectedAbove = false;
|
|
498417
499154
|
this.host.state.ui.setFocus(this.host.state.editor);
|
|
@@ -498426,6 +499163,14 @@ var BtwPanelController = class {
|
|
|
498426
499163
|
active.panel.addTransientNotice(uiText("btw.busy"));
|
|
498427
499164
|
this.host.state.ui.requestRender();
|
|
498428
499165
|
}
|
|
499166
|
+
promptPanel(panel, prompt) {
|
|
499167
|
+
const active = this.active;
|
|
499168
|
+
if (active === void 0 || active.panel !== panel) return;
|
|
499169
|
+
active.prompt = prompt;
|
|
499170
|
+
active.retryCount = 0;
|
|
499171
|
+
this.promptAgent(active.agentId, prompt, panel);
|
|
499172
|
+
this.armInactivityTimer(active);
|
|
499173
|
+
}
|
|
498429
499174
|
promptAgent(agentId, prompt, panel) {
|
|
498430
499175
|
const session = this.host.session;
|
|
498431
499176
|
if (session === void 0) {
|
|
@@ -498434,16 +499179,76 @@ var BtwPanelController = class {
|
|
|
498434
499179
|
return;
|
|
498435
499180
|
}
|
|
498436
499181
|
this.withInteractiveAgent(agentId, () => session.prompt(prompt)).catch((error) => {
|
|
499182
|
+
if (this.panelsByAgentId.get(agentId) !== panel) return;
|
|
499183
|
+
this.clearInactivityTimer(this.activeForAgent(agentId));
|
|
498437
499184
|
panel.markFailed(uiText("btw.error.send", { error: formatErrorMessage$2(error) }));
|
|
498438
499185
|
this.host.state.ui.requestRender();
|
|
498439
499186
|
});
|
|
498440
499187
|
}
|
|
498441
499188
|
async cancelAgent(agentId) {
|
|
498442
499189
|
const session = this.host.session;
|
|
498443
|
-
if (session === void 0) return;
|
|
498444
|
-
|
|
498445
|
-
this.
|
|
498446
|
-
|
|
499190
|
+
if (session === void 0) return noActiveSessionMessage();
|
|
499191
|
+
try {
|
|
499192
|
+
await this.withInteractiveAgent(agentId, () => session.cancel());
|
|
499193
|
+
return;
|
|
499194
|
+
} catch (error) {
|
|
499195
|
+
const message = formatErrorMessage$2(error);
|
|
499196
|
+
this.host.showError(uiText("btw.error.cancel", { error: message }));
|
|
499197
|
+
return message;
|
|
499198
|
+
}
|
|
499199
|
+
}
|
|
499200
|
+
activeForAgent(agentId) {
|
|
499201
|
+
return this.active?.agentId === agentId ? this.active : void 0;
|
|
499202
|
+
}
|
|
499203
|
+
armInactivityTimer(active) {
|
|
499204
|
+
if (active === void 0 || !active.panel.isRunning()) return;
|
|
499205
|
+
this.clearInactivityTimer(active);
|
|
499206
|
+
active.inactivityTimer = setTimeout(() => {
|
|
499207
|
+
active.inactivityTimer = void 0;
|
|
499208
|
+
this.handleInactivity(active);
|
|
499209
|
+
}, BTW_INACTIVITY_TIMEOUT_MS);
|
|
499210
|
+
active.inactivityTimer.unref?.();
|
|
499211
|
+
}
|
|
499212
|
+
clearInactivityTimer(active) {
|
|
499213
|
+
if (active?.inactivityTimer === void 0) return;
|
|
499214
|
+
clearTimeout(active.inactivityTimer);
|
|
499215
|
+
active.inactivityTimer = void 0;
|
|
499216
|
+
}
|
|
499217
|
+
async handleInactivity(active) {
|
|
499218
|
+
if (this.active !== active || !active.panel.isRunning()) return;
|
|
499219
|
+
const staleAgentId = active.agentId;
|
|
499220
|
+
this.panelsByAgentId.delete(staleAgentId);
|
|
499221
|
+
const cancelError = await this.cancelAgent(staleAgentId);
|
|
499222
|
+
if (this.active !== active || !active.panel.isRunning()) return;
|
|
499223
|
+
if (cancelError !== void 0) {
|
|
499224
|
+
active.panel.markFailed(uiText("btw.error.cancel", { error: cancelError }));
|
|
499225
|
+
this.host.state.ui.requestRender();
|
|
499226
|
+
return;
|
|
499227
|
+
}
|
|
499228
|
+
if (active.retryCount >= 1) {
|
|
499229
|
+
active.panel.markFailed(uiText("btw.timeout"));
|
|
499230
|
+
this.host.state.ui.requestRender();
|
|
499231
|
+
return;
|
|
499232
|
+
}
|
|
499233
|
+
active.retryCount += 1;
|
|
499234
|
+
active.panel.restartCurrentTurn(uiText("btw.retrying"));
|
|
499235
|
+
try {
|
|
499236
|
+
const session = this.host.session;
|
|
499237
|
+
if (session === void 0) throw new Error(noActiveSessionMessage());
|
|
499238
|
+
const nextAgentId = await session.startBtw();
|
|
499239
|
+
if (this.active !== active || !active.panel.isRunning()) {
|
|
499240
|
+
await this.cancelAgent(nextAgentId);
|
|
499241
|
+
return;
|
|
499242
|
+
}
|
|
499243
|
+
active.agentId = nextAgentId;
|
|
499244
|
+
this.panelsByAgentId.set(nextAgentId, active.panel);
|
|
499245
|
+
this.promptAgent(nextAgentId, active.prompt, active.panel);
|
|
499246
|
+
this.armInactivityTimer(active);
|
|
499247
|
+
this.host.state.ui.requestRender();
|
|
499248
|
+
} catch (error) {
|
|
499249
|
+
active.panel.markFailed(uiText("btw.error.start", { error: formatErrorMessage$2(error) }));
|
|
499250
|
+
this.host.state.ui.requestRender();
|
|
499251
|
+
}
|
|
498447
499252
|
}
|
|
498448
499253
|
shouldCancelOnUnmount(panel) {
|
|
498449
499254
|
return panel.isRunning() || panel.isEmpty();
|
|
@@ -498491,6 +499296,7 @@ var ChannelQueueDeadlineController = class {
|
|
|
498491
499296
|
if (this.deadlineTimer === void 0 && !this.interruptionRequested) this.scheduleDeadline(CHANNEL_QUEUE_DEADLINE_MS);
|
|
498492
499297
|
}
|
|
498493
499298
|
requestDeliveryAtSafePoint() {
|
|
499299
|
+
if (this.retainReleaseWhileDeliveryIsInFlight()) return;
|
|
498494
499300
|
if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) {
|
|
498495
499301
|
this.requestInterruption();
|
|
498496
499302
|
return;
|
|
@@ -498498,12 +499304,18 @@ var ChannelQueueDeadlineController = class {
|
|
|
498498
499304
|
this.requestDelivery();
|
|
498499
499305
|
}
|
|
498500
499306
|
requestDeliveryNow() {
|
|
499307
|
+
if (this.retainReleaseWhileDeliveryIsInFlight()) return;
|
|
498501
499308
|
if (this.host.hasWaitingWork() && !this.host.canDeliverWork()) {
|
|
498502
499309
|
this.requestInterruption();
|
|
498503
499310
|
return;
|
|
498504
499311
|
}
|
|
498505
499312
|
this.requestDelivery();
|
|
498506
499313
|
}
|
|
499314
|
+
retainReleaseWhileDeliveryIsInFlight() {
|
|
499315
|
+
if (this.disposed || !this.deliveryInFlight || !this.host.hasWaitingWork()) return false;
|
|
499316
|
+
this.pendingReleaseCount += 1;
|
|
499317
|
+
return true;
|
|
499318
|
+
}
|
|
498507
499319
|
dispose() {
|
|
498508
499320
|
this.disposed = true;
|
|
498509
499321
|
this.pendingReleaseCount = 0;
|
|
@@ -502987,6 +503799,7 @@ var SessionEventHandler = class {
|
|
|
502987
503799
|
synthetic: event.synthetic
|
|
502988
503800
|
};
|
|
502989
503801
|
const matchedCall = streamingUI.completeToolResult(event.toolCallId, resultData);
|
|
503802
|
+
if (matchedCall?.name === "GetMedia" && event.isError !== true) this.host.runChannelMediaFallback(event.output);
|
|
502990
503803
|
this.subAgentEventHandler.handleAgentSwarmToolResult(event.toolCallId, resultData, event.isError === true);
|
|
502991
503804
|
if (matchedCall !== void 0 && matchedCall.name === "TodoList" && !event.isError) {
|
|
502992
503805
|
const rawTodos = matchedCall.args.todos;
|
|
@@ -503375,7 +504188,7 @@ var SessionEventHandler = class {
|
|
|
503375
504188
|
}
|
|
503376
504189
|
handleCompactionEnd(event) {
|
|
503377
504190
|
this.host.setAppState({ contextTokens: event.projectedContextTokens ?? event.result.tokensAfter });
|
|
503378
|
-
this.host.streamingUI.endCompaction(event.result.tokensBefore, event.result.tokensAfter);
|
|
504191
|
+
this.host.streamingUI.endCompaction(event.result.tokensBefore, event.result.tokensAfter, event.stageCount);
|
|
503379
504192
|
this.lastCompactionInstruction = void 0;
|
|
503380
504193
|
this.finishCompaction();
|
|
503381
504194
|
}
|
|
@@ -506335,7 +507148,7 @@ var StreamingUIController = class {
|
|
|
506335
507148
|
this._activeCompactionBlock.markDone();
|
|
506336
507149
|
this._activeCompactionBlock = void 0;
|
|
506337
507150
|
}
|
|
506338
|
-
const block = new CompactionComponent(state.ui, instruction, currentWorkingTip()?.text,
|
|
507151
|
+
const block = new CompactionComponent(state.ui, instruction, currentWorkingTip()?.text, true);
|
|
506339
507152
|
this._activeCompactionBlock = block;
|
|
506340
507153
|
state.transcriptContainer.addChild(block);
|
|
506341
507154
|
state.ui.requestRender();
|
|
@@ -506347,11 +507160,11 @@ var StreamingUIController = class {
|
|
|
506347
507160
|
block.setProgress(progress);
|
|
506348
507161
|
this.host.state.ui.requestRender();
|
|
506349
507162
|
}
|
|
506350
|
-
endCompaction(tokensBefore, tokensAfter) {
|
|
507163
|
+
endCompaction(tokensBefore, tokensAfter, stageCount) {
|
|
506351
507164
|
this.host.state.footer.finishCompaction();
|
|
506352
507165
|
const block = this._activeCompactionBlock;
|
|
506353
507166
|
if (block === void 0) return;
|
|
506354
|
-
block.markDone(tokensBefore, tokensAfter);
|
|
507167
|
+
block.markDone(tokensBefore, tokensAfter, stageCount);
|
|
506355
507168
|
this._activeCompactionBlock = void 0;
|
|
506356
507169
|
this._cancelledCompactionBlock = void 0;
|
|
506357
507170
|
this.host.state.ui.requestRender();
|
|
@@ -509330,6 +510143,10 @@ function channelDir() {
|
|
|
509330
510143
|
function outboxPath() {
|
|
509331
510144
|
return join$4(channelDir(), "outbox.jsonl");
|
|
509332
510145
|
}
|
|
510146
|
+
function mediaDir() {
|
|
510147
|
+
const base = process.env["BLUN_HOME"]?.trim();
|
|
510148
|
+
return join$4(base !== void 0 && base.length > 0 ? base : join$4(homedir(), ".blun"), "media");
|
|
510149
|
+
}
|
|
509333
510150
|
/** Host-owned channel setting from process env or the channel .env. */
|
|
509334
510151
|
function channelSetting(name) {
|
|
509335
510152
|
const configured = process.env[name]?.trim();
|
|
@@ -509372,6 +510189,49 @@ function outboxGrewForChat(marker, chatId) {
|
|
|
509372
510189
|
return false;
|
|
509373
510190
|
}
|
|
509374
510191
|
const TELEGRAM_TEXT_LIMIT = 4096;
|
|
510192
|
+
const TELEGRAM_ATTACHMENT_LIMIT = 50 * 1024 * 1024;
|
|
510193
|
+
function mediaTelegramTarget(filePath) {
|
|
510194
|
+
const lower = filePath.toLowerCase();
|
|
510195
|
+
if (/\.(?:png|jpe?g|webp|gif)$/u.test(lower)) return {
|
|
510196
|
+
method: "sendPhoto",
|
|
510197
|
+
field: "photo",
|
|
510198
|
+
mimeType: lower.endsWith(".png") ? "image/png" : lower.endsWith(".webp") ? "image/webp" : lower.endsWith(".gif") ? "image/gif" : "image/jpeg"
|
|
510199
|
+
};
|
|
510200
|
+
if (lower.endsWith(".mp4")) return {
|
|
510201
|
+
method: "sendVideo",
|
|
510202
|
+
field: "video",
|
|
510203
|
+
mimeType: "video/mp4"
|
|
510204
|
+
};
|
|
510205
|
+
if (/\.(?:mp3|wav)$/u.test(lower)) return {
|
|
510206
|
+
method: "sendAudio",
|
|
510207
|
+
field: "audio",
|
|
510208
|
+
mimeType: lower.endsWith(".mp3") ? "audio/mpeg" : "audio/wav"
|
|
510209
|
+
};
|
|
510210
|
+
return {
|
|
510211
|
+
method: "sendDocument",
|
|
510212
|
+
field: "document",
|
|
510213
|
+
mimeType: "application/octet-stream"
|
|
510214
|
+
};
|
|
510215
|
+
}
|
|
510216
|
+
function safeCompletedMediaPath(filePath) {
|
|
510217
|
+
try {
|
|
510218
|
+
const root = realpathSync(mediaDir());
|
|
510219
|
+
const resolved = realpathSync(filePath);
|
|
510220
|
+
const withinRoot = relative(root, resolved);
|
|
510221
|
+
if (withinRoot.length === 0 || withinRoot.startsWith("..") || isAbsolute(withinRoot)) return;
|
|
510222
|
+
const info = statSync(resolved);
|
|
510223
|
+
if (!info.isFile() || info.size <= 0 || info.size > TELEGRAM_ATTACHMENT_LIMIT) return void 0;
|
|
510224
|
+
return resolved;
|
|
510225
|
+
} catch {
|
|
510226
|
+
return;
|
|
510227
|
+
}
|
|
510228
|
+
}
|
|
510229
|
+
/** Extract the host-owned local result path from a successful GetMedia output. */
|
|
510230
|
+
function completedMediaLocalPath(output) {
|
|
510231
|
+
const text = Array.isArray(output) ? output.filter((part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string").map((part) => part.text).join("\n") : typeof output === "string" ? output : "";
|
|
510232
|
+
const candidate = /Media job [^\r\n]+ is complete\. Local file: (.+?)\. The BLUN host/u.exec(text)?.[1]?.trim();
|
|
510233
|
+
return candidate === void 0 || candidate.length === 0 ? void 0 : safeCompletedMediaPath(candidate);
|
|
510234
|
+
}
|
|
509375
510235
|
/** Telegram group/supergroup ids are negative; DMs are the positive user id. */
|
|
509376
510236
|
function isGroupChat(chatId) {
|
|
509377
510237
|
return chatId.startsWith("-");
|
|
@@ -509444,6 +510304,40 @@ async function sendReplyFallback(chatId, text, contextOnly = false) {
|
|
|
509444
510304
|
return false;
|
|
509445
510305
|
}
|
|
509446
510306
|
}
|
|
510307
|
+
/**
|
|
510308
|
+
* Deliver a completed BLUN media file immediately for a channel-origin turn.
|
|
510309
|
+
* The path must resolve to a non-empty file below BLUN_HOME/media. Returns true
|
|
510310
|
+
* only after Telegram accepted the upload and the outbox receipt was appended.
|
|
510311
|
+
*/
|
|
510312
|
+
async function sendMediaReplyFallback(chatId, filePath) {
|
|
510313
|
+
const safePath = safeCompletedMediaPath(filePath);
|
|
510314
|
+
const token = botToken();
|
|
510315
|
+
if (safePath === void 0 || token === void 0) return false;
|
|
510316
|
+
const target = mediaTelegramTarget(safePath);
|
|
510317
|
+
const form = new FormData();
|
|
510318
|
+
form.append("chat_id", chatId);
|
|
510319
|
+
form.append(target.field, new Blob([new Uint8Array(readFileSync(safePath))], { type: target.mimeType }), basename(safePath));
|
|
510320
|
+
try {
|
|
510321
|
+
const payload = await (await fetch(`https://api.telegram.org/bot${token}/${target.method}`, {
|
|
510322
|
+
method: "POST",
|
|
510323
|
+
body: form
|
|
510324
|
+
})).json();
|
|
510325
|
+
if (payload.ok !== true) return false;
|
|
510326
|
+
try {
|
|
510327
|
+
appendFileSync(outboxPath(), `${JSON.stringify({
|
|
510328
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
510329
|
+
direction: "out",
|
|
510330
|
+
kind: "media-reply-fallback",
|
|
510331
|
+
chat_id: String(chatId),
|
|
510332
|
+
message_ids: payload.result?.message_id === void 0 ? [] : [payload.result.message_id],
|
|
510333
|
+
files: [safePath]
|
|
510334
|
+
})}\n`);
|
|
510335
|
+
} catch {}
|
|
510336
|
+
return true;
|
|
510337
|
+
} catch {
|
|
510338
|
+
return false;
|
|
510339
|
+
}
|
|
510340
|
+
}
|
|
509447
510341
|
//#endregion
|
|
509448
510342
|
//#region src/tui/utils/dead-terminal.ts
|
|
509449
510343
|
/**
|
|
@@ -510404,406 +511298,6 @@ function turnsToTrim(turns, maxTurns, hysteresis) {
|
|
|
510404
511298
|
return toRemove;
|
|
510405
511299
|
}
|
|
510406
511300
|
//#endregion
|
|
510407
|
-
//#region src/tui/blun-tui.copy.ts
|
|
510408
|
-
registerUiCatalogFragment({
|
|
510409
|
-
en: {
|
|
510410
|
-
"blunTui.provider.modelAdded.one": "{providerName} · +{count} model.",
|
|
510411
|
-
"blunTui.provider.modelAdded.other": "{providerName} · +{count} models.",
|
|
510412
|
-
"blunTui.provider.refreshSkipped": "Skipped refreshing {provider}: {reason}",
|
|
510413
|
-
"blunTui.warning": "Warning: {warning}",
|
|
510414
|
-
"blunTui.startup.sessionNotFound": "Session \"{sessionId}\" not found.",
|
|
510415
|
-
"blunTui.startup.sessionDifferentDirectory": "Session \"{sessionId}\" was created under a different directory.",
|
|
510416
|
-
"blunTui.startup.noSessionsToContinue": "No sessions to continue under \"{workDir}\"; starting a fresh session.",
|
|
510417
|
-
"blunTui.startup.sessionNotInitialized": "Startup session was not initialized.",
|
|
510418
|
-
"blunTui.input.replayBlocked": "Cannot send input while session history is replaying.",
|
|
510419
|
-
"blunTui.shell.noSession": "No active session for shell command.",
|
|
510420
|
-
"blunTui.shell.runFailed": "Shell command failed: {error}",
|
|
510421
|
-
"blunTui.shell.cancelFailed": "Failed to cancel shell command: {error}",
|
|
510422
|
-
"blunTui.channel.steerFailed": "Failed to steer channel message: {error}",
|
|
510423
|
-
"blunTui.session.sendFailed": "Failed to send: {error}",
|
|
510424
|
-
"blunTui.media.imageUnsupported": "Current model does not support image input.",
|
|
510425
|
-
"blunTui.media.videoUnsupported": "Current model does not support video input.",
|
|
510426
|
-
"blunTui.skill.failed": "Skill \"{skillName}\" failed: {error}",
|
|
510427
|
-
"blunTui.pluginCommand.failed": "Command \"{command}\" failed: {error}",
|
|
510428
|
-
"blunTui.steer.failed": "Failed to steer: {error}",
|
|
510429
|
-
"blunTui.session.otherWorkDir": "Current session is in a different working directory.",
|
|
510430
|
-
"blunTui.session.resumeCommand": "To resume, run: {command}",
|
|
510431
|
-
"blunTui.clipboard.commandCopied": "Command copied to clipboard",
|
|
510432
|
-
"blunTui.clipboard.commandCopyFailed": "Failed to copy command to clipboard",
|
|
510433
|
-
"blunTui.session.alreadyCurrent": "Already on this session.",
|
|
510434
|
-
"blunTui.session.switchStreamingBlocked": "Cannot switch sessions while streaming — press Esc or Ctrl-C first.",
|
|
510435
|
-
"blunTui.session.switchReplayBlocked": "Cannot switch sessions while history is replaying.",
|
|
510436
|
-
"blunTui.session.resumeFailed": "Failed to resume session {sessionId}: {error}",
|
|
510437
|
-
"blunTui.session.resumed": "Resumed session ({sessionId}).",
|
|
510438
|
-
"blunTui.session.replayFailed": "Failed to replay session history: {error}",
|
|
510439
|
-
"blunTui.session.createReplayBlocked": "Cannot start a new session while history is replaying.",
|
|
510440
|
-
"blunTui.session.createFailed": "Failed to start a new session: {error}",
|
|
510441
|
-
"blunTui.session.postCreateFailed": "Post-create setup failed: {error}",
|
|
510442
|
-
"blunTui.session.started": "Started a new session ({sessionId}).",
|
|
510443
|
-
"blunTui.error": "Error: {message}",
|
|
510444
|
-
"blunTui.login.title": "Sign in to BLUN",
|
|
510445
|
-
"blunTui.login.hint": "Press Ctrl-C to cancel",
|
|
510446
|
-
"blunTui.login.waiting": "Waiting for authorization…",
|
|
510447
|
-
"blunTui.detach.noShell": "No shell command running.",
|
|
510448
|
-
"blunTui.detach.shellStarting": "Command is still starting — try again.",
|
|
510449
|
-
"blunTui.detach.shellFinished": "Command already finished.",
|
|
510450
|
-
"blunTui.detach.moveFailed": "Failed to move to background: {error}",
|
|
510451
|
-
"blunTui.detach.movedTranscript": "Moved to background.",
|
|
510452
|
-
"blunTui.detach.movedView": "Moved to background. /tasks to view.",
|
|
510453
|
-
"blunTui.detach.noForeground": "No foreground task running.",
|
|
510454
|
-
"blunTui.detach.listFailed": "Failed to list tasks: {error}",
|
|
510455
|
-
"blunTui.detach.taskFailed": "Failed to detach {taskId}: {error}",
|
|
510456
|
-
"blunTui.detach.finished.one": "Task already finished.",
|
|
510457
|
-
"blunTui.detach.finished.other": "Tasks already finished.",
|
|
510458
|
-
"blunTui.detach.moved.one": "Moved {count} task to background.",
|
|
510459
|
-
"blunTui.detach.moved.other": "Moved {count} tasks to background.",
|
|
510460
|
-
"blunTui.detach.partial": "Moved {detached} of {total} tasks to background.",
|
|
510461
|
-
"blunTui.detach.viewSuffix": "/tasks to view.",
|
|
510462
|
-
"blunTui.startup.flagsFailed": "Failed to apply startup flags: {error}",
|
|
510463
|
-
"blunTui.notification.approvalRequired": "BLUN approval required",
|
|
510464
|
-
"blunTui.notification.answerRequired": "BLUN needs your answer",
|
|
510465
|
-
"blunTui.telegram.fallbackDelivered": "Reply delivered to Telegram automatically (fallback).",
|
|
510466
|
-
"blunTui.telegram.attachDisabled": "Telegram attachment disabled by BLUN_TELEGRAM_ATTACH=off — headless mode active.",
|
|
510467
|
-
"blunTui.telegram.noToken": "Telegram attachment: no token detected — headless mode active.",
|
|
510468
|
-
"blunTui.telegram.attached": "Telegram channel attached (lease PID {pid}) — messages appear in this window.",
|
|
510469
|
-
"blunTui.auto.status": "Auto: {label}",
|
|
510470
|
-
"blunTui.activity.thinking": "{name} is thinking…",
|
|
510471
|
-
"blunTui.activity.working": "{name} is working…",
|
|
510472
|
-
"blunTui.activity.composing": "working...",
|
|
510473
|
-
"blunTui.activity.tokens": "Tokens"
|
|
510474
|
-
},
|
|
510475
|
-
de: {
|
|
510476
|
-
"blunTui.provider.modelAdded.one": "{providerName} · +{count} Modell.",
|
|
510477
|
-
"blunTui.provider.modelAdded.other": "{providerName} · +{count} Modelle.",
|
|
510478
|
-
"blunTui.provider.refreshSkipped": "Aktualisierung von {provider} übersprungen: {reason}",
|
|
510479
|
-
"blunTui.warning": "Warnung: {warning}",
|
|
510480
|
-
"blunTui.startup.sessionNotFound": "Sitzung „{sessionId}“ wurde nicht gefunden.",
|
|
510481
|
-
"blunTui.startup.sessionDifferentDirectory": "Sitzung „{sessionId}“ wurde in einem anderen Arbeitsverzeichnis erstellt.",
|
|
510482
|
-
"blunTui.startup.noSessionsToContinue": "Unter „{workDir}“ gibt es keine Sitzung zum Fortsetzen; eine neue Sitzung wird gestartet.",
|
|
510483
|
-
"blunTui.startup.sessionNotInitialized": "Die Sitzung konnte beim Start nicht initialisiert werden.",
|
|
510484
|
-
"blunTui.input.replayBlocked": "Während der Wiedergabe des Sitzungsverlaufs können keine Eingaben gesendet werden.",
|
|
510485
|
-
"blunTui.shell.noSession": "Keine aktive Sitzung für den Shell-Befehl.",
|
|
510486
|
-
"blunTui.shell.runFailed": "Shell-Befehl fehlgeschlagen: {error}",
|
|
510487
|
-
"blunTui.shell.cancelFailed": "Shell-Befehl konnte nicht abgebrochen werden: {error}",
|
|
510488
|
-
"blunTui.channel.steerFailed": "Die Kanalnachricht konnte nicht zur laufenden Antwort hinzugefügt werden: {error}",
|
|
510489
|
-
"blunTui.session.sendFailed": "Senden fehlgeschlagen: {error}",
|
|
510490
|
-
"blunTui.media.imageUnsupported": "Das aktuelle Modell unterstützt keine Bildeingaben.",
|
|
510491
|
-
"blunTui.media.videoUnsupported": "Das aktuelle Modell unterstützt keine Videoeingaben.",
|
|
510492
|
-
"blunTui.skill.failed": "Skill „{skillName}“ fehlgeschlagen: {error}",
|
|
510493
|
-
"blunTui.pluginCommand.failed": "Befehl „{command}“ fehlgeschlagen: {error}",
|
|
510494
|
-
"blunTui.steer.failed": "Nachsteuern fehlgeschlagen: {error}",
|
|
510495
|
-
"blunTui.session.otherWorkDir": "Die aktuelle Sitzung befindet sich in einem anderen Arbeitsverzeichnis.",
|
|
510496
|
-
"blunTui.session.resumeCommand": "Zum Fortsetzen ausführen: {command}",
|
|
510497
|
-
"blunTui.clipboard.commandCopied": "Befehl in die Zwischenablage kopiert",
|
|
510498
|
-
"blunTui.clipboard.commandCopyFailed": "Befehl konnte nicht in die Zwischenablage kopiert werden",
|
|
510499
|
-
"blunTui.session.alreadyCurrent": "Diese Sitzung ist bereits aktiv.",
|
|
510500
|
-
"blunTui.session.switchStreamingBlocked": "Während einer laufenden Antwort kann die Sitzung nicht gewechselt werden. Drücke zuerst Esc oder Ctrl-C.",
|
|
510501
|
-
"blunTui.session.switchReplayBlocked": "Während der Wiedergabe des Sitzungsverlaufs kann die Sitzung nicht gewechselt werden.",
|
|
510502
|
-
"blunTui.session.resumeFailed": "Sitzung {sessionId} konnte nicht fortgesetzt werden: {error}",
|
|
510503
|
-
"blunTui.session.resumed": "Sitzung fortgesetzt ({sessionId}).",
|
|
510504
|
-
"blunTui.session.replayFailed": "Der Sitzungsverlauf konnte nicht wiedergegeben werden: {error}",
|
|
510505
|
-
"blunTui.session.createReplayBlocked": "Während der Wiedergabe des Sitzungsverlaufs kann keine neue Sitzung gestartet werden.",
|
|
510506
|
-
"blunTui.session.createFailed": "Neue Sitzung konnte nicht gestartet werden: {error}",
|
|
510507
|
-
"blunTui.session.postCreateFailed": "Die neue Sitzung konnte nicht eingerichtet werden: {error}",
|
|
510508
|
-
"blunTui.session.started": "Neue Sitzung gestartet ({sessionId}).",
|
|
510509
|
-
"blunTui.error": "Fehler: {message}",
|
|
510510
|
-
"blunTui.login.title": "Bei BLUN anmelden",
|
|
510511
|
-
"blunTui.login.hint": "Zum Abbrechen Ctrl-C drücken",
|
|
510512
|
-
"blunTui.login.waiting": "Warten auf Autorisierung…",
|
|
510513
|
-
"blunTui.detach.noShell": "Es wird kein Shell-Befehl ausgeführt.",
|
|
510514
|
-
"blunTui.detach.shellStarting": "Der Befehl wird noch gestartet — versuche es erneut.",
|
|
510515
|
-
"blunTui.detach.shellFinished": "Der Befehl ist bereits beendet.",
|
|
510516
|
-
"blunTui.detach.moveFailed": "Verschieben in den Hintergrund fehlgeschlagen: {error}",
|
|
510517
|
-
"blunTui.detach.movedTranscript": "In den Hintergrund verschoben.",
|
|
510518
|
-
"blunTui.detach.movedView": "In den Hintergrund verschoben. Mit /tasks anzeigen.",
|
|
510519
|
-
"blunTui.detach.noForeground": "Es wird keine Aufgabe im Vordergrund ausgeführt.",
|
|
510520
|
-
"blunTui.detach.listFailed": "Aufgaben konnten nicht aufgelistet werden: {error}",
|
|
510521
|
-
"blunTui.detach.taskFailed": "Aufgabe {taskId} konnte nicht in den Hintergrund verschoben werden: {error}",
|
|
510522
|
-
"blunTui.detach.finished.one": "Aufgabe ist bereits beendet.",
|
|
510523
|
-
"blunTui.detach.finished.other": "Aufgaben sind bereits beendet.",
|
|
510524
|
-
"blunTui.detach.moved.one": "{count} Aufgabe in den Hintergrund verschoben.",
|
|
510525
|
-
"blunTui.detach.moved.other": "{count} Aufgaben in den Hintergrund verschoben.",
|
|
510526
|
-
"blunTui.detach.partial": "{detached} von {total} Aufgaben in den Hintergrund verschoben.",
|
|
510527
|
-
"blunTui.detach.viewSuffix": "Mit /tasks anzeigen.",
|
|
510528
|
-
"blunTui.startup.flagsFailed": "Startoptionen konnten nicht angewendet werden: {error}",
|
|
510529
|
-
"blunTui.notification.approvalRequired": "BLUN-Genehmigung erforderlich",
|
|
510530
|
-
"blunTui.notification.answerRequired": "BLUN benötigt deine Antwort",
|
|
510531
|
-
"blunTui.telegram.fallbackDelivered": "Antwort automatisch nach Telegram zugestellt (Fallback).",
|
|
510532
|
-
"blunTui.telegram.attachDisabled": "Telegram-Anbindung durch BLUN_TELEGRAM_ATTACH=off deaktiviert — Headless-Modus aktiv.",
|
|
510533
|
-
"blunTui.telegram.noToken": "Telegram-Anbindung: kein Token erkannt — Headless-Modus aktiv.",
|
|
510534
|
-
"blunTui.telegram.attached": "Telegram-Kanal angebunden (Lease-PID {pid}) — Nachrichten erscheinen in diesem Fenster.",
|
|
510535
|
-
"blunTui.auto.status": "Auto: {label}",
|
|
510536
|
-
"blunTui.activity.thinking": "{name} denkt…",
|
|
510537
|
-
"blunTui.activity.working": "{name} arbeitet…",
|
|
510538
|
-
"blunTui.activity.composing": "arbeitet...",
|
|
510539
|
-
"blunTui.activity.tokens": "Token"
|
|
510540
|
-
},
|
|
510541
|
-
es: {
|
|
510542
|
-
"blunTui.provider.modelAdded.one": "{providerName} · +{count} modelo.",
|
|
510543
|
-
"blunTui.provider.modelAdded.other": "{providerName} · +{count} modelos.",
|
|
510544
|
-
"blunTui.provider.refreshSkipped": "Se omitió la actualización de {provider}: {reason}",
|
|
510545
|
-
"blunTui.warning": "Advertencia: {warning}",
|
|
510546
|
-
"blunTui.startup.sessionNotFound": "No se encontró la sesión «{sessionId}».",
|
|
510547
|
-
"blunTui.startup.sessionDifferentDirectory": "La sesión «{sessionId}» se creó en otro directorio de trabajo.",
|
|
510548
|
-
"blunTui.startup.noSessionsToContinue": "No hay sesiones que reanudar en «{workDir}»; se iniciará una sesión nueva.",
|
|
510549
|
-
"blunTui.startup.sessionNotInitialized": "No se pudo inicializar la sesión durante el arranque.",
|
|
510550
|
-
"blunTui.input.replayBlocked": "No se puede enviar ninguna entrada mientras se reproduce el historial de la sesión.",
|
|
510551
|
-
"blunTui.shell.noSession": "No hay ninguna sesión activa para el comando de shell.",
|
|
510552
|
-
"blunTui.shell.runFailed": "El comando de shell falló: {error}",
|
|
510553
|
-
"blunTui.shell.cancelFailed": "No se pudo cancelar el comando de shell: {error}",
|
|
510554
|
-
"blunTui.channel.steerFailed": "No se pudo añadir el mensaje del canal a la respuesta en curso: {error}",
|
|
510555
|
-
"blunTui.session.sendFailed": "No se pudo enviar: {error}",
|
|
510556
|
-
"blunTui.media.imageUnsupported": "El modelo actual no admite entradas de imagen.",
|
|
510557
|
-
"blunTui.media.videoUnsupported": "El modelo actual no admite entradas de vídeo.",
|
|
510558
|
-
"blunTui.skill.failed": "El skill «{skillName}» falló: {error}",
|
|
510559
|
-
"blunTui.pluginCommand.failed": "El comando «{command}» falló: {error}",
|
|
510560
|
-
"blunTui.steer.failed": "No se pudo reorientar la respuesta: {error}",
|
|
510561
|
-
"blunTui.session.otherWorkDir": "La sesión actual se encuentra en otro directorio de trabajo.",
|
|
510562
|
-
"blunTui.session.resumeCommand": "Para reanudarla, ejecuta: {command}",
|
|
510563
|
-
"blunTui.clipboard.commandCopied": "Comando copiado al portapapeles",
|
|
510564
|
-
"blunTui.clipboard.commandCopyFailed": "No se pudo copiar el comando al portapapeles",
|
|
510565
|
-
"blunTui.session.alreadyCurrent": "Esta sesión ya está activa.",
|
|
510566
|
-
"blunTui.session.switchStreamingBlocked": "No se puede cambiar de sesión mientras se genera una respuesta. Pulsa primero Esc o Ctrl-C.",
|
|
510567
|
-
"blunTui.session.switchReplayBlocked": "No se puede cambiar de sesión mientras se reproduce el historial.",
|
|
510568
|
-
"blunTui.session.resumeFailed": "No se pudo reanudar la sesión {sessionId}: {error}",
|
|
510569
|
-
"blunTui.session.resumed": "Sesión reanudada ({sessionId}).",
|
|
510570
|
-
"blunTui.session.replayFailed": "No se pudo reproducir el historial de la sesión: {error}",
|
|
510571
|
-
"blunTui.session.createReplayBlocked": "No se puede iniciar una sesión nueva mientras se reproduce el historial.",
|
|
510572
|
-
"blunTui.session.createFailed": "No se pudo iniciar una sesión nueva: {error}",
|
|
510573
|
-
"blunTui.session.postCreateFailed": "No se pudo configurar la sesión recién creada: {error}",
|
|
510574
|
-
"blunTui.session.started": "Se inició una sesión nueva ({sessionId}).",
|
|
510575
|
-
"blunTui.error": "Error: {message}",
|
|
510576
|
-
"blunTui.login.title": "Iniciar sesión en BLUN",
|
|
510577
|
-
"blunTui.login.hint": "Pulsa Ctrl-C para cancelar",
|
|
510578
|
-
"blunTui.login.waiting": "Esperando autorización…",
|
|
510579
|
-
"blunTui.detach.noShell": "No hay ningún comando de shell en ejecución.",
|
|
510580
|
-
"blunTui.detach.shellStarting": "El comando todavía se está iniciando; inténtalo de nuevo.",
|
|
510581
|
-
"blunTui.detach.shellFinished": "El comando ya ha finalizado.",
|
|
510582
|
-
"blunTui.detach.moveFailed": "No se pudo mover a segundo plano: {error}",
|
|
510583
|
-
"blunTui.detach.movedTranscript": "Se movió a segundo plano.",
|
|
510584
|
-
"blunTui.detach.movedView": "Se movió a segundo plano. Consulta /tasks.",
|
|
510585
|
-
"blunTui.detach.noForeground": "No hay ninguna tarea en ejecución en primer plano.",
|
|
510586
|
-
"blunTui.detach.listFailed": "No se pudieron obtener las tareas: {error}",
|
|
510587
|
-
"blunTui.detach.taskFailed": "No se pudo mover la tarea {taskId} a segundo plano: {error}",
|
|
510588
|
-
"blunTui.detach.finished.one": "La tarea ya ha finalizado.",
|
|
510589
|
-
"blunTui.detach.finished.other": "Las tareas ya han finalizado.",
|
|
510590
|
-
"blunTui.detach.moved.one": "Se ha movido {count} tarea a segundo plano.",
|
|
510591
|
-
"blunTui.detach.moved.other": "Se han movido {count} tareas a segundo plano.",
|
|
510592
|
-
"blunTui.detach.partial": "Se han movido {detached} de {total} tareas a segundo plano.",
|
|
510593
|
-
"blunTui.detach.viewSuffix": "Consulta /tasks.",
|
|
510594
|
-
"blunTui.startup.flagsFailed": "No se pudieron aplicar las opciones de inicio: {error}",
|
|
510595
|
-
"blunTui.notification.approvalRequired": "Se requiere aprobación de BLUN",
|
|
510596
|
-
"blunTui.notification.answerRequired": "BLUN necesita tu respuesta",
|
|
510597
|
-
"blunTui.telegram.fallbackDelivered": "La respuesta se envió automáticamente a Telegram (modo alternativo).",
|
|
510598
|
-
"blunTui.telegram.attachDisabled": "Conexión con Telegram desactivada mediante BLUN_TELEGRAM_ATTACH=off — modo headless activo.",
|
|
510599
|
-
"blunTui.telegram.noToken": "Conexión con Telegram: no se detectó ningún token — modo headless activo.",
|
|
510600
|
-
"blunTui.telegram.attached": "Canal de Telegram conectado (PID de lease {pid}) — los mensajes aparecen en esta ventana.",
|
|
510601
|
-
"blunTui.auto.status": "Automático: {label}",
|
|
510602
|
-
"blunTui.activity.thinking": "{name} está pensando…",
|
|
510603
|
-
"blunTui.activity.working": "{name} está trabajando…",
|
|
510604
|
-
"blunTui.activity.composing": "trabajando...",
|
|
510605
|
-
"blunTui.activity.tokens": "tokens"
|
|
510606
|
-
},
|
|
510607
|
-
fr: {
|
|
510608
|
-
"blunTui.provider.modelAdded.one": "{providerName} · +{count} modèle.",
|
|
510609
|
-
"blunTui.provider.modelAdded.other": "{providerName} · +{count} modèles.",
|
|
510610
|
-
"blunTui.provider.refreshSkipped": "Actualisation de {provider} ignorée : {reason}",
|
|
510611
|
-
"blunTui.warning": "Avertissement : {warning}",
|
|
510612
|
-
"blunTui.startup.sessionNotFound": "Session « {sessionId} » introuvable.",
|
|
510613
|
-
"blunTui.startup.sessionDifferentDirectory": "La session « {sessionId} » a été créée dans un autre répertoire de travail.",
|
|
510614
|
-
"blunTui.startup.noSessionsToContinue": "Aucune session à reprendre dans « {workDir} » ; démarrage d’une nouvelle session.",
|
|
510615
|
-
"blunTui.startup.sessionNotInitialized": "La session de démarrage n’a pas été initialisée.",
|
|
510616
|
-
"blunTui.input.replayBlocked": "Impossible d’envoyer une saisie pendant la relecture de l’historique de la session.",
|
|
510617
|
-
"blunTui.shell.noSession": "Aucune session active pour la commande shell.",
|
|
510618
|
-
"blunTui.shell.runFailed": "Échec de la commande shell : {error}",
|
|
510619
|
-
"blunTui.shell.cancelFailed": "Impossible d’annuler la commande shell : {error}",
|
|
510620
|
-
"blunTui.channel.steerFailed": "Impossible d’ajouter le message du canal à la réponse en cours : {error}",
|
|
510621
|
-
"blunTui.session.sendFailed": "Échec de l’envoi : {error}",
|
|
510622
|
-
"blunTui.media.imageUnsupported": "Le modèle actuel ne prend pas en charge les images en entrée.",
|
|
510623
|
-
"blunTui.media.videoUnsupported": "Le modèle actuel ne prend pas en charge les vidéos en entrée.",
|
|
510624
|
-
"blunTui.skill.failed": "Échec du skill « {skillName} » : {error}",
|
|
510625
|
-
"blunTui.pluginCommand.failed": "Échec de la commande « {command} » : {error}",
|
|
510626
|
-
"blunTui.steer.failed": "Impossible de réorienter la réponse : {error}",
|
|
510627
|
-
"blunTui.session.otherWorkDir": "La session actuelle se trouve dans un autre répertoire de travail.",
|
|
510628
|
-
"blunTui.session.resumeCommand": "Pour la reprendre, exécutez : {command}",
|
|
510629
|
-
"blunTui.clipboard.commandCopied": "Commande copiée dans le presse-papiers",
|
|
510630
|
-
"blunTui.clipboard.commandCopyFailed": "Impossible de copier la commande dans le presse-papiers",
|
|
510631
|
-
"blunTui.session.alreadyCurrent": "Cette session est déjà active.",
|
|
510632
|
-
"blunTui.session.switchStreamingBlocked": "Impossible de changer de session pendant la génération d’une réponse. Appuyez d’abord sur Esc ou Ctrl-C.",
|
|
510633
|
-
"blunTui.session.switchReplayBlocked": "Impossible de changer de session pendant la relecture de l’historique.",
|
|
510634
|
-
"blunTui.session.resumeFailed": "Impossible de reprendre la session {sessionId} : {error}",
|
|
510635
|
-
"blunTui.session.resumed": "Session reprise ({sessionId}).",
|
|
510636
|
-
"blunTui.session.replayFailed": "Impossible de relire l’historique de la session : {error}",
|
|
510637
|
-
"blunTui.session.createReplayBlocked": "Impossible de démarrer une nouvelle session pendant la relecture de l’historique.",
|
|
510638
|
-
"blunTui.session.createFailed": "Impossible de démarrer une nouvelle session : {error}",
|
|
510639
|
-
"blunTui.session.postCreateFailed": "Impossible de configurer la nouvelle session : {error}",
|
|
510640
|
-
"blunTui.session.started": "Nouvelle session démarrée ({sessionId}).",
|
|
510641
|
-
"blunTui.error": "Erreur : {message}",
|
|
510642
|
-
"blunTui.login.title": "Se connecter à BLUN",
|
|
510643
|
-
"blunTui.login.hint": "Appuyez sur Ctrl-C pour annuler",
|
|
510644
|
-
"blunTui.login.waiting": "En attente de l’autorisation…",
|
|
510645
|
-
"blunTui.detach.noShell": "Aucune commande shell en cours.",
|
|
510646
|
-
"blunTui.detach.shellStarting": "La commande est encore en cours de démarrage — réessayez.",
|
|
510647
|
-
"blunTui.detach.shellFinished": "La commande est déjà terminée.",
|
|
510648
|
-
"blunTui.detach.moveFailed": "Impossible de passer la commande en arrière-plan : {error}",
|
|
510649
|
-
"blunTui.detach.movedTranscript": "Commande passée en arrière-plan.",
|
|
510650
|
-
"blunTui.detach.movedView": "Commande passée en arrière-plan. Consultez /tasks.",
|
|
510651
|
-
"blunTui.detach.noForeground": "Aucune tâche en cours au premier plan.",
|
|
510652
|
-
"blunTui.detach.listFailed": "Impossible de répertorier les tâches : {error}",
|
|
510653
|
-
"blunTui.detach.taskFailed": "Impossible de passer la tâche {taskId} en arrière-plan : {error}",
|
|
510654
|
-
"blunTui.detach.finished.one": "La tâche est déjà terminée.",
|
|
510655
|
-
"blunTui.detach.finished.other": "Les tâches sont déjà terminées.",
|
|
510656
|
-
"blunTui.detach.moved.one": "{count} tâche passée en arrière-plan.",
|
|
510657
|
-
"blunTui.detach.moved.other": "{count} tâches passées en arrière-plan.",
|
|
510658
|
-
"blunTui.detach.partial": "{detached} tâches sur {total} passées en arrière-plan.",
|
|
510659
|
-
"blunTui.detach.viewSuffix": "Consultez /tasks.",
|
|
510660
|
-
"blunTui.startup.flagsFailed": "Impossible d’appliquer les options de démarrage : {error}",
|
|
510661
|
-
"blunTui.notification.approvalRequired": "Approbation BLUN requise",
|
|
510662
|
-
"blunTui.notification.answerRequired": "BLUN attend votre réponse",
|
|
510663
|
-
"blunTui.telegram.fallbackDelivered": "Réponse envoyée automatiquement sur Telegram (solution de secours).",
|
|
510664
|
-
"blunTui.telegram.attachDisabled": "Connexion à Telegram désactivée via BLUN_TELEGRAM_ATTACH=off — mode headless actif.",
|
|
510665
|
-
"blunTui.telegram.noToken": "Connexion à Telegram\xA0: aucun jeton détecté — mode headless actif.",
|
|
510666
|
-
"blunTui.telegram.attached": "Canal Telegram connecté (PID de lease\xA0: {pid}) — les messages apparaissent dans cette fenêtre.",
|
|
510667
|
-
"blunTui.auto.status": "Auto\xA0: {label}",
|
|
510668
|
-
"blunTui.activity.thinking": "{name} réfléchit…",
|
|
510669
|
-
"blunTui.activity.working": "{name} travaille…",
|
|
510670
|
-
"blunTui.activity.composing": "travail en cours...",
|
|
510671
|
-
"blunTui.activity.tokens": "jetons"
|
|
510672
|
-
},
|
|
510673
|
-
sv: {
|
|
510674
|
-
"blunTui.provider.modelAdded.one": "{providerName} · +{count} modell.",
|
|
510675
|
-
"blunTui.provider.modelAdded.other": "{providerName} · +{count} modeller.",
|
|
510676
|
-
"blunTui.provider.refreshSkipped": "Uppdateringen av {provider} hoppades över: {reason}",
|
|
510677
|
-
"blunTui.warning": "Varning: {warning}",
|
|
510678
|
-
"blunTui.startup.sessionNotFound": "Sessionen ”{sessionId}” hittades inte.",
|
|
510679
|
-
"blunTui.startup.sessionDifferentDirectory": "Sessionen ”{sessionId}” skapades i en annan arbetskatalog.",
|
|
510680
|
-
"blunTui.startup.noSessionsToContinue": "Det finns inga sessioner att återuppta i ”{workDir}”; en ny session startas.",
|
|
510681
|
-
"blunTui.startup.sessionNotInitialized": "Sessionen initierades inte vid start.",
|
|
510682
|
-
"blunTui.input.replayBlocked": "Det går inte att skicka indata medan sessionshistoriken spelas upp.",
|
|
510683
|
-
"blunTui.shell.noSession": "Det finns ingen aktiv session för skalkommandot.",
|
|
510684
|
-
"blunTui.shell.runFailed": "Skalkommandot misslyckades: {error}",
|
|
510685
|
-
"blunTui.shell.cancelFailed": "Det gick inte att avbryta skalkommandot: {error}",
|
|
510686
|
-
"blunTui.channel.steerFailed": "Det gick inte att lägga till kanalmeddelandet i det pågående svaret: {error}",
|
|
510687
|
-
"blunTui.session.sendFailed": "Det gick inte att skicka: {error}",
|
|
510688
|
-
"blunTui.media.imageUnsupported": "Den aktuella modellen stöder inte bildindata.",
|
|
510689
|
-
"blunTui.media.videoUnsupported": "Den aktuella modellen stöder inte videoindata.",
|
|
510690
|
-
"blunTui.skill.failed": "Skill ”{skillName}” misslyckades: {error}",
|
|
510691
|
-
"blunTui.pluginCommand.failed": "Kommandot ”{command}” misslyckades: {error}",
|
|
510692
|
-
"blunTui.steer.failed": "Det gick inte att styra om svaret: {error}",
|
|
510693
|
-
"blunTui.session.otherWorkDir": "Den aktuella sessionen finns i en annan arbetskatalog.",
|
|
510694
|
-
"blunTui.session.resumeCommand": "Kör följande för att återuppta den: {command}",
|
|
510695
|
-
"blunTui.clipboard.commandCopied": "Kommandot kopierades till urklipp",
|
|
510696
|
-
"blunTui.clipboard.commandCopyFailed": "Det gick inte att kopiera kommandot till urklipp",
|
|
510697
|
-
"blunTui.session.alreadyCurrent": "Den här sessionen är redan aktiv.",
|
|
510698
|
-
"blunTui.session.switchStreamingBlocked": "Det går inte att byta session medan ett svar genereras. Tryck först på Esc eller Ctrl-C.",
|
|
510699
|
-
"blunTui.session.switchReplayBlocked": "Det går inte att byta session medan historiken spelas upp.",
|
|
510700
|
-
"blunTui.session.resumeFailed": "Det gick inte att återuppta sessionen {sessionId}: {error}",
|
|
510701
|
-
"blunTui.session.resumed": "Sessionen återupptogs ({sessionId}).",
|
|
510702
|
-
"blunTui.session.replayFailed": "Det gick inte att spela upp sessionshistoriken: {error}",
|
|
510703
|
-
"blunTui.session.createReplayBlocked": "Det går inte att starta en ny session medan historiken spelas upp.",
|
|
510704
|
-
"blunTui.session.createFailed": "Det gick inte att starta en ny session: {error}",
|
|
510705
|
-
"blunTui.session.postCreateFailed": "Det gick inte att konfigurera den nya sessionen: {error}",
|
|
510706
|
-
"blunTui.session.started": "En ny session startades ({sessionId}).",
|
|
510707
|
-
"blunTui.error": "Fel: {message}",
|
|
510708
|
-
"blunTui.login.title": "Logga in på BLUN",
|
|
510709
|
-
"blunTui.login.hint": "Tryck på Ctrl-C för att avbryta",
|
|
510710
|
-
"blunTui.login.waiting": "Väntar på auktorisering…",
|
|
510711
|
-
"blunTui.detach.noShell": "Inget skalkommando körs.",
|
|
510712
|
-
"blunTui.detach.shellStarting": "Kommandot håller fortfarande på att startas – försök igen.",
|
|
510713
|
-
"blunTui.detach.shellFinished": "Kommandot är redan slutfört.",
|
|
510714
|
-
"blunTui.detach.moveFailed": "Det gick inte att flytta kommandot till bakgrunden: {error}",
|
|
510715
|
-
"blunTui.detach.movedTranscript": "Flyttades till bakgrunden.",
|
|
510716
|
-
"blunTui.detach.movedView": "Flyttades till bakgrunden. Visa med /tasks.",
|
|
510717
|
-
"blunTui.detach.noForeground": "Ingen uppgift körs i förgrunden.",
|
|
510718
|
-
"blunTui.detach.listFailed": "Det gick inte att lista uppgifterna: {error}",
|
|
510719
|
-
"blunTui.detach.taskFailed": "Det gick inte att flytta uppgiften {taskId} till bakgrunden: {error}",
|
|
510720
|
-
"blunTui.detach.finished.one": "Uppgiften är redan slutförd.",
|
|
510721
|
-
"blunTui.detach.finished.other": "Uppgifterna är redan slutförda.",
|
|
510722
|
-
"blunTui.detach.moved.one": "{count} uppgift flyttades till bakgrunden.",
|
|
510723
|
-
"blunTui.detach.moved.other": "{count} uppgifter flyttades till bakgrunden.",
|
|
510724
|
-
"blunTui.detach.partial": "{detached} av {total} uppgifter flyttades till bakgrunden.",
|
|
510725
|
-
"blunTui.detach.viewSuffix": "Visa med /tasks.",
|
|
510726
|
-
"blunTui.startup.flagsFailed": "Det gick inte att tillämpa startalternativen: {error}",
|
|
510727
|
-
"blunTui.notification.approvalRequired": "BLUN-godkännande krävs",
|
|
510728
|
-
"blunTui.notification.answerRequired": "BLUN behöver ditt svar",
|
|
510729
|
-
"blunTui.telegram.fallbackDelivered": "Svaret skickades automatiskt till Telegram (reservlösning).",
|
|
510730
|
-
"blunTui.telegram.attachDisabled": "Telegram-anslutningen inaktiverades via BLUN_TELEGRAM_ATTACH=off — headless-läget är aktivt.",
|
|
510731
|
-
"blunTui.telegram.noToken": "Telegram-anslutning: ingen token hittades — headless-läget är aktivt.",
|
|
510732
|
-
"blunTui.telegram.attached": "Telegram-kanalen är ansluten (lease-PID {pid}) — meddelanden visas i det här fönstret.",
|
|
510733
|
-
"blunTui.auto.status": "Automatiskt: {label}",
|
|
510734
|
-
"blunTui.activity.thinking": "{name} tänker…",
|
|
510735
|
-
"blunTui.activity.working": "{name} arbetar…",
|
|
510736
|
-
"blunTui.activity.composing": "arbetar...",
|
|
510737
|
-
"blunTui.activity.tokens": "token"
|
|
510738
|
-
},
|
|
510739
|
-
cs: {
|
|
510740
|
-
"blunTui.provider.modelAdded.one": "{providerName} · +{count} model.",
|
|
510741
|
-
"blunTui.provider.modelAdded.other": "{providerName} · nové modely: +{count}.",
|
|
510742
|
-
"blunTui.provider.refreshSkipped": "Přeskočeno obnovení {provider}: {reason}",
|
|
510743
|
-
"blunTui.warning": "Upozornění: {warning}",
|
|
510744
|
-
"blunTui.startup.sessionNotFound": "Relace \"{sessionId}\" nebyla nalezena.",
|
|
510745
|
-
"blunTui.startup.sessionDifferentDirectory": "Relace \"{sessionId}\" byla vytvořena v jiném adresáři.",
|
|
510746
|
-
"blunTui.startup.noSessionsToContinue": "V adresáři \"{workDir}\" nejsou žádné relace, ve kterých by bylo možné pokračovat; spouští se nová relace.",
|
|
510747
|
-
"blunTui.startup.sessionNotInitialized": "Relace při spuštění nebyla inicializována.",
|
|
510748
|
-
"blunTui.input.replayBlocked": "Nelze odeslat vstup během přehrávání historie relace.",
|
|
510749
|
-
"blunTui.shell.noSession": "Žádná aktivní relace pro příkaz shellu.",
|
|
510750
|
-
"blunTui.shell.runFailed": "Příkaz shellu selhal: {error}",
|
|
510751
|
-
"blunTui.shell.cancelFailed": "Selhalo zrušení příkazu shellu: {error}",
|
|
510752
|
-
"blunTui.channel.steerFailed": "Předání zprávy z kanálu do probíhající odpovědi selhalo: {error}",
|
|
510753
|
-
"blunTui.session.sendFailed": "Selhalo odeslání: {error}",
|
|
510754
|
-
"blunTui.media.imageUnsupported": "Aktuální model nepodporuje vstup obrázku.",
|
|
510755
|
-
"blunTui.media.videoUnsupported": "Aktuální model nepodporuje vstup videa.",
|
|
510756
|
-
"blunTui.skill.failed": "Dovednost \"{skillName}\" selhala: {error}",
|
|
510757
|
-
"blunTui.pluginCommand.failed": "Příkaz \"{command}\" selhal: {error}",
|
|
510758
|
-
"blunTui.steer.failed": "Doplnění pokynu selhalo: {error}",
|
|
510759
|
-
"blunTui.session.otherWorkDir": "Aktuální relace je v jiném pracovním adresáři.",
|
|
510760
|
-
"blunTui.session.resumeCommand": "Chcete-li pokračovat, spusťte: {command}",
|
|
510761
|
-
"blunTui.clipboard.commandCopied": "Příkaz zkopírován do schránky",
|
|
510762
|
-
"blunTui.clipboard.commandCopyFailed": "Selhalo kopírování příkazu do schránky",
|
|
510763
|
-
"blunTui.session.alreadyCurrent": "Již jste v této relaci.",
|
|
510764
|
-
"blunTui.session.switchStreamingBlocked": "Nelze přepínat relace během streamování — nejdříve stiskněte Esc nebo Ctrl-C.",
|
|
510765
|
-
"blunTui.session.switchReplayBlocked": "Nelze přepínat relace během přehrávání historie.",
|
|
510766
|
-
"blunTui.session.resumeFailed": "Selhalo obnovení relace {sessionId}: {error}",
|
|
510767
|
-
"blunTui.session.resumed": "Obnovena relace ({sessionId}).",
|
|
510768
|
-
"blunTui.session.replayFailed": "Selhalo přehrávání historie relace: {error}",
|
|
510769
|
-
"blunTui.session.createReplayBlocked": "Nelze spustit novou relaci během přehrávání historie.",
|
|
510770
|
-
"blunTui.session.createFailed": "Selhalo spuštění nové relace: {error}",
|
|
510771
|
-
"blunTui.session.postCreateFailed": "Selhalo nastavení po vytvoření: {error}",
|
|
510772
|
-
"blunTui.session.started": "Spuštěna nová relace ({sessionId}).",
|
|
510773
|
-
"blunTui.error": "Chyba: {message}",
|
|
510774
|
-
"blunTui.login.title": "Přihlaste se do BLUN",
|
|
510775
|
-
"blunTui.login.hint": "Stiskněte Ctrl-C pro zrušení",
|
|
510776
|
-
"blunTui.login.waiting": "Čekání na autorizaci…",
|
|
510777
|
-
"blunTui.detach.noShell": "Žádný příkaz shellu není spuštěn.",
|
|
510778
|
-
"blunTui.detach.shellStarting": "Příkaz se stále spouští — zkuste znovu.",
|
|
510779
|
-
"blunTui.detach.shellFinished": "Příkaz již skončil.",
|
|
510780
|
-
"blunTui.detach.moveFailed": "Selhalo přesunutí na pozadí: {error}",
|
|
510781
|
-
"blunTui.detach.movedTranscript": "Přesunuto na pozadí.",
|
|
510782
|
-
"blunTui.detach.movedView": "Přesunuto na pozadí. Zobrazíte příkazem /tasks.",
|
|
510783
|
-
"blunTui.detach.noForeground": "Žádný úkol na popředí není spuštěn.",
|
|
510784
|
-
"blunTui.detach.listFailed": "Selhalo vypsání úkolů: {error}",
|
|
510785
|
-
"blunTui.detach.taskFailed": "Přesunutí úlohy {taskId} na pozadí selhalo: {error}",
|
|
510786
|
-
"blunTui.detach.finished.one": "Úkol již skončil.",
|
|
510787
|
-
"blunTui.detach.finished.other": "Úkoly již skončily.",
|
|
510788
|
-
"blunTui.detach.moved.one": "Přesunut {count} úkol na pozadí.",
|
|
510789
|
-
"blunTui.detach.moved.other": "Úkoly přesunuté na pozadí: {count}.",
|
|
510790
|
-
"blunTui.detach.partial": "Přesunuto {detached} z {total} úkolů na pozadí.",
|
|
510791
|
-
"blunTui.detach.viewSuffix": "/tasks k zobrazení.",
|
|
510792
|
-
"blunTui.startup.flagsFailed": "Nepodařilo se použít spouštěcí příznaky: {error}",
|
|
510793
|
-
"blunTui.notification.approvalRequired": "Vyžadováno schválení BLUN",
|
|
510794
|
-
"blunTui.notification.answerRequired": "BLUN potřebuje vaši odpověď",
|
|
510795
|
-
"blunTui.telegram.fallbackDelivered": "Odpověď byla automaticky doručena do Telegramu (náhradním způsobem).",
|
|
510796
|
-
"blunTui.telegram.attachDisabled": "Připojení Telegramu je zakázáno nastavením BLUN_TELEGRAM_ATTACH=off — aktivní je režim bez uživatelského rozhraní.",
|
|
510797
|
-
"blunTui.telegram.noToken": "Připojení Telegramu: nebyl nalezen žádný token — aktivní je režim bez uživatelského rozhraní.",
|
|
510798
|
-
"blunTui.telegram.attached": "Kanál Telegramu je připojen (PID držitele připojení {pid}) — zprávy se zobrazují v tomto okně.",
|
|
510799
|
-
"blunTui.auto.status": "Automaticky: {label}",
|
|
510800
|
-
"blunTui.activity.thinking": "{name} přemýšlí…",
|
|
510801
|
-
"blunTui.activity.working": "{name} pracuje…",
|
|
510802
|
-
"blunTui.activity.composing": "pracuje…",
|
|
510803
|
-
"blunTui.activity.tokens": "Tokeny"
|
|
510804
|
-
}
|
|
510805
|
-
});
|
|
510806
|
-
//#endregion
|
|
510807
511301
|
//#region src/tui/blun-tui.ts
|
|
510808
511302
|
function loadingTipKind(mode) {
|
|
510809
511303
|
if (mode === "waiting" || mode === "tool") return "blun";
|
|
@@ -511649,7 +512143,8 @@ var BlunTUI = class {
|
|
|
511649
512143
|
this.state.queuedMessages = this.state.queuedMessages.slice(1);
|
|
511650
512144
|
const turnId = this.streamingUI.getTurnContext().turnId;
|
|
511651
512145
|
let transcriptRendered = item.channelTranscriptRendered === true;
|
|
511652
|
-
|
|
512146
|
+
const renderTranscript = () => {
|
|
512147
|
+
if (transcriptRendered) return;
|
|
511653
512148
|
this.appendTranscriptEntry({
|
|
511654
512149
|
id: nextTranscriptId(),
|
|
511655
512150
|
kind: "user",
|
|
@@ -511659,8 +512154,9 @@ var BlunTUI = class {
|
|
|
511659
512154
|
origin: item.origin
|
|
511660
512155
|
});
|
|
511661
512156
|
transcriptRendered = true;
|
|
511662
|
-
}
|
|
512157
|
+
};
|
|
511663
512158
|
if (item.channelContextOnly === true) {
|
|
512159
|
+
renderTranscript();
|
|
511664
512160
|
item.channelAcknowledge?.();
|
|
511665
512161
|
if (this.queueFlushBatchRemaining > 0) this.queueFlushBatchRemaining -= 1;
|
|
511666
512162
|
this.syncChannelQueueDeadline();
|
|
@@ -511690,6 +512186,7 @@ var BlunTUI = class {
|
|
|
511690
512186
|
stepStarted: false,
|
|
511691
512187
|
turnEnded: false,
|
|
511692
512188
|
onCommit: () => {
|
|
512189
|
+
renderTranscript();
|
|
511693
512190
|
item.channelAcknowledge?.();
|
|
511694
512191
|
if (this.queueFlushBatchRemaining > 0) this.queueFlushBatchRemaining -= 1;
|
|
511695
512192
|
},
|
|
@@ -511975,6 +512472,21 @@ var BlunTUI = class {
|
|
|
511975
512472
|
/** Pending delivery guard for the channel-origin turn currently running. */
|
|
511976
512473
|
pendingChannelReplyGuard;
|
|
511977
512474
|
/** See SessionEventHost.runChannelReplyFallback — called at turn end. */
|
|
512475
|
+
channelMediaDeliveries = /* @__PURE__ */ new Set();
|
|
512476
|
+
/** Deliver completed media at tool-result time so later queued work cannot hide it. */
|
|
512477
|
+
runChannelMediaFallback(output) {
|
|
512478
|
+
const guard = this.pendingChannelReplyGuard;
|
|
512479
|
+
const filePath = completedMediaLocalPath(output);
|
|
512480
|
+
if (guard === void 0 || filePath === void 0) return;
|
|
512481
|
+
const deliveryKey = `${guard.chatId}\0${filePath}`;
|
|
512482
|
+
if (this.channelMediaDeliveries.has(deliveryKey)) return;
|
|
512483
|
+
this.channelMediaDeliveries.add(deliveryKey);
|
|
512484
|
+
sendMediaReplyFallback(guard.chatId, filePath).then((sent) => {
|
|
512485
|
+
if (sent) return;
|
|
512486
|
+
this.channelMediaDeliveries.delete(deliveryKey);
|
|
512487
|
+
this.showError(uiText("blunTui.session.sendFailed", { error: "Telegram media" }));
|
|
512488
|
+
});
|
|
512489
|
+
}
|
|
511978
512490
|
runChannelReplyFallback(reason) {
|
|
511979
512491
|
const guard = this.pendingChannelReplyGuard;
|
|
511980
512492
|
if (guard === void 0) return;
|