opencode-provider-switch/.trellis/workspace/Apale/journal-1.md
2026-04-18 20:49:54 +08:00

18 KiB

Journal - Apale (Part 1)

AI development session journal Started: 2026-04-16


Session 1: Finalize OPS MVP review PRD

Date: 2026-04-17 Task: Finalize OPS MVP review PRD Branch: master

Summary

(Add summary)

Main Changes

Area Description
PRD Redesign Reframed OPS MVP around alias-driven multi-provider failover for OpenAI Responses only.
OpenCode Integration Locked config-sync approach for exposing aliases through provider.ops.models, with connected-provider requirement.
Failover Semantics Finalized pre-first-byte-only failover, streaming pass-through, and no mid-stream provider switching.
MVP Boundaries Locked import scope to config-defined @ai-sdk/openai, excluded auth.json as provider definition source, and kept ops doctor static by default.
Task Closure Marked review task completed, cleared current task, and archived both finished docs tasks.

Updated Files:

  • .trellis/tasks/archive/2026-04/04-17-04-17-ops-mvp-design-review/prd.md
  • .trellis/tasks/archive/2026-04/04-17-04-17-ops-mvp-design-review/task.json
  • .trellis/tasks/archive/2026-04/04-17-ops-mvp-design/task.json

Notes:

  • Follow-up implementation should start in a new task from the finalized PRD.
  • Existing unrelated worktree change in AGENTS.md was left untouched.

Git Commits

Hash Message
eeacdc4 (see git log)
00747fa (see git log)
ca0b3c4 (see git log)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 2: Build OPS MVP failover proxy

Date: 2026-04-17 Task: Build OPS MVP failover proxy Branch: master

Summary

Implemented the Go-based OPS MVP: local config, provider and alias CLI, OpenCode sync/import, and a streaming OpenAI Responses proxy with deterministic pre-first-byte failover. Added Chinese and English README documentation for quick onboarding.

Main Changes

(Add details)

Git Commits

Hash Message
2b04d91 (see git log)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 3: Support disabling providers in ocswitch

Date: 2026-04-17 Task: Support disabling providers in ocswitch Branch: master

Summary

Added provider-level disable/enable support, made failover skip disabled providers without mutating alias target state, and aligned doctor/opencode sync/models exposure with routable aliases.

Main Changes

(Add details)

Git Commits

Hash Message
HEAD (see git log)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 4: Review MVP completion status

Date: 2026-04-17 Task: Review MVP completion status Branch: master

Summary

Reviewed current implementation against the archived MVP PRD and classified implemented, missing, and beyond-MVP features.

Main Changes

Category Result
Overall status MVP core flow is effectively complete
Implemented MVP Local ocswitch config, provider/alias CLI, OpenCode sync, static doctor, /v1/responses proxy, streaming pass-through, pre-first-byte failover, debug headers
Partial / missing MVP edges doctor validates generated preview more than on-disk synced state; OpenCode provider import only reads options.apiKey, not broader header-style auth
Beyond MVP provider enable/disable, minimal /v1/models, broader alias normalization, careful OpenCode config patching

Reviewed Sources:

  • .trellis/tasks/archive/2026-04/04-17-04-17-ops-mvp-design-review/prd.md
  • internal/config/config.go
  • internal/cli/provider.go
  • internal/cli/alias.go
  • internal/cli/opencode.go
  • internal/cli/doctor.go
  • internal/cli/serve.go
  • internal/opencode/opencode.go
  • internal/proxy/server.go
  • internal/proxy/server_test.go
  • internal/opencode/opencode_test.go
  • internal/cli/cli_test.go
  • internal/config/config_test.go

Verification:

  • Ran go test ./... successfully: 34 tests passed across 5 packages.

Git Commits

(No commits - planning session)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 5: Fix sync command panic

Date: 2026-04-17 Task: Fix sync command panic Branch: master

Summary

Fixed a panic in opencode sync when preserved model metadata contains slices, and added package plus CLI regression coverage.

Main Changes

  • Root cause: internal/opencode/opencode.go compared interface{} values directly inside mapsEqualShallow, which panicked when preserved provider.ocswitch.models.<alias> metadata included slices.
  • Fix: replaced the unsafe hand-rolled comparison with reflect.DeepEqual so existing model metadata with nested maps/slices can be compared safely during sync.
  • Added regression tests in internal/opencode/opencode_test.go and internal/cli/cli_test.go covering preserved slice metadata and a real opencode sync --target no-op path.
  • Verification: ran rtk go test ./internal/opencode, rtk go test ./internal/cli ./internal/opencode, and rtk go test ./... successfully.

Git Commits

Hash Message
887eb14 (see git log)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 6: Rename CLI to ocswitch

Date: 2026-04-17 Task: Rename CLI to ocswitch Branch: master

Summary

Renamed the CLI and synced docs, examples, and Trellis history from olpx/opswitch to ocswitch while keeping the repository name opencode-provider-switch.

Main Changes

(Add details)

Git Commits

Hash Message
cf3dcec (see git log)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 7: Deep code review for ocswitch

Date: 2026-04-17 Task: Deep code review for ocswitch Branch: master

Summary

Recorded the deep code review findings in Trellis, including 2 high-risk, 4 medium-risk, and 4 low-risk/improvement items with concrete remediation guidance.

Main Changes

  • Added .trellis/tasks/04-17-deep-code-review-ocswitch/review.md to capture the full deep review output and concrete remediation guidance.
  • Recorded 2 high-risk items:
    • concurrent config/OpenCode save paths are unsafe under concurrent writers
    • proxy request body has no read timeout after headers
  • Recorded 4 medium-risk items:
    • streaming responses have no idle timeout
    • retryable upstream failures are collapsed into a generic 502
    • opencode sync --set-model / --set-small-model can silently write invalid defaults
    • fixed default API key remains unsafe when binding to non-loopback addresses
  • Recorded 4 low-risk or improvement items:
    • alias lifecycle lacks enable/disable recovery path
    • provider import docs and implementation disagree on empty apiKey
    • opencode sync side effects on JSONC comments and $schema need clearer docs
    • header forwarding should better handle dynamic hop-by-hop headers and narrower forwarding rules
  • Verification already completed during review:
    • go test ./...
    • go test -race ./...

Git Commits

(No commits - planning session)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 8: Provider discovery and model ref hardening

Date: 2026-04-18 Task: Provider discovery and model ref hardening Branch: master

Summary

Completed provider model discovery hardening, provider/model parsing improvements, README/help sync, follow-up review fixes, and final test-name cleanup.

Main Changes

(Add details)

Git Commits

Hash Message
09d0c1f (see git log)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 9: GUI desktop direction and architecture decision

Date: 2026-04-18 Task: forwarding-log-viewer-gui Branch: master

Summary

Recorded the GUI direction change from a local web-only surface to a desktop-shell follow-up, driven by explicit requirements for launch at login, native menu/tray integration, and native notifications.

Main Changes

  • Confirmed the existing Trellis task 04-17-forwarding-log-viewer-gui remains historically correct as a completed local web log-viewer design task and should not be retrofitted in place.
  • Recorded follow-up product guidance that desktop capabilities now justify a separate native-shell track rather than a browser-only UI.
  • Captured the recommended follow-up stack as Wails + React + TypeScript + Tailwind CSS + react-hook-form + zod.
  • Captured the preferred layering so existing Go logic is not rewritten into desktop-specific code:
    • internal/config continues config IO and validation
    • internal/proxy continues proxy runtime and failover
    • internal/opencode continues OpenCode sync
    • new internal/app application service layer is shared by CLI and GUI
    • Wails desktop shell owns window, tray/menu, notifications, autostart, and frontend hosting only
  • Recorded the frontend recommendation that React is a better fit than Vue for this project because the desktop control panel is form-heavy and aligns better with the chosen react-hook-form + zod stack.

Git Commits

(No commits - Trellis documentation update only)

Testing

  • [OK] No code changes; updated Trellis task metadata and workspace journal only

Status

[OK] Completed

Next Steps

  • Create a separate Trellis task for the desktop shell if implementation should proceed

Session 10: Desktop shell skeleton implementation

Date: 2026-04-18 Task: Desktop shell skeleton implementation Branch: master

Summary

Implemented the first desktop-shell skeleton by introducing a shared internal/app layer, desktop preference persistence, CLI reuse of shared workflows, and a minimal desktop bootstrap with passing Go tests/builds.

Main Changes

  • Added config.Desktop to persist desktop-shell preferences (launch_at_login, minimize_to_tray, notifications) without coupling core runtime logic to a desktop framework.
  • Added internal/app/types.go and internal/app/service.go as the shared application-service layer described in the PRD.
  • Implemented shared DTOs and workflows for:
    • overview
    • provider listing
    • doctor report generation
    • OpenCode sync preview/apply plumbing
    • proxy lifecycle management
    • desktop preference read/write
  • Refactored CLI reuse points so doctor, opencode sync, provider list, and serve now delegate through internal/app instead of keeping those orchestration paths CLI-only.
  • Preserved CLI output behavior closely while centralizing the orchestration logic that future desktop bindings can call.
  • Added internal/desktop/ skeleton adapters (app, bindings, tray, notify, autostart) as placeholders for a future Wails/native shell integration, keeping desktop-only concerns outside internal/app.
  • Added cmd/ocswitch-desktop/main.go as a minimal desktop bootstrap binary that exercises the shared bindings and confirms the skeleton is wired.
  • Added internal/app/service_test.go to cover desktop preference persistence and proxy start/stop status flow.
  • Verified the implementation with:
    • gofmt -w ...
    • rtk go test ./...
    • rtk go build ./...
  • Scope intentionally stayed at the PRD's recommended “skeleton wiring only” level: no Wails dependency, no React frontend, and no tray/autostart implementation yet.

Git Commits

(No commits - planning session)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 11: Desktop control panel implementation

Date: 2026-04-18 Task: Desktop control panel implementation Branch: master

Summary

Extended the desktop-shell skeleton into a minimal usable local control panel by adding an embedded web UI, desktop HTTP bindings, alias/provider overview surfaces, proxy controls, desktop preference editing, and OpenCode sync/doctor actions while keeping the shared Go application layer intact.

Main Changes

  • Upgraded cmd/ocswitch-desktop/main.go from a skeleton print-only bootstrap into a runnable local desktop control panel entrypoint with --config, --listen, and --no-open flags.
  • Added internal/desktop/http.go as a lightweight desktop shell runtime that:
    • serves embedded frontend assets
    • exposes JSON endpoints for overview, providers, aliases, proxy status/start/stop, desktop prefs, doctor, and OpenCode sync preview/apply
    • opens the browser by default and shuts down cleanly on SIGINT/SIGTERM
  • Added web/ embedded assets (web/assets.go, web/dist/index.html, web/dist/app.css, web/dist/app.js) to provide a minimal control-panel UI without introducing Wails/WebKit runtime dependencies into the current repo.
  • Expanded internal/app/internal/desktop bindings with alias DTOs and alias listing so the GUI can show both routable provider state and alias routing state.
  • Added internal/desktop/http_test.go to verify the desktop control panel serves the app shell, returns overview JSON, and persists desktop preferences through the HTTP API.
  • Verified with:
    • gofmt -w cmd/ocswitch-desktop/main.go internal/app/service.go internal/app/types.go internal/desktop/bindings.go internal/desktop/http.go internal/desktop/http_test.go web/assets.go
    • rtk go test ./...
    • rtk go build ./...
    • go run ./cmd/ocswitch-desktop --no-open followed by live HTTP checks against / and /api/overview
  • Constraint note: the PRD still recommends Wails as the long-term native shell, but the current environment lacks wails CLI and desktop system dependencies, so this implementation deliberately ships a dependency-light local control panel first while keeping internal/app and internal/desktop ready for a future Wails swap-in.

Git Commits

(No commits - planning session)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete

Session 12: Wails desktop shell integration

Date: 2026-04-18 Task: Wails desktop shell integration Branch: master

Summary

Migrated the desktop control panel onto a formal Wails + React/TypeScript structure while preserving a browser fallback shell, added real Linux XDG launch-at-login support, and verified both default and desktop_wails Go paths. Native desktop compilation now fails only on missing Linux system packages rather than repository structure issues.

Main Changes

  • Added Wails v2.12.0 to go.mod and introduced wails.json so the repository has a formal desktop-shell project structure.
  • Split desktop entrypoints by build tag:
    • cmd/ocswitch-desktop/main_fallback.go keeps the browser fallback shell for default builds.
    • cmd/ocswitch-desktop/main_wails.go and root main_wails.go provide the real desktop_wails Wails entry path expected by the Wails CLI.
  • Added internal/desktop/wails.go to centralize Wails startup configuration, bind the desktop app object, and serve frontend/dist assets from the same source used by the browser fallback shell.
  • Expanded internal/desktop/app.go into a real desktop composition root with startup, shutdown, close-to-background, preference sync, metadata, and Wails-callable facade methods.
  • Replaced the ad-hoc web/ assets with a formal frontend/ Vite + React + TypeScript app:
    • frontend/src/App.tsx now owns the GUI.
    • frontend/src/api.ts bridges both Wails-bound calls and fallback HTTP /api/* calls.
    • frontend/src/types.ts mirrors the Go DTOs.
    • frontend/src/env.d.ts declares the Wails bridge surface.
    • frontend/src/styles.css carries forward the control-panel styling.
  • Updated the fallback HTTP shell in internal/desktop/http.go to serve frontendassets.DistFS() and to align doctor/meta responses with the Wails bridge semantics.
  • Implemented real Linux XDG launch-at-login handling in internal/desktop/autostart.go and added internal/desktop/autostart_test.go to cover write/remove behavior.
  • Wired MinimizeToTray into close-to-background behavior through internal/desktop/tray.go using public Wails window lifecycle APIs only; intentionally did not depend on private Wails tray internals because the pinned Wails version does not expose a stable public tray API.
  • Added tag-specific runtime helpers:
    • internal/desktop/runtime_wails.go hides the Wails window.
    • internal/desktop/runtime_fallback.go is a no-op for browser fallback mode.
  • Removed the obsolete web/ embedded assets directory after the frontend migration because all code now serves assets from frontend/.
  • Verified with:
    • rtk npm install (frontend dependencies)
    • rtk npm run build
    • rtk go test ./...
    • rtk go test -tags desktop_wails ./...
    • wails build -tags desktop_wails -debug
  • Verification outcome:
    • repository structure, bindings generation, frontend build, and tagged Go compilation all succeed
    • wails build now reaches native Linux compilation and stops only at missing system packages (pkg-config, and likely GTK/WebKit dev packages)
    • native tray menus and native notifications remain intentionally incomplete because the current pinned Wails release does not provide a stable public tray API and no notification backend has been integrated yet

Git Commits

(No commits - planning session)

Testing

  • [OK] (Add test results)

Status

[OK] Completed

Next Steps

  • None - task complete