Release v0.17.0 - Provider management, custom workspaces, faster sessions, safer settings, more languages and smoother desktop performance#534
Merged
Conversation
## Summary - Show attachments added to the no-session draft prompt before a session exists. - Create and activate a real session before first-prompt slash commands or shell commands execute. - Keep existing session command behavior unchanged by adding an optional PromptInput command handler. ## Validation - npm run typecheck --workspace @codenomad/ui
…cs (#413) ## Summary Adds a new **Info** section to the Settings screen, giving users quick visibility into their CodeNomad version, runtime environment, and a way to collect diagnostic data for bug reports. Closes #412 ## Changes - **New component:** `info-settings-section.tsx` — renders three cards: - **About** — Server/UI version, runtime type (electron/tauri/web), platform, OS with CPU architecture detection, server URL, workspace root - **Updates** — Placeholder "Check for updates" button, ready to wire into the existing dev release monitor (`serverMeta.update`) - **Diagnostics** — Log scope dropdown (Summary only / Summary + workspace logs), Copy to clipboard, Download .txt — generates a structured diagnostic report - **New styles:** `settings-info.css` — info row layout, select row, toast feedback, update note - **Wiring:** Added `"info"` to `SettingsSectionId` union, registered nav item and routing case in `settings-screen.tsx`, imported CSS in `controls.css` - **i18n:** 20 new keys added to all 7 locales (English canonical, others fall back via existing fallback chain) ## Design decisions - No server changes needed — version/runtime info comes from existing `GET /api/meta` endpoint and client-side `navigator` detection - No sensitive data (API keys, env values) included in diagnostic reports - CPU architecture extracted from `navigator.userAgent` for Linux/Windows/macOS - Log scope dropdown uses existing Kobalte Select pattern for consistency ## Verification - `tsc --noEmit` passes (0 errors) - `vite build` bundles successfully - Tauri Rust backend compiles and starts correctly --- > **Note:** The majority of this implementation was produced through CodeNomad using DeepSeek v4 Pro and has undergone manual review before submission. All design, architecture, and code quality decisions were evaluated by a human reviewer. --------- Co-authored-by: Shantur Rathore <i@shantur.com>
## Summary - add a top-edge resize handle so the session composer can be freely stretched upward while keeping the bottom edge anchored - switch the expand/shrink control to track the actual composer height, clamp expansion to the session toolbar boundary, and reset the composer back to its default height after each send - preserve the right-side three-column control layout in narrow and windowed panes so the five utility controls stay outside the input, the stop button rises with the composer, and the send button remains bottom-pinned ## Testing - npm run typecheck --workspace @codenomad/ui - npm run build --workspace @codenomad/ui ## Notes - the build still reports the existing `virtua` JSX warning from `../../node_modules/virtua/lib/solid/index.jsx`; this PR does not introduce that warning - local unstaged changes in `.opencode/package-lock.json`, `.sisyphus/`, and Electron dev-port files were intentionally excluded from this PR because they are unrelated to the composer height feature --------- Co-authored-by: Shantur Rathore <i@shantur.com>
## Summary - Make the folder selection home screen scroll vertically when short viewports cannot fit the primary action column. - Cap the recent folders/server list to the measured action column height on desktop so it scrolls internally instead of stretching the layout. - Use a focused home layout stylesheet with equal-width desktop columns. ## Validation - npm run typecheck --workspace @codenomad/ui - npm run build --workspace @codenomad/ui ## Notes - Build still emits existing warnings about virtua JSX import source and large chunks; unrelated to this change.
## Summary - Trim Electron app packaging to only include runtime shell assets and remove unused workspace runtime dependencies. - Copy server resources explicitly, filtering stale build artifacts and pruning known non-runtime dependency files. - Bundle only the Node executable instead of the full Node distribution. ## Validation - Built macOS Electron artifacts with `npm run build:mac --workspace @neuralnomads/codenomad-electron-app`. - Ran packaged server CLI smoke test: `dist/bin.js --version` returned `0.16.0`. - Ran packaged dependency import smoke test for pruned runtime dependencies. ## Size Impact - macOS x64 zip: 161M - macOS arm64 zip: 161M - macOS arm64 app bundle: 435M - Packaged server node_modules: 25M
## Summary - Stop the right panel from immediately re-opening collapsed Status sections. - Keep the existing default expanded sections, including session changes. ## Why Users could click Status sub-panels to collapse them, but the UI immediately expanded them again, making the accordion controls feel broken. ## Validation - npm run typecheck --workspace @codenomad/ui - git diff --check - npm run build --workspace @codenomad/ui
## Summary - Fixes #460 by changing the prompt control DOM order so tabbing from the textarea reaches expand before clear. - Clears prompt text through the textarea native delete path so Cmd/Ctrl+Z can restore cleared text where the browser supports native undo. - Keeps the existing app-state fallback for environments where native editing commands are unavailable or throw. ## Validation - npm run typecheck --workspace @codenomad/ui - Reviewed fallback behavior: `document.execCommand` is checked for callability and wrapped in `try/catch`, so unavailable native editing commands still fall back to app-state clearing. ## Manual QA Notes - In a supported desktop/browser host: type text, click clear, then press Cmd/Ctrl+Z and confirm text restores. - Type text, press Tab and confirm focus moves to expand before clear; pressing Tab again reaches clear.
…s open (#459) ## Summary Fixes a mobile UX bug where, with the session list (left drawer) open on phone layout, the still-visible instance/project tab bar at the top was non-interactive. Tapping a tab did nothing — users had to close the drawer first and then switch projects/instances. After this change, tapping a tab in that bar switches the instance/project **and** the drawer auto-closes in a single gesture, matching user expectation. ## Root cause On phone (`max-width: 767px`), `InstanceShell` renders the left session sidebar via MUI's `Drawer variant="temporary"`. The drawer paper is offset down to `floatingTopPx()` so the instance tab bar remains visually visible above it. However, MUI's `Modal` Backdrop is `position: fixed; inset: 0` and covers the entire viewport — including the area over the tab bar. The backdrop is styled `backgroundColor: transparent` (so it's invisible) but it still captures pointer events at `z-index: 60`. Taps over the tab bar hit the transparent backdrop → MUI calls `onClose` (closing the drawer) but the tab's click handler never fires. ## Implementation 1. **`packages/ui/src/components/instance/instance-shell2.tsx`** — Constrain the MUI Drawer Backdrop via `sx` overrides on both the left (session list) and right drawers so the backdrop is bound to the drawer paper's vertical range (`top: floatingTopPx(); height: floatingHeight();`) instead of fullscreen. Taps over the tab bar now reach the tab buttons. 2. **`packages/ui/src/styles/panels/tabs.css`** — Lift `.tab-bar-instance` to `position: relative; z-index: 70` so it stacks deterministically above the drawer (z-index 60) across browsers as defense-in-depth. 3. **`packages/ui/src/components/instance/shell/useDrawerChrome.ts` + `instance-shell2.tsx`** — Expose `closeFloatingDrawersIfAny` from `useDrawerChrome` and call it from an `InstanceShell` effect that fires when `props.isActiveInstance` flips `true → false`. This closes any open floating drawer on the instance the user just switched away from, so its previously-open state doesn't bleed back when the user returns to that tab later. Tablet (>=768px) and desktop (>=1280px) layouts use pinned drawers (no temporary modal), so the backdrop constraint and z-index lift are inert there. The fix applies symmetrically to the right drawer on phone. ## Verification - `tsc --noEmit` clean. - `vite build` clean. - Manual mobile-emulation checklist in the task file (`tasks/done/058-mobile-session-list-blocks-tab-switch.md`) and SUMMARY in `evidences/058-mobile-session-list-blocks-tab-switch/`. ## Reviewer manual check (phone viewport <=767px) - Open session list drawer. Tap a different instance tab → it activates AND drawer closes. - Tap "+" while drawer open → folder picker opens, drawer closes. - Tap Settings / Notifications / Remote while drawer open → action fires, drawer closes. - Same checks against the right drawer. - Tap area below tab bar but outside drawer paper → drawer still closes (existing backdrop dismissal preserved). - Resize to tablet and desktop widths → pinned drawers unaffected. - No visual regression in light or dark theme. --------- Co-authored-by: Ubuntu <omer@Omer.dn3uxh3znnmu5eefnjnut0i1af.tlvx.internal.cloudapp.net> Co-authored-by: Shantur Rathore <i@shantur.com>
## Problem The `Comment PR Artifacts` workflow consistently times out before the `PR Build Validation` run can complete. The build pipeline typically takes 14–25 minutes (especially the Tauri macOS build), but the comment workflow only polled for ~12 minutes (30 attempts × 10-second intervals plus API overhead). This has been causing the `comment` check to fail on every PR — see PR #463 where it failed 3 consecutive times. ## Fix - Increase polling attempts from **30 → 90** - Increase sleep interval from **10s → 20s** - Effective maximum wait: ~30 minutes of sleep + API overhead ≈ 45+ minutes total This gives ample headroom for the full build matrix to complete, including slower runners like `build-tauri-macos`. ## Why this needs to merge first The `comment-pr-artifacts.yml` workflow uses `pull_request_target`, which means it runs **from the base branch (dev)**, not the PR branch. Changes to this file in PR #463 cannot take effect until this fix lands on `dev`. Once merged, the comment workflow will stop timing out on PR #463 and all future PRs. --- _This PR was created by an AI agent (OpenHands) on behalf of the user to unblock PR #463._ Co-authored-by: openhands <openhands@all-hands.dev>
## Summary - revert the NomadWorks initialization artifacts that introduced tracked `.nomadworks` state, root `codemap.yml`, SCR registry files, and task registry files - keep the tracked `.opencode` project configuration/commands/agent files because they are part of the expected CodeNomad repo setup - preserve unrelated product commits while cleaning up only the NomadWorks-generated repo state
## Summary - Expands Linux `--launch` browser discovery for Brave and Vivaldi package variants (`brave-browser-stable`, `brave`, `vivaldi-stable`). - Adds snap path candidates for Brave and Vivaldi plus Flatpak launch commands. - Adds `xdg-open` as the final fallback when direct browser app-mode launch candidates are unavailable. ## Validation - Attempted `npm run typecheck --workspace @neuralnomads/codenomad`, but it failed before checking this change because the worktree is missing the `node` type definitions (`TS2688: Cannot find type definition file for 'node'`). Fixes #469 -- Yours, [CodeNomadBot](https://github.com/NeuralNomadsAI/CodeNomad) --------- Co-authored-by: Shantur Rathore <i@shantur.com>
) ## Summary - move provider authentication management out of global settings and into the model selector so it always runs against a live OpenCode instance - add an instance-scoped provider manager modal with API-key and OAuth flows, cancellable OAuth waiting, and provider discovery/configuration details - handle configured provider sources differently so config- and env-backed providers are explained in the UI while auth-backed providers can be disconnected safely ## Validation - npm run typecheck --workspace @codenomad/ui - npm run build --workspace @codenomad/ui
## Summary - Add an allowlisted server API for editing global config files, starting with OpenCode global config. - Add a Config Files settings section using the existing Monaco editor with save, reload, dirty-state handling, and responsive layout. - Improve compact settings navigation with a full-width section selector, settings icon, and close action in the compact toolbar. ## Validation - npm run typecheck in packages/server - npm run typecheck in packages/ui - npm run build in packages/ui ## Notes - Existing Vite warnings about virtua JSX import source and large chunks remain unrelated.
Reserve space for the absolute homepage controls on narrow screens so the language selector no longer overlaps the CodeNomad logo. Apply the existing actions-column height constraint to the recent folder panel across viewport sizes so mobile lists scroll instead of expanding beyond the browse/actions section. Validated with npm run typecheck --workspace @codenomad/ui.
## Summary
Add comprehensive architecture and SDK navigation skill to help
contributors navigate the codebase without missing related code.
## What's Included
- **Architecture Overview** — 6 functional areas (UserInterface,
ServerBackend, DesktopClient, SpeechAndAudio, BuildAndPackaging,
CloudflareDeployment), package map, and key entry points
- **UI Conventions** — SolidJS patterns, i18n system (7 locales),
signal-based stores, component styling
- **Server Conventions** — Fastify route patterns, API types,
configuration, testing approach
- **Desktop Conventions** — Electron + Tauri parity rules, native API
abstractions
- **SDK API Reference** — All 10 OpenCode SDK V2 categories used by
CodeNomad with signatures and wrapper locations
- **SDK Critical Behaviors** — Schema gotchas (assistant part metadata,
ignored flag asymmetry), decision matrix, race conditions
- **SDK Integration Patterns** — Client lifecycle, worktree routing,
error handling, optimistic updates
- **Feature Traces** — 5 end-to-end flows with decision branches:
permissions, sessions, speech, background processes, git clone
- **Anti-Patterns** — Common mistakes with file references to correct
implementations
- **Implementation Checklist** — Actionable steps before submitting
changes
## Design Decisions
- All navigation guidance uses standard grep/file search tools (no RPG
MCP server required)
- Split into 8 reference files to stay under 300 lines each
- File references included for every anti-pattern and convention
- Decision branches in feature traces (not just linear flows)
- Weighted quick start by contribution frequency
## Files Added
`
.opencode/skills/codenomad-architecture-guide/
├── SKILL.md
└── references/
├── architecture-overview.md
├── ui-conventions.md
├── server-conventions.md
├── desktop-conventions.md
├── sdk-api-reference.md
├── sdk-critical-behaviors.md
├── sdk-integration-patterns.md
└── feature-traces.md
`
## Summary - render Markdown horizontal rules instead of hiding them in message content - keep the existing Markdown parser behavior and style the generated hr with the shared border token Solves #491 ## Validation - npm run typecheck --workspace @codenomad/ui - npm run build:linux --workspace @neuralnomads/codenomad-electron-app ## Test release artifact Built locally for Linux; artifacts are ignored and not included in this PR: - packages/electron-app/release/CodeNomad-Electron-linux-x64-0.16.0.zip - packages/electron-app/release/CodeNomad-Electron-linux-x86_64-0.16.0.AppImage Co-authored-by: Shantur Rathore <i@shantur.com> Co-authored-by: Pascal André <pascalandr@gmail.com>
## Summary - this fixes a bug where no plugin are displayed in the UI - normalize OpenCode plugin metadata through a dedicated helper instead of assuming every entry is a string - support tuple-form plugin entries by displaying the tuple specifier and preserving existing file:// normalization - add focused regression coverage for string, tuple, and invalid plugin entry shapes ## Validation - npm run typecheck --workspace @codenomad/ui - node --test packages/ui/src/lib/hooks/use-instance-metadata.test.ts - npm run build --workspace @codenomad/ui
## Summary - Adds a two-step deny flow for permission requests so users can provide optional feedback. - Passes reject feedback through `sendPermissionResponse` to `client.permission.reply` as `message`. - Hardens the flow by ignoring permission shortcuts while text inputs are focused and capping feedback length. ## Validation - `npm run typecheck --workspace @codenomad/ui` - `npm run build:ui` - `npm run build:linux --workspace @neuralnomads/codenomad-electron-app` ## Showcase <img width="1709" height="1118" alt="image" src="https://github.com/user-attachments/assets/9f516100-7c3f-4c08-95b2-236b5168394e" /> Related to #496 --------- Co-authored-by: Shantur Rathore <i@shantur.com> Co-authored-by: Pascal André <pascalandr@gmail.com>
## Summary - make YOLO/permission auto-accept resolve by session family root so master and subagent sessions share the same state - keep fork/revert sessions as their own family root - keep existing local YOLO persistence behavior; no server-backed persistence, migration, global setting, or confirmation dialog - re-drain queued child permissions when session metadata arrives so permissions that arrived before parent metadata can be auto-accepted Solves #495 ## Validation - npm run typecheck --workspace @codenomad/ui - npx tsx --test packages/ui/src/stores/permission-auto-accept.test.ts - git diff --check ## Build Artifact - Not generated in this update --------- Co-authored-by: Pascal André <pascalandr@gmail.com>
## Summary - Add missing Hebrew translation keys for Speech navigation and deleted git changes. - Fix Hebrew placeholder coverage for singular count strings and apply-patch file counts. - Polish stale Hebrew wording in notifications and tool call labels. ## Verification - Hebrew catalog parity check: `en=1027 he=1027 missing=0 extra=0 placeholderMismatch=0` - `git diff --check -- packages/ui/src/lib/i18n/messages/he` - `npm run typecheck --workspace @codenomad/ui` fails on existing unrelated issues: missing `virtua/solid`, missing `@tauri-apps/plugin-dialog`, and implicit `any` parameters in `virtual-follow-list.tsx`. Co-authored-by: Pascal André <pascalandr@gmail.com>
#481) ## Summary Fixes #468 and #470. The quick-start examples crashed on first run without a password, and the browser self-signed certificate warning was not documented anywhere a new user would see it. ## Changes - Add `--password` to all npx quick-start examples (main README + server README) - Document the three ways to configure auth: `--password`, env var, `auth.json` - Show `auth.json` schema so users understand the expected format - Add browser warning note to self-signed certificates section with step-by-step instructions for Chrome/Brave and Firefox - Mention `--https=false --http=true` as an alternative for local-only use ## Validation - Reviewed rendered markdown structure - Verified auth.json schema matches AuthFile interface in auth-store.ts
…#284) ## Summary - Display only environment variable names in instance info panel (hide values) - Display only environment variable names in logs view (hide values) - Change environment variable value inputs to password type in settings editor ## Motivation Environment variable values (which may contain sensitive data like API keys, tokens, or secrets) were displayed in plain text across multiple UI surfaces. This change: 1. **Reduces visual exposure** — instance info and logs view now show only variable names 2. **Masks input fields** — the settings editor uses `type="password"` for value inputs, preventing shoulder-surfing and accidental exposure in screenshots or screen recordings --------- Co-authored-by: Pascal André <pascalandr@gmail.com>
# PR: Enhance UI with Toast Notification History & Server Logs Improvements ## 中文摘要 (Chinese Summary) ### 功能概述 本 PR 包含兩個 UI 增強功能:**通知歷史面板** 和 **伺服器日誌改進**。 ### 功能一:通知歷史面板 (Toast Notification History) - 新增 `ToastHistoryPanel` 組件,顯示所有 Toast 通知的歷史記錄 - 支援按類型(info/success/warning/error)篩選 - 支援時間分組(今日/昨日/更早) - 支援清除全部、標記已讀、刪除單項 - 最多保留 50 筆歷史記錄 ### 功能二:伺服器日誌改進 (Server Logs Enhancements) - 新增清除日誌按鈕(垃圾桶圖標) - 新增返回對話按鈕(箭頭圖標,位於日誌工具列) - 新增浮動向上/向下滾動按鈕(圓形小球,與對話介面一致) - 滾動按鈕根據位置自動顯示/隱藏 - 滾動按鈕狀態會隨日誌變化自動同步 --- ## English Summary ### Overview This PR introduces two UI enhancements: **Toast Notification History Panel** and **Server Logs Improvements**. ### Feature 1: Toast Notification History Panel - New `ToastHistoryPanel` component displays all toast notification history - Filter by variant type (info/success/warning/error) - Time grouping (Today/Yesterday/Earlier) - Clear all, mark as read, delete individual items - Maximum 50 history records retained ### Feature 2: Server Logs Enhancements - Clear logs button with Trash2 icon - Back to conversation button with ArrowLeft icon (in logs toolbar) - Floating scroll-to-top/scroll-to-bottom buttons (circular, consistent with message section) - Auto show/hide based on scroll position - Scroll button state syncs automatically with log changes --------- Co-authored-by: Pascal André <pascalandr@gmail.com>
## Summary - Resolve the plugin fetch/SSE base URL from actual listener bindings instead of always publishing 127.0.0.1. - Preserve loopback plugin loading for default local, localhost, wildcard, and mixed HTTP/HTTPS listener setups. - Make the git clone destination test portable so server tests run with zero skips. ## Validation - npm run typecheck --workspace @neuralnomads/codenomad - node --import tsx --test packages/server/src/server/__tests__/listener-base-url.test.ts packages/server/src/server/__tests__/network-addresses.test.ts packages/server/src/workspaces/__tests__/git-clone.test.ts — 15 pass / 0 fail / 0 skipped - shopt -s globstar && node --import tsx --test packages/server/src/**/*.test.ts — 59 pass / 0 fail / 0 skipped ## Notes - Nomad task/evidence artifacts intentionally excluded from the commit per maintainer request.
## Summary - Upgrade `@opencode-ai/sdk` to `1.15.13` and adapt UI types for the current session/diff API surface. - Add a session metadata store helper that safely updates OpenCode session metadata via read-merge-full-replace while preserving non-CodeNomad metadata. - Migrate CodeNomad worktree assignments from `.codenomad/worktreeMap.json` into `metadata.codenomad.worktreeSlug`, with legacy fallback, stale-entry pruning, and server-side deletion of the legacy map once empty. - Add `.codenomad/background_processes/` to CodeNomad-managed `.git/info/exclude` entries. ## Details - New sessions and worktree reassignment now persist explicit session worktree assignments in OpenCode session metadata under: `metadata.codenomad.worktreeSlug` - Worktree resolution now prefers session metadata, then falls back to legacy `parentSessionWorktreeSlug`, then `root`. - Legacy migration runs after session/map loading; after the full session list is known, missing legacy session IDs are treated as stale and pruned. - The UI no longer uses `defaultWorktreeSlug`; the fallback is `root`. - `writeWorktreeMap` deletes `.codenomad/worktreeMap.json` server-side when no legacy parent-session mappings remain. ## Validation - `npm run typecheck --workspace @codenomad/ui` - `npm run typecheck --workspace @neuralnomads/codenomad`
…e scoping (#511) # Session Pagination & Search Enhancement ## Changes ### Progressive Session Loading - `fetchSessions()` now accepts `{ limit, search }` options - Added pagination state: `sessionFetchLimit`, `sessionHasMore` (50-session pages) - Scroll-to-bottom sentinel triggers `loadMoreSessions()` via IntersectionObserver - Hydration loads initial 50 sessions; subsequent scrolls fetch 100, 150, etc. ### Server-Side Search - Added `searchSessions()` using `session.list({ search, limit: 50, directory })` - Merges results into store (preserves active session, no replacement) - Added `"sessionList.loading.more"` i18n key (7 locales) ### Hybrid Search Performance - Client-side filtering runs first — instant results for loaded sessions - Server search only fires when no client matches exist - Debounce reduced from 300ms → 150ms for server fallback ### Workspace Scoping - All `session.list()` calls pass `directory: instance.folder` - Prevents cross-workspace session pollution ## Files - `packages/ui/src/stores/session-state.ts` - `packages/ui/src/stores/session-api.ts` - `packages/ui/src/stores/instances.ts` - `packages/ui/src/stores/sessions.ts` - `packages/ui/src/components/session-list.tsx` - `packages/ui/src/lib/i18n/messages/*/session.ts` --------- Co-authored-by: Shantur Rathore <i@shantur.com>
## Summary - add a release-published workflow that prepares and submits Winget manifest updates automatically - poll the GitHub Release API for the stable Windows Tauri asset and compute its SHA-256 before submission - document the maintainer secret and repository variables needed for the Winget automation flow ## Validation - `node --check "scripts/winget/resolve-release-asset.cjs"` - `node "scripts/winget/resolve-release-asset.cjs" --help` - dry-run resolver against the published `v0.16.0` release asset ## Notes - skips draft and prerelease GitHub releases - uses the maintainer fork submission flow for `microsoft/winget-pkgs` - live PR submission still depends on configuring `WINGET_GITHUB_TOKEN` - Fixes #462
## Summary This fixes #518 by moving CodeNomad worktree execution from directory-header routing to OpenCode experimental workspace routing. OpenCode changed existing-session routing so session routes can prefer the session's stored directory over `x-opencode-directory`. That made the old CodeNomad worktree proxy model unreliable for sessions that should execute in a worktree. This PR switches CodeNomad to resolve an OpenCode workspace ID for each CodeNomad worktree and pass that workspace ID on worktree-scoped OpenCode calls. ## What changed - Start OpenCode with `OPENCODE_EXPERIMENTAL_WORKSPACES=true`. - Change the OpenCode server base URL from `/workspaces/:id/worktrees/root/instance` to `/workspaces/:id/instance`. - Add a root OpenCode client helper in `packages/ui/src/stores/opencode-client.ts`. - Add OpenCode workspace sync/cache helpers in `packages/ui/src/stores/opencode-workspaces.ts`. - Sync OpenCode workspaces after CodeNomad worktree hydration and after worktree create/delete flows. - Map CodeNomad worktree slugs/directories to OpenCode `workspace.id` values discovered by `experimental.workspace.syncList` and `experimental.workspace.list`. - Replace all OpenCode worktree clients with the root client plus explicit `workspace` payloads where the active session/worktree requires it. - Route session, permission/question, file browser reads, SDK git status, and prompt/action calls through root OpenCode client + workspace ID. - Keep CodeNomad local git worktree server APIs intact; those still need filesystem directories for local git operations. ## Review fix - Fixed right-panel file saves so they no longer write to the root workspace after reading from a selected worktree. - The existing CodeNomad file-content API now accepts an optional `worktree` query parameter. - Right-panel saves pass `worktreeSlugForViewer()`, and the server resolves that slug to the same worktree directory used by local git worktree APIs before writing. - Root saves continue to use the original root workspace path. ## Removed old routing - Removed `/workspaces/:id/worktrees/:slug/instance` OpenCode proxy routes. - Removed directory override proxy support using `/__dir/<encoded>`. - Removed proxy injection of `x-opencode-directory`. - Removed the remaining background-process completion prompt `x-opencode-directory` header. - Removed `getOrCreateWorktreeClient`, `getOrCreateWorktreeClientWithDirectoryOverride`, and worktree proxy path helpers from the UI worktree store. - Simplified `sdkManager.createClient` because clients are no longer keyed by worktree slug. ## Why this fixes #518 Worktree sessions can now stay visible under the root project session listing while worktree execution is selected through OpenCode's workspace routing model. CodeNomad no longer depends on `x-opencode-directory` to override existing session directories, so sessions should not disappear from the root-directory list or execute in the wrong directory because of stale session directory fallback behavior. Fixes #518 ## Validation - `npm run typecheck --workspace @codenomad/ui` - `npm run typecheck --workspace @neuralnomads/codenomad` - `git diff --check` ## Notes Some touched files are already oversized and were not refactored as part of this migration: `packages/server/src/server/http-server.ts`, `packages/ui/src/stores/instances.ts`, `packages/ui/src/stores/session-api.ts`, `packages/ui/src/stores/session-state.ts`, `packages/ui/src/components/instance/shell/right-panel/RightPanel.tsx`, `packages/ui/src/stores/session-events.ts`, and `packages/server/src/background-processes/manager.ts`.
## Summary - Adds editable workspace display names for recent folders. - Shows the saved workspace name in the recent folder list and instance tab, including the launching workspace state. - Preserves workspace names when recent folders are relaunched and keeps basename fallback for unnamed folders. Fixes #510 ## Validation - npm run typecheck --workspace @codenomad/ui - npm run typecheck --workspace @neuralnomads/codenomad
Added comprehensive German (de) and Nepali (ne) translations to the CodeNomad UI. Key Changes: New Localization Files: Created 17 new message part files for each locale in packages/ui/src/lib/i18n/messages/de/ and packages/ui/src/lib/i18n/messages/ne/. These cover all application areas, including settings, commands, session management, and the loading screen. I18n Registration: Updated the core i18n configuration to include the new locales, enabling dynamic loading of the translation bundles. UI Integration: Added "Deutsch" and "नेपाली" to the language selection picker on the home screen, allowing users to switch to these languages. Translation Quality: Provided high-quality translations that maintain the humorous and technical tone of the original English strings. The Nepali version uses the Devanagari script and includes technical terms in parentheses where helpful for clarity. Verification: Verified that the UI build process completes successfully with the new files. Confirmed that all translation keys from the English source are accounted for in both new languages. Conducted a code review to ensure compliance with project i18n patterns. --------- Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
## Summary - Stabilize virtualized message autoscroll by keeping DOM/Virtua orchestration in `VirtualFollowList` and moving pure follow/hold behavior into a colocated tested module. - Restore per-session scroll positions using Virtua metrics and anchor snapshots while preventing hidden/inactive panes from overwriting good snapshots. - Gate streaming magnetization on active streaming, hold state, and the bottom-of-viewport item so long assistant replies can still rejoin near their tail without using stale top-of-viewport position. ## Supersedes / fixes - supersedes #375. - supersedes #356. - fixes #305. ## Validation - `node --test packages/ui/src/components/virtual-follow-behavior.test.ts` - `npm run typecheck --workspace @codenomad/ui` - `npm run build --workspace @codenomad/tauri-app` - Many manual release executable testing.
Fixes #297 ## Summary - show total assistant response duration next to the existing message timestamp using only explicit OpenCode message timing - show reasoning duration on reasoning cards only when OpenCode provides explicit part timing ## Why This revision keeps the UI scoped to explicit server-side timing data that OpenCode already provides, which matches the maintainer feedback on this PR. ## Validation - node --experimental-strip-types --test "packages/ui/src/lib/message-timing.test.ts" - npm run build --workspace @codenomad/ui
## Summary - upgrade the UI OpenCode SDK usage for the 1.16 v2 session list/response shapes - migrate session list/search handling to v2 while preserving unsupported legacy session actions - support mixed legacy/v2 permission and question queues, events, hydration, and reply routing during the 1.16 transition ## Validation - npm run typecheck --workspace packages/ui - npx tsx --test "packages/ui/src/types/permission.test.ts" "packages/ui/src/stores/message-v2/instance-store.test.ts"
Fixes #299 ## Summary - show the active session title in the instance header, just after the menu switch. - keep the title visible whenever the left session drawer is not pinned, using a quiet two-line header treatment without active-item highlighting. - when the unpinned drawer is open as a floating overlay, keep the title in the same left header slot so the drawer covers it instead of pushing toolbar controls around. - disable the feature in mobile view ## Validation - `git diff --check` - `npm run typecheck --workspace @codenomad/ui` - `npm run build --workspace @codenomad/ui` - visually validated in the rebuilt desktop app raw executable
## Summary - Collapse intact placeholder-backed long pasted text blocks by default in user message history for readability. - Keep pasted content fully visible to the model; this is a display-only history treatment. - Persist pasted-text collapse metadata across optimistic message replacement and app reloads. - Fall back to normal plain-text history rendering when the placeholder-backed pasted structure has been edited or is no longer intact before send. Fixes #266 ## Behavior When a user submits a prompt containing an intact long pasted block from the existing pasted-text placeholder flow, the full pasted text is still sent to the model unchanged, but the chat history renders that pasted section as a collapsed expandable block. This applies to the existing placeholder-backed long-paste flow only. If the pasted placeholder structure is broken before submission, the message renders in history as normal plain text with no collapse metadata. ## Verification - `npx tsx --test "packages/ui/src/components/prompt-input/submitPrompt.test.ts" "packages/ui/src/lib/prompt-display-metadata.test.ts" "packages/ui/src/stores/message-prompt-display.test.ts"` - `npm run typecheck --workspace @codenomad/ui` - `npm run build --workspace @codenomad/ui` - `npm run build --workspace @codenomad/tauri-app` ## Local desktop verification - Built executable: `packages/tauri-app/target/release/codenomad-tauri.exe` - Built installer: `packages/tauri-app/target/release/bundle/nsis/CodeNomad_0.15.0_x64-setup.exe` - Launched the built Tauri executable locally and confirmed startup succeeded. <img width="487" height="129" alt="image" src="https://github.com/user-attachments/assets/6c3d670c-b049-4fa7-bc8b-c69d0fb3ca25" />
## Summary - rescope the UI portion of #385 to the remaining main-session selector issue from #384 - keep main-session primary selectors limited to selectable primary agents - preserve child/subagent behavior by keeping the current hidden agent available for steering - add focused tests for selector eligibility behavior This intentionally excludes the OMO/config-directory merge and plugin retry scope from #385, since that part was determined to belong outside CodeNomad. Credit to @jollyxenon for the original #385 investigation and UI direction. ## Validation - ode --test packages/ui/src/types/session.test.ts ✅ - pm run typecheck --workspace @codenomad/ui⚠️ fails on existing SDK/type drift outside this diff Fixes #384 Based on #385
## Summary - store per-session message load failures so automatic session effects stop retrying after server errors - show the server-provided error in the message stream with a reload action that forces a fresh request - add localized labels for the load-error title and reload button ## Validation - npm run typecheck --workspace @codenomad/ui - npm run build --workspace @codenomad/ui
…#519) ## Problem When the client receives a ping from the server, it responds with a pong via HTTP POST. On unstable networks (mobile, WiFi with poor signal, network switches), this POST can fail in multiple ways: - **Hung requests**: `fetch()` never rejects, blocking retries indefinitely - **Network disconnection**: `Failed to fetch` - **Brief disconnections**: transient network errors Previously, a single missed pong would cause the server to close the SSE connection after 45s, leaving message responses stuck in queue until the next message triggered a reconnection. ## Solution Three improvements to make the pong POST resilient: ### 1. Request timeout (10s) Each pong POST is now bounded with a 10s `AbortSignal` timeout. Hung requests fail fast instead of blocking indefinitely, allowing retries to start before the server's stale connection sweep. ### 2. Selective retry with `isRetryableError()` Only retries transient failures where recovery is possible: - `AbortError` / `TimeoutError` (hung or timed-out requests) - `Failed to fetch` (network disconnected) - `NetworkError` (browser network errors) Non-retryable errors like `404 Client connection not found` (permanently closed connection) fail immediately instead of wasting retry attempts. ### 3. Exponential backoff (3 attempts, 100ms → 2000ms) Handles burst failures gracefully without hammering the server. ## Changes - **`packages/ui/src/lib/retry-utils.ts`** (new): Reusable retry utility with `timeoutMs` and `shouldRetry` predicate support - **`packages/ui/src/lib/server-events.ts`**: Updated pong handler to use bounded timeout + selective retry ## Verification - Build passes: `npm run build:ui` ✅ - Manually verified in production logs: retries now visible as `Pong failed after retries` instead of single immediate failure - SSE monitor log at `~/.codenomad/logs/sse-monitor.log` shows `PONG_OK` / `PONG_FAIL` / `STALE` events for ongoing monitoring
## Summary
This PR removes tracked NomadWorks/OpenCode/task-tracking artifacts that
were accidentally committed to the repository and now interfere with
local NomadWorks usage for other contributors.
NomadWorks generates local workflow state such as `tasks/`, SCR
registries, and codemaps as needed. Keeping those generated artifacts
tracked in the shared repository creates stale state, false active
tasks, and confusing/broken NomadWorks behavior for other users who
initialize or run the workflow locally.
## Problematic commits / artifacts
The cleanup addresses artifacts introduced by the following
Shantur-authored commits:
- `e708c565ef6221dcded8a3da81c73e4755824f2d`
- `docs(wake-lock): record wake-lock change workflow`
- Introduced NomadWorks wake-lock SCR/task artifacts:
- `docs/scrs/SCR-2026-04-21-001-wake-lock-system-sleep-only.md`
- `tasks/current.md`
-
`tasks/discussions/DISCUSSION-001-wake-lock-behavior-change-for-macos-sleep-vs-screen-lock.md`
- `tasks/todo/055-wake-lock-investigation.md`
- `tasks/todo/056-wake-lock-behavior-change.md`
- `tasks/todo/057-implement-system-sleep-only-wake-lock.md`
- `a337c19b63198f076836644c9a9a4d29e8a47c18`
- `Init nomadworks`
- Introduced tracked NomadWorks/OpenCode initialization artifacts:
- `.nomadworks/**`
- root `codemap.yml`
- `docs/scrs/current.md`
- `docs/scrs/done.md`
- `tasks/done.md`
- `.opencode/opencode.jsonc`
- `.opencode/package-lock.json`
- The removed `.opencode/opencode.jsonc` only contained the OpenCode
schema plus a commented NomadWorks plugin entry:
- `"$schema": "https://opencode.ai/config.json"`
- `// "@neuralnomads/nomadworks@0.1.0-rc.10"`
- The removed `.opencode/package-lock.json` was an orphan lockfile with
no tracked `.opencode/package.json`. It pinned old OpenCode
plugin/runtime packages, notably:
- `@opencode-ai/plugin@1.14.24`
- `@opencode-ai/sdk@1.14.24`
- Those pinned OpenCode versions are stale for the current
CodeNomad/OpenCode integration, so keeping this lockfile is misleading
and can imply an unsupported local plugin setup.
- `b06b8104a519e7c3a798651c1980f3fc59284786`
- `Add task specifications for Phase 5 advanced input features`
- Introduced tracked task-planning artifacts including:
- `tasks/todo/015-keyboard-shortcuts.md`
- `tasks/todo/020-command-palette.md`
- `tasks/todo/021-file-attachments.md`
- `tasks/todo/022-long-paste-handling.md`
- `tasks/todo/023-symbol-attachments.md`
- `tasks/todo/024-agent-attachments.md`
- `tasks/todo/025-image-clipboard-support.md`
- `0a3ac6cbf24b4eaa19bba972ff691f7a6ff12275`
- `docs: add theme overhaul task series`
- Introduced tracked task-planning artifacts `tasks/todo/041-*` through
`tasks/todo/045-*`.
- `cb56eed4f94f6a656f78965386bb4ac5e3ab0d6f`
- `docs: add tailwind refactor follow-up tasks`
- Introduced tracked task-planning artifacts `tasks/todo/046-*` through
`tasks/todo/048-*`.
- `7267baf23d34e71e32e193540e08d718167415ac`
- `docs: queue remaining style cleanup tasks`
- Introduced tracked task-planning artifacts `tasks/todo/049-*` through
`tasks/todo/054-*`.
Some older mixed product commits also added `tasks/done/*` or
`PROGRESS.md` while introducing real product code. Those commits should
not be fully reverted because that would remove product functionality,
so this PR removes the stale tracking files directly in a final cleanup
commit.
## Changes
- Reverts the previous partial NomadWorks cleanup so the full original
faulty state can be reverted cleanly.
- Fully reverts the original `Init nomadworks` commit.
- Fully reverts the wake-lock NomadWorks workflow artifact commit.
- Removes remaining stale historical progress/task-tracking files that
are not used by CodeNomad runtime, builds, or GitHub workflows.
- Removes stale `.opencode` root config/lock artifacts introduced by the
NomadWorks initialization because the config only references a commented
NomadWorks plugin and the lockfile pins unsupported old OpenCode
packages without a matching package manifest.
## Validation
- `git status --short` is clean.
- `git diff --check upstream/dev..HEAD` passes with no output.
- Final diff only removes tracked NomadWorks/OpenCode/task/progress
artifacts; no runtime source files are changed.
## Summary - remove the obsolete session.diff fetch/store/SSE pipeline from packages/ui - delete the right drawer Session Changes tab and Status accordion section - map stored removed "changes" tab values to Git Changes and remove unused i18n keys ## Validation - npm run typecheck --workspace @codenomad/ui - git diff --check
## Summary
- switch the Tauri desktop runtime from the browser `EventSource` path
to a native Rust desktop event transport while leaving browser and
Electron unchanged
- restore SSE heartbeat parity by parsing named `event:` frames and
replying to `codenomad.client.ping` with an authenticated
`/api/client-connections/pong`
- add a Tauri-only settings toggle that lets the current device fall
back to the browser `EventSource` transport without leaking that choice
through shared config
- remove the temporary benchmark harness from the shipped code now that
the transport behavior has been validated
## Benchmark
The temporary in-app benchmark harness used during validation has been
removed from the final code, but the measured results are retained here
for review context.
Real Tauri/WebView2 benchmark on Windows using the dedicated session:
- workspace: `D:\CodeNomad`
- session: `ses_21feb15b3ffeLz3uRModK4KKnG`
Short command:
- `node -e "for (let i = 1; i <= 400; i += 1) console.log('line ' + i)"`
Results:
- browser `EventSource` forced in Tauri:
- timed out after `131479.7ms`
- `sawWorking=false`
- `reachedIdle=false`
- `batchesReceived=84`
- `eventsReceived=84`
- `maxBatchSize=1`
- Rust-native transport:
- completed in `1437.4ms`
- `sawWorking=true`
- `reachedIdle=true`
- `batchesReceived=4`
- `eventsReceived=45`
- `maxBatchSize=27`
Long heartbeat / stale-timeout validation:
- command: `powershell -NoProfile -Command Start-Sleep -Seconds 70`
- Rust-native transport:
- completed in `71689.5ms`
- `sawWorking=true`
- `reachedIdle=true`
- `batchesReceived=13`
- `eventsReceived=72`
- `maxBatchSize=25`
Confirmed separately afterward: the native transport also behaves better
on Linux.
## Validation
- `cargo test named_ping_event_is_routed_to_ping_channel`
- `cargo test session_cookie_is_attached_to_requests`
- `cargo test --no-run`
- `npx tsc --noEmit --pretty -p packages/ui/tsconfig.json`
- `npx tsc --noEmit --pretty -p packages/server/tsconfig.json`
- manual Tauri/WebView2 benchmark on Windows
- manual confirmation on Linux after the benchmark phase
## Notes
- this remains a Tauri-only transport; browser and Electron stay on the
browser `EventSource` path
- the Tauri fallback toggle is now genuinely device-local and restarts
the local event stream immediately when changed
- the long run validates heartbeat / stale-timeout robustness, not
headline perf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thanks for contributions
Highlights
What’s Improved
Fixes
Docs
Contributors
Full Changelog: v0.16.0...v0.17.0
Merged Pull Requests
@shantur
@pascalandr
@OfflinePing
@omercnet
@VooDisss
@JDis03
@bluelovers
@aayurt
@MusiCode1
@jollyxenon