diff --git a/.gitignore b/.gitignore index c287d91ac12..ac21b42764b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ target .scripts .direnv/ +# Local mirrors for air-gapped use (see docs/OFFLINE_WEB.md) +offline/ + # Local dev files opencode-dev logs/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2ae3fc6f2fb..4796db64560 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -121,6 +121,10 @@ bun run --cwd packages/app dev This starts a local dev server at http://localhost:5173 (or similar port shown in output). Most UI changes can be tested here, but the server must be running for full functionality. +### Air-gapped or offline `opencode web` + +If the machine cannot reach `app.opencode.ai`, build the web app and point the server at the `dist` output. See [docs/OFFLINE_WEB.md](./docs/OFFLINE_WEB.md) for `OPENCODE_APP_DIST`, optional model list mirroring, and troubleshooting. + ### Running the Desktop App The desktop app is a native Tauri application that wraps the web UI. diff --git a/docs/OFFLINE_WEB.md b/docs/OFFLINE_WEB.md new file mode 100644 index 00000000000..e3a2239c3da --- /dev/null +++ b/docs/OFFLINE_WEB.md @@ -0,0 +1,82 @@ +# Air-gapped or offline `opencode web` + +Serve the web UI from a local **`vite build`** output so the server does not proxy to `https://app.opencode.ai`. If no build is present (no `index.html` under the resolved path), behavior is unchanged: the server falls back to that proxy (requires outbound access). + +**Before opening a PR for related code changes:** the project expects an [issue first](https://github.com/anomalyco/opencode/blob/dev/CONTRIBUTING.md#issue-first-policy) (`Fixes #…` / `Closes #…` in the PR description). + +--- + +## 1. Build the web app (while online) + +From the repository root: + +```bash +bun install +cd packages/app +bun run build +``` + +Confirm **`packages/app/dist/index.html`** exists. + +--- + +## 2. Environment variables + +| Variable | Purpose | +|----------|---------| +| `OPENCODE_APP_DIST` | Absolute path to the `dist` directory (must contain `index.html`). If unset, the server looks for `packages/app/dist` relative to the running server package. | +| `OPENCODE_DISABLE_MODELS_FETCH` | Set to `1` to disable periodic fetches to `https://models.dev`. | +| `OPENCODE_MODELS_PATH` | Optional path to a local `api.json`–compatible file (e.g. downloaded from `https://models.dev/api.json`) when the network cannot reach models.dev. | +| `OPENCODE_DISABLE_AUTOUPDATE` | Set to `1` to disable autoupdate checks. | +| `OPENCODE_SERVER_PASSWORD` | Recommended: protect the web server with HTTP Basic auth. | + +Download a models list for `OPENCODE_MODELS_PATH` (optional): + +```bash +mkdir -p offline +curl -fsSL "https://models.dev/api.json" -o offline/models-api.json +``` + +The `offline/` directory is gitignored for local mirrors; use any path for `OPENCODE_MODELS_PATH`. + +--- + +## 3. Start + +```bash +export PATH="$HOME/.bun/bin:$PATH" +REPO="/path/to/opencode" +export OPENCODE_APP_DIST="$REPO/packages/app/dist" +export OPENCODE_DISABLE_MODELS_FETCH=1 +export OPENCODE_MODELS_PATH="$REPO/offline/models-api.json" +export OPENCODE_DISABLE_AUTOUPDATE=1 +export OPENCODE_SERVER_PASSWORD="your-strong-password" + +cd "$REPO/packages/opencode" +bun run --conditions=browser ./src/index.ts web +``` + +Open the URL printed in the terminal (often `http://127.0.0.1:4096/`). + +On success, logs include **`serving web UI from local dist`** once, with the resolved `root` path. + +--- + +## 4. Bundled static assets in this repo + +- **`packages/app/public/changelog.json`** — copied into `dist/` on build; the app requests **`/changelog.json`** on the same origin instead of `https://opencode.ai/changelog.json`. + +--- + +## 5. Troubleshooting + +| Symptom | What to check | +|---------|----------------| +| Blank page or failed UI load | `OPENCODE_APP_DIST` (if set), and that `dist/index.html` exists at that path. | +| Traffic still goes to `app.opencode.ai` | Invalid or missing local `index.html` causes fallback to the remote proxy. | + +--- + +## 6. Regenerating SDK after server changes + +If you change `packages/opencode/src/server/server.ts`, follow [CONTRIBUTING.md](https://github.com/anomalyco/opencode/blob/dev/CONTRIBUTING.md) and run `./script/generate.ts` when API or SDK artifacts need updating. diff --git a/packages/app/public/changelog.json b/packages/app/public/changelog.json new file mode 100644 index 00000000000..2574ee2536b --- /dev/null +++ b/packages/app/public/changelog.json @@ -0,0 +1 @@ +{"releases":[{"tag":"v1.2.27","name":"v1.2.27","date":"2026-03-16T02:34:10Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.27","highlights":[],"sections":[{"title":"Core","items":["Fixed VCS watcher if statement logic","Delete legacy permission module","Clean up pending entry when question is aborted","Remove SIGHUP exit handler","Effectify PermissionNext and fix InstanceState ALS bug","Inline branded ID schemas","Refactor QuestionService to use effects","Ensure that compaction message is tracked as agent initiated","Increase default chunk timeout from 2 minutes to 5 minutes","Fix lost sessions across worktrees and orphan branches (@michaeldwan)"]},{"title":"Desktop","items":["Remove open label from UI","Handle multiline web paste in prompt composer"]}]},{"tag":"v1.2.26","name":"v1.2.26","date":"2026-03-13T16:33:18Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.26","highlights":[],"sections":[{"title":"Core","items":["Scaffold effect-to-zod bridge for schema conversion","Serialize configuration for Bun installations","Support text attachments in app","Paginate session history for improved server performance","Sessions lost after git init in existing project (@michaeldwan)","Fail fast on config dependency installs in end-to-end tests","Filter empty content blocks for Bedrock provider (@Tom-Ryder)","Refactor ProviderAuthService to use Effect pattern","Add console account subcommands to CLI","Refactor AuthService to use Effect pattern"]},{"title":"TUI","items":["Hide console command from help output","Remove OpenRouter warning","Reorder provider list in providers login"]},{"title":"Desktop","items":["Model selection now persists by session","Polish prompt composer controls","Synchronize sidebar state across the application","Use new-session icon in sidebar buttons","Avoid clipping new session during sidebar animation","Animate titlebar controls on sidebar open","Restore sidebar dash and sync session spinner colors","Fork should copy prompt into new session","Improved sidebar spacing and session list spinner transition","Terminal cloning without retry","Scroll falls behind prompt input","Adjust spacing in todo list component","Better optimistic prompt submit in app","Synchronize internationalization translations","Use cursor session history loading for improved performance","List item background colors fixed in app","Stabilize todo dock end-to-end tests with composer probe","Desktop multi-window support added to Electron","Increase CI end-to-end test workers"]}]},{"tag":"v1.2.25","name":"v1.2.25","date":"2026-03-12T23:34:33Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.25","highlights":[],"sections":[{"title":"Core","items":["Support non-OpenAI Azure models that use completions endpoints","Flow branded ProviderID and ModelID through internal signatures","Brand ProviderID and ModelID types for improved type safety","Remove external sourcemap generation to reduce build artifacts","Brand PermissionID, PtyID, QuestionID, and ToolID types for improved type safety","Add ARM64 release targets for Windows CLI and desktop","Brand PartID through Drizzle and Zod schemas","Brand WorkspaceID through Drizzle and Zod schemas","Resolve symlinks in Instance cache to prevent duplicate contexts (@jmylchreest)","Brand SessionID through Drizzle and Zod schemas","Restore plugin serverUrl getter so plugins can connect to local server","Re-enable snapshot in ACP (@noamzbr)","Adjust skill presentation to reduce token usage","Brand ProjectID through Drizzle and Zod schemas","Tighten effect-based account flows","Read stdout and stderr in PackageRegistry.info before waiting for process to exit (@ghost91-)","Improve skill presentation to agent to increase likelihood of skill invocations","Hide Windows background consoles in Electron","Add GOOGLE_VERTEX_LOCATION environment variable support for Vertex AI (@SOUMITRO-SAHA)","Implement resilient organization data fetching with error handling","Make account login upgrades safe while adding multi-account workspace authentication","Don't permit access to system directories","Allow passing workspaceID into session create endpoint","Fixed chunk timeout when processing LLM stream","Make worktrees read the project ID from local workspace","Add thinking variants support for SAP AI provider (@jerome-benoit)","Upgrade OpenTUI to v0.1.87","Fix OAuth auto-connect failing on first MCP connection (@domdomegg)","Extract createApp function for server initialization","Put workspace routing behind OPENCODE_EXPERIMENTAL_WORKSPACES flag","Replace Bun semver with npm semver package","Replace Bun shell with direct spawn calls in core flows","Change pathToFileURL imports from bun to url module","Multiple jdtls LSPs eating memory in Java monorepos (@stevoland)"]},{"title":"TUI","items":["Use parse() at boundaries instead of manual make() for imports","Wait for model store before auto-submitting --prompt in TUI (@altendky)","Handle error when creating a session in TUI"]},{"title":"Desktop","items":["Fix broken mobile sidebar sizing issue in workflows mode (@5w14)","Fixed terminal animation in application","Fix sidebar quirks in app","Rework default server initialization and connection handling in desktop client","Fix terminal e2e test flakiness by implementing a real terminal driver","Set default WebSocket username and fix terminal spawn lifecycle issues in desktop app (@OpeOginni)","Theme Windows titlebar overlay in Electron","Guard comment accessor in message timeline","Re-focus prompt after terminal opens in slash-terminal test","Restore to message and fork session functionality in app","Todos not clearing in app","Skip editor reconcile during IME composition (@ysm-dev)","Simplify review pane","Trim session render work in app for improved performance","Fix tests in app package","Fixed terminal jank in the app","Fixed terminal focus issues and reduced jank in the app","Add debug window to app","Display development statistics in the application","Terminal state corruption fixed"]},{"title":"SDK","items":["Fix ESM imports for @opencode-ai/plugin"]}]},{"tag":"v1.2.24","name":"v1.2.24","date":"2026-03-09T16:10:00Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.24","highlights":[],"sections":[{"title":"Core","items":["Add initial support for workspaces into the TUI","Send context-1m-2025-08-07 beta header to GitLab to enable 1M context window (@Krule)","Add Copilot GPT-5.4 xhigh support"]},{"title":"Desktop","items":["Fix scroll jitter and loop issues in app","Session title turn spinner now displays correctly","Dismiss toast notifications when questions or permissions are resolved (@neriousy)"]}]},{"tag":"v1.2.23","name":"v1.2.23","date":"2026-03-09T13:51:07Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.23","highlights":[],"sections":[{"title":"Core","items":["Disable fallback to free nano for small model requests"]},{"title":"TUI","items":["Pass missing auth headers in run --attach (@ericclemmons)"]},{"title":"Desktop","items":["Remove oc-1 theme from app","Fix sidebar workspace container sizing to prevent content overflow","Don't animate review panel in/out","Revert \"Stupid Sexy Timeline\" feature","Sanitize workspace store filenames on Windows","Generate color palettes in app"]}]},{"tag":"v1.2.22","name":"v1.2.22","date":"2026-03-08T22:35:21Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.22","highlights":[],"sections":[{"title":"Core","items":["Canonicalize current working directory after changing directories in TUI","Fix broken MCP toggling in TUI (@natewill)","Update database path test to verify correct channel-based filename","Allow beta channel to share database with stable channel","Add OPENCODE_SKIP_MIGRATIONS flag to bypass database migrations"]},{"title":"TUI","items":["Guard TUI exit to prevent premature termination","Avoid TTY corruption from double cleanup (@tobwen)"]},{"title":"Desktop","items":["Fix sidebar background color when collapsed","Suppress hover when opening project menu or right-clicking to prevent flickering","Trim retained desktop terminal buffers","Messages not loading reliably","Prune and evict stale app session caches","Restore new-session logo on dev so users recognize OpenCode immediately","Revert new session logo on dev branch to ship UI change with auto-accept-permissions feature","Add OpenCode logo to new session screen for immediate app identification","Revert prompt control docking in TUI","Dock auto-accept after thinking and move Add file to bottom-left","Balance titlebar columns so center content doesn't get squeezed by long side content","Center empty states vertically in session view and improve review panel messaging for projects without version control","Review panel transition fixed in app"]}]},{"tag":"v1.2.21","name":"v1.2.21","date":"2026-03-07T18:01:01Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.21","highlights":[],"sections":[{"title":"Core","items":["Preserve original line endings in edit tool (@ranqn)","Fix Git path resolution for modified files across Git Bash, MSYS2, and Cygwin on Windows","Fix PTY session handle leak (@kikuchan)","Sanitize preview database filenames","Log stack trace when schema validation fails","I need to see the actual commit diff to understand what was fixed and provide an accurate changelog entry.","Add project git init API","Update Drizzle and channel database handling","Speed up share loads","Enable auto-accept keybind regardless of permission config (@luisfelipesena)"]},{"title":"TUI","items":["Fix broken /export toggling in TUI (@natewill)"]},{"title":"Desktop","items":["Guard session-header current() against undefined when options is empty (@cyberprophet)","Preserve file tree tab on reopen and fix e2e test regressions (@neriousy)","Remove close button from project hover popover","New session uses agent model/variant","Model sticks to session after being changed","Based on the commit message \"fix(app): all panels transition\", here's the changelog entry:","Can't scroll files in app","Fix maximum width on timeline component","Align session empty states in TUI","Add interactive timeline visualization feature","Share workspace slug wait helper across e2e specs","Abort sessions and wait for idle before e2e cleanup","Show skill issue when snapshotting is off in desktop app","Fix portal positioning for sidebar menus and tooltips by removing conditional mount logic","Add end-to-end tests for app (part 67) (@neriousy)","Add sidebar reveal animation, hover peek overlay, and weaker dividers to app","Better review and file tree empty states","Enable Safari autocorrect in normal mode, disable in shell mode (@alexandrereyes)","Revert stale read error fix in app","Add English to locale matchers (@KirillTregubov)"]}]},{"tag":"v1.2.20","name":"v1.2.20","date":"2026-03-06T07:29:56Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.20","highlights":[],"sections":[{"title":"Core","items":["Stop leaking fsmonitor daemons that caused 60GB+ of committed memory after running tests","Replace Bun.which with npm which in OpenCode"]},{"title":"TUI","items":["Restore Bun stdin reads for prompt input"]}]},{"tag":"v1.2.19","name":"v1.2.19","date":"2026-03-06T04:29:31Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.19","highlights":[],"sections":[{"title":"Core","items":["Add GPT-5.4 to Codex allowed models list (@msadiks)","Replace Bun.stderr and Bun.color with Node.js equivalents","Replace Bun.connect with net.createConnection for better compatibility","Use SHA1 for hash instead of unsupported xxHash3-XXH64","Replace Bun.hash with Hash.fast using xxhash3-xxh64","Replace Bun.write with Filesystem.write in config files","Replace Bun.write/file with Filesystem utilities in snapshot","Replace Bun.sleep with Node.js timers for better compatibility"]},{"title":"TUI","items":["Use node:stream/consumers for stdin reading","Replace Bun.stdin.text with Node.js stream reading for better compatibility"]},{"title":"Desktop","items":["Fix stale show in app (@neriousy)","Remove keyboard shortcut tooltips from new session and new workspace buttons in the sidebar","Load tab when opening file"]}]},{"tag":"v1.2.18","name":"v1.2.18","date":"2026-03-05T19:01:30Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.18","highlights":[],"sections":[{"title":"Core","items":["Handle SIGHUP signal and kill process gracefully"]},{"title":"TUI","items":["Add onClick handler to InlineTool and Task components","Add options to auth login command to skip interactive questions (@dbpolito)","Don't let Dax touch the UI"]},{"title":"Desktop","items":["Fork Ghostty for web-based terminal implementation","Show errors for stale keyed components","Fixed locale error in app","Resolve stale read error in app","Improve provider settings consistency in app","Preserve question dock state across session switches (@ualtinok)","Fix icon jiggle in app","Open search with Mod+F even when editor is not focused","Improve error handling and translation in desktop server error formatting (@OpeOginni)","Improve agent selection logic to correctly pass configured models and variants (@OpeOginni)","Remove unnecessary macOS entitlements","Add desktop deep link support for creating new sessions","Prefer using useLocation hook instead of window.location in app"]},{"title":"SDK","items":["Update SDK package.json"]}]},{"tag":"v1.2.17","name":"v1.2.17","date":"2026-03-04T14:58:43Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.17","highlights":[],"sections":[{"title":"Core","items":["Rework workspace integration and adaptor interface","Clarify output capture guidance in bash tool documentation"]},{"title":"TUI","items":["Show scrollbar by default","Prevent orphaned opencode subprocesses on shutdown","Validate agent when running with attach flag (@alberti42)"]},{"title":"Desktop","items":["Remove blur from todos in app","Delay dock animation on session load","Remove diff lines from sessions in sidebar","Loading session should be scrolled to the bottom","Close terminal tabs properly"]}]},{"tag":"v1.2.16","name":"v1.2.16","date":"2026-03-03T21:08:54Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.16","highlights":[],"sections":[{"title":"Core","items":["Normalize trailing slashes in auth login URLs (@elithrar)","Upgrade OpenTUI to v0.1.86 and enable markdown rendering by default","Avoid Gemini combiner schema sibling injection","Forward metadata options to Cloudflare AI Gateway provider (@ryanskidmore)","Clone part data in Bus event to preserve token values (@ryanskidmore)","Recover from 413 Request Entity Too Large errors via automatic compaction (@bentrd)","Show human-readable message for HTML error responses (@rianvdm)","Kill orphaned MCP child processes and expose OPENCODE_PID on shutdown (@ryanwyler)","Add workspace_id to session table","Add WorkspaceContext to core","Basic implementation of remote workspace support","Change keybindings to navigate between child sessions","Fixed test issues","Fixed terminal rendering and interaction issues in the application"]},{"title":"TUI","items":["Replace curved arrow with straight arrow for better terminal compatibility","Show pending tool call count in TUI instead of generic 'Running...' message","Use arrow indicator for active tool execution in TUI","Disable session navigation commands when no parent session (@jerome-benoit)","Fixed project ID conflict and updated handling for same session ID (@noamzbr)","Improve task tool display with subagent keybind hints and spinner animations","Add Go provider list command"]},{"title":"Desktop","items":["Defer diff rendering","Fixed timeline performance jank in the application","Tighten up header elements in the app","Stabilize project close navigation","Add comprehensive animation system with multiple easing functions and transition utilities","Default auto-respond to false","Refactor app to use SolidJS","Move session review bottom padding to UI layer","Fix latest.json finalizer in desktop application","Revert Polish Turkish translations","Use correct download link in finalize-latest-json script","Faster session switching via windowed rendering and staged timeline","Add compact UI to the app (@neriousy)","Polish Turkish translations (@vaur94)","Fallback to synthetic icon for unknown provider IDs (@rexdotsh)","Fixed scroll issues in the app","Synchronize internationalization translations","Add Warp to the open menu","Add latest.json finalizer script for desktop builds","Auto-accept permissions in app","Add Turkish locale support for app and UI packages (@vaur94)","Add recent projects section to command palette (@neriousy)","Move desktop open_path functionality to Rust","Allow providing username and password when connecting to remote server","Fixed permission indicator in app","Add permission notifications to app","Show keybind on context tab close button","Better diff and code comments in app","Deduplicate file tree scroll state management","Align review changes select height","Mute inactive file tab icons","Set max-width on session when review is closed but file tree is open","Add border to file tree on scroll","Fix session tab alignment in compact view to prevent vertical overflow","New tabs styling in the app","Auto-accept all permissions mode","Enhance project tile interaction with suppress hover functionality (@OpeOginni)","Simplify review layout","Restore shell path environment for desktop sidecar","Open app in PowerShell instead of Command Prompt on Windows (@neriousy)"]},{"title":"SDK","items":["Add zen mode feature"]}]},{"tag":"v1.2.15","name":"v1.2.15","date":"2026-02-26T08:22:40Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.15","highlights":[],"sections":[{"title":"Core","items":["Fix most segfaults on Windows with Bun v1.3.10 stable","Split TUI and server configuration"]},{"title":"Desktop","items":["Remove interactive shell flag from sidecar spawn to prevent hang on macOS (@kilhyeonjun)","Fixed permissions and questions handling from child sessions in the app","Fixed keyboard navigation for previous/next message (@neriousy)","Correct Copilot provider description in i18n files (@Oleksii-Pavliuk)"]}]},{"tag":"v1.2.14","name":"v1.2.14","date":"2026-02-25T14:56:11Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.14","highlights":[],"sections":[{"title":"Core","items":["Add message delete endpoint (@shantur)"]},{"title":"TUI","items":["Consume stdout concurrently with process exit in auth login (@Ayushlm10)"]}]},{"tag":"v1.2.13","name":"v1.2.13","date":"2026-02-25T07:27:33Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.13","highlights":[],"sections":[]},{"tag":"v1.2.12","name":"v1.2.12","date":"2026-02-25T07:12:41Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.12","highlights":[],"sections":[{"title":"Core","items":["Synchronize changes","Temporarily disable plan enter tool to prevent unintended mode switches during task execution","Migrate Bun.spawn to Process utility with timeout and cleanup","Disable Bun config cache in CI","Await git ID cache write in project module","Import custom tools via file URL"]},{"title":"TUI","items":["Add Go SDK code generation script","Show LSP errors for apply_patch tool"]},{"title":"Desktop","items":["Enhance Windows app resolution and UI loading states (@neriousy)","Update desktop README for accuracy"]}]},{"tag":"v1.2.11","name":"v1.2.11","date":"2026-02-24T23:29:16Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.11","highlights":[],"sections":[{"title":"Core","items":["Add workspace-serve command (experimental)","ACP both live and load share synthetic pending status preceding actual data (@noamzbr)","Replace structuredClone with spread operator for process.env in tests","Add 50ms tolerance for NTFS mtime precision in Windows FileTime assertions","Replace Unix-only test assumptions with cross-platform alternatives","Use path.sep in discovery test for cross-platform path matching","Normalize backslash paths in config rel() and file ignore on Windows","Fix plugin resolution with createRequire fallback on Windows","Harden preload cleanup against Windows EBUSY errors","Normalize git excludesFile path for Windows in tests","Stream bash output and add synthetic pending events to ACP (@noamzbr)","Add git flags for snapshot operations and fix tests for cross-platform on Windows","Handle CRLF line endings in markdown frontmatter parsing on Windows","Use path.join for cross-platform glob test assertions","Upgrade to Bun 1.3.10 canary and force baseline builds always","Normalize paths at permission boundaries on Windows","Windows path support and canonicalization (@edemaine)","Upgrade OpenTUI to v0.1.81","Change detection on Windows, especially Cygwin (@edemaine)","Cache platform binary in postinstall for faster startup","Revert caching platform binary in postinstall for faster startup","Cache platform binary in postinstall for faster startup","Publish desktop beta releases to a separate repository","Add experimental endpoint to list all sessions","Fixed terminal issues in the app","Respect info exclude in snapshot staging","Missing plugin dependencies cause TUI to black screen (@elithrar)"]},{"title":"TUI","items":["Support variant parameter in GitHub Actions and OpenCode GitHub run command (@elithrar)"]},{"title":"Desktop","items":["Ignore stale part deltas in the application","Fix bug where lines remain highlighted after canceling a comment (@neriousy)","Replace error handling with serverErrorMessage utility and add ConfigInvalidError checks (@OpeOginni)","Preserve native path separators in file path helpers","Remove file tree tooltips","Update createOpenReviewFile test to match new call order","Wait for loadFile to complete before opening file tab","Windows E2E test failures due to IPv6 networking issues resolved","Correct inverted chevron direction in todo list (@kevinWangSheng)","Feed customization options","Add beta icon to desktop application","E2E test updated to current version","Remove double-border in share button","Better sound effect disabling UX","Add custom scroll view to app","Show and hide reasoning summaries in the app","Stay pinned with auto-scroll on todos, questions, and permissions","Bring back -i flag in sidecar arguments for desktop","Large text pasted into prompt input no longer causes main thread to lock"]},{"title":"SDK","items":["Scripts using Turbo commands would not run on Windows"]}]},{"tag":"v1.2.10","name":"v1.2.10","date":"2026-02-20T11:18:54Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.10","highlights":[],"sections":[{"title":"Desktop","items":["Don't spawn sidecar if default is localhost server"]},{"title":"SDK","items":["Build SDK to dist/ instead of dist/src"]}]},{"tag":"v1.2.9","name":"v1.2.9","date":"2026-02-20T01:45:35Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.9","highlights":[],"sections":[{"title":"Core","items":["Add missing id, sessionID, and messageID to MCP tool attachments (@NatChung)","Remove unnecessary deep clones from session loop and LLM stream","Remove User-Agent header assertion from LLM test to fix failing test"]},{"title":"TUI","items":["Use structuredClone instead of remeda's clone for better performance and native support (@mhart)"]},{"title":"Desktop","items":["Restore settings header mask"]}]},{"tag":"v1.2.8","name":"v1.2.8","date":"2026-02-19T22:38:57Z","url":"https://github.com/anomalyco/opencode/releases/tag/v1.2.8","highlights":[],"sections":[{"title":"Core","items":["Support adaptive thinking for Claude Sonnet 4.6 (@tctev)"]},{"title":"TUI","items":["Add custom tool and MCP call responses that are visible and collapsible (@yanosh-k)"]},{"title":"Desktop","items":["Black screen on launch with sidecar server fixed","Clear todos on abort"]}]}]} \ No newline at end of file diff --git a/packages/app/src/components/dialog-connect-provider.tsx b/packages/app/src/components/dialog-connect-provider.tsx index e4fe9e7c4ed..0d8e0ac4d36 100644 --- a/packages/app/src/components/dialog-connect-provider.tsx +++ b/packages/app/src/components/dialog-connect-provider.tsx @@ -383,7 +383,7 @@ export function DialogConnectProvider(props: { provider: string }) { setFormStore("error", undefined) await globalSDK.client.auth.set({ providerID: props.provider, - auth: { + body: { type: "api", key: apiKey, }, diff --git a/packages/app/src/components/dialog-custom-provider.tsx b/packages/app/src/components/dialog-custom-provider.tsx index 4d220a0b191..528c31b3f07 100644 --- a/packages/app/src/components/dialog-custom-provider.tsx +++ b/packages/app/src/components/dialog-custom-provider.tsx @@ -131,7 +131,7 @@ export function DialogCustomProvider(props: Props) { const auth = result.key ? globalSDK.client.auth.set({ providerID: result.providerID, - auth: { + body: { type: "api", key: result.key, }, diff --git a/packages/app/src/context/highlights.tsx b/packages/app/src/context/highlights.tsx index 058f7cc4b6c..f5fdc0bc795 100644 --- a/packages/app/src/context/highlights.tsx +++ b/packages/app/src/context/highlights.tsx @@ -7,7 +7,7 @@ import { useSettings } from "@/context/settings" import { persisted } from "@/utils/persist" import { DialogReleaseNotes, type Highlight } from "@/components/dialog-release-notes" -const CHANGELOG_URL = "https://opencode.ai/changelog.json" +const CHANGELOG_URL = "/changelog.json" type Store = { version?: string diff --git a/packages/app/src/entry.tsx b/packages/app/src/entry.tsx index b5cbed6e75d..4d8fa500c2c 100644 --- a/packages/app/src/entry.tsx +++ b/packages/app/src/entry.tsx @@ -67,7 +67,7 @@ const notify: Platform["notify"] = async (title, description, href) => { const notification = new Notification(title, { body: description ?? "", - icon: "https://opencode.ai/favicon-96x96-v3.png", + icon: "/favicon-96x96-v3.png", }) notification.onclick = () => { diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx index f8e16f3e122..3b3f5b0236b 100644 --- a/packages/app/src/pages/layout/sidebar-items.tsx +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -44,7 +44,7 @@ export const ProjectIcon = (props: { project: LocalProject; class?: string; noti createApp({})) @@ -497,19 +501,49 @@ export namespace Server { }, ) .all("/*", async (c) => { - const path = c.req.path + const webCsp = + "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src 'self' data:" - const response = await proxy(`https://app.opencode.ai${path}`, { + const root = Flag.OPENCODE_APP_DIST + ? path.resolve(Flag.OPENCODE_APP_DIST) + : path.join(path.dirname(fileURLToPath(import.meta.url)), "../../../app/dist") + const indexPath = path.join(root, "index.html") + if (await Bun.file(indexPath).exists()) { + if (!webUiLocalLogged) { + webUiLocalLogged = true + log.info("serving web UI from local dist", { root }) + } + const urlPath = c.req.path + const rel = urlPath === "/" ? "index.html" : urlPath.slice(1) + if (rel.includes("..")) return c.text("Not found", 404) + + const rootResolved = path.resolve(root) + const resolved = path.resolve(path.join(root, rel)) + const relative = path.relative(rootResolved, resolved) + if (relative.startsWith("..") || path.isAbsolute(relative)) return c.text("Not found", 404) + + try { + const st = await stat(resolved) + const body = st.isDirectory() ? Bun.file(indexPath) : Bun.file(resolved) + const res = new Response(body) + res.headers.set("Content-Security-Policy", webCsp) + return res + } catch { + const res = new Response(Bun.file(indexPath)) + res.headers.set("Content-Security-Policy", webCsp) + return res + } + } + + const reqPath = c.req.path + const response = await proxy(`https://app.opencode.ai${reqPath}`, { ...c.req, headers: { ...c.req.raw.headers, host: "app.opencode.ai", }, }) - response.headers.set( - "Content-Security-Policy", - "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; media-src 'self' data:; connect-src 'self' data:", - ) + response.headers.set("Content-Security-Policy", webCsp) return response }) }