wire

package
v0.32.0 Latest Latest
Warning

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

Go to latest
Published: Sep 5, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package common is the memcode PROTOCOL contract: the wire types shared by the CLI (the client) and the api gateway (the server), the sdk/agent ↔ CLI stream-json envelope, the abstract Intent, shared error sentinels, and the model/pricing metadata both ledgers price against.

It is the single source of truth for everything that crosses a memcode wire. Both the cli and api modules redeclared these types independently once, and the drift caused real outages (tool input_schema, lane bypass) — this package exists so that can never happen again.

Invariant: common holds the PROTOCOL only and is stdlib-only (zero third-party dependencies). It contains no prompt doctrine, no provider keys, no routing logic, and no capability interfaces — those live at their consuming boundary (the cli and api each declare the structural interface they need; a client implementation merely satisfies them). A guard test enforces the stdlib-only rule.

Index

Constants

View Source
const (
	// client → CLI (control)
	MsgInitialize         = "initialize"          // first message; configure the session
	MsgUserTurn           = "user_turn"           // submit a user prompt (starts a turn)
	MsgPermissionResponse = "permission_response" // answer a permission_request
	MsgAskResponse        = "ask_response"        // answer an ask_request
	MsgCancel             = "cancel"              // interrupt the running turn

	// CLI → client (events)
	MsgInitialized       = "initialized"        // session ready; carries session id
	MsgAssistantDelta    = "assistant_delta"    // a chunk of assistant text
	MsgToolCall          = "tool_call"          // a tool is running
	MsgToolResult        = "tool_result"        // a tool finished (summary)
	MsgPermissionRequest = "permission_request" // the turn is blocked awaiting approval
	MsgAskRequest        = "ask_request"        // the turn is blocked awaiting a user choice
	MsgSessionState      = "session_state"      // busy/idle + room/mode telemetry
	MsgUsage             = "usage"              // running token counts
	MsgResult            = "result"             // a turn finished
	MsgError             = "error"              // a turn errored
)

Message families. The direction comments are from the wrapper's point of view.

View Source
const CodeAccountLocked = "account_locked"

CodeAccountLocked is the gateway's machine-readable error code for an org locked by a negative balance (HTTP 402), mapped to ErrAccountLocked.

View Source
const CodeByokKeyFailed = "byok_key_failed"

CodeByokKeyFailed is the gateway's machine-readable error code for a turn killed by the user's own provider key (HTTP 422 body and the SSE error event), mapped to ErrByokKeyFailed.

View Source
const CodeContextOverflow = "context_overflow"

CodeContextOverflow is the gateway's machine-readable error code for a context-window overflow — carried on the HTTP 413 body and the SSE error event, mapped to ErrContextOverflow by the client.

View Source
const CodeInsufficientCredit = "insufficient_credits"

CodeInsufficientCredit is the gateway's machine-readable error code for an exhausted credit wallet — carried on the HTTP 402 body and the SSE error event, mapped to ErrInsufficientCredit by the client.

View Source
const CodeSubscriptionRequired = "subscription_required"

CodeSubscriptionRequired is the gateway's machine-readable error code for an org with no active subscription (HTTP 402), mapped to ErrSubscriptionRequired.

View Source
const StreamJSONVersion = "1"

StreamJSONVersion is the protocol version stamped on every Envelope. Bump on a breaking change to the message families or payloads.

Variables

View Source
var ErrAccountLocked = errors.New("your balance is negative — hosted models are paused; settle it at memcode.ai/account/billing (your own API keys keep working via /apikeys)")

ErrAccountLocked is returned when the org's balance went negative from a post-hoc debit overrun — the gateway returns 402 with code "account_locked". Everything is refused, BYOK included, until credits are added. Never retried.

View Source
var ErrByokKeyFailed = errors.New("your API key was rejected — fix or remove it with /apikeys")

ErrByokKeyFailed is returned when the turn died on the USER's own provider key (fail-the-turn doctrine: a failing BYOK key is never absorbed onto memcode's keys) — the gateway returns 422 with code "byok_key_failed". Never retried: the fix is /apikeys, not another attempt.

View Source
var ErrContextOverflow = errors.New("context window overflow")

ErrContextOverflow is returned when a turn's prompt exceeds the served context window on EVERY available backend (the gateway already absorbs vLLM overflow up to Anthropic; this fires only when even Anthropic's window is exceeded). The CLI runtime watches for it with errors.Is and compacts-then-retries the turn rather than surfacing a raw error — the reactive end of the routing ladder. On the wire it is signalled by HTTP 413 with code "context_overflow" and by an SSE error event carrying the same code.

View Source
var ErrInsufficientCredit = errors.New("credits exhausted — add your own API keys with /apikeys, or manage your plan and credits at memcode.ai/account/billing")

ErrInsufficientCredit is returned when the org's prepaid credit balance is exhausted — the gateway returns 402 with code "insufficient_credits". The CLI surfaces a friendly message and stops the turn (no retry: it's a user action, not a transient failure). Keys lead the message: they're the fix on every plan, while "add credits" doesn't exist on the BYOK-only Free plan.

View Source
var ErrStreamIncomplete = errors.New("gateway stream ended without a response")

ErrStreamIncomplete is returned when an SSE stream ends WITHOUT a terminal response event (a mid-stream read error, or the connection closing early — e.g. a Cloud Run request-timeout cutting off a long model call). It is a transient TRANSPORT failure, not a model/logic error: the failed call appended nothing, so the runtime can retry it from the same history. Watched with errors.Is and retried (bounded) rather than dying mid-turn with work half-done.

View Source
var ErrSubscriptionRequired = errors.New("subscription required — choose a plan at memcode.ai/account/billing")

ErrSubscriptionRequired is returned when the org has no active subscription — the gateway returns 402 with code "subscription_required". Subscription is mandatory for every LLM call, BYOK included (2026-07-26). Never retried: choosing a plan is a user action.

View Source
var ErrUnauthorized = errors.New("not signed in — your session expired or the token was revoked; run /login to reconnect")

ErrUnauthorized is returned when the gateway rejects the bearer token (HTTP 401): expired, revoked, or the retired legacy static token. It means the SESSION is signed out, not that the turn transiently failed — hosts watch with errors.Is, flip to their signed-out state, and prompt for /login instead of surfacing a raw HTTP error. Never retried.

Functions

This section is empty.

Types

type AskRequestData

type AskRequestData struct {
	Question string   `json:"question"`
	Options  []string `json:"options,omitempty"`
}

AskRequestData / AskResponseData are the ask_user human-in-the-loop round-trip.

type AskResponseData

type AskResponseData struct {
	Answer string `json:"answer"`
}

type AssistantDeltaData

type AssistantDeltaData struct {
	Text string `json:"text"`
}

AssistantDeltaData is a chunk of streamed assistant text (CLI → client).

type Block

type Block struct {
	Type string `json:"type"` // "text" | "image" | "document" | "tool_use" | "tool_result"
	Text string `json:"text,omitempty"`

	// image / document
	Source *MediaSource `json:"source,omitempty"`

	// tool_use
	ID    string          `json:"id,omitempty"`
	Name  string          `json:"name,omitempty"`
	Input json.RawMessage `json:"input,omitempty"`

	// tool_result
	ToolUseID string `json:"tool_use_id,omitempty"`
	Content   string `json:"content,omitempty"`
	IsError   bool   `json:"is_error,omitempty"`

	// ContentBlocks carries STRUCTURED content for a tool_result — one or more
	// content blocks (text and/or image) instead of the flat Content string. This
	// is the path for tool results that include vision (e.g. a browser screenshot
	// returned to the model as an image block). When non-empty, providers emit the
	// structured content union (Anthropic: text+image parts in the tool_result;
	// OpenAI: multi-part tool message). When empty, Content (flat string) is used
	// — backwards compatible with every text-only tool result.
	ContentBlocks []Block `json:"content_blocks,omitempty"`

	// thinking (extended/adaptive reasoning). These MUST round-trip UNMODIFIED: the
	// API requires the assistant's thinking blocks to be passed back verbatim on the
	// next tool-use turn (it verifies them via Signature) or it rejects the request.
	// So we parse them off responses and re-send them; we just don't display them.
	// Data carries a redacted_thinking block's opaque payload, if one ever appears.
	Thinking  string `json:"thinking,omitempty"`
	Signature string `json:"signature,omitempty"`
	Data      string `json:"data,omitempty"`

	// prompt caching (set on the wire only, never on shared history — see the gateway)
	CacheControl *CacheControl `json:"cache_control,omitempty"`
}

Block is one content block in a message (text, image/document, a tool call, or a tool result, or a thinking block).

func DocumentBlock

func DocumentBlock(mediaType string, data []byte) Block

DocumentBlock builds a document block from raw file bytes (application/pdf is the interoperable case: Anthropic document source, OpenAI Responses input_file, Gemini inline blob). Models without native document input absorb the turn to a capable tier — the catalog's pdf flag gates that in the router.

func ImageBlock

func ImageBlock(mediaType string, data []byte) Block

ImageBlock builds a vision block from raw image bytes.

func TextBlock

func TextBlock(text string) Block

TextBlock builds a text block.

func ToolResultBlocks

func ToolResultBlocks(toolUseID string, blocks []Block, isError bool) Block

ToolResultBlocks builds a tool_result block carrying structured content blocks (text and/or image) instead of a flat string. This is the path for tool results that include vision — e.g. a browser screenshot returned as an image block. When blocks is empty, falls back to an empty text result.

func (Block) MarshalJSON

func (b Block) MarshalJSON() ([]byte, error)

MarshalJSON serializes a Block for the wire. Thinking blocks MUST carry the "thinking" field even when its text is EMPTY: adaptive thinking frequently returns a block that is just a signature (the reasoning text omitted), and on the next tool-use turn Anthropic rejects a thinking block without the field — "thinking.thinking: Field required". The struct tag is `omitempty` (correct for every OTHER block type, which must NOT carry a stray empty "thinking"), so we special-case thinking / redacted_ thinking here and let the alias handle the rest with default tags.

type CacheControl

type CacheControl struct {
	Type string `json:"type"` // "ephemeral"
	// TTL is the cache lifetime: "" (default 5m) or "1h". The long TTL is used for the
	// STABLE doctrine+tools prefix, which is byte-identical across turns even as the
	// volatile facts (room/personality) change — so it survives interactive gaps >5min.
	TTL string `json:"ttl,omitempty"`
}

CacheControl marks a prompt-cache breakpoint. Everything from the start of the prompt up to and including the marked block is cached (5-min ephemeral TTL); later requests sharing that prefix read it instead of re-paying input tokens, and cache reads are excluded from the input-tokens/min rate limit.

type Effort

type Effort string

Effort is an abstract reasoning-depth setting. It exists so call sites express INTENT ("this is a judgment call, think harder") without hardcoding a provider shape that differs by model — e.g. Opus 5 rejects manual budget_tokens and requires adaptive thinking + an effort hint, while Opus 4.5 wants budget_tokens.

const (
	EffortOff    Effort = ""       // no extended thinking (default; cheap paths)
	EffortLow    Effort = "low"    // light reasoning
	EffortMedium Effort = "medium" // judgment calls (edits, reflection)
	EffortHigh   Effort = "high"   // hardest reasoning (planning, review)
)

type Envelope

type Envelope struct {
	Version string          `json:"version"`
	Type    string          `json:"type"`
	ID      string          `json:"id,omitempty"`      // correlation id (e.g. a permission/ask request↔response)
	TurnID  string          `json:"turn_id,omitempty"` // the turn this message belongs to
	Data    json.RawMessage `json:"data,omitempty"`
}

Envelope is the single wire frame. Data is a type-specific payload (below).

type ErrorData

type ErrorData struct {
	Message string `json:"message"`
}

ErrorData reports a turn-level error (CLI → client).

type InitializeData

type InitializeData struct {
	Cwd  string `json:"cwd,omitempty"`  // working directory / repo root
	Mode string `json:"mode,omitempty"` // permission mode: ask | auto | allow-all
	Pin  string `json:"pin,omitempty"`  // the session's model label
}

InitializeData configures the session (client → CLI).

type InitializedData

type InitializedData struct {
	SessionID string `json:"session_id"`
	Protocol  string `json:"protocol"` // echoes the version for handshake validation
}

InitializedData announces a ready session (CLI → client).

type Intent

type Intent struct {
	// Purpose is what this turn is FOR (ledger attribution + the utility split):
	// "main_loop" | "explore" | "classify" | "compact" | …
	Purpose string `json:"purpose,omitempty"`

	// Mode names the doctrine the turn runs under ("chat" | "exec" | "plan" | …).
	Mode string `json:"mode,omitempty"`

	// Reasoning is the abstract reasoning depth the turn warrants (maps to
	// Effort). Effort is a genuinely separate axis from model choice and
	// survives the ladder: a tricky single-file bug can want deep thinking on
	// the same model an easy one uses.
	Reasoning Effort `json:"reasoning,omitempty"`

	// Interactive is true when a live user is present (vs a batch/background
	// job) — available to the policy for latency-vs-cost trade-offs.
	Interactive bool `json:"interactive,omitempty"`

	// Pin is the session's model: a catalog LABEL ("sol", "sonnet", "glm-5p2",
	// …), never a raw provider id — raw ids stay at the serving edge. The pin
	// resolver settles it once at session start from the
	// session -> workspace -> user -> default_model chain, so it is always set
	// for a real session; selection refuses rather than inventing one if it
	// isn't.
	//
	// Every real request serves this model. Internal plumbing
	// (classify/compact/shrinkwrap) rides the catalog's utility_model instead,
	// and capability gaps fail the turn visibly rather than rerouting it.
	Pin string `json:"pin,omitempty"`
}

Intent is the abstract selection contract: the session layer expresses WHAT a turn is, and the CLI's selection policy (internal/llm/resolve.go) maps it to a concrete catalog label. It is a client-internal type — it never rides a wire.

It used to carry the Automatic ladder's inputs (Difficulty, Risk, Vendor), and resolving them into a model was a per-turn decision. That is gone: there is exactly one model per session, the user's pin, and Intent now only says what KIND of turn this is so that internal plumbing can be told apart from the user's own work.

type MediaSource

type MediaSource struct {
	Type      string `json:"type"`       // "base64"
	MediaType string `json:"media_type"` // e.g. image/png, application/pdf
	Data      string `json:"data"`
}

MediaSource carries base64 image/document data for vision blocks.

type Message

type Message struct {
	Role   string  `json:"role"` // "user" | "assistant"
	Blocks []Block `json:"content"`
}

Message is one turn (a role plus its content blocks).

type PermissionRequestData

type PermissionRequestData struct {
	Title    string `json:"title"`
	Label    string `json:"label,omitempty"`
	Detail   string `json:"detail,omitempty"`
	Command  string `json:"command,omitempty"`
	Cwd      string `json:"cwd,omitempty"`
	Risk     string `json:"risk,omitempty"`
	Editable bool   `json:"editable,omitempty"`
}

PermissionRequestData asks the client to approve an action (CLI → client). The client answers with a PermissionResponseData carrying the same Envelope.ID.

type PermissionResponseData

type PermissionResponseData struct {
	Allow     bool   `json:"allow"`
	Command   string `json:"command,omitempty"`   // run this edited command instead
	Reason    string `json:"reason,omitempty"`    // when !allow: fed back to the model
	Interrupt bool   `json:"interrupt,omitempty"` // stop the whole turn
}

type Request

type Request struct {
	Model    string    `json:"model,omitempty"` // resolved id at the serving edge; clients carry their choice in Pin
	System   string    `json:"system,omitempty"`
	Messages []Message `json:"messages"`

	// SystemVolatile is the per-turn-variable doctrine suffix (room/personality/
	// extra-mile/nudge + the turn-scoped extra) split OUT of System so it sits
	// OUTSIDE the cached prefix. The CLI's doctrine composer fills it (directly,
	// or via the transport's compose hook from Mode+Facts); adapters place it
	// cache-safely — Anthropic as a second, uncached system block, chat/
	// completions as a trailing system message, so the stable prefix still
	// auto-caches.
	SystemVolatile string    `json:"system_volatile,omitempty"`
	Tools          []ToolDef `json:"tools,omitempty"`
	MaxTokens      int       `json:"max_tokens,omitempty"`

	// ToolChoice, when set to a tool name, FORCES the model to call that tool — the
	// reliable cross-provider path to structured output (Anthropic tool_choice / OpenAI
	// tool_choice). Used by the plan reviewer's verdict so the JSON comes back in a tool_use
	// block instead of best-effort prose-JSON. "" = the model chooses (the common case).
	ToolChoice string `json:"tool_choice,omitempty"`

	// Mode + Facts select a doctrine prompt: the transport's compose hook
	// (cli/internal/doctrine) renders the mode's doctrine with these gathered
	// facts (root, platform, shell, overview/pack, room, nudge) into System/
	// SystemVolatile just before encoding. Mode "" = raw transport (no
	// composition; System passes through as-is).
	Mode  string            `json:"mode,omitempty"`
	Facts map[string]string `json:"facts,omitempty"`

	// Effort is the ABSTRACT reasoning-depth knob. The provider maps it to whatever
	// thinking control the target model actually supports (adaptive+effort, manual
	// budget_tokens, or nothing). Zero value (EffortOff) means no extended thinking.
	Effort Effort `json:"effort,omitempty"`

	// Purpose + Session are transport-local labels (json:"-": never marshaled on
	// this type). Purpose labels the call for the client ledger and the lane
	// leak-log. Session rides the compat wire as the standard `user` field for
	// serving affinity (prefix-cache locality) and gateway telemetry. Stamped by
	// the CLI's llm.Runner; never set by hand.
	Purpose string `json:"-"`
	Session string `json:"-"`

	// Pin is the CLI-side carrier for the session's model choice: the resolved
	// catalog LABEL the transport puts in the wire `model` field. Under
	// all-policy-client-side the CLI's selection policy stamps it on EVERY
	// call (Automatic is client behavior); "" is only ever seen by test fakes.
	Pin string `json:"-"`

	// BillingLane is the requested billing lane: "" / "byok_preferred" |
	// "byok_only" | "credits". Client-side it is set by policy (the consented
	// credits retry after a BYOK key failure) and rides the wire as the
	// memcode_billing extension; server-side the compat handler re-stamps it
	// from that extension and the gateway ENFORCES it — it never silently
	// reroutes between the user's keys and credits. NOT marshaled on this type.
	BillingLane string `json:"-"`
	// LaneBypass forces a turn OFF its family lane after an explicit,
	// consented exhaustion choice: "gateway" serves it on the hosted base.
	// Client-side routing state only — never serialized to any wire.
	LaneBypass string `json:"-"`
}

Request is a model completion request — the provider-neutral shape every adapter encodes from. Model selection is the CLI's job (llm/lane.go + llm/resolve.go): the Runner's policy resolves a catalog label into Pin, and the transport writes it into the wire `model` field. Server-side, Model carries the gateway's raw provider id after the label gate resolves it.

type Response

type Response struct {
	StopReason   string  `json:"stop_reason"` // "end_turn" | "tool_use" | "max_tokens"
	Blocks       []Block `json:"blocks"`      // assistant content (text and/or tool_use)
	InputTokens  int     `json:"input_tokens"`
	OutputTokens int     `json:"output_tokens"`

	// prompt-cache telemetry (tokens written to / read from the cache this call)
	CacheWriteTokens int `json:"cache_write_tokens,omitempty"`
	CacheReadTokens  int `json:"cache_read_tokens,omitempty"`

	// SearchCount is the number of native server-side web searches the serving
	// vendor billed on this call (Anthropic usage.server_tool_use.web_search_requests;
	// OpenAI/Grok Responses web_search_call output items). Searches carry a
	// PER-REQUEST fee on top of tokens — the gateway prices it via
	// common.SearchFeeUSD(Backend, SearchCount) when it emits cost_usd.
	SearchCount int `json:"search_count,omitempty"`

	// ToolOrigin records how a tool call was obtained: "structured" (the model's native
	// tool_calls — the intended path) or "salvaged_*" (the gateway recovered it from
	// text a brittle parser missed). Surfaced so salvage stays OBSERVABLE, never silently
	// the main contract.
	ToolOrigin string `json:"tool_origin,omitempty"`

	// Serving telemetry — the ledger's ground truth for WHO served this call.
	// Model is the model that actually ran (a fallback-chain hop can differ from
	// the requested label). Backend is the serving vendor: "cheap" (the hosted
	// cheap lane, vendor-neutral — the inference vendor never rides the wire) |
	// "anthropic" | "openai" | "gemini" | "grok" | "unknown" (label missing from
	// the client catalog); "vllm" is the legacy cheap-lane tag an un-redeployed
	// gateway sends (clients accept both). FallbackReason names why the served
	// model differs from the primary choice: a client-side absorb ("vision" |
	// "pdf" | "window") or a recovery hop ("model_error: …").
	Model          string `json:"model,omitempty"`
	Backend        string `json:"backend,omitempty"`
	FallbackReason string `json:"fallback_reason,omitempty"`

	// RequestedModel is the label the selection policy chose BEFORE any absorb/
	// fallback — the basis for the ledger's counterfactual "what the primary
	// would have cost". The CLI's finalize stamps it (the gateway echoes the
	// requested id on hosted turns); it equals Model when nothing intervened.
	RequestedModel string `json:"requested_model,omitempty"`

	// ContextWindow is the serving backend's real input window in tokens, when
	// the backend reports one (0 when the client's catalog already knows it).
	ContextWindow int `json:"context_window,omitempty"`

	// InputBudget is the serving lane's usable INPUT budget (window − output reserve −
	// safety margin) — the size a prompt must fit under to land on THIS lane. The CLI
	// learns the cheap lane's budget from this and aims compaction at it. 0 when not
	// lane-served.
	InputBudget int `json:"input_budget,omitempty"`

	// Pool is the cheap lane's served-model short label ("glm-5p2" | "kimi-k3"),
	// the CLI's ⇄ ServedBy tag for lane serves. EstimatedPromptTokens is the
	// server's pre-call size estimate (stamped per serve so the usage log's
	// EstimateRatio can calibrate the estimator against real InputTokens).
	Pool                  string `json:"pool,omitempty"`
	EstimatedPromptTokens int    `json:"estimated_prompt_tokens,omitempty"`

	// BYOK telemetry. BYOK (whether this call ran on the user's OWN provider
	// key) rides the wire — it is the key owner's own information, shown by the
	// CLI footer strictly per-turn. BYOKVendor stays SERVER-INTERNAL (json:"-"):
	// the cheap lane's inference vendor never leaves the server (SanitizeResponse
	// zeroes it defensively). The gateway reads both for metering (usage line +
	// zero-debit policy) before sanitizing.
	BYOK       bool   `json:"byok,omitempty"`
	BYOKVendor string `json:"-"`
}

Response is a model completion result, plus the serving telemetry the footer/ ledger read. On the hosted backend the gateway stamps the serving facts (via the memcode response extension); in direct-endpoint mode the CLI's recovery policy stamps them itself (finalize) — same fields, one reader.

func (Response) Text

func (r Response) Text() string

Text returns the concatenated text blocks of a response.

func (Response) ToolUses

func (r Response) ToolUses() []Block

ToolUses returns the tool_use blocks of a response.

type ResultData

type ResultData struct {
	Text      string `json:"text,omitempty"` // final assistant text, if captured
	Completed bool   `json:"completed"`
}

ResultData ends a turn (CLI → client).

type SessionStateData

type SessionStateData struct {
	Busy bool   `json:"busy"`
	Mode string `json:"mode,omitempty"` // room mode (normal/repair/replan), when known
}

SessionStateData reports busy/idle + light room telemetry (CLI → client).

type StreamHandler

type StreamHandler struct {
	Text  func(delta string)
	Usage func(input, output int)
}

StreamHandler receives incremental events during a streamed completion. Both callbacks are optional. Text fires for each chunk of assistant text as it arrives; Usage fires when the API reports token counts (input at the start, authoritative output near the end — NOT per delta, so a live "tokens so far" display must estimate from streamed text between Usage calls and reconcile when Usage fires).

This is a data type (a struct of callbacks), part of the wire contract's shape. The capability INTERFACES (ModelProvider, Streamer, WebSearcher, WebFetcher, Advisor) are intentionally NOT declared here — each consumer declares the structural interface it needs, referencing these common types; an implementation merely satisfies it.

type ToolCallData

type ToolCallData struct {
	Name   string `json:"name"`
	Target string `json:"target,omitempty"`
	Detail string `json:"detail,omitempty"`
}

ToolCallData / ToolResultData report tool activity (CLI → client).

type ToolDef

type ToolDef struct {
	Name        string         `json:"name"`
	Description string         `json:"description"`
	InputSchema map[string]any `json:"input_schema"`

	// prompt caching — set on the LAST tool only, on the wire (see the gateway)
	CacheControl *CacheControl `json:"cache_control,omitempty"`
}

ToolDef describes a tool the model may call.

type ToolResultData

type ToolResultData struct {
	Name   string `json:"name"`
	Status string `json:"status,omitempty"` // "ok" | "failed" | …
}

type UsageData

type UsageData struct {
	OutputTokens int `json:"output_tokens"`
}

UsageData reports running token counts (CLI → client).

type UserTurnData

type UserTurnData struct {
	Text string `json:"text"`
}

UserTurnData submits a prompt (client → CLI).

Jump to

Keyboard shortcuts

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