Documentation
¶
Overview ¶
Package turn defines the application-level contract for starting and observing agent turns. It is the only agent surface Channel may depend on; it must not import Echo, fx, sqlc, conversation, or any channel package.
Index ¶
- Constants
- Variables
- func ContextBudgetBytes(tokens int) int64
- func CurrentAdmissionEntries(entries []AdmissionEntry) []bool
- func EstimateTokensFromBytes(n int) int
- func FormatUserHeader(input UserMessageHeaderInput, query string) string
- func FormatUserHeaderFromMeta(meta UserMessageMeta, query string) string
- func HasToolCallContent(msg ModelMessage) bool
- func IsPrivateConversationType(raw string) bool
- func NewRunTerminalEvent(state, errorCode string) (json.RawMessage, error)
- func NewTextContent(text string) json.RawMessage
- func NormalizeConversationType(raw string) string
- func PlaceSummary[T any](items []T, summary T, covered func(T) bool) ([]T, bool)
- func ProtectedAdmissionEntries(entries []AdmissionEntry, budgetTokens int) []bool
- func ReportsRunTerminal(handle RunHandle) bool
- func SkillActivationModelQuery(activation *SkillActivation) string
- func SummaryText(summary string) string
- func UnwrapUserMessageEnvelope(text string) string
- type ACPAgentProfile
- type ACPManagedField
- type ACPProfileResolver
- type ACPSetupPreflight
- type AdmissionDecision
- type AdmissionEntry
- type AssistantOutput
- type Attachment
- type ContentPart
- type ContextMessageSource
- type DeferredTurnService
- type DiscussImageRef
- type DiscussMessage
- type DiscussRunResolvedPayload
- type Event
- type InjectMessage
- type Mode
- type ModelMessage
- type OutboundAssetRef
- type QuestionAnswer
- type RequestedSkillContext
- type RunHandle
- type RunTerminal
- type RuntimeCommand
- type RuntimeCommandKind
- type RuntimeCommandResult
- type RuntimeControlCapabilities
- type RuntimeControlRequest
- type RuntimeControlService
- type RuntimeControls
- type RuntimeGoal
- type RuntimeGoalService
- type RuntimeMode
- type RuntimeModeState
- type RuntimeModelOption
- type RuntimeModelState
- type Service
- type SkillActivation
- type SkillActivationSkill
- type StartTurnCommand
- type StopCommand
- type Stopper
- type TerminalReporter
- type ToolApprovalResponse
- type ToolCall
- type ToolCallFunction
- type UserInputResponse
- type UserMessageHeaderInput
- type UserMessageMeta
Constants ¶
const ( // ContextBytesPerToken is the shared byte-per-token heuristic. ContextBytesPerToken = contextfrag.EstimateBytesPerToken // DefaultContextCapTokens is the fail-closed admission cap used when no // explicit configuration reaches a consumer (CM-ADM-001). DefaultContextCapTokens = contextfrag.DefaultAbsoluteCapTokens )
The turn port re-exports the agent context ledger's estimation vocabulary for the packages the architecture guards keep on this contract: chat/timeline and channel may not import agent/context, yet their admission decisions must agree with the fragment ledger (CM-EST-001). internal/agent/context/fragment stays the authority and the single swap point for a real tokenizer; no package may keep a private bytes-per-token constant.
const ( ConversationTypePrivate = "private" ConversationTypeGroup = "group" ConversationTypeThread = "thread" )
const ( RunStateCompleted = "completed" RunStateAborted = "aborted" RunStateFailed = "failed" RunStateLost = "lost" )
Terminal run states. They are the durable record's values.
const ( // DiscussEventRunResolved is always the first event of a discuss run; // its payload is DiscussRunResolvedPayload. DiscussEventRunResolved = "discuss_run_resolved" // DiscussEventSkipped signals the runtime declined to start (e.g. ACP // participation gate); the run ends after this event. DiscussEventSkipped = "discuss_skipped" // DiscussEventRecompose signals the runtime compacted the thread // synchronously before calling the model; the run ends after this event // and the driver must recompose against the session's new history // checkpoint and resubmit (CM-CMP-001). The cursor must not advance. DiscussEventRecompose = "discuss_recompose" )
Synthetic discuss event kinds emitted by the runtime before (or instead of) the model event stream.
const EventRunTerminal = "run_terminal"
EventRunTerminal is the last event of a run whose durable record reached a terminal state. Its payload is RunTerminal, read from that record, so it names the same outcome and error code the run's history shows. A run that parks on a decision, or whose owner lost the run before recording its end, has no such event.
const MessageSourceInternalFeedback = "internal_feedback"
MessageSourceInternalFeedback is runtime-generated input, never a new user turn.
const UserMessageKindSkillActivation = "skill_activation"
UserMessageKindSkillActivation identifies persisted skill activation messages.
Variables ¶
var ErrDuplicateTurn = errors.New("turn: duplicate idempotency key")
ErrDuplicateTurn reports that a StartTurnCommand's (TeamID, IdempotencyKey) pair was already claimed by an earlier run. Callers handling platform webhook retries should treat it as successful delivery and drop the duplicate silently.
var ErrSessionBusy = errors.New("turn: thread already has a run in flight")
ErrSessionBusy reports that the thread already has a run in flight. An ingress whose user observes runs through the session runtime subscription may park the full command with DeferredTurnService and report ErrTurnDeferred instead; other callers retry the unchanged command.
It is declared here rather than reused from the runtime because this package is the only agent surface Channel may import, and it must not depend on the runtime that produces the condition.
var ErrTeamNotServed = errors.New("turn: team not served by this instance")
ErrTeamNotServed reports that the service instance does not serve the command's team. The in-process runtime binds its database pool to the single self-hosted team, so commands for any other team must fail closed instead of silently reading and writing the default team's data.
var ErrTurnDeferred = errors.New("turn: deferred until current run completes")
ErrTurnDeferred means the complete turn command was accepted by the configured session runtime queue and will start after the current run ends.
Functions ¶
func ContextBudgetBytes ¶ added in v0.22.0
func CurrentAdmissionEntries ¶ added in v0.22.0
func CurrentAdmissionEntries(entries []AdmissionEntry) []bool
func EstimateTokensFromBytes ¶
EstimateTokensFromBytes converts a byte count to the shared token estimate.
func FormatUserHeader ¶
func FormatUserHeader(input UserMessageHeaderInput, query string) string
FormatUserHeader wraps a user query in an XML <message> tag so the LLM sees structured context (sender, channel, conversation, time, attachments) alongside the raw message. This must be the single source of truth for user-message formatting — the agent gateway must NOT add its own header.
func FormatUserHeaderFromMeta ¶
func FormatUserHeaderFromMeta(meta UserMessageMeta, query string) string
FormatUserHeaderFromMeta formats a pre-built UserMessageMeta into the XML <message> string sent to the LLM.
func HasToolCallContent ¶
func HasToolCallContent(msg ModelMessage) bool
func IsPrivateConversationType ¶
IsPrivateConversationType reports whether raw describes a direct conversation.
func NewRunTerminalEvent ¶ added in v0.21.0
func NewRunTerminalEvent(state, errorCode string) (json.RawMessage, error)
NewRunTerminalEvent builds the EventRunTerminal payload.
func NewTextContent ¶
func NewTextContent(text string) json.RawMessage
NewTextContent creates a JSON string value from plain text.
func NormalizeConversationType ¶
NormalizeConversationType normalizes delivery-specific aliases into the application-level conversation vocabulary carried by turn commands.
func PlaceSummary ¶ added in v1.0.0
PlaceSummary renders summary in place of the items it covers. Every other item keeps its order. The summary goes right after the last kept item inside the covered span, or where the first covered item was when no kept item lies inside it: items the span holds but the summary does not cover render before it. Without a covered item, items come back unchanged and summary is not placed.
A fold orders the request it leaves by this rule, which the in-run splice and a request built from rows apply, and a history checkpoint orders the rows a request read the same way: the ones it keeps, then its summary. A summary then renders at the same relative place in the request that wrote it and in every later one.
func ProtectedAdmissionEntries ¶ added in v0.22.0
func ProtectedAdmissionEntries(entries []AdmissionEntry, budgetTokens int) []bool
ProtectedAdmissionEntries marks the current entries no admission may drop: the whole unconsumed batch when it fits beside the pinned entries, otherwise the newest contiguous run of it that leaves a tenth of the budget for the summary of the rest. The newest current entry is always protected. Older current entries become ordinary history that recovery compacts.
func ReportsRunTerminal ¶ added in v0.21.0
ReportsRunTerminal reports whether handle sends EventRunTerminal.
func SkillActivationModelQuery ¶
func SkillActivationModelQuery(activation *SkillActivation) string
SkillActivationModelQuery renders the user query represented by an activation payload.
func SummaryText ¶ added in v1.0.0
SummaryText is the text a summary renders as wherever a request carries it: the preamble, then the summary in its tags.
func UnwrapUserMessageEnvelope ¶
UnwrapUserMessageEnvelope is the inverse of FormatUserHeaderFromMeta: it returns the text the user actually wrote, with the model-facing <message> wrapper and its structural children (<attachment>, <in-reply-to>) removed. Input that is not a complete envelope is returned unchanged, so callers can apply it defensively to any query string. An attachment-only message unwraps to the empty string — the envelope is the only content it ever had.
Types ¶
type ACPAgentProfile ¶
ACPAgentProfile is the channel-safe view of one external agent profile. Runtime launch commands and credential details stay behind ACPProfileResolver and never cross the Channel boundary.
type ACPManagedField ¶
ACPManagedField identifies one required managed setting that is missing during a Channel preflight. It deliberately carries only presentation-safe metadata; configured values and other runtime details remain private.
type ACPProfileResolver ¶
type ACPProfileResolver interface {
ResolveACPProfile(agentID string) ACPAgentProfile
ResolveACPSetupPreflight(ctx context.Context, botID, botAgentID, agentID string, metadata map[string]any) (ACPSetupPreflight, error)
}
ACPProfileResolver is the read-only Agent port used by Channel while interpreting /new commands. Implementations own profile normalization, registration, and setup validation, including which Agent instance's setup applies; Channel supplies only stable inputs.
type ACPSetupPreflight ¶
type ACPSetupPreflight struct {
Enabled bool
MissingManagedField *ACPManagedField
}
ACPSetupPreflight is the minimum setup state Channel needs before creating an ACP-backed thread.
type AdmissionDecision ¶
type AdmissionDecision struct {
// Selected holds one keep-flag per input entry. It is nil when the input
// was empty or the decision is a ProtectedOverflow rejection.
Selected []bool
// EstimatedTokens is the pre-selection estimate of the full input.
EstimatedTokens int
// SelectedTokens is the estimate of the selected entries.
SelectedTokens int
// DroppedEntries counts entries not selected.
DroppedEntries int
// ProtectedOverflow is set when the protected set alone (pinned entries
// plus the newest raw entry) exceeds the budget, or when the newest raw
// entry is a tool response that cannot open a valid window. Callers must
// fail closed instead of materializing (CM-ADM-002).
ProtectedOverflow bool
}
AdmissionDecision reports one admission outcome (CM-ADM-002).
func AdmitContextEntries ¶
func AdmitContextEntries(entries []AdmissionEntry, budgetTokens int) AdmissionDecision
AdmitContextEntries makes the deterministic admission decision shared by the channel-side composer and the agent-side re-admission (CM-ADM-002): pinned entries are always kept, the newest raw entry is protected, older raw entries fill a contiguous recent window that stops at the first entry that does not fit, and the window never opens on an orphaned tool response. A budget of zero or less admits everything; the orphan trim still applies because a byte-budgeted history load can cut a tool pair in half even when the composed total fits the budget.
type AdmissionEntry ¶
type AdmissionEntry struct {
Source *ContextMessageSource
// Cost is the entry's estimate in shared-estimator tokens.
Cost int
// Pinned entries (what the session's history checkpoint holds) are always
// selected.
Pinned bool
// ToolResponse marks a raw tool-response entry. The selected window must
// never open on one, because its tool call would fall outside the window.
ToolResponse bool
}
AdmissionEntry describes one context entry, ordered oldest to newest, for the shared pre-materialization admission decision (CM-ADM-001).
type AssistantOutput ¶
type AssistantOutput struct {
Content string
Parts []ContentPart
}
AssistantOutput holds extracted assistant content for downstream consumers.
func ExtractAssistantOutputs ¶
func ExtractAssistantOutputs(messages []ModelMessage) []AssistantOutput
ExtractAssistantOutputs collects assistant-role outputs from a slice of ModelMessages.
type Attachment ¶
type Attachment struct {
Type string `json:"type"`
Base64 string `json:"base64,omitempty"`
Path string `json:"path,omitempty"`
URL string `json:"url,omitempty"`
PlatformKey string `json:"platform_key,omitempty"`
ContentHash string `json:"content_hash,omitempty"`
Name string `json:"name,omitempty"`
Mime string `json:"mime,omitempty"`
Size int64 `json:"size,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
Attachment is a media attachment carried in a turn request.
func AttachmentFromBundle ¶
func AttachmentFromBundle(bundle attachment.Bundle) Attachment
AttachmentFromBundle converts the shared internal bundle shape to the turn contract without normalizing or otherwise changing its values.
func (Attachment) Bundle ¶
func (a Attachment) Bundle() attachment.Bundle
Bundle converts the turn attachment to the shared normalized attachment representation used by media ingestion and persistence.
type ContentPart ¶
type ContentPart struct {
Type string `json:"type"`
Text string `json:"text,omitempty"`
URL string `json:"url,omitempty"`
Styles []string `json:"styles,omitempty"`
Language string `json:"language,omitempty"`
ChannelIdentityID string `json:"channel_identity_id,omitempty"`
Emoji string `json:"emoji,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
ContentPart is one element of multipart message content.
func (ContentPart) HasValue ¶
func (p ContentPart) HasValue() bool
HasValue reports whether the content part carries a meaningful value.
type ContextMessageSource ¶ added in v0.22.0
type ContextMessageSource struct {
Kind string `json:"kind"`
ID string `json:"id,omitempty"`
Current bool `json:"current,omitempty"`
}
ContextMessageSource names the stored message a context message renders. Channel composes Discuss context in another process, so it crosses the wire with it.
type DeferredTurnService ¶ added in v0.20.0
type DeferredTurnService interface {
EnqueueDeferredTurn(context.Context, StartTurnCommand) error
}
DeferredTurnService parks a complete user turn that arrived while its session was busy. The run it later starts has no handle consumer, so only an ingress that delivers output through the session runtime subscription (web, cli) may use it; platform channels stream replies from the handle and must not.
type DiscussImageRef ¶
type DiscussImageRef struct {
ContentHash string `json:"content_hash"`
Mime string `json:"mime,omitempty"`
MessageID string `json:"message_id,omitempty"`
}
DiscussImageRef references an image attachment to inline as vision input. MessageID names the external message it arrived with; a ref without one rides on the current input.
type DiscussMessage ¶
type DiscussMessage struct {
Source *ContextMessageSource `json:"source,omitempty"`
Role string `json:"role"`
Content string `json:"content"`
RawContent json.RawMessage `json:"raw_content,omitempty"`
CompactionArtifactID string `json:"compaction_artifact_id,omitempty"`
Pinned bool `json:"pinned,omitempty"`
}
DiscussMessage is one composed context message for a discuss turn. CompactionArtifactID names the summary a message renders. Pinned marks what admission keeps whatever the budget: what the session's history checkpoint holds.
type DiscussRunResolvedPayload ¶
type DiscussRunResolvedPayload struct {
RuntimeType string `json:"runtime_type"`
}
DiscussRunResolvedPayload is the payload of DiscussEventRunResolved.
type Event ¶
type Event struct {
RunID string
TeamID string
ThreadID string
Seq int64
Kind string
Payload json.RawMessage
}
Event is one element of a thread turn's event stream. Payload is the raw JSON chunk exactly as produced by the runtime; Kind is the parsed "type" field (best effort, empty when unparsable). Seq is monotonically increasing per run.
type InjectMessage ¶
type InjectMessage struct {
Text string
Attachments []Attachment
HeaderifiedText string
Applied func()
}
InjectMessage carries a user message to inject into a running agent stream between tool rounds.
type ModelMessage ¶
type ModelMessage struct {
ContextSource *ContextMessageSource `json:"-"`
Source string `json:"-"`
Role string `json:"role"`
Content json.RawMessage `json:"content,omitempty"`
Usage json.RawMessage `json:"-"`
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
Name string `json:"name,omitempty"`
}
ModelMessage is the canonical message format exchanged at the turn boundary.
func (ModelMessage) ContentParts ¶
func (m ModelMessage) ContentParts() []ContentPart
ContentParts parses multipart content, returning nil for strings or invalid JSON.
func (ModelMessage) HasContent ¶
func (m ModelMessage) HasContent() bool
HasContent reports whether the message carries non-empty content or tool calls.
func (ModelMessage) TextContent ¶
func (m ModelMessage) TextContent() string
TextContent extracts plain text from string or multipart content.
type OutboundAssetRef ¶
type OutboundAssetRef struct {
ContentHash string
Role string
Ordinal int
Mime string
SizeBytes int64
StorageKey string
Name string
Metadata map[string]any
}
OutboundAssetRef carries an asset reference accumulated during outbound streaming.
type QuestionAnswer ¶
type QuestionAnswer struct {
QuestionID string `json:"question_id"`
OptionIDs []string `json:"option_ids,omitempty"`
CustomText string `json:"custom_text,omitempty"`
Text string `json:"text,omitempty"`
Skipped bool `json:"skipped,omitempty"`
}
QuestionAnswer is the user's answer to one ask_user question.
type RequestedSkillContext ¶
type RequestedSkillContext struct {
Name string `json:"-"`
Description string `json:"-"`
Content string `json:"-"`
SourceKind string `json:"-"`
OpaqueSourceID string `json:"-"`
ContentHash string `json:"-"`
Identity string `json:"-"`
}
RequestedSkillContext is the full skill material made available to one turn. Its fields are internal execution context and are intentionally omitted from JSON payloads.
type RunHandle ¶
type RunHandle interface {
RunID() string
Events() <-chan Event
Errs() <-chan error
Inject(ctx context.Context, msg InjectMessage) error
AddOutboundAssets(refs []OutboundAssetRef)
Cancel()
}
RunHandle observes and steers one running turn. Events and Errs mirror the runtime's chunk/error channel pair; both close when the run ends.
type RunTerminal ¶ added in v0.21.0
type RunTerminal struct {
Type string `json:"type"`
State string `json:"state"`
ErrorCode string `json:"error_code,omitempty"`
}
RunTerminal is the payload of EventRunTerminal. ErrorCode is the catalog code the run's record carries; it is empty for a completed or aborted run.
func RunTerminalFrom ¶ added in v0.21.0
func RunTerminalFrom(event Event) (RunTerminal, bool)
RunTerminalFrom decodes event as an EventRunTerminal. It reports false for any other event.
func (RunTerminal) Failed ¶ added in v0.21.0
func (t RunTerminal) Failed() bool
Failed reports whether the run ended in failure: its owner reported one, or the runtime declared the run lost.
type RuntimeCommand ¶ added in v0.20.0
type RuntimeCommand struct {
// I18nKey identifies host-owned copy. Native descriptions take precedence.
I18nKey string `json:"i18n_key,omitempty"`
Name string `json:"name"`
Description string `json:"description"`
InputHint string `json:"input_hint,omitempty"`
Kind RuntimeCommandKind `json:"kind"`
RunningText string `json:"running_text,omitempty"`
CompletedText string `json:"completed_text,omitempty"`
// Skill marks a prompt skill, which clients list apart from the runtime's own commands.
Skill bool `json:"skill,omitempty"`
}
type RuntimeCommandKind ¶ added in v0.20.0
type RuntimeCommandKind string
const ( RuntimeCommandTurn RuntimeCommandKind = "turn" RuntimeCommandRead RuntimeCommandKind = "read" RuntimeCommandOperation RuntimeCommandKind = "operation" )
type RuntimeCommandResult ¶ added in v0.20.0
type RuntimeCommandResult struct {
Text string `json:"text,omitempty"`
Data any `json:"data,omitempty"`
Notice string `json:"notice,omitempty"`
}
RuntimeCommandResult preserves structured observations for each surface to render. Text is reserved for native, already textual output; Notice is a stable catalog code.
type RuntimeControlCapabilities ¶ added in v0.20.0
type RuntimeControlRequest ¶ added in v0.20.0
type RuntimeControlRequest struct {
TeamID string `json:"team_id,omitempty"`
BotID string `json:"bot_id"`
ThreadID string `json:"session_id"`
ActorID string `json:"actor_id"`
Command string `json:"command,omitempty"`
ModeID string `json:"mode_id,omitempty"`
ModeKind string `json:"mode_kind,omitempty"`
// ModelID and ReasoningEffort name a session model pick; an empty
// ModelID keeps the session's current model and changes only the effort.
ModelID string `json:"model_id,omitempty"`
ReasoningEffort string `json:"reasoning_effort,omitempty"`
ToolHTTPURL string `json:"tool_http_url,omitempty"`
}
type RuntimeControlService ¶ added in v0.20.0
type RuntimeControlService interface {
RuntimeCommands(context.Context, RuntimeControlRequest) ([]RuntimeCommand, error)
RuntimeControls(context.Context, RuntimeControlRequest) (RuntimeControls, error)
SetRuntimeMode(context.Context, RuntimeControlRequest) (RuntimeModeState, error)
// RuntimeModel and SetRuntimeModel read and remember the session's model
// and reasoning effort, through the same preference the Web picker writes.
RuntimeModel(context.Context, RuntimeControlRequest) (RuntimeModelState, error)
SetRuntimeModel(context.Context, RuntimeControlRequest) (RuntimeModelState, error)
ExecuteRuntimeCommand(context.Context, RuntimeControlRequest) (RuntimeCommandResult, error)
}
RuntimeControlService is the channel-safe, optional control port.
type RuntimeControls ¶ added in v0.20.0
type RuntimeControls struct {
SessionID string `json:"session_id"`
Commands []RuntimeCommand `json:"commands"`
Modes RuntimeModeState `json:"modes"`
PlanMode *RuntimeModeState `json:"plan_mode,omitempty"`
Capabilities RuntimeControlCapabilities `json:"capabilities"`
}
type RuntimeGoal ¶ added in v0.20.0
type RuntimeGoal struct {
Objective string `json:"objective"`
Status string `json:"status"`
TokensUsed int64 `json:"tokens_used"`
TokenBudget *int64 `json:"token_budget,omitempty"`
TimeUsedSeconds int64 `json:"time_used_seconds"`
}
RuntimeGoal is a view of the runtime-owned goal, not another goal store.
type RuntimeGoalService ¶ added in v0.20.0
type RuntimeGoalService interface {
RuntimeGoal(context.Context, RuntimeControlRequest) (*RuntimeGoal, error)
ControlRuntimeGoal(context.Context, RuntimeControlRequest, string) error
}
RuntimeGoalService controls an existing goal without claiming a second run. Creation and resumption use the ordinary admitted conversation path.
type RuntimeMode ¶ added in v0.20.0
type RuntimeMode struct {
I18nKey string `json:"i18n_key,omitempty"`
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
// Icon is a presentation hint; clients may fall back for unknown values.
Icon string `json:"icon,omitempty"`
// Warning marks a runtime-declared elevated permission option.
Warning bool `json:"warning,omitempty"`
}
type RuntimeModeState ¶ added in v0.20.0
type RuntimeModeState struct {
// Kind distinguishes permission presets from arbitrary agent session modes.
Kind string `json:"kind,omitempty"`
// Direct runtimes save a preference and apply it when starting the next turn.
ApplyOnNextTurn bool `json:"apply_on_next_turn,omitempty"`
AvailableModes []RuntimeMode `json:"available_modes"`
CurrentModeID string `json:"current_mode_id"`
Supported bool `json:"supported"`
}
type RuntimeModelOption ¶ added in v0.22.0
type RuntimeModelOption struct {
ID string `json:"id"`
Name string `json:"name"`
Default bool `json:"default,omitempty"`
DefaultReasoningEffort string `json:"default_reasoning_effort,omitempty"`
ReasoningEfforts []string `json:"reasoning_efforts"`
}
RuntimeModelOption is one model a direct runtime offers its session.
type RuntimeModelState ¶ added in v0.22.0
type RuntimeModelState struct {
Supported bool `json:"supported"`
ModelID string `json:"model_id,omitempty"`
ReasoningEffort string `json:"reasoning_effort,omitempty"`
Models []RuntimeModelOption `json:"models"`
}
RuntimeModelState is the model a session's runtime will use next turn and the models it can switch to. Supported is false for runtimes whose model is not chosen per session through Memoh (ACP changes it in the agent).
func (RuntimeModelState) Model ¶ added in v0.22.0
func (s RuntimeModelState) Model() (RuntimeModelOption, bool)
Model returns the option for ModelID, if the runtime still offers it.
type Service ¶
type Service interface {
StartTurn(ctx context.Context, cmd StartTurnCommand) (RunHandle, error)
RespondToolApproval(ctx context.Context, input ToolApprovalResponse, eventCh chan<- json.RawMessage) error
RespondUserInput(ctx context.Context, input UserInputResponse, eventCh chan<- json.RawMessage) error
AdvancePlainTextUserInput(ctx context.Context, input userinput.AdvanceTextInput) (userinput.AdvanceTextResult, error)
}
Service starts and resumes turns. The application service implements this contract directly; cross-process transports expose the same contract. The eventCh parameters mirror the application's raw JSON stream for resumed turns and are not part of the serialized command shape.
type SkillActivation ¶
type SkillActivation struct {
Skills []SkillActivationSkill `json:"skills,omitempty"`
Prompt string `json:"prompt,omitempty"`
} // @name conversation.SkillActivation
SkillActivation is the stable user-message payload for skills activated on a turn.
func NewSkillActivation ¶
func NewSkillActivation(items []RequestedSkillContext, prompt string) *SkillActivation
NewSkillActivation constructs a deduplicated activation payload.
type SkillActivationSkill ¶
type SkillActivationSkill struct {
Name string `json:"name"`
DisplayName string `json:"display_name,omitempty"`
Description string `json:"description,omitempty"`
SourceKind string `json:"source_kind,omitempty"`
State string `json:"state,omitempty"`
} // @name conversation.SkillActivationSkill
SkillActivationSkill is one effective skill named by an activation message.
type StartTurnCommand ¶
type StartTurnCommand struct {
SchemaVersion int
// NoDefer is reserved for server-owned continuation attempts. A follow-up
// that is already being started must surface ErrSessionBusy instead of
// re-entering the follow-up queue when it races another admission.
NoDefer bool
TeamID string // required; the service fails closed when empty
Mode Mode
BotID string
ChatID string
ThreadID string
RouteID string
// ActorAccountID is the account whose authority the run uses: the bot
// owner, or the runtime owner of an external-runtime session, for a
// channel turn; the signed-in user for a Web turn. The caller has
// authenticated it; the run records it to authorize a later resume.
ActorAccountID string
UserID string
SourceChannelIdentityID string
DisplayName string
IdempotencyKey string // derived from platform external message id
ExternalMessageID string
EventID string
AgentCommand string
Query string
ModelQuery string
UserMessageKind string
UserVisibleText string
Attachments []Attachment
ReplyTarget string
ConversationType string
ConversationName string
SourceReplyToMessageID string
ReplySender string
ReplyPreview string
ReplyAttachments []Attachment
MentionsBot bool
RepliesToBot bool
ForwardMessageID string
ForwardFromUserID string
ForwardFromConversationID string
ForwardSender string
ForwardDate int64
CurrentChannel string
Channels []string
Model string
ReasoningEffort string
WorkspaceTargetID string
SkillActivation *SkillActivation
RequestedSkills []RequestedSkillContext
SkipMemoryExtraction bool
SkipTitleGeneration bool
UserMessagePersisted bool
// Discuss-mode extras.
ToolHTTPURL string
// DiscussMessages is the composed conversation context for a discuss
// turn (Mode == ModeDiscuss), already rendered by the caller's
// projection. Image parts are injected into the last real user message
// before the runtime starts streaming.
DiscussCurrentSources []ContextMessageSource
// DiscussOmittedSources is older unconsumed input Channel selection left
// out of DiscussMessages; the server compacts it or records its omission.
DiscussOmittedSources []ContextMessageSource
DiscussMessages []DiscussMessage
DiscussImageRefs []DiscussImageRef
// Pressure is measured before Channel selection. Overflow requests recovery
// without materializing or forwarding the rejected context.
DiscussContextTokens int
DiscussRecoveryExhausted bool
DiscussContextOverflow bool
DiscussCurrentTokens int
// DiscussAddressed covers an explicit @-mention, a reply-to, or a direct
// (1:1) conversation. Expensive external runtimes (ACP) use it as a
// participation gate and skip the run when false. Mention/reply details
// stay attached to their canonical timeline messages.
DiscussAddressed bool
}
StartTurnCommand is a pure-data command. Field set mirrors exactly what the channel inbound processor supplies today; function- and channel-typed fields are intentionally excluded — injection goes through RunHandle.Inject and outbound assets through RunHandle.AddOutboundAssets.
type StopCommand ¶ added in v0.20.0
type StopCommand struct{ TeamID, BotID, ThreadID string }
StopCommand targets the current durable run, including a parked decision. TeamID must match the runtime instance; channel ingress authorizes the actor.
type Stopper ¶ added in v0.20.0
type Stopper interface {
StopTurn(context.Context, StopCommand) (bool, error)
}
Stopper supplements stream cancellation for runs whose output stream ended while waiting for a decision. Kept separate for alternate turn providers.
type TerminalReporter ¶ added in v0.21.0
type TerminalReporter interface {
ReportsRunTerminal() bool
}
TerminalReporter is implemented by a RunHandle that ends every terminal run with EventRunTerminal. A consumer that holds back error events until the run ends checks it first; a handle from a runtime that does not send the event keeps delivering failures only as they happen.
type ToolApprovalResponse ¶
type ToolApprovalResponse struct {
ControlID string
BotID string
ThreadID string
ActorChannelIdentityID string
ActorUserID string
ApprovalID string
ExplicitID string
ReplyExternalMessageID string
Decision string
// OptionID is the opaque agent-provided permission option selected by the
// Web client. Empty retains the legacy binary approve/reject behavior.
OptionID string
Reason string
SuppressActivePromptAttach bool
}
ToolApprovalResponse resumes a thread's turn deferred on tool approval (RFC ResumeApprovalCommand).
type ToolCall ¶
type ToolCall struct {
ID string `json:"id,omitempty"`
Type string `json:"type"`
Function ToolCallFunction `json:"function"`
}
ToolCall represents a function/tool invocation in an assistant message.
type ToolCallFunction ¶
ToolCallFunction holds the name and serialized arguments of a tool call.
type UserInputResponse ¶
type UserInputResponse struct {
ControlID string
BotID string
ThreadID string
ActorChannelIdentityID string
ActorUserID string
UserInputID string
ExplicitID string
ReplyExternalMessageID string
Answers []QuestionAnswer
UILanguage string
TextAnswer string
Canceled bool
Reason string
SuppressActivePromptAttach bool
}
UserInputResponse resumes a thread's turn deferred on ask_user (RFC ResumeUserInputCommand).
type UserMessageHeaderInput ¶
type UserMessageHeaderInput struct {
MessageID string
ChannelIdentityID string
DisplayName string
Channel string
ConversationType string
ConversationName string
Target string
AttachmentPaths []string
Time time.Time
Timezone string
}
UserMessageHeaderInput is the unified input for building user message headers. Keeping this as a struct avoids long positional argument lists and makes future metadata extension backward-compatible for call sites.
type UserMessageMeta ¶
type UserMessageMeta struct {
MessageID string `json:"message-id,omitempty"`
ChannelIdentityID string `json:"channel-identity-id"`
DisplayName string `json:"display-name"`
Channel string `json:"channel"`
ConversationType string `json:"conversation-type"`
ConversationName string `json:"conversation-name,omitempty"`
Target string `json:"target,omitempty"`
Time string `json:"time"`
Timezone string `json:"timezone,omitempty"`
AttachmentPaths []string `json:"attachments"`
}
UserMessageMeta holds the structured metadata attached to every user message. It is the single source of truth for the XML message tag sent to the LLM.
func BuildUserMessageMetaFromInput ¶
func BuildUserMessageMetaFromInput(input UserMessageHeaderInput) UserMessageMeta
BuildUserMessageMetaFromInput constructs metadata from one cohesive input.
func BuildUserMessageMetaWithTime ¶
func BuildUserMessageMetaWithTime(messageID, channelIdentityID, displayName, channel, conversationType, conversationName string, attachmentPaths []string, now time.Time, timezone string) UserMessageMeta
BuildUserMessageMetaWithTime constructs metadata with an explicit timestamp and timezone label for user-facing prompts.
func (UserMessageMeta) ToMap ¶
func (m UserMessageMeta) ToMap() map[string]any
ToMap returns the metadata as a map with the same keys used in the XML attributes, suitable for storing as inbox content JSONB.