diff options
| author | Adam <[email protected]> | 2026-03-06 11:03:32 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-03-06 11:03:37 -0600 |
| commit | a71b11caca88243a9e4399317bcc5234d432976c (patch) | |
| tree | 3854bfd906ddaae04351d8e327dc5d6e6fc9d536 /packages/app | |
| parent | e9568999c385242756c2ea3530560481cf97999d (diff) | |
| download | opencode-a71b11caca88243a9e4399317bcc5234d432976c.tar.gz opencode-a71b11caca88243a9e4399317bcc5234d432976c.zip | |
fix(app): stale keyed show errors
Diffstat (limited to 'packages/app')
| -rw-r--r-- | packages/app/e2e/actions.ts | 51 | ||||
| -rw-r--r-- | packages/app/e2e/session/session-child-navigation.spec.ts | 37 |
2 files changed, 88 insertions, 0 deletions
diff --git a/packages/app/e2e/actions.ts b/packages/app/e2e/actions.ts index fbb13008b..919a1add8 100644 --- a/packages/app/e2e/actions.ts +++ b/packages/app/e2e/actions.ts @@ -445,6 +445,57 @@ export async function seedSessionPermission( return { id: result.id } } +export async function seedSessionTask( + sdk: ReturnType<typeof createSdk>, + input: { + sessionID: string + description: string + prompt: string + subagentType?: string + }, +) { + const text = [ + "Your only valid response is one task tool call.", + `Use this JSON input: ${JSON.stringify({ + description: input.description, + prompt: input.prompt, + subagent_type: input.subagentType ?? "general", + })}`, + "Do not output plain text.", + "Wait for the task to start and return the child session id.", + ].join("\n") + + const result = await seed({ + sdk, + sessionID: input.sessionID, + prompt: text, + timeout: 90_000, + probe: async () => { + const messages = await sdk.session.messages({ sessionID: input.sessionID, limit: 50 }).then((x) => x.data ?? []) + const part = messages + .flatMap((message) => message.parts) + .find((part) => { + if (part.type !== "tool" || part.tool !== "task") return false + if (part.state.input?.description !== input.description) return false + return typeof part.state.metadata?.sessionId === "string" && part.state.metadata.sessionId.length > 0 + }) + + if (!part) return + const id = part.state.metadata?.sessionId + if (typeof id !== "string" || !id) return + const child = await sdk.session + .get({ sessionID: id }) + .then((x) => x.data) + .catch(() => undefined) + if (!child?.id) return + return { sessionID: id } + }, + }) + + if (!result) throw new Error("Timed out seeding task tool") + return result +} + export async function seedSessionTodos( sdk: ReturnType<typeof createSdk>, input: { diff --git a/packages/app/e2e/session/session-child-navigation.spec.ts b/packages/app/e2e/session/session-child-navigation.spec.ts new file mode 100644 index 000000000..ac2dca33c --- /dev/null +++ b/packages/app/e2e/session/session-child-navigation.spec.ts @@ -0,0 +1,37 @@ +import { seedSessionTask, withSession } from "../actions" +import { test, expect } from "../fixtures" + +test("task tool child-session link does not trigger stale show errors", async ({ page, sdk, gotoSession }) => { + test.setTimeout(120_000) + + const errs: string[] = [] + const onError = (err: Error) => { + errs.push(err.message) + } + page.on("pageerror", onError) + + await withSession(sdk, `e2e child nav ${Date.now()}`, async (session) => { + const child = await seedSessionTask(sdk, { + sessionID: session.id, + description: "Open child session", + prompt: "Search the repository for AssistantParts and then reply with exactly CHILD_OK.", + }) + + try { + await gotoSession(session.id) + + const link = page + .locator("a.subagent-link") + .filter({ hasText: /open child session/i }) + .first() + await expect(link).toBeVisible({ timeout: 30_000 }) + await link.click() + + await expect(page).toHaveURL(new RegExp(`/session/${child.sessionID}(?:[/?#]|$)`), { timeout: 30_000 }) + await page.waitForTimeout(1000) + expect(errs).toEqual([]) + } finally { + page.off("pageerror", onError) + } + }) +}) |
