From 4466619497f01424d9d9d4547f2a5215a160fc62 Mon Sep 17 00:00:00 2001 From: jorge guerrero Date: Thu, 19 Mar 2026 12:13:56 -0400 Subject: [PATCH 1/4] fix: stabilize prompt agent and skill ordering --- packages/opencode/src/agent/agent.ts | 5 +- packages/opencode/src/session/system.ts | 2 +- packages/opencode/src/tool/skill.ts | 2 +- packages/opencode/src/tool/task.ts | 7 ++- packages/opencode/test/agent/agent.test.ts | 26 ++++++++ packages/opencode/test/session/system.test.ts | 59 +++++++++++++++++++ packages/opencode/test/tool/skill.test.ts | 50 ++++++++++++++++ packages/opencode/test/tool/task.test.ts | 45 ++++++++++++++ 8 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 packages/opencode/test/session/system.test.ts create mode 100644 packages/opencode/test/tool/task.test.ts diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index b2dae0402ca3..e30d05e9350a 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -260,7 +260,10 @@ export namespace Agent { return pipe( await state(), values(), - sortBy([(x) => (cfg.default_agent ? x.name === cfg.default_agent : x.name === "build"), "desc"]), + sortBy( + [(x) => (cfg.default_agent ? x.name === cfg.default_agent : x.name === "build"), "desc"], + [(x) => x.name, "asc"], + ), ) } diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index 63230e6426c4..bcbf69349892 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -59,7 +59,7 @@ export namespace SystemPrompt { export async function skills(agent: Agent.Info) { if (PermissionNext.disabled(["skill"], agent.permission).has("skill")) return - const list = await Skill.available(agent) + const list = await Skill.available(agent).then((x) => x.toSorted((a, b) => a.name.localeCompare(b.name))) return [ "Skills provide specialized instructions and workflows for specific tasks.", diff --git a/packages/opencode/src/tool/skill.ts b/packages/opencode/src/tool/skill.ts index 17016b06f807..a9edea99301d 100644 --- a/packages/opencode/src/tool/skill.ts +++ b/packages/opencode/src/tool/skill.ts @@ -7,7 +7,7 @@ import { Ripgrep } from "../file/ripgrep" import { iife } from "@/util/iife" export const SkillTool = Tool.define("skill", async (ctx) => { - const list = await Skill.available(ctx?.agent) + const list = await Skill.available(ctx?.agent).then((x) => x.toSorted((a, b) => a.name.localeCompare(b.name))) const description = list.length === 0 diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 14ecea107589..ad2b41f002ca 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -33,12 +33,13 @@ export const TaskTool = Tool.define("task", async (ctx) => { const accessibleAgents = caller ? agents.filter((a) => PermissionNext.evaluate("task", a.name, caller.permission).action !== "deny") : agents + const list = accessibleAgents.toSorted((a, b) => a.name.localeCompare(b.name)) const description = DESCRIPTION.replace( "{agents}", - accessibleAgents - .map((a) => `- ${a.name}: ${a.description ?? "This subagent should only be called manually by the user."}`) - .join("\n"), + list.map((a) => `- ${a.name}: ${a.description ?? "This subagent should only be called manually by the user."}`).join( + "\n", + ), ) return { description, diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts index d6b6ebb33bc9..60c8e57c9260 100644 --- a/packages/opencode/test/agent/agent.test.ts +++ b/packages/opencode/test/agent/agent.test.ts @@ -384,6 +384,32 @@ test("multiple custom agents can be defined", async () => { }) }) +test("Agent.list keeps the default agent first and sorts the rest by name", async () => { + await using tmp = await tmpdir({ + config: { + default_agent: "plan", + agent: { + zebra: { + description: "Zebra", + mode: "subagent", + }, + alpha: { + description: "Alpha", + mode: "subagent", + }, + }, + }, + }) + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const names = (await Agent.list()).map((a) => a.name) + expect(names[0]).toBe("plan") + expect(names.slice(1)).toEqual(names.slice(1).toSorted((a, b) => a.localeCompare(b))) + }, + }) +}) + test("Agent.get returns undefined for non-existent agent", async () => { await using tmp = await tmpdir() await Instance.provide({ diff --git a/packages/opencode/test/session/system.test.ts b/packages/opencode/test/session/system.test.ts new file mode 100644 index 000000000000..47f5f6fc25dd --- /dev/null +++ b/packages/opencode/test/session/system.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, test } from "bun:test" +import path from "path" +import { Agent } from "../../src/agent/agent" +import { Instance } from "../../src/project/instance" +import { SystemPrompt } from "../../src/session/system" +import { tmpdir } from "../fixture/fixture" + +describe("session.system", () => { + test("skills output is sorted by name and stable across calls", async () => { + await using tmp = await tmpdir({ + git: true, + init: async (dir) => { + for (const [name, description] of [ + ["zeta-skill", "Zeta skill."], + ["alpha-skill", "Alpha skill."], + ["middle-skill", "Middle skill."], + ]) { + const skillDir = path.join(dir, ".opencode", "skill", name) + await Bun.write( + path.join(skillDir, "SKILL.md"), + `--- +name: ${name} +description: ${description} +--- + +# ${name} +`, + ) + } + }, + }) + + const home = process.env.OPENCODE_TEST_HOME + process.env.OPENCODE_TEST_HOME = tmp.path + + try { + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const build = await Agent.get("build") + const first = await SystemPrompt.skills(build!) + const second = await SystemPrompt.skills(build!) + + expect(first).toBe(second) + + const alpha = first!.indexOf("alpha-skill") + const middle = first!.indexOf("middle-skill") + const zeta = first!.indexOf("zeta-skill") + + expect(alpha).toBeGreaterThan(-1) + expect(middle).toBeGreaterThan(alpha) + expect(zeta).toBeGreaterThan(middle) + }, + }) + } finally { + process.env.OPENCODE_TEST_HOME = home + } + }) +}) diff --git a/packages/opencode/test/tool/skill.test.ts b/packages/opencode/test/tool/skill.test.ts index 7cfaee1353a5..f622341d3330 100644 --- a/packages/opencode/test/tool/skill.test.ts +++ b/packages/opencode/test/tool/skill.test.ts @@ -54,6 +54,56 @@ description: Skill for tool tests. } }) + test("description sorts skills by name and is stable across calls", async () => { + await using tmp = await tmpdir({ + git: true, + init: async (dir) => { + for (const [name, description] of [ + ["zeta-skill", "Zeta skill."], + ["alpha-skill", "Alpha skill."], + ["middle-skill", "Middle skill."], + ]) { + const skillDir = path.join(dir, ".opencode", "skill", name) + await Bun.write( + path.join(skillDir, "SKILL.md"), + `--- +name: ${name} +description: ${description} +--- + +# ${name} +`, + ) + } + }, + }) + + const home = process.env.OPENCODE_TEST_HOME + process.env.OPENCODE_TEST_HOME = tmp.path + + try { + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const first = await SkillTool.init() + const second = await SkillTool.init() + + expect(first.description).toBe(second.description) + + const alpha = first.description.indexOf("**alpha-skill**: Alpha skill.") + const middle = first.description.indexOf("**middle-skill**: Middle skill.") + const zeta = first.description.indexOf("**zeta-skill**: Zeta skill.") + + expect(alpha).toBeGreaterThan(-1) + expect(middle).toBeGreaterThan(alpha) + expect(zeta).toBeGreaterThan(middle) + }, + }) + } finally { + process.env.OPENCODE_TEST_HOME = home + } + }) + test("execute returns skill content block with files", async () => { await using tmp = await tmpdir({ git: true, diff --git a/packages/opencode/test/tool/task.test.ts b/packages/opencode/test/tool/task.test.ts new file mode 100644 index 000000000000..df319d8de1e5 --- /dev/null +++ b/packages/opencode/test/tool/task.test.ts @@ -0,0 +1,45 @@ +import { describe, expect, test } from "bun:test" +import { Agent } from "../../src/agent/agent" +import { Instance } from "../../src/project/instance" +import { TaskTool } from "../../src/tool/task" +import { tmpdir } from "../fixture/fixture" + +describe("tool.task", () => { + test("description sorts subagents by name and is stable across calls", async () => { + await using tmp = await tmpdir({ + config: { + agent: { + zebra: { + description: "Zebra agent", + mode: "subagent", + }, + alpha: { + description: "Alpha agent", + mode: "subagent", + }, + }, + }, + }) + + await Instance.provide({ + directory: tmp.path, + fn: async () => { + const build = await Agent.get("build") + const first = await TaskTool.init({ agent: build }) + const second = await TaskTool.init({ agent: build }) + + expect(first.description).toBe(second.description) + + const alpha = first.description.indexOf("- alpha: Alpha agent") + const explore = first.description.indexOf("- explore:") + const general = first.description.indexOf("- general:") + const zebra = first.description.indexOf("- zebra: Zebra agent") + + expect(alpha).toBeGreaterThan(-1) + expect(explore).toBeGreaterThan(alpha) + expect(general).toBeGreaterThan(explore) + expect(zebra).toBeGreaterThan(general) + }, + }) + }) +}) From 0f190d017d240bcdafced48ccc889fa3a8770ec0 Mon Sep 17 00:00:00 2001 From: jorge guerrero Date: Thu, 19 Mar 2026 15:13:11 -0400 Subject: [PATCH 2/4] fix: stabilize workspace e2e path assertions --- .../projects/workspace-new-session.spec.ts | 42 +++++++++++-------- packages/app/e2e/projects/workspaces.spec.ts | 13 +++--- packages/app/e2e/utils.ts | 6 ++- 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/packages/app/e2e/projects/workspace-new-session.spec.ts b/packages/app/e2e/projects/workspace-new-session.spec.ts index 18fa46d3299c..b4b44a468d45 100644 --- a/packages/app/e2e/projects/workspace-new-session.spec.ts +++ b/packages/app/e2e/projects/workspace-new-session.spec.ts @@ -1,9 +1,8 @@ -import { base64Decode } from "@opencode-ai/util/encode" import type { Page } from "@playwright/test" import { test, expect } from "../fixtures" import { openSidebar, sessionIDFromUrl, setWorkspacesEnabled, slugFromUrl, waitSlug } from "../actions" import { promptSelector, workspaceItemSelector, workspaceNewSessionSelector } from "../selectors" -import { createSdk } from "../utils" +import { createSdk, dirDecode, dirSlug, resolveDirectory } from "../utils" async function waitWorkspaceReady(page: Page, slug: string) { await openSidebar(page) @@ -27,19 +26,20 @@ async function createWorkspace(page: Page, root: string, seen: string[]) { await openSidebar(page) await page.getByRole("button", { name: "New workspace" }).first().click() - const slug = await waitSlug(page, [root, ...seen]) - const directory = base64Decode(slug) - if (!directory) throw new Error(`Failed to decode workspace slug: ${slug}`) - return { slug, directory } + const raw = await waitSlug(page, [root, ...seen]) + const directory = dirDecode(raw) + if (!directory) throw new Error(`Failed to decode workspace slug: ${raw}`) + const space = await resolveDirectory(directory) + return { slug: dirSlug(space), directory: space, raw } } -async function openWorkspaceNewSession(page: Page, slug: string) { +async function openWorkspaceNewSession(page: Page, slug: string, raw = slug) { await waitWorkspaceReady(page, slug) - const item = page.locator(workspaceItemSelector(slug)).first() + const item = page.locator(`${workspaceItemSelector(slug)}, ${workspaceItemSelector(raw)}`).first() await item.hover() - const button = page.locator(workspaceNewSessionSelector(slug)).first() + const button = page.locator(`${workspaceNewSessionSelector(slug)}, ${workspaceNewSessionSelector(raw)}`).first() await expect(button).toBeVisible() await button.click({ force: true }) @@ -48,8 +48,16 @@ async function openWorkspaceNewSession(page: Page, slug: string) { return next } -async function createSessionFromWorkspace(page: Page, slug: string, text: string) { - const next = await openWorkspaceNewSession(page, slug) +async function createSessionFromWorkspace( + page: Page, + workspace: { slug: string; raw?: string }, + text: string, +) { + const next = await openWorkspaceNewSession(page, workspace.slug, workspace.raw) + const directory = dirDecode(next) + if (!directory) throw new Error(`Failed to decode workspace slug: ${next}`) + const space = await resolveDirectory(directory) + const target = dirSlug(space) const prompt = page.locator(promptSelector) await expect(prompt).toBeVisible() @@ -60,13 +68,13 @@ async function createSessionFromWorkspace(page: Page, slug: string, text: string await expect.poll(async () => ((await prompt.textContent()) ?? "").trim()).toContain(text) await prompt.press("Enter") - await expect.poll(() => slugFromUrl(page.url())).toBe(next) + await expect.poll(() => slugFromUrl(page.url())).toBe(target) await expect.poll(() => sessionIDFromUrl(page.url()) ?? "", { timeout: 30_000 }).not.toBe("") const sessionID = sessionIDFromUrl(page.url()) if (!sessionID) throw new Error(`Failed to parse session id from url: ${page.url()}`) - await expect(page).toHaveURL(new RegExp(`/${next}/session/${sessionID}(?:[/?#]|$)`)) - return { sessionID, slug: next } + await expect(page).toHaveURL(new RegExp(`/${target}/session/${sessionID}(?:[/?#]|$)`)) + return { sessionID, slug: target } } async function sessionDirectory(directory: string, sessionID: string) { @@ -93,13 +101,13 @@ test("new sessions from sidebar workspace actions stay in selected workspace", a trackDirectory(second.directory) await waitWorkspaceReady(page, second.slug) - const firstSession = await createSessionFromWorkspace(page, first.slug, `workspace one ${Date.now()}`) + const firstSession = await createSessionFromWorkspace(page, first, `workspace one ${Date.now()}`) trackSession(firstSession.sessionID, first.directory) - const secondSession = await createSessionFromWorkspace(page, second.slug, `workspace two ${Date.now()}`) + const secondSession = await createSessionFromWorkspace(page, second, `workspace two ${Date.now()}`) trackSession(secondSession.sessionID, second.directory) - const thirdSession = await createSessionFromWorkspace(page, first.slug, `workspace one again ${Date.now()}`) + const thirdSession = await createSessionFromWorkspace(page, first, `workspace one again ${Date.now()}`) trackSession(thirdSession.sessionID, first.directory) await expect.poll(() => sessionDirectory(first.directory, firstSession.sessionID)).toBe(first.directory) diff --git a/packages/app/e2e/projects/workspaces.spec.ts b/packages/app/e2e/projects/workspaces.spec.ts index aeeccb9bba9a..0380079cb22f 100644 --- a/packages/app/e2e/projects/workspaces.spec.ts +++ b/packages/app/e2e/projects/workspaces.spec.ts @@ -1,4 +1,3 @@ -import { base64Decode } from "@opencode-ai/util/encode" import fs from "node:fs/promises" import os from "node:os" import path from "node:path" @@ -18,7 +17,7 @@ import { waitSlug, } from "../actions" import { dropdownMenuContentSelector, inlineInputSelector, workspaceItemSelector } from "../selectors" -import { createSdk, dirSlug } from "../utils" +import { createSdk, dirDecode, dirSlug } from "../utils" async function setupWorkspaceTest(page: Page, project: { slug: string }) { const rootSlug = project.slug @@ -28,7 +27,7 @@ async function setupWorkspaceTest(page: Page, project: { slug: string }) { await page.getByRole("button", { name: "New workspace" }).first().click() const slug = await waitSlug(page, [rootSlug]) - const dir = base64Decode(slug) + const dir = dirDecode(slug) await openSidebar(page) @@ -80,7 +79,7 @@ test("can create a workspace", async ({ page, withProject }) => { await page.getByRole("button", { name: "New workspace" }).first().click() const workspaceSlug = await waitSlug(page, [slug]) - const workspaceDir = base64Decode(workspaceSlug) + const workspaceDir = dirDecode(workspaceSlug) await openSidebar(page) @@ -119,7 +118,7 @@ test("non-git projects keep workspace mode disabled", async ({ page, withProject await expect.poll(() => slugFromUrl(page.url()), { timeout: 30_000 }).not.toBe("") - const activeDir = base64Decode(slugFromUrl(page.url())) + const activeDir = dirDecode(slugFromUrl(page.url())) expect(path.basename(activeDir)).toContain("opencode-e2e-project-nongit-") await openSidebar(page) @@ -256,7 +255,7 @@ test("can delete a workspace", async ({ page, withProject }) => { await clickMenuItem(menu, /^Delete$/i, { force: true }) await confirmDialog(page, /^Delete workspace$/i) - await expect.poll(() => base64Decode(slugFromUrl(page.url()))).toBe(project.directory) + await expect.poll(() => dirDecode(slugFromUrl(page.url()))).toBe(project.directory) await expect .poll( @@ -332,7 +331,7 @@ test("can reorder workspaces by drag and drop", async ({ page, withProject }) => const prev = slugFromUrl(page.url()) await page.getByRole("button", { name: "New workspace" }).first().click() const slug = await waitSlug(page, [rootSlug, prev]) - const dir = base64Decode(slug) + const dir = dirDecode(slug) workspaces.push({ slug, directory: dir }) await openSidebar(page) diff --git a/packages/app/e2e/utils.ts b/packages/app/e2e/utils.ts index f07a8d3f1116..f2c3919f5c5d 100644 --- a/packages/app/e2e/utils.ts +++ b/packages/app/e2e/utils.ts @@ -1,5 +1,5 @@ import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" -import { base64Encode, checksum } from "@opencode-ai/util/encode" +import { base64Decode, base64Encode, checksum } from "@opencode-ai/util/encode" export const serverHost = process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1" export const serverPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096" @@ -48,6 +48,10 @@ export function dirSlug(directory: string) { return base64Encode(directory) } +export function dirDecode(slug: string) { + return base64Decode(slug) +} + export function dirPath(directory: string) { return `/${dirSlug(directory)}` } From 82b5f1fc5d567be938db4b0051fcd58e138c5437 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 19 Mar 2026 14:30:24 -0500 Subject: [PATCH 3/4] tweak: centralize skill sorting --- packages/opencode/src/session/system.ts | 2 +- packages/opencode/src/skill/skill.ts | 2 +- packages/opencode/src/tool/skill.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/opencode/src/session/system.ts b/packages/opencode/src/session/system.ts index bcbf69349892..63230e6426c4 100644 --- a/packages/opencode/src/session/system.ts +++ b/packages/opencode/src/session/system.ts @@ -59,7 +59,7 @@ export namespace SystemPrompt { export async function skills(agent: Agent.Info) { if (PermissionNext.disabled(["skill"], agent.permission).has("skill")) return - const list = await Skill.available(agent).then((x) => x.toSorted((a, b) => a.name.localeCompare(b.name))) + const list = await Skill.available(agent) return [ "Skills provide specialized instructions and workflows for specific tasks.", diff --git a/packages/opencode/src/skill/skill.ts b/packages/opencode/src/skill/skill.ts index d7aeb911f326..5339691a01b9 100644 --- a/packages/opencode/src/skill/skill.ts +++ b/packages/opencode/src/skill/skill.ts @@ -204,7 +204,7 @@ export namespace Skill { const available = Effect.fn("Skill.available")(function* (agent?: Agent.Info) { yield* Effect.promise(() => state.ensure()) - const list = Object.values(state.skills) + const list = Object.values(state.skills).toSorted((a, b) => a.name.localeCompare(b.name)) if (!agent) return list return list.filter((skill) => PermissionNext.evaluate("skill", skill.name, agent.permission).action !== "deny") }) diff --git a/packages/opencode/src/tool/skill.ts b/packages/opencode/src/tool/skill.ts index a9edea99301d..17016b06f807 100644 --- a/packages/opencode/src/tool/skill.ts +++ b/packages/opencode/src/tool/skill.ts @@ -7,7 +7,7 @@ import { Ripgrep } from "../file/ripgrep" import { iife } from "@/util/iife" export const SkillTool = Tool.define("skill", async (ctx) => { - const list = await Skill.available(ctx?.agent).then((x) => x.toSorted((a, b) => a.name.localeCompare(b.name))) + const list = await Skill.available(ctx?.agent) const description = list.length === 0 From c88e4a5b74aa410fbb7173b659bcc70e18eae4ac Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 19 Mar 2026 14:49:34 -0500 Subject: [PATCH 4/4] cleanup: minimize diff --- packages/app/e2e/projects/workspace-new-session.spec.ts | 8 ++++---- packages/app/e2e/projects/workspaces.spec.ts | 4 ++-- packages/app/e2e/utils.ts | 6 +----- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/packages/app/e2e/projects/workspace-new-session.spec.ts b/packages/app/e2e/projects/workspace-new-session.spec.ts index 31ba1098dff3..0858f26273c6 100644 --- a/packages/app/e2e/projects/workspace-new-session.spec.ts +++ b/packages/app/e2e/projects/workspace-new-session.spec.ts @@ -2,7 +2,7 @@ import type { Page } from "@playwright/test" import { test, expect } from "../fixtures" import { openSidebar, resolveSlug, sessionIDFromUrl, setWorkspacesEnabled, waitDir, waitSlug } from "../actions" import { promptSelector, workspaceItemSelector, workspaceNewSessionSelector } from "../selectors" -import { createSdk, dirDecode, dirSlug, resolveDirectory } from "../utils" +import { createSdk } from "../utils" function item(space: { slug: string; raw: string }) { return `${workspaceItemSelector(space.slug)}, ${workspaceItemSelector(space.raw)}` @@ -101,13 +101,13 @@ test("new sessions from sidebar workspace actions stay in selected workspace", a trackDirectory(second.directory) await waitWorkspaceReady(page, second) - const firstSession = await createSessionFromWorkspace(page, first, `workspace one ${Date.now()}`) + const firstSession = await createSessionFromWorkspace(page, first.slug, `workspace one ${Date.now()}`) trackSession(firstSession.sessionID, first.directory) - const secondSession = await createSessionFromWorkspace(page, second, `workspace two ${Date.now()}`) + const secondSession = await createSessionFromWorkspace(page, second.slug, `workspace two ${Date.now()}`) trackSession(secondSession.sessionID, second.directory) - const thirdSession = await createSessionFromWorkspace(page, first, `workspace one again ${Date.now()}`) + const thirdSession = await createSessionFromWorkspace(page, first.slug, `workspace one again ${Date.now()}`) trackSession(thirdSession.sessionID, first.directory) await expect.poll(() => sessionDirectory(first.directory, firstSession.sessionID)).toBe(first.directory) diff --git a/packages/app/e2e/projects/workspaces.spec.ts b/packages/app/e2e/projects/workspaces.spec.ts index 22f09bc33429..297cdb9fc969 100644 --- a/packages/app/e2e/projects/workspaces.spec.ts +++ b/packages/app/e2e/projects/workspaces.spec.ts @@ -20,7 +20,7 @@ import { waitSlug, } from "../actions" import { dropdownMenuContentSelector, inlineInputSelector, workspaceItemSelector } from "../selectors" -import { createSdk, dirDecode, dirSlug } from "../utils" +import { createSdk, dirSlug } from "../utils" async function setupWorkspaceTest(page: Page, project: { slug: string }) { const rootSlug = project.slug @@ -258,7 +258,7 @@ test("can delete a workspace", async ({ page, withProject }) => { await clickMenuItem(menu, /^Delete$/i, { force: true }) await confirmDialog(page, /^Delete workspace$/i) - await expect.poll(() => dirDecode(slugFromUrl(page.url()))).toBe(project.directory) + await expect.poll(() => base64Decode(slugFromUrl(page.url()))).toBe(project.directory) await expect .poll( diff --git a/packages/app/e2e/utils.ts b/packages/app/e2e/utils.ts index f2c3919f5c5d..f07a8d3f1116 100644 --- a/packages/app/e2e/utils.ts +++ b/packages/app/e2e/utils.ts @@ -1,5 +1,5 @@ import { createOpencodeClient } from "@opencode-ai/sdk/v2/client" -import { base64Decode, base64Encode, checksum } from "@opencode-ai/util/encode" +import { base64Encode, checksum } from "@opencode-ai/util/encode" export const serverHost = process.env.PLAYWRIGHT_SERVER_HOST ?? "127.0.0.1" export const serverPort = process.env.PLAYWRIGHT_SERVER_PORT ?? "4096" @@ -48,10 +48,6 @@ export function dirSlug(directory: string) { return base64Encode(directory) } -export function dirDecode(slug: string) { - return base64Decode(slug) -} - export function dirPath(directory: string) { return `/${dirSlug(directory)}` }