mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-13 19:20:06 +00:00
aeb704367c
- Set context tokens per-step in recordStepUsage instead of waiting for turn completion; each step re-sends the full conversation so the reported usage monotonically increases - Add UsageUpdatedEvent to trigger a TUI re-render after each step so the status bar reflects updated tokens, cost, and context % even during gaps between streaming chunks - Update test to expect per-step context token updates
355 lines
14 KiB
Go
355 lines
14 KiB
Go
package app
|
|
|
|
import kit "github.com/mark3labs/kit/pkg/kit"
|
|
|
|
// StreamChunkEvent is sent by the app layer when a streaming text delta arrives
|
|
// from the LLM. Each chunk contains an incremental portion of the response.
|
|
type StreamChunkEvent struct {
|
|
// Content is the incremental text delta from the streaming response.
|
|
Content string
|
|
}
|
|
|
|
// ReasoningChunkEvent is sent when a streaming reasoning/thinking delta arrives
|
|
// from the LLM. Thinking content is rendered separately from regular text.
|
|
type ReasoningChunkEvent struct {
|
|
// Delta is the incremental reasoning text from the streaming response.
|
|
Delta string
|
|
}
|
|
|
|
// ReasoningCompleteEvent is sent when reasoning/thinking is finished, after
|
|
// the last reasoning token has been processed. The TUI uses this to freeze
|
|
// the reasoning duration counter.
|
|
type ReasoningCompleteEvent struct{}
|
|
|
|
// ToolCallStartedEvent is sent when a tool call has been parsed and is about to execute.
|
|
// It carries the tool name and its arguments for display purposes.
|
|
type ToolCallStartedEvent struct {
|
|
// ToolCallID is the stable identifier for correlating tool lifecycle events.
|
|
ToolCallID string
|
|
// ToolName is the name of the tool being called.
|
|
ToolName string
|
|
// ToolArgs is the JSON-encoded arguments for the tool call.
|
|
ToolArgs string
|
|
}
|
|
|
|
// ToolCallInputStartEvent is sent when the LLM begins generating tool call
|
|
// arguments. The tool name is known but the full argument JSON is still being
|
|
// streamed. UIs can use this to show a "running" indicator immediately instead
|
|
// of waiting for the full argument JSON to finish streaming.
|
|
type ToolCallInputStartEvent struct {
|
|
// ToolCallID is the stable identifier for correlating tool lifecycle events.
|
|
ToolCallID string
|
|
// ToolName is the name of the tool being called.
|
|
ToolName string
|
|
// ToolKind classifies the tool: "execute", "edit", "read", "search", "agent".
|
|
ToolKind string
|
|
}
|
|
|
|
// ToolCallInputDeltaEvent is sent for each streamed fragment of tool call
|
|
// arguments as they arrive from the LLM. Useful for live-previewing content
|
|
// or showing a progress indicator with byte count.
|
|
type ToolCallInputDeltaEvent struct {
|
|
// ToolCallID is the stable identifier for correlating tool lifecycle events.
|
|
ToolCallID string
|
|
// Delta is a JSON fragment of tool call arguments.
|
|
Delta string
|
|
}
|
|
|
|
// ToolCallInputEndEvent is sent when tool argument streaming is complete,
|
|
// before the tool call is parsed and execution begins.
|
|
type ToolCallInputEndEvent struct {
|
|
// ToolCallID is the stable identifier for correlating tool lifecycle events.
|
|
ToolCallID string
|
|
}
|
|
|
|
// ToolExecutionEvent is sent when a tool starts or finishes executing.
|
|
// The IsStarting flag distinguishes between the start and end of execution.
|
|
type ToolExecutionEvent struct {
|
|
// ToolCallID is the stable identifier for correlating tool lifecycle events.
|
|
ToolCallID string
|
|
// ToolName is the name of the tool being executed.
|
|
ToolName string
|
|
// ToolArgs is the JSON-encoded arguments for the tool call (only set when IsStarting is true).
|
|
ToolArgs string
|
|
// IsStarting is true when execution is beginning, false when it is complete.
|
|
IsStarting bool
|
|
}
|
|
|
|
// ToolResultEvent is sent after a tool execution completes with its result.
|
|
type ToolResultEvent struct {
|
|
// ToolCallID is the stable identifier for correlating tool lifecycle events.
|
|
ToolCallID string
|
|
// ToolName is the name of the tool that was executed.
|
|
ToolName string
|
|
// ToolArgs is the JSON-encoded arguments that were passed to the tool.
|
|
ToolArgs string
|
|
// Result is the text output from the tool execution.
|
|
Result string
|
|
// IsError indicates whether the tool returned an error result.
|
|
IsError bool
|
|
}
|
|
|
|
// ToolOutputEvent is sent when a tool produces streaming output chunks (e.g., bash output).
|
|
// This allows the TUI to display tool output as it arrives, before the tool completes.
|
|
type ToolOutputEvent struct {
|
|
// ToolCallID is the stable identifier for the tool call producing output.
|
|
ToolCallID string
|
|
// ToolName is the name of the tool producing output.
|
|
ToolName string
|
|
// Chunk is a piece of the tool's output text.
|
|
Chunk string
|
|
// IsStderr indicates whether this chunk came from stderr.
|
|
IsStderr bool
|
|
}
|
|
|
|
// ToolCallContentEvent is sent when a step includes text content alongside tool calls.
|
|
// This allows the TUI to display assistant commentary that accompanies tool usage.
|
|
type ToolCallContentEvent struct {
|
|
// Content is the assistant text that accompanies one or more tool calls.
|
|
Content string
|
|
}
|
|
|
|
// PasswordPromptEvent is sent when a sudo command needs a password.
|
|
// The TUI should display a password prompt overlay and send the result back.
|
|
type PasswordPromptEvent struct {
|
|
// Prompt is the message to display to the user.
|
|
Prompt string
|
|
// ResponseCh receives the password from the TUI.
|
|
// The TUI must send exactly one value.
|
|
ResponseCh chan<- PasswordPromptResponse
|
|
}
|
|
|
|
// PasswordPromptResponse carries the user's password input.
|
|
type PasswordPromptResponse struct {
|
|
// Password is the entered password.
|
|
Password string
|
|
// Cancelled is true if the user cancelled the prompt.
|
|
Cancelled bool
|
|
}
|
|
|
|
// ResponseCompleteEvent is sent when the LLM produces a final (non-streaming) response.
|
|
// In streaming mode, this may be empty if all content was delivered via StreamChunkEvents.
|
|
type ResponseCompleteEvent struct {
|
|
// Content is the complete final response text.
|
|
Content string
|
|
}
|
|
|
|
// StepCompleteEvent is sent when an agent step finishes successfully.
|
|
type StepCompleteEvent struct {
|
|
// ResponseText is the final assistant response text.
|
|
ResponseText string
|
|
}
|
|
|
|
// StepErrorEvent is sent when an agent step fails with an error.
|
|
// The TUI should display the error inline and transition back to input state.
|
|
type StepErrorEvent struct {
|
|
// Err is the error that caused the step to fail.
|
|
Err error
|
|
}
|
|
|
|
// StepCancelledEvent is sent when an agent step is cancelled by the user
|
|
// (e.g. via double-ESC). The TUI should flush any partially streamed content,
|
|
// cut off the agent message where it was, and return to input state without
|
|
// displaying an error.
|
|
type StepCancelledEvent struct{}
|
|
|
|
// QueueUpdatedEvent is sent whenever the message queue length changes.
|
|
// The TUI uses this to update the queue badge display.
|
|
type QueueUpdatedEvent struct {
|
|
// Length is the current number of messages waiting in the queue.
|
|
Length int
|
|
}
|
|
|
|
// SpinnerEvent is sent to show or hide the spinner animation in the stream component.
|
|
// The spinner is shown before the first streaming chunk arrives and hidden once
|
|
// content begins flowing or the step completes.
|
|
type SpinnerEvent struct {
|
|
// Show is true to display the spinner and false to hide it.
|
|
Show bool
|
|
}
|
|
|
|
// MessageCreatedEvent is sent when a new message is added to the message store.
|
|
// This allows the TUI to stay in sync with the conversation history.
|
|
type MessageCreatedEvent struct {
|
|
// Message is the message that was added to the store.
|
|
Message kit.LLMMessage
|
|
}
|
|
|
|
// CompactCompleteEvent is sent when a /compact operation finishes successfully.
|
|
// It carries the summary text and before/after statistics.
|
|
type CompactCompleteEvent struct {
|
|
// Summary is the LLM-generated structured summary of the compacted messages.
|
|
Summary string
|
|
// OriginalTokens is the estimated token count before compaction.
|
|
OriginalTokens int
|
|
// CompactedTokens is the estimated token count after compaction.
|
|
CompactedTokens int
|
|
// MessagesRemoved is the number of messages that were summarised away.
|
|
MessagesRemoved int
|
|
}
|
|
|
|
// CompactErrorEvent is sent when a /compact operation fails.
|
|
type CompactErrorEvent struct {
|
|
// Err is the error that caused compaction to fail.
|
|
Err error
|
|
}
|
|
|
|
// SteerConsumedEvent is sent when one or more steering messages have been
|
|
// consumed — either injected mid-turn via PrepareStep, or drained into the
|
|
// queue after a turn completes. The TUI uses this to clear the steering
|
|
// badge from the display.
|
|
type SteerConsumedEvent struct{}
|
|
|
|
// ModelChangedEvent is sent when an extension changes the active model via
|
|
// ctx.SetModel. The TUI updates the model name shown in the status bar and
|
|
// message attribution.
|
|
type ModelChangedEvent struct {
|
|
// ProviderName is the new provider (e.g. "anthropic").
|
|
ProviderName string
|
|
// ModelName is the new model ID (e.g. "claude-3-5-haiku-20241022").
|
|
ModelName string
|
|
}
|
|
|
|
// UsageUpdatedEvent is sent after each completed LLM step to notify the TUI
|
|
// that token counts and costs have changed. The UsageTracker is updated
|
|
// in-place before this event is sent; the TUI just needs to re-render to
|
|
// reflect the new values in the status bar.
|
|
type UsageUpdatedEvent struct{}
|
|
|
|
// WidgetUpdateEvent is sent when an extension adds, updates, or removes a
|
|
// widget via ctx.SetWidget or ctx.RemoveWidget. The TUI re-reads widget state
|
|
// from its WidgetProvider on the next render cycle.
|
|
type WidgetUpdateEvent struct{}
|
|
|
|
// ContentReloadEvent is sent when prompt templates or skills are reloaded
|
|
// from disk (e.g. by a file watcher detecting changes). The TUI refreshes
|
|
// its autocomplete entries and internal state from the provider callbacks.
|
|
type ContentReloadEvent struct{}
|
|
|
|
// MCPToolsReadyEvent is sent when background MCP tool loading completes.
|
|
// The TUI refreshes its tool names and MCP tool count from provider callbacks
|
|
// so that /tools and the startup info bar reflect the loaded MCP tools.
|
|
type MCPToolsReadyEvent struct{}
|
|
|
|
// MCPServerLoadedEvent is sent when a single MCP server finishes loading
|
|
// (successfully or with error). The TUI displays a system message so users
|
|
// see real-time progress as each server initializes.
|
|
type MCPServerLoadedEvent struct {
|
|
ServerName string
|
|
ToolCount int
|
|
Error error // nil on success
|
|
}
|
|
|
|
// EditorTextSetEvent is sent when an extension calls ctx.SetEditorText to
|
|
// pre-fill the input editor with text. The TUI handles this by setting the
|
|
// textarea content and moving the cursor to the end.
|
|
type EditorTextSetEvent struct {
|
|
Text string
|
|
}
|
|
|
|
// ExtensionPrintEvent is sent when an extension calls ctx.Print, ctx.PrintInfo,
|
|
// ctx.PrintError, or ctx.PrintBlock. The TUI renders it via the appropriate
|
|
// renderer and tea.Println (scrollback); the CLI handler uses
|
|
// DisplayInfo/DisplayError or plain fmt.Println. This exists because BubbleTea
|
|
// captures stdout, so plain fmt.Println inside extensions would be swallowed.
|
|
type ExtensionPrintEvent struct {
|
|
// Text is the content the extension wants to display to the user.
|
|
Text string
|
|
// Level controls the rendering style:
|
|
// "" — plain text (no styling)
|
|
// "info" — system message block (bordered, themed)
|
|
// "error" — error block (red border, bold text)
|
|
// "block" — custom block with BorderColor and Subtitle
|
|
Level string
|
|
// BorderColor is a hex color (e.g. "#a6e3a1") for Level="block".
|
|
BorderColor string
|
|
// Subtitle is optional muted text below the content for Level="block".
|
|
Subtitle string
|
|
}
|
|
|
|
// PromptResponse carries the user's answer to an interactive prompt. The TUI
|
|
// sends exactly one PromptResponse through the channel embedded in
|
|
// PromptRequestEvent when the user completes or cancels the prompt.
|
|
type PromptResponse struct {
|
|
// Value is the response text — the selected option (select), or the
|
|
// entered text (input). Unused for confirm prompts.
|
|
Value string
|
|
// Index is the zero-based index of the selected option (select only).
|
|
Index int
|
|
// Confirmed is the boolean answer for confirm prompts.
|
|
Confirmed bool
|
|
// Cancelled is true if the user dismissed the prompt (ESC) or the
|
|
// prompt could not be shown (e.g. app shutting down).
|
|
Cancelled bool
|
|
}
|
|
|
|
// PromptRequestEvent is sent when an extension requests an interactive
|
|
// prompt from the user (select, confirm, or text input). The TUI enters a
|
|
// modal prompt state, renders the prompt, and sends a single PromptResponse
|
|
// through ResponseCh when the user completes or cancels.
|
|
//
|
|
// The extension goroutine blocks on the read side of ResponseCh until the
|
|
// TUI sends a response. The channel must have buffer size >= 1.
|
|
type PromptRequestEvent struct {
|
|
// PromptType is "select", "confirm", or "input".
|
|
PromptType string
|
|
// Message is the question displayed to the user.
|
|
Message string
|
|
// Options lists the choices for select prompts.
|
|
Options []string
|
|
// Default is the pre-filled value: "true"/"false" for confirm prompts,
|
|
// or the initial text for input prompts.
|
|
Default string
|
|
// Placeholder is the ghost text for input prompts.
|
|
Placeholder string
|
|
// ResponseCh receives the user's answer. The TUI must send exactly one
|
|
// value. The channel must be buffered (cap >= 1) so sending never
|
|
// blocks inside Update().
|
|
ResponseCh chan<- PromptResponse
|
|
}
|
|
|
|
// OverlayResponse carries the user's answer to a modal overlay dialog. The
|
|
// TUI sends exactly one OverlayResponse through the channel embedded in
|
|
// OverlayRequestEvent when the user completes or cancels the overlay.
|
|
type OverlayResponse struct {
|
|
// Action is the text of the selected action button, or "" if no actions
|
|
// were configured or the dialog was dismissed without selection.
|
|
Action string
|
|
// Index is the zero-based index of the selected action, or -1 if no
|
|
// action was selected.
|
|
Index int
|
|
// Cancelled is true if the user dismissed the overlay (ESC) or the
|
|
// overlay could not be shown (e.g. non-interactive mode).
|
|
Cancelled bool
|
|
}
|
|
|
|
// OverlayRequestEvent is sent when an extension requests a modal overlay
|
|
// dialog. The TUI enters an overlay state, renders the dialog, and sends a
|
|
// single OverlayResponse through ResponseCh when the user dismisses or
|
|
// selects an action.
|
|
//
|
|
// The extension goroutine blocks on the read side of ResponseCh until the
|
|
// TUI sends a response. The channel must have buffer size >= 1.
|
|
type OverlayRequestEvent struct {
|
|
// Title is displayed at the top of the dialog. Empty means no title.
|
|
Title string
|
|
// Content is the text to render inside the dialog body.
|
|
Content string
|
|
// Markdown, when true, renders Content as styled markdown.
|
|
Markdown bool
|
|
// BorderColor is a hex color for the dialog border. Empty uses default.
|
|
BorderColor string
|
|
// Background is a hex color for the dialog background. Empty = none.
|
|
Background string
|
|
// Width is the dialog width in columns. 0 = auto (60% of terminal).
|
|
Width int
|
|
// MaxHeight limits dialog height. 0 = auto (80% of terminal).
|
|
MaxHeight int
|
|
// Anchor is the vertical positioning: "center", "top-center", "bottom-center".
|
|
Anchor string
|
|
// Actions lists the action button labels. Empty = simple dismiss dialog.
|
|
Actions []string
|
|
// ResponseCh receives the user's response. Must have buffer size >= 1.
|
|
ResponseCh chan<- OverlayResponse
|
|
}
|