refactor(schema): session shell payloads and event prefix restore (#35229)

This commit is contained in:
Kit Langton
2026-07-03 17:30:25 -04:00
committed by GitHub
parent 64e4f6f91b
commit 650d774372
49 changed files with 1521 additions and 1200 deletions
@@ -25,7 +25,7 @@ function prompted(inputID: string): V2Event {
return {
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: { aggregateID: "ses_1", seq: 0, version: 1 },
data: { sessionID: "ses_1", inputID },
}
@@ -35,7 +35,7 @@ function settled(outcome: "success" | "interrupted" = "success"): V2Event {
return {
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome },
}
}
@@ -329,7 +329,7 @@ describe("run session data", () => {
test("renders direct shell mode from first-class shell events", () => {
let data = createSessionData()
const started = reduce(data, {
type: "shell.started",
type: "session.shell.started",
properties: {
sessionID: "session-1",
timestamp: 1,
@@ -353,7 +353,7 @@ describe("run session data", () => {
data = started.data
const ended = reduce(data, {
type: "shell.ended",
type: "session.shell.ended",
properties: {
sessionID: "session-1",
timestamp: 2,
@@ -380,7 +380,7 @@ describe("run session data", () => {
test("suppresses legacy bash part updates once shell events claim the call", () => {
let data = reduce(createSessionData(), {
type: "shell.started",
type: "session.shell.started",
properties: {
sessionID: "session-1",
timestamp: 1,
@@ -409,7 +409,7 @@ describe("run session data", () => {
).toEqual([])
data = reduce(data, {
type: "shell.ended",
type: "session.shell.ended",
properties: {
sessionID: "session-1",
timestamp: 2,
@@ -463,7 +463,7 @@ describe("run session data", () => {
expect(
reduce(data, {
type: "shell.started",
type: "session.shell.started",
properties: {
sessionID: "session-1",
timestamp: 1,
@@ -497,7 +497,7 @@ describe("run session data", () => {
expect(
reduce(data, {
type: "shell.ended",
type: "session.shell.ended",
properties: {
sessionID: "session-1",
timestamp: 2,
@@ -200,7 +200,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -210,7 +210,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_text",
created: 0,
type: "text.delta",
type: "session.text.delta",
data: {
sessionID: "ses_1",
assistantMessageID: "msg_assistant",
@@ -221,7 +221,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
await turn
@@ -259,7 +259,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -269,7 +269,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
})
@@ -353,7 +353,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -363,7 +363,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
})
@@ -450,7 +450,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -460,7 +460,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
})
@@ -724,7 +724,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_text",
created: 0,
type: "text.delta",
type: "session.text.delta",
data: {
sessionID: "ses_1",
assistantMessageID: "msg_assistant",
@@ -809,7 +809,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_reasoning",
created: 0,
type: "reasoning.ended",
type: "session.reasoning.ended",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -865,7 +865,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
await turn
@@ -921,7 +921,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -931,7 +931,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
await turn
@@ -981,7 +981,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -993,7 +993,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
await turn
@@ -1021,16 +1021,42 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_shell_start",
created: 0,
type: "shell.started",
type: "session.shell.started",
durable: durable("ses_1"),
data: { sessionID: "ses_1", callID: "call_shell", command: "ls" },
data: {
sessionID: "ses_1",
shell: {
id: "sh_shell",
status: "running",
command: "ls",
cwd: "/tmp",
shell: "/bin/sh",
file: "/tmp/opencode-shell",
metadata: {},
time: { started: 0 },
},
},
})
events.push({
id: "evt_shell_end",
created: 0,
type: "shell.ended",
type: "session.shell.ended",
durable: durable("ses_1", 1),
data: { sessionID: "ses_1", callID: "call_shell", output: "file.txt" },
data: {
sessionID: "ses_1",
shell: {
id: "sh_shell",
status: "exited",
command: "ls",
cwd: "/tmp",
shell: "/bin/sh",
file: "/tmp/opencode-shell",
exit: 0,
metadata: {},
time: { started: 0, completed: 1 },
},
output: { output: "file.txt", cursor: 8, size: 8, truncated: false },
},
})
})
return ok(undefined) as never
@@ -1047,8 +1073,8 @@ describe("V2 mini transport", () => {
expect(request).toMatchObject({ sessionID: "ses_1", command: "ls" })
expect(ui.commits.filter((item) => item.shell)).toMatchObject([
{ phase: "start", tool: "bash", toolState: "running", shell: { callID: "call_shell", command: "ls" } },
{ phase: "progress", text: "file.txt", toolState: "completed", shell: { callID: "call_shell", command: "ls" } },
{ phase: "start", tool: "bash", toolState: "running", shell: { callID: "sh_shell", command: "ls" } },
{ phase: "progress", text: "file.txt", toolState: "completed", shell: { callID: "sh_shell", command: "ls" } },
])
expect(ui.events).toContainEqual({ type: "stream.patch", patch: { phase: "running", status: "running shell" } })
await transport.close()
@@ -1107,9 +1133,18 @@ describe("V2 mini transport", () => {
{
id: "msg_shell",
type: "shell" as const,
callID: "call_1",
command: "ls",
output: "file.txt",
shell: {
id: "sh_1",
status: "exited",
command: "ls",
cwd: "/tmp",
shell: "/bin/sh",
file: "/tmp/opencode-shell",
exit: 0,
metadata: {},
time: { started: 0, completed: 1 },
},
output: { output: "file.txt", cursor: 8, size: 8, truncated: false },
time: { created: 1, completed: 2 },
},
],
@@ -1127,15 +1162,29 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_shell_end",
created: 0,
type: "shell.ended",
type: "session.shell.ended",
durable: durable("ses_1", 1),
data: { sessionID: "ses_1", callID: "call_1", output: "file.txt" },
data: {
sessionID: "ses_1",
shell: {
id: "sh_1",
status: "exited",
command: "ls",
cwd: "/tmp",
shell: "/bin/sh",
file: "/tmp/opencode-shell",
exit: 0,
metadata: {},
time: { started: 0, completed: 1 },
},
output: { output: "file.txt", cursor: 8, size: 8, truncated: false },
},
})
await Bun.sleep(0)
await Bun.sleep(0)
expect(ui.commits.filter((item) => item.shell)).toMatchObject([
{ phase: "start", shell: { callID: "call_1", command: "ls" } },
{ phase: "start", shell: { callID: "sh_1", command: "ls" } },
{ phase: "progress", text: "file.txt", toolState: "completed" },
])
await transport.close()
@@ -1160,7 +1209,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_prompted",
created: 0,
type: "prompt.promoted",
type: "session.prompt.promoted",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -1170,7 +1219,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
})
@@ -1236,7 +1285,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_skill",
created: 0,
type: "skill.activated",
type: "session.skill.activated",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -1247,7 +1296,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
})
@@ -1317,7 +1366,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_unrelated_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
await Bun.sleep(0)
@@ -1327,7 +1376,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_skill",
created: 0,
type: "skill.activated",
type: "session.skill.activated",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -1338,7 +1387,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_skill_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_1", outcome: "success" },
})
await turn
@@ -1376,7 +1425,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_skill",
created: 0,
type: "skill.activated",
type: "session.skill.activated",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -1438,7 +1487,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_step",
created: 0,
type: "step.started",
type: "session.step.started",
durable: durable("ses_child"),
data: {
sessionID: "ses_child",
@@ -1456,7 +1505,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_text",
created: 0,
type: "text.delta",
type: "session.text.delta",
data: {
sessionID: "ses_child",
assistantMessageID: "msg_child_a",
@@ -1470,7 +1519,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_child", outcome: "success" },
})
while (!states().some((state) => state.tabs.some((tab) => tab.status === "completed"))) await Bun.sleep(0)
@@ -1515,7 +1564,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_step",
created: 0,
type: "step.started",
type: "session.step.started",
durable: durable("ses_child"),
data: {
sessionID: "ses_child",
@@ -1527,7 +1576,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_child", outcome: "interrupted" },
})
await Bun.sleep(0)
@@ -1574,7 +1623,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_step",
created: 0,
type: "step.started",
type: "session.step.started",
durable: durable("ses_child"),
data: {
sessionID: "ses_child",
@@ -1587,7 +1636,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_parent_call",
created: 0,
type: "tool.called",
type: "session.tool.called",
durable: durable("ses_1"),
data: {
sessionID: "ses_1",
@@ -1601,7 +1650,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_parent_success",
created: 0,
type: "tool.success",
type: "session.tool.success",
durable: durable("ses_1", 1),
data: {
sessionID: "ses_1",
@@ -1616,7 +1665,7 @@ describe("V2 mini transport", () => {
events.push({
id: "evt_child_settled",
created: 0,
type: "execution.settled",
type: "session.execution.settled",
data: { sessionID: "ses_child", outcome: "interrupted" },
})
while (!states().some((state) => state.tabs.some((tab) => tab.status === "cancelled"))) await Bun.sleep(0)
@@ -99,10 +99,10 @@ describe("pty HttpApi bridge", () => {
const updated = await app().request(PtyPaths.update.replace(":ptyID", info.id), {
method: "PUT",
headers: { ...headers, "content-type": "application/json" },
body: JSON.stringify({ title: "renamed", size: { cols: 80, rows: 24 } }),
body: JSON.stringify({ title: "session.renamed", size: { cols: 80, rows: 24 } }),
})
expect(updated.status).toBe(200)
expect(await updated.json()).toMatchObject({ id: info.id, title: "renamed" })
expect(await updated.json()).toMatchObject({ id: info.id, title: "session.renamed" })
} finally {
await app().request(PtyPaths.remove.replace(":ptyID", info.id), { method: "DELETE", headers })
}
@@ -573,7 +573,7 @@ describe("HttpApi SDK", () => {
const child = yield* capture(() => sdk.session.create({ title: "child", parentID }))
const childID = String(record(child.data).id)
const get = yield* capture(() => sdk.session.get({ sessionID: parentID }))
const update = yield* capture(() => sdk.session.update({ sessionID: parentID, title: "renamed" }))
const update = yield* capture(() => sdk.session.update({ sessionID: parentID, title: "session.renamed" }))
const roots = yield* capture(() => sdk.session.list({ roots: true, limit: 10 }))
const all = yield* capture(() => sdk.session.list({ roots: false, limit: 10 }))
const children = yield* capture(() => sdk.session.children({ sessionID: parentID }))
@@ -271,7 +271,7 @@ describe("tool.apply_patch freeform", () => {
yield* execute({ patchText }, ctx)
const moved = path.join(test.directory, "renamed", "dir", "name.txt")
const moved = path.join(test.directory, "session.renamed", "dir", "name.txt")
yield* expectReadFailure(original)
expect(yield* readText(moved)).toBe("new content\n")
}),
@@ -282,7 +282,7 @@ describe("tool.apply_patch freeform", () => {
const test = yield* TestInstance
const { ctx } = makeCtx()
const original = path.join(test.directory, "old", "name.txt")
const destination = path.join(test.directory, "renamed", "dir", "name.txt")
const destination = path.join(test.directory, "session.renamed", "dir", "name.txt")
yield* makeDir(path.dirname(original))
yield* makeDir(path.dirname(destination))
yield* writeText(original, "from\n")
@@ -79593,8 +79593,8 @@
}
}
},
"synthetic": {
"id": "synthetic",
"session.synthetic": {
"id": "session.synthetic",
"env": ["SYNTHETIC_API_KEY"],
"npm": "@ai-sdk/openai-compatible",
"api": "https://api.synthetic.new/openai/v1",
@@ -22,7 +22,7 @@ test.skip("step snapshots carry over to assistant messages", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "step.started",
type: "session.step.started",
durable: durable(sessionID),
data: {
sessionID,
@@ -44,7 +44,7 @@ test.skip("step snapshots carry over to assistant messages", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "step.ended",
type: "session.step.ended",
durable: durable(sessionID, 1, 2),
data: {
sessionID,
@@ -77,7 +77,7 @@ test.skip("text ended populates assistant text content", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "step.started",
type: "session.step.started",
durable: durable(sessionID),
data: {
sessionID,
@@ -96,7 +96,7 @@ test.skip("text ended populates assistant text content", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "text.started",
type: "session.text.started",
durable: durable(sessionID, 1),
data: {
sessionID,
@@ -110,7 +110,7 @@ test.skip("text ended populates assistant text content", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "text.ended",
type: "session.text.ended",
durable: durable(sessionID, 2),
data: {
sessionID,
@@ -136,7 +136,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "step.started",
type: "session.step.started",
durable: durable(sessionID),
data: {
sessionID,
@@ -155,7 +155,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "tool.input.started",
type: "session.tool.input.started",
durable: durable(sessionID, 1),
data: {
sessionID,
@@ -170,7 +170,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "tool.called",
type: "session.tool.called",
durable: durable(sessionID, 2),
data: {
sessionID,
@@ -187,7 +187,7 @@ test.skip("tool completion stores completed timestamp", () => {
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "tool.success",
type: "session.tool.success",
durable: durable(sessionID, 3),
data: {
sessionID,
@@ -218,7 +218,7 @@ test("compaction events reduce to compaction message only when completed", () =>
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id,
created: DateTime.makeUnsafe(0),
type: "compaction.started",
type: "session.compaction.started",
durable: durable(sessionID),
data: {
sessionID,
@@ -233,7 +233,7 @@ test("compaction events reduce to compaction message only when completed", () =>
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "compaction.delta",
type: "session.compaction.delta",
data: {
sessionID,
text: "hello ",
@@ -245,7 +245,7 @@ test("compaction events reduce to compaction message only when completed", () =>
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: EventV2.ID.create(),
created: DateTime.makeUnsafe(0),
type: "compaction.delta",
type: "session.compaction.delta",
data: {
sessionID,
text: "summary",
@@ -257,7 +257,7 @@ test("compaction events reduce to compaction message only when completed", () =>
SessionMessageUpdater.update(SessionMessageUpdater.memory(state), {
id: endedID,
created: DateTime.makeUnsafe(0),
type: "compaction.ended",
type: "session.compaction.ended",
durable: durable(sessionID, 1),
data: {
sessionID,