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
|
|
@ -126,8 +126,8 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
const item = position === undefined ? undefined : messages[position]
|
||||
return item?.type === "assistant" ? item : undefined
|
||||
},
|
||||
activeShell(messages: SessionMessage[], callID: string) {
|
||||
const item = messages.findLast((item) => item.type === "shell" && item.callID === callID)
|
||||
shell(messages: SessionMessage[], shellID: string) {
|
||||
const item = messages.findLast((item) => item.type === "shell" && item.shell.id === shellID)
|
||||
return item?.type === "shell" ? item : undefined
|
||||
},
|
||||
latestTool(assistant: SessionMessageAssistant | undefined, callID?: string) {
|
||||
|
|
@ -220,7 +220,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
case "skill.updated":
|
||||
void result.location.skill.refresh(event.location)
|
||||
break
|
||||
case "agent.selected":
|
||||
case "session.agent.selected":
|
||||
if (store.session.info[event.data.sessionID])
|
||||
setStore("session", "info", event.data.sessionID, "agent", event.data.agent)
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
|
|
@ -232,7 +232,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "model.selected":
|
||||
case "session.model.selected":
|
||||
if (store.session.info[event.data.sessionID])
|
||||
setStore("session", "info", event.data.sessionID, "model", event.data.model)
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
|
|
@ -244,11 +244,11 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "renamed":
|
||||
case "session.renamed":
|
||||
if (store.session.info[event.data.sessionID])
|
||||
setStore("session", "info", event.data.sessionID, "title", event.data.title)
|
||||
break
|
||||
case "prompt.promoted": {
|
||||
case "session.prompt.promoted": {
|
||||
setStore("session", "status", event.data.sessionID, "running")
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const position = index.get(event.data.inputID)
|
||||
|
|
@ -264,7 +264,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
break
|
||||
}
|
||||
case "prompt.admitted":
|
||||
case "session.prompt.admitted":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.append(draft, index, {
|
||||
id: event.data.inputID,
|
||||
|
|
@ -287,7 +287,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "synthetic":
|
||||
case "session.synthetic":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.append(draft, index, {
|
||||
id: messageIDFromEvent(event.id),
|
||||
|
|
@ -299,29 +299,28 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "shell.started":
|
||||
case "session.shell.started":
|
||||
setStore("session", "status", event.data.sessionID, "running")
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.append(draft, index, {
|
||||
id: messageIDFromEvent(event.id),
|
||||
type: "shell",
|
||||
callID: event.data.callID,
|
||||
command: event.data.command,
|
||||
output: "",
|
||||
shell: event.data.shell,
|
||||
time: { created: event.created },
|
||||
})
|
||||
})
|
||||
break
|
||||
case "shell.ended":
|
||||
case "session.shell.ended":
|
||||
setStore("session", "status", event.data.sessionID, "idle")
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.activeShell(draft, event.data.callID)
|
||||
message.update(event.data.sessionID, (draft) => {
|
||||
const match = message.shell(draft, event.data.shell.id)
|
||||
if (!match) return
|
||||
match.shell = event.data.shell
|
||||
match.output = event.data.output
|
||||
match.time.completed = event.created
|
||||
})
|
||||
break
|
||||
case "step.started":
|
||||
case "session.step.started":
|
||||
setStore("session", "status", event.data.sessionID, "running")
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
if (index.has(event.data.assistantMessageID)) return
|
||||
|
|
@ -338,7 +337,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "step.ended":
|
||||
case "session.step.ended":
|
||||
setStore("session", "status", event.data.sessionID, "running")
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const currentAssistant = message.assistant(draft, index, event.data.assistantMessageID)
|
||||
|
|
@ -351,7 +350,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
currentAssistant.snapshot = { ...currentAssistant.snapshot, end: event.data.snapshot }
|
||||
})
|
||||
break
|
||||
case "step.failed":
|
||||
case "session.step.failed":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const currentAssistant = message.assistant(draft, index, event.data.assistantMessageID)
|
||||
if (!currentAssistant) return
|
||||
|
|
@ -360,7 +359,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
currentAssistant.error = event.data.error
|
||||
})
|
||||
break
|
||||
case "text.started":
|
||||
case "session.text.started":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.assistant(draft, index, event.data.assistantMessageID)?.content.push({
|
||||
type: "text",
|
||||
|
|
@ -369,7 +368,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "text.delta":
|
||||
case "session.text.delta":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestText(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -378,7 +377,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
if (match) match.text += event.data.delta
|
||||
})
|
||||
break
|
||||
case "text.ended":
|
||||
case "session.text.ended":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestText(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -387,7 +386,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
if (match) match.text = event.data.text
|
||||
})
|
||||
break
|
||||
case "tool.input.started":
|
||||
case "session.tool.input.started":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.assistant(draft, index, event.data.assistantMessageID)?.content.push({
|
||||
type: "tool",
|
||||
|
|
@ -398,7 +397,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "tool.input.delta":
|
||||
case "session.tool.input.delta":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestTool(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -407,7 +406,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
if (match?.state.status === "pending") match.state.input += event.data.delta
|
||||
})
|
||||
break
|
||||
case "tool.input.ended":
|
||||
case "session.tool.input.ended":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestTool(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -416,7 +415,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
if (match?.state.status === "pending") match.state.input = event.data.text
|
||||
})
|
||||
break
|
||||
case "tool.called":
|
||||
case "session.tool.called":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestTool(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -428,7 +427,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
match.state = { status: "running", input: event.data.input, structured: {}, content: [] }
|
||||
})
|
||||
break
|
||||
case "tool.progress":
|
||||
case "session.tool.progress":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestTool(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -439,7 +438,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
match.state.content = [...event.data.content]
|
||||
})
|
||||
break
|
||||
case "tool.success":
|
||||
case "session.tool.success":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestTool(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -461,7 +460,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
match.time.completed = event.created
|
||||
})
|
||||
break
|
||||
case "tool.failed":
|
||||
case "session.tool.failed":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestTool(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -484,7 +483,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
match.time.completed = event.created
|
||||
})
|
||||
break
|
||||
case "reasoning.started":
|
||||
case "session.reasoning.started":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.assistant(draft, index, event.data.assistantMessageID)?.content.push({
|
||||
type: "reasoning",
|
||||
|
|
@ -495,7 +494,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
})
|
||||
})
|
||||
break
|
||||
case "reasoning.delta":
|
||||
case "session.reasoning.delta":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestReasoning(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -504,7 +503,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
if (match) match.text += event.data.delta
|
||||
})
|
||||
break
|
||||
case "reasoning.ended":
|
||||
case "session.reasoning.ended":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
const match = message.latestReasoning(
|
||||
message.assistant(draft, index, event.data.assistantMessageID),
|
||||
|
|
@ -517,25 +516,25 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({
|
|||
}
|
||||
})
|
||||
break
|
||||
case "retried":
|
||||
case "compaction.started":
|
||||
case "session.retried":
|
||||
case "session.compaction.started":
|
||||
setStore("session", "status", event.data.sessionID, "running")
|
||||
break
|
||||
case "execution.settled":
|
||||
case "session.execution.settled":
|
||||
setStore("session", "status", event.data.sessionID, "idle")
|
||||
break
|
||||
case "revert.staged":
|
||||
case "session.revert.staged":
|
||||
if (store.session.info[event.data.sessionID])
|
||||
setStore("session", "info", event.data.sessionID, "revert", event.data.revert)
|
||||
break
|
||||
case "revert.cleared":
|
||||
case "revert.committed":
|
||||
case "session.revert.cleared":
|
||||
case "session.revert.committed":
|
||||
if (store.session.info[event.data.sessionID])
|
||||
setStore("session", "info", event.data.sessionID, "revert", undefined)
|
||||
break
|
||||
case "compaction.delta":
|
||||
case "session.compaction.delta":
|
||||
break
|
||||
case "compaction.ended":
|
||||
case "session.compaction.ended":
|
||||
message.update(event.data.sessionID, (draft, index) => {
|
||||
message.append(draft, index, {
|
||||
id: messageIDFromEvent(event.id),
|
||||
|
|
|
|||
|
|
@ -74,17 +74,17 @@ const tui: TuiPlugin = async (api) => {
|
|||
notify(api, sessionID, "Session done", session?.parentID ? "subagent_done" : "done")
|
||||
}
|
||||
|
||||
api.event.on("prompt.promoted", (event) => started(event.data.sessionID))
|
||||
api.event.on("shell.started", (event) => started(event.data.sessionID))
|
||||
api.event.on("step.started", (event) => started(event.data.sessionID))
|
||||
api.event.on("retried", (event) => started(event.data.sessionID))
|
||||
api.event.on("compaction.started", (event) => started(event.data.sessionID))
|
||||
api.event.on("shell.ended", (event) => ended(event.data.sessionID))
|
||||
api.event.on("step.ended", (event) => {
|
||||
api.event.on("session.prompt.promoted", (event) => started(event.data.sessionID))
|
||||
api.event.on("session.shell.started", (event) => started(event.data.sessionID))
|
||||
api.event.on("session.step.started", (event) => started(event.data.sessionID))
|
||||
api.event.on("session.retried", (event) => started(event.data.sessionID))
|
||||
api.event.on("session.compaction.started", (event) => started(event.data.sessionID))
|
||||
api.event.on("session.shell.ended", (event) => ended(event.data.sessionID))
|
||||
api.event.on("session.step.ended", (event) => {
|
||||
if (event.data.finish === "tool-calls") return
|
||||
ended(event.data.sessionID)
|
||||
})
|
||||
api.event.on("step.failed", (event) => {
|
||||
api.event.on("session.step.failed", (event) => {
|
||||
const sessionID = event.data.sessionID
|
||||
if (!active.has(sessionID)) return
|
||||
errored.add(sessionID)
|
||||
|
|
|
|||
|
|
@ -1346,7 +1346,7 @@ function RevertMessage(props: {
|
|||
|
||||
function ShellMessage(props: { message: Extract<SessionMessage, { type: "shell" }> }) {
|
||||
const { theme } = useTheme()
|
||||
const output = createMemo(() => stripAnsi(props.message.output.trim()))
|
||||
const output = createMemo(() => stripAnsi(props.message.output?.output.trim() ?? ""))
|
||||
|
||||
return (
|
||||
<box
|
||||
|
|
@ -1359,7 +1359,7 @@ function ShellMessage(props: { message: Extract<SessionMessage, { type: "shell"
|
|||
customBorderChars={SplitBorder.customBorderChars}
|
||||
borderColor={theme.background}
|
||||
>
|
||||
<text fg={theme.text}>$ {props.message.command}</text>
|
||||
<text fg={theme.text}>$ {props.message.shell.command}</text>
|
||||
<Show when={output()}>
|
||||
<text fg={theme.textMuted}>{output()}</text>
|
||||
</Show>
|
||||
|
|
@ -1408,13 +1408,7 @@ function UserMessage(props: { message: SessionMessageUser }) {
|
|||
>
|
||||
<text fg={theme.text}>{props.message.text}</text>
|
||||
<Show when={files().length}>
|
||||
<box
|
||||
flexDirection="row"
|
||||
paddingBottom={metadataVisible() ? 1 : 0}
|
||||
paddingTop={1}
|
||||
gap={1}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
<box flexDirection="row" paddingBottom={metadataVisible() ? 1 : 0} paddingTop={1} gap={1} flexWrap="wrap">
|
||||
<For each={files()}>
|
||||
{(file) => {
|
||||
const directory = file.mime === "application/x-directory"
|
||||
|
|
@ -1744,7 +1738,8 @@ function ToolPart(props: { part: SessionMessageAssistantTool }) {
|
|||
return Boolean(shellID && data.shell.get(shellID))
|
||||
}
|
||||
if (display() === "subagent") {
|
||||
const sessionID = stringValue(props.part.state.structured.sessionID) ?? stringValue(props.part.state.structured.sessionId)
|
||||
const sessionID =
|
||||
stringValue(props.part.state.structured.sessionID) ?? stringValue(props.part.state.structured.sessionId)
|
||||
return Boolean(sessionID && data.session.status(sessionID) === "running")
|
||||
}
|
||||
return false
|
||||
|
|
@ -2660,7 +2655,8 @@ function formatSessionTranscript(
|
|||
) {
|
||||
const body = messages.flatMap((message) => {
|
||||
if (message.type === "user") return [`## User\n\n${message.text}`]
|
||||
if (message.type === "shell") return [`## Shell\n\n\`\`\`\n$ ${message.command}\n${message.output}\n\`\`\``]
|
||||
if (message.type === "shell")
|
||||
return [`## Shell\n\n\`\`\`\n$ ${message.shell.command}\n${message.output?.output ?? ""}\n\`\`\``]
|
||||
if (message.type !== "assistant") return []
|
||||
const content = message.content.flatMap((item) => {
|
||||
if (item.type === "text") return [item.text]
|
||||
|
|
|
|||
|
|
@ -133,42 +133,42 @@ export function createSessionRows(sessionID: Accessor<string>) {
|
|||
if (event.data.sessionID === sessionID()) appendMessage(event.data.inputID)
|
||||
}
|
||||
const subscriptions = [
|
||||
data.on("prompt.admitted", input),
|
||||
data.on("prompt.promoted", input),
|
||||
data.on("session.prompt.admitted", input),
|
||||
data.on("session.prompt.promoted", input),
|
||||
data.on("session.context.updated", message),
|
||||
data.on("synthetic", (event) => {
|
||||
data.on("session.synthetic", (event) => {
|
||||
if (event.data.sessionID === sessionID() && event.data.description?.trim())
|
||||
appendMessage(event.id.replace(/^evt_/, "msg_"))
|
||||
}),
|
||||
data.on("shell.started", message),
|
||||
data.on("agent.selected", message),
|
||||
data.on("model.selected", message),
|
||||
data.on("compaction.ended", message),
|
||||
data.on("text.delta", (event) => {
|
||||
data.on("session.shell.started", message),
|
||||
data.on("session.agent.selected", message),
|
||||
data.on("session.model.selected", message),
|
||||
data.on("session.compaction.ended", message),
|
||||
data.on("session.text.delta", (event) => {
|
||||
if (event.data.sessionID === sessionID())
|
||||
appendPart({ messageID: event.data.assistantMessageID, partID: event.data.textID })
|
||||
}),
|
||||
data.on("text.ended", (event) => {
|
||||
data.on("session.text.ended", (event) => {
|
||||
if (event.data.sessionID === sessionID() && event.data.text.trim())
|
||||
appendPart({ messageID: event.data.assistantMessageID, partID: event.data.textID })
|
||||
}),
|
||||
data.on("reasoning.delta", (event) => {
|
||||
data.on("session.reasoning.delta", (event) => {
|
||||
if (event.data.sessionID === sessionID())
|
||||
appendPart({ messageID: event.data.assistantMessageID, partID: event.data.reasoningID })
|
||||
}),
|
||||
data.on("reasoning.ended", (event) => {
|
||||
data.on("session.reasoning.ended", (event) => {
|
||||
if (event.data.sessionID === sessionID() && event.data.text.trim())
|
||||
appendPart({ messageID: event.data.assistantMessageID, partID: event.data.reasoningID })
|
||||
}),
|
||||
data.on("tool.input.started", (event) => {
|
||||
data.on("session.tool.input.started", (event) => {
|
||||
if (event.data.sessionID === sessionID())
|
||||
appendPart({ messageID: event.data.assistantMessageID, partID: event.data.callID }, event.data.name)
|
||||
}),
|
||||
data.on("step.ended", (event) => {
|
||||
data.on("session.step.ended", (event) => {
|
||||
if (event.data.sessionID !== sessionID() || ["tool-calls", "unknown"].includes(event.data.finish)) return
|
||||
appendFooter(event.data.assistantMessageID)
|
||||
}),
|
||||
data.on("step.failed", (event) => {
|
||||
data.on("session.step.failed", (event) => {
|
||||
if (event.data.sessionID === sessionID()) appendFooter(event.data.assistantMessageID)
|
||||
}),
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue