You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(desktop): preserve generation timeout reason and raise dropdown ceiling (#169)
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.tsx` —
`TIMEOUT_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
- [x] `pnpm typecheck` — 10/10 tasks pass.
- [x] `pnpm --filter @open-codesign/desktop test -- --run` — 878/878
pass.
- [x] `pnpm lint` — clean.
- [x] 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.
😇
Signed-off-by: hqhq1025 <1506751656@qq.com>
Fix: preserve the generation-timeout reason so long runs no longer surface a bare "Request was aborted." Provider SDKs rewrite aborted fetches into a generic message that drops `signal.reason`; the generate IPC now re-surfaces the stashed `GENERATION_TIMEOUT` CodesignError (with configured seconds + Settings path) when the controller was aborted by our own timer. Settings → Advanced → Generation timeout also gains 10m / 20m / 30m / 1h / 2h choices so the default 1200s and longer full-PDP runs can actually be configured without the dropdown silently downgrading the stored value.
it('covers the default 1200s stored value and long-generation 30m / 1h / 2h choices so users can configure what they need without hitting the old 300s ceiling',()=>{
98
+
expect(TIMEOUT_OPTION_SECONDS).toContain(1200);
99
+
expect(TIMEOUT_OPTION_SECONDS).toContain(1800);
100
+
expect(TIMEOUT_OPTION_SECONDS).toContain(3600);
101
+
expect(TIMEOUT_OPTION_SECONDS).toContain(7200);
102
+
});
103
+
104
+
it('returns the canonical options unchanged when the stored value is already present',()=>{
it("merges a stored value that is not in the canonical list and keeps the list sorted so the select shows the user's existing choice instead of silently downgrading on save",()=>{
0 commit comments