turn

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 8, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

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

View Source
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.

View Source
const (
	ConversationTypePrivate = "private"
	ConversationTypeGroup   = "group"
	ConversationTypeThread  = "thread"
)
View Source
const (
	RunStateCompleted = "completed"
	RunStateAborted   = "aborted"
	RunStateFailed    = "failed"
	RunStateLost      = "lost"
)

Terminal run states. They are the durable record's values.

View Source
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.

View Source
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.

View Source
const MessageSourceInternalFeedback = "internal_feedback"

MessageSourceInternalFeedback is runtime-generated input, never a new user turn.

View Source
const UserMessageKindSkillActivation = "skill_activation"

UserMessageKindSkillActivation identifies persisted skill activation messages.

Variables

View Source
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.

View Source
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.

View Source
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.

View Source
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 ContextBudgetBytes(tokens int) int64

func CurrentAdmissionEntries added in v0.22.0

func CurrentAdmissionEntries(entries []AdmissionEntry) []bool

func EstimateTokensFromBytes

func EstimateTokensFromBytes(n int) int

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

func IsPrivateConversationType(raw string) bool

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

func NormalizeConversationType(raw string) string

NormalizeConversationType normalizes delivery-specific aliases into the application-level conversation vocabulary carried by turn commands.

func PlaceSummary added in v1.0.0

func PlaceSummary[T any](items []T, summary T, covered func(T) bool) ([]T, bool)

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

func ReportsRunTerminal(handle RunHandle) bool

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

func SummaryText(summary string) string

SummaryText is the text a summary renders as wherever a request carries it: the preamble, then the summary in its tags.

func UnwrapUserMessageEnvelope

func UnwrapUserMessageEnvelope(text string) string

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

type ACPAgentProfile struct {
	ID          string
	DisplayName string
	Known       bool
}

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

type ACPManagedField struct {
	ID    string
	Label string
}

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 Mode

type Mode string

Mode selects the turn orchestration path.

const (
	ModeChat    Mode = "chat"
	ModeDiscuss Mode = "discuss"
)

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 RuntimeControlCapabilities struct {
	ForkLatestOnly  bool `json:"fork_latest_only"`
	PermissionModes bool `json:"permission_modes"`
	Compact         bool `json:"compact"`
	PlanMode        bool `json:"plan_mode"`
	Goal            bool `json:"goal"`
}

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

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

type ToolCallFunction struct {
	Name      string `json:"name"`
	Arguments string `json:"arguments"`
}

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.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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