Skip to content

Commit 4e7375c

Browse files
authored
Merge pull request #219 from Latitudes-Dev/shuvcode-dev
Merge shuvcode-dev: upstream v1.0.210 → v1.0.218 + desktop rebrand
2 parents 2db0dd6 + 4fec118 commit 4e7375c

171 files changed

Lines changed: 3345 additions & 1698 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/last-synced-tag

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.0.209
1+
v1.0.218
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# Dev Environment LAN Access Issue
2+
3+
**Date:** 2025-12-30
4+
**Status:** Unresolved
5+
**Affects:** Development environment only (not production)
6+
7+
## Problem Summary
8+
9+
When accessing the Vite dev server from a LAN IP address (e.g., `http://10.0.2.100:3000/`), the web app fails to connect to the backend opencode server, even though both servers are bound to `0.0.0.0`.
10+
11+
## Environment
12+
13+
- **Vite dev server:** `bun run dev` → listening on `0.0.0.0:3000`
14+
- **OpenCode server:** `bun run dev serve --port 4096 --hostname 0.0.0.0 --print-logs`
15+
- **Access method:** Browser on same machine or LAN device via IP address
16+
17+
## Error Messages
18+
19+
### Original (before attempted fix):
20+
```
21+
Error: Could not connect to server. Is there a server running at `http://localhost:4096`?
22+
at bootstrap (http://10.0.2.100:3000/src/context/global-sync.tsx:317:31)
23+
```
24+
25+
### After attempted fix (using `location.hostname`):
26+
```
27+
Error: Could not connect to server. Is there a server running at `http://10.0.2.100:4096`?
28+
at bootstrap (http://10.0.2.100:3000/src/context/global-sync.tsx:317:31)
29+
```
30+
31+
## Analysis
32+
33+
### What's happening:
34+
35+
1. When accessing via `http://10.0.2.100:3000/`, the browser correctly loads the Vite dev server
36+
2. The app tries to connect to the OpenCode API server
37+
3. With original code: tries `http://localhost:4096` (wrong host from browser's perspective on LAN)
38+
4. With fix attempt: tries `http://10.0.2.100:4096` (correct host, but still fails)
39+
40+
### Why the fix didn't work:
41+
42+
The issue is **NOT** the URL resolution logic. The URL `http://10.0.2.100:4096` is correct. The problem is one of:
43+
44+
1. **CORS (Cross-Origin Resource Sharing)**
45+
- Browser origin: `http://10.0.2.100:3000`
46+
- API request to: `http://10.0.2.100:4096`
47+
- These are different origins (different ports)
48+
- The OpenCode server may not be sending proper CORS headers for this origin
49+
50+
2. **Vite Proxy Not Being Used**
51+
- In dev mode, Vite is configured with a proxy to forward `/api/*` requests to the backend
52+
- But if the app is constructing absolute URLs like `http://10.0.2.100:4096`, it bypasses the Vite proxy entirely
53+
- The proxy only works for relative URLs or same-origin requests
54+
55+
3. **Network/Firewall**
56+
- Less likely since both servers are on same machine, but port 4096 could be blocked for non-localhost
57+
58+
## Current Server URL Resolution Logic
59+
60+
```typescript
61+
const defaultServerUrl = iife(() => {
62+
// 1. Query parameter (highest priority)
63+
const param = new URLSearchParams(document.location.search).get("url")
64+
if (param) return param
65+
66+
// 2. Known production hosts -> localhost
67+
if (location.hostname.includes("opencode.ai") || location.hostname.includes("shuv.ai"))
68+
return "http://localhost:4096"
69+
70+
// 3. Desktop app (Tauri) with injected port
71+
if (window.__SHUVCODE__?.port) return `http://127.0.0.1:${window.__SHUVCODE__.port}`
72+
if (window.__OPENCODE__?.port) return `http://127.0.0.1:${window.__OPENCODE__.port}`
73+
74+
// 4. Dev mode -> explicit host:port from env
75+
if (import.meta.env.DEV)
76+
return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}`
77+
78+
// 5. Default -> same origin (production web command)
79+
return window.location.origin
80+
})
81+
```
82+
83+
## Potential Solutions
84+
85+
### Option 1: Use Vite Proxy in Dev Mode (Recommended)
86+
87+
Instead of returning an absolute URL in dev mode, return a relative URL so requests go through Vite's proxy:
88+
89+
```typescript
90+
// 4. Dev mode -> use relative URL to go through Vite proxy
91+
if (import.meta.env.DEV) return "/"
92+
```
93+
94+
This requires the Vite proxy to be properly configured in `vite.config.ts` to forward API requests to `localhost:4096`.
95+
96+
**Pros:**
97+
- Works regardless of how you access the dev server (localhost, IP, hostname)
98+
- No CORS issues since requests are same-origin
99+
- Already partially configured in vite.config.ts
100+
101+
**Cons:**
102+
- Need to ensure all API routes are proxied
103+
- Slightly different behavior than production
104+
105+
### Option 2: Configure CORS on OpenCode Server
106+
107+
Add CORS headers to the OpenCode server to allow requests from any origin in dev mode:
108+
109+
```typescript
110+
// In packages/opencode/src/server/server.ts
111+
if (isDev) {
112+
app.use('*', (c, next) => {
113+
c.header('Access-Control-Allow-Origin', '*')
114+
c.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS')
115+
c.header('Access-Control-Allow-Headers', '*')
116+
return next()
117+
})
118+
}
119+
```
120+
121+
**Pros:**
122+
- Allows direct access to API from any origin
123+
- Useful for debugging API directly
124+
125+
**Cons:**
126+
- Security consideration (dev only)
127+
- Need to modify server code
128+
129+
### Option 3: Environment Variable Override
130+
131+
Set `VITE_OPENCODE_SERVER_HOST=0.0.0.0` or the specific IP when starting dev server.
132+
133+
**Pros:**
134+
- Simple, no code changes
135+
- Explicit control
136+
137+
**Cons:**
138+
- Manual configuration required
139+
- Still has CORS issues
140+
141+
### Option 4: Use Same-Origin Detection (Our Previous Implementation)
142+
143+
Our previous (more complex) implementation had logic to detect when to use same-origin requests:
144+
145+
```typescript
146+
const isLoopback = ["localhost", "127.0.0.1", "0.0.0.0"].includes(location.hostname)
147+
const isWebCommand = !import.meta.env.DEV
148+
const useSameOrigin = isSecure || isKnownHost || (isLoopback && !import.meta.env.DEV) || isWebCommand
149+
150+
if (useSameOrigin) return "/"
151+
```
152+
153+
This was more complex but handled the case of non-loopback access in dev mode.
154+
155+
## Recommended Next Steps
156+
157+
1. **Verify the Vite proxy configuration** in `packages/app/vite.config.ts`
158+
2. **Test Option 1** - Return `/` in dev mode and ensure Vite proxy forwards correctly
159+
3. **If proxy approach doesn't work**, investigate CORS headers on the OpenCode server
160+
161+
## Files Involved
162+
163+
- `packages/app/src/app.tsx` - Server URL resolution
164+
- `packages/app/vite.config.ts` - Vite proxy configuration
165+
- `packages/app/src/context/global-sync.tsx` - Where the connection error originates
166+
- `packages/opencode/src/server/server.ts` - Backend server (if CORS fix needed)
167+
168+
## Workaround
169+
170+
For now, access the dev server via `http://localhost:3000/` instead of IP address.

LOCAL_TAURI_PUBLISH.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Local Tauri Publish (Shuvcode)
2+
3+
This guide is local-only: build, sign, and publish the desktop app without GitHub Actions.
4+
5+
## 1) Prerequisites
6+
7+
- Bun and Rust installed (host triple in `rustc -vV`).
8+
- Tauri CLI available via `bun run tauri` in `packages/desktop`.
9+
- Linux-only bundling dependencies for AppImage:
10+
- Install `fuse2` (or set `APPIMAGE_EXTRACT_AND_RUN=1` to avoid FUSE).
11+
- Ensure `glibc`, `gtk3`, `webkit2gtk`, and related system libs are installed.
12+
13+
## 2) Branding + updater config you must own
14+
15+
- Set the updater public key to your Shuvcode key in `packages/desktop/src-tauri/tauri.prod.conf.json`.
16+
- Confirm updater endpoint uses your repo: `https://github.com/Latitudes-Dev/shuvcode/releases/latest/download/latest.json`.
17+
- Ensure bundle identifiers are correct:
18+
- Dev: `dev.shuvcode.desktop.dev`
19+
- Prod: `dev.shuvcode.desktop`
20+
21+
## 3) Generate signing keys (one-time)
22+
23+
Run locally:
24+
25+
```bash
26+
bun run --cwd packages/desktop tauri signer generate -w ./shuvcode-private.key
27+
```
28+
29+
- The command prints a public key; copy that into `plugins.updater.pubkey` in `packages/desktop/src-tauri/tauri.prod.conf.json`.
30+
- Store the private key securely. If you set a password, also store it.
31+
32+
## 4) Local build workflow (per release)
33+
34+
```bash
35+
export RUST_TARGET=x86_64-unknown-linux-gnu
36+
bun run --cwd packages/desktop predev
37+
bun run --cwd packages/desktop build
38+
TAURI_SIGNING_PRIVATE_KEY="$(cat ./shuvcode-private.key)" \
39+
TAURI_SIGNING_PRIVATE_KEY_PASSWORD="<if-set>" \
40+
bun run --cwd packages/desktop tauri build
41+
```
42+
43+
Outputs appear in:
44+
45+
- Bundles: `packages/desktop/src-tauri/target/release/bundle/`
46+
- App binary: `packages/desktop/src-tauri/target/release/Shuvcode`
47+
48+
## 5) Publish locally (no CI)
49+
50+
You have two viable local publish paths:
51+
52+
### Option A: GitHub Releases (local upload)
53+
54+
- Create a release and upload bundle artifacts + `latest.json` (updater manifest).
55+
- Use `gh release create --repo Latitudes-Dev/shuvcode` from your machine.
56+
57+
### Option B: Self-hosted updater
58+
59+
- Host the full contents of `bundle/` plus `latest.json` on your own server.
60+
- Update `plugins.updater.endpoints` to your hosting URL.
61+
62+
## 6) Known local issues
63+
64+
- AppImage bundling failed locally with `failed to run linuxdeploy`.
65+
- linuxdeploy’s embedded `strip` fails on `.relr.dyn` sections; try `NO_STRIP=1` or use a newer linuxdeploy build that understands RELR.
66+
- Install `fuse2` (or set `APPIMAGE_EXTRACT_AND_RUN=1`) plus `squashfs-tools` and `patchelf`.
67+
- Re-run `bun run --cwd packages/desktop tauri build` after adjusting linuxdeploy/strip.
68+
69+
## 7) Validation checklist
70+
71+
- Launch `Shuvcode` binary, verify UI loads.
72+
- Confirm sidecar starts (CLI server is reachable on the injected port).
73+
- Run in-app update check; ensure it hits your Shuvcode release endpoint.
74+
- Verify installed bundle name and identifier for each OS.

STATS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,4 @@
185185
| 2025-12-27 | 1,371,771 (+19,360) | 1,238,236 (+10,621) | 2,610,007 (+29,981) |
186186
| 2025-12-28 | 1,390,388 (+18,617) | 1,245,690 (+7,454) | 2,636,078 (+26,071) |
187187
| 2025-12-29 | 1,415,560 (+25,172) | 1,257,101 (+11,411) | 2,672,661 (+36,583) |
188+
| 2025-12-30 | 1,445,450 (+29,890) | 1,272,689 (+15,588) | 2,718,139 (+45,478) |

TAURI_DESKTOP_FOLLOWUPS.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Shuvcode Desktop (Tauri) Follow-ups
2+
3+
- Update the Tauri updater public key to the Shuvcode signing key in `packages/desktop/src-tauri/tauri.prod.conf.json`.
4+
- Confirm the fork’s release workflow uploads `latest.json` and uses the Shuvcode repo endpoint for updater artifacts.
5+
- Ensure the CI artifact name for the sidecar is `shuvcode-cli` (matches `packages/desktop/scripts/prepare.ts`).
6+
- Verify all sidecar binaries exist for targets in `packages/desktop/scripts/utils.ts` (especially Linux arm64).
7+
- Validate bundle naming in CI now that the product name is Shuvcode (script expects `Shuvcode*` in `packages/desktop/scripts/copy-bundles.ts`).
8+
- Resolve AppImage bundling on Linux: linuxdeploy’s embedded `strip` fails on `.relr.dyn` sections; try `NO_STRIP=1` or a newer linuxdeploy build, or wrap linuxdeploy to use `/usr/bin/strip`.
9+
- Check macOS/Windows signing identities and entitlements to match the new bundle identifiers (`dev.shuvcode.desktop`).
10+
- Run a full desktop smoke test: `bun run predev` then `bun run tauri dev`, confirm sidecar launch + update flow.

0 commit comments

Comments
 (0)