Skip to content

fix(desktop): preserve generation timeout reason and raise dropdown ceiling#169

Open
hqhq1025 wants to merge 1 commit intomainfrom
worktree-agent-a5ff9ce6
Open

fix(desktop): preserve generation timeout reason and raise dropdown ceiling#169
hqhq1025 wants to merge 1 commit intomainfrom
worktree-agent-a5ff9ce6

Conversation

@hqhq1025
Copy link
Copy Markdown
Collaborator

Fixes #164.

Summary

  • Root cause of the opaque "Request was aborted." message. When the generation timer fires, armGenerationTimeout calls controller.abort(new CodesignError('Generation aborted after {n}s (Settings → Advanced → Generation timeout).', 'GENERATION_TIMEOUT')). But the Anthropic and OpenAI SDKs catch the aborted fetch and rethrow their own generic 'Request was aborted.', which drops signal.reason. The main-process catch then logged and re-threw that opaque error, so the user never saw the configured timeout or where to change it.
  • Fix at the catch boundary, not the SDK boundary. New extractGenerationTimeoutError(signal) reads back the CodesignError we stashed. Both codesign:v1:generate and the legacy codesign:generate catch blocks now prefer it over the rewritten SDK error, so the log row and the renderer toast both carry GENERATION_TIMEOUT with the full message.
  • Settings dropdown ceiling raised. The default preference is 1200s (20 min) but the UI only listed 60/120/180/300, so the select rendered blank and updatePref silently downgraded on save (covered in project_bug_settings_timeout_dropdown memory — this PR resolves that). Options now run 60s / 2m / 3m / 5m / 10m / 20m / 30m / 1h / 2h, and a stored value outside the list is injected so the user's existing choice is preserved.

Changes

  • apps/desktop/src/main/generation-ipc.ts — export extractGenerationTimeoutError(signal).
  • apps/desktop/src/main/index.ts — both generate catch blocks upgrade the SDK error back to GENERATION_TIMEOUT when our timer fired.
  • apps/desktop/src/renderer/src/components/Settings.tsxTIMEOUT_OPTION_SECONDS + resolveTimeoutOptions(currentSec) helper; dropdown maps from it.
  • Tests: new extractGenerationTimeoutError suite (4 cases) + resolveTimeoutOptions suite (4 cases).
  • Changeset: patch.

PRINCIPLES §5b

  • Compatibility: prefs schema unchanged, only the list of UI choices widened. Any stored timeout (including the legacy 1200) renders correctly.
  • Upgradeability: resolveTimeoutOptions merges unknown stored values, so we can change the canonical list in the future without stranding user settings.
  • No bloat: one new exported function per concern, no new deps.
  • Elegance: fix is at the one place where the SDK's rewrite lands (the catch), not spread across every provider adapter.

Test plan

  • pnpm typecheck — 10/10 tasks pass.
  • pnpm --filter @open-codesign/desktop test -- --run — 878/878 pass.
  • pnpm lint — clean.
  • Full pre-commit hook (turbo full test + lint) — clean.
  • Manual: Settings → Advanced shows the new 30m/1h/2h choices; stored 1200s renders as "1200 s"; changing to 3600s and triggering a generation that exceeds the provider turn time shows the friendly GENERATION_TIMEOUT toast instead of "Request was aborted."

Coordination

  • Does not touch retry.ts or remapProviderError (out of scope, other PRs own those).
  • Does not change applyGenerateError in the renderer store — the richer error code already flows through the normal error pipeline; a follow-up can add a "Open Settings" secondary action on the toast if desired.

😇

@github-actions github-actions Bot added docs Documentation area:desktop apps/desktop (Electron shell, renderer) labels Apr 22, 2026
…eiling (#164)

When a long-running generation hits the configured timeout, the main-process
AbortController was stamped with a CodesignError(GENERATION_TIMEOUT) — but the
Anthropic / OpenAI SDKs catch the aborted fetch and rethrow a generic
'Request was aborted.' error, dropping signal.reason. The user ended up with
an opaque message with no hint about which limit was hit or where to raise it.

- Add extractGenerationTimeoutError(signal) to recover the stashed error.
- Both generate IPC catches (v1 + legacy) now upgrade the SDK error back to
  GENERATION_TIMEOUT when our own timer fired, so the log row and the renderer
  toast both show the configured seconds + Settings → Advanced path.
- Expand the Settings timeout dropdown to 60s / 2m / 3m / 5m / 10m / 20m /
  30m / 1h / 2h (the default prefs value is 1200s but the old 60-300s list
  silently downgraded to 300 on save). When a stored value is outside the
  canonical list, inject it so the select shows the user's existing choice
  instead of rendering blank.

Signed-off-by: hqhq1025 <1506751656@qq.com>
@hqhq1025 hqhq1025 force-pushed the worktree-agent-a5ff9ce6 branch from f5c9aea to 423f0dd Compare April 22, 2026 14:26
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • None.

Summary

  • Review mode: initial
  • No issues were identified on added/modified lines in this diff at high confidence.
  • Residual risk: docs/VISION.md and docs/PRINCIPLES.md were not found in this checkout (Not found in repo/docs), so architectural/principle alignment could only be checked against CLAUDE.md and the changed code/tests.

Testing

  • Not run (automation)

open-codesign Bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:desktop apps/desktop (Electron shell, renderer) docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(desktop): generation timeout abort surfaces as raw 'Request was aborted.' losing reason

1 participant