feature: interactive setup wizard#14
Conversation
adamdotdevin
left a comment
There was a problem hiding this comment.
this is really great, thank you so much! left some feedback/questions!
|
sorry for the delay @l0gicgate, just wanted to pull this down and run through it myself before merging; should have it merged first thing tomorrow! |
|
No worries @adamdottv, happy to address any other feedback you have before we merge! |
adamdotdevin
left a comment
There was a problem hiding this comment.
pulled this down this morning and ran through it, a few changes needed:
- if you hit
ctrl+cyou're able to exit the setup dialog and get into a weird state where there's nothing to do but close the app and restart - the list of providers/models should use the new
simple-listcomponent (it has vim navigation with j/k as well) - it's not clear to me what "API key" would be for some of the providers like Bedrock and Azure where you have to have AWS/Azure credentials configured in your environment for these to be setup correctly; not sure what we should do here, but we could just display a message when you choose one of those providers (instead of the API key form) that basically tells the user they need to ensure they have AWS/Azure creds setup and then restart the app
- had an inline note about repurposing the provider friendly names
|
can we just remove bedrock and azure from that dialog in the interim? |
|
i actually forgot to delete the existing folder/file, so didn't hit the setup wizard, just went straight into a previously saved session and saw the "thinking..." indicator |
|
@adamdottv okay I was able to repro and find the bug! Fixed via 9e274d0 |
|
@adamdottv is it safe to assume that this PR will be superseded by #38? I will close if so |
|
@l0gicgate that PR is overhauling the core of opencode to be powered by bun. the TUI is still going to be in go - simple server client model. this PR will probably have to change but we'll keep the TUI parts |
|
Okay cool @thdxr, thanks for the update! Let me know what changes need to be done and I’ll address right away. |
|
closing as we rewrote the codebase - appreciate it though! |
- Issue anomalyco#14: SDK cache now limited to 50 entries with LRU eviction - Issue anomalyco#15: Languages cache now limited to 100 entries with LRU eviction - Issue anomalyco#16: Instance cache now limited to 20 entries with LRU eviction Creates new createLruCache utility in src/util/cache.ts with: - maxEntries limit for bounded cache size - LRU eviction policy when limit is reached - Optional onEvict callback for cleanup
add refresh gesture to chat window
The previous flow took the three ORT sessions out of self, ran the preprocess/encode/decode pipeline in a closure, and restored them back only on normal return. Any .unwrap() panic mid-pipeline left self with three None sessions, so the next transcribe() hit "Not loaded" and the user had to wait ~1 s for ONNX to reload ~700 MB from disk. Wrap the body in std::panic::catch_unwind(AssertUnwindSafe(...)) and keep the sessions in local Options that we restore unconditionally before returning — even on unwind. The panic payload is stringified so the caller gets a meaningful error instead of a hard abort. Closes anomalyco#14/21.
Fixes all 17 Copilot comments: Telemetry opt-out (#1, #2, #3, #9, #16): - tracker.ts now reads FINNY_TELEMETRY=0 / OPENCODE_TELEMETRY=0 at module load, so the opt-out applies in every entrypoint (TUI worker, server, CLI), not just the bootstrap path. - Email dialog auto-prompt and /subscribe slash command also gated on Analytics.isEnabled() — email POST goes to the same Convex deployment. Tracker correctness (#5, #14, #17): - drain() now also waits for the DeviceProfile.userId() resolution promise, not just the post-send promise. - worker rpc.shutdown() and main-thread thread.ts both call Analytics.drain() before tearing down — neither beforeExit nor SIGTERM fire on worker.terminate() / process.exit(0). - beforeExit handler runs at most once per process, preventing an infinite drain loop when a hung telemetry request later resolves and re-empties the loop. Privacy (#10, #11, #12): - Drop process.argv from tui.worker.booted (could include --prompt text and project paths). - error.surfaced now sends only error.name; error messages frequently embed user prompt content and local file paths. - Don't persist the submitted email address to local KV (no reader, just unnecessary PII retention). Email dialog state machine (#4, #6, #8): - Wait for kv.ready before evaluating the prompt gate so we don't re-show the dialog to users who already submitted/skipped. - Conditional dismiss handler — only marks "skipped" when no terminal status has been set, so a successful submit isn't overwritten by the dismiss callback that fires on dialog.clear() and isn't suppressed by another dialog replacing this one. Server-side validation (#15): - subscribe mutation now rejects empty / oversized / regex-failing emails with a ConvexError, so the public Convex client can't bypass the TUI regex. Command coverage (#13): - Hook Analytics.track() in DialogCommand.trigger() instead of the bus event handler. trigger() is the central activation point for palette, slash, keybind, plugin, and bus paths — single hook, full coverage, no double-counting. Comment wording (#7): - bootstrap.ts: "opt-in by default" → "enabled by default" (correct description of opt-out semantics). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous flow took the three ORT sessions out of self, ran the preprocess/encode/decode pipeline in a closure, and restored them back only on normal return. Any .unwrap() panic mid-pipeline left self with three None sessions, so the next transcribe() hit "Not loaded" and the user had to wait ~1 s for ONNX to reload ~700 MB from disk. Wrap the body in std::panic::catch_unwind(AssertUnwindSafe(...)) and keep the sessions in local Options that we restore unconditionally before returning — even on unwind. The panic payload is stringified so the caller gets a meaningful error instead of a hard abort. Closes anomalyco#14/21.
feat: add non-invasive in-app updater
…as/refiner UI fixes: - anomalyco#15 Remove the gear-icon "Tweaks" popover (theme + collapse) — user reported it as useless chrome. Theme falls back to saved pref / system, rail collapse stays on the rail's own chevron toggle. - anomalyco#7 Task names now follow each session's title (auto-generated or user- renamed). Root cause: `newWorkflowTask` was pre-setting `title: "Workflow"` on session.create, which blocked the backend's title agent from auto-generating (the agent only fires when title matches the default ISO placeholder). New sessions now leave title unset → ensureTitle fires → each task gets a distinct name. Rail and Tasks drawer show "Untitled" for sessions that still have the default placeholder; node-tab labels prefer the bound child session's title. - Rail's sub-task list capped at 8 visible rows with internal scroll (was squeezing all tasks into the visible rail height). - anomalyco#14 Per-slave model picker: clear `local.model` before opening the picker so picking the SAME model as master still routes (previously the on(key) effect required a key change to fire, so same-model picks silently no-op'd — the user's "选其他不生效" complaint). - anomalyco#10 Canvas bottom-half occluded: `.wf-canvas-host` was `position: relative` only, so its `flex: 1` child `.wf-r2-canvas` had no flex parent to grow into. Made the host a flex column so the canvas actually fills its allotted height. - anomalyco#11 React production error anomalyco#409 fixed by un-nesting the drill-in button: the outer node card was a `<button>` wrapping an inner drill-in `<button>` — invalid HTML that React surfaces as anomalyco#409. Switched the outer to `div role="button"` with Enter/Space handling. Refiner: - anomalyco#13 Refiner no longer observes user messages addressed to the orchestrator agent (workflow planning commands aren't generalisable experiences). Gate added in `extractUserMessage`. - anomalyco#5 Archived experiences are now discoverable: new "已归档 (N)" chip in the Knowledge substrip when N > 0, toggles `includeArchived`. Archived rows already had an "Unarchive" button in the card menu — this just makes finding them obvious. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Description
On first start, when

.opencode.jsondoes not exist, we prompt the user with the setup wizard:Step 1: Select Provider

Step 2: Select Model

Step 3: Enter API Key

Demo
.opencodeand.opencode.jsonfrom your home directoryCloses #7