scream-code 0.18.5 → 0.18.7

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.
@@ -4,9 +4,9 @@ import { dirname as __cjsShimDirname } from 'node:path';
4
4
  const __filename = __cjsShimFileURLToPath(import.meta.url);
5
5
  const __dirname = __cjsShimDirname(__filename);
6
6
  import "./suppress-sqlite-warning-C2VB0doZ.mjs";
7
- import { A as sharedMemoStore } from "./src-C7C9e5Ds.mjs";
8
- import { $ as refineGoal, $n as ScreamHarness, $t as FooterComponent, A as renderDiffLinesClustered, An as setExperimentalFlags, At as isEmptySessionHintDismissed, B as AssistantMessageComponent, Bn as saveTuiConfig, Bt as ENABLE_TERMINAL_FOCUS_REPORTING, C as readJsonlFile, Cn as getCtrlDHint, Ct as supportsBalance, D as UserMessageComponent, Dn as BUILTIN_SLASH_COMMANDS, Dt as resolveThemeSync, En as buildSkillSlashCommands, F as NoticeMessageComponent, Fn as PIXEL_PULSE_FRAMES, Ft as getColorPalette, G as BackgroundAgentStatusComponent, Gn as detectInstallSource, Gt as OSC11_RESPONSE_PREFIX_NO_ESC, H as charsForTokenBudget, Hn as getDataDir, Ht as OSC11_QUERY, I as StatusMessageComponent, In as PULSE_WAVE_FRAMES, It as detectTerminalTheme, J as BREATHE_CYCLE_MS, Jn as CLI_USER_AGENT_PRODUCT, Jt as TERMINAL_FOCUS_OUT, K as AgentGroupComponent, Kn as CLI_COMMAND_NAME, Kt as QUERY_TERMINAL_THEME, L as replaceTabs, Ln as TuiConfigParseError, Lt as parseOsc11BackgroundTheme, M as langFromPath, Mn as getKnowledgeStore, Mt as toggleEmptySessionHint, N as CachedContainer, Nn as hasEmbeddingModelCache, Nt as createThemeStyles, O as ToolCallComponent, On as sortSlashCommands, Ot as createEditorTheme, P as ThinkingComponent, Pn as startManualEmbeddingDownload, Pt as contrastTextHex, Q as clearGoalState, Qn as saveCatalogCache, Qt as isStreaming, R as sanitizeShellOutput, Rn as TuiLikePreferencesSchema, Rt as DISABLE_TERMINAL_FOCUS_REPORTING, S as appendJsonlLine, Sn as getCtrlCHint, St as refreshProviderBalance, T as getDaemonInstructions, Tn as getNoActiveSessionMessage, U as estimateTokens, Un as getInputHistoryFile, Ut as OSC11_RESPONSE, V as ActivityGroupComponent, Vn as detectShellEnvironment, Vt as ENABLE_TERMINAL_THEME_REPORTING, W as getSharedSpeedTracker, Wn as getLogDir, Wt as OSC11_RESPONSE_PREFIX, X as resetBreathingClock, Xn as DEFAULT_CATALOG_URL, Xt as TERMINAL_THEME_LIGHT, Y as getBreathingFrame, Yn as PRODUCT_NAME, Yt as TERMINAL_THEME_DARK, Z as CompactionComponent, Zn as fetchCatalog, Zt as isBusy, _n as EMPTY_SESSION_HINT_URL, a as buildRoleAdditionalText, at as isInternalMessage, b as refreshUpdateCache, bn as SESSION_TIPS, cn as appendSessionHeaderHint, cr as resolveScreamHome, ct as getModelCycleLevel, d as isExpandable, dn as formatErrorMessage, dr as resolveGlobalLogPath, en as lerpGradient, er as encodeWorkDirKey, f as isPlanExpandable, fn as isTodoItemShape, fr as isScreamError, gn as truncateErrorMessage, hn as stringValue, hr as SCREAM_ERROR_INFO, ht as handlePlanCommand, i as openUrl, ir as removeSessionIndexEntry, j as highlightLines, jn as embeddingFailureDetail, jt as isTurnElapsedEnabled, k as renderDiffLines, kn as isExperimentalFlagEnabled, kt as createMarkdownTheme, l as disposeChildren, ln as appendStreamingArgsPreview, lr as flushDiagnosticLogs, m as formatMemoryMemoForInjection, mn as serializeToolResultOutput, mr as ErrorCodes, n as clearEvalPanelState, nr as appendSessionIndexEntry, o as syncDiagramCapabilityPrompt, on as printableChar, or as isRealUserPrompt, ot as toTerminalHyperlink, p as MoonLoader, pn as parseStreamingArgs, pr as isOrphanedToolCallError, pt as handleFusionPlanCommand, q as WelcomeComponent, qn as CLI_UI_MODE, qt as TERMINAL_FOCUS_IN, rr as readSessionIndex, sn as STATUS_BULLET, sr as parseRlmMaxDepthArg, st as changeThinkingLevel, t as dispatchInput, tn as SubagentSlots, tr as normalizeWorkDir, u as hasDispose, un as argsRecord, ur as log, vn as EXIT_CONFIRM_WINDOW_MS, wn as getLlmNotSetMessage, wt as clearInfoPanelState, x as readUpdateCache, xn as TIP_ROTATION_INTERVAL_MS, y as selectUpdateTarget, yn as MAIN_AGENT_ID, z as SkillActivationComponent, zn as loadTuiConfig, zt as DISABLE_TERMINAL_THEME_REPORTING } from "./dispatch-BFsePVX6.mjs";
9
- import { i as t, n as getLocale, r as setLocale } from "./text-input-dialog-CxdRYbA4.mjs";
7
+ import { A as sharedMemoStore } from "./src-CQwXASmd.mjs";
8
+ import { $ as refineGoal, $n as ScreamHarness, $t as FooterComponent, A as renderDiffLinesClustered, An as setExperimentalFlags, At as isEmptySessionHintDismissed, B as AssistantMessageComponent, Bn as saveTuiConfig, Bt as ENABLE_TERMINAL_FOCUS_REPORTING, C as readJsonlFile, Cn as getCtrlDHint, Ct as supportsBalance, D as UserMessageComponent, Dn as BUILTIN_SLASH_COMMANDS, Dt as resolveThemeSync, En as buildSkillSlashCommands, F as NoticeMessageComponent, Fn as PIXEL_PULSE_FRAMES, Ft as getColorPalette, G as BackgroundAgentStatusComponent, Gn as detectInstallSource, Gt as OSC11_RESPONSE_PREFIX_NO_ESC, H as charsForTokenBudget, Hn as getDataDir, Ht as OSC11_QUERY, I as StatusMessageComponent, In as PULSE_WAVE_FRAMES, It as detectTerminalTheme, J as BREATHE_CYCLE_MS, Jn as CLI_USER_AGENT_PRODUCT, Jt as TERMINAL_FOCUS_OUT, K as AgentGroupComponent, Kn as CLI_COMMAND_NAME, Kt as QUERY_TERMINAL_THEME, L as replaceTabs, Ln as TuiConfigParseError, Lt as parseOsc11BackgroundTheme, M as langFromPath, Mn as getKnowledgeStore, Mt as toggleEmptySessionHint, N as CachedContainer, Nn as hasEmbeddingModelCache, Nt as createThemeStyles, O as ToolCallComponent, On as sortSlashCommands, Ot as createEditorTheme, P as ThinkingComponent, Pn as startManualEmbeddingDownload, Pt as contrastTextHex, Q as clearGoalState, Qn as saveCatalogCache, Qt as isStreaming, R as sanitizeShellOutput, Rn as TuiLikePreferencesSchema, Rt as DISABLE_TERMINAL_FOCUS_REPORTING, S as appendJsonlLine, Sn as getCtrlCHint, St as refreshProviderBalance, T as getDaemonInstructions, Tn as getNoActiveSessionMessage, U as estimateTokens, Un as getInputHistoryFile, Ut as OSC11_RESPONSE, V as ActivityGroupComponent, Vn as detectShellEnvironment, Vt as ENABLE_TERMINAL_THEME_REPORTING, W as getSharedSpeedTracker, Wn as getLogDir, Wt as OSC11_RESPONSE_PREFIX, X as resetBreathingClock, Xn as DEFAULT_CATALOG_URL, Xt as TERMINAL_THEME_LIGHT, Y as getBreathingFrame, Yn as PRODUCT_NAME, Yt as TERMINAL_THEME_DARK, Z as CompactionComponent, Zn as fetchCatalog, Zt as isBusy, a as buildRoleAdditionalText, at as isInternalMessage, b as refreshUpdateCache, bn as SESSION_TIPS, cn as appendSessionHeaderHint, cr as resolveScreamHome, ct as getModelCycleLevel, d as isExpandable, dn as formatErrorMessage, dr as resolveGlobalLogPath, en as lerpGradient, er as encodeWorkDirKey, f as isPlanExpandable, fn as isTodoItemShape, fr as isScreamError, gn as truncateErrorMessage, hn as stringValue, hr as SCREAM_ERROR_INFO, ht as handlePlanCommand, i as openUrl, ir as removeSessionIndexEntry, j as highlightLines, jn as embeddingFailureDetail, jt as isTurnElapsedEnabled, k as renderDiffLines, kn as isExperimentalFlagEnabled, kt as createMarkdownTheme, l as disposeChildren, ln as appendStreamingArgsPreview, lr as flushDiagnosticLogs, m as formatMemoryMemoForInjection, mn as serializeToolResultOutput, mr as ErrorCodes, n as clearEvalPanelState, nr as appendSessionIndexEntry, o as syncDiagramCapabilityPrompt, on as printableChar, or as isRealUserPrompt, ot as toTerminalHyperlink, p as MoonLoader, pn as parseStreamingArgs, pr as isOrphanedToolCallError, pt as handleFusionPlanCommand, q as WelcomeComponent, qn as CLI_UI_MODE, qt as TERMINAL_FOCUS_IN, rr as readSessionIndex, sn as STATUS_BULLET, sr as parseRlmMaxDepthArg, st as changeThinkingLevel, t as dispatchInput, tn as SubagentSlots, tr as normalizeWorkDir, u as hasDispose, un as argsRecord, ur as log, vn as EXIT_CONFIRM_WINDOW_MS, wn as getLlmNotSetMessage, wt as clearInfoPanelState, x as readUpdateCache, xn as TIP_ROTATION_INTERVAL_MS, y as selectUpdateTarget, yn as MAIN_AGENT_ID, z as SkillActivationComponent, zn as loadTuiConfig, zt as DISABLE_TERMINAL_THEME_REPORTING } from "./dispatch-7Mas_Tvb.mjs";
9
+ import { i as t, n as getLocale, r as setLocale } from "./text-input-dialog-gDr3i7xz.mjs";
10
10
  import { createRequire } from "node:module";
11
11
  import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
12
12
  import { access, appendFile, chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
@@ -33,7 +33,7 @@ function optionalBuildString(value) {
33
33
  return typeof value === "string" && value.length > 0 ? value : void 0;
34
34
  }
35
35
  const SCREAM_BUILD_INFO = {
36
- version: optionalBuildString("0.18.5"),
36
+ version: optionalBuildString("0.18.7"),
37
37
  channel: optionalBuildString(""),
38
38
  commit: optionalBuildString(""),
39
39
  buildTarget: optionalBuildString("darwin-arm64")
@@ -1785,8 +1785,9 @@ var EditorKeyboardController = class {
1785
1785
  editor.onCtrlF = () => {
1786
1786
  if (host.state.transcriptEntries.length > 0) return false;
1787
1787
  if (isEmptySessionHintDismissed()) return false;
1788
- if (!(SESSION_TIPS[host.lifecycleController.currentTipIdx]?.isAd ?? false)) return false;
1789
- openUrl(EMPTY_SESSION_HINT_URL);
1788
+ const currentTip = SESSION_TIPS[host.lifecycleController.currentTipIdx];
1789
+ if ((currentTip?.isAd ?? false) !== true) return false;
1790
+ openUrl(currentTip?.url ?? "https://github.com/LIUTod/scream-code");
1790
1791
  return true;
1791
1792
  };
1792
1793
  editor.onCtrlB = () => {
@@ -3450,6 +3451,7 @@ var SessionEventHandler = class {
3450
3451
  this.host.setAppState({ streamingPhase: "waiting" });
3451
3452
  }
3452
3453
  handleTurnEnd(event, sendQueued) {
3454
+ if (event.stepBudgetExhausted === true) this.host.showStatus(t("handler.max_steps_reached"), this.host.state.theme.colors.warning);
3453
3455
  this.host.setAppState({ reconnectAttempt: 0 });
3454
3456
  const todos = this.host.state.todoPanel.getTodos();
3455
3457
  if (todos.length > 0 && todos.every((todo) => todo.status === "done")) this.host.streamingUI.setTodoList([]);
@@ -3502,6 +3504,7 @@ var SessionEventHandler = class {
3502
3504
  reconnectDelayMs: event.delayMs,
3503
3505
  reconnectStatusCode: event.statusCode,
3504
3506
  reconnectErrorName: event.errorName,
3507
+ reconnectErrorCode: event.errorCode,
3505
3508
  sessionApiCalls: this.host.state.appState.sessionApiCalls + 1
3506
3509
  });
3507
3510
  }
@@ -3520,7 +3523,8 @@ var SessionEventHandler = class {
3520
3523
  reconnectMaxAttempts: void 0,
3521
3524
  reconnectDelayMs: void 0,
3522
3525
  reconnectStatusCode: void 0,
3523
- reconnectErrorName: void 0
3526
+ reconnectErrorName: void 0,
3527
+ reconnectErrorCode: void 0
3524
3528
  });
3525
3529
  }
3526
3530
  maybeShowDebugTiming(event) {
@@ -3578,7 +3582,7 @@ var SessionEventHandler = class {
3578
3582
  this.host.showStatus(t("handler.user_interrupted"), this.host.state.theme.colors.error);
3579
3583
  return;
3580
3584
  }
3581
- this.host.showError(reason === "max_steps" ? t("handler.max_steps_reached") : t("handler.step_interrupted", { reason }));
3585
+ this.host.showError(t("handler.step_interrupted", { reason }));
3582
3586
  }
3583
3587
  handleThinkingDelta(event) {
3584
3588
  const { state, streamingUI } = this.host;
@@ -3701,7 +3705,9 @@ var SessionEventHandler = class {
3701
3705
  is_error: event.isError,
3702
3706
  synthetic: event.synthetic,
3703
3707
  display: event.display,
3704
- message: event.message
3708
+ message: event.message,
3709
+ code: event.code,
3710
+ abort_reason: event.abortReason
3705
3711
  };
3706
3712
  if (isBackgroundedHandoffResult(resultData.output)) streamingUI.markSubagentBackgrounded({ toolCallId: event.toolCallId });
3707
3713
  streamingUI.completeToolResult(event.toolCallId, resultData);
@@ -7676,6 +7682,41 @@ var TranscriptController = class TranscriptController {
7676
7682
  }
7677
7683
  };
7678
7684
  //#endregion
7685
+ //#region src/tui/utils/tip-hyperlink.ts
7686
+ /**
7687
+ * Composes the idle tip line shown above the editor: the raw i18n text, with
7688
+ * an optional clickable domain for tips that carry a `url`.
7689
+ *
7690
+ * A tip whose text mentions its bare domain inline gets that domain wrapped as
7691
+ * an OSC 8 hyperlink (link color + underline) so it reads as a link against
7692
+ * the dimmed cue text. Clicking opens through the alt-screen openUrl callback;
7693
+ * Ctrl+F targets the same destination for terminals without mouse reporting.
7694
+ * Tips without a `url`, or whose text does not mention the domain, render
7695
+ * unchanged (e.g. the GitHub tip is keyboard-only and has no inline URL).
7696
+ */
7697
+ function composeTipLabel(raw, tip, linkColor) {
7698
+ if (tip.url === void 0) return raw;
7699
+ const domain = tip.url.replace(/^https?:\/\//iu, "");
7700
+ if (!raw.includes(domain)) return raw;
7701
+ const link = toTerminalHyperlink(chalk.hex(linkColor).underline(domain), tip.url);
7702
+ return raw.replace(domain, link);
7703
+ }
7704
+ /**
7705
+ * Weighted rotation pick: `OFFER_TIP_PROBABILITY` of the rolls select the
7706
+ * offer tip (regardless of what is currently shown — a re-pick keeps the ad
7707
+ * line up), everything else picks uniformly excluding the current tip.
7708
+ */
7709
+ function pickTipIndex(tips, current) {
7710
+ if (tips.length <= 1) return Math.max(0, current ?? 0);
7711
+ const offerIndex = tips.findIndex((tip) => tip.isAd && tip.url !== void 0);
7712
+ if (offerIndex !== -1 && Math.random() < .8) return offerIndex;
7713
+ let next;
7714
+ do
7715
+ next = Math.floor(Math.random() * tips.length);
7716
+ while (next === current);
7717
+ return next;
7718
+ }
7719
+ //#endregion
7679
7720
  //#region src/tui/components/chrome/gutter-container.ts
7680
7721
  /**
7681
7722
  * Container that reserves left/right gutter columns around its children,
@@ -8875,6 +8916,21 @@ var PulseWaveLoader = class extends Text {
8875
8916
  };
8876
8917
  //#endregion
8877
8918
  //#region src/tui/controllers/lifecycle-controller.ts
8919
+ /**
8920
+ * Reason label for the status-bar reconnect line.
8921
+ *
8922
+ * The structured `errorCode` carried by the retry event is authoritative. The
8923
+ * status-code and error-name checks are the fallback for retry records written
8924
+ * before that field existed — and for codes this label has no wording for.
8925
+ */
8926
+ function reconnectReasonKey(a) {
8927
+ if (a.reconnectErrorCode === "provider.timeout") return "status.reason_timeout";
8928
+ if (a.reconnectErrorCode === "provider.rate_limit") return "status.reason_rate_limit";
8929
+ if (a.reconnectStatusCode === 429) return "status.reason_rate_limit";
8930
+ if (a.reconnectStatusCode !== void 0 && a.reconnectStatusCode >= 500) return "status.reason_server";
8931
+ if (a.reconnectErrorCode === void 0 && (a.reconnectErrorName ?? "").includes("Timeout")) return "status.reason_timeout";
8932
+ return "status.reason_connection";
8933
+ }
8878
8934
  var LifecycleController = class LifecycleController {
8879
8935
  host;
8880
8936
  signalCleanupHandlers = [];
@@ -8895,7 +8951,7 @@ var LifecycleController = class LifecycleController {
8895
8951
  return usage.inputOther + usage.inputCacheRead + usage.inputCacheCreation + usage.output;
8896
8952
  }
8897
8953
  tipRotationTimer;
8898
- currentTipIndex = Math.floor(Math.random() * SESSION_TIPS.length);
8954
+ currentTipIndex = pickTipIndex(SESSION_TIPS, void 0);
8899
8955
  /** Sidebar-only git cache (the footer owns its own). Rebuilt when the
8900
8956
  * workDir changes; `getStatus()` is TTL-cached so polling is cheap. */
8901
8957
  sidebarGitCache;
@@ -9325,7 +9381,7 @@ var LifecycleController = class LifecycleController {
9325
9381
  const tip = SESSION_TIPS[this.currentTipIndex] ?? SESSION_TIPS[0];
9326
9382
  state.statusBarContainer.addChild(new StatusBarPaneComponent({
9327
9383
  mode: "idle",
9328
- label: t(tip.i18nKey),
9384
+ label: composeTipLabel(t(tip.i18nKey), tip, state.theme.colors.primary),
9329
9385
  labelColor: "#999999"
9330
9386
  }));
9331
9387
  this.startTipRotation();
@@ -9334,6 +9390,9 @@ var LifecycleController = class LifecycleController {
9334
9390
  }
9335
9391
  state.ui.requestRender();
9336
9392
  }
9393
+ /** The idle tip line delegates its optional domain link to composeTipLabel
9394
+ * (see tui/utils/tip-hyperlink.ts): linked tips render the bare domain as
9395
+ * a clickable OSC 8 hyperlink against the dimmed cue text. */
9337
9396
  /** Builds the reconnect label shown next to the status-bar pulse wave
9338
9397
  * while a step retry is in flight, e.g. "重连中 3/10 · 限流 · 20s 后重试".
9339
9398
  * Returns an empty string when no retry is active. Static by design: the
@@ -9342,7 +9401,7 @@ var LifecycleController = class LifecycleController {
9342
9401
  buildReconnectLabel(state) {
9343
9402
  const a = state.appState;
9344
9403
  if (a.reconnectAttempt <= 0) return "";
9345
- const reasonKey = a.reconnectStatusCode === 429 ? "status.reason_rate_limit" : a.reconnectStatusCode !== void 0 && a.reconnectStatusCode >= 500 ? "status.reason_server" : (a.reconnectErrorName ?? "").includes("Timeout") ? "status.reason_timeout" : "status.reason_connection";
9404
+ const reasonKey = reconnectReasonKey(a);
9346
9405
  const reason = a.reconnectStatusCode !== void 0 ? `${t(reasonKey)} (${String(a.reconnectStatusCode)})` : a.reconnectErrorName !== void 0 && a.reconnectErrorName.length > 0 ? `${t(reasonKey)} (${a.reconnectErrorName})` : t(reasonKey);
9347
9406
  const delaySec = Math.max(1, Math.round((a.reconnectDelayMs ?? 0) / 1e3));
9348
9407
  const label = t("status.reconnecting_detail", {
@@ -9364,17 +9423,13 @@ var LifecycleController = class LifecycleController {
9364
9423
  get currentTipIdx() {
9365
9424
  return this.currentTipIndex;
9366
9425
  }
9367
- /** Start the random tip rotation timer. Picks a random tip different
9368
- * from the current one and refreshes the status bar. */
9426
+ /** Start the weighted tip rotation timer: 80% of rotations land on the
9427
+ * offer tip (see tui/utils/tip-hyperlink.ts), the rest spread uniformly
9428
+ * and never repeat the line currently on screen. */
9369
9429
  startTipRotation() {
9370
9430
  if (this.tipRotationTimer !== void 0) return;
9371
9431
  this.tipRotationTimer = setInterval(() => {
9372
- if (SESSION_TIPS.length <= 1) return;
9373
- let next;
9374
- do
9375
- next = Math.floor(Math.random() * SESSION_TIPS.length);
9376
- while (next === this.currentTipIndex);
9377
- this.currentTipIndex = next;
9432
+ this.currentTipIndex = pickTipIndex(SESSION_TIPS, this.currentTipIndex);
9378
9433
  this.lastActivityMode = void 0;
9379
9434
  this.updateActivityPane();
9380
9435
  }, TIP_ROTATION_INTERVAL_MS);
@@ -14653,6 +14708,7 @@ function createInitialAppState(input) {
14653
14708
  streamingPhase: "idle",
14654
14709
  streamingStartTime: 0,
14655
14710
  pendingUserAction: null,
14711
+ pendingUserActionSince: null,
14656
14712
  theme: input.tuiConfig.theme,
14657
14713
  version: input.version,
14658
14714
  hasNewVersion: false,
@@ -15133,7 +15189,10 @@ var ScreamTUI = class {
15133
15189
  syncPendingUserAction() {
15134
15190
  const { pendingApproval, pendingQuestion } = this.state.livePane;
15135
15191
  const next = pendingApproval !== null ? "approval" : pendingQuestion !== null ? "question" : null;
15136
- if (next !== this.state.appState.pendingUserAction) this.setAppState({ pendingUserAction: next });
15192
+ if (next !== this.state.appState.pendingUserAction) this.setAppState({
15193
+ pendingUserAction: next,
15194
+ pendingUserActionSince: next === null ? null : Date.now()
15195
+ });
15137
15196
  }
15138
15197
  requireSession() {
15139
15198
  if (this.session === void 0) throw new Error(getNoActiveSessionMessage());
@@ -15211,7 +15270,7 @@ var ScreamTUI = class {
15211
15270
  const card = new OnboardingCardComponent({
15212
15271
  colors: this.state.theme.colors,
15213
15272
  onConfigure: () => {
15214
- import("./dispatch-fJ2MwyhX.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
15273
+ import("./dispatch-BqBnrIMj.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
15215
15274
  this.restoreEditor();
15216
15275
  onDone?.();
15217
15276
  });
@@ -16582,7 +16641,7 @@ async function runStreamJson(opts) {
16582
16641
  if (event.agentId !== "main") return;
16583
16642
  const errCode = event.code;
16584
16643
  let exitCode = 1;
16585
- if (errCode === "provider.auth_error" || errCode === "provider.rate_limit" || errCode === "provider.api_error" || errCode === "provider.connection_error") exitCode = 3;
16644
+ if (errCode === "provider.auth_error" || errCode === "provider.rate_limit" || errCode === "provider.api_error" || errCode === "provider.connection_error" || errCode === "provider.timeout") exitCode = 3;
16586
16645
  finish(/* @__PURE__ */ new Error(`${event.code}: ${event.message}`), exitCode);
16587
16646
  return;
16588
16647
  }
@@ -16623,14 +16682,14 @@ async function runStreamJson(opts) {
16623
16682
  const inputTotal = (event.usage.inputOther ?? 0) + (event.usage.inputCacheRead ?? 0) + (event.usage.inputCacheCreation ?? 0);
16624
16683
  writer.updateUsage(inputTotal, event.usage.output ?? 0);
16625
16684
  }
16626
- } else if (type === "turn.ended") if (event.reason === "completed") finish();
16685
+ } else if (type === "turn.ended") if (event.reason === "completed") if (event.stepBudgetExhausted === true) finish(/* @__PURE__ */ new Error("Turn ended: step budget exhausted"), 4);
16686
+ else finish();
16627
16687
  else if (event.reason === "cancelled") finish(/* @__PURE__ */ new Error("Turn cancelled"));
16628
16688
  else {
16629
16689
  const errCode = event.error?.code;
16630
16690
  const errMsg = event.error !== void 0 ? `${event.error.code}: ${event.error.message}` : `Turn ended: ${event.reason}`;
16631
16691
  let code = 1;
16632
- if (errCode === "loop.max_steps_exceeded") code = 4;
16633
- else if (errCode === "provider.auth_error" || errCode === "provider.rate_limit" || errCode === "provider.api_error" || errCode === "provider.connection_error") code = 3;
16692
+ if (errCode === "provider.auth_error" || errCode === "provider.rate_limit" || errCode === "provider.api_error" || errCode === "provider.connection_error" || errCode === "provider.timeout") code = 3;
16634
16693
  finish(new Error(errMsg), code);
16635
16694
  }
16636
16695
  });