Skip to content

sync: merge upstream v1.0.145 into integration#115

Closed
shuv1337 wants to merge 71 commits intointegrationfrom
opencode/issue113-20251211062235
Closed

sync: merge upstream v1.0.145 into integration#115
shuv1337 wants to merge 71 commits intointegrationfrom
opencode/issue113-20251211062235

Conversation

@shuv1337
Copy link
Collaborator

@shuv1337 shuv1337 commented Dec 11, 2025

Summary

  • Merge upstream v1.0.145 changes from sst/opencode into the shuvcode fork
  • Resolve merge conflicts in 10 files (preserving fork-specific workflows and accepting upstream UI improvements)
  • Fix type errors introduced by the merge (font/theme picker state management, Command type, icon names)

Conflicts Resolved

File Resolution
.github/workflows/opencode.yml Kept ours (fork-specific workflow)
.github/workflows/publish.yml Deleted (fork doesn't use upstream's publish)
packages/desktop/src/components/prompt-input.tsx Accepted upstream (new model dialog UI)
packages/desktop/src/context/global-sync.tsx Accepted upstream + added Command type
packages/desktop/src/context/layout.tsx Accepted upstream (new dialog system)
packages/desktop/src/pages/home.tsx Accepted upstream (projects property)
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx Accepted upstream (text styling)
packages/opencode/src/session/prompt.ts Accepted upstream (improved error handling)
packages/ui/src/components/icon.tsx Accepted upstream (new icons)
packages/ui/src/components/select-dialog.tsx Accepted upstream (new actions prop)

Additional Fixes

  • Updated font-picker.tsx and theme-picker.tsx to use local state (createSignal) instead of removed layout context
  • Added Command type and command property to State in global-sync.tsx
  • Fixed useKittyKeyboard to use object type instead of boolean in TUI app
  • Replaced removed icon names with available alternatives

Closes #113

Summary by CodeRabbit

  • New Features

    • Added provider selection and connection UI for seamless model switching
    • New List and Tag components for improved UI interaction
    • Project colorization system in desktop app
    • Permission feedback options ("accept always") for bash commands
    • Helicone provider integration documentation
  • Refactor

    • Redesigned prompt input component with enhanced file attachment and model selection
    • Updated provider and project data management architecture
    • Improved theme and font picker state handling
  • Bug Fixes

    • Fixed icon discovery feature flag behavior
  • Documentation

    • Clarified permission scope and pipeline command handling
    • Updated product description across platforms
  • Style

    • Enhanced dialog sizing and spacing
    • Refined button and UI component styling

✏️ Tip: You can customize this high-level summary in your review settings.

rekram1-node and others added 30 commits December 10, 2025 14:48
- Tauri app now automatically finds an available port instead of defaulting to 4096
- Icon discovery feature is now enabled by default in the Tauri app
- Prevents port conflicts when multiple OpenCode instances are running
Frontend now receives the server port via window.__OPENCODE__.port,
allowing it to connect when using a random free port instead of hardcoded 4096
thdxr and others added 24 commits December 10, 2025 22:36
- Add og:image and twitter:image meta tags for better social sharing
- Generate dynamic social card URLs with session title, models, and version
- Include description meta tag for search engines
- Add og:image and twitter:image meta tags to entry-server
- Provide fallback social card image for pages without specific social cards
Resolved conflicts:
- .github/workflows/opencode.yml: Keep ours (fork-specific workflow)
- .github/workflows/publish.yml: Deleted (fork-specific publishing)
- packages/desktop/src/components/prompt-input.tsx: Accept upstream (new model dialog UI)
- packages/desktop/src/context/global-sync.tsx: Accept upstream (ProviderListResponse type)
- packages/desktop/src/context/layout.tsx: Accept upstream (new dialog system)
- packages/desktop/src/pages/home.tsx: Accept upstream (projects property name)
- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx: Accept upstream (text styling)
- packages/opencode/src/session/prompt.ts: Accept upstream (better error handling)
- packages/ui/src/components/icon.tsx: Accept upstream (new icons)
- packages/ui/src/components/select-dialog.tsx: Accept upstream (actions prop)
- bun.lock: Regenerated
- Update font-picker.tsx to use local state instead of removed layout.font
- Update theme-picker.tsx to use local state instead of removed layout.theme
- Remove onHighlight prop from SelectDialog (no longer supported)
- Replace 'type' icon with 'code-lines' and 'droplet' with 'dot-grid'
- Add Command type and command property to State in global-sync.tsx
- Fix useKittyKeyboard to use object type instead of boolean
@coderabbitai
Copy link

coderabbitai bot commented Dec 11, 2025

Walkthrough

Upstream sync to v1.0.145 introducing provider-aware UI components, refactoring desktop TUI session interface, renaming global data structures (projects→project, adding provider.list), expanding multi-platform availability messaging, version bumping across packages, and API enhancements including a global disposal endpoint.

Changes

Cohort / File(s) Summary
Version Bumps
.github/last-synced-tag, packages/*/package.json (15 files), packages/extensions/zed/extension.toml
Bump package versions from 1.0.143 to 1.0.145 across console, desktop, enterprise, function, mail, opencode, plugin, sdk/js, slack, tauri, ui, util, web, and zed extension
Provider Infrastructure & Data Restructuring
packages/desktop/src/context/global-sync.tsx, packages/desktop/src/context/local.tsx, packages/desktop/src/context/sync.tsx, packages/opencode/src/provider/...
Replace Provider[] with ProviderListResponse; rename globalStore.projects→globalStore.project; add provider.list() API call; add latest flag to LocalModel; introduce cerebras custom loader and fix reasoning content handling for specific model/provider combos
Desktop Provider & Model UI
packages/desktop/src/context/layout.tsx, packages/desktop/src/hooks/use-providers.ts, packages/desktop/src/pages/layout.tsx, packages/desktop/src/pages/home.tsx
Add dialog-based provider/model selection, useProviders hook with popular provider filtering, project colorization system, replace AsciiLogo with Logo, update projects reference and layout styling
Desktop Component Refactoring
packages/desktop/src/components/prompt-input.tsx
Major refactor: remove shell mode and slash command UI; consolidate to SDK-driven prompts with file attachments; replace model selection UI with provider-aware dialog picker; simplify popover/input mode state
Desktop Theme & Font Management
packages/desktop/src/components/theme-picker.tsx, packages/desktop/src/components/font-picker.tsx, packages/desktop/src/app.tsx
Replace layout-derived state with internal signals (currentTheme/currentFont, previewTheme/previewFont); add getDefaultTheme/getDefaultFont helpers; update icon triggers; support window.OPENCODE port from global object
UI Component Library
packages/ui/src/components/list.tsx, packages/ui/src/components/list.css, packages/ui/src/components/tag.tsx, packages/ui/src/components/tag.css, packages/ui/src/components/select-dialog.tsx, packages/ui/src/components/select-dialog.css
Add new List component with filtering/grouping/keyboard nav; add Tag component with size variants; refactor SelectDialog to extend List (remove filter prop); update dialog styling (narrower width, adjusted margins/padding)
UI Icon & Provider Icon Updates
packages/ui/src/components/icon.tsx, packages/ui/src/components/provider-icon.tsx, packages/ui/src/components/button.css, packages/ui/src/components/dialog.tsx, packages/ui/src/components/input.tsx, packages/ui/src/components/input.css
Remove newIcons support; narrow Icon to icons map only; change ProviderIcon prop from name→id; update button icon padding/typography; add dialog ghost close button variant; add hidden prop to Input; add width: 100% to input styling
UI Styling & Theme
packages/ui/src/components/dialog.css, packages/ui/src/styles/theme.css, packages/ui/src/styles/tailwind/index.css, packages/ui/src/styles/index.css
Add --radius-xs and --radius-xl CSS vars; refactor dialog layout (narrower, adjusted padding/margin/border-radius); update CSS imports for list/tag components; remove demo/index files
TUI Session & Prompt Refactoring
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx, packages/opencode/src/session/prompt.ts, packages/opencode/src/cli/cmd/tui/context/directory.ts
Remove search/token display/bash output UI from session; simplify session context API; replace token propagation with error handling for tool execution; use sync.data.path.directory for resolved directory; update terminal title case
API & Server Endpoints
packages/opencode/src/server/server.ts, packages/sdk/openapi.json, packages/opencode/src/session/index.ts
Add POST /global/dispose endpoint and Event.Disposed; extend Path schema with home field; add archived field to Session.time and Project.time; refactor session sharing to use ShareNext without sync overhead
Enterprise & Console Routes
packages/enterprise/src/routes/index.tsx, packages/enterprise/src/routes/share/[shareID].tsx, packages/enterprise/package.json, infra/enterprise.ts, infra/stage.ts
Add simple Hello World index route; add dynamic OG image generation for shares using Base64; add shortDomain constant; update domain construction; add js-base64 dependency; set enterprise baseURL via env var
Documentation & Content
README.md, packages/console/app/src/app.tsx, packages/console/app/src/config.ts, packages/console/app/src/routes/index.tsx, packages/web/src/content/docs/*
Update OpenCode description from "terminal-focused" to "open source, multi-platform"; bump stats (stars 35K→38K, contributors 350→375); expand feature descriptions; add Helicone provider docs; clarify permissions scope and 'ask' option feedback
Configuration & Infrastructure
.opencode/opencode.jsonc, packages/tauri/src-tauri/src/lib.rs, packages/tauri/src-tauri/capabilities/default.json, packages/tauri/src/index.tsx, packages/enterprise/vite.config.ts
Remove MCP config (exa remote, morph local); implement TCP listener for unused port discovery; set OPENCODE_EXPERIMENTAL_ICON_DISCOVERY env var; remove global OPENCODE Window type from tauri; add webview zoom permission; add baseURL to nitro config
Bus & Experimental Flags
packages/opencode/src/bus/index.ts, packages/opencode/src/flag/flag.ts, packages/opencode/src/project/project.ts, packages/opencode/src/project/instance.ts
Consolidate InstanceDisposed event definition; add OPENCODE_EXPERIMENTAL_ICON_DISCOVERY flag; gate icon discovery behind new flag; emit disposal events via GlobalBus
Proxy Route
packages/console/app/src/routes/t/[...path].tsx
Add catch-all proxy handler routing to https://enterprise.opencode.ai/ with support for all HTTP methods
Build & Config Updates
nix/hashes.json, packages/ui/package.json, packages/opencode/src/cli/cmd/auth.ts, packages/opencode/src/cli/cmd/tui/app.tsx, packages/opencode/src/tool/bash.txt
Update nix hash; remove ui build script; add plugin auth handler; update TUI keyboard/title options; make bash tool description required; add tool bash permissions test suite

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • packages/desktop/src/components/prompt-input.tsx — Major refactor removing multiple UI modes; verify SDK integration and file attachment flow
  • packages/desktop/src/context/global-sync.tsx — Data structure rename (projects→project) and provider state shape; confirm reconciliation logic
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx — Significant public API surface removal (tokens, search, bash output); verify no dependent code paths broken
  • packages/opencode/src/session/prompt.ts — Token field removal and tool error handling refactor; confirm error propagation and state consistency
  • packages/ui/src/components/icon.tsx — Removal of newIcons support; verify no legacy icon references remain in codebase
  • packages/sdk/openapi.json — Multiple schema additions (archived, home fields, /global/dispose endpoint); confirm backward compatibility
  • packages/desktop/src/context/layout.tsx — Ephemeral dialog state and colorization system; verify project list ordering and rendering

Possibly related issues

Possibly related PRs

  • sync: merge upstream v1.0.141 #103 — Prior upstream sync affecting same infrastructure files (.github/last-synced-tag, provider/context modules)
  • sync: merge upstream v1.0.133 #87 — Overlapping TUI session and prompt refactoring touching packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
  • Sidebar fix #97 — Concurrent modifications to session TUI route with differing feature coverage (commands vs. UI surface removal)

Poem

🐰 The great upstream hop of v1.0.145,
With providers and projects reborn in their state,
List and Tag dance where dialogs now bloom,
Terminal, desktop, and IDE—no more gloom!
The platform expands on multi-platform wings.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.96% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'sync: merge upstream v1.0.145 into integration' directly and clearly describes the primary change: merging upstream version v1.0.145 into the integration branch.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #113: merges v1.0.145 into integration, resolves all 10 specified file conflicts, fixes type errors (font/theme pickers, Command type, icon names), and completes validation steps.
Out of Scope Changes check ✅ Passed All changes in the PR are directly related to the upstream sync merge and conflict resolution specified in issue #113. No extraneous modifications or unrelated refactoring detected.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch opencode/issue113-20251211062235

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@opencode-agent
Copy link

User coderabbitai[bot] does not have write permissions

github run

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 17

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
packages/console/app/src/routes/index.tsx (1)

145-148: Update platform availability messaging to match changes elsewhere.

This section still says "desktop (coming soon)" but the updated FAQ content at line 670 states "OpenCode is now available as an app for your desktop." Additionally, this mentions "web" but doesn't mention "IDE extension," while the updated content throughout the file (lines 160, 196, 648-649) emphasizes "IDE extension" instead.

Apply this diff to align the messaging:

-            <p data-slot="installation-options">
-              Available in terminal, web, and desktop (coming soon).
-              <br />
-              Extensions for VS Code, Cursor, Windsurf, and more.
-            </p>
+            <p data-slot="installation-options">
+              Available in terminal, desktop app, and web.
+              <br />
+              Extensions for VS Code, Cursor, Windsurf, and more.
+            </p>
packages/opencode/package.json (1)

12-17: Fix misleading and broken script definitions in packages/opencode/package.json.

The scripts section contains several problematic definitions that do not match their intended purpose:

  • Line 12 (random): Placeholder script with multiple echo statements; no functional purpose.
  • Line 14 (lint): Mislabeled—runs bun test --coverage (testing) instead of actual linting checks.
  • Line 15 (format): Uses non-standard bun run --prettier syntax; unclear if prettier is actually executed.
  • Line 16 (docs): Only echoes file paths with find; does not generate documentation.
  • Line 17 (deploy): Basic echo statements and build execution; appears to be a placeholder.

Either replace these with proper implementations or remove them if they are not needed.

packages/opencode/src/session/index.ts (1)

221-234: Add idempotency check before creating a share.

The share() function calls ShareNext.create(id) without verifying if a share already exists for the session. Calling share() multiple times would create duplicate share records on the server, with only the latest URL retained locally, orphaning previous shares.

Consider checking session.share before calling ShareNext.create(), or ensure the API endpoint handles idempotency by returning the existing share when one already exists for that session ID.

packages/opencode/src/server/server.ts (1)

791-798: Schema requires time object even for title-only updates.

The validation schema requires a time object with an optional archived field. This means clients must always send time: {} even when only updating title, which is awkward.

Consider making the entire time object optional:

        validator(
          "json",
          z.object({
            title: z.string().optional(),
-           time: z.object({
+           time: z.object({
              archived: z.number().optional(),
-           }),
+           }).optional(),
          }),
        ),

Then update line 808 to check updates.time?.archived.

packages/sdk/openapi.json (1)

8190-8207: v1 SDK types out of sync with OpenAPI spec — regenerate packages/sdk/js/src/gen/types.gen.ts

The server correctly returns home as a required field (confirmed in packages/opencode/src/server/server.ts line 534). However, the v1 SDK generated types at packages/sdk/js/src/gen/types.gen.ts are missing the home field, while the v2 SDK at packages/sdk/js/src/v2/gen/types.gen.ts has been properly updated to include it.

This creates a type safety gap: the home field will be present in responses from /path, but v1 TypeScript clients won't have it in their type definitions. The v1 SDK types must be regenerated from the updated OpenAPI spec to match the server implementation and v2 SDK.

♻️ Duplicate comments (1)
packages/ui/src/styles/tailwind/index.css (1)

60-60: LGTM - Valid Tailwind CSS v4 syntax (static analysis false positive).

The syntax --radius-xl: 0.625rem; is valid CSS custom property syntax within Tailwind CSS v4's @theme directive. The Biome parser errors are false positives caused by the tool not recognizing Tailwind v4's CSS-first configuration pattern. This addition extends the radius scale consistently with other radius tokens defined in the theme.

🧹 Nitpick comments (24)
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx (1)

855-913: Consider extracting the IIFE to a named component.

The inline IIFE pattern works but reduces readability and testability. Consider extracting this revert message UI to a separate component like RevertedMessageBanner.

-                    <Match when={message.id === revert()?.messageID}>
-                      {(function () {
-                        const command = useCommandDialog()
-                        const [hover, setHover] = createSignal(false)
-                        const dialog = useDialog()
-
-                        const handleUnrevert = async () => {
-                          const confirmed = await DialogConfirm.show(
-                            dialog,
-                            "Confirm Redo",
-                            "Are you sure you want to restore the reverted messages?",
-                          )
-                          if (confirmed) {
-                            command.trigger("session.redo")
-                          }
-                        }
-
-                        return (
-                          <box ... >
-                            ...
-                          </box>
-                        )
-                      })()}
-                    </Match>
+                    <Match when={message.id === revert()?.messageID}>
+                      <RevertedMessageBanner revert={revert()!} keybind={keybind} />
+                    </Match>
packages/console/app/src/routes/index.tsx (1)

160-160: Consider aligning phrasing with other platform descriptions.

For consistency with lines 196 and 648-649, consider rephrasing to match the "available as" pattern used elsewhere:

-              <p>OpenCode is an open source agent that helps you write code in your terminal, IDE, or desktop.</p>
+              <p>OpenCode is an open source agent that helps you write code using a terminal interface, IDE extension, or desktop app.</p>
packages/ui/src/components/input.tsx (1)

10-32: hidden prop semantics and overflow when collapsed

Introducing hidden?: boolean and wiring it into the wrapper style is reasonable, but there are two subtle behavior points worth calling out:

  • Because hidden is now pulled out in splitProps, it will no longer be forwarded as the native hidden attribute to <Kobalte.Input>. If anything relied on <Input hidden /> affecting the actual <input> element, this changes that behavior; if that’s not desired, consider either a different prop name or also forwarding a hidden/data-hidden flag to the inner input.
  • With only height: 0, children can visually overflow the wrapper in some layouts. Adding overflow: "hidden" when hidden is true will make the collapse more robust.

A small tweak to the style would address the overflow case:

-    <Kobalte
-      data-component="input"
-      style={{ height: local.hidden ? 0 : undefined }}
+    <Kobalte
+      data-component="input"
+      style={{
+        height: local.hidden ? 0 : undefined,
+        overflow: local.hidden ? "hidden" : undefined,
+      }}
packages/opencode/src/cli/cmd/auth.ts (2)

17-160: Centralized plugin auth flow looks solid; consider small robustness and DRY tweaks

The helper correctly covers method selection, prompt collection, OAuth (auto/code) and API flows, and returns a clear handled/fallthrough boolean, matching its docstring.

Two minor follow‑ups you might consider:

  • Add a defensive guard in case a misconfigured plugin exposes methods.length === 0, to avoid plugin.auth.methods[0] being undefined.
  • The success branches for OAuth (auto vs code) duplicate the logic that extracts refresh/access/expires vs key and calls Auth.set. Extracting that into a small helper (e.g. savePluginAuthResult(result, provider)) would reduce repetition and keep future changes in one place.

These are non‑blocking and can be deferred.


324-329: Custom provider plugin auth handling is correct; minor duplication opportunity

Checking for a matching plugin again after the “other” provider ID is entered is a nice touch and lets plugins own custom IDs too. You’re calling Plugin.list() twice in the handler now; if this grows, you could optionally cache the result once and reuse it for both lookups, but it’s not critical given expected plugin counts.

packages/web/astro.config.mjs (1)

34-40: Brand title change to “OpenCode” is fine; consider fixing Discord label typo

The updated title: "OpenCode" matches the rest of the branding and is good. While you’re here, you may also want to correct the existing label: "Dscord" to "Discord" for polish.

packages/web/src/content/docs/index.mdx (1)

10-21: Docs wording update is good; optional hyphenation tweak

The broader description (“terminal-based interface, desktop app, or IDE extension”) and terminal‑specific prerequisites read well and match current product scope. For style, you might consider changing “open source AI coding agent” to “open‑source AI coding agent” since it’s used as a compound adjective.

packages/opencode/src/share/share-next.ts (1)

14-16: Centralized URL helper is fine; consider minor reuse / DRY improvements

The new url() helper and updated fetch calls correctly centralize enterprise/base URL resolution and introduce a sensible default (https://opncd.ai). Behaviorally this matches the intent of always having a share host even when config.enterprise is absent.

You might optionally:

  • Cache the resolved URL in url() (or higher up) if Config.get() is relatively expensive or always static.
  • Reuse a single constant or helper for the "https://opncd.ai" fallback (e.g., aligned with shortDomain usage) to avoid drift if the host ever changes.

Not blocking; just a small maintainability win if this URL is reused elsewhere.

Also applies to: 67-76, 133-143, 147-159

packages/enterprise/src/routes/index.tsx (1)

1-3: Component is fine; consider giving the default export a name

This minimal route component works as expected. For better debugging and consistency with typical JSX/Solid conventions, consider naming it, e.g.:

export default function Index() {
  return <div>Hello World</div>
}

Not required, just a clarity/diagnostics improvement.

infra/stage.ts (1)

15-19: shortDomain behavior is correct; consider deduplicating stage logic

shortDomain uses the same stage rules as domain with a different base host, which is correct for the new short hostname.

To avoid future drift if stage handling changes, you might extract a small helper, e.g.:

function makeDomain(base: string) {
  if ($app.stage === "production") return base
  if ($app.stage === "dev") return `dev.${base}`
  return `${$app.stage}.dev.${base}`
}

export const domain = makeDomain("opencode.ai")
export const shortDomain = makeDomain("opncd.ai")

Optional, but keeps all stage-domain mapping logic in one place.

packages/desktop/src/hooks/use-providers.ts (1)

25-30: Nested memo returns accessor functions instead of values.

The returned object contains popular and connected as accessor functions (memos), while all and default are direct values. This inconsistency means consumers must call providers().popular() but can directly use providers().all. Consider destructuring the memo values for a consistent API:

  return createMemo(() => ({
    all: providers().all,
    default: providers().default,
-   popular,
-   connected,
+   popular: popular(),
+   connected: connected(),
  }))
packages/desktop/src/components/theme-picker.tsx (1)

14-14: Unused previewTheme signal.

The previewTheme signal is created and cleared in handlers, but never set to a theme value (only to undefined). With the removal of onHighlight from SelectDialog, the preview functionality appears incomplete or vestigial. Consider removing if preview-on-hover is no longer supported:

-const [previewTheme, setPreviewTheme] = createSignal<Theme | undefined>()

And simplify handleOpenChange:

 function handleOpenChange(open: boolean) {
-  if (!open && previewTheme()) {
-    applyTheme(currentTheme().id)
-    setPreviewTheme(undefined)
-  }
+  // No preview revert needed
 }
packages/ui/src/components/list.css (1)

100-111: Consider avoiding !important for icon color overrides.

The !important declarations on lines 101 and 109 suggest specificity conflicts. If possible, increase specificity through more specific selectors rather than using !important, which can make future style overrides difficult:

-        [data-slot="list-item-extra-icon"] {
-          color: var(--icon-strong-base) !important;
-        }
+        &[data-active="true"] [data-slot="list-item-extra-icon"],
+        &:hover [data-slot="list-item-extra-icon"] {
+          color: var(--icon-strong-base);
+        }
packages/opencode/src/session/prompt.ts (1)

366-370: Catch block may receive non-Error values.

The catch block types executionError as Error | undefined, but JavaScript can throw any value. Consider defensive handling:

       .catch((error) => {
-        executionError = error
+        executionError = error instanceof Error ? error : new Error(String(error))
         log.error("subtask execution failed", { error, agent: task.agent, description: task.description })
         return undefined
       })

This ensures executionError.message on line 396 always works.

packages/desktop/src/components/prompt-input.tsx (1)

323-346: Remove commented-out code.

The commented code blocks (lines 323-327 and 331-346) appear to be leftover from the refactor. Consider removing them to improve code maintainability.

Apply this diff to clean up the commented code:

-    // if (!session.id) {
-    // session.layout.setOpenedTabs(
-    // session.layout.copyTabs("", session.id)
-    // }
-
     const toAbsolutePath = (path: string) => (path.startsWith("/") ? path : sync.absolute(path))
     const attachments = prompt.filter((part) => part.type === "file")
-
-    // const activeFile = local.context.active()
-    // if (activeFile) {
-    //   registerAttachment(
-    //     activeFile.path,
-    //     activeFile.selection,
-    //     activeFile.name ?? formatAttachmentLabel(activeFile.path, activeFile.selection),
-    //   )
-    // }
-
-    // for (const contextFile of local.context.all()) {
-    //   registerAttachment(
-    //     contextFile.path,
-    //     contextFile.selection,
-    //     formatAttachmentLabel(contextFile.path, contextFile.selection),
-    //   )
-    // }
-
+    
     const attachmentParts = attachments.map((attachment) => {
packages/web/src/content/docs/providers.mdx (1)

571-681: Helicone provider section looks consistent; just confirm JSONC/trailing‑comma support

The Helicone docs match the structure and tone of other provider sections, and the examples (baseURL, models, headers, plugin) look coherent.

One thing to double‑check: the config snippets are marked as jsonc and use comments plus trailing commas. That’s fine if opencode.jsonc is parsed as JSONC with trailing‑comma support; if not, you may want to drop the trailing commas in the examples to avoid copy‑paste parse errors.

packages/ui/src/components/select-dialog.css (1)

1-16: Scrollbar hiding inside dialog content: check usability/accessibility impact

The nested [data-slot="dialog-body"] rules fully hide scrollbars (scrollbar-width: none, -ms-overflow-style: none, ::-webkit-scrollbar { display: none; }). That’s visually clean but can make scrollability less discoverable and harder for some users.

If this dialog can overflow significantly, consider at least verifying keyboard scrolling works well and that there’s some visual cue (e.g., fade gradient) indicating more content below.

packages/ui/src/components/provider-icon.tsx (1)

6-8: Renaming prop to id changes its semantics vs DOM id

Using id: IconName and pulling it out via splitProps means this id is now purely the sprite symbol identifier and is not forwarded as the <svg>’s DOM id attribute anymore.

If that’s intentional and call sites have been updated, this is fine. If any consumers relied on setting a DOM id on ProviderIcon, they’ll now need another prop (e.g. svgId) or to pass it via a different name.

Also applies to: 11-12, 21-22

packages/opencode/src/provider/transform.ts (2)

77-88: Confirm bugged detection is using the correct model identifier

The new bugged gate uses model.id:

const bugged =
  (model.id === "kimi-k2-thinking" && model.providerID === "opencode") ||
  (model.id === "moonshotai/Kimi-K2-Thinking" && model.providerID === "baseten")

Everywhere else in this file, checks are done against model.api.id (e.g., temperature/options logic). If those Kimi identifiers actually live on model.api.id, this condition will never trigger and the “bugged” models will still go through the reasoning_content path you’re trying to avoid.

Consider aligning this with the rest of the file, e.g. by checking model.api.id (with consistent casing) or by confirming that Provider.Model["id"] is indeed populated with these exact strings.


237-244: Make the Gemini‑3 thinkingConfig check case‑insensitive for consistency

Here:

if (model.api.npm === "@ai-sdk/google" || model.api.npm === "@ai-sdk/google-vertex") {
  result["thinkingConfig"] = { includeThoughts: true }
  if (model.api.id.includes("gemini-3")) {
    result["thinkingConfig"]["thinkingLevel"] = "high"
  }
}

Other logic (e.g., temperature) uses model.api.id.toLowerCase().includes("gemini-3-pro"). To avoid missing models whose IDs differ only by case (e.g., Gemini-3-pro), it would be safer to mirror that pattern:

if (model.api.id.toLowerCase().includes("gemini-3")) {
  result.thinkingConfig.thinkingLevel = "high"
}

This keeps behavior robust across potential ID variants.

packages/ui/src/components/tag.css (1)

25-36: Consider using a CSS variable for font-size consistency.

The normal size variant uses var(--font-size-small) for font-size, but the large variant hardcodes 14px. For consistency and easier theming, consider using a CSS variable like var(--font-size-base) or equivalent.

   &[data-size="large"] {
     height: 22px;
     padding: 0 8px;

     /* text-14-medium */
     font-family: var(--font-family-sans);
-    font-size: 14px;
+    font-size: var(--font-size-base);
     font-style: normal;
     font-weight: var(--font-weight-medium);
     line-height: var(--line-height-large); /* 142.857% */
     letter-spacing: var(--letter-spacing-normal);
   }
packages/ui/src/components/select-dialog.tsx (1)

23-30: Consider guarding against missing props.key function.

If props.current is truthy but props.key is undefined, this will throw. The type system should prevent this, but a defensive check could help.

  createEffect(() => {
    if (!props.current) return
+   if (!props.key) return
    const key = props.key(props.current)
    requestAnimationFrame(() => {
      const element = document.querySelector(`[data-key="${key}"]`)
      element?.scrollIntoView({ block: "center" })
    })
  })
packages/desktop/src/context/layout.tsx (2)

59-77: Consider handling failures from project.update or at least logging

colorize writes icon.color back via globalSdk.client.project.update but ignores errors. For a noncritical cosmetic field this is mostly fine, but silent failures could leave UI and backend out of sync (client shows a color that never persisted).

If this matters operationally, you might consider:

  • Adding a .catch with a debug log/telemetry hook, or
  • Making the update fire-and-forget but conditional on some “allow auto-write” flag.

Not urgent, but worth thinking about if users rely on colors being durable.


82-91: Rename inner setStore in loadProjectSessions to avoid shadowing

Inside loadProjectSessions, the destructured const [, setStore] = globalSync.child(directory) shadows the outer layout setStore from makePersisted. This is easy to misread as updating the layout store instead of the per-directory sync store.

A small rename improves clarity:

-    async function loadProjectSessions(directory: string) {
-      const [, setStore] = globalSync.child(directory)
+    async function loadProjectSessions(directory: string) {
+      const [, setChildStore] = globalSync.child(directory)
       globalSdk.client.session.list({ directory }).then((x) => {
         const sessions = (x.data ?? [])
           .slice()
           .sort((a, b) => a.id.localeCompare(b.id))
           .slice(0, 5)
-        setStore("session", sessions)
+        setChildStore("session", sessions)
       })
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af6e630 and 6c2f117.

⛔ Files ignored due to path filters (52)
  • bun.lock is excluded by !**/*.lock
  • packages/sdk/js/src/v2/gen/sdk.gen.ts is excluded by !**/gen/**
  • packages/sdk/js/src/v2/gen/types.gen.ts is excluded by !**/gen/**
  • packages/tauri/src-tauri/icons/128x128.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/32x32.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/64x64.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square107x107Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square142x142Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square150x150Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square284x284Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square30x30Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square310x310Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square44x44Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square71x71Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/Square89x89Logo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/StoreLogo.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/icon.ico is excluded by !**/*.ico
  • packages/tauri/src-tauri/icons/icon.png is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
  • packages/tauri/src-tauri/icons/ios/[email protected] is excluded by !**/*.png
📒 Files selected for processing (93)
  • .github/last-synced-tag (1 hunks)
  • .opencode/opencode.jsonc (0 hunks)
  • README.md (1 hunks)
  • infra/enterprise.ts (1 hunks)
  • infra/stage.ts (1 hunks)
  • nix/hashes.json (1 hunks)
  • package.json (1 hunks)
  • packages/console/app/package.json (1 hunks)
  • packages/console/app/src/app.tsx (1 hunks)
  • packages/console/app/src/config.ts (2 hunks)
  • packages/console/app/src/routes/index.tsx (4 hunks)
  • packages/console/app/src/routes/t/[...path].tsx (1 hunks)
  • packages/console/core/package.json (1 hunks)
  • packages/console/function/package.json (1 hunks)
  • packages/console/mail/package.json (1 hunks)
  • packages/desktop/package.json (1 hunks)
  • packages/desktop/src/app.tsx (1 hunks)
  • packages/desktop/src/components/font-picker.tsx (3 hunks)
  • packages/desktop/src/components/prompt-input.tsx (10 hunks)
  • packages/desktop/src/components/theme-picker.tsx (2 hunks)
  • packages/desktop/src/context/global-sync.tsx (5 hunks)
  • packages/desktop/src/context/layout.tsx (4 hunks)
  • packages/desktop/src/context/local.tsx (4 hunks)
  • packages/desktop/src/context/session.tsx (1 hunks)
  • packages/desktop/src/context/sync.tsx (2 hunks)
  • packages/desktop/src/hooks/use-providers.ts (1 hunks)
  • packages/desktop/src/pages/home.tsx (4 hunks)
  • packages/desktop/src/pages/layout.tsx (8 hunks)
  • packages/enterprise/package.json (2 hunks)
  • packages/enterprise/src/entry-server.tsx (0 hunks)
  • packages/enterprise/src/routes/index.tsx (1 hunks)
  • packages/enterprise/src/routes/share/[shareID].tsx (4 hunks)
  • packages/enterprise/vite.config.ts (1 hunks)
  • packages/extensions/zed/extension.toml (2 hunks)
  • packages/function/package.json (1 hunks)
  • packages/opencode/package.json (1 hunks)
  • packages/opencode/src/bus/index.ts (2 hunks)
  • packages/opencode/src/cli/cmd/auth.ts (3 hunks)
  • packages/opencode/src/cli/cmd/tui/app.tsx (2 hunks)
  • packages/opencode/src/cli/cmd/tui/context/directory.ts (1 hunks)
  • packages/opencode/src/cli/cmd/tui/context/sync.tsx (4 hunks)
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx (6 hunks)
  • packages/opencode/src/flag/flag.ts (1 hunks)
  • packages/opencode/src/project/instance.ts (2 hunks)
  • packages/opencode/src/project/project.ts (1 hunks)
  • packages/opencode/src/provider/provider.ts (1 hunks)
  • packages/opencode/src/provider/transform.ts (2 hunks)
  • packages/opencode/src/server/server.ts (8 hunks)
  • packages/opencode/src/session/compaction.ts (1 hunks)
  • packages/opencode/src/session/index.ts (2 hunks)
  • packages/opencode/src/session/prompt.ts (5 hunks)
  • packages/opencode/src/share/share-next.ts (4 hunks)
  • packages/opencode/src/tool/bash.txt (1 hunks)
  • packages/opencode/test/tool/bash.test.ts (2 hunks)
  • packages/plugin/package.json (1 hunks)
  • packages/sdk/js/package.json (1 hunks)
  • packages/sdk/openapi.json (7 hunks)
  • packages/slack/package.json (1 hunks)
  • packages/tauri/package.json (1 hunks)
  • packages/tauri/src-tauri/capabilities/default.json (1 hunks)
  • packages/tauri/src-tauri/src/lib.rs (4 hunks)
  • packages/tauri/src/index.tsx (0 hunks)
  • packages/ui/index.html (0 hunks)
  • packages/ui/package.json (1 hunks)
  • packages/ui/src/components/avatar.tsx (1 hunks)
  • packages/ui/src/components/button.css (1 hunks)
  • packages/ui/src/components/dialog.css (4 hunks)
  • packages/ui/src/components/dialog.tsx (1 hunks)
  • packages/ui/src/components/icon.tsx (3 hunks)
  • packages/ui/src/components/input.css (1 hunks)
  • packages/ui/src/components/input.tsx (1 hunks)
  • packages/ui/src/components/list.css (1 hunks)
  • packages/ui/src/components/list.tsx (1 hunks)
  • packages/ui/src/components/provider-icon.tsx (2 hunks)
  • packages/ui/src/components/select-dialog.css (2 hunks)
  • packages/ui/src/components/select-dialog.tsx (1 hunks)
  • packages/ui/src/components/tag.css (1 hunks)
  • packages/ui/src/components/tag.tsx (1 hunks)
  • packages/ui/src/demo.tsx (0 hunks)
  • packages/ui/src/index.css (0 hunks)
  • packages/ui/src/index.tsx (0 hunks)
  • packages/ui/src/styles/index.css (2 hunks)
  • packages/ui/src/styles/tailwind/index.css (1 hunks)
  • packages/ui/src/styles/theme.css (1 hunks)
  • packages/util/package.json (1 hunks)
  • packages/web/astro.config.mjs (1 hunks)
  • packages/web/package.json (1 hunks)
  • packages/web/src/content/docs/ecosystem.mdx (1 hunks)
  • packages/web/src/content/docs/index.mdx (2 hunks)
  • packages/web/src/content/docs/permissions.mdx (1 hunks)
  • packages/web/src/content/docs/providers.mdx (1 hunks)
  • packages/web/src/content/docs/sdk.mdx (2 hunks)
  • sdks/vscode/package.json (1 hunks)
💤 Files with no reviewable changes (7)
  • packages/enterprise/src/entry-server.tsx
  • .opencode/opencode.jsonc
  • packages/tauri/src/index.tsx
  • packages/ui/src/demo.tsx
  • packages/ui/src/index.tsx
  • packages/ui/src/index.css
  • packages/ui/index.html
🧰 Additional context used
📓 Path-based instructions (9)
packages/opencode/**/*.ts

📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)

packages/opencode/**/*.ts: Use Bun with TypeScript ESM modules as the runtime
Organize file structure using namespace-based organization (e.g., Tool.define(), Session.create())
Validate all inputs with Zod schemas
Use Log.create({ service: "name" }) pattern for logging
Use Storage namespace for persistence operations

Files:

  • packages/opencode/src/share/share-next.ts
  • packages/opencode/src/provider/provider.ts
  • packages/opencode/src/project/project.ts
  • packages/opencode/src/project/instance.ts
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/index.ts
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/provider/transform.ts
  • packages/opencode/src/server/server.ts
  • packages/opencode/src/bus/index.ts
  • packages/opencode/src/flag/flag.ts
  • packages/opencode/src/cli/cmd/auth.ts
  • packages/opencode/test/tool/bash.test.ts
packages/opencode/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)

packages/opencode/**/*.{ts,tsx,js,jsx}: Use relative imports for local modules, with named imports preferred
Use camelCase for variable and function names
Use PascalCase for classes and namespaces

Files:

  • packages/opencode/src/share/share-next.ts
  • packages/opencode/src/provider/provider.ts
  • packages/opencode/src/project/project.ts
  • packages/opencode/src/project/instance.ts
  • packages/opencode/src/cli/cmd/tui/app.tsx
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/index.ts
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/provider/transform.ts
  • packages/opencode/src/server/server.ts
  • packages/opencode/src/bus/index.ts
  • packages/opencode/src/flag/flag.ts
  • packages/opencode/src/cli/cmd/tui/context/sync.tsx
  • packages/opencode/src/cli/cmd/auth.ts
  • packages/opencode/test/tool/bash.test.ts
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
packages/opencode/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/opencode/AGENTS.md)

packages/opencode/**/*.{ts,tsx}: Use Zod schemas for validation and TypeScript interfaces for structure
Use Result patterns for error handling; avoid throwing exceptions in tools

Files:

  • packages/opencode/src/share/share-next.ts
  • packages/opencode/src/provider/provider.ts
  • packages/opencode/src/project/project.ts
  • packages/opencode/src/project/instance.ts
  • packages/opencode/src/cli/cmd/tui/app.tsx
  • packages/opencode/src/session/compaction.ts
  • packages/opencode/src/session/index.ts
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/provider/transform.ts
  • packages/opencode/src/server/server.ts
  • packages/opencode/src/bus/index.ts
  • packages/opencode/src/flag/flag.ts
  • packages/opencode/src/cli/cmd/tui/context/sync.tsx
  • packages/opencode/src/cli/cmd/auth.ts
  • packages/opencode/test/tool/bash.test.ts
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
packages/desktop/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/desktop/AGENTS.md)

packages/desktop/**/*.{ts,tsx}: Use SolidJS with TypeScript as the primary framework
Use @/ alias for src/ directory imports (e.g., import Button from "@/ui/button")
Use function declarations and splitProps for SolidJS component props
Define interfaces for component props and avoid using any type
Use PascalCase for component names
Use camelCase for variable and function names

Files:

  • packages/desktop/src/pages/home.tsx
  • packages/desktop/src/context/session.tsx
  • packages/desktop/src/hooks/use-providers.ts
  • packages/desktop/src/context/local.tsx
  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/context/sync.tsx
  • packages/desktop/src/pages/layout.tsx
  • packages/desktop/src/app.tsx
  • packages/desktop/src/components/theme-picker.tsx
  • packages/desktop/src/context/layout.tsx
  • packages/desktop/src/context/global-sync.tsx
packages/desktop/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (packages/desktop/AGENTS.md)

Apply Prettier formatting with semicolons disabled and 120 character line width

Files:

  • packages/desktop/src/pages/home.tsx
  • packages/desktop/src/context/session.tsx
  • packages/desktop/src/hooks/use-providers.ts
  • packages/desktop/src/context/local.tsx
  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/context/sync.tsx
  • packages/desktop/src/pages/layout.tsx
  • packages/desktop/src/app.tsx
  • packages/desktop/src/components/theme-picker.tsx
  • packages/desktop/src/context/layout.tsx
  • packages/desktop/src/context/global-sync.tsx
packages/desktop/**/*.{css,ts,tsx}

📄 CodeRabbit inference engine (packages/desktop/AGENTS.md)

Use TailwindCSS with custom CSS variables theme system for styling

Files:

  • packages/desktop/src/pages/home.tsx
  • packages/desktop/src/context/session.tsx
  • packages/desktop/src/hooks/use-providers.ts
  • packages/desktop/src/context/local.tsx
  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/context/sync.tsx
  • packages/desktop/src/pages/layout.tsx
  • packages/desktop/src/app.tsx
  • packages/desktop/src/components/theme-picker.tsx
  • packages/desktop/src/context/layout.tsx
  • packages/desktop/src/context/global-sync.tsx
packages/desktop/**/*

📄 CodeRabbit inference engine (packages/desktop/AGENTS.md)

Use snake_case for file names

Files:

  • packages/desktop/src/pages/home.tsx
  • packages/desktop/src/context/session.tsx
  • packages/desktop/src/hooks/use-providers.ts
  • packages/desktop/src/context/local.tsx
  • packages/desktop/package.json
  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/context/sync.tsx
  • packages/desktop/src/pages/layout.tsx
  • packages/desktop/src/app.tsx
  • packages/desktop/src/components/theme-picker.tsx
  • packages/desktop/src/context/layout.tsx
  • packages/desktop/src/context/global-sync.tsx
packages/desktop/**/pages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/desktop/AGENTS.md)

Place pages in /pages/ directory

Files:

  • packages/desktop/src/pages/home.tsx
  • packages/desktop/src/pages/layout.tsx
packages/desktop/**/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (packages/desktop/AGENTS.md)

Place higher-level components in /components/ directory

Files:

  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/components/theme-picker.tsx
🧠 Learnings (22)
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{css,ts,tsx} : Use TailwindCSS with custom CSS variables theme system for styling

Applied to files:

  • packages/ui/src/styles/theme.css
  • packages/ui/src/styles/tailwind/index.css
  • packages/ui/src/styles/index.css
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{ts,tsx} : Use function declarations and splitProps for SolidJS component props

Applied to files:

  • packages/ui/src/components/input.tsx
  • packages/ui/src/components/provider-icon.tsx
  • packages/ui/src/components/tag.tsx
  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/pages/layout.tsx
  • packages/ui/src/components/avatar.tsx
  • packages/ui/src/components/list.tsx
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{ts,tsx} : Use PascalCase for component names

Applied to files:

  • packages/desktop/src/pages/home.tsx
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{ts,tsx} : Use `@/` alias for src/ directory imports (e.g., `import Button from "@/ui/button"`)

Applied to files:

  • packages/desktop/src/pages/home.tsx
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
  • packages/ui/src/components/avatar.tsx
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{ts,tsx} : Use camelCase for variable and function names

Applied to files:

  • packages/desktop/src/pages/home.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.{ts,tsx,js,jsx} : Use relative imports for local modules, with named imports preferred

Applied to files:

  • packages/ui/package.json
  • packages/opencode/package.json
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
  • packages/opencode/src/cli/cmd/tui/context/sync.tsx
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/ui/**/*.{ts,tsx} : Place UI primitives in `/ui/` directory

Applied to files:

  • packages/ui/package.json
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Use `bun run typecheck` for type checking (or `npm run typecheck` as alternative)

Applied to files:

  • packages/ui/package.json
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Use `bun run dev` to start Vite dev server on port 3000 for development

Applied to files:

  • packages/ui/package.json
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/providers/**/*.{ts,tsx} : Place providers in `/providers/` directory

Applied to files:

  • packages/desktop/src/context/session.tsx
  • packages/desktop/src/hooks/use-providers.ts
  • packages/desktop/src/context/sync.tsx
  • packages/desktop/src/pages/layout.tsx
  • packages/desktop/src/context/global-sync.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/tools/**/*.ts : Pass `sessionID` in tool context and use `App.provide()` for dependency injection

Applied to files:

  • packages/desktop/src/context/session.tsx
  • packages/web/src/content/docs/ecosystem.mdx
  • packages/opencode/src/session/prompt.ts
  • packages/opencode/src/server/server.ts
  • packages/desktop/src/app.tsx
  • packages/opencode/test/tool/bash.test.ts
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.ts : Organize file structure using namespace-based organization (e.g., `Tool.define()`, `Session.create()`)

Applied to files:

  • packages/opencode/package.json
  • packages/web/src/content/docs/ecosystem.mdx
  • packages/opencode/src/cli/cmd/tui/context/directory.ts
  • packages/opencode/src/cli/cmd/tui/context/sync.tsx
  • packages/opencode/test/tool/bash.test.ts
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.{ts,tsx} : Use Zod schemas for validation and TypeScript interfaces for structure

Applied to files:

  • packages/opencode/package.json
  • packages/sdk/js/package.json
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.ts : Validate all inputs with Zod schemas

Applied to files:

  • packages/opencode/package.json
  • packages/sdk/js/package.json
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.ts : Use Bun with TypeScript ESM modules as the runtime

Applied to files:

  • packages/opencode/package.json
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.{ts,tsx,js,jsx} : Use PascalCase for classes and namespaces

Applied to files:

  • packages/opencode/package.json
  • packages/console/app/src/routes/index.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.ts : Use `Storage` namespace for persistence operations

Applied to files:

  • packages/opencode/package.json
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Go TUI communicates with TypeScript server via stainless SDK. When adding/modifying server endpoints in `packages/opencode/src/server/server.ts`, ask the user to generate a new client SDK before proceeding with client-side changes

Applied to files:

  • packages/web/src/content/docs/sdk.mdx
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{ts,tsx} : Use SolidJS with TypeScript as the primary framework

Applied to files:

  • packages/ui/src/components/tag.tsx
  • packages/desktop/src/components/font-picker.tsx
  • packages/desktop/src/components/prompt-input.tsx
  • packages/desktop/src/context/layout.tsx
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
📚 Learning: 2025-12-02T19:05:12.128Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/desktop/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:12.128Z
Learning: Applies to packages/desktop/**/*.{ts,tsx} : Define interfaces for component props and avoid using `any` type

Applied to files:

  • packages/ui/src/components/tag.tsx
  • packages/ui/src/components/select-dialog.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/*.{ts,tsx,js,jsx} : Use camelCase for variable and function names

Applied to files:

  • packages/console/app/src/routes/index.tsx
📚 Learning: 2025-12-02T19:05:23.634Z
Learnt from: CR
Repo: Latitudes-Dev/shuvcode PR: 0
File: packages/opencode/AGENTS.md:0-0
Timestamp: 2025-12-02T19:05:23.634Z
Learning: Applies to packages/opencode/**/tools/**/*.ts : Implement tools with the `Tool.Info` interface including an `execute()` method

Applied to files:

  • packages/opencode/test/tool/bash.test.ts
  • packages/opencode/src/cli/cmd/tui/routes/session/index.tsx
🧬 Code graph analysis (17)
packages/ui/src/components/dialog.tsx (1)
packages/ui/src/components/icon-button.tsx (1)
  • IconButton (12-28)
infra/enterprise.ts (1)
infra/stage.ts (1)
  • shortDomain (15-19)
packages/opencode/src/project/instance.ts (1)
packages/opencode/src/bus/global.ts (1)
  • GlobalBus (3-10)
packages/opencode/src/session/index.ts (2)
packages/sdk/js/src/v2/gen/sdk.gen.ts (1)
  • share (1062-1085)
packages/sdk/js/src/gen/sdk.gen.ts (1)
  • share (571-576)
packages/opencode/src/session/prompt.ts (3)
packages/sdk/js/src/v2/gen/types.gen.ts (2)
  • Session (564-592)
  • ToolPart (325-336)
packages/opencode/src/tool/task.ts (1)
  • TaskTool (16-137)
packages/opencode/src/session/message-v2.ts (2)
  • ToolPart (273-281)
  • ToolPart (282-282)
packages/desktop/src/hooks/use-providers.ts (1)
packages/util/src/encode.ts (1)
  • base64Decode (5-7)
packages/opencode/src/server/server.ts (2)
packages/opencode/src/project/instance.ts (1)
  • Instance (16-78)
packages/opencode/src/bus/global.ts (1)
  • GlobalBus (3-10)
packages/desktop/src/components/prompt-input.tsx (3)
packages/desktop/src/hooks/use-providers.ts (2)
  • useProviders (8-31)
  • popularProviders (6-6)
packages/util/src/path.ts (2)
  • getFilename (1-6)
  • getDirectory (8-12)
packages/util/src/iife.ts (1)
  • iife (1-3)
packages/desktop/src/pages/layout.tsx (6)
packages/desktop/src/hooks/use-providers.ts (2)
  • useProviders (8-31)
  • popularProviders (6-6)
packages/util/src/encode.ts (1)
  • base64Decode (5-7)
packages/ui/src/components/select-dialog.tsx (1)
  • SelectDialog (16-101)
packages/desktop/src/context/layout.tsx (4)
  • open (104-108)
  • open (131-133)
  • open (147-149)
  • open (172-174)
packages/ui/src/components/provider-icon.tsx (1)
  • ProviderIcon (10-24)
packages/ui/src/components/tag.tsx (1)
  • Tag (7-22)
packages/opencode/src/cli/cmd/auth.ts (2)
packages/plugin/src/index.ts (2)
  • Hooks (144-182)
  • Plugin (33-33)
packages/sdk/js/src/gen/types.gen.ts (1)
  • Auth (1680-1680)
packages/ui/src/components/list.tsx (6)
packages/ui/src/hooks/use-filtered-list.tsx (2)
  • FilteredListProps (7-16)
  • useFilteredList (18-90)
packages/ui/src/components/icon.tsx (2)
  • IconProps (50-53)
  • Icon (55-73)
packages/web/src/components/share/common.tsx (1)
  • ref (46-58)
packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx (1)
  • filter (168-170)
packages/opencode/src/cli/cmd/tui/context/theme.tsx (1)
  • selected (314-316)
packages/desktop/src/context/session.tsx (1)
  • setActive (139-141)
packages/enterprise/src/routes/share/[shareID].tsx (5)
packages/ui/src/components/logo.tsx (1)
  • Mark (1-14)
packages/ui/src/components/provider-icon.tsx (1)
  • ProviderIcon (10-24)
packages/ui/src/components/session-turn.tsx (1)
  • SessionTurn (27-298)
packages/ui/src/components/session-message-rail.tsx (1)
  • SessionMessageRail (14-57)
packages/ui/src/components/session-review.tsx (1)
  • SessionReview (25-125)
packages/opencode/test/tool/bash.test.ts (2)
packages/opencode/test/fixture/fixture.ts (1)
  • tmpdir (16-34)
packages/opencode/src/tool/bash.ts (2)
  • BashTool (55-369)
  • log (23-23)
packages/console/app/src/routes/t/[...path].tsx (1)
packages/opencode/src/share/share.ts (1)
  • URL (68-70)
packages/desktop/src/context/layout.tsx (3)
packages/desktop/src/context/sync.tsx (2)
  • project (45-49)
  • directory (88-90)
packages/sdk/js/src/v2/gen/types.gen.ts (1)
  • Project (21-35)
packages/sdk/js/src/v2/gen/sdk.gen.ts (1)
  • Project (211-291)
packages/opencode/src/cli/cmd/tui/routes/session/index.tsx (4)
packages/opencode/src/cli/cmd/tui/routes/session/header.tsx (1)
  • Header (31-125)
packages/sdk/js/src/gen/sdk.gen.ts (6)
  • messages (605-610)
  • message (629-634)
  • revert (681-690)
  • command (653-662)
  • text (780-785)
  • prompt (615-624)
packages/sdk/js/src/gen/types.gen.ts (1)
  • AssistantMessage (114-147)
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx (1)
  • Prompt (49-941)
packages/desktop/src/context/global-sync.tsx (2)
packages/sdk/js/src/v2/gen/types.gen.ts (3)
  • ProviderListResponse (3135-3135)
  • Command (1479-1486)
  • Project (21-35)
packages/sdk/js/src/v2/gen/sdk.gen.ts (2)
  • Command (1530-1549)
  • Project (211-291)
🪛 Biome (2.1.2)
packages/ui/src/styles/tailwind/index.css

[error] 60-60: expected , but instead found --radius-xl

Remove --radius-xl

(parse)


[error] 60-60: Unexpected value or character.

Expected one of:

(parse)


[error] 60-60: expected , but instead found rem

Remove rem

(parse)


[error] 60-60: expected , but instead found ;

Remove ;

(parse)


[error] 60-60: Unknown type selector is not allowed.

See MDN web docs for more details.
Consider replacing the unknown type selector with valid one.

(lint/correctness/noUnknownTypeSelector)

packages/ui/src/components/button.css

[error] 114-114: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🪛 LanguageTool
packages/web/src/content/docs/providers.mdx

[grammar] ~571-~571: Ensure spelling is correct
Context: ... txt /models --- ### Helicone Helicone is an LLM...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~671-~671: Ensure spelling is correct
Context: ...ed as a separate session. ##### Common Helicone headers | Header |...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

packages/web/src/content/docs/permissions.mdx

[grammar] ~143-~143: Use a hyphen to join words.
Context: ...run a command in a pipeline, we use tree sitter to parse each command in the pipe...

(QB_NEW_EN_HYPHEN)

packages/web/src/content/docs/index.mdx

[grammar] ~10-~10: Use a hyphen to join words.
Context: ...ig.console OpenCode is an open source AI coding agent. It's available a...

(QB_NEW_EN_HYPHEN)

Comment on lines +3 to +12
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
const response = await fetch(targetUrl, {
method: req.method,
headers: req.headers,
body: req.body,
})
return response
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add error handling and consider security implications.

The proxy lacks error handling for network failures and forwards all request headers (including cookies, authorization) to the target. Consider:

  1. Wrapping fetch in try-catch
  2. Filtering sensitive headers if not all should be forwarded
  3. Adding a timeout
 async function handler(evt: APIEvent) {
   const req = evt.request.clone()
   const url = new URL(req.url)
   const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
-  const response = await fetch(targetUrl, {
-    method: req.method,
-    headers: req.headers,
-    body: req.body,
-  })
-  return response
+  try {
+    const response = await fetch(targetUrl, {
+      method: req.method,
+      headers: req.headers,
+      body: req.body,
+      signal: AbortSignal.timeout(30000),
+    })
+    return response
+  } catch (error) {
+    return new Response("Proxy error", { status: 502 })
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
const response = await fetch(targetUrl, {
method: req.method,
headers: req.headers,
body: req.body,
})
return response
async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
try {
const response = await fetch(targetUrl, {
method: req.method,
headers: req.headers,
body: req.body,
signal: AbortSignal.timeout(30000),
})
return response
} catch (error) {
return new Response("Proxy error", { status: 502 })
}
}

async function handler(evt: APIEvent) {
const req = evt.request.clone()
const url = new URL(req.url)
const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cd /tmp/repo && find . -type f -name "[...path].tsx" | head -20

Repository: Latitudes-Dev/shuvcode

Length of output: 125


🏁 Script executed:

cd /tmp/repo && cat -n packages/console/app/src/routes/t/[...path].tsx 2>/dev/null || echo "File not found"

Repository: Latitudes-Dev/shuvcode

Length of output: 157


🏁 Script executed:

cd /tmp/repo && rg -n 'enterprise\.opencode\.ai' packages/console/ --type=ts --type=tsx 2>/dev/null || echo "Pattern not found"

Repository: Latitudes-Dev/shuvcode

Length of output: 160


🏁 Script executed:

cd /tmp/repo && git ls-files | grep -E "(routes|proxy)" | head -20

Repository: Latitudes-Dev/shuvcode

Length of output: 125


🏁 Script executed:

git ls-files | grep -E "packages/console" | head -20

Repository: Latitudes-Dev/shuvcode

Length of output: 914


🏁 Script executed:

git ls-files | grep -E "\[.*\]\.tsx$"

Repository: Latitudes-Dev/shuvcode

Length of output: 304


🏁 Script executed:

git ls-files | grep -E "routes" | head -20

Repository: Latitudes-Dev/shuvcode

Length of output: 1016


🏁 Script executed:

cat -n packages/console/app/src/routes/t/[...path].tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 759


🏁 Script executed:

rg -n 'enterprise\.opencode\.ai' packages/console/app/src/routes/

Repository: Latitudes-Dev/shuvcode

Length of output: 197


🏁 Script executed:

rg -n 'OPENCODE_API' packages/console/ --type=ts --type=tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 93


🏁 Script executed:

rg -n '\[\.\.\.' packages/console/app/src/routes/ -A 5 -B 2

Repository: Latitudes-Dev/shuvcode

Length of output: 1371


🏁 Script executed:

cat -n packages/console/app/src/routes/t/[...path].tsx packages/console/app/src/routes/docs/[...path].ts 2>/dev/null | head -40

Repository: Latitudes-Dev/shuvcode

Length of output: 1446


🏁 Script executed:

rg -n 'params\|pathname' packages/console/app/src/routes/ --type=ts

Repository: Latitudes-Dev/shuvcode

Length of output: 48


🏁 Script executed:

rg -n 'url\.pathname|params\.' packages/console/app/src/routes/ -B 2 -A 2 --type=ts --type=tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 93


🏁 Script executed:

cat -n packages/console/app/src/routes/workspace/[id].tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 2905


🏁 Script executed:

rg -n 'export.*handler|export.*GET' packages/console/app/src/routes/docs/ -B 5 -A 5

Repository: Latitudes-Dev/shuvcode

Length of output: 1626


🏁 Script executed:

cat -n packages/console/app/src/routes/docs/index.ts packages/console/app/src/routes/docs/[...path].ts

Repository: Latitudes-Dev/shuvcode

Length of output: 1439


Remove the trailing slash to match the docs proxy pattern and avoid double slash in URLs.

The URL construction has an inconsistency: the /t/[...path] route includes a trailing slash after the domain (https://enterprise.opencode.ai/), while the similar /docs/[...path] route does not (https://docs.opencode.ai). This creates a double slash when url.pathname starts with /:

-const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
+const targetUrl = `https://enterprise.opencode.ai${url.pathname}${url.search}`

This aligns with how the docs proxy route is implemented and ensures clean URLs without double slashes.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const targetUrl = `https://enterprise.opencode.ai/${url.pathname}${url.search}`
const targetUrl = `https://enterprise.opencode.ai${url.pathname}${url.search}`
🤖 Prompt for AI Agents
packages/console/app/src/routes/t/[...path].tsx around line 6: the targetUrl
includes a trailing slash after the domain which can produce double slashes when
url.pathname starts with '/', so remove the trailing slash from the domain
literal (use "https://enterprise.opencode.ai" instead of
"https://enterprise.opencode.ai/") or alternatively normalize by stripping the
leading slash from url.pathname before concatenation so the final URL matches
the docs proxy pattern and avoids double slashes.

Comment on lines +196 to +198
sdk.client.provider.list().then((x) => {
setGlobalStore("provider", x.data ?? {})
}),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent fallback for provider data.

The fallback {} doesn't match the expected ProviderListResponse shape used in the default initialization (line 63). If x.data is nullish, accessing provider.all, provider.connected, or provider.default would return undefined instead of the expected arrays/object.

Apply this diff to use a consistent fallback:

      sdk.client.provider.list().then((x) => {
-        setGlobalStore("provider", x.data ?? {})
+        setGlobalStore("provider", x.data ?? { all: [], connected: [], default: {} })
      }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sdk.client.provider.list().then((x) => {
setGlobalStore("provider", x.data ?? {})
}),
sdk.client.provider.list().then((x) => {
setGlobalStore("provider", x.data ?? { all: [], connected: [], default: {} })
}),
🤖 Prompt for AI Agents
In packages/desktop/src/context/global-sync.tsx around lines 196 to 198, the
.then fallback uses {} which doesn't match the ProviderListResponse shape
initialized at line 63; change the fallback from {} to the same structured
default (e.g. { all: [], connected: [], default: {} } or the existing
constant/variable used at line 63) so setGlobalStore("provider", x.data ?? <that
structured default>) returns the expected arrays/objects instead of undefined.

Comment on lines 41 to 44
function isModelValid(model: ModelKey) {
const provider = sync.data.provider.find((x) => x.id === model.providerID)
return !!provider?.models[model.modelID]
const provider = sync.data.provider?.all.find((x) => x.id === model.providerID)
return !!provider?.models[model.modelID] && sync.data.provider?.connected.includes(model.providerID)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check if the files exist and their line counts
wc -l packages/desktop/src/context/local.tsx packages/desktop/src/context/sync.tsx 2>/dev/null || echo "Files may not exist at those paths"

# List files in the context directory
find packages/desktop/src/context -type f -name "*.tsx" -o -name "*.ts" 2>/dev/null | head -20

Repository: Latitudes-Dev/shuvcode

Length of output: 188


🏁 Script executed:

#!/bin/bash
# Read the relevant sections from local.tsx
echo "=== Lines 35-50 from local.tsx ==="
sed -n '35,50p' packages/desktop/src/context/local.tsx

echo ""
echo "=== Lines 110-125 from local.tsx ==="
sed -n '110,125p' packages/desktop/src/context/local.tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 1353


🏁 Script executed:

#!/bin/bash
# Search for sync context definition and provider type
echo "=== Checking sync.tsx for provider definition ==="
rg -n "provider" packages/desktop/src/context/sync.tsx -B 2 -A 2 | head -50

Repository: Latitudes-Dev/shuvcode

Length of output: 663


🏁 Script executed:

#!/bin/bash
# Search for the store definition in sync.tsx to see provider's type
echo "=== Store definition in sync.tsx ==="
rg -n "setStore\|provider:" packages/desktop/src/context/sync.tsx -B 5 -A 5 | head -80

Repository: Latitudes-Dev/shuvcode

Length of output: 102


🏁 Script executed:

#!/bin/bash
# Check if there's a type definition file for the store
fd -e "ts" -e "tsx" packages/desktop/src -type f | xargs rg -l "ModelKey|provider.*type" | head -10

Repository: Latitudes-Dev/shuvcode

Length of output: 545


🏁 Script executed:

#!/bin/bash
# Get more context around line 117 to see if there are guards
echo "=== Full context around lines 110-130 ==="
sed -n '105,135p' packages/desktop/src/context/local.tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 1161


🏁 Script executed:

#!/bin/bash
# Read the entire sync.tsx to understand the store definition
cat packages/desktop/src/context/sync.tsx

Repository: Latitudes-Dev/shuvcode

Length of output: 3929


🏁 Script executed:

#!/bin/bash
# Also check if there are any type imports or definitions related to provider
rg -n "interface\|type.*[Pp]rovider" packages/desktop/src/context/ -A 3

Repository: Latitudes-Dev/shuvcode

Length of output: 48


🏁 Script executed:

#!/bin/bash
# Find and read global-sync.tsx
find packages/desktop/src -name "global-sync*" -type f

Repository: Latitudes-Dev/shuvcode

Length of output: 110


🏁 Script executed:

#!/bin/bash
# Read the global-sync file to understand initial store state
cat packages/desktop/src/context/global-sync.tsx 2>/dev/null || cat packages/desktop/src/context/global-sync.ts 2>/dev/null

Repository: Latitudes-Dev/shuvcode

Length of output: 5874


Remove unnecessary optional chaining on sync.data.provider.

Lines 42-43 use optional chaining (sync.data.provider?.all, sync.data.provider?.connected), but provider is initialized as { all: [], connected: [], default: {} } in global-sync.tsx and is never undefined. This contradicts the direct access without optional chaining used at lines 117-120 (sync.data.provider.all, sync.data.provider.connected). Remove the optional chaining operators for consistency.

🤖 Prompt for AI Agents
In packages/desktop/src/context/local.tsx around lines 41 to 44, the
isModelValid function uses unnecessary optional chaining on sync.data.provider
(sync.data.provider?.all and sync.data.provider?.connected) even though provider
is always initialized as { all: [], connected: [], default: {} }; remove the
optional chaining and access sync.data.provider.all and
sync.data.provider.connected directly to match other usages and ensure
consistency.

Comment on lines +147 to 158

for (const p of sync.data.provider.connected) {
if (p in sync.data.provider.default) {
return {
providerID: p,
modelID: sync.data.provider.default[p],
}
}
}

throw new Error("No default model found")
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Throwing an error here will crash the app if no providers are connected.

When no connected providers have a default model, this throws "No default model found", which will propagate up and likely crash the reactive context. Consider returning a sentinel value or handling this more gracefully.

        for (const p of sync.data.provider.connected) {
          if (p in sync.data.provider.default) {
            return {
              providerID: p,
              modelID: sync.data.provider.default[p],
            }
          }
        }

-       throw new Error("No default model found")
+       // Return undefined to signal no valid model; callers should handle this
+       return undefined
      })

Then update fallbackModel usage to handle the undefined case appropriately.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In packages/desktop/src/context/local.tsx around lines 147 to 158 the code
throws a new Error("No default model found") when no connected provider has a
default model; change this to return a sentinel (e.g., undefined) instead of
throwing so the reactive context won't crash, i.e., return { providerID:
undefined, modelID: undefined } or simply undefined as appropriate for the
surrounding selector, and then update any callers/uses of fallbackModel to
handle the undefined case (fall back to a safe default UI state or no-op) rather
than assuming a non-null value.

Comment on lines 108 to +118
font-size: var(--font-size-small);
line-height: var(--line-height-large);
gap: 6px;

/* text-12-medium */
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
font-style: normal;
font-weight: var(--font-weight-medium);
line-height: var(--line-height-large); /* 166.667% */
letter-spacing: var(--letter-spacing-normal);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove duplicate font-size and line-height declarations in normal button size.

Lines 108–109 declare font-size and line-height, which are redundantly declared again in the explicit typography token block (lines 113–117). This duplication violates DRY and can cause confusion during maintenance.

Apply this diff to remove the earlier, redundant declarations:

   &[data-size="normal"] {
     height: 24px;
     padding: 0 6px;
     &[data-icon] {
       padding: 0 12px 0 4px;
     }
 
-    font-size: var(--font-size-small);
-    line-height: var(--line-height-large);
     gap: 6px;
 
     /* text-12-medium */
     font-family: var(--font-family-sans);
     font-size: var(--font-size-small);
     font-style: normal;
     font-weight: var(--font-weight-medium);
     line-height: var(--line-height-large); /* 166.667% */
     letter-spacing: var(--letter-spacing-normal);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
font-size: var(--font-size-small);
line-height: var(--line-height-large);
gap: 6px;
/* text-12-medium */
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
font-style: normal;
font-weight: var(--font-weight-medium);
line-height: var(--line-height-large); /* 166.667% */
letter-spacing: var(--letter-spacing-normal);
gap: 6px;
/* text-12-medium */
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
font-style: normal;
font-weight: var(--font-weight-medium);
line-height: var(--line-height-large); /* 166.667% */
letter-spacing: var(--letter-spacing-normal);
🧰 Tools
🪛 Biome (2.1.2)

[error] 114-114: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

font-size is already defined here.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

🤖 Prompt for AI Agents
In packages/ui/src/components/button.css around lines 108 to 118, remove the
duplicate font-size and line-height declarations at lines 108–109 so only the
explicit typography token block (lines 113–117) defines those properties; update
the CSS by deleting the earlier redundant font-size and line-height lines to
keep a single source of truth under the "text-12-medium" token block.

[data-component="dialog"] {
position: fixed;
inset: 0;
margin-left: var(--dialog-left-margin);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n 'dialog-left-margin' --type css

Repository: Latitudes-Dev/shuvcode

Length of output: 148


Define the --dialog-left-margin CSS variable or remove the margin-left property.

The --dialog-left-margin variable referenced on line 19 is not defined anywhere in the codebase. Without a definition, this property will not apply, and the margin will fall back to browser defaults, defeating the intent of the styling change.

🤖 Prompt for AI Agents
In packages/ui/src/components/dialog.css around line 19, the rule uses
margin-left: var(--dialog-left-margin) but the CSS variable --dialog-left-margin
is not defined; either define --dialog-left-margin (preferably in a global scope
like :root or in the dialog component’s root selector) with the intended value,
or replace the declaration with a concrete margin or a var() call that includes
a fallback (e.g. var(--dialog-left-margin, 1rem)); ensure the variable name and
scope match other component variables if you choose to define it.

Comment on lines +47 to +55
createEffect(() => {
if (!scrollRef()) return
if (!props.current) return
const key = props.key(props.current)
requestAnimationFrame(() => {
const element = scrollRef()!.querySelector(`[data-key="${key}"]`)
element?.scrollIntoView({ block: "center" })
})
})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Guard scrollRef inside the animation frame to avoid potential runtime errors

The requestAnimationFrame callback dereferences scrollRef()! without rechecking it. If the list unmounts or scrollRef is cleared between scheduling and execution, this can throw at runtime.

You can capture the element up front and bail out early:

-  createEffect(() => {
-    if (!scrollRef()) return
-    if (!props.current) return
-    const key = props.key(props.current)
-    requestAnimationFrame(() => {
-      const element = scrollRef()!.querySelector(`[data-key="${key}"]`)
-      element?.scrollIntoView({ block: "center" })
-    })
-  })
+  createEffect(() => {
+    const container = scrollRef()
+    if (!container) return
+    if (!props.current) return
+    const key = props.key(props.current)
+    requestAnimationFrame(() => {
+      const element = container.querySelector<HTMLElement>(`[data-key="${key}"]`)
+      element?.scrollIntoView({ block: "center" })
+    })
+  })

[scratchpad_start]
[done]

  • Comment for scrollRef safeguard added.
    [scratchpad_end] -->
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
createEffect(() => {
if (!scrollRef()) return
if (!props.current) return
const key = props.key(props.current)
requestAnimationFrame(() => {
const element = scrollRef()!.querySelector(`[data-key="${key}"]`)
element?.scrollIntoView({ block: "center" })
})
})
createEffect(() => {
const container = scrollRef()
if (!container) return
if (!props.current) return
const key = props.key(props.current)
requestAnimationFrame(() => {
const element = container.querySelector<HTMLElement>(`[data-key="${key}"]`)
element?.scrollIntoView({ block: "center" })
})
})
🤖 Prompt for AI Agents
In packages/ui/src/components/list.tsx around lines 47 to 55, the
requestAnimationFrame callback dereferences scrollRef()! without rechecking it,
which can throw if the ref is cleared before the frame runs; change the code to
capture the current scroll container and derived key before scheduling (const
container = scrollRef(); if (!container) return; const key =
props.key(props.current); requestAnimationFrame(() => { const el =
container.querySelector(`[data-key="${key}"]`); if (!el) return;
el.scrollIntoView({ block: "center" }); })), or alternatively re-read and guard
scrollRef() inside the RAF callback before calling querySelector and
scrollIntoView so you never dereference a possibly null ref.

Comment on lines +124 to +131
>
{props.children(item)}
<Show when={item === props.current}>
<Icon data-slot="list-item-selected-icon" name="check-small" />
</Show>
<Show when={props.activeIcon}>
{(icon) => <Icon data-slot="list-item-active-icon" name={icon()} />}
</Show>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

activeIcon currently renders on every row, not just the active item

Right now the active icon is shown for all items whenever props.activeIcon is set:

<Show when={props.activeIcon}>
  {(icon) => <Icon data-slot="list-item-active-icon" name={icon()} />}
</Show>

This ignores which item is actually active and will likely confuse users.

A targeted fix is to gate on the active key:

-                      <Show when={props.activeIcon}>
-                        {(icon) => <Icon data-slot="list-item-active-icon" name={icon()} />}
-                      </Show>
+                      <Show when={props.activeIcon && props.key(item) === active()}>
+                        {(icon) => (
+                          <Icon data-slot="list-item-active-icon" name={icon()!} />
+                        )}
+                      </Show>

[scratchpad_start]
[done]

  • Comment for activeIcon semantics added.
    [scratchpad_end] -->
🤖 Prompt for AI Agents
In packages/ui/src/components/list.tsx around lines 124-131, the current <Show
when={props.activeIcon}> renders the activeIcon for every row whenever
props.activeIcon is truthy; change the guard to only render the icon for the
active item by gating on both the active key and the prop (e.g., Show when={item
=== props.current && props.activeIcon}) and keep using the render function to
call the icon before passing its result to <Icon> so only the active row shows
the activeIcon.

Comment on lines +135 to +144
#### Scope of the `"ask"` option

When the agent asks for permission to run a particular bash command, it will
request feedback with the three options "accept", "accept always" and "deny".
The "accept always" answer applies for the rest of the current session.

In addition, command permissions are applied to the first two elements of a command. So, an "accept always" response for a command like `git log` would whitelist `git log *` but not `git commit ...`.

When an agent asks for permission to run a command in a pipeline, we use tree sitter to parse each command in the pipeline. The "accept always" permission thus applies separately to each command in the pipeline.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix hyphenation of tool name.

The term "tree sitter" should be hyphenated as "tree-sitter" when referring to the parsing tool.

Apply this diff:

-When an agent asks for permission to run a command in a pipeline, we use tree sitter to parse each command in the pipeline. The "accept always" permission thus applies separately to each command in the pipeline.
+When an agent asks for permission to run a command in a pipeline, we use tree-sitter to parse each command in the pipeline. The "accept always" permission thus applies separately to each command in the pipeline.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#### Scope of the `"ask"` option
When the agent asks for permission to run a particular bash command, it will
request feedback with the three options "accept", "accept always" and "deny".
The "accept always" answer applies for the rest of the current session.
In addition, command permissions are applied to the first two elements of a command. So, an "accept always" response for a command like `git log` would whitelist `git log *` but not `git commit ...`.
When an agent asks for permission to run a command in a pipeline, we use tree sitter to parse each command in the pipeline. The "accept always" permission thus applies separately to each command in the pipeline.
#### Scope of the `"ask"` option
When the agent asks for permission to run a particular bash command, it will
request feedback with the three options "accept", "accept always" and "deny".
The "accept always" answer applies for the rest of the current session.
In addition, command permissions are applied to the first two elements of a command. So, an "accept always" response for a command like `git log` would whitelist `git log *` but not `git commit ...`.
When an agent asks for permission to run a command in a pipeline, we use tree-sitter to parse each command in the pipeline. The "accept always" permission thus applies separately to each command in the pipeline.
🧰 Tools
🪛 LanguageTool

[grammar] ~143-~143: Use a hyphen to join words.
Context: ...run a command in a pipeline, we use tree sitter to parse each command in the pipe...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
In packages/web/src/content/docs/permissions.mdx around lines 135 to 144, the
tooling name is written as "tree sitter" but should be hyphenated; update the
text so every occurrence in this block reads "tree-sitter" (e.g., "we use
tree-sitter to parse each command in the pipeline") and ensure consistent
hyphenation across the paragraph.

@opencode-agent
Copy link

User coderabbitai[bot] does not have write permissions

github run

@opencode-agent
Copy link

User coderabbitai[bot] does not have write permissions

github run

@shuv1337 shuv1337 closed this Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Upstream Sync] Merge conflict with v1.0.145