blun-king-cli 9.1.102 → 9.1.103

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
@@ -103,7 +103,7 @@ Das Telemetrieereignis `tool_result_batch_offloaded` meldet ausschließlich die
103
103
 
104
104
  Reguläre `Agent`-Teilaufgaben verwenden eine eigene `ContextMemory` und eine eigene `wire.jsonl` in einem getrennten Agentenverzeichnis. Der Hauptagent erhält nur die Ergebniszusammenfassung, sodass lange Teilaufgaben nicht den Hauptverlauf füllen. `TodoList` speichert Pläne weiterhin maschinenlesbar im Sitzungs-Wire; `blun handoff` übergibt sie zusammen mit prüfbaren Hashes zwischen CLI, Desktop und Web.
105
105
 
106
- Verliert ein delegierter Einzelagent die Provider-Verbindung, erhält er eine leere Provider-Antwort, trifft er auf einen Leerlaufabbruch des Streams oder meldet der Server einen wiederholbaren Status, setzt BLUN King denselben Agenten anhand seines dauerhaften Verlaufs fort. Die erste Fortsetzung wartet zwei Sekunden, die zweite fünf Sekunden; danach bleibt der ursprüngliche Fehler sichtbar. Die Fortsetzungsanweisung fordert den Agenten ausdrücklich auf, den erhaltenen Arbeitsstand zu prüfen und abgeschlossene Schritte nicht zu wiederholen. Authentifizierungs-, Guthaben-, Sicherheits-, Kontext- sowie beliebige Code- und Werkzeugfehler und manuelle Abbrüche bleiben endgültig. Dieser Schutz gilt für einen delegierten Einzelagenten; für Schwärme gelten weiterhin deren bestehende Zeitgrenzen- und Überlastungsregeln.
106
+ Verliert ein delegierter Einzelagent oder ein Mitglied eines Agentenschwarms die Provider-Verbindung, erhält es eine leere Provider-Antwort, bricht sein Stream wegen Leerlaufs ab oder meldet der Server HTTP 408/500/502/503/504, setzt BLUN King denselben Agenten anhand seines dauerhaften Verlaufs fort. Bei Einzelagenten sowie bei Schwarm-Unterbrechungen außerhalb von HTTP 429 wartet die erste Fortsetzung zwei Sekunden und die zweite fünf Sekunden; danach bleibt der ursprüngliche Fehler sichtbar. HTTP 429 behält im Schwarm seine getrennte, längere Überlastungsregel. Authentifizierungs-, Zahlungs- oder Kontingent-, Richtlinien-, Kontext-, Werkzeug- und Codefehler sowie manuelle Abbrüche lösen keine automatische Fortsetzung aus. Jeder Fortsetzungsversuch verwendet die bestehende Agenten-ID, damit bereits abgeschlossene Arbeit nicht wiederholt wird.
107
107
 
108
108
  Rein lesende Sitzungsdiagnose
109
109
  --------------------------------
@@ -74,6 +74,18 @@ function isRetryableSubagentFailure(error) {
74
74
  return RETRYABLE_MESSAGE_RE.test(message);
75
75
  }
76
76
 
77
+ function transientSubagentRetryDelayMs(retryCount) {
78
+ if (!Number.isInteger(retryCount) || retryCount < 1) {
79
+ throw new Error("retryCount must be a positive integer.");
80
+ }
81
+ return DEFAULT_TRANSIENT_RETRY_DELAYS_MS[retryCount - 1]
82
+ ?? DEFAULT_TRANSIENT_RETRY_DELAYS_MS.at(-1);
83
+ }
84
+
85
+ function shouldStopTransientSubagentContinuation(retryCount) {
86
+ return retryCount >= MAX_TRANSIENT_SUBAGENT_CONTINUATIONS;
87
+ }
88
+
77
89
  function waitForRetryDelay(delayMs, signal) {
78
90
  if (delayMs <= 0) return Promise.resolve();
79
91
  if (signal.aborted) return Promise.reject(abortError(signal.reason));
@@ -134,7 +146,8 @@ async function runAgentWithTimeoutContinuation({
134
146
  throw result.error;
135
147
  }
136
148
  const attempt = transientContinuations + 1;
137
- const delayMs = retryDelaysMs[transientContinuations] ?? retryDelaysMs.at(-1) ?? 0;
149
+ const delayMs = retryDelaysMs[transientContinuations]
150
+ ?? transientSubagentRetryDelayMs(attempt);
138
151
  transientContinuations = attempt;
139
152
  await waitForRetryDelay(delayMs, signal);
140
153
  currentHandle = await retrySameAgent(currentHandle.agentId, {
@@ -164,4 +177,6 @@ module.exports = {
164
177
  isRetryableSubagentFailure,
165
178
  resolveSubagentTimeoutMs,
166
179
  runAgentWithTimeoutContinuation,
180
+ shouldStopTransientSubagentContinuation,
181
+ transientSubagentRetryDelayMs,
167
182
  };
package/blun.mjs CHANGED
@@ -251353,18 +251353,20 @@ function resolveSwarmMaxConcurrency(env = process.env) {
251353
251353
  if (!Number.isInteger(value) || value <= 0) throw new Error(`${AGENT_SWARM_MAX_CONCURRENCY_ENV} must be a positive integer, got ${JSON.stringify(raw)}.`);
251354
251354
  return value;
251355
251355
  }
251356
- var import_retry, INITIAL_LAUNCH_LIMIT, INITIAL_LAUNCH_INTERVAL_MS, RATE_LIMIT_RETRY_BASE_MS, RATE_LIMIT_RETRY_FACTOR, RATE_LIMIT_CAPACITY_SHRINK_INTERVAL_MS, RATE_LIMIT_CAPACITY_RECOVERY_INTERVAL_MS, RATE_LIMIT_SUSPENDED_REASON, AGENT_SWARM_MAX_CONCURRENCY_ENV, MAX_AUTOMATIC_RATE_LIMIT_RESUMES, rateLimitRetryDelayMs, shouldCompactBeforeRateLimitResume, shouldStopAutomaticRateLimitResume, SubagentBatch;
251356
+ var import_retry, INITIAL_LAUNCH_LIMIT, INITIAL_LAUNCH_INTERVAL_MS, RATE_LIMIT_RETRY_BASE_MS, RATE_LIMIT_RETRY_FACTOR, RATE_LIMIT_CAPACITY_SHRINK_INTERVAL_MS, RATE_LIMIT_CAPACITY_RECOVERY_INTERVAL_MS, RATE_LIMIT_SUSPENDED_REASON, TRANSIENT_PROVIDER_SUSPENDED_REASON, AGENT_SWARM_MAX_CONCURRENCY_ENV, MAX_AUTOMATIC_RATE_LIMIT_RESUMES, MAX_TRANSIENT_SUBAGENT_CONTINUATIONS, isRetryableSubagentFailure, rateLimitRetryDelayMs, shouldCompactBeforeRateLimitResume, shouldStopAutomaticRateLimitResume, shouldStopTransientSubagentContinuation, transientSubagentRetryDelayMs, SubagentBatch;
251357
251357
  var init_subagent_batch = __esmMin((() => {
251358
251358
  init_src$4();
251359
251359
  import_retry = /* @__PURE__ */ __toESM(require_retry$1(), 1);
251360
251360
  init_abort();
251361
251361
  ({ MAX_AUTOMATIC_RATE_LIMIT_RESUMES, RATE_LIMIT_RETRY_BASE_MS, rateLimitRetryDelayMs, shouldCompactBeforeRateLimitResume, shouldStopAutomaticRateLimitResume } = createRequire(import.meta.url)("./bin/rate-limit-recovery-policy.cjs"));
251362
+ ({ MAX_TRANSIENT_SUBAGENT_CONTINUATIONS, isRetryableSubagentFailure, shouldStopTransientSubagentContinuation, transientSubagentRetryDelayMs } = createRequire(import.meta.url)("./bin/subagent-timeout-policy.cjs"));
251362
251363
  INITIAL_LAUNCH_LIMIT = 5;
251363
251364
  INITIAL_LAUNCH_INTERVAL_MS = 700;
251364
251365
  RATE_LIMIT_RETRY_FACTOR = 2;
251365
251366
  RATE_LIMIT_CAPACITY_SHRINK_INTERVAL_MS = 2e3;
251366
251367
  RATE_LIMIT_CAPACITY_RECOVERY_INTERVAL_MS = 180 * 1e3;
251367
251368
  RATE_LIMIT_SUSPENDED_REASON = "Provider rate limit; subagent requeued for retry.";
251369
+ TRANSIENT_PROVIDER_SUSPENDED_REASON = "Transient provider interruption; subagent requeued for continuation.";
251368
251370
  AGENT_SWARM_MAX_CONCURRENCY_ENV = "BLUN_AGENT_SWARM_MAX_CONCURRENCY";
251369
251371
  SubagentBatch = class {
251370
251372
  launcher;
@@ -251379,6 +251381,7 @@ var init_subagent_batch = __esmMin((() => {
251379
251381
  normalLaunchCount = 0;
251380
251382
  normalLaunchTimer;
251381
251383
  rateLimitLaunchTimer;
251384
+ transientRetryTimers = /* @__PURE__ */ new Set();
251382
251385
  resolve;
251383
251386
  reject;
251384
251387
  finished = false;
@@ -251398,6 +251401,7 @@ var init_subagent_batch = __esmMin((() => {
251398
251401
  index,
251399
251402
  task,
251400
251403
  retryCount: 0,
251404
+ transientRetryCount: 0,
251401
251405
  retryReadyAt: 0,
251402
251406
  started: false
251403
251407
  }));
@@ -251540,6 +251544,11 @@ var init_subagent_batch = __esmMin((() => {
251540
251544
  agentId: handle.agentId,
251541
251545
  error: this.attemptErrorMessage(attempt, error, "failed")
251542
251546
  };
251547
+ if (isRetryableSubagentFailure(error)) return {
251548
+ type: "transient_provider",
251549
+ agentId: handle.agentId,
251550
+ error: this.attemptErrorMessage(attempt, error, "failed")
251551
+ };
251543
251552
  return this.failedAttemptOutcome(attempt, error);
251544
251553
  }
251545
251554
  }
@@ -251571,6 +251580,14 @@ var init_subagent_batch = __esmMin((() => {
251571
251580
  this.requeueTimedOut(attempt, outcome.agentId);
251572
251581
  }
251573
251582
  else if ("status" in outcome) this.results[attempt.state.index] = outcome;
251583
+ else if (outcome.type === "transient_provider" && shouldStopTransientSubagentContinuation(attempt.state.transientRetryCount)) this.results[attempt.state.index] = {
251584
+ task: attempt.state.task,
251585
+ agentId: outcome.agentId,
251586
+ status: "failed",
251587
+ state: "started",
251588
+ error: `${outcome.error} Automatic continuation stopped after ${String(MAX_TRANSIENT_SUBAGENT_CONTINUATIONS)} attempts; agent ${outcome.agentId} remains resumable.`
251589
+ };
251590
+ else if (outcome.type === "transient_provider") this.requeueTransientProvider(attempt, outcome.agentId);
251574
251591
  else if (shouldStopAutomaticRateLimitResume(attempt.state.retryCount)) this.results[attempt.state.index] = {
251575
251592
  task: attempt.state.task,
251576
251593
  agentId: outcome.agentId,
@@ -251604,6 +251621,26 @@ var init_subagent_batch = __esmMin((() => {
251604
251621
  attempt.cleanup();
251605
251622
  return true;
251606
251623
  }
251624
+ requeueTransientProvider(attempt, agentId) {
251625
+ const state = attempt.state;
251626
+ state.agentId = agentId;
251627
+ state.retryAgentId = agentId;
251628
+ state.transientRetryCount += 1;
251629
+ this.launcher.suspended?.({
251630
+ task: state.task,
251631
+ agentId,
251632
+ reason: TRANSIENT_PROVIDER_SUSPENDED_REASON
251633
+ });
251634
+ const retryDelay = transientSubagentRetryDelayMs(state.transientRetryCount);
251635
+ const timer = setTimeout(() => {
251636
+ this.transientRetryTimers.delete(timer);
251637
+ if (this.finished || this.controller.signal.aborted) return;
251638
+ state.retryReadyAt = 0;
251639
+ this.pending.unshift(state);
251640
+ this.schedule();
251641
+ }, retryDelay);
251642
+ this.transientRetryTimers.add(timer);
251643
+ }
251607
251644
  requeueRateLimited(attempt, agentId) {
251608
251645
  const state = attempt.state;
251609
251646
  state.agentId = agentId;
@@ -251714,6 +251751,8 @@ var init_subagent_batch = __esmMin((() => {
251714
251751
  this.batchSignal?.removeEventListener("abort", this.batchAbortListener);
251715
251752
  this.clearNormalTimer();
251716
251753
  this.clearRateLimitTimer();
251754
+ for (const timer of this.transientRetryTimers) clearTimeout(timer);
251755
+ this.transientRetryTimers.clear();
251717
251756
  for (const attempt of this.active.values()) attempt.cleanup();
251718
251757
  this.active.clear();
251719
251758
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "9.1.102",
3
+ "version": "9.1.103",
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": {