Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 7 additions & 9 deletions packages/app/e2e/regression/review-state-persistence.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async function switchSession(page: Page, title: string) {

async function setup(page: Page) {
await mockOpenCodeServer(page, {
protocol: "v2",
protocol: "v1",
directory,
project: {
id: projectID,
Expand Down Expand Up @@ -93,20 +93,18 @@ async function setup(page: Page) {
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({ location: { directory }, data: { branch: "feature", defaultBranch: "dev" } }),
body: JSON.stringify({ branch: "feature", default_branch: "dev" }),
}),
)
await page.route("**/vcs/diff**", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
location: { directory },
data:
new URL(route.request().url()).searchParams.get("mode") === "branch"
? [diff("src/alpha.ts"), diff("src/beta.ts")]
: [diff("src/alpha.ts"), diff("src/gamma.ts")],
}),
body: JSON.stringify(
new URL(route.request().url()).searchParams.get("mode") === "branch"
? [diff("src/alpha.ts"), diff("src/beta.ts")]
: [diff("src/alpha.ts"), diff("src/gamma.ts")],
),
}),
)
await page.addInitScript(
Expand Down
46 changes: 22 additions & 24 deletions packages/app/e2e/regression/review-terminal-stacked.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
let detailFailures = 1
await page.setViewportSize({ width: 1400, height: 900 })
await mockOpenCodeServer(page, {
protocol: "v2",
protocol: "v1",
directory,
project: {
id: projectID,
Expand Down Expand Up @@ -67,33 +67,31 @@ test("keeps the review tree and terminal sized when both panels are open", async
status: 200,
contentType: "application/json",
body: JSON.stringify({
location: { directory },
data: { branch: "review-pane-performance", defaultBranch: "dev" },
branch: "review-pane-performance",
default_branch: "dev",
}),
}),
)
await page.route("**/api/vcs/diff**", (route) => {
await page.route("**/vcs/diff**", (route) => {
const url = new URL(route.request().url())
const scope = url.searchParams.get("location[directory]")?.replaceAll("\\", "/")
const scope = url.searchParams.get("directory")?.replaceAll("\\", "/")
const detail = scope?.endsWith("/src/branch/d00027")
if (detail && detailFailures-- > 0) return route.fulfill({ status: 500, body: "retry detail" })
return route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
location: { directory: scope ?? directory, project: { id: projectID, directory } },
data:
url.searchParams.get("mode") === "branch"
? detail
? branchDiffs
.filter((diff) => diff.file.startsWith("src/branch/d00027/"))
.map((diff) => fileDiff(diff.file, diff.additions, true, detailVersion))
: branchDiffs
: Array.from({ length: 7 }, (_, index) => fileDiff(`src/git-${index}.ts`, 1)),
}),
body: JSON.stringify(
url.searchParams.get("mode") === "branch"
? detail
? branchDiffs
.filter((diff) => diff.file.startsWith("src/branch/d00027/"))
.map((diff) => fileDiff(diff.file, diff.additions, true, detailVersion))
: branchDiffs
: Array.from({ length: 7 }, (_, index) => fileDiff(`src/git-${index}.ts`, 1)),
),
})
})
await page.route("**/api/pty*", (route) =>
await page.route("**/pty*", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
Expand All @@ -111,7 +109,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
}),
}),
)
await page.route("**/api/pty/pty_review_terminal*", (route) =>
await page.route("**/pty/pty_review_terminal*", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
Expand All @@ -129,7 +127,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
}),
}),
)
await page.route("**/api/pty/pty_review_terminal/connect-token*", (route) =>
await page.route("**/pty/pty_review_terminal/connect-token*", (route) =>
route.fulfill({
status: 200,
contentType: "application/json",
Expand All @@ -139,7 +137,7 @@ test("keeps the review tree and terminal sized when both panels are open", async
}),
}),
)
await page.routeWebSocket("**/api/pty/pty_review_terminal/connect", () => undefined)
await page.routeWebSocket("**/pty/pty_review_terminal/connect", () => undefined)
await page.addInitScript(() => {
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))
localStorage.setItem(
Expand Down Expand Up @@ -177,8 +175,8 @@ test("keeps the review tree and terminal sized when both panels are open", async
const lazyDiff = page.waitForRequest((request) => {
const url = new URL(request.url())
return (
url.pathname === "/api/vcs/diff" &&
url.searchParams.get("location[directory]")?.replaceAll("\\", "/").endsWith("/src/branch/d00027") === true
url.pathname === "/vcs/diff" &&
url.searchParams.get("directory")?.replaceAll("\\", "/").endsWith("/src/branch/d00027") === true
)
})
await lastFile.click()
Expand All @@ -192,8 +190,8 @@ test("keeps the review tree and terminal sized when both panels are open", async
const refreshedDiff = page.waitForRequest((request) => {
const url = new URL(request.url())
return (
url.pathname === "/api/vcs/diff" &&
url.searchParams.get("location[directory]")?.replaceAll("\\", "/").endsWith("/src/branch/d00027") === true
url.pathname === "/vcs/diff" &&
url.searchParams.get("directory")?.replaceAll("\\", "/").endsWith("/src/branch/d00027") === true
)
})
sessionStatus[sessionID] = { type: "idle" }
Expand Down
2 changes: 1 addition & 1 deletion packages/app/e2e/regression/terminal-tab-switch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ test("keeps the terminal session alive when switching session tabs in a workspac
const connection = new URL(connections[0]!)
expect(connection.pathname).toBe(`/api/pty/${ptyID}/connect`)
expect(connection.searchParams.get("location[directory]")).toBe(directory)
expect(connection.searchParams.get("ticket")).toBe("e2e-ticket")
expect(connection.searchParams.get("ticket")).toBeNull()
await writeProbe(page)

await switchTab(page, titleB)
Expand Down
2 changes: 1 addition & 1 deletion packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@dnd-kit/helpers": "0.5.0",
"@dnd-kit/solid": "0.5.0",
"@kobalte/core": "catalog:",
"@opencode-ai/client": "file:vendor/opencode-ai-client-1.17.13.tgz",
"@opencode-ai/client": "file:vendor/opencode-ai-client-1.17.13-v2.tgz",
"@opencode-ai/core": "workspace:*",
"@opencode-ai/schema": "workspace:*",
"@opencode-ai/sdk": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { createEffect, createMemo, createResource, createSignal, For, onCleanup,
import { useGlobal } from "@/context/global"
import { useLanguage } from "@/context/language"
import { ServerConnection } from "@/context/server"
import type { Path } from "@opencode-ai/sdk/v2/client"
import {
absoluteTreePath,
activeTreeNavigation,
Expand Down Expand Up @@ -68,7 +69,13 @@ export function DialogSelectDirectoryV2(props: DialogSelectDirectoryV2Props) {
const missingBase = createMemo(() => !(sync.data.path.home || sync.data.path.directory))
const [fallbackPath] = createResource(
() => (missingBase() ? true : undefined),
() => sdk.api.path.get().catch(() => undefined),
async (): Promise<Path | undefined> => {
if ((await sdk.protocol) !== "v1") return
return sdk.client.path
.get()
.then((result) => result.data)
.catch(() => undefined)
},
{ initialValue: undefined },
)
const home = createMemo(() => sync.data.path.home || fallbackPath()?.home || "")
Expand Down
9 changes: 7 additions & 2 deletions packages/app/src/components/dialog-select-directory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useLanguage } from "@/context/language"
import { ServerConnection } from "@/context/server"
import { useGlobal } from "@/context/global"
import { cleanPickerInput, createDirectorySearch, displayPickerPath } from "./directory-picker-domain"
import type { Path } from "@opencode-ai/sdk/v2/client"

interface DialogSelectDirectoryProps {
title?: string
Expand Down Expand Up @@ -59,8 +60,12 @@ export function DialogSelectDirectory(props: DialogSelectDirectoryProps) {
const missingBase = createMemo(() => !(sync.data.path.home || sync.data.path.directory))
const [fallbackPath] = createResource(
() => (missingBase() ? true : undefined),
async () => {
return sdk.api.path.get().catch(() => undefined)
async (): Promise<Path | undefined> => {
if ((await sdk.protocol) !== "v1") return
return sdk.client.path
.get()
.then((result) => result.data)
.catch(() => undefined)
},
{ initialValue: undefined },
)
Expand Down
23 changes: 17 additions & 6 deletions packages/app/src/components/edit-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,23 @@ export function createEditProjectModel(props: { project: LocalProject; server: S
const start = store.startup.trim()

if (props.project.id && props.project.id !== "global") {
const project = await serverCtx().sdk.api.project.update({
projectID: props.project.id,
name,
icon: { color: store.color || "", override: store.iconOverride || "" },
commands: { start },
})
if ((await serverCtx().sdk.protocol) !== "v1") return
const project = await serverCtx()
.sdk.client.project.update({
projectID: props.project.id,
directory: props.project.worktree,
name,
icon: { color: store.color || "", override: store.iconOverride || "" },
commands: { start },
})
.then((result) => result.data)
if (!project) return
// const project = await serverCtx().sdk.api.project.update({
// projectID: props.project.id,
// name,
// icon: { color: store.color || "", override: store.iconOverride || "" },
// commands: { start },
// })
serverCtx().sync.set("project", (items) =>
items.map((item) => (item.id === project.id ? normalizeProjectInfo(project) : item)),
)
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/prompt-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
title: cmd.name,
description: cmd.description,
type: "custom" as const,
source: cmd.source,
// source: cmd.source,
}))

return [...custom, ...builtin]
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/components/settings-general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ export const SettingsGeneral: Component = () => {
if ((await sdk.protocol) === "v1") {
return (await sdk.client.pty.shells()).data ?? []
}
return (await sdk.api.pty.shells()).data
// return (await sdk.api.pty.shells()).data
return [] as ShellOption[]
},
{ initialValue: [] as ShellOption[] },
)
Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/components/settings-v2/general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ export const SettingsGeneralV2: Component<{
if ((await sdk.protocol) === "v1") {
return (await sdk.client.pty.shells()).data ?? []
}
return (await sdk.api.pty.shells()).data
// return (await sdk.api.pty.shells()).data
return [] as ShellOption[]
},
{ initialValue: [] as ShellOption[] },
)
Expand Down
22 changes: 8 additions & 14 deletions packages/app/src/components/terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -573,19 +573,13 @@ export const Terminal = (props: TerminalProps) => {
throw new Error("PTY connect ticket rejected by origin or CSRF checks. Check the server CORS config.")
throw new Error(`PTY connect ticket failed with ${result.response.status}`)
}
return sdk()
.api.pty.connectToken({
ptyID: id,
location: { directory },
"x-opencode-ticket": "1",
})
.then((result) => result.data.ticket)
.catch((err: unknown) => {
if (err && typeof err === "object" && "_tag" in err && err._tag === "ForbiddenError") {
throw new Error("PTY connect ticket rejected by origin or CSRF checks. Check the server CORS config.")
}
throw err
})
// return sdk()
// .api.pty.connectToken({
// ptyID: id,
// location: { directory },
// "x-opencode-ticket": "1",
// })
// .then((result) => result.data.ticket)
}

const retry = (err: unknown) => {
Expand Down Expand Up @@ -616,7 +610,7 @@ export const Terminal = (props: TerminalProps) => {
return undefined
})
const protocol = await sdk().protocol
if (protocol === "v2" && !ticket) return
// if (protocol === "v2" && !ticket) return
if (once.value) return
if (disposed) return

Expand Down
3 changes: 2 additions & 1 deletion packages/app/src/context/directory-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ export const createDirSyncContext = (
},
more: createMemo(() => current()[0].session.length >= current()[0].limit),
archive: async (sessionID: string) => {
await serverSDK.api.session.archive({ sessionID, directory })
if ((await serverSDK.protocol) !== "v1") return
await serverSDK.client.session.update({ sessionID, directory, time: { archived: Date.now() } })
current()[1](
"session",
produce((draft) => {
Expand Down
8 changes: 5 additions & 3 deletions packages/app/src/context/global-sync/bootstrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, expect, test } from "bun:test"
import { createStore } from "solid-js/store"
import { QueryClient } from "@tanstack/solid-query"
import type { Config, OpencodeClient, Project } from "@opencode-ai/sdk/v2/client"
import type { AgentApi, CatalogApi, CommandApi, ProjectApi, ReferenceApi } from "@opencode-ai/client/promise"
import type { AgentApi, CatalogApi, CommandApi, ReferenceApi } from "@opencode-ai/client/promise"
import type { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
import {
bootstrapDirectory,
Expand All @@ -17,6 +17,8 @@ import type { State, VcsCache } from "./types"
import { ServerScope } from "@/utils/server-scope"
import type { ServerApi } from "@/utils/server"

type ProjectApi = ServerApi["project"]

const provider = { all: new Map(), connected: [], default: {} } satisfies NormalizedProviderListResponse
const api = {
agent: { list: async () => ({ location: {}, data: [] }) },
Expand Down Expand Up @@ -200,15 +202,15 @@ describe("query keys", () => {
calls.push(input)
return {
location: {},
data: [{ name: "review", template: "Review files", source: "command" as const }],
data: [{ name: "review", template: "Review files" /* source: "command" as const */ }],
}
},
} as unknown as CommandApi

const result = await loadCommands("/repo", api)

expect(calls).toEqual([{ location: { directory: "/repo" } }])
expect(result).toEqual([{ name: "review", template: "Review files", source: "command" }])
expect(result).toEqual([{ name: "review", template: "Review files" /* source: "command" */ }])
})

test("loads projects from the current endpoint", async () => {
Expand Down
Loading
Loading