view

package
v0.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplyBackgroundTaskSnapshots

func ApplyBackgroundTaskSnapshots(turns []UITurn, tasks []UIBackgroundTask)

ApplyBackgroundTaskSnapshots overlays live background-task state onto converted UI turns. This keeps persisted background_started tool results accurate after a page reload.

Types

type UIAttachment

type UIAttachment struct {
	ID          string         `json:"id,omitempty"`
	Type        string         `json:"type"`
	Path        string         `json:"path,omitempty"`
	URL         string         `json:"url,omitempty"`
	Base64      string         `json:"base64,omitempty"`
	Name        string         `json:"name,omitempty"`
	ContentHash string         `json:"content_hash,omitempty"`
	BotID       string         `json:"bot_id,omitempty"`
	Mime        string         `json:"mime,omitempty"`
	Size        int64          `json:"size,omitempty"`
	StorageKey  string         `json:"storage_key,omitempty"`
	Metadata    map[string]any `json:"metadata,omitempty"`

} // @name conversation.UIAttachment

UIAttachment is the normalized attachment shape used by the web frontend.

func UIAttachmentFromAgentAttachment

func UIAttachmentFromAgentAttachment(attachment event.FileAttachment) UIAttachment

UIAttachmentFromAgentAttachment adapts a runtime file attachment to the UI shape, including the bot_id/storage_key metadata extraction the UI needs to resolve asset URLs.

func UIAttachmentsFromTurnAttachments

func UIAttachmentsFromTurnAttachments(botID string, attachments []turn.Attachment) []UIAttachment

UIAttachmentsFromTurnAttachments converts turn attachments into the normalized UI shape for live runtime projections. Runtime state carries media references, not the uploaded bytes: Base64 is deliberately not copied, which would duplicate every attachment into the live backend.

type UIBackgroundTask

type UIBackgroundTask struct {
	TaskID         string `json:"task_id"`
	Status         string `json:"status"`
	Command        string `json:"command,omitempty"`
	AgentID        string `json:"agent_id,omitempty"`
	AgentSessionID string `json:"agent_session_id,omitempty"`
	OutputFile     string `json:"output_file,omitempty"`
	ExitCode       int32  `json:"exit_code,omitempty"`
	Duration       string `json:"duration,omitempty"`
	OutputTail     string `json:"output_tail,omitempty"`
	Stream         string `json:"stream,omitempty"`
	Chunk          string `json:"chunk,omitempty"`
	Stalled        bool   `json:"stalled,omitempty"`

} // @name conversation.UIBackgroundTask

UIBackgroundTask is the compact background exec state sent to the Web UI.

type UIExecutionLocation

type UIExecutionLocation struct {
	Kind string `json:"kind"`
	Name string `json:"name"`

} // @name conversation.UIExecutionLocation

type UIForwardRef

type UIForwardRef struct {
	MessageID          string `json:"message_id,omitempty"`
	FromUserID         string `json:"from_user_id,omitempty"`
	FromConversationID string `json:"from_conversation_id,omitempty"`
	Sender             string `json:"sender,omitempty"`
	Date               int64  `json:"date,omitempty"`

} // @name conversation.UIForwardRef

type UIMessage

type UIMessage struct {
	ID                 int                  `json:"id"`
	Type               UIMessageType        `json:"type"`
	Content            string               `json:"content,omitempty"`
	Name               string               `json:"name,omitempty"`
	Input              any                  `json:"input,omitempty"`
	Output             any                  `json:"output,omitempty"`
	ToolCallID         string               `json:"tool_call_id,omitempty"`
	Running            *bool                `json:"running,omitempty"`
	Progress           []any                `json:"progress,omitempty"`
	ElapsedTimeSeconds *float64             `json:"elapsed_time_seconds,omitempty"`
	Approval           *UIToolApproval      `json:"approval,omitempty"`
	ExecutionLocation  *UIExecutionLocation `json:"execution_location,omitempty"`
	// Diff is a UI-only unified diff attached to the tool call at execution
	// time (edit/write tools). It never reaches the model: rows persist it
	// under the diffs metadata key — on the assistant row (lifted out of
	// providerMetadata at store time) or, for the deferred-approval path, on
	// the tool message row — never inside the tool result.
	Diff            string             `json:"diff,omitempty"`
	UserInput       *UIUserInput       `json:"user_input,omitempty"`
	Attachments     []UIAttachment     `json:"attachments,omitempty"`
	Background      *UIBackgroundTask  `json:"background_task,omitempty"`
	ReasoningTiming *UIReasoningTiming `json:"reasoning_timing,omitempty"`
	Code            string             `json:"code,omitempty"`
	// Args are the machine-readable parameters of a notice block: the string
	// values of the runtime_notice event metadata (dep_id and install_task_id
	// for a workspace dependency notice, for instance). The client renders
	// actions from them instead of parsing Content.
	Args map[string]string `json:"args,omitempty"`

} // @name conversation.UIMessage

UIMessage is the normalized assistant output block used by the web frontend.

func ConvertModelMessagesToUIAssistantMessages

func ConvertModelMessagesToUIAssistantMessages(messages []turn.ModelMessage) []UIMessage

ConvertModelMessagesToUIAssistantMessages converts assistant/tool output messages into frontend-friendly UI message blocks.

func ConvertRawModelMessagesToUIAssistantMessages

func ConvertRawModelMessagesToUIAssistantMessages(raw json.RawMessage) []UIMessage

ConvertRawModelMessagesToUIAssistantMessages converts terminal stream payload messages into frontend-friendly assistant UI messages.

type UIMessageStreamConverter

type UIMessageStreamConverter struct {
	// contains filtered or unexported fields
}

UIMessageStreamConverter converts low-level stream events into complete UI messages.

func NewUIMessageStreamConverter

func NewUIMessageStreamConverter() *UIMessageStreamConverter

NewUIMessageStreamConverter creates a new UI stream converter.

func (*UIMessageStreamConverter) ConvertTerminalMessages

func (c *UIMessageStreamConverter) ConvertTerminalMessages(raw json.RawMessage) []UIMessage

ConvertTerminalMessages converts the terminal snapshot into UI messages whose IDs line up with the blocks this converter emitted during the live stream. The client orders and upserts blocks by ID, and the snapshot regenerates only text/reasoning/tool blocks from raw model messages — attachments exist solely as stream events. A plain sequential renumbering would therefore shift onto the IDs of live attachment blocks and overwrite them at stream end (the generated image flashes away, then reappears after the history refresh). Instead each snapshot block reuses the ID of its live counterpart — tools are matched by tool call ID, text/reasoning positionally within their kind — and only blocks without one get fresh IDs.

func (*UIMessageStreamConverter) HandleEvent

HandleEvent updates converter state and returns zero or one complete UI messages.

type UIMessageStreamEvent

type UIMessageStreamEvent struct {
	Type        string
	Delta       string
	ToolName    string
	ToolCallID  string
	Input       any
	Output      any
	Progress    any
	Attachments []UIAttachment
	Error       string
	ApprovalID  string
	UserInputID string
	ShortID     int
	Status      string
	Code        string
	Metadata    map[string]any
}

UIMessageStreamEvent is the generic event shape accepted by the UI stream converter. The handler layer adapts agent/channel events to this struct to avoid package cycles.

func UIStreamEventFromAgentEvent

func UIStreamEventFromAgentEvent(ev event.StreamEvent) UIMessageStreamEvent

UIStreamEventFromAgentEvent adapts a runtime stream event to the UI converter's input shape. This is the ONLY adaptation point between the streaming vocabulary (internal/agent/event) and UI rendering - every delivery path (WS handler, trigger/background delivery, parity tests) must use it. It previously existed as two hand-maintained copies (handlers and flow) that had already drifted: one extracted bot_id/storage_key from attachment metadata, the other silently didn't.

type UIMessageType

type UIMessageType string // @name conversation.UIMessageType

UIMessageType identifies the frontend-friendly message block type.

const (
	UIMessageText        UIMessageType = "text"
	UIMessageReasoning   UIMessageType = "reasoning"
	UIMessageTool        UIMessageType = "tool"
	UIMessageAttachments UIMessageType = "attachments"
	UIMessageError       UIMessageType = "error"
	UIMessageCommand     UIMessageType = "command"
	UIMessageStatus      UIMessageType = "status"
	// UIMessageNotice is an inline runtime degradation notice (tools
	// unavailable, an interaction declined). Name carries the machine code,
	// Content the human-readable text.
	UIMessageNotice UIMessageType = "notice"
)

type UIReasoningTiming

type UIReasoningTiming struct {
	DurationMS int64 `json:"duration_ms"`

} // @name conversation.UIReasoningTiming

UIReasoningTiming is the persisted server observation for one reasoning block. It is absent for legacy rows and non-streaming responses whose block boundaries were not observable.

type UIReplyRef

type UIReplyRef struct {
	MessageID   string         `json:"message_id,omitempty"`
	Sender      string         `json:"sender,omitempty"`
	Preview     string         `json:"preview,omitempty"`
	Attachments []UIAttachment `json:"attachments,omitempty"`

} // @name conversation.UIReplyRef

type UIToolApproval

type UIToolApproval struct {
	ApprovalID     string `json:"approval_id"`
	ShortID        int    `json:"short_id,omitempty"`
	Status         string `json:"status"`
	DecisionReason string `json:"decision_reason,omitempty"`
	CanApprove     bool   `json:"can_approve,omitempty"`
	// Options are the agent-provided permission options, verbatim; the client
	// renders one action per option and answers with the chosen option id.
	Options          []UIToolApprovalOption `json:"options,omitempty"`
	SelectedOptionID string                 `json:"selected_option_id,omitempty"`

} // @name conversation.UIToolApproval

type UIToolApprovalOption

type UIToolApprovalOption struct {
	ID   string `json:"id"`
	Name string `json:"name,omitempty"`
	Kind string `json:"kind,omitempty"`

} // @name conversation.UIToolApprovalOption

type UITurn

type UITurn struct {
	// RuntimeForkable means this persisted turn has a runtime fork anchor.
	// Session-level runtime support and access permissions still apply.
	RuntimeForkable bool `json:"runtime_forkable"`

	TurnID string `json:"turn_id" validate:"required" format:"uuid"`
	// TurnPosition is the immutable turn-level sequence reserved at admission.
	// The frontend uses it to order turns and reconcile the settled list
	// against live/optimistic turns; never derived from text or timestamps.
	TurnPosition      *int64                `json:"turn_position,omitempty"`
	Role              string                `json:"role" validate:"required" enums:"user,assistant,system"`
	Kind              string                `json:"kind,omitempty"`
	Messages          []UIMessage           `json:"messages,omitempty"`
	Text              string                `json:"text,omitempty"`
	UserMessageKind   string                `json:"user_message_kind,omitempty"`
	SkillActivation   *turn.SkillActivation `json:"skill_activation,omitempty"`
	Attachments       []UIAttachment        `json:"attachments,omitempty"`
	Reply             *UIReplyRef           `json:"reply,omitempty"`
	Forward           *UIForwardRef         `json:"forward,omitempty"`
	BackgroundTask    *UIBackgroundTask     `json:"background_task,omitempty"`
	Timestamp         time.Time             `json:"timestamp" validate:"required" format:"date-time"`
	Platform          string                `json:"platform,omitempty"`
	SenderDisplayName string                `json:"sender_display_name,omitempty"`
	SenderAvatarURL   string                `json:"sender_avatar_url,omitempty"`
	SenderUserID      string                `json:"sender_user_id,omitempty"`
	ExternalMessageID string                `json:"external_message_id,omitempty"`
	ID                string                `json:"id,omitempty"`

} // @name conversation.UITurn

UITurn is the normalized chat turn used by the web frontend.

func ConvertMessagesToUITurns

func ConvertMessagesToUITurns(messages []messagepkg.Message) []UITurn

ConvertMessagesToUITurns converts persisted message rows into frontend-friendly turns.

func NewRequestUserTurn

func NewRequestUserTurn(cmd turn.StartTurnCommand, turnID string) *UITurn

NewRequestUserTurn builds the subscriber-facing projection of the user message that fired a run, so subscribers watching a thread see the triggering message while the run is still executing — not only after the step committer lands it in history.

Two invariants keep the live bubble seamless with the settled one:

  1. The result is nil exactly when the turn will not persist a user message (mirrors prependTurnUserMessage in internal/agent/application): an attachment-only or discuss-shaped command produces no history turn, so projecting one would make a bubble vanish at the database handover.
  2. The text is the same display text the persistence layer stores (mirrors the displayText switch in service_store.go): UserVisibleText when present, else the envelope-unwrapped Query. Anything else would visibly change the bubble's content when the runtime projection hands over to the database at run end.

Reply, forward, sender, and platform fields come straight from the command, which is also the source buildInteractionMetadata persists from.

type UIUserInput

type UIUserInput struct {
	UserInputID string                 `json:"user_input_id"`
	ShortID     int                    `json:"short_id,omitempty"`
	Status      string                 `json:"status"`
	Questions   []userinput.UIQuestion `json:"questions,omitempty"`
	Answers     []userinput.UIAnswer   `json:"answers,omitempty"`
	CanRespond  bool                   `json:"can_respond,omitempty"`

} // @name conversation.UIUserInput

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL