Skip to content

Commit fb6d6b4

Browse files
committed
fix: resolve post-merge type errors and missing imports for v1.2.7 sync
1 parent aabdd25 commit fb6d6b4

11 files changed

Lines changed: 379 additions & 111 deletions

File tree

bun.lock

Lines changed: 336 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@
107107
},
108108
"patchedDependencies": {
109109
"ghostty-opentui@1.3.7": "patches/ghostty-opentui@1.3.7.patch",
110-
"ghostty-web@0.3.0": "patches/ghostty-web@0.3.0.patch",
111110
"@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch",
112111
"@openrouter/ai-sdk-provider@1.5.4": "patches/@openrouter%2Fai-sdk-provider@1.5.4.patch"
113112
}

packages/app/src/app.tsx

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,29 +68,6 @@ declare global {
6868
}
6969
}
7070

71-
const defaultServerUrl = iife(() => {
72-
// NOTE: The ?url= query parameter was intentionally removed due to CVE-2026-22813 (GHSA-c83v-7274-4vgp)
73-
// Allowing arbitrary server URLs via query params enables XSS attacks on localhost:4096
74-
75-
// 1. Configured server URL (from desktop settings)
76-
if (window.__OPENCODE__?.serverUrl) return window.__OPENCODE__.serverUrl
77-
78-
// 2. Known production hosts -> localhost (same as upstream + shuv.ai)
79-
if (location.hostname.includes("opencode.ai") || location.hostname.includes("shuv.ai")) return "http://localhost:4096"
80-
81-
// 3. Desktop app (Tauri) with injected port
82-
if (window.__SHUVCODE__?.port) return `http://127.0.0.1:${window.__SHUVCODE__.port}`
83-
if (window.__OPENCODE__?.port) return `http://127.0.0.1:${window.__OPENCODE__.port}`
84-
85-
// 4. Dev mode -> same-origin so Vite proxy handles LAN access + CORS
86-
if (import.meta.env.DEV) {
87-
return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}`
88-
}
89-
90-
// 5. Default -> same origin (production web command)
91-
return window.location.origin
92-
})
93-
9471
function MarkedProviderWithNativeParser(props: ParentProps) {
9572
const platform = usePlatform()
9673
return <MarkedProvider nativeParser={platform.parseMarkdown}>{props.children}</MarkedProvider>

packages/app/src/components/welcome-screen.tsx

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { AsciiLogo } from "@opencode-ai/ui/logo"
44
import { Button } from "@opencode-ai/ui/button"
55
import { TextField } from "@opencode-ai/ui/text-field"
66
import { Icon } from "@opencode-ai/ui/icon"
7-
import { normalizeServerUrl, serverDisplayName, useServer } from "@/context/server"
7+
import { normalizeServerUrl, ServerConnection, serverDisplayName, useServer } from "@/context/server"
88
import { usePlatform } from "@/context/platform"
99
import { createOpencodeClient } from "@opencode-ai/sdk/v2/client"
1010
import { isHostedEnvironment, hasUrlQueryParam, getUrlQueryParam } from "@/utils/hosted"
@@ -46,14 +46,15 @@ export function WelcomeScreen(props: WelcomeScreenProps) {
4646

4747
const items = createMemo(() => {
4848
const list = server.list
49-
return list.filter((x) => x !== props.attemptedUrl)
49+
return list.filter((x) => ServerConnection.key(x) !== props.attemptedUrl)
5050
})
5151

5252
async function refreshHealth() {
5353
const results: Record<string, ServerStatus> = {}
5454
await Promise.all(
55-
items().map(async (url) => {
56-
results[url] = await checkHealth(url, platform.fetch)
55+
items().map(async (conn) => {
56+
const key = ServerConnection.key(conn)
57+
results[key] = await checkHealth(conn.http.url, platform.fetch)
5758
}),
5859
)
5960
setStore("status", reconcile(results))
@@ -84,7 +85,7 @@ export function WelcomeScreen(props: WelcomeScreenProps) {
8485
if (persist) {
8586
server.add(normalized)
8687
} else {
87-
server.setActive(normalized)
88+
server.setActive(ServerConnection.Key.make(normalized))
8889
}
8990
props.onRetry?.()
9091
}
@@ -177,32 +178,35 @@ export function WelcomeScreen(props: WelcomeScreenProps) {
177178
<h2 class="text-sm font-medium text-text-strong">Saved Servers</h2>
178179
<div class="flex flex-col gap-2">
179180
<For each={items()}>
180-
{(url) => (
181-
<button
182-
type="button"
183-
class="flex items-center gap-3 p-2 rounded hover:bg-background-base transition-colors text-left"
184-
onClick={() => handleConnect(url)}
185-
disabled={store.status[url]?.healthy === false}
186-
>
187-
<div
188-
classList={{
189-
"size-2 rounded-full shrink-0": true,
190-
"bg-icon-success-base": store.status[url]?.healthy === true,
191-
"bg-icon-critical-base": store.status[url]?.healthy === false,
192-
"bg-border-weak-base": store.status[url] === undefined,
193-
}}
194-
/>
195-
<span
196-
class="truncate text-sm"
197-
classList={{ "text-text-weak": store.status[url]?.healthy === false }}
181+
{(conn) => {
182+
const key = ServerConnection.key(conn)
183+
return (
184+
<button
185+
type="button"
186+
class="flex items-center gap-3 p-2 rounded hover:bg-background-base transition-colors text-left"
187+
onClick={() => handleConnect(conn.http.url)}
188+
disabled={store.status[key]?.healthy === false}
198189
>
199-
{serverDisplayName(url)}
200-
</span>
201-
<Show when={store.status[url]?.version}>
202-
<span class="text-xs text-text-weak ml-auto">{store.status[url]?.version}</span>
203-
</Show>
204-
</button>
205-
)}
190+
<div
191+
classList={{
192+
"size-2 rounded-full shrink-0": true,
193+
"bg-icon-success-base": store.status[key]?.healthy === true,
194+
"bg-icon-critical-base": store.status[key]?.healthy === false,
195+
"bg-border-weak-base": store.status[key] === undefined,
196+
}}
197+
/>
198+
<span
199+
class="truncate text-sm"
200+
classList={{ "text-text-weak": store.status[key]?.healthy === false }}
201+
>
202+
{serverDisplayName(conn)}
203+
</span>
204+
<Show when={store.status[key]?.version}>
205+
<span class="text-xs text-text-weak ml-auto">{store.status[key]?.version}</span>
206+
</Show>
207+
</button>
208+
)
209+
}}
206210
</For>
207211
</div>
208212
</div>

packages/app/src/context/global-sync.tsx

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -354,54 +354,6 @@ function createGlobalSync() {
354354
return
355355
}
356356

357-
return Promise.all([
358-
retry(() =>
359-
globalSDK.client.path.get().then((x) => {
360-
setGlobalStore("path", x.data!)
361-
}),
362-
),
363-
retry(() =>
364-
globalSDK.client.global.config.get().then((x) => {
365-
setGlobalStore("config", x.data!)
366-
}),
367-
),
368-
retry(() =>
369-
globalSDK.client.project.list().then(async (x) => {
370-
const data = Array.isArray(x.data) ? x.data : []
371-
const projects = data
372-
.filter((p) => !!p?.id)
373-
.filter((p) => !!p.worktree && !p.worktree.includes("opencode-test"))
374-
.slice()
375-
.sort((a, b) => cmp(a.id, b.id))
376-
setGlobalStore("project", projects)
377-
}),
378-
),
379-
retry(() =>
380-
globalSDK.client.provider.list().then((x) => {
381-
setGlobalStore("provider", normalizeProviderList(x.data!))
382-
}),
383-
),
384-
retry(() =>
385-
globalSDK.client.provider.auth().then((x) => {
386-
setGlobalStore("provider_auth", x.data ?? {})
387-
}),
388-
),
389-
])
390-
.then(() => {
391-
setGlobalStore("ready", true)
392-
setGlobalStore("connectionState", "ready")
393-
})
394-
.catch((e) => {
395-
setGlobalStore("error", e)
396-
setGlobalStore("connectionState", "error")
397-
})
398-
}
399-
// For non-hosted environments, show the error page
400-
setGlobalStore("error", new Error(language.t("error.globalSync.connectFailed", { url: globalSDK.url })))
401-
setGlobalStore("connectionState", "error")
402-
return
403-
}
404-
405357
return Promise.all([
406358
retry(() =>
407359
globalSDK.client.path.get().then((x) => {

packages/app/src/entry.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ const platform: Platform = {
113113
const defaultUrl = iife(() => {
114114
const lsDefault = readDefaultServerUrl()
115115
if (lsDefault) return lsDefault
116-
if (location.hostname.includes("opencode.ai")) return "http://localhost:4096"
116+
if (location.hostname.includes("opencode.ai") || location.hostname.includes("shuv.ai")) return "http://localhost:4096"
117+
// Desktop app (Tauri) with injected port
118+
if (window.__SHUVCODE__?.port) return `http://127.0.0.1:${window.__SHUVCODE__.port}`
117119
if (import.meta.env.DEV)
118120
return `http://${import.meta.env.VITE_OPENCODE_SERVER_HOST ?? "localhost"}:${import.meta.env.VITE_OPENCODE_SERVER_PORT ?? "4096"}`
119121
return location.origin

packages/app/src/pages/session.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ import { createStore } from "solid-js/store"
77
import { ResizeHandle } from "@opencode-ai/ui/resize-handle"
88
import { Select } from "@opencode-ai/ui/select"
99
import { createAutoScroll } from "@opencode-ai/ui/hooks"
10-
import { SessionReview } from "@opencode-ai/ui/session-review"
1110
import { AsciiMark } from "@opencode-ai/ui/logo"
12-
import { QuestionDock } from "@/components/question-dock"
1311
import { LineComment as LineCommentView, LineCommentEditor } from "@opencode-ai/ui/line-comment"
1412
import { decode64 } from "@/utils/base64"
1513

packages/opencode/src/cli/cmd/tui/routes/session/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ export function Session() {
160160
const [showAssistantMetadata, setShowAssistantMetadata] = kv.signal("assistant_metadata_visibility", true)
161161
const [showScrollbar, setShowScrollbar] = kv.signal("scrollbar_visible", false)
162162
const [showHeader, setShowHeader] = kv.signal("header_visible", true)
163-
const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word")
163+
const [diffWrapMode, setDiffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word")
164164
const [animationsEnabled, setAnimationsEnabled] = kv.signal("animations_enabled", true)
165165
const [headerVisible, setHeaderVisible] = kv.signal("header_visible", true)
166166
const [draggingSidebar, setDraggingSidebar] = createSignal(false)

packages/opencode/src/file/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export namespace File {
4343

4444
export const Content = z
4545
.object({
46-
type: z.literal("text"),
46+
type: z.enum(["text", "binary"]),
4747
content: z.string(),
4848
diff: z.string().optional(),
4949
patch: z

packages/opencode/src/project/project.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { BusEvent } from "@/bus/bus-event"
1313
import { iife } from "@/util/iife"
1414
import { GlobalBus } from "@/bus/global"
1515
import { existsSync } from "fs"
16+
import fs from "fs/promises"
17+
import { $ } from "bun"
1618
import { git } from "../util/git"
1719
import { Glob } from "../util/glob"
1820

0 commit comments

Comments
 (0)