Skip to content

SessionEvent

Category: Core

Source: session_event.dart

Sealed event hierarchy emitted by a running session.

Status: proposed (PR 2 of harness-layers plan). Not yet wired to consumers — see docs/plans/2026-04-29-harness-layers.md.

Design properties encoded here:

  1. Permission and OAuth are events, not callbacks. The agent emits [PermissionRequestedEvent] and the surface responds via session.dispatch(ResolvePermissionCommand(...)). Same for device-code OAuth. The agent never imports surface code.

  2. Subagents emit forwarded events. [SubagentEventForwardedEvent] carries an inner event. Surfaces decide whether to render inline (CLI does this) or in a separate pane (web could).

  3. Sequence numbers are mandatory. Every event has a monotonic per-session [SessionEvent.sequence]. This is what makes "snapshot + subscribe" work without missing or duplicating events.

Enums

McpDisconnectReason

Why an MCP server disconnected. Drives the surface message and the reconnection state machine.

ValueDescription
SSE
WebSocket
dropped
shutdown

McpServerErrorKind

What flavour of error fired for [McpServerErrorEvent].

ValueDescription
required
required
required
required
required
required
required

RuntimeOutputStream

ValueDescription
stdout
stderr

RuntimeCancelReason

RuntimeContainerStopReason

AttachmentKind

ValueDescription
image
pdf
text
binary

ChunkKind

ValueDescription
text
thinking
toolCallArgs

ToolKind

ValueDescription
read
write
exec
network
meta

SessionStatus

ValueDescription
idle
thinking
callingTool
awaitingPermission
completed
error

TurnOutcome

ValueDescription
completed
interrupted
errored

ErrorCategory

ValueDescription
provider
tool
runtime
internal

PermissionScope

How long a permission grant applies.

Classes

sealed SessionEvent

Base type for all events emitted by a [Session].

Pattern-match with switch to handle each variant:

dart
switch (event) {
AssistantChunkEvent(:final delta) => render(delta),
PermissionRequestedEvent() => showPermissionUi(event),
_ => null,
}

Constructor

dart
const SessionEvent({
    required this.turnId,
    required this.timestamp,
    required this.sequence,
  })

Properties

PropertyTypeDescription
turnIdTurnIdThe turn this event belongs to. A turn is one user-message → assistant-response cycle (which may include many tool calls).
timestampDateTimeWall-clock time the event was produced.
sequenceintMonotonic per-session sequence number. Surfaces use this to resume from a known position without missing or duplicating events.

UserMessageEvent

User-authored input dispatched into a session.

Constructor

dart
const UserMessageEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.text,
    this.attachments = const [],
    this.fileRefs = const [],
  })

Properties

PropertyTypeDescription
textString
attachmentsList<Attachment>
fileRefsList<FileReference>@file expansions resolved at dispatch time.

AssistantThinkingStartedEvent

The model has begun producing thinking tokens (if exposed).

Constructor

dart
const AssistantThinkingStartedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
  })

AssistantChunkEvent

A streamed delta from the model — text, thinking, or tool-call args.

Constructor

dart
const AssistantChunkEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.delta,
    required this.kind,
  })

Properties

PropertyTypeDescription
deltaString
kindChunkKind

AssistantMessageEvent

The model finished producing a complete assistant message for this turn.

Constructor

dart
const AssistantMessageEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.text,
    required this.usage,
    required this.elapsed,
  })

Properties

PropertyTypeDescription
textString
usageTokenUsage
elapsedDuration

AssistantThinkingCompletedEvent

The model finished producing thinking tokens.

Constructor

dart
const AssistantThinkingCompletedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.usage,
    this.summary,
  })

Properties

PropertyTypeDescription
summaryString?Some providers expose a thinking summary; null if not.
usageTokenUsage

ToolCallStartedEvent

A tool call has begun executing (after permission, if applicable).

Constructor

dart
const ToolCallStartedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.id,
    required this.tool,
    required this.args,
    required this.kind,
  })

Properties

PropertyTypeDescription
idToolCallId
toolString
argsMap<String, Object?>
kindToolKind

ToolCallProgressEvent

Optional progress update emitted while a tool is running.

Constructor

dart
const ToolCallProgressEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.id,
    required this.message,
    this.percentComplete,
  })

Properties

PropertyTypeDescription
idToolCallId
messageString
percentCompletedouble?

ToolCallCompletedEvent

A tool call finished — either successfully, with an error, or cancelled.

Constructor

dart
const ToolCallCompletedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.id,
    required this.result,
    required this.elapsed,
  })

Properties

PropertyTypeDescription
idToolCallId
resultToolResultSnapshot
elapsedDuration

PermissionRequestedEvent

The agent needs the user's permission to proceed with a tool call.

The surface responds by dispatching a ResolvePermissionCommand with the same [requestId].

Constructor

dart
const PermissionRequestedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.requestId,
    required this.toolCallId,
    required this.scope,
    required this.summary,
    required this.dangerLevel,
  })

Properties

PropertyTypeDescription
requestIdPermissionRequestId
toolCallIdToolCallId
scopePermissionScope
summaryString
dangerLevelToolKind

PermissionResolvedEvent

The user resolved a pending permission request.

Constructor

dart
const PermissionResolvedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.requestId,
    required this.granted,
    required this.appliedScope,
  })

Properties

PropertyTypeDescription
requestIdPermissionRequestId
grantedbool
appliedScopePermissionScope

SubagentSpawnedEvent

The agent spawned a subagent. Subsequent events from that subagent arrive wrapped in [SubagentEventForwardedEvent].

Constructor

dart
const SubagentSpawnedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.childId,
    required this.childSessionId,
    required this.task,
    required this.model,
  })

Properties

PropertyTypeDescription
childIdSubagentId
childSessionIdSessionId
taskString
modelModelRef

SubagentEventForwardedEvent

An event emitted by a subagent, forwarded to the parent stream.

Surfaces choose to render [inner] inline (CLI today) or in a separate pane (a future web client could).

Constructor

dart
const SubagentEventForwardedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.childId,
    required this.inner,
  })

Properties

PropertyTypeDescription
childIdSubagentId
innerSessionEvent

SubagentCompletedEvent

A subagent finished — emitted on the parent stream.

Constructor

dart
const SubagentCompletedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.childId,
    required this.usage,
    required this.elapsed,
    this.finalMessage,
  })

Properties

PropertyTypeDescription
childIdSubagentId
finalMessageString?
usageTokenUsage
elapsedDuration

DeviceCodeRequestedEvent

A device-code OAuth flow has produced a code the user must enter.

The surface displays [code] + [verificationUrl], waits for the user to complete the flow in their browser, and dispatches ResolveDeviceCodeCommand.

Constructor

dart
const DeviceCodeRequestedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.code,
    required this.verificationUrl,
    required this.expiresIn,
  })

Properties

PropertyTypeDescription
codeString
verificationUrlString
expiresInDuration

DeviceCodeResolvedEvent

The OAuth flow completed (success or failure).

Constructor

dart
const DeviceCodeResolvedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.success,
    this.errorMessage,
  })

Properties

PropertyTypeDescription
successbool
errorMessageString?

TurnStartedEvent

A new turn started.

Constructor

dart
const TurnStartedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.model,
  })

Properties

PropertyTypeDescription
idTurnId getEqual to [SessionEvent.turnId]; included for ergonomics in switch arms.
modelModelRef
idTurnId getEqual to [SessionEvent.turnId]; included for ergonomics in switch arms.

TurnCompletedEvent

The current turn finished — completed normally, was interrupted, or errored.

Constructor

dart
const TurnCompletedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.outcome,
    required this.usage,
  })

Properties

PropertyTypeDescription
idTurnId get
outcomeTurnOutcome
usageTokenUsage
idTurnId get

StatusChangeEvent

The session's high-level status changed.

Constructor

dart
const StatusChangeEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.from,
    required this.to,
  })

Properties

PropertyTypeDescription
fromSessionStatus
toSessionStatus

TitleGeneratedEvent

A title was generated for this session (typically after the first turn).

Constructor

dart
const TitleGeneratedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.title,
  })

Properties

PropertyTypeDescription
titleString

MetricsUpdatedEvent

Session metrics were refreshed.

Constructor

dart
const MetricsUpdatedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.current,
  })

Properties

PropertyTypeDescription
currentSessionMetricsSnapshot

ErrorEvent

An error occurred. May or may not be recoverable.

Constructor

dart
const ErrorEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.message,
    required this.category,
    required this.recoverable,
    this.stackTrace,
  })

Properties

PropertyTypeDescription
messageString
categoryErrorCategory
recoverablebool
stackTraceStackTrace?Null in production builds.

McpServerConnectedEvent

An MCP server completed the initialize handshake and its tools are available to the agent.

Constructor

dart
const McpServerConnectedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.serverId,
    required this.serverName,
    required this.serverVersion,
    required this.toolNames,
  })

Properties

PropertyTypeDescription
serverIdStringLocal config id for the server (the user's chosen name).
serverNameStringServer-reported name (from initializeserverInfo.name).
serverVersionStringServer-reported version.
toolNamesList<String>Namespaced tool names registered with the agent (<serverId>.<tool>).
serverIdString
reasonMcpDisconnectReason
reconnectAttemptint0 when not retrying (e.g. clean shutdown or dead).
nextAttemptInDurationDuration.zero when not retrying.
serverIdString
kindMcpServerErrorKind
messageString
serverIdString
reauthCommandStringShell command the user should run (or that the TUI can trigger via a modal-confirmed action). e.g. glue mcp auth login notion.
serverIdString
addedList<String>Namespaced tool names that appeared since the last tools/list.
removedList<String>Namespaced tool names that disappeared.
runtimeIdStringIdentifier of the runtime running this command: 'host', 'docker', 'daytona', …
commandIdStringPer-session-unique id for correlating this event with later progress / completion / cancellation events. Distinct from [SessionEvent.sequence], which is monotonic across the whole session.
commandStringThe command line as dispatched (may be redacted/truncated by the emitter — surfaces should treat it as a display string, not a fully reconstructible value).
runtimeCwdStringThe directory inside the runtime where the command will execute (e.g. /workspace for Docker / cloud, or the host cwd otherwise).
sessionScopedIdString?Cloud-side session id (e.g. a Daytona sandboxId), when relevant.
commandIdString
streamRuntimeOutputStream
textString
commandIdString
exitCodeint
durationDuration
stdoutBytesint?Total bytes emitted on stdout, when known. Useful for surfaces that want to elide huge outputs.
stderrBytesint?
commandIdString
errorTypeString
messageString
commandIdString
reasonRuntimeCancelReason
runtimeIdString
containerIdString
imageString?
runtimeIdString
containerIdString
reasonRuntimeContainerStopReason
kindAttachmentKind
bytesList<int>
mimeTypeString?
filenameString?
pathString
absolutePathString
promptTokensint
completionTokensint
cachedTokensintTokens served from prompt cache (provider-dependent).
estimatedCostUsddoubleCost estimate in USD. May be 0.0 when pricing is unavailable.
turnCountint
usageTokenUsage
totalElapsedDuration

Methods

`const McpServerDisconnectedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.serverId,
required this.reason,
this.reconnectAttempt = 0,
this.nextAttemptIn = Duration.zero,

})`

`const McpServerErrorEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.serverId,
required this.kind,
required this.message,

})`

`const McpServerAuthRequiredEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.serverId,
required this.reauthCommand,

})`

`const McpToolListChangedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.serverId,
required this.added,
required this.removed,

})`

`const RuntimeCommandStartedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.runtimeId,
required this.commandId,
required this.command,
required this.runtimeCwd,
this.sessionScopedId,

})`

`const RuntimeCommandOutputEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.commandId,
required this.stream,
required this.text,

})`

`const RuntimeCommandCompletedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.commandId,
required this.exitCode,
required this.duration,
this.stdoutBytes,
this.stderrBytes,

})`

`const RuntimeCommandFailedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.commandId,
required this.errorType,
required this.message,

})`

`const RuntimeCommandCancelledEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.commandId,
required this.reason,

})`

`const RuntimeContainerStartedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.runtimeId,
required this.containerId,
this.image,

})`

`const RuntimeContainerStoppedEvent({
required super.turnId,
required super.timestamp,
required super.sequence,
required this.runtimeId,
required this.containerId,
required this.reason,

})`

`const Attachment({
required this.kind,
required this.bytes,
this.mimeType,
this.filename,

})`

`const FileReference({
required this.path,
required this.absolutePath,
this.lineRange,

})`

`const TokenUsage({
required this.promptTokens,
required this.completionTokens,
this.cachedTokens = 0,
this.estimatedCostUsd = 0.0,

})`

`const SessionMetricsSnapshot({
required this.turnCount,
required this.usage,
required this.totalElapsed,

})`

McpServerDisconnectedEvent

An MCP server's connection has dropped — possibly transiently. If [reconnectAttempt] is > 0 the pool is retrying after [nextAttemptIn]. If [reason] is [McpDisconnectReason.dead], the pool has given up.

Constructor

dart
const McpServerDisconnectedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.serverId,
    required this.reason,
    this.reconnectAttempt = 0,
    this.nextAttemptIn = Duration.zero,
  })

Properties

PropertyTypeDescription
serverIdString
reasonMcpDisconnectReason
reconnectAttemptint0 when not retrying (e.g. clean shutdown or dead).
nextAttemptInDurationDuration.zero when not retrying.

McpServerErrorEvent

An error specific to the MCP server lifecycle (not a tool-call error, which surfaces as [ToolCallCompletedEvent] with an error snapshot).

Constructor

dart
const McpServerErrorEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.serverId,
    required this.kind,
    required this.message,
  })

Properties

PropertyTypeDescription
serverIdString
kindMcpServerErrorKind
messageString

McpServerAuthRequiredEvent

The server needs the user to re-authorise (OAuth refresh failed or bearer was rejected). The surface should display [reauthCommand] and pause the server until [reauthCommand] (or equivalent) completes.

Constructor

dart
const McpServerAuthRequiredEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.serverId,
    required this.reauthCommand,
  })

Properties

PropertyTypeDescription
serverIdString
reauthCommandStringShell command the user should run (or that the TUI can trigger via a modal-confirmed action). e.g. glue mcp auth login notion.

McpToolListChangedEvent

The server's tool list changed mid-session (via the notifications/tools/list_changed protocol message).

Constructor

dart
const McpToolListChangedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.serverId,
    required this.added,
    required this.removed,
  })

Properties

PropertyTypeDescription
serverIdString
addedList<String>Namespaced tool names that appeared since the last tools/list.
removedList<String>Namespaced tool names that disappeared.

RuntimeCommandStartedEvent

A command has been dispatched to a runtime and is starting.

Constructor

dart
const RuntimeCommandStartedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.runtimeId,
    required this.commandId,
    required this.command,
    required this.runtimeCwd,
    this.sessionScopedId,
  })

Properties

PropertyTypeDescription
runtimeIdStringIdentifier of the runtime running this command: 'host', 'docker', 'daytona', …
commandIdStringPer-session-unique id for correlating this event with later progress / completion / cancellation events. Distinct from [SessionEvent.sequence], which is monotonic across the whole session.
commandStringThe command line as dispatched (may be redacted/truncated by the emitter — surfaces should treat it as a display string, not a fully reconstructible value).
runtimeCwdStringThe directory inside the runtime where the command will execute (e.g. /workspace for Docker / cloud, or the host cwd otherwise).
sessionScopedIdString?Cloud-side session id (e.g. a Daytona sandboxId), when relevant.

RuntimeCommandOutputEvent

Streamed output bytes from a running runtime command.

Optional/high-volume — emitters may suppress this for short commands or gate it behind a debug flag.

Constructor

dart
const RuntimeCommandOutputEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.commandId,
    required this.stream,
    required this.text,
  })

Properties

PropertyTypeDescription
commandIdString
streamRuntimeOutputStream
textString

RuntimeCommandCompletedEvent

A runtime command finished normally with an [exitCode]. Non-zero exit codes are not errors — they're the program's own failure signal. Use [RuntimeCommandFailedEvent] for transport-level errors.

Constructor

dart
const RuntimeCommandCompletedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.commandId,
    required this.exitCode,
    required this.duration,
    this.stdoutBytes,
    this.stderrBytes,
  })

Properties

PropertyTypeDescription
commandIdString
exitCodeint
durationDuration
stdoutBytesint?Total bytes emitted on stdout, when known. Useful for surfaces that want to elide huge outputs.
stderrBytesint?

RuntimeCommandFailedEvent

A runtime command failed at the transport or runtime layer (i.e. the runtime couldn't run it at all, or lost connection). Distinct from a non-zero exit code, which is [RuntimeCommandCompletedEvent].

Constructor

dart
const RuntimeCommandFailedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.commandId,
    required this.errorType,
    required this.message,
  })

Properties

PropertyTypeDescription
commandIdString
errorTypeString
messageString

RuntimeCommandCancelledEvent

A runtime command was cancelled by the harness (timeout, /cancel, shutdown) before it finished.

Constructor

dart
const RuntimeCommandCancelledEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.commandId,
    required this.reason,
  })

Properties

PropertyTypeDescription
commandIdString
reasonRuntimeCancelReason

RuntimeContainerStartedEvent

A runtime container (Docker / cloud sandbox) was started for the session. Host runtimes don't emit this — there's no container.

Constructor

dart
const RuntimeContainerStartedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.runtimeId,
    required this.containerId,
    this.image,
  })

Properties

PropertyTypeDescription
runtimeIdString
containerIdString
imageString?

RuntimeContainerStoppedEvent

A runtime container was stopped (either normally on session end, or because of a failure / cancellation).

Constructor

dart
const RuntimeContainerStoppedEvent({
    required super.turnId,
    required super.timestamp,
    required super.sequence,
    required this.runtimeId,
    required this.containerId,
    required this.reason,
  })

Properties

PropertyTypeDescription
runtimeIdString
containerIdString
reasonRuntimeContainerStopReason

Attachment

A non-text input attached to a user message.

Constructor

dart
const Attachment({
    required this.kind,
    required this.bytes,
    this.mimeType,
    this.filename,
  })

Properties

PropertyTypeDescription
kindAttachmentKind
bytesList<int>
mimeTypeString?
filenameString?

FileReference

A reference to a file in the project (the result of @file expansion).

Constructor

dart
const FileReference({
    required this.path,
    required this.absolutePath,
    this.lineRange,
  })

Properties

PropertyTypeDescription
pathString
absolutePathString

TokenUsage

Constructor

dart
const TokenUsage({
    required this.promptTokens,
    required this.completionTokens,
    this.cachedTokens = 0,
    this.estimatedCostUsd = 0.0,
  })

Properties

PropertyTypeDescription
promptTokensint
completionTokensint
cachedTokensintTokens served from prompt cache (provider-dependent).
estimatedCostUsddoubleCost estimate in USD. May be 0.0 when pricing is unavailable.

SessionMetricsSnapshot

Constructor

dart
const SessionMetricsSnapshot({
    required this.turnCount,
    required this.usage,
    required this.totalElapsed,
  })

Properties

PropertyTypeDescription
turnCountint
usageTokenUsage
totalElapsedDuration

sealed ToolResultSnapshot

A serializable snapshot of a [ToolCall]'s outcome. The runtime tool result type lives elsewhere; this is the on-the-wire / on-disk shape.

Constructor

dart
const ToolResultSnapshot({required this.id, required this.elapsed})

Properties

PropertyTypeDescription
idToolCallId
elapsedDuration

ToolOkSnapshot

Constructor

dart
const ToolOkSnapshot({
    required super.id,
    required super.elapsed,
    required this.contentSummary,
  })

Properties

PropertyTypeDescription
contentSummaryStringHuman-readable summary; the full content is the tool's own concern.
messageString
categoryErrorCategory
retryablebool

Methods

`const ToolErrorSnapshot({
required super.id,
required super.elapsed,
required this.message,
required this.category,
required this.retryable,

})`

const ToolCancelledSnapshot({required super.id, required super.elapsed})

ToolErrorSnapshot

Constructor

dart
const ToolErrorSnapshot({
    required super.id,
    required super.elapsed,
    required this.message,
    required this.category,
    required this.retryable,
  })

Properties

PropertyTypeDescription
messageString
categoryErrorCategory
retryablebool

ToolCancelledSnapshot

Constructor

dart
const ToolCancelledSnapshot({required super.id, required super.elapsed})

Released under the MIT License.