fix(app): own v2 rendering projections
This commit is contained in:
parent
689fb214e0
commit
d4105e04e5
6 changed files with 209 additions and 45 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import type { OpenCodeEvent } from "@opencode-ai/client/promise"
|
||||
import type { Event } from "@/types"
|
||||
import type { Event, PermissionRequest } from "@/types"
|
||||
import { createSimpleContext } from "@opencode-ai/ui/context"
|
||||
import { createGlobalEmitter } from "@solid-primitives/event-bus"
|
||||
import { makeEventListener } from "@solid-primitives/event-listener"
|
||||
|
|
@ -39,9 +39,9 @@ export function adaptServerEvent(event: OpenCodeEvent): ServerEvent {
|
|||
event.data.source?.type === "tool"
|
||||
? { messageID: event.data.source.messageID, callID: event.data.source.callID }
|
||||
: undefined,
|
||||
},
|
||||
} satisfies PermissionRequest,
|
||||
current: event,
|
||||
} as ServerEvent
|
||||
}
|
||||
}
|
||||
return { id: event.id, type: event.type, properties: event.data, current: event } as ServerEvent
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ const session = (id: string, parentID?: string): Session => ({
|
|||
type UserMessage = Extract<Message, { role: "user" }>
|
||||
type AssistantMessage = Extract<Message, { role: "assistant" }>
|
||||
type TextPart = Extract<Part, { type: "text" }>
|
||||
type CurrentToolObject = Extract<SessionMessageAssistantTool["state"], { status: "running" }>["input"]
|
||||
type MessageResponse = {
|
||||
data: { info: Message; parts: Part[] }[]
|
||||
response: { headers: Headers }
|
||||
|
|
@ -97,21 +98,21 @@ function currentMessages(data: MessageResponse["data"]): SessionMessageInfo[] {
|
|||
if (part.state.status === "running")
|
||||
return {
|
||||
status: "running" as const,
|
||||
input: part.state.input,
|
||||
metadata: part.state.metadata ?? {},
|
||||
input: part.state.input as CurrentToolObject,
|
||||
metadata: (part.state.metadata ?? {}) as CurrentToolObject,
|
||||
}
|
||||
if (part.state.status === "error")
|
||||
return {
|
||||
status: "error" as const,
|
||||
input: part.state.input,
|
||||
input: part.state.input as CurrentToolObject,
|
||||
error: { type: "tool_error", message: part.state.error },
|
||||
metadata: part.state.metadata,
|
||||
metadata: part.state.metadata as CurrentToolObject | undefined,
|
||||
}
|
||||
return {
|
||||
status: "completed" as const,
|
||||
input: part.state.input,
|
||||
input: part.state.input as CurrentToolObject,
|
||||
content: [{ type: "text" as const, text: part.state.output }],
|
||||
metadata: part.state.metadata,
|
||||
metadata: part.state.metadata as CurrentToolObject,
|
||||
}
|
||||
})()
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -1,59 +1,45 @@
|
|||
import type {
|
||||
AgentPart,
|
||||
AssistantMessage,
|
||||
EventSubscribeOutput,
|
||||
FileDiffInfo,
|
||||
FileDiffLegacyInfo,
|
||||
FilePart,
|
||||
FilePartSource,
|
||||
Message,
|
||||
Part,
|
||||
Project,
|
||||
QuestionAnswer,
|
||||
QuestionInfo,
|
||||
QuestionV2Request,
|
||||
QuestionRequest,
|
||||
ReferenceInfo,
|
||||
SessionInfo,
|
||||
SessionNotFoundError,
|
||||
SessionStatus,
|
||||
SessionV1Info,
|
||||
SessionsResponse,
|
||||
TextPart,
|
||||
ToolPart,
|
||||
UserMessage,
|
||||
} from "@opencode-ai/client/promise"
|
||||
import type { NormalizedProviderListResponse } from "@opencode-ai/session-ui/context"
|
||||
|
||||
export type {
|
||||
AgentPart,
|
||||
AssistantMessage,
|
||||
FilePart,
|
||||
FilePartSource,
|
||||
Message,
|
||||
Part,
|
||||
Project,
|
||||
QuestionAnswer,
|
||||
QuestionRequest,
|
||||
ReferenceInfo,
|
||||
SessionNotFoundError,
|
||||
SessionStatus,
|
||||
TextPart,
|
||||
ToolPart,
|
||||
UserMessage,
|
||||
}
|
||||
|
||||
export type Session = SessionV1Info
|
||||
export type SessionV2Info = SessionInfo
|
||||
export type V2SessionListResponse = SessionsResponse
|
||||
export type QuestionRequest = QuestionV2Request
|
||||
export type SnapshotFileDiff = FileDiffLegacyInfo
|
||||
export type VcsFileDiff = FileDiffInfo
|
||||
|
||||
export type Event = EventSubscribeOutput extends infer Item
|
||||
type CurrentEvent = EventSubscribeOutput extends infer Item
|
||||
? Item extends { type: infer Type extends string; data: infer Data }
|
||||
? { type: Type; properties: Data }
|
||||
: never
|
||||
: never
|
||||
|
||||
export type Event =
|
||||
| Exclude<CurrentEvent, { type: "permission.asked" }>
|
||||
| { type: "permission.asked"; properties: PermissionRequest }
|
||||
|
||||
export type EventSessionError = Extract<Event, { type: "session.error" }>
|
||||
|
||||
export type PermissionRequest = {
|
||||
|
|
@ -66,6 +52,193 @@ export type PermissionRequest = {
|
|||
tool?: { messageID: string; callID: string }
|
||||
}
|
||||
|
||||
type MessageError =
|
||||
| { name: "ProviderAuthError"; data: { providerID: string; message: string } }
|
||||
| { name: "UnknownError"; data: { message: string; ref?: string } }
|
||||
| { name: "MessageOutputLengthError"; data: Record<string, unknown> }
|
||||
| { name: "MessageAbortedError"; data: { message: string } }
|
||||
| { name: "StructuredOutputError"; data: { message: string; retries: number } }
|
||||
| { name: "ContextOverflowError"; data: { message: string; responseBody?: string } }
|
||||
| { name: "ContentFilterError"; data: { message: string } }
|
||||
| {
|
||||
name: "APIError"
|
||||
data: {
|
||||
message: string
|
||||
statusCode?: number
|
||||
isRetryable: boolean
|
||||
responseHeaders?: Record<string, string>
|
||||
responseBody?: string
|
||||
metadata?: Record<string, string>
|
||||
}
|
||||
}
|
||||
|
||||
export type UserMessage = {
|
||||
id: string
|
||||
sessionID: string
|
||||
role: "user"
|
||||
time: { created: number }
|
||||
format?: { type: "text" } | { type: "json_schema"; schema: Record<string, unknown>; retryCount?: number }
|
||||
summary?: { title?: string; body?: string; diffs: SnapshotFileDiff[] }
|
||||
agent: string
|
||||
model: { providerID: string; modelID: string; variant?: string }
|
||||
system?: string
|
||||
tools?: Record<string, boolean>
|
||||
}
|
||||
|
||||
export type AssistantMessage = {
|
||||
id: string
|
||||
sessionID: string
|
||||
role: "assistant"
|
||||
time: { created: number; completed?: number }
|
||||
error?: MessageError
|
||||
parentID: string
|
||||
modelID: string
|
||||
providerID: string
|
||||
mode: string
|
||||
agent: string
|
||||
path: { cwd: string; root: string }
|
||||
summary?: boolean
|
||||
cost: number
|
||||
tokens: {
|
||||
total?: number
|
||||
input: number
|
||||
output: number
|
||||
reasoning: number
|
||||
cache: { read: number; write: number }
|
||||
}
|
||||
structured?: unknown
|
||||
variant?: string
|
||||
finish?: string
|
||||
}
|
||||
|
||||
export type Message = UserMessage | AssistantMessage
|
||||
|
||||
type PartBase = { id: string; sessionID: string; messageID: string }
|
||||
|
||||
export type TextPart = PartBase & {
|
||||
type: "text"
|
||||
text: string
|
||||
synthetic?: boolean
|
||||
ignored?: boolean
|
||||
time?: { start: number; end?: number }
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
type FilePartSourceText = { value: string; start: number; end: number }
|
||||
type FileSource = { text: FilePartSourceText; type: "file"; path: string }
|
||||
type SymbolSource = {
|
||||
text: FilePartSourceText
|
||||
type: "symbol"
|
||||
path: string
|
||||
range: { start: { line: number; character: number }; end: { line: number; character: number } }
|
||||
name: string
|
||||
kind: number
|
||||
}
|
||||
type ResourceSource = { text: FilePartSourceText; type: "resource"; clientName: string; uri: string }
|
||||
|
||||
export type FilePartSource = FileSource | SymbolSource | ResourceSource
|
||||
|
||||
export type FilePart = PartBase & {
|
||||
type: "file"
|
||||
mime: string
|
||||
filename?: string
|
||||
url: string
|
||||
source?: FilePartSource
|
||||
}
|
||||
|
||||
export type ToolState =
|
||||
| { status: "pending"; input: Record<string, unknown>; raw: string }
|
||||
| {
|
||||
status: "running"
|
||||
input: Record<string, unknown>
|
||||
title?: string
|
||||
metadata?: Record<string, unknown>
|
||||
time: { start: number }
|
||||
}
|
||||
| {
|
||||
status: "completed"
|
||||
input: Record<string, unknown>
|
||||
output: string
|
||||
title: string
|
||||
metadata: Record<string, unknown>
|
||||
time: { start: number; end: number; compacted?: number }
|
||||
attachments?: FilePart[]
|
||||
}
|
||||
| {
|
||||
status: "error"
|
||||
input: Record<string, unknown>
|
||||
error: string
|
||||
metadata?: Record<string, unknown>
|
||||
time: { start: number; end: number }
|
||||
}
|
||||
|
||||
export type ToolPart = PartBase & {
|
||||
type: "tool"
|
||||
callID: string
|
||||
tool: string
|
||||
state: ToolState
|
||||
metadata?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export type AgentPart = PartBase & {
|
||||
type: "agent"
|
||||
name: string
|
||||
source?: { value: string; start: number; end: number }
|
||||
}
|
||||
|
||||
type ReasoningPart = PartBase & {
|
||||
type: "reasoning"
|
||||
text: string
|
||||
metadata?: Record<string, unknown>
|
||||
time: { start: number; end?: number }
|
||||
}
|
||||
|
||||
type SubtaskPart = PartBase & {
|
||||
type: "subtask"
|
||||
prompt: string
|
||||
description: string
|
||||
agent: string
|
||||
model?: { providerID: string; modelID: string }
|
||||
command?: string
|
||||
}
|
||||
|
||||
type StepStartPart = PartBase & { type: "step-start"; snapshot?: string }
|
||||
type StepFinishPart = PartBase & {
|
||||
type: "step-finish"
|
||||
reason: string
|
||||
snapshot?: string
|
||||
cost: number
|
||||
tokens: AssistantMessage["tokens"]
|
||||
}
|
||||
type SnapshotPart = PartBase & { type: "snapshot"; snapshot: string }
|
||||
type PatchPart = PartBase & { type: "patch"; hash: string; files: string[] }
|
||||
type RetryPart = PartBase & {
|
||||
type: "retry"
|
||||
attempt: number
|
||||
error: Extract<MessageError, { name: "APIError" }>
|
||||
time: { created: number }
|
||||
}
|
||||
type CompactionPart = PartBase & {
|
||||
type: "compaction"
|
||||
auto: boolean
|
||||
overflow?: boolean
|
||||
tail_start_id?: string
|
||||
}
|
||||
|
||||
export type Part =
|
||||
| TextPart
|
||||
| SubtaskPart
|
||||
| ReasoningPart
|
||||
| FilePart
|
||||
| ToolPart
|
||||
| StepStartPart
|
||||
| StepFinishPart
|
||||
| SnapshotPart
|
||||
| PatchPart
|
||||
| AgentPart
|
||||
| RetryPart
|
||||
| CompactionPart
|
||||
|
||||
export type Todo = {
|
||||
content: string
|
||||
status: string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue