Problem
New Amicode users activate the extension with no model configured. No LLM calls are possible, so conversational onboarding cannot begin. The user needs a deterministic, non-agentic setup surface that configures a model provider before chat opens.
Part of #359 — see parent for full design-of-record, approaches considered, and architectural context.
Key Decisions
| Decision |
Choice |
Rationale |
| Surface type |
VS Code WebviewPanel (not a walkthrough or modal) |
Full control over brand animation + form UX; CatalogCard pattern proves the approach works |
| First visual |
Branded welcome animation (logo fade-in → dissolve, ~2-3s) plays before any form elements |
Pure brand moment at true first touch |
| Framework |
Vanilla DOM + brand CSS (same as CatalogCard) |
Consistent with existing webview patterns; no framework dependency |
| Provider form |
Provider picker → API key (masked) → model selection → Test connection |
Progressive disclosure; no LLM calls until explicit user action |
| Config target |
Write to the existing opencode config location (opencode.json or equivalent) |
Existing config infrastructure; no new persistence path |
| Lifecycle |
Webview closes on success; chat panel auto-opens |
Transition from non-agentic to agentic phase |
Acceptance Criteria
- A new
OnboardingPanel (or equivalent) WebviewPanel can be opened programmatically and renders in VS Code.
- On open, the branded welcome animation plays first (~2-3s logo fade-in → dissolve) before any interactive elements appear.
- After the animation, a model configuration form appears with: provider picker dropdown, API key/credential text input (masked/password type), model selection dropdown (options populated per provider), and a "Test connection" button.
- The "Test connection" button makes exactly one LLM call to validate credentials. Success/failure is shown inline.
- On successful connection test, the provider/model/key config is written to the correct config file.
- On successful config write, the webview panel closes itself.
- After panel close, a message is posted (or event emitted) that downstream wiring (Slice 2) can observe to auto-open the chat.
- The webview MUST NOT make any LLM calls other than the explicit "Test connection" action.
- The animation plays exactly once per webview open — it does not loop or replay on interaction.
- The form gracefully handles: empty fields (disable Test button), invalid keys (show error inline), network failures (show error, allow retry).
Testing Decisions
- Unit test: animation completion callback — verify the animation emits a "done" event/callback that reveals the form.
- Unit test: provider-to-model mapping — given a provider selection, the correct model options populate.
- Unit test: config write — after a mock-successful test, the correct config structure is written to disk. Verify file content.
- Unit test: secret masking — the API key input renders as password type and the value is not logged or emitted in any telemetry.
- Integration test: panel lifecycle — open panel → fill form → mock test success → verify panel disposes and event fires.
- Integration test: error states — test failure shows inline error, panel remains open, user can retry.
Constraints & Invariants
- Zero LLM calls except the explicit "Test connection" button press.
- Welcome animation plays before any form elements are visible in the DOM.
- API keys are never logged, included in telemetry, or written anywhere except the config file.
- The webview uses only the existing
media/ui/ component library patterns + brand CSS — no new framework.
- The panel must work with VS Code's standard CSP (Content Security Policy) for webviews.
- Provider list and model options per provider should be data-driven (a config/map), not hard-coded conditionals.
Prior Art
src/catalog_card_shell.ts + src/catalog_card_webview.ts — proven WebviewPanel pattern with bundled JS, injected data, and brand CSS
media/ui/ — vanilla DOM component library (button, text, logo atoms)
src/chat_panel.ts — panel lifecycle management (dispose, reveal, event posting)
src/opencode_config.ts — existing config read/write infrastructure
Source
Part of #359 (Enhanced Onboarding: Orient → Demo → Collect)
Covers: AC 1–5, Stage 0 flow, Key decisions: model setup surface, first visual
Problem
New Amicode users activate the extension with no model configured. No LLM calls are possible, so conversational onboarding cannot begin. The user needs a deterministic, non-agentic setup surface that configures a model provider before chat opens.
Part of #359 — see parent for full design-of-record, approaches considered, and architectural context.
Key Decisions
opencode.jsonor equivalent)Acceptance Criteria
OnboardingPanel(or equivalent) WebviewPanel can be opened programmatically and renders in VS Code.Testing Decisions
Constraints & Invariants
media/ui/component library patterns + brand CSS — no new framework.Prior Art
src/catalog_card_shell.ts+src/catalog_card_webview.ts— proven WebviewPanel pattern with bundled JS, injected data, and brand CSSmedia/ui/— vanilla DOM component library (button, text, logo atoms)src/chat_panel.ts— panel lifecycle management (dispose, reveal, event posting)src/opencode_config.ts— existing config read/write infrastructureSource
Part of #359 (Enhanced Onboarding: Orient → Demo → Collect)
Covers: AC 1–5, Stage 0 flow, Key decisions: model setup surface, first visual