mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-11 09:03:30 +00:00
refactor(schema): session shell payloads and event prefix restore (#35229)
This commit is contained in:
parent
64e4f6f91b
commit
650d774372
49 changed files with 1521 additions and 1200 deletions
|
|
@ -158,14 +158,14 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
if (!("sessionID" in event.data) || event.data.sessionID !== input.sessionID) continue
|
||||
const time = toMillis(event.created)
|
||||
|
||||
if (event.type === "prompt.promoted") {
|
||||
if (event.type === "session.prompt.promoted") {
|
||||
if (event.data.inputID === messageID) {
|
||||
promoted = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (
|
||||
event.type === "execution.settled" &&
|
||||
event.type === "session.execution.settled" &&
|
||||
event.data.outcome === "interrupted" &&
|
||||
(interrupted || permissionRejected || questionRejected || formCancelled)
|
||||
) {
|
||||
|
|
@ -173,7 +173,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
}
|
||||
if (!promoted) continue
|
||||
|
||||
if (event.type === "step.started") {
|
||||
if (event.type === "session.step.started") {
|
||||
const part: StepStartPart = {
|
||||
id: partID(event.id),
|
||||
sessionID: input.sessionID,
|
||||
|
|
@ -189,11 +189,11 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
continue
|
||||
}
|
||||
|
||||
if (event.type === "text.started") {
|
||||
if (event.type === "session.text.started") {
|
||||
starts.set(event.data.textID, { id: partID(event.id), timestamp: time })
|
||||
continue
|
||||
}
|
||||
if (event.type === "text.ended") {
|
||||
if (event.type === "session.text.ended") {
|
||||
const started = starts.get(event.data.textID)
|
||||
const part: TextPart = {
|
||||
id: started?.id ?? partID(event.id),
|
||||
|
|
@ -207,11 +207,11 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
continue
|
||||
}
|
||||
|
||||
if (event.type === "reasoning.started") {
|
||||
if (event.type === "session.reasoning.started") {
|
||||
starts.set(event.data.reasoningID, { id: partID(event.id), timestamp: time })
|
||||
continue
|
||||
}
|
||||
if (event.type === "reasoning.ended" && input.thinking) {
|
||||
if (event.type === "session.reasoning.ended" && input.thinking) {
|
||||
const started = starts.get(event.data.reasoningID)
|
||||
const part: ReasoningPart = {
|
||||
id: started?.id ?? partID(event.id),
|
||||
|
|
@ -236,7 +236,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
continue
|
||||
}
|
||||
|
||||
if (event.type === "tool.input.started") {
|
||||
if (event.type === "session.tool.input.started") {
|
||||
tools.set(event.data.callID, {
|
||||
id: partID(event.id),
|
||||
timestamp: time,
|
||||
|
|
@ -246,12 +246,12 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
})
|
||||
continue
|
||||
}
|
||||
if (event.type === "tool.input.ended") {
|
||||
if (event.type === "session.tool.input.ended") {
|
||||
const current = tools.get(event.data.callID)
|
||||
if (current) current.raw = event.data.text
|
||||
continue
|
||||
}
|
||||
if (event.type === "tool.called") {
|
||||
if (event.type === "session.tool.called") {
|
||||
const current = tools.get(event.data.callID)
|
||||
tools.set(event.data.callID, {
|
||||
id: current?.id ?? partID(event.id),
|
||||
|
|
@ -264,7 +264,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
})
|
||||
continue
|
||||
}
|
||||
if (event.type === "tool.success") {
|
||||
if (event.type === "session.tool.success") {
|
||||
const current = tools.get(event.data.callID) ?? fallbackTool(event)
|
||||
const part: ToolPart = {
|
||||
id: current.id,
|
||||
|
|
@ -297,7 +297,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
if (!emit("tool_use", time, { part })) await input.renderTool(part)
|
||||
continue
|
||||
}
|
||||
if (event.type === "tool.failed") {
|
||||
if (event.type === "session.tool.failed") {
|
||||
const current = tools.get(event.data.callID) ?? fallbackTool(event)
|
||||
const error = event.data.error.message
|
||||
const part: ToolPart = {
|
||||
|
|
@ -328,7 +328,7 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
continue
|
||||
}
|
||||
|
||||
if (event.type === "step.ended") {
|
||||
if (event.type === "session.step.ended") {
|
||||
const part: StepFinishPart = {
|
||||
id: partID(event.id),
|
||||
sessionID: input.sessionID,
|
||||
|
|
@ -342,14 +342,14 @@ export async function runNonInteractivePrompt(input: Input) {
|
|||
emit("step_finish", time, { part })
|
||||
continue
|
||||
}
|
||||
if (event.type === "step.failed") {
|
||||
if (event.type === "session.step.failed") {
|
||||
if (interrupted || permissionRejected || questionRejected || formCancelled) continue
|
||||
emittedError = true
|
||||
process.exitCode = 1
|
||||
if (!emit("error", time, { error: event.data.error })) UI.error(event.data.error.message)
|
||||
continue
|
||||
}
|
||||
if (event.type === "execution.settled") {
|
||||
if (event.type === "session.execution.settled") {
|
||||
if (event.data.outcome === "failure" && !emittedError && !questionRejected && !formCancelled) {
|
||||
emittedError = true
|
||||
process.exitCode = 1
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ type SessionCommit = StreamCommit
|
|||
// - sent: part ID → byte offset of last flushed text (for incremental output)
|
||||
// - visible: part ID → rendered text for an active part after display transforms
|
||||
// - end: part IDs whose time.end has arrived (part is finished)
|
||||
// - shell: shell call ID → chosen transcript source for direct shell calls
|
||||
// - shell: shell ID → chosen transcript source for direct shell calls
|
||||
// - echo: message ID → bash outputs to strip from the next assistant chunk
|
||||
type ShellCall = {
|
||||
source: "shell" | "tool"
|
||||
|
|
@ -607,12 +607,12 @@ function toolCommit(
|
|||
}
|
||||
}
|
||||
|
||||
function shellPartID(callID: string): string {
|
||||
return `shell:${callID}`
|
||||
function shellPartID(shellID: string): string {
|
||||
return `shell:${shellID}`
|
||||
}
|
||||
|
||||
function claimShell(data: SessionData, callID: string, source: ShellCall["source"], command?: string): ShellCall {
|
||||
const current = data.shell.get(callID)
|
||||
function claimShell(data: SessionData, shellID: string, source: ShellCall["source"], command?: string): ShellCall {
|
||||
const current = data.shell.get(shellID)
|
||||
if (current) {
|
||||
if (command && !current.command) {
|
||||
current.command = command
|
||||
|
|
@ -625,7 +625,7 @@ function claimShell(data: SessionData, callID: string, source: ShellCall["source
|
|||
source,
|
||||
...(command ? { command } : {}),
|
||||
} satisfies ShellCall
|
||||
data.shell.set(callID, next)
|
||||
data.shell.set(shellID, next)
|
||||
return next
|
||||
}
|
||||
|
||||
|
|
@ -728,37 +728,37 @@ export function reduceSessionData(input: SessionDataInput): SessionDataOutput {
|
|||
const data = input.data
|
||||
const event = input.event
|
||||
|
||||
if (event.type === "shell.started") {
|
||||
if (event.type === "session.shell.started") {
|
||||
if (event.properties.sessionID !== input.sessionID) {
|
||||
return out(data, commits)
|
||||
}
|
||||
|
||||
const shell = claimShell(data, event.properties.callID, "shell", event.properties.command)
|
||||
const shell = claimShell(data, event.properties.shell.id, "shell", event.properties.shell.command)
|
||||
if (shell.source !== "shell") {
|
||||
return out(data, commits)
|
||||
}
|
||||
|
||||
const partID = shellPartID(event.properties.callID)
|
||||
const partID = shellPartID(event.properties.shell.id)
|
||||
if (data.ids.has(partID) || data.tools.has(partID)) {
|
||||
return out(data, commits, patch({ status: "running shell" }))
|
||||
}
|
||||
|
||||
data.tools.add(partID)
|
||||
commits.push(startShell(event.properties.callID, shell.command ?? event.properties.command))
|
||||
commits.push(startShell(event.properties.shell.id, shell.command ?? event.properties.shell.command))
|
||||
return out(data, commits, patch({ status: "running shell" }))
|
||||
}
|
||||
|
||||
if (event.type === "shell.ended") {
|
||||
if (event.type === "session.shell.ended") {
|
||||
if (event.properties.sessionID !== input.sessionID) {
|
||||
return out(data, commits)
|
||||
}
|
||||
|
||||
const shell = claimShell(data, event.properties.callID, "shell")
|
||||
const shell = claimShell(data, event.properties.shell.id, "shell")
|
||||
if (shell.source !== "shell") {
|
||||
return out(data, commits)
|
||||
}
|
||||
|
||||
const partID = shellPartID(event.properties.callID)
|
||||
const partID = shellPartID(event.properties.shell.id)
|
||||
const seen = data.tools.has(partID)
|
||||
const command = shell.command ?? ""
|
||||
data.tools.delete(partID)
|
||||
|
|
@ -767,11 +767,11 @@ export function reduceSessionData(input: SessionDataInput): SessionDataOutput {
|
|||
}
|
||||
|
||||
if (!seen && command) {
|
||||
commits.push(startShell(event.properties.callID, command))
|
||||
commits.push(startShell(event.properties.shell.id, command))
|
||||
}
|
||||
|
||||
data.ids.add(partID)
|
||||
commits.push(doneShell(event.properties.callID, command, event.properties.output))
|
||||
commits.push(doneShell(event.properties.shell.id, command, event.properties.output.output))
|
||||
return out(data, commits)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -424,21 +424,21 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
}
|
||||
|
||||
const reduce = (child: ChildState, event: V2Event) => {
|
||||
if (event.type === "prompt.promoted") {
|
||||
if (event.type === "session.prompt.promoted") {
|
||||
if (userFrame(child, event.data.inputID, "")) {
|
||||
touch(child, event.created)
|
||||
notifyDetail(child)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (event.type === "step.started") {
|
||||
if (event.type === "session.step.started") {
|
||||
touch(child, event.created)
|
||||
if (child.label === FALLBACK_LABEL && event.data.agent) child.label = Locale.titlecase(event.data.agent)
|
||||
if (child.status !== "running") child.status = "running"
|
||||
input.emit()
|
||||
return
|
||||
}
|
||||
if (event.type === "text.delta") {
|
||||
if (event.type === "session.text.delta") {
|
||||
const projected = child.projectedText.get(event.data.textID)
|
||||
const covered = projected?.indexOf(event.data.delta) ?? -1
|
||||
if (projected && covered >= 0) {
|
||||
|
|
@ -459,7 +459,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "text.ended") {
|
||||
if (event.type === "session.text.ended") {
|
||||
child.text.set(event.data.textID, event.data.text)
|
||||
child.projectedText.delete(event.data.textID)
|
||||
setFrame(child, `text:${event.data.textID}`, {
|
||||
|
|
@ -474,7 +474,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "reasoning.delta") {
|
||||
if (event.type === "session.reasoning.delta") {
|
||||
const projected = child.projectedReasoning.get(event.data.reasoningID)
|
||||
const covered = projected?.indexOf(event.data.delta) ?? -1
|
||||
if (projected && covered >= 0) {
|
||||
|
|
@ -495,7 +495,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "reasoning.ended") {
|
||||
if (event.type === "session.reasoning.ended") {
|
||||
child.reasoning.set(event.data.reasoningID, event.data.text)
|
||||
child.projectedReasoning.delete(event.data.reasoningID)
|
||||
if (!input.thinking) return
|
||||
|
|
@ -510,11 +510,11 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.input.started") {
|
||||
if (event.type === "session.tool.input.started") {
|
||||
child.tools.set(event.data.callID, { name: event.data.name, input: {}, started: event.created })
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.called") {
|
||||
if (event.type === "session.tool.called") {
|
||||
const current = child.tools.get(event.data.callID)
|
||||
child.tools.set(event.data.callID, {
|
||||
name: event.data.tool,
|
||||
|
|
@ -537,10 +537,10 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.success" || event.type === "tool.failed") {
|
||||
if (event.type === "session.tool.success" || event.type === "session.tool.failed") {
|
||||
if (child.finishedTools.has(event.data.callID)) return
|
||||
const current = child.tools.get(event.data.callID)
|
||||
const failed = event.type === "tool.failed"
|
||||
const failed = event.type === "session.tool.failed"
|
||||
childTool(
|
||||
child,
|
||||
{
|
||||
|
|
@ -577,7 +577,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "step.failed") {
|
||||
if (event.type === "session.step.failed") {
|
||||
setFrame(child, `error:step:${event.data.assistantMessageID}`, {
|
||||
kind: "error",
|
||||
source: "system",
|
||||
|
|
@ -589,7 +589,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
notifyDetail(child)
|
||||
return
|
||||
}
|
||||
if (event.type === "execution.settled") {
|
||||
if (event.type === "session.execution.settled") {
|
||||
child.status =
|
||||
event.data.outcome === "success" ? "completed" : event.data.outcome === "interrupted" ? "cancelled" : "error"
|
||||
touch(child, event.created)
|
||||
|
|
@ -613,15 +613,15 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac
|
|||
|
||||
return {
|
||||
main(event) {
|
||||
if (event.type === "tool.called") {
|
||||
if (event.type === "session.tool.called") {
|
||||
if (event.data.tool === "subagent") pendingCalls.set(event.data.callID, event.data.input)
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.failed") {
|
||||
if (event.type === "session.tool.failed") {
|
||||
pendingCalls.delete(event.data.callID)
|
||||
return
|
||||
}
|
||||
if (event.type !== "tool.success") return
|
||||
if (event.type !== "session.tool.success") return
|
||||
const pending = pendingCalls.get(event.data.callID)
|
||||
pendingCalls.delete(event.data.callID)
|
||||
const found = childSessionID(record(event.data.structured))
|
||||
|
|
|
|||
|
|
@ -213,7 +213,9 @@ function promptAgents(next: SessionTurnInput) {
|
|||
? [
|
||||
{
|
||||
name: part.name,
|
||||
source: part.source ? { start: part.source.start, end: part.source.end, text: part.source.value } : undefined,
|
||||
source: part.source
|
||||
? { start: part.source.start, end: part.source.end, text: part.source.value }
|
||||
: undefined,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
|
|
@ -404,27 +406,39 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
return
|
||||
}
|
||||
if (message.type === "shell") {
|
||||
state.shellCommands.set(message.callID, message.command)
|
||||
state.shellCommands.set(message.shell.id, message.shell.command)
|
||||
const completed = message.time.completed !== undefined
|
||||
if (!render) {
|
||||
// Suppressed history: mark settled shells rendered so live redelivery
|
||||
// stays silent. A still-running shell stays unmarked and renders in
|
||||
// full when its live shell.ended event arrives.
|
||||
if (completed) {
|
||||
state.shellStarted.add(message.callID)
|
||||
state.shellEnded.add(message.callID)
|
||||
state.shellStarted.add(message.shell.id)
|
||||
state.shellEnded.add(message.shell.id)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (!state.shellStarted.has(message.callID)) {
|
||||
state.shellStarted.add(message.callID)
|
||||
write([shellCommit(message.callID, message.command, { text: "running shell", phase: "start", toolState: "running" })])
|
||||
if (!state.shellStarted.has(message.shell.id)) {
|
||||
state.shellStarted.add(message.shell.id)
|
||||
write([
|
||||
shellCommit(message.shell.id, message.shell.command, {
|
||||
text: "running shell",
|
||||
phase: "start",
|
||||
toolState: "running",
|
||||
}),
|
||||
])
|
||||
}
|
||||
if (completed && !state.shellEnded.has(message.callID)) {
|
||||
state.shellEnded.add(message.callID)
|
||||
write([shellCommit(message.callID, message.command, { text: message.output, phase: "progress", toolState: "completed" })])
|
||||
if (completed && message.output && !state.shellEnded.has(message.shell.id)) {
|
||||
state.shellEnded.add(message.shell.id)
|
||||
write([
|
||||
shellCommit(message.shell.id, message.shell.command, {
|
||||
text: message.output.output,
|
||||
phase: "progress",
|
||||
toolState: "completed",
|
||||
}),
|
||||
])
|
||||
}
|
||||
if (completed && state.shellWait?.callID === message.callID) state.shellWait.resolve()
|
||||
if (completed && state.shellWait?.callID === message.shell.id) state.shellWait.resolve()
|
||||
return
|
||||
}
|
||||
if (message.type !== "assistant") return
|
||||
|
|
@ -515,17 +529,17 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
}
|
||||
input.trace?.write("recv.event", event)
|
||||
subagents.main(event)
|
||||
if (event.type === "prompt.promoted") {
|
||||
if (event.type === "session.prompt.promoted") {
|
||||
if (state.wait?.messageID === event.data.inputID) state.wait.promoted = true
|
||||
state.messageIDs.add(event.data.inputID)
|
||||
write([], { phase: "running", status: "waiting for assistant" })
|
||||
return
|
||||
}
|
||||
if (event.type === "step.started") {
|
||||
if (event.type === "session.step.started") {
|
||||
write([], { phase: "running", status: "assistant responding" })
|
||||
return
|
||||
}
|
||||
if (event.type === "skill.activated") {
|
||||
if (event.type === "session.skill.activated") {
|
||||
const messageID = event.id.replace(/^evt_/, "msg_")
|
||||
if (state.wait) state.wait.promoted = true
|
||||
if (state.skillMessages.has(messageID)) return
|
||||
|
|
@ -533,38 +547,56 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
write([skillCommit(messageID, event.data.name)])
|
||||
return
|
||||
}
|
||||
if (event.type === "shell.started") {
|
||||
state.shellCommands.set(event.data.callID, event.data.command)
|
||||
if (event.type === "session.shell.started") {
|
||||
state.shellCommands.set(event.data.shell.id, event.data.shell.command)
|
||||
const wait = state.shellWait
|
||||
if (wait && wait.callID === undefined) wait.callID = event.data.callID
|
||||
if (state.shellStarted.has(event.data.callID)) return
|
||||
state.shellStarted.add(event.data.callID)
|
||||
write([shellCommit(event.data.callID, event.data.command, { text: "running shell", phase: "start", toolState: "running" })], {
|
||||
phase: "running",
|
||||
status: "running shell",
|
||||
})
|
||||
if (wait && wait.callID === undefined) wait.callID = event.data.shell.id
|
||||
if (state.shellStarted.has(event.data.shell.id)) return
|
||||
state.shellStarted.add(event.data.shell.id)
|
||||
write(
|
||||
[
|
||||
shellCommit(event.data.shell.id, event.data.shell.command, {
|
||||
text: "running shell",
|
||||
phase: "start",
|
||||
toolState: "running",
|
||||
}),
|
||||
],
|
||||
{
|
||||
phase: "running",
|
||||
status: "running shell",
|
||||
},
|
||||
)
|
||||
return
|
||||
}
|
||||
if (event.type === "shell.ended") {
|
||||
const command = state.shellCommands.get(event.data.callID) ?? ""
|
||||
if (event.type === "session.shell.ended") {
|
||||
const command = state.shellCommands.get(event.data.shell.id) ?? event.data.shell.command
|
||||
const commits: StreamCommit[] = []
|
||||
if (!state.shellStarted.has(event.data.callID)) {
|
||||
state.shellStarted.add(event.data.callID)
|
||||
if (command) commits.push(shellCommit(event.data.callID, command, { text: "running shell", phase: "start", toolState: "running" }))
|
||||
if (!state.shellStarted.has(event.data.shell.id)) {
|
||||
state.shellStarted.add(event.data.shell.id)
|
||||
if (command)
|
||||
commits.push(
|
||||
shellCommit(event.data.shell.id, command, { text: "running shell", phase: "start", toolState: "running" }),
|
||||
)
|
||||
}
|
||||
if (!state.shellEnded.has(event.data.callID)) {
|
||||
state.shellEnded.add(event.data.callID)
|
||||
commits.push(shellCommit(event.data.callID, command, { text: event.data.output, phase: "progress", toolState: "completed" }))
|
||||
if (!state.shellEnded.has(event.data.shell.id)) {
|
||||
state.shellEnded.add(event.data.shell.id)
|
||||
commits.push(
|
||||
shellCommit(event.data.shell.id, command, {
|
||||
text: event.data.output.output,
|
||||
phase: "progress",
|
||||
toolState: "completed",
|
||||
}),
|
||||
)
|
||||
}
|
||||
const wait = state.shellWait
|
||||
// An unset callID means shell.started has not been observed yet (event
|
||||
// delivery lag); mini serializes its own shells, so adopt this ended.
|
||||
const owned = wait !== undefined && (wait.callID === undefined || wait.callID === event.data.callID)
|
||||
const owned = wait !== undefined && (wait.callID === undefined || wait.callID === event.data.shell.id)
|
||||
write(commits, owned || state.wait ? undefined : { phase: "idle", status: "" })
|
||||
if (owned) wait.resolve()
|
||||
return
|
||||
}
|
||||
if (event.type === "text.delta") {
|
||||
if (event.type === "session.text.delta") {
|
||||
const key = streamPartKey(event.data.assistantMessageID, event.data.textID)
|
||||
const projected = state.projectedText.get(key)
|
||||
const covered = projected?.indexOf(event.data.delta) ?? -1
|
||||
|
|
@ -586,7 +618,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
])
|
||||
return
|
||||
}
|
||||
if (event.type === "text.ended") {
|
||||
if (event.type === "session.text.ended") {
|
||||
const key = streamPartKey(event.data.assistantMessageID, event.data.textID)
|
||||
const previous = state.text.get(key) ?? ""
|
||||
if (event.data.text.length > previous.length)
|
||||
|
|
@ -604,7 +636,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
state.projectedText.delete(key)
|
||||
return
|
||||
}
|
||||
if (event.type === "reasoning.delta") {
|
||||
if (event.type === "session.reasoning.delta") {
|
||||
const key = streamPartKey(event.data.assistantMessageID, event.data.reasoningID)
|
||||
const projected = state.projectedReasoning.get(key)
|
||||
const covered = projected?.indexOf(event.data.delta) ?? -1
|
||||
|
|
@ -627,7 +659,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
])
|
||||
return
|
||||
}
|
||||
if (event.type === "reasoning.ended") {
|
||||
if (event.type === "session.reasoning.ended") {
|
||||
const key = streamPartKey(event.data.assistantMessageID, event.data.reasoningID)
|
||||
const previous = state.reasoning.get(key) ?? ""
|
||||
if (input.thinking && event.data.text.length > previous.length)
|
||||
|
|
@ -645,7 +677,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
state.projectedReasoning.delete(key)
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.input.started") {
|
||||
if (event.type === "session.tool.input.started") {
|
||||
state.tools.set(event.data.callID, {
|
||||
messageID: event.data.assistantMessageID,
|
||||
name: event.data.name,
|
||||
|
|
@ -655,7 +687,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
})
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.called") {
|
||||
if (event.type === "session.tool.called") {
|
||||
if (state.finishedTools.has(event.data.callID)) return
|
||||
const current = state.tools.get(event.data.callID)
|
||||
const item: SessionMessageAssistantTool = {
|
||||
|
|
@ -669,10 +701,10 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
renderTool(event.data.assistantMessageID, item)
|
||||
return
|
||||
}
|
||||
if (event.type === "tool.progress") return
|
||||
if (event.type === "tool.success" || event.type === "tool.failed") {
|
||||
if (event.type === "session.tool.progress") return
|
||||
if (event.type === "session.tool.success" || event.type === "session.tool.failed") {
|
||||
const current = state.tools.get(event.data.callID)
|
||||
const failed = event.type === "tool.failed"
|
||||
const failed = event.type === "session.tool.failed"
|
||||
const item: SessionMessageAssistantTool = {
|
||||
type: "tool",
|
||||
id: event.data.callID,
|
||||
|
|
@ -720,7 +752,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
syncBlockers()
|
||||
return
|
||||
}
|
||||
if (event.type === "step.ended") {
|
||||
if (event.type === "session.step.ended") {
|
||||
const total =
|
||||
event.data.tokens.input +
|
||||
event.data.tokens.output +
|
||||
|
|
@ -734,13 +766,13 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
})
|
||||
return
|
||||
}
|
||||
if (event.type === "step.failed") {
|
||||
if (event.type === "session.step.failed") {
|
||||
state.errors.add(event.data.assistantMessageID)
|
||||
if (state.wait) state.wait.failureRendered = true
|
||||
write([{ kind: "error", source: "system", text: errorMessage(event.data.error), phase: "start" }])
|
||||
return
|
||||
}
|
||||
if (event.type === "execution.settled") {
|
||||
if (event.type === "session.execution.settled") {
|
||||
write([], { phase: "idle", status: "" })
|
||||
const current = state.wait
|
||||
if (!current || (!current.promoted && !current.interrupted)) return
|
||||
|
|
@ -977,10 +1009,7 @@ export async function createSessionTransport(input: StreamInput): Promise<Sessio
|
|||
sessionID: input.sessionID,
|
||||
id: messageID,
|
||||
prompt: {
|
||||
text: [
|
||||
next.prompt.text,
|
||||
...prepared.flatMap((file) => (file.text ? [file.text] : [])),
|
||||
].join("\n\n"),
|
||||
text: [next.prompt.text, ...prepared.flatMap((file) => (file.text ? [file.text] : []))].join("\n\n"),
|
||||
files: attachments.length ? attachments : undefined,
|
||||
agents: agents.length ? agents : undefined,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue