Skip to content

Conversation

@shuv1337
Copy link
Collaborator

@shuv1337 shuv1337 commented Jan 12, 2026

Summary

Syncs shuvcode fork with upstream opencode v1.1.13, bringing desktop app improvements, tool enhancements, and bug fixes.

Changes

Features

Fixes

Refactoring

  • Core: Extract external directory validation to shared utility to reduce code duplication across tools

Internal

  • Ensure codex built-in plugin is always available
  • Sync marker updated to v1.1.13

Breaking Changes

None

Testing

  • Production builds tested locally (CLI and app)
  • All existing tests pass

Greptile Overview

Greptile Summary

This PR syncs the shuvcode fork with upstream opencode v1.1.13, bringing substantial improvements across desktop functionality, tool enhancements, and bug fixes.

Key Changes

Desktop Application Enhancements:

  • Default Server Configuration: Added ability to configure a default remote server URL that connects on app launch instead of spawning a local server. Includes health checking and fallback to local server if unavailable. Requires app restart to take effect.
  • Session Forking: New dialog component allowing users to create a new session from a previous message in the conversation history.
  • UI Improvements: Added autocomplete mouse interaction, copy-to-clipboard for responses, and fixed text editing shortcuts on macOS.

Core Tool Refactoring:

  • Extracted external directory validation logic into a shared assertExternalDirectory utility, eliminating code duplication across Edit, Write, Read, Glob, and Grep tools.
  • All file operation tools now consistently validate external directory access with user permission.

Search & File Operations:

  • Grep now follows symlinks by default (--follow and --hidden flags added to ripgrep).
  • Improved ripgrep file search with better handling of hidden files and symbolic links.

Built-in Codex Plugin:

  • New internal plugin (CodexAuthPlugin) provides ChatGPT Pro/Plus OAuth authentication with PKCE flow.
  • Supports GPT-5.1 and GPT-5.2 Codex models with automatic token refresh.
  • Replaces external opencode-openai-codex-auth plugin for better reliability.

ACP Agent Enhancement:

  • Tracks file modification events by applying diffs when edit permissions are approved, enabling better integration with external editors.

Provider & Plugin System:

  • Added sessionID parameter to chat.system.transform hook for session-aware system message transformations.
  • Enhanced OAuth flow to capture and store accountId for organization subscriptions.
  • Updated Codex model effort configuration to include "xhigh" effort level for gpt-5.2-codex.

TUI Fixes:

  • Fixed component initialization by moving props.ref to onMount.
  • Corrected mouse hover highlighting in command palette.

LSP Enhancement:

  • Disabled telemetry in PHP Intelephense LSP server for improved privacy.

Integration Quality

The changes integrate cleanly with the existing codebase architecture. The refactoring to shared utilities (external-directory validation) improves maintainability and reduces the risk of inconsistent behavior across tools. The new Codex plugin follows established plugin patterns and is properly integrated as an internal plugin alongside existing authentication providers.

Issues Found

Two issues were identified that should be addressed:

  1. ACP Agent File Operations: Missing error handling when reading files for diff application (line 114 of acp/agent.ts). File read can fail if the file doesn't exist or is not readable.

  2. URL Injection Security: The Rust code that injects the configured server URL into JavaScript uses basic string escaping that may not handle all special characters safely (line 448-451 of lib.rs). Consider using proper JSON serialization or a safer injection method.

These are not critical blockers but should be fixed to prevent potential runtime errors and security issues.

Confidence Score: 4/5

  • This PR is generally safe to merge with two moderate issues that should be addressed
  • The PR represents a well-structured upstream sync with comprehensive improvements. The code quality is high, with good refactoring (external-directory utility) and proper architectural patterns (Codex plugin integration). However, the score is reduced from 5 to 4 due to two identified issues: missing error handling in the ACP agent's file read operation, and potentially unsafe URL injection in the Rust code. Both issues could cause runtime problems but are not critical security vulnerabilities. The changes have been tested locally and all existing tests pass according to the PR description.
  • Pay close attention to packages/opencode/src/acp/agent.ts (needs error handling) and packages/desktop/src-tauri/src/lib.rs (needs safer URL injection)

Important Files Changed

File Analysis

Filename Score Overview
packages/opencode/src/tool/external-directory.ts 5/5 New utility to extract and centralize external directory validation logic from multiple tools - clean refactoring
packages/opencode/src/acp/agent.ts 3/5 Added file modification tracking on edit permission approval; missing error handling for file read operations
packages/desktop/src-tauri/src/lib.rs 3/5 Adds default server URL configuration and health checking; URL injection in eval() needs safer handling
packages/opencode/src/plugin/codex.ts 5/5 New built-in Codex auth plugin with OAuth PKCE flow - well-structured implementation
packages/opencode/src/tool/edit.ts 5/5 Refactored to use shared assertExternalDirectory utility - clean code deduplication
packages/opencode/src/tool/write.ts 5/5 Replaced TODO comment with proper external directory assertion - good cleanup
packages/opencode/src/tool/read.ts 5/5 Refactored to use shared external directory validation with bypass option support
packages/app/src/components/dialog-select-server.tsx 5/5 Added default server URL configuration UI for desktop - well-integrated feature
packages/opencode/src/provider/auth.ts 5/5 Added accountId field support for OAuth responses - good enhancement for org subscriptions

Sequence Diagram

sequenceDiagram
    participant User
    participant DesktopApp as Desktop App (Tauri)
    participant Store as Settings Store
    participant Server as Remote/Local Server
    participant UI as React UI

    Note over User,UI: Desktop App Launch Flow with Default Server

    User->>DesktopApp: Launch App
    DesktopApp->>Store: get_default_server_url()
    
    alt Default Server URL Configured
        Store-->>DesktopApp: Return server URL
        DesktopApp->>Server: check_server_health(url)
        
        alt Server is Healthy
            Server-->>DesktopApp: Health check success
            DesktopApp->>UI: Inject serverUrl via window.__SHUVCODE__
            DesktopApp->>UI: Set serverReady = true
            UI->>Server: Connect to configured server
        else Server Not Reachable
            Server-->>DesktopApp: Health check failed
            DesktopApp->>User: Show dialog: Retry or Start Local?
            
            alt User Chooses Retry
                User-->>DesktopApp: Retry
                DesktopApp->>Server: check_server_health(url) again
            else User Chooses Start Local
                User-->>DesktopApp: Start Local
                DesktopApp->>DesktopApp: spawn_sidecar() on port
                DesktopApp->>UI: Set serverReady = true
                UI->>Server: Connect to local server
            end
        end
    else No Default Server Configured
        Store-->>DesktopApp: Return None
        DesktopApp->>DesktopApp: Check if port already running
        
        alt Port Not Running
            DesktopApp->>DesktopApp: spawn_sidecar() on port
        end
        
        DesktopApp->>UI: Set serverReady = true
        UI->>Server: Connect to local server
    end

    Note over User,UI: User Configures Default Server

    User->>UI: Open Server Selection Dialog
    UI->>DesktopApp: getDefaultServerUrl()
    DesktopApp->>Store: get_default_server_url()
    Store-->>UI: Current default URL (or null)
    
    User->>UI: Set Current as Default
    UI->>DesktopApp: setDefaultServerUrl(url)
    DesktopApp->>Store: set(DEFAULT_SERVER_URL_KEY, url)
    Store->>Store: save()
    Store-->>UI: Success
    
    Note over User: Requires app restart to take effect
Loading

madflow and others added 25 commits January 10, 2026 08:44
Resolved conflicts:
- .gitignore: merged both .loop* and *.bun-build patterns
- bun.lock: kept fork's @shuvcode/desktop name, updated version to 1.1.13
- packages/app/src/app.tsx: merged shuv.ai hostname, __OPENCODE__.serverUrl support, and query param priority
- packages/app/src/components/prompt-input.tsx: kept upstream onClick/onMouseEnter pattern (mobile-friendly)
- packages/desktop/src-tauri/src/lib.rs: kept shuv.ai branding, merged configured server URL health check logic
- sdks/vscode/package.json: kept fork's shuvcode name and latitudes-dev publisher, updated version to 1.1.13
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

const filepath = typeof metadata["filepath"] === "string" ? metadata["filepath"] : ""
const diff = typeof metadata["diff"] === "string" ? metadata["diff"] : ""

const content = await Bun.file(filepath).text()
Copy link

Choose a reason for hiding this comment

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

The file read operation await Bun.file(filepath).text() can throw an error if the file doesn't exist, is not readable, or the path is invalid. This should be wrapped in a try-catch block to handle potential errors gracefully.

Suggested change
const content = await Bun.file(filepath).text()
try {
const content = await Bun.file(filepath).text()
const newContent = getNewContent(content, diff)
if (newContent) {
this.connection.writeTextFile({
sessionId: sessionId,
path: filepath,
content: newContent,
})
}
} catch (error) {
log.error("Failed to read or apply diff to file", { filepath, error })
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/opencode/src/acp/agent.ts
Line: 114:114

Comment:
The file read operation `await Bun.file(filepath).text()` can throw an error if the file doesn't exist, is not readable, or the path is invalid. This should be wrapped in a try-catch block to handle potential errors gracefully.

```suggestion
                  try {
                    const content = await Bun.file(filepath).text()
                    const newContent = getNewContent(content, diff)

                    if (newContent) {
                      this.connection.writeTextFile({
                        sessionId: sessionId,
                        path: filepath,
                        content: newContent,
                      })
                    }
                  } catch (error) {
                    log.error("Failed to read or apply diff to file", { filepath, error })
                  }
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +448 to +451
let escaped_url = url.replace('\\', "\\\\").replace('"', "\\\"");
let _ = window.eval(format!(
"window.__SHUVCODE__.serverUrl = \"{escaped_url}\"; window.__OPENCODE__.serverUrl = \"{escaped_url}\";",
));
Copy link

Choose a reason for hiding this comment

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

The URL escaping logic here may not correctly handle all special characters. The replace calls handle backslashes and quotes, but URLs can contain other characters that need escaping (e.g., single quotes, newlines, or other control characters). Consider using a proper URL encoding/escaping function or JSON serialization to ensure the URL is safely injected into JavaScript.

Additionally, injecting URLs directly into JavaScript via eval could be vulnerable to injection attacks if the URL contains malicious content. Consider using a safer alternative like postMessage or Tauri's state management.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/desktop/src-tauri/src/lib.rs
Line: 448:451

Comment:
The URL escaping logic here may not correctly handle all special characters. The `replace` calls handle backslashes and quotes, but URLs can contain other characters that need escaping (e.g., single quotes, newlines, or other control characters). Consider using a proper URL encoding/escaping function or JSON serialization to ensure the URL is safely injected into JavaScript.

Additionally, injecting URLs directly into JavaScript via `eval` could be vulnerable to injection attacks if the URL contains malicious content. Consider using a safer alternative like `postMessage` or Tauri's state management.

How can I resolve this? If you propose a fix, please make it concise.

@shuv1337 shuv1337 merged commit 33aee23 into integration Jan 12, 2026
3 of 4 checks passed
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.