blun-king-cli 9.1.35 → 9.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LIESMICH.txt +1 -1
- package/README.md +1 -1
- package/blun.mjs +92 -80
- package/package.json +1 -1
package/LIESMICH.txt
CHANGED
package/README.md
CHANGED
package/blun.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// BLUN_BUILD_INPUT_SHA256:
|
|
2
|
+
// BLUN_BUILD_INPUT_SHA256:0a9b399298f68e4bffadcc1ead801f14012d39becc3a208a737071e6bb201f97
|
|
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);
|
|
@@ -30089,6 +30089,74 @@ var init_abort = __esmMin((() => {
|
|
|
30089
30089
|
};
|
|
30090
30090
|
}));
|
|
30091
30091
|
//#endregion
|
|
30092
|
+
//#region ../../packages/agent-core/src/utils/completion-budget.ts
|
|
30093
|
+
/**
|
|
30094
|
+
* Resolve configured completion budget. Env values are explicit hard caps;
|
|
30095
|
+
* non-positive env values disable clamping.
|
|
30096
|
+
*/
|
|
30097
|
+
function resolveCompletionBudget(args) {
|
|
30098
|
+
const env = args.env ?? process.env;
|
|
30099
|
+
const fromNew = parseEnvBudget(env["BLUN_MODEL_MAX_COMPLETION_TOKENS"]);
|
|
30100
|
+
if (fromNew !== "absent") return fromNew === "disabled" ? void 0 : { hardCap: fromNew };
|
|
30101
|
+
const fromLegacy = parseEnvBudget(env["BLUN_MODEL_MAX_TOKENS"]);
|
|
30102
|
+
if (fromLegacy !== "absent") return fromLegacy === "disabled" ? void 0 : { hardCap: fromLegacy };
|
|
30103
|
+
if (args.maxOutputSize !== void 0 && args.maxOutputSize > 0) return { hardCap: args.maxOutputSize };
|
|
30104
|
+
if (args.reservedContextSize !== void 0 && args.reservedContextSize > 0) return { fallback: args.reservedContextSize };
|
|
30105
|
+
return { fallback: DEFAULT_UNKNOWN_CONTEXT_FALLBACK };
|
|
30106
|
+
}
|
|
30107
|
+
function parseEnvBudget(raw) {
|
|
30108
|
+
if (raw === void 0 || raw === "") return "absent";
|
|
30109
|
+
const n = Number(raw);
|
|
30110
|
+
if (!Number.isFinite(n) || !Number.isInteger(n)) return "absent";
|
|
30111
|
+
if (n <= 0) return "disabled";
|
|
30112
|
+
return n;
|
|
30113
|
+
}
|
|
30114
|
+
/**
|
|
30115
|
+
* Compute the effective `max_completion_tokens` cap.
|
|
30116
|
+
*/
|
|
30117
|
+
function computeCompletionBudgetCap(args) {
|
|
30118
|
+
const maxCtx = args.capability?.max_context_tokens ?? 0;
|
|
30119
|
+
const cap = args.budget.hardCap ?? (maxCtx > 0 ? maxCtx : args.budget.fallback ?? DEFAULT_UNKNOWN_CONTEXT_FALLBACK);
|
|
30120
|
+
return Math.max(MIN_FLOOR, cap);
|
|
30121
|
+
}
|
|
30122
|
+
/**
|
|
30123
|
+
* Apply a completion budget to a provider via its optional
|
|
30124
|
+
* `withMaxCompletionTokens` capability. Returns the original provider
|
|
30125
|
+
* unchanged when no budget is configured or the provider opts out.
|
|
30126
|
+
*
|
|
30127
|
+
* The returned provider is intentionally a shallow clone that shares the
|
|
30128
|
+
* original's HTTP client. Callers MUST treat it as a single-step value
|
|
30129
|
+
* and NOT persist it back to durable agent state — see the F3 discussion
|
|
30130
|
+
* in `BlunChatProvider._clone()`.
|
|
30131
|
+
*/
|
|
30132
|
+
function applyCompletionBudget(args) {
|
|
30133
|
+
return applyCompletionBudgetWithDetails(args).provider;
|
|
30134
|
+
}
|
|
30135
|
+
function applyCompletionBudgetWithDetails(args) {
|
|
30136
|
+
if (args.budget === void 0) return { provider: args.provider };
|
|
30137
|
+
if (args.provider.withMaxCompletionTokens === void 0) return { provider: args.provider };
|
|
30138
|
+
let cap = computeCompletionBudgetCap({
|
|
30139
|
+
budget: args.budget,
|
|
30140
|
+
capability: args.capability
|
|
30141
|
+
});
|
|
30142
|
+
if (args.retry !== void 0) cap = Math.max(args.retry.minimumCompletionTokens, Math.ceil(cap * args.retry.multiplier));
|
|
30143
|
+
const maxContextTokens = args.capability?.max_context_tokens;
|
|
30144
|
+
if (args.usedContextTokens !== void 0 && maxContextTokens !== void 0 && maxContextTokens > 0) cap = Math.max(MIN_FLOOR, Math.min(cap, maxContextTokens - args.usedContextTokens));
|
|
30145
|
+
return {
|
|
30146
|
+
provider: args.provider.withMaxCompletionTokens(cap, {
|
|
30147
|
+
usedContextTokens: args.usedContextTokens,
|
|
30148
|
+
maxContextTokens
|
|
30149
|
+
}),
|
|
30150
|
+
maxCompletionTokens: cap
|
|
30151
|
+
};
|
|
30152
|
+
}
|
|
30153
|
+
var MIN_FLOOR, DEFAULT_UNKNOWN_CONTEXT_FALLBACK, MIN_THINKING_COMPLETION_TOKENS;
|
|
30154
|
+
var init_completion_budget = __esmMin((() => {
|
|
30155
|
+
MIN_FLOOR = 1;
|
|
30156
|
+
DEFAULT_UNKNOWN_CONTEXT_FALLBACK = 32e3;
|
|
30157
|
+
MIN_THINKING_COMPLETION_TOKENS = 1024;
|
|
30158
|
+
}));
|
|
30159
|
+
//#endregion
|
|
30092
30160
|
//#region ../../packages/agent-core/src/loop/retry.ts
|
|
30093
30161
|
async function chatWithRetry(input) {
|
|
30094
30162
|
const maxAttempts = input.maxAttempts ?? 3;
|
|
@@ -30103,23 +30171,22 @@ async function chatWithRetry(input) {
|
|
|
30103
30171
|
}
|
|
30104
30172
|
const delays = retryBackoffDelays(maxAttempts);
|
|
30105
30173
|
let completionBudgetRetry;
|
|
30106
|
-
let
|
|
30174
|
+
let emptyRetryKind;
|
|
30107
30175
|
for (let attempt = 1;; attempt += 1) try {
|
|
30108
30176
|
return await input.llm.chat(paramsForAttempt(input, attempt, maxAttempts, completionBudgetRetry));
|
|
30109
30177
|
} catch (error) {
|
|
30110
|
-
if (error instanceof APIEmptyResponseError && (
|
|
30111
|
-
const emptyAttemptLimit = Math.min(maxAttempts, 2);
|
|
30178
|
+
if (error instanceof APIEmptyResponseError && (emptyRetryKind !== void 0 || error.emptyResponseKind === "length" || error.emptyResponseKind === "stop")) {
|
|
30112
30179
|
logEmptyResponse(input, error, attempt);
|
|
30113
|
-
if (attempt >=
|
|
30114
|
-
const terminal = error.withMetadata({ attempts:
|
|
30115
|
-
logRequestFailure(input, terminal, attempt,
|
|
30180
|
+
if (emptyRetryKind !== void 0 || attempt >= maxAttempts) {
|
|
30181
|
+
const terminal = error.withMetadata({ attempts: emptyRetryKind === error.emptyResponseKind ? 2 : 1 });
|
|
30182
|
+
logRequestFailure(input, terminal, attempt, maxAttempts);
|
|
30116
30183
|
throw terminal;
|
|
30117
30184
|
}
|
|
30118
30185
|
completionBudgetRetry = error.emptyResponseKind === "length" ? {
|
|
30119
|
-
minimumCompletionTokens:
|
|
30186
|
+
minimumCompletionTokens: MIN_THINKING_COMPLETION_TOKENS,
|
|
30120
30187
|
multiplier: 2
|
|
30121
30188
|
} : void 0;
|
|
30122
|
-
|
|
30189
|
+
emptyRetryKind = error.emptyResponseKind;
|
|
30123
30190
|
input.params.signal.throwIfAborted();
|
|
30124
30191
|
input.dispatchEvent({
|
|
30125
30192
|
type: "step.retrying",
|
|
@@ -30128,7 +30195,7 @@ async function chatWithRetry(input) {
|
|
|
30128
30195
|
stepUuid: input.stepUuid,
|
|
30129
30196
|
failedAttempt: attempt,
|
|
30130
30197
|
nextAttempt: attempt + 1,
|
|
30131
|
-
maxAttempts
|
|
30198
|
+
maxAttempts,
|
|
30132
30199
|
delayMs: 0,
|
|
30133
30200
|
...retryErrorFields(error)
|
|
30134
30201
|
});
|
|
@@ -30214,6 +30281,7 @@ var init_retry = __esmMin((() => {
|
|
|
30214
30281
|
init_src$4();
|
|
30215
30282
|
import_retry$1 = /* @__PURE__ */ __toESM(require_retry$1(), 1);
|
|
30216
30283
|
init_abort();
|
|
30284
|
+
init_completion_budget();
|
|
30217
30285
|
init_errors$4();
|
|
30218
30286
|
RETRY_MIN_TIMEOUT_MS = 300;
|
|
30219
30287
|
RETRY_MAX_TIMEOUT_MS = 5e3;
|
|
@@ -30832,73 +30900,6 @@ var init_tokens = __esmMin((() => {
|
|
|
30832
30900
|
MAX_IMAGE_HEADER_BYTES = 1024 * 1024;
|
|
30833
30901
|
}));
|
|
30834
30902
|
//#endregion
|
|
30835
|
-
//#region ../../packages/agent-core/src/utils/completion-budget.ts
|
|
30836
|
-
/**
|
|
30837
|
-
* Resolve configured completion budget. Env values are explicit hard caps;
|
|
30838
|
-
* non-positive env values disable clamping.
|
|
30839
|
-
*/
|
|
30840
|
-
function resolveCompletionBudget(args) {
|
|
30841
|
-
const env = args.env ?? process.env;
|
|
30842
|
-
const fromNew = parseEnvBudget(env["BLUN_MODEL_MAX_COMPLETION_TOKENS"]);
|
|
30843
|
-
if (fromNew !== "absent") return fromNew === "disabled" ? void 0 : { hardCap: fromNew };
|
|
30844
|
-
const fromLegacy = parseEnvBudget(env["BLUN_MODEL_MAX_TOKENS"]);
|
|
30845
|
-
if (fromLegacy !== "absent") return fromLegacy === "disabled" ? void 0 : { hardCap: fromLegacy };
|
|
30846
|
-
if (args.maxOutputSize !== void 0 && args.maxOutputSize > 0) return { hardCap: args.maxOutputSize };
|
|
30847
|
-
if (args.reservedContextSize !== void 0 && args.reservedContextSize > 0) return { fallback: args.reservedContextSize };
|
|
30848
|
-
return { fallback: DEFAULT_UNKNOWN_CONTEXT_FALLBACK };
|
|
30849
|
-
}
|
|
30850
|
-
function parseEnvBudget(raw) {
|
|
30851
|
-
if (raw === void 0 || raw === "") return "absent";
|
|
30852
|
-
const n = Number(raw);
|
|
30853
|
-
if (!Number.isFinite(n) || !Number.isInteger(n)) return "absent";
|
|
30854
|
-
if (n <= 0) return "disabled";
|
|
30855
|
-
return n;
|
|
30856
|
-
}
|
|
30857
|
-
/**
|
|
30858
|
-
* Compute the effective `max_completion_tokens` cap.
|
|
30859
|
-
*/
|
|
30860
|
-
function computeCompletionBudgetCap(args) {
|
|
30861
|
-
const maxCtx = args.capability?.max_context_tokens ?? 0;
|
|
30862
|
-
const cap = args.budget.hardCap ?? (maxCtx > 0 ? maxCtx : args.budget.fallback ?? DEFAULT_UNKNOWN_CONTEXT_FALLBACK);
|
|
30863
|
-
return Math.max(MIN_FLOOR, cap);
|
|
30864
|
-
}
|
|
30865
|
-
/**
|
|
30866
|
-
* Apply a completion budget to a provider via its optional
|
|
30867
|
-
* `withMaxCompletionTokens` capability. Returns the original provider
|
|
30868
|
-
* unchanged when no budget is configured or the provider opts out.
|
|
30869
|
-
*
|
|
30870
|
-
* The returned provider is intentionally a shallow clone that shares the
|
|
30871
|
-
* original's HTTP client. Callers MUST treat it as a single-step value
|
|
30872
|
-
* and NOT persist it back to durable agent state — see the F3 discussion
|
|
30873
|
-
* in `BlunChatProvider._clone()`.
|
|
30874
|
-
*/
|
|
30875
|
-
function applyCompletionBudget(args) {
|
|
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 };
|
|
30881
|
-
let cap = computeCompletionBudgetCap({
|
|
30882
|
-
budget: args.budget,
|
|
30883
|
-
capability: args.capability
|
|
30884
|
-
});
|
|
30885
|
-
if (args.retry !== void 0) cap = Math.max(args.retry.minimumCompletionTokens, Math.ceil(cap * args.retry.multiplier));
|
|
30886
|
-
const maxContextTokens = args.capability?.max_context_tokens;
|
|
30887
|
-
if (args.usedContextTokens !== void 0 && maxContextTokens !== void 0 && maxContextTokens > 0) cap = Math.max(MIN_FLOOR, Math.min(cap, maxContextTokens - args.usedContextTokens));
|
|
30888
|
-
return {
|
|
30889
|
-
provider: args.provider.withMaxCompletionTokens(cap, {
|
|
30890
|
-
usedContextTokens: args.usedContextTokens,
|
|
30891
|
-
maxContextTokens
|
|
30892
|
-
}),
|
|
30893
|
-
maxCompletionTokens: cap
|
|
30894
|
-
};
|
|
30895
|
-
}
|
|
30896
|
-
var MIN_FLOOR, DEFAULT_UNKNOWN_CONTEXT_FALLBACK;
|
|
30897
|
-
var init_completion_budget = __esmMin((() => {
|
|
30898
|
-
MIN_FLOOR = 1;
|
|
30899
|
-
DEFAULT_UNKNOWN_CONTEXT_FALLBACK = 32e3;
|
|
30900
|
-
}));
|
|
30901
|
-
//#endregion
|
|
30902
30903
|
//#region ../../node_modules/.pnpm/bmp-ts@1.0.9/node_modules/bmp-ts/dist/esm/header-types.js
|
|
30903
30904
|
var HeaderTypes, header_types_default;
|
|
30904
30905
|
var init_header_types = __esmMin((() => {
|
|
@@ -74369,6 +74370,9 @@ var init_vision_reader = __esmMin((() => {
|
|
|
74369
74370
|
}));
|
|
74370
74371
|
//#endregion
|
|
74371
74372
|
//#region ../../packages/agent-core/src/agent/turn/kosong-llm.ts
|
|
74373
|
+
function thinkingEnabled(effort) {
|
|
74374
|
+
return effort !== null && effort !== "off" && effort !== "none";
|
|
74375
|
+
}
|
|
74372
74376
|
function buildStreamTiming(requestStartedAt, requestSentAt, firstChunkAt, streamEndedAt, decodeStats) {
|
|
74373
74377
|
const outputEndedAt = streamEndedAt ?? Date.now();
|
|
74374
74378
|
const timing = {
|
|
@@ -74611,7 +74615,10 @@ var init_kosong_llm = __esmMin((() => {
|
|
|
74611
74615
|
budget: this.completionBudgetConfig,
|
|
74612
74616
|
capability: this.capability,
|
|
74613
74617
|
usedContextTokens,
|
|
74614
|
-
retry: params.completionBudgetRetry
|
|
74618
|
+
retry: params.completionBudgetRetry ?? (thinkingEnabled(this.provider.thinkingEffort) ? {
|
|
74619
|
+
minimumCompletionTokens: 1024,
|
|
74620
|
+
multiplier: 1
|
|
74621
|
+
} : void 0)
|
|
74615
74622
|
});
|
|
74616
74623
|
result = await this.generate(completionBudget.provider, this.systemPrompt, tools, outgoingMessages, callbacks, options);
|
|
74617
74624
|
} catch (error) {
|
|
@@ -259405,6 +259412,10 @@ function blunThinkingIntentInput(input) {
|
|
|
259405
259412
|
text: channelText
|
|
259406
259413
|
}];
|
|
259407
259414
|
}
|
|
259415
|
+
function blunToolsForOrigin(tools, origin) {
|
|
259416
|
+
if (origin.kind !== "system_trigger" && origin.kind !== "injection") return tools;
|
|
259417
|
+
return tools.filter((tool) => !BLUN_TELEGRAM_OUTBOUND_TOOL_RE.test(tool.name));
|
|
259418
|
+
}
|
|
259408
259419
|
/**
|
|
259409
259420
|
* Choose the tool set for a task turn. Returns the full set unless the model
|
|
259410
259421
|
* window is small enough that the schemas alone blow the context budget, in
|
|
@@ -259636,7 +259647,7 @@ function toolResultText(result) {
|
|
|
259636
259647
|
function abandonedToolResultOutput(ended) {
|
|
259637
259648
|
return `Tool call did not complete: ${ended.reason === "cancelled" ? "the turn was cancelled" : ended.reason === "failed" ? `the turn failed${ended.error !== void 0 ? ` (${ended.error.message})` : ""}` : "the turn ended"} before its result was recorded. Do not assume the tool completed successfully.`;
|
|
259638
259649
|
}
|
|
259639
|
-
var BLUN_LEAN_TOOL_NAMES, BLUN_LEAN_KEEP_RE, BLUN_TOOL_BUDGET_RATIO, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
259650
|
+
var BLUN_LEAN_TOOL_NAMES, BLUN_LEAN_KEEP_RE, BLUN_TELEGRAM_OUTBOUND_TOOL_RE, BLUN_TOOL_BUDGET_RATIO, LLM_NOT_SET_MESSAGE, GOAL_CONTINUATION_ORIGIN, GOAL_COMPLETION_REMINDER_NAME, GOAL_BLOCKED_REMINDER_NAME, GOAL_RATE_LIMIT_PAUSE_REASON, GOAL_PROVIDER_CONNECTION_PAUSE_PREFIX, GOAL_PROVIDER_AUTH_PAUSE_PREFIX, GOAL_PROVIDER_API_PAUSE_PREFIX, GOAL_MODEL_CONFIG_PAUSE_PREFIX, GOAL_RUNTIME_PAUSE_PREFIX, GOAL_PROVIDER_FILTERED_PAUSE_REASON, GOAL_CONTINUATION_PROMPT, TurnFlow;
|
|
259640
259651
|
var init_turn = __esmMin((() => {
|
|
259641
259652
|
init_dist$4();
|
|
259642
259653
|
init_src$4();
|
|
@@ -259662,6 +259673,7 @@ var init_turn = __esmMin((() => {
|
|
|
259662
259673
|
"MistakeRecord"
|
|
259663
259674
|
]);
|
|
259664
259675
|
BLUN_LEAN_KEEP_RE = /(^|__|:)(reply|react|edit_message|download_attachment|memory_(?:status|settings_update|remember|list|threads_list|recall))$/i;
|
|
259676
|
+
BLUN_TELEGRAM_OUTBOUND_TOOL_RE = /^mcp__[^\s]*telegram[^\s]*__(?:reply|react|edit_message)$/i;
|
|
259665
259677
|
BLUN_TOOL_BUDGET_RATIO = .25;
|
|
259666
259678
|
LLM_NOT_SET_MESSAGE = "LLM not set, send \"/login\" to login";
|
|
259667
259679
|
GOAL_CONTINUATION_ORIGIN = {
|
|
@@ -260229,7 +260241,7 @@ var init_turn = __esmMin((() => {
|
|
|
260229
260241
|
const loopControl = this.agent.blunConfig?.loopControl;
|
|
260230
260242
|
let stopForGoalBudget = false;
|
|
260231
260243
|
try {
|
|
260232
|
-
const eligibleTools = this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools);
|
|
260244
|
+
const eligibleTools = blunToolsForOrigin(this.agent.injection.filterPersonalMemoryToolsForTurn(turnId, input, origin, this.agent.tools.loopTools), origin);
|
|
260233
260245
|
const selectedTools = turnNeedsTools ? blunSelectTurnTools(eligibleTools, this.agent.config.modelCapabilities?.max_context_tokens) : [];
|
|
260234
260246
|
return (await runTurn({
|
|
260235
260247
|
turnId: String(turnId),
|