mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-11 13:43:35 +00:00
feat(core): finalize session event lifecycle (#35272)
This commit is contained in:
parent
b046bbe4e3
commit
bf01264661
82 changed files with 5847 additions and 4358 deletions
|
|
@ -28,11 +28,20 @@ function prompted(inputID: string): V2Event {
|
|||
}
|
||||
|
||||
function settled(outcome: "success" | "interrupted" = "success"): V2Event {
|
||||
if (outcome === "interrupted")
|
||||
return {
|
||||
id: "evt_interrupted",
|
||||
created: 0,
|
||||
type: "session.execution.interrupted",
|
||||
durable: { aggregateID: "ses_1", seq: 1, version: 1 },
|
||||
data: { sessionID: "ses_1", reason: "user" },
|
||||
}
|
||||
return {
|
||||
id: "evt_settled",
|
||||
id: "evt_succeeded",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome },
|
||||
type: "session.execution.succeeded",
|
||||
durable: { aggregateID: "ses_1", seq: 1, version: 1 },
|
||||
data: { sessionID: "ses_1" },
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,8 +67,7 @@ async function run(input: { turn: (inputID: string) => V2Event[]; pendingForms?:
|
|||
spyOn(sdk.permission, "list").mockImplementation(() => ok([]) as never)
|
||||
spyOn(sdk.question, "list").mockImplementation(() => ok([]) as never)
|
||||
spyOn(sdk.form, "list").mockImplementation(
|
||||
(request) =>
|
||||
ok(input.pendingForms?.filter((item) => item.sessionID === request.sessionID) ?? []) as never,
|
||||
(request) => ok(input.pendingForms?.filter((item) => item.sessionID === request.sessionID) ?? []) as never,
|
||||
)
|
||||
spyOn(sdk.form, "cancel").mockImplementation(() => ok(undefined) as never)
|
||||
spyOn(sdk.session, "prompt").mockImplementation((request) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,12 @@ import { afterEach, describe, expect, mock, spyOn, test } from "bun:test"
|
|||
import fs from "fs/promises"
|
||||
import path from "path"
|
||||
import { pathToFileURL } from "node:url"
|
||||
import { OpenCode, type EventSubscribeOutput, type MessageListOutput, type OpenCodeClient } from "@opencode-ai/client/promise"
|
||||
import {
|
||||
OpenCode,
|
||||
type EventSubscribeOutput,
|
||||
type MessageListOutput,
|
||||
type OpenCodeClient,
|
||||
} from "@opencode-ai/client/promise"
|
||||
import { createSessionTransport } from "@opencode-ai/cli/mini/stream-v2.transport"
|
||||
import type { FooterApi, FooterEvent, StreamCommit } from "@opencode-ai/cli/mini/types"
|
||||
import { tmpdir } from "../../fixture/fixture"
|
||||
|
|
@ -200,15 +205,16 @@ describe("V2 mini transport", () => {
|
|||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
textID: "txt_1",
|
||||
ordinal: 0,
|
||||
delta: "answer",
|
||||
},
|
||||
})
|
||||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
await turn
|
||||
|
||||
|
|
@ -253,8 +259,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
})
|
||||
return ok({
|
||||
|
|
@ -347,8 +354,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
})
|
||||
return ok({
|
||||
|
|
@ -444,8 +452,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
})
|
||||
return ok({
|
||||
|
|
@ -693,7 +702,7 @@ describe("V2 mini transport", () => {
|
|||
type: "assistant",
|
||||
agent: "build",
|
||||
model: { providerID: "test", id: "model" },
|
||||
content: [{ type: "text", id: "txt_1", text: "the answer" }],
|
||||
content: [{ type: "text", text: "the answer" }],
|
||||
time: { created: 2, completed: 3 },
|
||||
},
|
||||
],
|
||||
|
|
@ -705,6 +714,17 @@ describe("V2 mini transport", () => {
|
|||
reset = resolve
|
||||
})
|
||||
const replay = transport.replayOnResize({ localRows: () => [], reset: () => resetting })
|
||||
events.push({
|
||||
id: "evt_text_started",
|
||||
created: 0,
|
||||
type: "session.text.started",
|
||||
durable: durable("ses_1"),
|
||||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
ordinal: 0,
|
||||
},
|
||||
})
|
||||
events.push({
|
||||
id: "evt_text",
|
||||
created: 0,
|
||||
|
|
@ -712,7 +732,7 @@ describe("V2 mini transport", () => {
|
|||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
textID: "txt_1",
|
||||
ordinal: 0,
|
||||
delta: "answer",
|
||||
},
|
||||
})
|
||||
|
|
@ -725,7 +745,7 @@ describe("V2 mini transport", () => {
|
|||
await transport.close()
|
||||
})
|
||||
|
||||
test("scopes repeated text and reasoning ids by assistant message", async () => {
|
||||
test("scopes text and reasoning ordinals by assistant message", async () => {
|
||||
const events = feed()
|
||||
events.push(connected())
|
||||
const client = sdk({ streams: [events] })
|
||||
|
|
@ -738,8 +758,8 @@ describe("V2 mini transport", () => {
|
|||
agent: "build",
|
||||
model: { providerID: "test", id: "model" },
|
||||
content: [
|
||||
{ type: "reasoning", id: "reasoning-0", text: "second thought" },
|
||||
{ type: "text", id: "text-0", text: "second answer" },
|
||||
{ type: "reasoning", text: "second thought" },
|
||||
{ type: "text", text: "second answer" },
|
||||
],
|
||||
time: { created: 4, completed: 5 },
|
||||
},
|
||||
|
|
@ -749,8 +769,8 @@ describe("V2 mini transport", () => {
|
|||
agent: "build",
|
||||
model: { providerID: "test", id: "model" },
|
||||
content: [
|
||||
{ type: "reasoning", id: "reasoning-0", text: "first thought" },
|
||||
{ type: "text", id: "text-0", text: "first answer" },
|
||||
{ type: "reasoning", text: "first thought" },
|
||||
{ type: "text", text: "first answer" },
|
||||
],
|
||||
time: { created: 2, completed: 3 },
|
||||
},
|
||||
|
|
@ -798,7 +818,7 @@ describe("V2 mini transport", () => {
|
|||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
reasoningID: "reasoning_1",
|
||||
ordinal: 0,
|
||||
text: "considering",
|
||||
},
|
||||
})
|
||||
|
|
@ -808,6 +828,52 @@ describe("V2 mini transport", () => {
|
|||
await transport.close()
|
||||
})
|
||||
|
||||
test("renders a live tool start when the call begins", async () => {
|
||||
const events = feed()
|
||||
events.push(connected())
|
||||
const client = sdk({ streams: [events] })
|
||||
const ui = footer()
|
||||
const transport = await createSessionTransport({
|
||||
sdk: client,
|
||||
sessionID: "ses_1",
|
||||
thinking: false,
|
||||
limits: () => ({}),
|
||||
footer: ui.api,
|
||||
})
|
||||
|
||||
events.push({
|
||||
id: "evt_tool_input",
|
||||
created: 1,
|
||||
type: "session.tool.input.started",
|
||||
durable: durable("ses_1"),
|
||||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
callID: "call_read",
|
||||
name: "read",
|
||||
},
|
||||
})
|
||||
events.push({
|
||||
id: "evt_tool_called",
|
||||
created: 2,
|
||||
type: "session.tool.called",
|
||||
durable: durable("ses_1", 1),
|
||||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_assistant",
|
||||
callID: "call_read",
|
||||
input: { path: "README.md" },
|
||||
executed: false,
|
||||
},
|
||||
})
|
||||
await Bun.sleep(0)
|
||||
|
||||
expect(ui.commits).toContainEqual(
|
||||
expect.objectContaining({ kind: "tool", phase: "start", partID: "prt_call_read", tool: "read" }),
|
||||
)
|
||||
await transport.close()
|
||||
})
|
||||
|
||||
test("resolves an interrupted turn even when promotion never arrived", async () => {
|
||||
const events = feed()
|
||||
events.push(connected())
|
||||
|
|
@ -849,8 +915,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.interrupted",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1", reason: "user" },
|
||||
})
|
||||
await turn
|
||||
|
||||
|
|
@ -913,8 +980,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
await turn
|
||||
|
||||
|
|
@ -975,8 +1043,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.interrupted",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1", reason: "user" },
|
||||
})
|
||||
await turn
|
||||
|
||||
|
|
@ -1413,8 +1482,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
})
|
||||
return ok({
|
||||
|
|
@ -1488,8 +1558,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
})
|
||||
return ok(undefined) as never
|
||||
|
|
@ -1569,8 +1640,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_unrelated_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
await Bun.sleep(0)
|
||||
await Bun.sleep(0)
|
||||
|
|
@ -1590,8 +1662,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_skill_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_1", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_1"),
|
||||
data: { sessionID: "ses_1" },
|
||||
})
|
||||
await turn
|
||||
|
||||
|
|
@ -1701,18 +1774,19 @@ describe("V2 mini transport", () => {
|
|||
],
|
||||
},
|
||||
})
|
||||
spyOn(client.session, "get").mockImplementation(() =>
|
||||
ok({
|
||||
id: "ses_child",
|
||||
parentID: "ses_1",
|
||||
projectID: "proj_1",
|
||||
agent: "explore",
|
||||
cost: 0,
|
||||
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
||||
time: { created: 1, updated: 1 },
|
||||
title: "Find files",
|
||||
location: { directory: "/tmp" },
|
||||
}) as never,
|
||||
spyOn(client.session, "get").mockImplementation(
|
||||
() =>
|
||||
ok({
|
||||
id: "ses_child",
|
||||
parentID: "ses_1",
|
||||
projectID: "proj_1",
|
||||
agent: "explore",
|
||||
cost: 0,
|
||||
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
|
||||
time: { created: 1, updated: 1 },
|
||||
title: "Find files",
|
||||
location: { directory: "/tmp" },
|
||||
}) as never,
|
||||
)
|
||||
const ui = footer()
|
||||
const transport = await createSessionTransport({
|
||||
|
|
@ -1750,7 +1824,7 @@ describe("V2 mini transport", () => {
|
|||
data: {
|
||||
sessionID: "ses_child",
|
||||
assistantMessageID: "msg_child_a",
|
||||
textID: "txt_child",
|
||||
ordinal: 0,
|
||||
delta: "child answer",
|
||||
},
|
||||
})
|
||||
|
|
@ -1760,8 +1834,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_child_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_child", outcome: "success" },
|
||||
type: "session.execution.succeeded",
|
||||
durable: durable("ses_child"),
|
||||
data: { sessionID: "ses_child" },
|
||||
})
|
||||
while (!states().some((state) => state.tabs.some((tab) => tab.status === "completed"))) await Bun.sleep(0)
|
||||
await transport.close()
|
||||
|
|
@ -1801,7 +1876,9 @@ describe("V2 mini transport", () => {
|
|||
})
|
||||
await Bun.sleep(0)
|
||||
expect(
|
||||
states().at(-1)?.details.ses_child?.commits.some((item) => item.messageID === "msg_child_prompt"),
|
||||
states()
|
||||
.at(-1)
|
||||
?.details.ses_child?.commits.some((item) => item.messageID === "msg_child_prompt"),
|
||||
).toBe(false)
|
||||
|
||||
events.push({
|
||||
|
|
@ -1955,19 +2032,36 @@ describe("V2 mini transport", () => {
|
|||
data: {
|
||||
sessionID: "ses_child",
|
||||
assistantMessageID: "msg_overflow_assistant",
|
||||
textID: `txt_overflow_${index}`,
|
||||
ordinal: index,
|
||||
delta: `live ${index}`,
|
||||
},
|
||||
})
|
||||
while (!states().at(-1)?.details.ses_child?.commits.some((item) => item.text === "live 64")) await Bun.sleep(0)
|
||||
while (
|
||||
!states()
|
||||
.at(-1)
|
||||
?.details.ses_child?.commits.some((item) => item.text === "live 64")
|
||||
)
|
||||
await Bun.sleep(0)
|
||||
releaseStale()
|
||||
while (childRequests < 2) await Bun.sleep(0)
|
||||
expect(states().at(-1)?.details.ses_child?.commits.some((item) => item.text === "live 64")).toBe(true)
|
||||
expect(
|
||||
states()
|
||||
.at(-1)
|
||||
?.details.ses_child?.commits.some((item) => item.text === "live 64"),
|
||||
).toBe(true)
|
||||
|
||||
releaseRetry()
|
||||
while (!states().at(-1)?.details.ses_child?.commits.some((item) => item.text === "baseline history"))
|
||||
while (
|
||||
!states()
|
||||
.at(-1)
|
||||
?.details.ses_child?.commits.some((item) => item.text === "baseline history")
|
||||
)
|
||||
await Bun.sleep(0)
|
||||
expect(states().at(-1)?.details.ses_child?.commits.some((item) => item.text === "live 64")).toBe(true)
|
||||
expect(
|
||||
states()
|
||||
.at(-1)
|
||||
?.details.ses_child?.commits.some((item) => item.text === "live 64"),
|
||||
).toBe(true)
|
||||
expect(childRequests).toBe(2)
|
||||
await transport.close()
|
||||
})
|
||||
|
|
@ -2032,7 +2126,7 @@ describe("V2 mini transport", () => {
|
|||
durable: durable("ses_child", seq),
|
||||
data: { sessionID: "ses_child", assistantMessageID: "msg_tool_projected", callID, name },
|
||||
})
|
||||
const called = (callID: string, tool: string, input: Record<string, unknown>, seq: number) =>
|
||||
const called = (callID: string, input: Record<string, unknown>, seq: number) =>
|
||||
events.push({
|
||||
id: `evt_called_${callID}`,
|
||||
created: seq,
|
||||
|
|
@ -2042,14 +2136,13 @@ describe("V2 mini transport", () => {
|
|||
sessionID: "ses_child",
|
||||
assistantMessageID: "msg_tool_projected",
|
||||
callID,
|
||||
tool,
|
||||
input,
|
||||
provider: { executed: true },
|
||||
executed: true,
|
||||
},
|
||||
})
|
||||
|
||||
inputStarted("call_terminal", "grep", 0)
|
||||
called("call_terminal", "grep", { pattern: "needle" }, 1)
|
||||
called("call_terminal", { pattern: "needle" }, 1)
|
||||
await Bun.sleep(0)
|
||||
transport.selectSubagent("ses_child")
|
||||
while (!childHydrating) await Bun.sleep(0)
|
||||
|
|
@ -2064,11 +2157,11 @@ describe("V2 mini transport", () => {
|
|||
callID: "call_terminal",
|
||||
structured: {},
|
||||
content: [{ type: "text", text: "found" }],
|
||||
provider: { executed: true },
|
||||
executed: true,
|
||||
},
|
||||
})
|
||||
inputStarted("call_overlap", "bash", 3)
|
||||
called("call_overlap", "bash", { command: "stale" }, 4)
|
||||
called("call_overlap", { command: "stale" }, 4)
|
||||
await Bun.sleep(0)
|
||||
const beforeHydration = states().length
|
||||
releaseHydration()
|
||||
|
|
@ -2137,8 +2230,9 @@ describe("V2 mini transport", () => {
|
|||
events.push({
|
||||
id: "evt_child_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_child", outcome: "interrupted" },
|
||||
type: "session.execution.interrupted",
|
||||
durable: durable("ses_child"),
|
||||
data: { sessionID: "ses_child", reason: "user" },
|
||||
})
|
||||
await Bun.sleep(0)
|
||||
resolveGet?.()
|
||||
|
|
@ -2192,6 +2286,18 @@ describe("V2 mini transport", () => {
|
|||
},
|
||||
})
|
||||
// Parent's background subagent tool.success adopts the child mid-discovery.
|
||||
events.push({
|
||||
id: "evt_parent_input",
|
||||
created: 0,
|
||||
type: "session.tool.input.started",
|
||||
durable: durable("ses_1"),
|
||||
data: {
|
||||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_parent_a",
|
||||
callID: "call_sub",
|
||||
name: "subagent",
|
||||
},
|
||||
})
|
||||
events.push({
|
||||
id: "evt_parent_call",
|
||||
created: 0,
|
||||
|
|
@ -2201,9 +2307,8 @@ describe("V2 mini transport", () => {
|
|||
sessionID: "ses_1",
|
||||
assistantMessageID: "msg_parent_a",
|
||||
callID: "call_sub",
|
||||
tool: "subagent",
|
||||
input: { agent: "explore", description: "Find things", prompt: "go", background: true },
|
||||
provider: { executed: true },
|
||||
executed: true,
|
||||
},
|
||||
})
|
||||
events.push({
|
||||
|
|
@ -2217,15 +2322,16 @@ describe("V2 mini transport", () => {
|
|||
callID: "call_sub",
|
||||
structured: { sessionID: "ses_child", status: "running", output: "" },
|
||||
content: [],
|
||||
provider: { executed: true },
|
||||
executed: true,
|
||||
},
|
||||
})
|
||||
// The settled event arrives after adoption, so it applies directly.
|
||||
events.push({
|
||||
id: "evt_child_settled",
|
||||
created: 0,
|
||||
type: "session.execution.settled",
|
||||
data: { sessionID: "ses_child", outcome: "interrupted" },
|
||||
type: "session.execution.interrupted",
|
||||
durable: durable("ses_child"),
|
||||
data: { sessionID: "ses_child", reason: "shutdown" },
|
||||
})
|
||||
while (!states().some((state) => state.tabs.some((tab) => tab.status === "cancelled"))) await Bun.sleep(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ test.skip("text ended populates assistant text content", () => {
|
|||
data: {
|
||||
sessionID,
|
||||
assistantMessageID,
|
||||
textID: "text-1",
|
||||
ordinal: 0,
|
||||
},
|
||||
} satisfies SessionEvent.Event),
|
||||
)
|
||||
|
|
@ -115,7 +115,7 @@ test.skip("text ended populates assistant text content", () => {
|
|||
data: {
|
||||
sessionID,
|
||||
assistantMessageID,
|
||||
textID: "text-1",
|
||||
ordinal: 0,
|
||||
text: "hello assistant",
|
||||
},
|
||||
} satisfies SessionEvent.Event),
|
||||
|
|
@ -123,7 +123,7 @@ test.skip("text ended populates assistant text content", () => {
|
|||
|
||||
expect(state.messages[0]?.type).toBe("assistant")
|
||||
if (state.messages[0]?.type !== "assistant") return
|
||||
expect(state.messages[0].content).toEqual([{ type: "text", id: "text-1", text: "hello assistant" }])
|
||||
expect(state.messages[0].content).toEqual([{ type: "text", text: "hello assistant" }])
|
||||
})
|
||||
|
||||
test.skip("tool completion stores completed timestamp", () => {
|
||||
|
|
@ -176,9 +176,9 @@ test.skip("tool completion stores completed timestamp", () => {
|
|||
sessionID,
|
||||
assistantMessageID,
|
||||
callID,
|
||||
tool: "bash",
|
||||
input: { command: "pwd" },
|
||||
provider: { executed: true, metadata: { fake: { source: "provider" } } },
|
||||
executed: true,
|
||||
state: { source: "provider" },
|
||||
},
|
||||
} satisfies SessionEvent.Event),
|
||||
)
|
||||
|
|
@ -195,7 +195,8 @@ test.skip("tool completion stores completed timestamp", () => {
|
|||
callID,
|
||||
structured: {},
|
||||
content: [{ type: "text", text: "/tmp" }],
|
||||
provider: { executed: true, metadata: { fake: { status: "done" } } },
|
||||
executed: true,
|
||||
resultState: { status: "done" },
|
||||
},
|
||||
} satisfies SessionEvent.Event),
|
||||
)
|
||||
|
|
@ -205,7 +206,11 @@ test.skip("tool completion stores completed timestamp", () => {
|
|||
expect(state.messages[0].content[0]?.type).toBe("tool")
|
||||
if (state.messages[0].content[0]?.type !== "tool") return
|
||||
expect(state.messages[0].content[0].time.completed).toEqual(DateTime.makeUnsafe(4))
|
||||
expect(state.messages[0].content[0].provider).toEqual({ executed: true, metadata: { fake: { status: "done" } } })
|
||||
expect(state.messages[0].content[0]).toMatchObject({
|
||||
executed: true,
|
||||
providerState: { source: "provider" },
|
||||
providerResultState: { status: "done" },
|
||||
})
|
||||
})
|
||||
|
||||
test("compaction events reduce to compaction message only when completed", () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue