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 CHANGED
@@ -9,7 +9,7 @@ Installation
9
9
  ------------
10
10
  Die geprüfte Version exakt global installieren:
11
11
 
12
- npm install -g blun-king-cli@9.1.35
12
+ npm install -g blun-king-cli@9.1.36
13
13
 
14
14
  Start
15
15
  -----
package/README.md CHANGED
@@ -9,7 +9,7 @@ Voraussetzung ist Node.js 24.15 oder neuer. Die geprüfte Version wird exakt
9
9
  installiert:
10
10
 
11
11
  ```powershell
12
- npm install -g blun-king-cli@9.1.35
12
+ npm install -g blun-king-cli@9.1.36
13
13
  ```
14
14
 
15
15
  ## Reproduzierbares Staging und Packen
package/blun.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // BLUN_BUILD_INPUT_SHA256:760e619c78a4f7144ea03820db15402ea00e8058f86f431c12fb1bbb633de6b9
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 emptyRetryStarted = false;
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 && (emptyRetryStarted || error.emptyResponseKind === "length" || error.emptyResponseKind === "stop")) {
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 >= emptyAttemptLimit) {
30114
- const terminal = error.withMetadata({ attempts: attempt });
30115
- logRequestFailure(input, terminal, attempt, emptyAttemptLimit);
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: 1024,
30186
+ minimumCompletionTokens: MIN_THINKING_COMPLETION_TOKENS,
30120
30187
  multiplier: 2
30121
30188
  } : void 0;
30122
- emptyRetryStarted = true;
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: emptyAttemptLimit,
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),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.35",
3
+ "version": "9.1.36",
4
4
  "description": "BLUN CLI - your own AI agent with a Telegram channel. Get it done. With BLUN.",
5
5
  "license": "MIT",
6
6
  "bin": {