Conversation
…hanged The TUI forwards SIGUSR2 to the worker's reload RPC, which invalidated the global config cache and unconditionally disposed every instance, aborting all in-flight sessions. Theme switchers (Omarchy, Noctalia hooks, ...) signal on every wallpaper change, so a periodic rotation kills active agent work every time. Themes are discovered from themes/*.json and are not part of the global config, so a theme-only signal never needs an instance rebuild. Reload now re-reads the global config and disposes instances only when it actually changed; the configUpdate route behavior is unaffected.
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
|
The following comment was made by an LLM, it may be inaccurate: Related PR found:
|
|
Thanks for updating your PR! It now meets our contributing guidelines. 👍 |
Review follow-ups: - Read failures can no longer wedge reload: the cached read runs through catchCause and invalidate() always executes. An unreadable config is treated as changed (the previous unconditional-dispose behavior), so a malformed file neither skips invalidation nor pins the cache. - The gate now also covers per-instance on-disk inputs (project config, agent/command/mode/plugin files, OPENCODE_CONFIG) via a content fingerprint captured at instance boot, so editing those and signaling still reloads the instance. Theme files stay excluded. - Config comparison is key-order insensitive (canonicalEquals), so pure key reordering no longer counts as a change.
|
Addressed all three findings in 1fcafcb (pushed to this branch): P1 — malformed config wedging reload. Verified the premise: P2 — project/custom config inputs. The gate now covers per-instance inputs, not just the global config. P2 — key reorder false positive. Config comparison now uses One related note: #42622 (defer disposal until sessions idle) is a complementary approach — this PR gates whether to dispose, that one would gate when. If both land, the gate here still avoids needless rebuilds for theme-only signals. Verification: |
|
Closing in favor of #49162. Review showed the fingerprint gate could not track everything the loaders read (managed config, auth, skills, tools, and permission-rule ordering), so any miss would leave stale state running. #49162 keeps the unconditional reload and instead defers disposal until sessions are idle, which fixes the reported abort for every reload trigger. |
Issue for this PR
Closes #42621
Type of change
What does this PR do?
Theme switchers send SIGUSR2 to refresh the TUI. The worker previously disposed all instances on every signal, aborting active model streams and tools even when configuration was unchanged.
Reload now compares global config and fingerprints project config, OPENCODE_CONFIG, and discovered agent/mode/command/plugin files. Fingerprints follow symlinks and expand file references. Comparisons preserve permission-rule order while ignoring harmless JSON key reorders. The baseline is captured before bootstrap consumes config, and failed reads conservatively trigger disposal without leaving instance loads pending. Theme files and loader-added schema metadata do not trigger disposal. The configUpdate route is unchanged.
How did you verify your code works?
bun run test test/server test/config test/project: 638 passed, 6 skipped, 0 failed.bun run typecheckand all 30 pre-push workspace typechecks passed; formatting passed; oxlint reported no errors and only two pre-existing return-style warnings.Screenshots / recordings
N/A — no UI change.
Checklist