extension

package
v0.4.1 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: MIT Imports: 34 Imported by: 0

Documentation

Overview

Package extension defines the contract every pig extension speaks. It mirrors upstream pi's ExtensionAPI surface 1:1 so a TS extension can be ported to Go almost line-for-line, and so each upstream version bump is an additive diff rather than a structural one.

Source of truth:

.upstream/current/packages/coding-agent/src/core/extensions/types.ts

This package contains only the public API contract: types, the fat API interface, and the Extension author-facing interface. Hosts (the inproc dispatch runner and subprocess transport adapter) live under coding/extension/host/ and depend on this package, never the reverse.

Faithfulness rules

  • Method order on the API interface matches upstream ExtensionAPI declaration order. Section dividers mirror upstream comments.
  • Every field on every event struct carries a json:"camelCaseName" tag matching upstream's TS field name. The parity gates in test/upstream-parity/ enforce this on every CI run.
  • Field names use idiomatic Go casing with terminal initialism uplift (Id→ID, Url→URL, Api→API, Json→JSON). For example, upstream `toolCallId` becomes Go `ToolCallID`. The parity reflection check uses [parity.CamelToGoField] which knows the closed initialism set; extending it requires a coordinated update to that helper plus a docs/parity/DIVERGENCES.md U1 sync-ritual entry.
  • Observable differences use a numbered source marker and ledger record.

Opaque compatibility types

Upstream references many domain types (AgentMessage, Model, CompactionEntry, AbortSignal, Component, etc.) that don't yet have concrete Go equivalents in PiG. Types that cross the current dynamic JSON or renderer boundaries are explicit opaque aliases in opaque_types.go. Concrete events and SDK methods use typed Go values where the contract is stable.

Shell command execution for extensions.

Mirrors upstream core/exec.ts. Provides the implementation backing extension.API.Exec: a simple process spawn with timeout and abort support.

upstream: coding-agent/src/core/exec.ts (107 LOC)

Index

Constants

View Source
const (
	DiagnosticWarning   = "warning"
	DiagnosticError     = "error"
	DiagnosticCollision = "collision"
)

Diagnostic type constants matching upstream's literal union.

View Source
const (
	LoginBrandWidth            = 41
	LoginBrandHeight           = 5
	LoginHeroWidth             = 32
	LoginHeroHeight            = 14
	LoginMascotWidth           = 16
	LoginMascotHeight          = 14
	LoginPaletteLimit          = 32
	LoginNameWidthLimit        = 24
	LoginDescriptionWidthLimit = 48
	LoginTaglineWidthLimit     = 76
	LoginMetadataWidthLimit    = 80
)

pig additive (D60): Pig validates a typed login definition because subprocess extensions cannot pass Pi's live TUI component factories.

View Source
const SpriteIDLimit = 32

pig divergence (D2): an extension adds a sprite to PiG's /sprite catalogue with the same kind of data as its native login (D60): pixel grids of palette symbols, a palette and display text. The host validates it and draws it; a sprite never replaces the header by itself.

View Source
const VirtualModelAPI = "pi-virtual"

VirtualModelAPI is the API id of virtual catalog entries. Requests for it fail unless routed first.

upstream: virtual-models.ts:29 (VIRTUAL_MODEL_API)

View Source
const VirtualModelStateEntry = "pi.virtual-model-state"

VirtualModelStateEntry is the custom entry type that stores router state on the session branch.

upstream: virtual-models.ts:32 (VIRTUAL_MODEL_STATE_ENTRY)

Variables

View Source
var (
	// ErrStaleContext is returned by API calls made through an
	// ExtensionContext whose runner has been replaced (typically after
	// /reload or a session swap). Mirrors upstream's invalidate() sentinel
	// in core/extensions/runner.ts.
	ErrStaleContext = errors.New("extension: context is stale (runner replaced)")

	// ErrBusy is returned when an action is rejected because the agent is
	// streaming or compacting. Mirrors upstream's reload guard in
	// modes/interactive/interactive-mode.ts handleReloadCommand.
	ErrBusy = errors.New("extension: agent is busy (streaming or compacting)")

	// ErrCapabilityNotDeclared is returned when an extension calls an API
	// surface it didn't declare in its manifest capabilities list.
	ErrCapabilityNotDeclared = errors.New("extension: capability not declared in manifest")

	// ErrUnknownEvent is returned when a host attempts to dispatch an event
	// name that no registered handler understands. Hosts may treat this as
	// an info-level no-op; it exists for tests and diagnostics.
	ErrUnknownEvent = errors.New("extension: unknown event")
)

Sentinel errors surfaced by extension hosts (the inproc dispatch runner and subprocess transport adapter) to extensions. Authors compare with errors.Is.

View Source
var ErrHandlerStopped = errors.New("extension handler stopped by the host")

ErrHandlerStopped marks a handler call the host itself cut short: it stopped the extension (shutdown, a termination signal, /reload) or cancelled the dispatch. The handler did not fail, so runners do not report it as an ExtensionError. Upstream never interrupts a running handler; its signal path disposes the runtime and exits without reporting the interrupted work.

View Source
var ErrRuntimeNotInitialized = errors.New("Extension runtime not initialized. Action methods cannot be called during extension loading.")

ErrRuntimeNotInitialized is returned by an action called while extensions are still loading. upstream: loader.ts:157-159 (notInitialized)

View Source
var ErrUIUnavailable = errors.New("UI not available")

ErrUIUnavailable reports that a UI-only operation cannot run in the current mode.

Functions

func AnyModelInfo

func AnyModelInfo(model ai.AnyModel) map[string]any

AnyModelInfo projects a model of any type into the extension-facing Pi model shape. A chat model is ModelInfo; an image or classifier model carries its own type and the fields of its variant (packages/ai/src/types.ts ImageModel and ClassifierModel). A nil model is nil.

func BeforeAgentStartSelectedTools

func BeforeAgentStartSelectedTools(ctx context.Context) json.RawMessage

BeforeAgentStartSelectedTools returns the current wire value, retaining untyped edits until prompt admission. A native collection replacement supersedes the preceding wire value.

func CallInitiated

func CallInitiated(ctx context.Context)

CallInitiated reports that the call carried by ctx has applied its synchronous part. It is a no-op without a mark and safe to call repeatedly when the mark is idempotent.

func ErrorStack

func ErrorStack(err error) string

ErrorStack returns the stack carried by err or an error it wraps, or "". Runners use it for ExtensionError.Stack: upstream reports the handler's `err.stack`, never the host's own dispatch stack.

func IsLoopbackRedirectURI

func IsLoopbackRedirectURI(value string) bool

IsLoopbackRedirectURI reports whether a redirect URI can be served by the loopback callback server: an `http` URI on `localhost`, `127.0.0.1`, or `[::1]` without query or fragment. The URI is parsed as `new URL(value)` does.

func MarshalInputEventResult

func MarshalInputEventResult(r InputEventResult) ([]byte, error)

MarshalInputEventResult serialises a sealed-interface variant to upstream wire shape with the `action` discriminator.

Why a free function not a method on the interface: defining a marshal method on the interface would force every variant to implement it (verbose); using a free function keeps marker structs trivial. Hosts dispatching events call this; authors returning a value from OnInput have their value passed through this helper by the runtime.

func MarshalToolCallEvent

func MarshalToolCallEvent(e ToolCallEvent) ([]byte, error)

MarshalToolCallEvent serialises any of the nine ToolCallEvent variants. Each variant struct already declares upstream-faithful JSON tags; this helper only narrows the interface to a concrete value before marshalling.

func MarshalToolResultEvent

func MarshalToolResultEvent(e ToolResultEvent) ([]byte, error)

MarshalToolResultEvent serialises any of the nine ToolResultEvent variants. Symmetric with MarshalToolCallEvent.

func McpNamespace

func McpNamespace(server string) string

McpNamespace is the namespace of a server's tools: `mcp__<server>` with `-` replaced by `_`, like the tool names.

Ports packages/coding-agent/src/core/mcp-servers.ts (mcpNamespace).

func ModelInfo

func ModelInfo(model *ai.Model) map[string]any

ModelInfo projects one composed model into the complete extension-facing Pi Model shape.

func NodeTimerDelay

func NodeTimerDelay(ms float64) time.Duration

NodeTimerDelay is the delay Node gives setTimeout(fn, ms): it truncates a fractional value and runs a delay outside [1, 2^31-1], or NaN, after one millisecond.

func OwnsSignal

func OwnsSignal(ctx context.Context) bool

OwnsSignal reports whether ctx belongs to a nested call that runs with the signal its caller passed in options.signal. Other tool calls run with the run's signal.

func ProviderStreamSimpleSelected

func ProviderStreamSimpleSelected(ctx context.Context) bool

func ResolveBeforeAgentStartSelectedTools

func ResolveBeforeAgentStartSelectedTools(ctx context.Context, before []string) ([]string, bool, error)

ResolveBeforeAgentStartSelectedTools compares the final selection before filtering non-string registry misses, as AgentSession.prompt does. Invalid lists reject prompt admission after every handler has had a chance to repair them.

func SetBeforeAgentStartSelectedTools

func SetBeforeAgentStartSelectedTools(ctx context.Context, raw json.RawMessage)

SetBeforeAgentStartSelectedTools retains the complete foreign value for later handlers. Only string entries can name registered Go tools; malformed selections are rejected after the handler chain, not swallowed as handler failures.

func ToolResultDetailsFor

func ToolResultDetailsFor(details any) any

ToolResultDetailsFor converts a tool result's Details to its SDK wire shape when the value implements ToolDetailsConverter; other details (custom-tool JSON, the already-SDK-shaped edit details, or nil) pass through unchanged.

func WithBeforeAgentStartOptions

func WithBeforeAgentStartOptions(ctx context.Context, options *BuildSystemPromptOptions) context.Context

WithBeforeAgentStartOptions attaches the shared per-run options to a handler dispatch. Hosts use this without changing the value-typed BeforeAgentStartEvent.SystemPromptOptions API.

func WithCallInitiation

func WithCallInitiation(ctx context.Context, mark func()) context.Context

WithCallInitiation returns ctx carrying mark, which the handler of a Promise-shaped call runs once its synchronous part has been applied.

func WithCallOrder

func WithCallOrder(ctx context.Context, order *CallOrder) context.Context

WithCallOrder returns ctx carrying the reservation of the call it is passed into.

func WithCommandContext

func WithCommandContext(ctx context.Context, cc *CommandContext) context.Context

WithCommandContext attaches a CommandContext to a context.Context.

func WithContext

func WithContext(parent context.Context, c *Context) context.Context

WithContext attaches a per-extension Context to a context.Context. Hosts call this once at event-dispatch time; the resulting context.Context is then threaded through to extension handlers.

Authors do not call WithContext directly.

func WithModelStreamRequest

func WithModelStreamRequest(ctx context.Context, request ModelStreamRequest) context.Context

WithModelStreamRequest binds transport callbacks to one model operation.

func WithOwnSignal

func WithOwnSignal(ctx context.Context) context.Context

WithOwnSignal marks ctx as the context of a nested call that runs with the signal its caller passed in options.signal.

upstream: runner.ts:979-981 (`{ ...options, signal: options.signal ?? signal }`)

func WithProviderStreamSimple

func WithProviderStreamSimple(ctx context.Context, simple bool) context.Context

WithProviderStreamSimple carries the selected Pi stream method through the host request.

func WithToolContext

func WithToolContext(parent context.Context, tc *ToolContext) context.Context

WithToolContext attaches a ToolContext to a context.Context. Hosts call it; authors do not.

Types

type AIContext

type AIContext = any

AIContext mirrors @earendil-works/pi-ai Context (the per-call provider context, distinct from pig's ExtensionContext).

type API

type API interface {

	// OnProjectTrust registers a handler for "project_trust".
	// upstream: types.ts:1125 (on("project_trust", ...))
	OnProjectTrust(handler func(ctx context.Context, evt ProjectTrustEvent) (ProjectTrustEventResult, error))

	// OnResourcesDiscover registers a handler for "resources_discover".
	// upstream: types.ts:1071
	OnResourcesDiscover(handler func(ctx context.Context, evt ResourcesDiscoverEvent) (ResourcesDiscoverResult, error))

	// OnSessionStart registers a handler for "session_start".
	// upstream: types.ts:1143
	OnSessionStart(handler func(ctx context.Context, evt SessionStartEvent) error)

	// OnSessionInfoChanged registers a handler for "session_info_changed"
	// (upstream types.ts SessionInfoChangedEvent; adopted upstream in 0.80.3).
	OnSessionInfoChanged(handler func(ctx context.Context, evt SessionInfoChangedEvent) error)

	// OnMcpServersChange registers a handler for "mcp_servers_change", fired when
	// an extension registers or unregisters an MCP server after the extensions
	// are bound. Handling it marks an extension as the one that connects
	// registered servers.
	// upstream: types.ts:1562 (on("mcp_servers_change", ...))
	OnMcpServersChange(handler func(ctx context.Context, evt McpServersChangeEvent) error)

	// OnSessionBeforeSwitch registers a handler for "session_before_switch".
	// upstream: types.ts:1145
	OnSessionBeforeSwitch(handler func(ctx context.Context, evt SessionBeforeSwitchEvent) (SessionBeforeSwitchResult, error))

	// OnSessionBeforeFork registers a handler for "session_before_fork".
	// upstream: types.ts:1077
	OnSessionBeforeFork(handler func(ctx context.Context, evt SessionBeforeForkEvent) (SessionBeforeForkResult, error))

	// OnSessionBeforeCompact registers a handler for "session_before_compact".
	// upstream: types.ts:1078
	OnSessionBeforeCompact(handler func(ctx context.Context, evt SessionBeforeCompactEvent) (SessionBeforeCompactResult, error))

	// OnSessionCompact registers a handler for "session_compact".
	// upstream: types.ts:1082
	OnSessionCompact(handler func(ctx context.Context, evt SessionCompactEvent) error)

	// OnSessionCompactFailed registers a handler for "session_compact_failed",
	// fired after manual or automatic compaction fails or is aborted.
	// upstream: types.ts:1374
	OnSessionCompactFailed(handler func(ctx context.Context, evt SessionCompactFailedEvent) error)

	// OnSessionShutdown registers a handler for "session_shutdown".
	// upstream: types.ts:1083
	OnSessionShutdown(handler func(ctx context.Context, evt SessionShutdownEvent) error)

	// OnSessionBeforeTree registers a handler for "session_before_tree".
	// upstream: types.ts:1084
	OnSessionBeforeTree(handler func(ctx context.Context, evt SessionBeforeTreeEvent) (SessionBeforeTreeResult, error))

	// OnSessionTree registers a handler for "session_tree".
	// upstream: types.ts:1085
	OnSessionTree(handler func(ctx context.Context, evt SessionTreeEvent) error)

	// OnContext registers a handler for "context".
	// upstream: types.ts:1086
	OnContext(handler func(ctx context.Context, evt ContextEvent) (ContextEventResult, error))

	// OnContextWithSystem registers a handler for "context_with_system".
	// upstream: types.ts ExtensionAPI.on("context_with_system")
	OnContextWithSystem(handler func(ctx context.Context, evt ContextWithSystemEvent) (ContextEventResult, error))

	// OnBeforeProviderRequest registers a handler for "before_provider_request".
	// upstream: types.ts:1087
	OnBeforeProviderRequest(handler func(ctx context.Context, evt BeforeProviderRequestEvent) (BeforeProviderRequestEventResult, error))

	// OnAfterProviderResponse registers a handler for "after_provider_response".
	// upstream: types.ts:1091
	OnAfterProviderResponse(handler func(ctx context.Context, evt AfterProviderResponseEvent) error)

	// OnBeforeProviderHeaders registers a handler for "before_provider_headers".
	// Handlers mutate evt.Headers in place before the request is sent.
	// upstream: types.ts:1199
	OnBeforeProviderHeaders(handler func(ctx context.Context, evt BeforeProviderHeadersEvent) error)

	// OnProviderStreamEvent registers a handler for "provider_stream_event",
	// fired for a parsed provider stream event before it is normalized.
	// upstream: types.ts:1580 (on("provider_stream_event", ...))
	OnProviderStreamEvent(handler func(ctx context.Context, evt ProviderStreamEvent) error)

	// OnBeforeAgentStart registers a handler for "before_agent_start".
	// upstream: types.ts:1092
	OnBeforeAgentStart(handler func(ctx context.Context, evt BeforeAgentStartEvent) (BeforeAgentStartEventResult, error))

	// OnAgentStart registers a handler for "agent_start".
	// upstream: types.ts:1093
	OnAgentStart(handler func(ctx context.Context, evt AgentStartEvent) error)

	// OnAgentEnd registers a handler for "agent_end".
	// upstream: types.ts:1399
	OnAgentEnd(handler func(ctx context.Context, evt AgentEndEvent) error)

	// OnAgentBeforeSettle registers an awaited final-settlement boundary handler.
	// Handlers may propose durable entries and request one runnable continuation.
	// upstream: types.ts:1401
	OnAgentBeforeSettle(handler func(ctx context.Context, evt *AgentBeforeSettleEvent) (AgentBeforeSettleEventResult, error))

	// OnAgentSettled registers a handler for "agent_settled", fired after an
	// agent run has fully settled (no retry, compaction, or queued continuation).
	// upstream: types.ts:1204
	OnAgentSettled(handler func(ctx context.Context, evt AgentSettledEvent) error)

	// OnUiPromptStart registers a handler for "ui_prompt_start", fired
	// without awaiting handlers when the outermost blocking ctx.ui prompt
	// (select, confirm, input, editor, custom) begins.
	// upstream: types.ts:1404
	OnUiPromptStart(handler func(ctx context.Context, evt UIPromptStartEvent) error)

	// OnUiPromptEnd registers a handler for "ui_prompt_end", fired without
	// awaiting handlers when the outermost blocking ctx.ui prompt settles.
	// upstream: types.ts:1405
	OnUiPromptEnd(handler func(ctx context.Context, evt UIPromptEndEvent) error)

	// OnTurnStart registers a handler for "turn_start".
	// upstream: types.ts:1095
	OnTurnStart(handler func(ctx context.Context, evt TurnStartEvent) error)

	// OnTurnEnd registers a handler for "turn_end".
	// upstream: types.ts:1096
	OnTurnEnd(handler func(ctx context.Context, evt TurnEndEvent) error)

	// OnMessageStart registers a handler for "message_start".
	// upstream: types.ts:1097
	OnMessageStart(handler func(ctx context.Context, evt MessageStartEvent) error)

	// OnMessageUpdate registers a handler for "message_update".
	// upstream: types.ts:1098
	OnMessageUpdate(handler func(ctx context.Context, evt MessageUpdateEvent) error)

	// OnMessageEnd registers a handler for "message_end".
	// upstream: types.ts:1099
	OnMessageEnd(handler func(ctx context.Context, evt MessageEndEvent) (MessageEndEventResult, error))

	// OnToolExecutionStart registers a handler for "tool_execution_start".
	// upstream: types.ts:1100
	OnToolExecutionStart(handler func(ctx context.Context, evt ToolExecutionStartEvent) error)

	// OnToolExecutionUpdate registers a handler for "tool_execution_update".
	// upstream: types.ts:1101
	OnToolExecutionUpdate(handler func(ctx context.Context, evt ToolExecutionUpdateEvent) error)

	// OnToolExecutionEnd registers a handler for "tool_execution_end".
	// upstream: types.ts:1102
	OnToolExecutionEnd(handler func(ctx context.Context, evt ToolExecutionEndEvent) error)

	// OnModelSelect registers a handler for "model_select".
	// upstream: types.ts:1103
	OnModelSelect(handler func(ctx context.Context, evt ModelSelectEvent) error)

	// OnThinkingLevelSelect registers a handler for "thinking_level_select".
	// upstream: types.ts:1122 (added in v0.71.0).
	OnThinkingLevelSelect(handler func(ctx context.Context, evt ThinkingLevelSelectEvent) error)

	// OnToolCall registers a handler for "tool_call". The event is the union
	// [ToolCallEvent]. Type-switch on its concrete variant.
	// upstream: types.ts:1104
	OnToolCall(handler func(ctx context.Context, evt ToolCallEvent) (ToolCallEventResult, error))

	// OnToolResult registers a handler for "tool_result". The event is the
	// union [ToolResultEvent].
	// upstream: types.ts:1105
	OnToolResult(handler func(ctx context.Context, evt ToolResultEvent) (ToolResultEventResult, error))

	// OnUserBash registers a handler for "user_bash".
	// upstream: types.ts:1106
	OnUserBash(handler func(ctx context.Context, evt UserBashEvent) (UserBashEventResult, error))

	// OnInput registers a handler for "input".
	// upstream: types.ts:1107
	OnInput(handler func(ctx context.Context, evt InputEvent) (InputEventResult, error))

	// RegisterTool registers a tool that the LLM can call.
	// upstream: types.ts:1114 (registerTool)
	RegisterTool(tool ToolDefinition)

	// RegisterCommand registers a custom command. Mirrors upstream's
	// `registerCommand(name, options: Omit<RegisteredCommand, "name" | "sourceInfo">)`.
	// upstream: types.ts:1123
	RegisterCommand(name string, options CommandOptions)

	// RegisterShortcut registers a keyboard shortcut.
	// upstream: types.ts:1126
	RegisterShortcut(shortcut KeyID, options ShortcutOptions)

	// RegisterFlag registers a CLI flag.
	// upstream: types.ts:1135
	RegisterFlag(name string, options FlagOptions)

	// GetFlag returns the value of a registered CLI flag. Upstream returns
	// `boolean | string | undefined`; Go returns `any` (nil when unset).
	// upstream: types.ts:1145
	GetFlag(name string) any

	// RegisterMessageRenderer registers a custom renderer for a CustomMessageEntry.
	// upstream: types.ts:1152
	RegisterMessageRenderer(customType string, renderer MessageRenderer)

	// RegisterEntryRenderer registers a custom renderer for a CustomEntry. Custom
	// entries do not participate in LLM context.
	// upstream: types.ts:1266
	RegisterEntryRenderer(customType string, renderer EntryRenderer)

	// RegisterToolRenderer chooses how tool calls are drawn. Resolvers run in
	// extension load order.
	// upstream: types.ts registerToolRenderer
	RegisterToolRenderer(resolver ToolRendererResolver)

	// RegisterMarkdownTransformer registers a display-only Markdown transform.
	// upstream: types.ts:1287
	RegisterMarkdownTransformer(transformer MarkdownTransformer)

	// SendMessage sends a custom message to the session. Pass nil options for defaults.
	// upstream: types.ts:1159
	SendMessage(message SendMessagePayload, options *SendMessageOptions)

	// SendUserMessage sends a user message to the agent. Always triggers a turn.
	// content is `string` or `[]any` carrying TextContent / ImageContent values
	// (matches upstream's `string | (TextContent | ImageContent)[]`).
	// upstream: types.ts:1168
	SendUserMessage(content any, options *SendUserMessageOptions)

	// AppendEntry appends a custom entry to the session for state persistence
	// (not sent to LLM).
	// upstream: types.ts:1174
	AppendEntry(customType string, data any)

	// SetSessionName sets the session display name (shown in session selector).
	// upstream: types.ts:1181
	SetSessionName(name string)

	// GetSessionName returns the current session name. Upstream returns
	// `string | undefined`; Go returns the empty string when unset.
	// upstream: types.ts:1184
	GetSessionName() string

	// SetLabel sets or clears a label on an entry. Pass empty string to clear.
	// upstream: types.ts:1187
	SetLabel(entryID string, label string)

	// Exec executes a shell command. Pass nil options for defaults. Upstream
	// returns `Promise<ExecResult>`; Go returns `(ExecResult, error)`.
	// Cancellation flows through `options.Signal` (which is a context.Context
	// after the D3 migration; see docs/parity/DIVERGENCES.md).
	// upstream: types.ts:1190
	Exec(command string, args []string, options *ExecOptions) (ExecResult, error)

	// GetActiveTools returns the names of the active tools, which are the tools
	// declared to the model.
	// upstream: types.ts:1193
	GetActiveTools() []string

	// GetAllTools returns all configured tools with parameter schema, prompt
	// guidelines, exposure, and source metadata.
	// upstream: types.ts:1196
	GetAllTools() []ToolInfo

	// GetSettings returns a copy of the effective settings (global and project
	// settings merged, with overrides).
	// upstream: types.ts:1708 (getSettings)
	GetSettings() Settings

	// SetActiveTools sets the active tools by name. Unknown and `hidden` tools
	// are ignored. Tools with `codemode` or `deferred` exposure stay callable
	// from codemode scripts whether active or not.
	// upstream: types.ts:1199
	SetActiveTools(toolNames []string)

	// GetCommands returns the available slash commands in the current session.
	// upstream: types.ts:1202
	GetCommands() []SlashCommandInfo

	// SetModel sets the current model. Upstream returns
	// `Promise<boolean>` (false when no API key available); Go returns
	// `(bool, error)`: error is non-nil only on host-side failures.
	// upstream: types.ts:1209
	SetModel(model Model) (bool, error)

	// GetThinkingLevel returns the current thinking level.
	// upstream: types.ts:1212
	GetThinkingLevel() ThinkingLevel

	// SetThinkingLevel sets the thinking level (clamped to model capabilities).
	// upstream: types.ts:1215
	SetThinkingLevel(level ThinkingLevel)

	// RegisterProvider registers or overrides a model provider. See [ProviderConfig]
	// for the field-level semantics (upstream JSDoc preserved).
	// upstream: types.ts:1264
	RegisterProvider(name string, config ProviderConfig)

	// UnregisterProvider unregisters a previously registered provider. Has
	// no effect if the provider is not currently registered.
	// upstream: types.ts:1280
	UnregisterProvider(name string)

	// RegisterMcpServer registers an MCP server for this session, with the same
	// config as an `mcpServers` entry in `mcp.json`. The server connects next to
	// the configured servers: on session_start when registered during extension
	// load, right away when registered later. Registering a name again replaces
	// the extension's earlier registration.
	//
	// The registration is not saved; register again on every load. A server of
	// the same name in `mcp.json` takes precedence. It returns an error for
	// invalid configs and for names another extension registered (upstream
	// throws). When no loaded extension handles MCP servers (for example because
	// another MCP extension replaced the built-in one), the registration is
	// reported as an extension error.
	// upstream: types.ts:1833 (registerMcpServer)
	RegisterMcpServer(name string, config McpServerConfig) error

	// UnregisterMcpServer removes an MCP server this extension registered and
	// closes its connection.
	// upstream: types.ts:1836 (unregisterMcpServer)
	UnregisterMcpServer(name string)

	// GetMcpServers returns every MCP server registered by extensions, for
	// extensions that connect MCP servers.
	// upstream: types.ts:1839 (getMcpServers)
	GetMcpServers() []RegisteredMcpServer

	// RegisterVirtualModel registers a virtual model: a selectable catalog entry
	// that routes each request to a physical model. The selection (`ctx.model`,
	// `model_change` entries) names the virtual model; assistant messages record
	// the physical model and thinking level the router picked.
	//
	// The provider may be any provider id, including one with physical models,
	// and may list several virtual models. Registering the same provider and id
	// again replaces the virtual model. See docs/virtual-models.md.
	// upstream: types.ts:1852 (registerVirtualModel)
	RegisterVirtualModel(model ExtensionVirtualModel)

	// UnregisterVirtualModel removes a virtual model registered with
	// [API.RegisterVirtualModel].
	// upstream: types.ts:1855 (unregisterVirtualModel)
	UnregisterVirtualModel(provider, id string)

	// Events returns the shared event bus for extension communication.
	//
	// pig translation rule (interface property → method): upstream exposes
	// this as the property `events: EventBus`. Go interfaces cannot have
	// fields, so the API surfaces a method that returns the host's single
	// shared instance. See docs/parity/DIVERGENCES.md "TS→Go translation rituals".
	// upstream: types.ts:1283
	Events() EventBus
}

API is the surface passed to extension factory functions. It mirrors upstream's `ExtensionAPI` interface 1:1: every event registrable via upstream's `pi.on(event, handler)` overload has a typed `On<Event>` method here, every other method on `ExtensionAPI` has a Go counterpart (camelCase → PascalCase), and the upstream `events: EventBus` property surfaces as the API.Events method.

Method order matches upstream declaration order so a side-by-side review against types.ts is mechanical. Every method's doc comment cites its upstream line in `types.ts`.

Go mapping:

  • Events is a method because Go interfaces cannot contain fields.
  • Handlers receive context.Context and return errors.

upstream: types.ts:1066–1296

type AbortSignal deprecated

type AbortSignal = context.Context

AbortSignal was the upstream cancellation primitive (DOM AbortSignal). Pig uses context.Context for cancellation (see docs/parity/DIVERGENCES.md D3). This deprecated alias preserves source compatibility while giving callers the real cancellation contract instead of an untyped value.

Deprecated: use context.Context.

type AfterProviderResponseEvent

type AfterProviderResponseEvent struct {
	Type    string            `json:"type"`
	Status  int               `json:"status"`
	Headers map[string]string `json:"headers"`
}

AfterProviderResponseEvent: upstream types.ts AfterProviderResponseEvent.

type AgentActivityOutcome

type AgentActivityOutcome string

AgentActivityOutcome mirrors upstream's completed/aborted/error boundary state.

const (
	AgentActivityCompleted AgentActivityOutcome = "completed"
	AgentActivityAborted   AgentActivityOutcome = "aborted"
	AgentActivityError     AgentActivityOutcome = "error"
)

type AgentBeforeSettleEvent

type AgentBeforeSettleEvent struct {
	Type string `json:"type"`
	BoundaryState
}

AgentBeforeSettleEvent: upstream types.ts AgentBeforeSettleEvent. It is awaited after retry, recovery, compaction, and queued continuations stop.

type AgentBeforeSettleEventResult

type AgentBeforeSettleEventResult = BoundaryResult

AgentBeforeSettleEventResult mirrors upstream's BoundaryResult alias.

type AgentEndEvent

type AgentEndEvent struct {
	Type     string         `json:"type"`
	Messages []AgentMessage `json:"messages"`
}

AgentEndEvent: upstream types.ts AgentEndEvent.

type AgentMessage

type AgentMessage = any

AgentMessage mirrors @earendil-works/pi-agent-core AgentMessage.

type AgentSettledEvent

type AgentSettledEvent struct {
	Type string `json:"type"`
}

AgentSettledEvent: upstream types.ts AgentSettledEvent. Fired after an agent run has fully settled and no automatic retry, compaction, or queued continuation will run.

type AgentStartEvent

type AgentStartEvent struct {
	Type string `json:"type"`
}

AgentStartEvent: upstream types.ts AgentStartEvent.

type AgentTool

type AgentTool struct {
	Name                string            `json:"name"`
	Label               string            `json:"label"`
	Description         string            `json:"description"`
	Parameters          json.RawMessage   `json:"parameters"`
	OutputSchema        json.RawMessage   `json:"outputSchema,omitempty"`
	ConstrainedSampling json.RawMessage   `json:"constrainedSampling,omitempty"`
	ExecutionMode       ToolExecutionMode `json:"executionMode,omitempty"`
}

AgentTool is the read-only view of a tool that a tool call sees through ToolContext.Tools and ToolLoadout. Go mechanic (not a divergence): upstream's AgentTool carries `execute`. A tool runs only through ToolContext.ExecuteTool, so the view holds the declaration fields and no function.

upstream: .upstream/v0.99.1/packages/agent/src/types.ts (AgentTool)

type AgentToolCall

type AgentToolCall = ai.ToolCall

AgentToolCall mirrors pi-agent-core AgentToolCall: the tool call block a tool call runs for.

type AgentToolCallOutcome

type AgentToolCallOutcome struct {
	ToolCall AgentToolCall   `json:"toolCall"`
	Result   AgentToolResult `json:"result"`
	IsError  bool            `json:"isError"`
}

AgentToolCallOutcome mirrors pi-agent-core AgentToolCallOutcome: the final outcome of a tool call after the hooks ran.

upstream: .upstream/v0.99.1/packages/agent/src/types.ts (AgentToolCallOutcome)

type AgentToolResult

type AgentToolResult = any

AgentToolResult mirrors @earendil-works/pi-agent-core AgentToolResult<TDetails>.

type AgentToolUpdateCallback

type AgentToolUpdateCallback = any

AgentToolUpdateCallback mirrors AgentToolUpdateCallback<TDetails>.

type ArgumentCompletionsFunc

type ArgumentCompletionsFunc = func(argumentPrefix string) ([]AutocompleteItem, error)

ArgumentCompletionsFunc mirrors upstream's getArgumentCompletions callback on RegisteredCommand. Returns a list of completion items, or nil to fall through to the default provider.

pig translation rule (Promise<T[] | null> → ([]T, error)): upstream returns `AutocompleteItem[] | null | Promise<AutocompleteItem[] | null>`. The Go signature returns the slice + error directly; if the host needs cancellation it wraps the call in a goroutine + ctx.Done() select: same shape upstream takes (the function has no signal/ctx parameter upstream either).

type AssistantMessageEvent

type AssistantMessageEvent = any

AssistantMessageEvent mirrors @earendil-works/pi-ai AssistantMessageEvent.

type AssistantMessageEventStream

type AssistantMessageEventStream = any

AssistantMessageEventStream mirrors AssistantMessageEventStream.

type AttributedResourcePath

type AttributedResourcePath struct {
	Path          string `json:"path"`
	ExtensionPath string `json:"extensionPath"`
}

AttributedResourcePath pairs a resource path with the extension that declared it. Used by EmitResourcesDiscover to surface where each skill/prompt/theme path came from.

upstream: anonymous type at runner.ts:944-947

skillPaths: Array<{ path: string; extensionPath: string }>;

pig names this type because Go's anonymous-type composition is less ergonomic than TS's; same wire shape.

type AutocompleteCompletion

type AutocompleteCompletion struct {
	Lines      []string `json:"lines"`
	CursorLine int      `json:"cursorLine"`
	CursorCol  int      `json:"cursorCol"`
}

AutocompleteCompletion carries the complete replacement and UTF-16 cursor position returned by a provider.

type AutocompleteItem

type AutocompleteItem struct {
	Value       string `json:"value"`
	Label       string `json:"label,omitempty"`
	Description string `json:"description,omitempty"`
}

AutocompleteItem mirrors @earendil-works/pi-tui AutocompleteItem.

Concrete shape so subprocess autocomplete responses can deserialise into a typed value the host can pass to the TUI editor without an extra translation step.

type AutocompleteProvider

type AutocompleteProvider struct {
	TriggerCharacters           []string
	GetSuggestions              func(context.Context, []string, int, int, bool) (*AutocompleteSuggestions, error)
	ApplyCompletion             func(context.Context, []string, int, int, AutocompleteItem, string) (AutocompleteCompletion, error)
	ShouldTriggerFileCompletion func(context.Context, []string, int, int) (bool, error)
}

AutocompleteProvider mirrors @earendil-works/pi-tui AutocompleteProvider.

func SetupAutocompleteProvider

func SetupAutocompleteProvider(ctx context.Context, base *AutocompleteProvider, factories []AutocompleteProviderFactory) (*AutocompleteProvider, error)

SetupAutocompleteProvider folds retained factories over a fresh base and merges their trigger characters in first-seen order.

type AutocompleteProviderFactory

type AutocompleteProviderFactory func(context.Context, *AutocompleteProvider) (*AutocompleteProvider, error)

AutocompleteProviderFactory mirrors upstream AutocompleteProviderFactory.

type AutocompleteSuggestions

type AutocompleteSuggestions struct {
	Items  []AutocompleteItem `json:"items"`
	Prefix string             `json:"prefix"`
}

AutocompleteSuggestions mirrors @earendil-works/pi-tui AutocompleteSuggestions.

type BashOperations

type BashOperations interface {
	Exec(ctx context.Context, command, cwd string, options BashOperationsExecOptions) (BashOperationsResult, error)
}

BashOperations mirrors upstream BashOperations (core/tools/bash.ts): pluggable command execution, local by default and remote (for example SSH) when an extension supplies it, such as from a user_bash handler's { operations } result. Exec returns an error whose message is "aborted" when ctx was cancelled and "timeout:<seconds>" when the timeout fired, as upstream's callers match on those messages.

type BashOperationsExecOptions

type BashOperationsExecOptions struct {
	// OnData receives raw output bytes (stdout and stderr) as they arrive,
	// from one goroutine at a time. The callee may keep the slice.
	OnData func(data []byte)
	// Timeout is the requested timeout in seconds; nil means none.
	Timeout *float64
	// Env replaces the inherited environment when non-nil.
	Env []string
}

BashOperationsExecOptions mirrors the options upstream BashOperations.exec receives (core/tools/bash.ts). Cancellation is the context.

type BashOperationsResult

type BashOperationsResult struct {
	ExitCode *int
}

BashOperationsResult mirrors upstream { exitCode: number | null }: a signal termination reports 128 + the signal number, and nil is a failed command.

type BashResult

type BashResult = any

BashResult mirrors core/bash-executor.BashResult. A native result must contain exitCode; its nil value represents undefined, not JSON null. A nil optional fullOutputPath is also undefined. Pre-encoded JSON retains its own null values.

type BashToolCallEvent

type BashToolCallEvent struct {
	ToolCallEventBase
	ToolName string        `json:"toolName"` // "bash"
	Input    BashToolInput `json:"input"`
}

BashToolCallEvent: upstream types.ts BashToolCallEvent.

type BashToolDetails

type BashToolDetails struct {
	Truncation     *ToolTruncation `json:"truncation,omitempty"`
	FullOutputPath string          `json:"fullOutputPath,omitempty"`
}

BashToolDetails mirrors upstream bash.ts:31. Attached only when output was truncated.

type BashToolInput

type BashToolInput = any

type BashToolResultEvent

type BashToolResultEvent struct {
	ToolResultEventBase
	ToolName string           `json:"toolName"` // "bash"
	Details  *BashToolDetails `json:"details,omitempty"`
}

BashToolResultEvent: upstream types.ts BashToolResultEvent.

func (BashToolResultEvent) MarshalJSON

func (e BashToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type BeforeAgentStartCombinedResult

type BeforeAgentStartCombinedResult struct {
	// Messages is the slice of custom messages collected from every
	// handler that returned `result.message`. Empty when no handler
	// pushed a message.
	Messages []CustomMessageRef `json:"messages,omitempty"`

	// SystemPrompt is the final mutated system prompt, non-nil only if at
	// least one handler set `result.systemPrompt` (an empty prompt included).
	SystemPrompt *string `json:"systemPrompt,omitempty"`

	// SystemPromptOptions is the per-run options object the handlers shared. It is set when the incoming options or a handler supplied sections, or a handler edited selectedTools. It does not alias the caller's base options.
	SystemPromptOptions *BuildSystemPromptOptions `json:"systemPromptOptions,omitempty"`

	// SelectedToolsEdited retains an explicit edit even when filtering non-string registry misses produces the original list.
	SelectedToolsEdited bool `json:"-"`
}

BeforeAgentStartCombinedResult is the aggregated result from all before_agent_start handlers. Returned by the runner's EmitBeforeAgentStart.

upstream: runner.ts:103-107 (interface BeforeAgentStartCombinedResult)

interface BeforeAgentStartCombinedResult {
	messages?: NonNullable<BeforeAgentStartEventResult["message"]>[];
	systemPrompt?: string;
}

Upstream declares this type as `interface` private to runner.ts; pig exports it because Go callers need to type-assert on it after EmitBeforeAgentStart returns. Field semantics match upstream verbatim.

type BeforeAgentStartEvent

type BeforeAgentStartEvent struct {
	Type         string         `json:"type"`
	Prompt       string         `json:"prompt"`
	Images       []ImageContent `json:"images,omitempty"`
	SystemPrompt string         `json:"systemPrompt"`
	// SystemPromptOptions is the per-handler value view of the run's options. Use BeforeAgentStartOptions with the dispatch context to replace collections on the shared per-run object.
	SystemPromptOptions BuildSystemPromptOptions `json:"systemPromptOptions"`
}

BeforeAgentStartEvent: upstream types.ts BeforeAgentStartEvent.

type BeforeAgentStartEventResult

type BeforeAgentStartEventResult struct {
	Message *CustomMessageRef `json:"message,omitempty"`
	// SystemPrompt replaces the run's system prompt when set, including when
	// it is empty; nil leaves it unchanged (upstream `systemPrompt?: string`).
	SystemPrompt *string `json:"systemPrompt,omitempty"`
}

BeforeAgentStartEventResult: upstream types.ts BeforeAgentStartEventResult.

type BeforeProviderHeadersEvent

type BeforeProviderHeadersEvent struct {
	Type    string          `json:"type"`
	Headers ProviderHeaders `json:"headers"`
}

BeforeProviderHeadersEvent: upstream types.ts BeforeProviderHeadersEvent. Handlers mutate Headers in place before the request is sent.

type BeforeProviderRequestEvent

type BeforeProviderRequestEvent struct {
	Type    string `json:"type"`
	Payload any    `json:"payload"`
}

BeforeProviderRequestEvent: upstream types.ts BeforeProviderRequestEvent.

type BeforeProviderRequestEventResult

type BeforeProviderRequestEventResult = any

BeforeProviderRequestEventResult: upstream type alias for `unknown`.

type BoundaryBaseEvent

type BoundaryBaseEvent interface {
	// contains filtered or unexported methods
}

BoundaryBaseEvent is the closed input union of actionable turn_end and agent_before_settle events. The runner supplies each handler's proposal and preview.

type BoundaryContextPreview

type BoundaryContextPreview struct {
	ContextEntries  []ProjectedSessionEntry `json:"contextEntries"`
	ContextMessages []AgentMessage          `json:"contextMessages"`
	LLMMessages     []any                   `json:"llmMessages"`
	PendingMessages []AgentMessage          `json:"pendingMessages"`
	CanContinue     bool                    `json:"canContinue"`
}

BoundaryContextPreview is the recomputed session/model context after the currently proposed entries.

type BoundaryResult

type BoundaryResult struct {
	Entries  *[]SessionBoundaryDraft `json:"entries,omitempty"`
	Continue *bool                   `json:"continue,omitempty"`
}

BoundaryResult chains proposed entries and explicit continuation. Pointer fields preserve omitted versus explicit empty/false results.

type BoundaryState

type BoundaryState struct {
	Entries  []SessionBoundaryDraft `json:"entries"`
	Continue bool                   `json:"continue"`
	Context  BoundaryContextPreview `json:"context"`
	Outcome  AgentActivityOutcome   `json:"outcome"`
}

BoundaryState is shared by turn_end and agent_before_settle upstream.

type BranchSummaryEntry

type BranchSummaryEntry = any

BranchSummaryEntry mirrors core/session-manager BranchSummaryEntry.

type BuildSystemPromptOptions

type BuildSystemPromptOptions struct {
	// CustomPrompt is the user-supplied prompt that replaces the default
	// (from --system-prompt, SYSTEM.md, or custom templates).
	CustomPrompt string `json:"customPrompt,omitempty"`
	// CustomPromptSet preserves a present empty customPrompt without changing the existing string field. A nonempty CustomPrompt is always present.
	CustomPromptSet bool `json:"-"`
	// ForceSystemPrompt is the exact full prompt a before_agent_start handler returned as systemPrompt; later handlers observe it (runner.ts:1346-1348). Nil is Pi's undefined; an empty string is a forced empty prompt.
	ForceSystemPrompt *string `json:"forceSystemPrompt,omitempty"`
	// SelectedTools is the list of tool names included in the prompt.
	// Defaults upstream to [read, bash, edit, write].
	SelectedTools []string `json:"selectedTools,omitzero"`
	// ToolSnippets maps tool name → one-line description used in the
	// "Available tools" section.
	ToolSnippets map[string]string `json:"toolSnippets,omitzero"`
	// ToolGuidelines contributes rules only while its tool is active.
	ToolGuidelines map[string][]string `json:"toolGuidelines,omitzero"`
	// PromptGuidelines holds bullet lines appended to the default
	// guidelines section.
	PromptGuidelines []string `json:"promptGuidelines,omitzero"`
	// AppendSystemPrompt is the joined text appended after the main
	// prompt body (from --append-system-prompt flags / settings).
	AppendSystemPrompt string `json:"appendSystemPrompt"`
	// Sections holds additional XML-wrapped sections in authored order. Event handlers mutate the per-run collection, not the Session's base options.
	Sections *ai.OrderedSections `json:"sections,omitempty"`
	// Cwd is the working directory shown to the LLM.
	Cwd string `json:"cwd"`
	// ContextFiles are pre-loaded AGENTS.md / CLAUDE.md files in the
	// order they appear in the prompt.
	ContextFiles []SystemPromptContextFile `json:"contextFiles,omitzero"`
	// Skills lists skills surfaced in the prompt's skills section.
	Skills []SystemPromptSkill `json:"skills,omitzero"`
}

BuildSystemPromptOptions mirrors upstream `core/system-prompt.ts::BuildSystemPromptOptions`.

Extensions receive this struct on every `before_agent_start` event via `event.systemPromptOptions` so they can inspect what pi has already assembled (custom prompt, tools, append text, context files, skills) without re-discovering resources.

Extensions receive upstream's NormalizedBuildSystemPromptOptions (system-prompt.ts:37-46): every collection is present, so an empty selectedTools is `[]`, not an omitted key. MarshalJSON writes that shape; the struct tags describe only decoding.

upstream: packages/coding-agent/src/core/system-prompt.ts:9-69

func BeforeAgentStartOptions

func BeforeAgentStartOptions(ctx context.Context) *BuildSystemPromptOptions

BeforeAgentStartOptions returns the shared per-run options during before_agent_start, or nil outside that dispatch. Assign collection replacements through this pointer; edits remain visible to later handlers even when the handler returns an error. The pointer never aliases the Session's base options.

func NormalizeBuildSystemPromptOptions

func NormalizeBuildSystemPromptOptions(input BuildSystemPromptOptions) BuildSystemPromptOptions

NormalizeBuildSystemPromptOptions supplies the collection-complete shape exposed to extensions while copying the per-run mutable collections.

Ports packages/coding-agent/src/core/system-prompt.ts

func (BuildSystemPromptOptions) MarshalJSON

func (o BuildSystemPromptOptions) MarshalJSON() ([]byte, error)

MarshalJSON writes the collection-complete shape that upstream's normalizeBuildSystemPromptOptions (system-prompt.ts:48-64) exposes to extensions: empty collections stay present, while customPrompt is omitted when it is undefined.

func (*BuildSystemPromptOptions) UnmarshalJSON

func (o *BuildSystemPromptOptions) UnmarshalJSON(data []byte) error

UnmarshalJSON retains customPrompt presence for command and event option round trips.

type CacheWarmingAction

type CacheWarmingAction string

CacheWarmingAction selects whether the scheduled prompt-cache refresh runs.

const (
	CacheWarmingActionWarm CacheWarmingAction = "warm"
	CacheWarmingActionStop CacheWarmingAction = "stop"
)

type CacheWarmingDecisionEvent

type CacheWarmingDecisionEvent struct {
	Type                    string             `json:"type"`
	WarmCost                float64            `json:"warmCost"`
	MissCost                float64            `json:"missCost"`
	ContinuationProbability float64            `json:"continuationProbability"`
	Action                  CacheWarmingAction `json:"action"`
}

CacheWarmingDecisionEvent carries the economics and default action before a cache refresh.

type CacheWarmingDecisionEventResult

type CacheWarmingDecisionEventResult struct {
	Action *CacheWarmingAction `json:"action,omitempty"`
}

CacheWarmingDecisionEventResult overrides the decision when Action is present.

type CallLane

type CallLane struct {
	// contains filtered or unexported fields
}

CallLane keeps the calls of one destination in call order up to the point their requests are issued. Pi runs each call's synchronous prefix in call order, so `Promise.all([tools.a(), tools.b()])` issues `a` first; Go's goroutines give no such order, so the host reserves each call's place in call order (ToolDefinition.ReserveCallOrder) and a call issues its request only after every earlier reservation released. The zero value is ready to use.

func (*CallLane) Reserve

func (l *CallLane) Reserve() *CallOrder

Reserve takes the next place in the lane. It must run in call order, before any of the calls runs.

type CallOrder

type CallOrder struct {
	Wait    func()
	Release func()
}

CallOrder is a reserved place in a tool's call order. Wait returns when every earlier reservation was released; Release, which is idempotent, hands the place on and must run however the call ends.

func CallOrderFromContext

func CallOrderFromContext(ctx context.Context) (*CallOrder, bool)

CallOrderFromContext returns the reservation the host made for this call, if any.

type CancelledResult

type CancelledResult struct {
	Cancelled bool `json:"cancelled"`
}

CancelledResult is the return type for session-mutation commands (newSession, fork, navigateTree, switchSession). Upstream returns `{ cancelled: boolean }`: Go uses a named struct for clarity.

upstream: types.ts (inline `Promise<{ cancelled: boolean }>` on each method)

type Capability

type Capability = string

Capability is a typed string for well-known extension capability names. Authors may use unknown strings; hosts only enforce the well-known set.

const (
	CapOnEvent           Capability = "onEvent" // umbrella for all on*() subscribers
	CapRegisterTool      Capability = "registerTool"
	CapRegisterCommand   Capability = "registerCommand"
	CapRegisterShortcut  Capability = "registerShortcut"
	CapRegisterFlag      Capability = "registerFlag"
	CapRegisterRenderer  Capability = "registerMessageRenderer"
	CapRegisterProvider  Capability = "registerProvider"
	CapSendMessage       Capability = "sendMessage"
	CapSendUserMessage   Capability = "sendUserMessage"
	CapAppendEntry       Capability = "appendEntry"
	CapSessionMetadata   Capability = "sessionMetadata"
	CapExec              Capability = "exec"
	CapToolIntrospection Capability = "toolIntrospection"
	CapModelControl      Capability = "modelControl"
	CapThinkingLevel     Capability = "thinkingLevel"
	CapEvents            Capability = "events" // EventBus pub/sub
)

Well-known capability names. These mirror the extension API surface groups.

type CommandActions

type CommandActions struct {
	// WaitForIdle blocks until the agent finishes streaming.
	WaitForIdle        func() error
	WaitForIdleContext func(context.Context) error

	// NewSession starts a new session.
	NewSession        func(opts *NewSessionOptions) (CancelledResult, error)
	NewSessionContext func(context.Context, *NewSessionOptions) (CancelledResult, error)

	// Fork creates a new branch from entryId.
	Fork        func(entryID string, opts *ForkOptions) (CancelledResult, error)
	ForkContext func(context.Context, string, *ForkOptions) (CancelledResult, error)

	// NavigateTree moves to a different point in the session tree.
	NavigateTree        func(targetID string, opts *NavigateTreeOptions) (CancelledResult, error)
	NavigateTreeContext func(context.Context, string, *NavigateTreeOptions) (CancelledResult, error)

	// SwitchSession switches to a different session file.
	SwitchSession        func(sessionPath string, opts *SwitchSessionOptions) (CancelledResult, error)
	SwitchSessionContext func(context.Context, string, *SwitchSessionOptions) (CancelledResult, error)

	// Reload reloads extensions, skills, prompts, themes.
	Reload        func() error
	ReloadContext func(context.Context) error
}

CommandActions is the host-side injection of command-specific callbacks. These are the extra surfaces available only in command handlers (via CommandContext), not in event handlers.

Mirrors upstream ExtensionCommandContextActions (types.ts:1484-1506). All fields are optional; nil functions produce safe no-ops.

upstream: types.ts:1484-1506

type CommandContext

type CommandContext struct {
	*Context
	// contains filtered or unexported fields
}

CommandContext extends Context with command-specific actions available only inside slash-command handlers. Mirrors upstream ExtensionCommandContext (types.ts:328-363).

Retrieve from a context.Context via CommandContextFromContext.

upstream: runner.ts:736-772 (createCommandContext)

func CommandContextFromContext

func CommandContextFromContext(ctx context.Context) *CommandContext

CommandContextFromContext retrieves the CommandContext attached by WithCommandContext. Returns nil if none is set.

func NewCommandContext

func NewCommandContext(base *Context, cmdActions CommandActions) *CommandContext

NewCommandContext constructs a CommandContext from the base context and command-specific actions. Called by the runner when dispatching a slash command registered by an extension. SendUserMessage is inherited from the base Context, which carries it for every dispatch.

upstream: runner.ts:736-772

func (*CommandContext) Fork

func (c *CommandContext) Fork(entryID string, opts *ForkOptions) (CancelledResult, error)

Fork creates a new branch from entryID.

func (*CommandContext) GetSystemPromptOptions

func (c *CommandContext) GetSystemPromptOptions() (*BuildSystemPromptOptions, error)

GetSystemPromptOptions returns the base inputs pi currently uses to build the system prompt (custom prompt, active tools, tool snippets, prompt guidelines, appended text, cwd, loaded context files, and skills). It reports the current base inputs only; it does not include per-turn before_agent_start chained changes, later context-event message mutations, or before_provider_request rewrites.

When no data source is wired, returns zero-value options carrying the runner cwd, matching upstream's `getSystemPromptOptions ?? (() => ({ cwd: this.cwd }))` default.

upstream: runner.ts:653-656 (createCommandContext getSystemPromptOptions), types.ts:339

func (*CommandContext) NavigateTree

func (c *CommandContext) NavigateTree(targetID string, opts *NavigateTreeOptions) (CancelledResult, error)

NavigateTree moves to a different point in the session tree.

func (*CommandContext) NewSession

func (c *CommandContext) NewSession(opts *NewSessionOptions) (CancelledResult, error)

NewSession starts a new session.

func (*CommandContext) Reload

func (c *CommandContext) Reload() error

Reload reloads extensions, skills, prompts, themes.

func (*CommandContext) SwitchSession

func (c *CommandContext) SwitchSession(sessionPath string, opts *SwitchSessionOptions) (CancelledResult, error)

SwitchSession switches to a different session file.

func (*CommandContext) WaitForIdle

func (c *CommandContext) WaitForIdle() error

WaitForIdle blocks until the agent finishes streaming.

type CommandHandler

type CommandHandler = func(ctx context.Context, args string) error

CommandHandler is invoked when an extension command is run. Mirrors upstream's RegisteredCommand.handler signature.

CommandHandler receives cancellation and per-extension values through the Go context. Use FromContext to access the extension context.

type CommandOptions

type CommandOptions struct {
	Description            string                  `json:"description,omitempty"`
	GetArgumentCompletions ArgumentCompletionsFunc `json:"-"`
	Handler                CommandHandler          `json:"-"`
}

CommandOptions is the registration payload for API.RegisterCommand : upstream's `Omit<RegisteredCommand, "name" | "sourceInfo">`.

type CompactOptions

type CompactOptions struct {
	CustomInstructions string                        `json:"customInstructions,omitempty"`
	OnComplete         func(result CompactionResult) `json:"-"`
	OnError            func(err error)               `json:"-"`
}

CompactOptions mirrors upstream `CompactOptions` (types.ts:284-288). Configures a compaction operation triggered via Context.Compact.

  • CustomInstructions: optional user-provided guidance for the summarization model.
  • OnComplete: callback invoked with the CompactionResult once the async compaction finishes. Nil disables the callback (fire-and- forget).
  • OnError: callback invoked when compaction fails. Nil routes the error to the runner's error listeners.

upstream: types.ts:284-288

type CompactionEntry

type CompactionEntry = any

CompactionEntry mirrors core/session-manager CompactionEntry.

type CompactionPreparation

type CompactionPreparation = any

CompactionPreparation mirrors core/compaction CompactionPreparation.

type CompactionResult

type CompactionResult = any

CompactionResult mirrors core/compaction CompactionResult.

type Component

type Component = any

Component mirrors @earendil-works/pi-tui Component. PiG transports rendered component state across the subprocess boundary, so the in-process value is opaque here.

type Context

type Context struct {
	// contains filtered or unexported fields
}

Context is the per-extension runtime context. Mirrors upstream's ExtensionContext (types.ts:ExtensionContext).

Authors retrieve the Context from a context.Context via FromContext. The host attaches it at event-dispatch time using WithContext.

Go carries cancellation and per-extension values through one context.Context. Authors retrieve the extension Context with FromContext.

Context exposes the runtime, UI, session, model, and cancellation surfaces backed by ContextActions. Optional actions use their documented zero-value behavior when the host does not bind them.

func FromContext

func FromContext(ctx context.Context) *Context

FromContext retrieves the per-extension Context that the host attached via WithContext. Returns nil if none was attached (e.g. a unit test that constructs handlers without a host).

Typical usage in an extension handler:

api.OnToolCall(func(ctx context.Context, event extension.ToolCallEvent) extension.ToolCallEventResult {
    extCtx := extension.FromContext(ctx)
    if extCtx != nil {
        cwd, _ := extCtx.CWD()
        // ... use cwd
    }
    return extension.ToolCallEventResult{}
})

func NewContext

func NewContext(cwd string, uiContext UIContext, assertActive func() error, actions ContextActions) *Context

NewContext constructs a Context with the given parameters. This is the constructor that hosts (Runner) use; extension authors never call this directly.

uiContext is the per-mode UI binding (matches upstream's `runner.uiContext` field at runner.ts:225). Pass NoopUIContext when no UI is available; nil is normalized to NoopUIContext so callers of Context.UI always receive a non-nil dispatchable.

assertActive is the runner's staleness guard; every getter/method on Context calls it first.

actions carries the optional injection callbacks that back Model/IsIdle/Shutdown/etc. Pass a zero-value `ContextActions{}` for the no-op defaults (matches upstream's bindCore-pre-bind state).

upstream: runner.ts:566-630 (createContext factory)

func (*Context) Abort

func (c *Context) Abort() error

Abort cancels the current agent operation. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: no-op (matches upstream's `() => {}` default at runner.ts:240).

upstream: runner.ts:602-605 (`abort: () => { ... }`)

func (*Context) CWD

func (c *Context) CWD() (string, error)

CWD returns the working directory captured at Runner construction. Returns an error if the runner has been invalidated.

upstream: runner.ts:581 (`get cwd()`)

func (*Context) Compact

func (c *Context) Compact(opts *CompactOptions) error

Compact triggers compaction without awaiting completion. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: no-op (matches upstream's `() => {}` default at runner.ts:234).

upstream: runner.ts:618-621 (`compact: (options) => { ... }`)

func (*Context) GetActiveTools

func (c *Context) GetActiveTools() []string

GetActiveTools returns the names of currently active tools. Returns nil if no tool-scoping actions are wired.

func (*Context) GetAllTools

func (c *Context) GetAllTools() []ToolInfo

pig additive (D23): these methods support Piglet tool scoping. GetAllTools returns metadata about all registered tools. Returns nil if no tool-scoping actions are wired.

func (*Context) GetContextUsage

func (c *Context) GetContextUsage() (*ContextUsage, error)

GetContextUsage returns the current context-window usage for the active model, or nil if unknown. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: returns nil (matches upstream's `() => undefined` default at runner.ts:233).

upstream: runner.ts:614-617 (`getContextUsage: () => { ... }`)

func (*Context) GetFlagValue

func (c *Context) GetFlagValue(name string) any

GetFlagValue returns the value of an extension-registered flag. Returns nil if no flag-value actions are wired.

func (*Context) GetMcpServers

func (c *Context) GetMcpServers() []RegisteredMcpServer

GetMcpServers returns the MCP servers extensions registered, in registration order. It returns nil if the runner's runtime is not bound.

upstream: loader.ts:475-478 (getMcpServers)

func (*Context) GetSystemPrompt

func (c *Context) GetSystemPrompt() (string, error)

GetSystemPrompt returns the current system prompt text. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: returns the empty string (matches upstream's `() => ""` default).

upstream: runner.ts:622-625 (`getSystemPrompt: () => { ... }`)

func (*Context) HasPendingMessages

func (c *Context) HasPendingMessages() (bool, error)

HasPendingMessages reports whether queued messages are awaiting processing. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: returns false (matches upstream's `() => false` default at runner.ts:232).

upstream: runner.ts:606-609 (`hasPendingMessages: () => { ... }`)

func (*Context) HasUI

func (c *Context) HasUI() (bool, error)

HasUI reports whether the runner has a real (non-noop) UI context attached. Mirrors upstream's pointer-identity check (runner.ts:361: `this.uiContext !== noOpUIContext`).

Returns an error if the runner has been invalidated.

upstream: runner.ts:359-362

func (*Context) IsIdle

func (c *Context) IsIdle() (bool, error)

IsIdle reports whether the agent is currently idle (not streaming). Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: returns true (matches upstream's `() => true` default at runner.ts:228).

upstream: runner.ts:594-597 (`isIdle: () => { ... return runner.isIdleFn(); }`)

func (*Context) IsProjectTrusted

func (c *Context) IsProjectTrusted() (bool, error)

IsProjectTrusted reports whether the current project is trusted, so an extension can refuse to read project-scoped configuration or run project code before the user has trusted it. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: returns true (matches upstream's `() => true` default at runner.ts:280).

upstream: runner.ts:718-721 (`isProjectTrusted: () => { ... }`)

func (*Context) Mode

func (c *Context) Mode() (ExtensionMode, error)

Mode returns the current run mode (tui/rpc/json/print), including changes made after this context was created. An unbound getter returns print. Stale contexts return an error. upstream: packages/coding-agent/src/core/extensions/runner.ts:createContext

func (*Context) Model

func (c *Context) Model() (Model, error)

Model returns the currently selected model, or nil if none is set. Returns an error if the runner has been invalidated.

Model is opaque at the extension boundary so providers retain their concrete model representation.

upstream: runner.ts:590 (`get model()`)

func (*Context) ModelRegistry

func (c *Context) ModelRegistry() (ModelRegistry, error)

ModelRegistry returns the per-runtime ModelRegistry. Returns an error if the runner has been invalidated.

upstream: runner.ts:586 (`get modelRegistry()`)

func (*Context) RefreshTools

func (c *Context) RefreshTools() error

RefreshTools rebuilds the session's tool registry from the tools extensions hold, so a tool an extension registered after load is admitted and, when it activates on registration, declared. An in-process extension calls it after Extension.SetRegisteredTool; it does nothing before the host binds the action.

upstream: loader.ts:273-284 (registerTool), types.ts:1598 (RefreshToolsHandler)

func (*Context) ScopedModels

func (c *Context) ScopedModels() ([]ScopedModel, error)

ScopedModels returns the current read-only scope through the callback captured when this context was created. An unbound callback returns an empty list. Do not mutate the returned slice or models. upstream: packages/coding-agent/src/core/extensions/runner.ts:createContext

func (*Context) SendUserMessage

func (c *Context) SendUserMessage(content any, opts *SendUserMessageOptions) error

SendUserMessage injects a user message into the agent loop and triggers a turn when the agent is idle.

Upstream exposes this method on ExtensionAPI. Go handlers receive Context directly, so the method is available here.

func (*Context) SessionManager

func (c *Context) SessionManager() (SessionManager, error)

SessionManager returns the per-runtime SessionManager. Returns an error if the runner has been invalidated.

SessionManager is opaque at the extension boundary; the host owns its concrete implementation.

upstream: runner.ts:582 (`get sessionManager()`)

func (*Context) SetActiveTools

func (c *Context) SetActiveTools(names []string)

SetActiveTools sets the active tool list by name. No-op if no tool-scoping actions are wired.

func (*Context) Shutdown

func (c *Context) Shutdown() error

Shutdown triggers graceful agent shutdown. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: no-op (matches upstream's `() => {}` default at runner.ts:241).

upstream: runner.ts:610-613 (`shutdown: () => { ... }`)

func (*Context) Signal

func (c *Context) Signal() (context.Context, error)

Signal returns the active run's cancellation, or nil while no run is active. Every read during one run returns the same context, and aborting the run cancels it, so a handler that holds it sees the abort while the handler is still in flight. Returns an error if the runner has been invalidated.

Default semantics when no actions injector is bound: returns nil (matches upstream's `() => undefined` default at runner.ts:369).

upstream: runner.ts:917-920 (`get signal()`)

func (*Context) UI

func (c *Context) UI() (UIContext, error)

UI returns the per-mode UIContext. Returns the package-level NoopUIContext singleton when no UI was bound (matches upstream's pre-bind state at runner.ts:255).

Returns an error if the runner has been invalidated.

upstream: runner.ts:572-575 (`get ui()` returns `runner.uiContext`)

type ContextActions

type ContextActions struct {
	// SessionManager backs Context.SessionManager().
	// upstream: types.ts:301 (read-only)
	SessionManager SessionManager

	// ModelRegistry backs Context.ModelRegistry().
	// upstream: types.ts:303
	ModelRegistry ModelRegistry

	// GetModel backs Context.Model(). Returns nil if no model is
	// currently selected.
	// upstream: types.ts:305 (Model<any> | undefined)
	GetModel func() Model

	// GetScopedModels returns the current read-only model scope. Context creation captures this callback, not its result.
	// upstream: packages/coding-agent/src/core/extensions/runner.ts:createContext
	GetScopedModels func() []ScopedModel

	// IsIdle backs Context.IsIdle().
	// upstream: types.ts:307
	IsIdle func() bool

	// IsProjectTrusted backs Context.IsProjectTrusted().
	// upstream: types.ts:332
	IsProjectTrusted func() bool

	// GetSignal backs Context.Signal(). It returns the active run's cancellation, or nil while no run is active.
	// upstream: types.ts:2158, runner.ts:917-920
	GetSignal func() context.Context

	// HasPendingMessages backs Context.HasPendingMessages().
	// upstream: types.ts:313
	HasPendingMessages func() bool

	// SendUserMessage backs Context.SendUserMessage(). Injects a user
	// message into the agent loop. Populated by the runner from
	// ExtensionActions, which is where a host supplies it.
	// upstream: types.ts:1306 (ExtensionAPI.sendUserMessage)
	SendUserMessage SendUserMessageHandler

	// Abort backs Context.Abort(). Cancels the current agent action.
	// upstream: types.ts:311
	Abort func()

	// Shutdown backs Context.Shutdown(). Triggers graceful agent
	// shutdown.
	// upstream: types.ts:315
	Shutdown func()

	// GetContextUsage backs Context.GetContextUsage().
	// upstream: types.ts:317
	GetContextUsage func() *ContextUsage

	// Compact backs Context.Compact(opts).
	// upstream: types.ts:319
	Compact func(opts *CompactOptions)

	// GetSystemPrompt backs Context.GetSystemPrompt(). The host callback
	// returns the latest prompt, including changes made by earlier
	// before_agent_start handlers.
	// upstream: types.ts:321
	GetSystemPrompt func() string

	// GetSystemPromptOptions backs CommandContext.GetSystemPromptOptions().
	// Returns the base inputs pi currently uses to build the system
	// prompt (custom prompt, tools, snippets, guidelines, append text,
	// cwd, context files, skills). nil → method returns zero-value
	// options, matching upstream's
	// `getSystemPromptOptions ?? (() => ({ cwd: this.cwd }))` default.
	// upstream: types.ts:1512, runner.ts:303,653
	GetSystemPromptOptions func() *BuildSystemPromptOptions

	// GetMode reads the current runner mode. Nil means print.
	// upstream: runner.ts:createContext
	GetMode func() ExtensionMode

	// GetUIContext reads the current runner UI binding. Nil uses the constructor's UI binding.
	// upstream: runner.ts:createContext
	GetUIContext func() UIContext

	// GetAllTools returns metadata about all registered tools.
	// Used by piglet scoping to enumerate available tools.
	GetAllTools func() []ToolInfo

	// GetActiveTools returns the names of currently active tools.
	GetActiveTools func() []string

	// SetActiveTools sets the active tool list by name.
	// Tools not in the list are hidden from the agent.
	SetActiveTools func(names []string)

	// RefreshTools rebuilds the session's tool registry from the tools extensions hold, so a tool registered after load
	// reaches the model. It returns the error that admitting a registered tool reports.
	// upstream: types.ts:1598 (RefreshToolsHandler), loader.ts:273-284 (registerTool calls runtime.refreshTools)
	RefreshTools func() error

	// GetMcpServers returns the MCP servers extensions registered, in registration order.
	// upstream: loader.ts:475-478 (getMcpServers)
	GetMcpServers func() []RegisteredMcpServer

	// GetFlagValue returns the value of an extension-registered flag.
	GetFlagValue func(name string) any

	// ToolActions back the [ToolContext] of a tool call: executeTool and
	// getCallableTools of upstream's ExtensionContextActions.
	// upstream: types.ts:2161-2169
	ToolActions
}

ContextActions is the host-side injection of per-runtime callbacks that back Context's surfaces. Mirrors upstream's `ExtensionContextActions` (types.ts:1467-1481): the single struct passed to `bindCore` to wire dynamic context surfaces (model selection, idle state, abort handling, etc.) without making the Context constructor signature unwieldy.

All fields are optional. Nil function fields produce upstream- equivalent default behavior:

GetModel              nil → Model() returns nil (upstream: () => undefined)
IsIdle                nil → IsIdle() returns true (upstream: () => true)
HasPendingMessages    nil → HasPendingMessages() returns false (upstream: () => false)
Shutdown              nil → Shutdown() is no-op (upstream: () => {})
GetContextUsage       nil → GetContextUsage() returns nil (upstream: () => undefined)
Compact               nil → Compact() is no-op (upstream: () => {})
GetSystemPrompt       nil → GetSystemPrompt() returns "" (upstream: () => "")

SessionManager and ModelRegistry are direct value injections (not closures) because upstream stores them as Runner fields, not callbacks; nil values are honored.

pig additive (D23): ContextActions supplies Piglet tool-scoping operations.

type ContextEvent

type ContextEvent struct {
	Type     string         `json:"type"`
	Messages []AgentMessage `json:"messages"`
}

ContextEvent: upstream types.ts ContextEvent.

type ContextEventResult

type ContextEventResult struct {
	Messages []AgentMessage `json:"messages,omitempty"`
}

ContextEventResult: upstream types.ts ContextEventResult.

type ContextUsage

type ContextUsage struct {
	Tokens        *int     `json:"tokens"`
	ContextWindow int      `json:"contextWindow"`
	Percent       *float64 `json:"percent"`
}

ContextUsage mirrors upstream `ContextUsage` (types.ts:276-283). Reports the agent's current context-window utilization for the active model.

Field semantics (from upstream JSDoc):

  • Tokens: estimated context tokens, or nil if unknown (e.g. right after compaction, before the next LLM response).
  • ContextWindow: model's maximum context size in tokens.
  • Percent: usage as percentage of context window, or nil if Tokens is unknown.

Pointer-typed nullable fields distinguish unknown from zero; percentages retain JavaScript number precision.

upstream: types.ts:276-283

type ContextWithSystemEvent

type ContextWithSystemEvent struct {
	Type     string         `json:"type"`
	Messages []AgentMessage `json:"messages"`
}

ContextWithSystemEvent: upstream types.ts ContextWithSystemEvent. Handlers see the full transcript, system messages included, after the context handlers; their returned messages are used as returned.

type CustomEntry

type CustomEntry = any

CustomEntry mirrors core CustomEntry<T>: a session entry appended via AppendEntry that does not participate in LLM context. Like CustomMessage, the generic payload is carried untyped (the wire boundary is JSON) and renderers type-assert as needed.

type CustomFactory

type CustomFactory func(host CustomHost, theme Theme, keybindings KeybindingsManager, done func(result any)) (Component, error)

CustomFactory builds the component UIContext.Custom shows, for an extension that runs in the host process (upstream `ctx.ui.custom(factory)`). theme is the active theme and keybindings the merged keybinding table of the interactive mode (both concrete types of the tui package); done ends the call with a result and may run on any goroutine. The component renders and reads input on the interactive loop; it may also implement interface{ Dispose() }, which runs once after done. upstream: packages/coding-agent/src/core/extensions/types.ts:187 (custom)

type CustomHost

type CustomHost interface {
	// RequestRender asks the terminal to draw again. It is safe from any goroutine.
	RequestRender()
}

CustomHost is the terminal a component built by a CustomFactory draws on (upstream's `tui` argument).

type CustomMessage

type CustomMessage = any

CustomMessage mirrors core/messages.CustomMessage<T>.

type CustomMessageRef

type CustomMessageRef struct {
	CustomType string `json:"customType"`
	Content    any    `json:"content"`
	Display    any    `json:"display,omitempty"`
	Details    any    `json:"details,omitempty"`
}

CustomMessageRef mirrors upstream's `Pick<CustomMessage, "customType" | "content" | "display" | "details">`.

func (*CustomMessageRef) UnmarshalJSON

func (m *CustomMessageRef) UnmarshalJSON(data []byte) error

UnmarshalJSON keeps the member order of the `details` object the extension wrote.

type CustomOptions

type CustomOptions struct {
	// Overlay shows the component over the screen instead of in the editor slot.
	Overlay bool
	// Layout positions an overlay.
	Layout *OverlayLayout
}

CustomOptions is the `options` of an in-process UIContext.Custom. upstream: packages/coding-agent/src/core/extensions/types.ts:187 (overlay, overlayOptions)

type CustomToolCallEvent

type CustomToolCallEvent struct {
	ToolCallEventBase
	ToolName string         `json:"toolName"`
	Input    map[string]any `json:"input"`
}

CustomToolCallEvent: upstream types.ts CustomToolCallEvent.

type CustomToolResultEvent

type CustomToolResultEvent struct {
	ToolResultEventBase
	ToolName string `json:"toolName"`
	Details  any    `json:"details,omitempty"`
}

CustomToolResultEvent: upstream types.ts CustomToolResultEvent.

func (CustomToolResultEvent) MarshalJSON

func (e CustomToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type DeliverAs

type DeliverAs string

DeliverAs is the queueing discriminator for API.SendMessage / API.SendUserMessage. Upstream literal-string union.

upstream: types.ts:1161, 1170

const (
	DeliverAsSteer    DeliverAs = "steer"
	DeliverAsFollowUp DeliverAs = "followUp"
	DeliverAsNextTurn DeliverAs = "nextTurn"
)

type DialogInitiationReporter

type DialogInitiationReporter interface {
	ReportsDialogInitiation() bool
}

DialogInitiationReporter is implemented by a UIContext whose Select, Confirm, Input, and Editor call CallInitiated once the dialog is installed. Other UIContexts are treated as initiated when the host dispatches the call.

type EditToolCallEvent

type EditToolCallEvent struct {
	ToolCallEventBase
	ToolName string        `json:"toolName"` // "edit"
	Input    EditToolInput `json:"input"`
}

EditToolCallEvent: upstream types.ts EditToolCallEvent.

type EditToolDetails

type EditToolDetails struct {
	Diff             string `json:"diff"`
	Patch            string `json:"patch"`
	FirstChangedLine int    `json:"firstChangedLine,omitempty"`
}

EditToolDetails is the upstream SDK contract for built-in edit-tool result details (edit.ts:61). Extensions and PostToolUse hooks receive this shape on tool_result events for the `edit` tool: a display diff, a standard unified patch, and the first changed line for navigation.

type EditToolInput

type EditToolInput = any

type EditToolResultEvent

type EditToolResultEvent struct {
	ToolResultEventBase
	ToolName string           `json:"toolName"` // "edit"
	Details  *EditToolDetails `json:"details,omitempty"`
}

EditToolResultEvent: upstream types.ts EditToolResultEvent.

func (EditToolResultEvent) MarshalJSON

func (e EditToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type EditorComponent

type EditorComponent = any

EditorComponent mirrors @earendil-works/pi-tui EditorComponent.

type EditorTheme

type EditorTheme = any

EditorTheme mirrors @earendil-works/pi-tui EditorTheme.

type EntryRenderOptions

type EntryRenderOptions struct {
	Expanded bool `json:"expanded"`
}

EntryRenderOptions is passed to an EntryRenderer. Mirrors upstream EntryRenderOptions.

type EntryRenderer

type EntryRenderer = func(
	entry CustomEntry,
	options EntryRenderOptions,
	theme Theme,
) Component

EntryRenderer mirrors upstream EntryRenderer<T>. Renders a custom session entry (appended via AppendEntry; not sent to the LLM) into a TUI Component, or returns nil to fall back to the default renderer.

As with MessageRenderer, the Go signature drops the TS generic parameter T: the entry's data is carried on CustomEntry (currently `any`) and the renderer type-asserts as needed.

type ErrorListener

type ErrorListener = func(*ExtensionError)

ErrorListener is the callback signature registered via Runner.AddErrorListener. Listeners run synchronously in the dispatch goroutine; long-running work should be moved to a dedicated goroutine by the listener itself.

upstream: runner.ts:469 (private errorListeners: Set<ErrorListener>)

type EventBus

type EventBus interface {
	// Emit broadcasts data on channel to every current listener. Synchronous:
	// handlers run before Emit returns. A handler's failure does not reach the
	// emitter or the other listeners; the host reports it as
	// `Event handler error (<channel>):` (event-bus.ts:19-23).
	Emit(channel string, data any)

	// On registers handler for channel and returns an idempotent function that
	// removes it. Handlers are dispatched in registration order.
	On(channel string, handler func(data any)) (unsubscribe func())
}

EventBus is the extension-to-extension event bus. Mirrors upstream's core/event-bus.ts EventBus, exposed on ExtensionAPI as the property `events: EventBus`, with upstream's method names.

Go exposes upstream's `events` property through API.Events.

upstream: event-bus.ts:3-6

type ExecOptions

type ExecOptions struct {
	// Timeout in milliseconds. Pi's timeout is a JavaScript number: a positive value starts a timer and anything else starts none.
	Timeout float64 `json:"timeout,omitempty"`
	// CWD overrides the working directory. Empty uses the extension's CWD.
	CWD string `json:"cwd,omitempty"`
}

ExecOptions configures a shell command execution.

upstream: core/exec.ts ExecOptions

type ExecResult

type ExecResult struct {
	Stdout string `json:"stdout"`
	Stderr string `json:"stderr"`
	Code   int    `json:"code"`
	Killed bool   `json:"killed"`
}

ExecResult is the outcome of a shell command execution.

upstream: core/exec.ts ExecResult

func ExecCommand

func ExecCommand(ctx context.Context, cwd, command string, args []string, opts *ExecOptions) (ExecResult, error)

ExecCommand runs a shell command synchronously and returns the result. This is the default implementation backing API.Exec when the host doesn't provide an override.

The command is spawned directly (no shell wrapping). Use args to pass arguments. If opts.CWD is empty, cwd is used as the working directory. Like upstream, a program that cannot start does not fail the call: the result has code 1 and empty output. Arguments that Node's spawn rejects, an empty command or a NUL in the command, an argument, or the working directory, fail the call with Node's ERR_INVALID_ARG_VALUE message, which upstream's spawn throws. On Windows the program is looked up as Node's spawn looks it up (nodespawn.LookPath), so a name that matches only through PATHEXT, such as npm for npm.cmd, cannot start. A batch file name fails the call with Node's "spawn EINVAL" error, which upstream's spawn throws.

Like upstream, the call waits for the child, then for its output pipes to end or to fall idle for 100 ms (utils/child-process.ts waitForChildProcess), so a descendant that keeps a pipe open does not block it, and output the descendant writes while the pipes stay active is kept.

Timeout and context cancellation signal the child alone with SIGTERM (Process.Kill on Windows, where Node's kill terminates the process). Like upstream, nothing follows it: Node sets proc.killed once SIGTERM is delivered, so upstream's SIGKILL after 5 seconds never runs, and no descendant is signalled. The result's code is the child's exit code; a child that a signal ended has none, and upstream resolves it as 0 (`code ?? 0`). On Windows a child that the kill ended has none either: libuv reports the signal it was sent instead of the exit status 1, so the code is 0 there too.

upstream: core/exec.ts execCommand

type ExecuteToolOptions

type ExecuteToolOptions struct {
	// Signal cancels the nested call. Defaults to the calling tool's context. Go mechanic (not a divergence): upstream's AbortSignal is a context.Context, as in [ExecOptions].
	Signal context.Context `json:"-"`
	// OnUpdate receives partial results of the nested tool, in addition to `tool_execution_update` events.
	OnUpdate AgentToolUpdateCallback `json:"-"`
}

ExecuteToolOptions mirrors upstream ExecuteToolOptions.

upstream: types.ts:367-372 (ExecuteToolOptions)

type Extension

type Extension struct {
	// Name is the human-readable name of the extension, typically derived
	// from the manifest or directory name. Used for display in the UI.
	Name string

	// Path is the original (unresolved) path the extension was loaded from.
	// This is typically the path the user passed via --extension or that the
	// loader discovered. May be relative.
	Path string

	// ResolvedPath is the absolute, canonical path used for diagnostics,
	// telemetry, and "Using <path>" UI strings.
	ResolvedPath string

	// Replaceable leaves the extension out when another extension registers a
	// tool, command, or flag with a name it registers during loading, instead of
	// reporting a conflict. The CLI's built-in MCP, codemode, and tool search
	// extensions use it. upstream: types.ts:2209 (Extension.replaceable)
	Replaceable bool

	// SourceInfo describes the extension's origin and ownership metadata. The
	// current public contract carries this value opaquely.
	SourceInfo SourceInfo

	// Handlers is the legacy construction shape. NewRunner imports it into the
	// concurrency-safe handler registry before dispatch.
	Handlers map[string][]HandlerFn

	// Tools is the startup construction shape, keyed by name. Runtime readers use RegisteredTools or RegisteredTool to include synchronized late registrations.
	Tools map[string]RegisteredTool

	// ToolOrder records tool registration order. Go maps do not retain
	// insertion order; loaders populate this alongside Tools so tool lists
	// keep upstream's registration order (a Map in extension.tools).
	ToolOrder []string

	// MessageRenderers is keyed by the custom message type the renderer handles.
	MessageRenderers map[string]MessageRenderer

	// EntryRenderers is keyed by the custom entry type the renderer handles.
	// Custom entries (appended via AppendEntry) do not participate in LLM context.
	EntryRenderers map[string]EntryRenderer

	// ToolRenderers are the extension's tool renderer resolvers, in registration order.
	// upstream: types.ts Extension.toolRenderers
	ToolRenderers []ToolRendererResolver

	// MarkdownTransformer is the extension's display-only Markdown transform,
	// if it registered one; a later registration replaces an earlier one.
	// upstream: types.ts Extension.markdownTransformer
	MarkdownTransformer MarkdownTransformer

	// Commands is keyed by the command name (without leading slash).
	Commands map[string]RegisteredCommand

	// CommandOrder records command registration order. Go maps do not retain
	// insertion order; loaders populate this alongside Commands so resolved
	// invocation names match upstream extension and registration order.
	CommandOrder []string

	// Flags is keyed by the flag name.
	Flags map[string]ExtensionFlag

	// FlagOrder records the first registration of each flag name. Loaders populate it alongside Flags, so --help lists flags in upstream registration order.
	FlagOrder []string

	// Shortcuts is keyed by the canonical KeyID (e.g. "ctrl+shift+r").
	Shortcuts map[KeyID]ExtensionShortcut

	// Hidden omits the extension from the startup Extensions list.
	// upstream: .upstream/v0.99.1/packages/coding-agent/src/core/extensions/types.ts:2208 (Extension.hidden)
	Hidden bool
	// contains filtered or unexported fields
}

Extension is the state container populated by an extension's factory during loading. It is the cross-tier contract between the host and the extension implementation: factories write registrations into the API, the API writes them into this struct, and the Runner reads from it during dispatch.

A pre-populated `[]Extension` is what gets handed to a Runner. Loaders produce these; runners consume them. The runner does not mutate them.

Field-level translation rule: Go's idiomatic field naming and JSON tag preservation are applied; see docs/parity/DIVERGENCES.md "TS→Go translation rituals" section. The maps, sets, and overall shape mirror upstream verbatim.

upstream: types.ts:1513-1523 (export interface Extension)

func (*Extension) AddEventHandler

func (e *Extension) AddEventHandler(event string, id int, handler HandlerFn)

AddEventHandler appends one identity-bearing handler in registration order.

func (*Extension) EventHandlers

func (e *Extension) EventHandlers(event string) []HandlerFn

EventHandlers returns a stable dispatch snapshot. Registration changes made while it is being iterated apply only to the next dispatch.

func (*Extension) InitializeEventHandlers

func (e *Extension) InitializeEventHandlers()

InitializeEventHandlers imports legacy Handlers once. Call before sharing an Extension between host and runner copies.

func (*Extension) InitializeToolRegistry

func (e *Extension) InitializeToolRegistry()

InitializeToolRegistry enables synchronized runtime registration before an Extension is shared with runners.

func (*Extension) RegisteredTool

func (e *Extension) RegisteredTool(name string) (RegisteredTool, bool)

RegisteredTool looks up the current definition without copying the registry.

func (*Extension) RegisteredTools

func (e *Extension) RegisteredTools() []RegisteredTool

RegisteredTools returns an ordered snapshot, including tools registered after load.

func (*Extension) RemoveEventHandler

func (e *Extension) RemoveEventHandler(event string, id int)

RemoveEventHandler removes the exact registered identity. It is idempotent.

func (*Extension) ReplaceEventHandlers

func (e *Extension) ReplaceEventHandlers(source *Extension)

ReplaceEventHandlers makes e's handlers exactly source's, in place, so every copy of e that shares its registry dispatches to the new set from the next dispatch on. A restarted subprocess registers afresh; its runner keeps the copy it was built with.

func (*Extension) ReplaceRegisteredTools

func (e *Extension) ReplaceRegisteredTools(source *Extension)

ReplaceRegisteredTools replaces the shared registry when the owning runtime restarts.

func (*Extension) SetRegisteredTool

func (e *Extension) SetRegisteredTool(tool RegisteredTool)

SetRegisteredTool replaces a definition in place or appends a new name in registration order.

type ExtensionActions

type ExtensionActions struct {
	// upstream: types.ts:1590: SendMessageHandler
	SendMessage any
	// upstream: types.ts:1591: SendUserMessageHandler
	SendUserMessage SendUserMessageHandler
	// upstream: types.ts:1591: AppendEntryHandler
	AppendEntry any
	// upstream: types.ts:1592: SetSessionNameHandler
	SetSessionName any
	// upstream: types.ts:1593: GetSessionNameHandler
	GetSessionName any
	// upstream: types.ts:1594: SetLabelHandler
	SetLabel any
	// upstream: types.ts:1595: GetActiveToolsHandler
	GetActiveTools any
	// upstream: types.ts:1596: GetAllToolsHandler
	GetAllTools any
	// upstream: types.ts:2135: GetSettingsHandler
	GetSettings func() Settings
	// upstream: types.ts:1597: SetActiveToolsHandler
	SetActiveTools any
	// upstream: types.ts:1598: RefreshToolsHandler
	RefreshTools any
	// upstream: types.ts:1599: GetCommandsHandler
	GetCommands any
	// upstream: types.ts:1600: SetModelHandler
	SetModel any
	// upstream: types.ts:1601: GetThinkingLevelHandler
	GetThinkingLevel any
	// upstream: types.ts:1602: SetThinkingLevelHandler
	SetThinkingLevel any
}

ExtensionActions is the host-side injection of agent-loop callbacks available to extensions via `ctx.actions.*` (the runtime side; this struct is consumed by [host.Runner.BindCore]). Mirrors upstream `ExtensionActions` (types.ts:1588-1603).

Most fields are opaque-typed (`any`) at this boundary because their concrete handler types live in upstream files not yet ported (session-manager, agent-runtime, tool-registry). Field names and upstream line cites are fixed here so a concrete handler type can replace `any` without renaming.

upstream: types.ts:1589-1603

type ExtensionError

type ExtensionError struct {
	// ExtensionPath is the resolved filesystem path of the extension
	// whose handler failed. Mirrors upstream `extensionPath`.
	ExtensionPath string `json:"extensionPath"`

	// Event is the event-type string the handler was registered for
	// (e.g. "tool_call", "session_start"). Mirrors upstream `event`.
	Event string `json:"event"`

	// Error is the human-readable message. In Go this is `err.Error()`;
	// upstream is `err.message`. Mirrors upstream `error`.
	Error string `json:"error"`

	// Stack is the optional stack of the failure itself, as upstream's
	// `err.stack`: the thrown error's stack for a subprocess extension, or
	// the panicking goroutine's stack for an in-process handler. It is empty
	// for a plain returned error, which carries no stack. See [ErrorStack].
	Stack string `json:"stack,omitempty"`
}

ExtensionError is the structured error surfaced when a registered handler throws (TS) / returns a non-nil error (Go) during event dispatch. Hosts collect these without aborting the dispatch chain and surface them through `Runner.AddErrorListener`.

upstream: types.ts:1537-1542

export interface ExtensionError {
	extensionPath: string;
	event: string;
	error: string;
	stack?: string;
}

Wire format note. JSON tags match upstream camelCase exactly so the type round-trips cleanly through current and future extension transports.

type ExtensionFlag

type ExtensionFlag struct {
	Name          string   `json:"name"`
	Description   string   `json:"description,omitempty"`
	Type          FlagType `json:"type"`
	Default       any      `json:"default,omitempty"`
	ExtensionPath string   `json:"extensionPath"`
}

ExtensionFlag mirrors upstream's ExtensionFlag: the loader's view of a registered flag, including its source extension. Hosts hand this to the CLI parser.

type ExtensionMode

type ExtensionMode string

ExtensionMode is the run mode pi is operating in, exposed to extensions via Context.Mode(). Extensions guard terminal-only UI (custom components, dialogs) on mode == ModeTUI.

upstream: packages/coding-agent/src/core/extensions/types.ts:298 (`export type ExtensionMode = "tui" | "rpc" | "json" | "print"`)

const (
	// ModeTUI is the interactive terminal UI. Set by interactive mode
	// (interactive-mode.ts:1511 `mode: "tui"`).
	ModeTUI ExtensionMode = "tui"
	// ModeRPC is the headless JSONL command/event loop. Set by rpc mode
	// (rpc-mode.ts:320 `mode: "rpc"`).
	ModeRPC ExtensionMode = "rpc"
	// ModeJSON is print mode emitting all events as JSON. Set by print
	// mode when its output mode is "json" (print-mode.ts:74).
	ModeJSON ExtensionMode = "json"
	// ModePrint is print mode emitting only the final text response.
	// The upstream Runner default (runner.ts:229).
	ModePrint ExtensionMode = "print"
)

type ExtensionRuntime

type ExtensionRuntime struct {
	// contains filtered or unexported fields
}

ExtensionRuntime shares pending and bound provider actions between extension loading and the Runner. It stores no model catalog and does not execute factories.

func CreateExtensionRuntime

func CreateExtensionRuntime() *ExtensionRuntime

CreateExtensionRuntime creates the pre-bind provider registration state.

func (*ExtensionRuntime) BindProviderActions

func (r *ExtensionRuntime) BindProviderActions(actions ProviderActions, report func(*ExtensionError))

BindProviderActions drains the loading queues in order, reports each failure before continuing, and installs immediate actions. Provider registrations drain first, then virtual models. Actions left nil leave their queue pending. The owner serializes binding with other binds. Callbacks run outside state locks and may register or unregister providers and virtual models.

upstream: runner.ts:265-294, 413-417, 497-541 (bindCore)

func (*ExtensionRuntime) CheckMcpServer

func (r *ExtensionRuntime) CheckMcpServer(extensionPath, name string, config json.RawMessage) (McpServerConfig, error)

CheckMcpServer runs the checks of ExtensionRuntime.RegisterMcpServer without registering: the config is valid and no other extension registered the name. It returns the validated config and the error the registration would return.

upstream: loader.ts:456-465 (registerMcpServer)

func (*ExtensionRuntime) CreateContext

func (r *ExtensionRuntime) CreateContext() (*Context, error)

CreateContext builds an extension Context. It returns ErrRuntimeNotInitialized before the runner binds.

upstream: loader.ts:190 (createContext: notInitialized), runner.ts:436

func (*ExtensionRuntime) McpServers

func (r *ExtensionRuntime) McpServers() []RegisteredMcpServer

McpServers returns copies of every registered server, in registration order.

upstream: loader.ts:475-478 (getMcpServers)

func (*ExtensionRuntime) PendingProviderRegistrations

func (r *ExtensionRuntime) PendingProviderRegistrations() []PendingProviderRegistration

PendingProviderRegistrations returns the current queue in registration order. Repeated provider names remain separate entries.

func (*ExtensionRuntime) PendingVirtualModelRegistrations

func (r *ExtensionRuntime) PendingVirtualModelRegistrations() []PendingVirtualModelRegistration

PendingVirtualModelRegistrations returns the queue in registration order.

upstream: loader.ts:225-227 (pendingVirtualModelRegistrations)

func (*ExtensionRuntime) RegisterMcpServer

func (r *ExtensionRuntime) RegisterMcpServer(extensionPath, name string, config json.RawMessage) error

RegisterMcpServer validates config as an `mcpServers` entry named name, checks that no other extension registered the name, and registers a copy for extensionPath. A registration replaces the extension's earlier one. The change listener runs after the registry changed.

It returns `Invalid MCP server registered by extension "<path>": <message>` for an invalid config and `MCP server "<name>" is already registered by extension "<owner>"` for a name another extension registered.

It returns `MCP server "<name>" conflicts with registered server "<other>"` for a name that shares the namespace of a registered server.

upstream: loader.ts:464-481 (registerMcpServer stores `structuredClone(validated)`, the alias-resolved copy, at 479)

func (*ExtensionRuntime) RegisterProvider

func (r *ExtensionRuntime) RegisterProvider(name string, config ProviderConfig, extensionPath ...string) error

RegisterProvider queues during loading and invokes the bound registry synchronously afterward. Configuration callbacks are retained, not serialized.

func (*ExtensionRuntime) RegisterVirtualModel

func (r *ExtensionRuntime) RegisterVirtualModel(definition VirtualModelDefinition, extensionPath string) error

RegisterVirtualModel queues a virtual model during loading and applies it through the bound ProviderActions afterward. Registering the same provider and id again replaces the virtual model.

upstream: loader.ts:225-227, runner.ts:497-537 (registerVirtualModel)

func (*ExtensionRuntime) SetContextFactory

func (r *ExtensionRuntime) SetContextFactory(create func() (*Context, error))

SetContextFactory installs the function that builds the extension Context a virtual model's Route receives. The runner sets it when it binds.

upstream: runner.ts:436 (runtime.createContext)

func (*ExtensionRuntime) SetMcpServersChangeListener

func (r *ExtensionRuntime) SetMcpServersChangeListener(listener func())

SetMcpServersChangeListener sets the function called after every registration change. The runner sets it when it binds, to emit `mcp_servers_change`; nil removes it.

upstream: runner.ts:459-462 (mcpServers.setChangeListener)

func (*ExtensionRuntime) UnregisterMcpServer

func (r *ExtensionRuntime) UnregisterMcpServer(extensionPath, name string)

UnregisterMcpServer removes a server extensionPath registered. Servers of other extensions are left alone.

upstream: loader.ts:470-473 (unregisterMcpServer)

func (*ExtensionRuntime) UnregisterProvider

func (r *ExtensionRuntime) UnregisterProvider(name string)

UnregisterProvider removes every queued registration of name before binding, and invokes the registry immediately afterward.

func (*ExtensionRuntime) UnregisterVirtualModel

func (r *ExtensionRuntime) UnregisterVirtualModel(provider, id string)

UnregisterVirtualModel removes every queued registration of the provider and id before binding, and applies the removal through the bound ProviderActions afterward.

upstream: loader.ts:229-233, runner.ts:538-541 (unregisterVirtualModel)

type ExtensionShortcut

type ExtensionShortcut struct {
	Shortcut      KeyID           `json:"shortcut"`
	Description   string          `json:"description,omitempty"`
	Handler       ShortcutHandler `json:"-"`
	ExtensionPath string          `json:"extensionPath"`
}

ExtensionShortcut mirrors upstream's ExtensionShortcut: the loader's view of a registered shortcut, including its source extension.

type ExtensionUIDialogOptions

type ExtensionUIDialogOptions = any

ExtensionUIDialogOptions mirrors upstream ExtensionUIDialogOptions.

type ExtensionVirtualModel

type ExtensionVirtualModel = VirtualModelDefinition

ExtensionVirtualModel is a virtual model registered through API.RegisterVirtualModel. Its Route runs with the extension Context in ctx.

upstream: types.ts:1864-1867 (ExtensionVirtualModel)

type ExtensionWidgetOptions

type ExtensionWidgetOptions = any

ExtensionWidgetOptions mirrors upstream ExtensionWidgetOptions.

type FindToolCallEvent

type FindToolCallEvent struct {
	ToolCallEventBase
	ToolName string        `json:"toolName"` // "find"
	Input    FindToolInput `json:"input"`
}

FindToolCallEvent: upstream types.ts FindToolCallEvent.

type FindToolDetails

type FindToolDetails struct {
	Truncation         *ToolTruncation `json:"truncation,omitempty"`
	ResultLimitReached *float64        `json:"resultLimitReached,omitempty"`
}

FindToolDetails mirrors upstream find.ts:32.

type FindToolInput

type FindToolInput = any

type FindToolResultEvent

type FindToolResultEvent struct {
	ToolResultEventBase
	ToolName string           `json:"toolName"` // "find"
	Details  *FindToolDetails `json:"details,omitempty"`
}

FindToolResultEvent: upstream types.ts FindToolResultEvent.

func (FindToolResultEvent) MarshalJSON

func (e FindToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type FlagOptions

type FlagOptions struct {
	Description string   `json:"description,omitempty"`
	Type        FlagType `json:"type"`
	// Default is bool when Type == FlagBoolean and string when
	// Type == FlagString. Nil when no default.
	Default any `json:"default,omitempty"`
}

FlagOptions is the registration payload for API.RegisterFlag. Mirrors the inline option object on upstream ExtensionAPI.registerFlag.

type FlagType

type FlagType string

FlagType is the value type of a CLI flag registered by an extension. Mirrors upstream's "boolean" | "string" union.

const (
	FlagBoolean FlagType = "boolean"
	FlagString  FlagType = "string"
)

type ForkOptions

type ForkOptions struct {
	Position    string                              `json:"position,omitempty"` // "before" | "at"
	WithSession func(*ReplacedSessionContext) error `json:"-"`
}

ForkOptions mirrors upstream's fork options.

upstream: types.ts:342-343

type GrepToolCallEvent

type GrepToolCallEvent struct {
	ToolCallEventBase
	ToolName string        `json:"toolName"` // "grep"
	Input    GrepToolInput `json:"input"`
}

GrepToolCallEvent: upstream types.ts GrepToolCallEvent.

type GrepToolDetails

type GrepToolDetails struct {
	Truncation        *ToolTruncation `json:"truncation,omitempty"`
	MatchLimitReached float64         `json:"matchLimitReached,omitempty"`
	LinesTruncated    bool            `json:"linesTruncated,omitempty"`
}

GrepToolDetails mirrors upstream grep.ts:41. Sparse fields retain the requested numeric limit without rounding.

type GrepToolInput

type GrepToolInput = any

type GrepToolResultEvent

type GrepToolResultEvent struct {
	ToolResultEventBase
	ToolName string           `json:"toolName"` // "grep"
	Details  *GrepToolDetails `json:"details,omitempty"`
}

GrepToolResultEvent: upstream types.ts GrepToolResultEvent.

func (GrepToolResultEvent) MarshalJSON

func (e GrepToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type HandlerFn

type HandlerFn = func(args ...any) (any, error)

HandlerFn is the type-erased storage shape for event handlers.

The typed API methods (`OnToolCall`, `OnSessionStart`, ...) accept strongly-typed handler functions and wrap them into HandlerFn for storage in `Extension.Handlers`. The Runner reverses the wrap when dispatching: for each event firing, it looks up handlers by event name, calls each with the typed payload boxed as `any`, and casts the returned `any` back to the typed *EventResult shape.

This is the implementation detail of D1, which uses type erasure where Go cannot express upstream's generic event-handler map. Typed API methods and SDK helpers keep HandlerFn out of normal extension authoring.

upstream: types.ts:1380 (type HandlerFn = (...args: unknown[]) => Promise<unknown>)

type ImageContent

type ImageContent = any

ImageContent mirrors @earendil-works/pi-ai ImageContent.

type InputEvent

type InputEvent struct {
	Type   string         `json:"type"`
	Text   string         `json:"text"`
	Images []ImageContent `json:"images,omitempty"`
	Source InputSource    `json:"source"`
	// StreamingBehavior indicates context when input arrives during streaming.
	// "steer" = mid-stream steer, "followUp" = queued follow-up.
	// Empty when the agent is idle. Mirrors upstream v0.77.0.
	StreamingBehavior string `json:"streamingBehavior,omitempty"`
}

InputEvent: upstream types.ts InputEvent.

type InputEventResult

type InputEventResult interface {
	// contains filtered or unexported methods
}

InputEventResult is the sealed union of handler responses for the "input" extension event. Mirrors upstream `types.ts InputEventResult`:

export type InputEventResult =
    | { action: "continue" }
    | { action: "transform"; text: string; images?: ImageContent[] }
    | { action: "handled" };

The interface is package-sealed via the unexported `isInputEventResult` marker method: only the three variants in this package can satisfy it. Custom MarshalJSON/UnmarshalJSON in marshalling.go preserves upstream's `{"action": "..."}` discriminator wire shape.

Authors return one of:

upstream: types.ts:750

func UnmarshalInputEventResult

func UnmarshalInputEventResult(data []byte) (InputEventResult, error)

UnmarshalInputEventResult parses upstream wire shape into the matching sealed-interface variant. Returns an error on unknown action discriminators so silent drift cannot enter the system.

type InputEventResultContinue

type InputEventResultContinue struct{}

InputEventResultContinue: upstream `{ action: "continue" }`.

type InputEventResultHandled

type InputEventResultHandled struct{}

InputEventResultHandled: upstream `{ action: "handled" }`. Tells the host the extension fully handled the input; the agent does NOT run for this turn.

type InputEventResultTransform

type InputEventResultTransform struct {
	Text   string         `json:"text"`
	Images []ImageContent `json:"images,omitempty"`
}

InputEventResultTransform: upstream `{ action: "transform"; text: string; images?: ImageContent[] }`. Replaces the user input before it reaches the agent.

type InputSource

type InputSource = string

InputSource mirrors upstream "interactive" | "rpc" | "extension".

const (
	InputSourceUser      InputSource = "interactive"
	InputSourceRPC       InputSource = "rpc"
	InputSourceExtension InputSource = "extension"
)

type KeyID

type KeyID = string

KeyID identifies a keyboard shortcut. Mirrors @mariozechner/pi-tui KeyId, which is a string (e.g. "ctrl+shift+l", "alt+enter").

type KeybindingsManager

type KeybindingsManager = any

KeybindingsManager mirrors core/keybindings.KeybindingsManager.

type LoginDefinition

type LoginDefinition struct {
	Brand       []string          `json:"brand"`
	Hero        []string          `json:"hero"`
	Mascot      []string          `json:"mascot"`
	Palette     map[string]string `json:"palette"`
	Name        string            `json:"name"`
	Description string            `json:"description"`
	Tagline     string            `json:"tagline"`
}

LoginDefinition describes one login using Pig's fixed native template. Grid cells are printable ASCII palette symbols; '.' is transparent.

type LoginDefinitionError

type LoginDefinitionError struct {
	Field   string
	Message string
}

LoginDefinitionError identifies the invalid field in a login definition.

func (*LoginDefinitionError) Error

func (e *LoginDefinitionError) Error() string

type LsToolCallEvent

type LsToolCallEvent struct {
	ToolCallEventBase
	ToolName string      `json:"toolName"` // "ls"
	Input    LsToolInput `json:"input"`
}

LsToolCallEvent: upstream types.ts LsToolCallEvent.

type LsToolDetails

type LsToolDetails struct {
	Truncation        *ToolTruncation `json:"truncation,omitempty"`
	EntryLimitReached float64         `json:"entryLimitReached,omitempty"`
}

LsToolDetails mirrors upstream ls.ts:23, including fractional requested limits.

type LsToolInput

type LsToolInput = any

type LsToolResultEvent

type LsToolResultEvent struct {
	ToolResultEventBase
	ToolName string         `json:"toolName"` // "ls"
	Details  *LsToolDetails `json:"details,omitempty"`
}

LsToolResultEvent: upstream types.ts LsToolResultEvent.

func (LsToolResultEvent) MarshalJSON

func (e LsToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type MarkdownMessageType

type MarkdownMessageType string

MarkdownMessageType identifies the transcript message being transformed for display. Transformers never change model context or persisted message data.

const (
	MarkdownMessageUser      MarkdownMessageType = "user"
	MarkdownMessageAssistant MarkdownMessageType = "assistant"
	// MarkdownMessageAssistantThinking marks the reasoning/thinking trace of an
	// assistant turn. Mirrors upstream MarkdownTransformContext.messageType
	// "assistant-thinking"; the built-in Mermaid transformer skips it.
	MarkdownMessageAssistantThinking MarkdownMessageType = "assistant-thinking"
)

type MarkdownTransformContext

type MarkdownTransformContext struct {
	// Context owns the off-loop host generation; it is not part of Pi's wire context.
	Context        context.Context     `json:"-"`
	MessageType    MarkdownMessageType `json:"messageType"`
	IsStreaming    bool                `json:"isStreaming"`
	AvailableWidth int                 `json:"availableWidth"`
}

MarkdownTransformContext mirrors upstream MarkdownTransformContext.

type MarkdownTransformer

type MarkdownTransformer func(markdown string, context MarkdownTransformContext) string

MarkdownTransformer performs a synchronous display-only Markdown rewrite.

type McpAuthConfig

type McpAuthConfig struct {
	Provider string `json:"provider"`
}

McpAuthConfig sends the token of a pi provider (`/login <provider>`) as the bearer token instead of using OAuth.

type McpExposure

type McpExposure string

McpExposure selects how the model reaches the tools of an MCP server.

  • codemode: tools are callable from codemode scripts, but not declared to the model and not listed in the codemode description, which lists only the server's namespace. Scripts find them with searchTools(). "codemode-deferred" is accepted as an alias.
  • deferred: not declared to the model until the tool_search tool loads them; the model then calls them directly. Does not need codemode.
  • direct: tools are declared to the model like any other tool (and callable from codemode).
  • hidden: tools are registered but unreachable.
const (
	McpExposureCodemode McpExposure = "codemode"
	McpExposureDeferred McpExposure = "deferred"
	McpExposureDirect   McpExposure = "direct"
	McpExposureHidden   McpExposure = "hidden"
)

The exposures of upstream's McpExposure union.

func GetMcpToolExposure

func GetMcpToolExposure(config McpServerConfig, toolName string) McpExposure

GetMcpToolExposure is the exposure of one tool of a server: its `toolExposure` entry, else the server's `exposure`.

type McpOAuthConfig

type McpOAuthConfig struct {
	// ClientID is a pre-registered client id. Without it, a client is registered
	// with the authorization server.
	ClientID string `json:"clientId,omitempty"`
	// ClientSecret may reference environment variables (`${NAME}`) or commands (`!cmd`).
	ClientSecret string `json:"clientSecret,omitempty"`
	// CallbackPort is the port of the loopback callback server, for clients
	// registered with a fixed redirect URI. Without CallbackURL, the redirect URI
	// is `http://127.0.0.1:<port>/callback`.
	CallbackPort *int `json:"callbackPort,omitempty"`
	// CallbackURL is the redirect URI registered for ClientID, for example
	// `http://localhost:8080/oauth/callback`. It must be an `http` URI on
	// `localhost`, `127.0.0.1`, or `[::1]`. Without a port, the callback server
	// listens on CallbackPort or a free port, which is added to the URI (RFC 8252).
	CallbackURL string `json:"callbackUrl,omitempty"`
	// Scope lists the scopes to request, separated by spaces. Default: the
	// scopes the server advertises.
	Scope string `json:"scope,omitempty"`
	// ClientName is the `client_name` sent with dynamic client registration,
	// for servers that only accept known clients. Default: the app name.
	ClientName string `json:"clientName,omitempty"`
	// ClientRegistration is how pi identifies itself without ClientID. `dcr`
	// (default): dynamic client registration. `cimd`: pi's Client ID Metadata
	// Document on pi.dev, for authorization servers that allow pi by that URL.
	// The server must support it for public clients, and the callback must use
	// the default path `/callback`.
	ClientRegistration string `json:"clientRegistration,omitempty"`
	// AuthServerMetadataURL is an authorization server metadata document
	// (RFC 8414 or OpenID Connect discovery) to use instead of discovery
	// through the server, for servers that advertise a wrong authorization
	// server or none. The document is trusted as configured. It must use
	// https, except on loopback hosts.
	AuthServerMetadataURL string `json:"authServerMetadataUrl,omitempty"`
}

McpOAuthConfig is OAuth client settings for servers that do not support dynamic client registration.

type McpServerConfig

type McpServerConfig struct {
	// Type is "stdio" or "http"; "streamable-http" is accepted for HTTP servers.
	Type string `json:"type,omitempty"`
	// Exposure defaults to codemode.
	Exposure McpExposure `json:"exposure,omitempty"`
	// Description is what the server offers, in a sentence. The `mcp_servers`
	// system prompt section lists the server with it, tool search ranks the
	// server's tools by it, and codemode's `describeNamespace()` returns it.
	Description string `json:"description,omitempty"`
	// ToolExposure overrides Exposure for single tools. Keys are tool names as
	// the server offers them, or patterns where `*` matches any characters. An
	// exact name wins over patterns; among patterns the first match in the
	// object wins. hidden removes tools, so `"exposure": "hidden"` with overrides
	// for a few tools exposes only those.
	ToolExposure *OrderedExposures `json:"toolExposure,omitempty"`
	// Enabled set to false keeps the entry without connecting. Default: true.
	Enabled *bool `json:"enabled,omitempty"`
	// Timeout is the per-request timeout in seconds. Progress notifications from
	// the server reset it. Default: 60.
	Timeout *float64 `json:"timeout,omitempty"`

	// Stdio servers.
	Command string   `json:"command,omitempty"`
	Args    []string `json:"args,omitempty"`
	// Env values may reference environment variables (`${NAME}`) or commands (`!cmd`).
	Env *OrderedStrings `json:"env,omitempty"`
	// Cwd is relative to the session working directory.
	Cwd string `json:"cwd,omitempty"`

	// HTTP servers.
	URL string `json:"url,omitempty"`
	// Headers values may reference environment variables (`${NAME}`) or commands (`!cmd`).
	Headers *OrderedStrings `json:"headers,omitempty"`
	OAuth   *McpOAuthConfig `json:"oauth,omitempty"`
	// Auth sends the token of a pi provider instead of using OAuth. Not allowed
	// in project `mcp.json` files, and requires https except on loopback hosts.
	Auth *McpAuthConfig `json:"auth,omitempty"`
}

McpServerConfig is one server entry of the `mcpServers` shape. It is either a stdio server (Command set) or a streamable HTTP server (URL set): upstream's McpStdioServerConfig | McpHttpServerConfig union.

func ValidateMcpServerConfig

func ValidateMcpServerConfig(name string, value json.RawMessage) (McpServerConfig, string)

ValidateMcpServerConfig validates one entry of the `mcpServers` shape. It returns the config, or the message upstream's validation returns as a string.

func (McpServerConfig) IsHTTP

func (c McpServerConfig) IsHTTP() bool

IsHTTP reports whether the entry is a streamable HTTP server: upstream's `"url" in config` check.

type McpServerRegistry

type McpServerRegistry struct {
	// contains filtered or unexported fields
}

McpServerRegistry holds the servers registered by the extensions of one runtime. It is safe for concurrent use; the change listener runs after the registry's lock is released.

func NewMcpServerRegistry

func NewMcpServerRegistry() *McpServerRegistry

NewMcpServerRegistry returns an empty registry.

func (*McpServerRegistry) Get

Get returns a registered server.

func (*McpServerRegistry) List

List returns copies of the registered servers, in registration order.

func (*McpServerRegistry) Register

func (r *McpServerRegistry) Register(server RegisteredMcpServer)

Register adds or replaces a server. The caller checks ownership. A replaced server keeps its position, as a JavaScript Map does.

func (*McpServerRegistry) SetChangeListener

func (r *McpServerRegistry) SetChangeListener(listener func())

SetChangeListener sets the function called after every change. The runner sets it when it binds, to emit `mcp_servers_change`.

func (*McpServerRegistry) Unregister

func (r *McpServerRegistry) Unregister(name, extensionPath string)

Unregister removes a server registered by extensionPath. Servers of other extensions are left alone.

type McpServersChangeEvent

type McpServersChangeEvent struct {
	Type string `json:"type"`
	// Servers is every registered server after the change.
	Servers []RegisteredMcpServer `json:"servers"`
}

McpServersChangeEvent: upstream types.ts McpServersChangeEvent. Fired when an extension registers or unregisters an MCP server after the extensions are bound (see API.RegisterMcpServer). Servers registered while extensions load are read with API.GetMcpServers on session_start. Handling this event marks an extension as the one that connects registered servers.

upstream: types.ts:699-709

type MessageEndEvent

type MessageEndEvent struct {
	Type    string       `json:"type"`
	Message AgentMessage `json:"message"`
}

MessageEndEvent: upstream types.ts MessageEndEvent.

type MessageEndEventResult

type MessageEndEventResult struct {
	// Message replaces the finalized message. Replacement must preserve role.
	Message *AgentMessage `json:"message,omitempty"`
}

MessageEndEventResult mirrors upstream message_end handler result.

type MessageRenderOptions

type MessageRenderOptions struct {
	Expanded bool `json:"expanded"`
	// OutputPad is the horizontal padding configured by the outputPad setting.
	OutputPad int `json:"outputPad"`
}

MessageRenderOptions is passed to a MessageRenderer.

type MessageRenderer

type MessageRenderer = func(
	message CustomMessage,
	options MessageRenderOptions,
	theme Theme,
) Component

MessageRenderer mirrors upstream MessageRenderer<T>. Renders a custom session message into a TUI Component, or returns nil to fall back to the default renderer.

The Go signature drops the TS generic parameter T: the message's data is carried on CustomMessage (currently `any`) and the renderer type-asserts as needed. This avoids the compilation explosion of N generic instantiations across the host package and matches how subprocess extensions see this surface (untyped JSON over the wire).

type MessageStartEvent

type MessageStartEvent struct {
	Type    string       `json:"type"`
	Message AgentMessage `json:"message"`
}

MessageStartEvent: upstream types.ts MessageStartEvent.

type MessageUpdateEvent

type MessageUpdateEvent struct {
	Type                  string                `json:"type"`
	Message               AgentMessage          `json:"message"`
	AssistantMessageEvent AssistantMessageEvent `json:"assistantMessageEvent"`
}

MessageUpdateEvent: upstream types.ts MessageUpdateEvent.

type Model

type Model = any

Model mirrors @earendil-works/pi-ai Model<Api>.

type ModelRegistry

type ModelRegistry = any

ModelRegistry mirrors core/model-registry.ModelRegistry.

type ModelRoute

type ModelRoute struct {
	Model         *ai.Model
	ThinkingLevel ai.ModelThinkingLevel
	// State is the new router state, stored on the session branch unless it is the request's own state. Return the request's state or nil to keep the current state. Must be JSON. Ignored for `direct` requests.
	State json.RawMessage
}

ModelRoute is the physical model and thinking level for one request.

upstream: virtual-models.ts:75-85 (ModelRoute)

type ModelRouteFailed

type ModelRouteFailed struct {
	Model         *ai.Model
	ThinkingLevel ai.ModelThinkingLevel
	Message       ai.AssistantMessage
}

ModelRouteFailed is the failed request of a `retry`, which the request's messages no longer contain. Message carries its stop reason and error message.

type ModelRouteFunc

type ModelRouteFunc = func(ctx context.Context, request ModelRouteRequest) (ModelRoute, error)

ModelRouteFunc picks the physical model, which must have credentials, and thinking level for one request. ctx carries the request's cancellation and, for an extension's virtual model, the extension Context (FromContext).

upstream: virtual-models.ts:100 (VirtualModelDefinition.route), types.ts:1866 (ExtensionVirtualModel.route)

type ModelRoutePrevious

type ModelRoutePrevious struct {
	Model         *ai.Model
	ThinkingLevel ai.ModelThinkingLevel
}

ModelRoutePrevious is the physical model and thinking level of the latest successful response in a request's messages.

type ModelRouteReason

type ModelRouteReason string

ModelRouteReason says why a request is being routed.

  • user: first request after a message the user wrote (prompt, steering, or follow-up)
  • continuation: any other request in the agent loop, e.g. after tool results or extension messages
  • retry: automatic retry after a failed request, including after compaction for a context overflow
  • direct: a request outside the agent loop, e.g. a compaction summary or an extension call

upstream: virtual-models.ts:53 (ModelRouteReason)

const (
	ModelRouteReasonUser         ModelRouteReason = "user"
	ModelRouteReasonContinuation ModelRouteReason = "continuation"
	ModelRouteReasonRetry        ModelRouteReason = "retry"
	ModelRouteReasonDirect       ModelRouteReason = "direct"
)

The reasons of upstream's ModelRouteReason union.

type ModelRouteRequest

type ModelRouteRequest struct {
	// Model is the selected virtual model.
	Model *ai.Model
	// ThinkingLevel is the selected thinking level. Its meaning is up to the router.
	ThinkingLevel ai.ModelThinkingLevel
	Reason        ModelRouteReason
	// Previous is the physical model and thinking level of the latest successful response in Messages.
	Previous *ModelRoutePrevious
	// Failed is the failed request of a retry. Absent when the router itself failed.
	Failed *ModelRouteFailed
	// State is the router state last returned on this session branch. Absent before the first state and for `direct` requests.
	State json.RawMessage
	// Messages is the conversation for this request, including system messages.
	Messages []ai.Message
}

ModelRouteRequest is what a router sees for one request.

Go mechanic (not a divergence): upstream's `signal` is the context.Context passed to Route, and the TState of `state` is a JSON value (an absent state is nil).

upstream: virtual-models.ts:55-72 (ModelRouteRequest)

type ModelSelectEvent

type ModelSelectEvent struct {
	Type          string            `json:"type"`
	Model         Model             `json:"model"`
	PreviousModel Model             `json:"previousModel,omitempty"`
	Source        ModelSelectSource `json:"source"`
}

ModelSelectEvent: upstream types.ts ModelSelectEvent.

type ModelSelectSource

type ModelSelectSource = string

ModelSelectSource mirrors upstream "set" | "cycle" | "restore".

const (
	ModelSelectSourceUser    ModelSelectSource = "set"
	ModelSelectSourceCycle   ModelSelectSource = "cycle"
	ModelSelectSourceRestore ModelSelectSource = "restore"
)

type ModelStreamRequest

type ModelStreamRequest struct {
	API              bool
	Fetch            *http.Client
	OnPayload        func(any, *ai.Model) (any, error)
	OnResponse       func(context.Context, ai.ProviderResponse, *ai.Model) error
	TransformHeaders func(context.Context, ai.ProviderHeaders) (ai.ProviderHeaders, error)
}

ModelStreamRequest carries a resolved API-leaf request and connection-owned callbacks. API leaves use the caller's model/auth, not the parent catalog.

func ModelStreamRequestFromContext

func ModelStreamRequestFromContext(ctx context.Context) ModelStreamRequest

ModelStreamRequestFromContext returns the transport contract for this operation.

type NativeProvider

type NativeProvider struct {
	// IsCurrent guards publication when host registrations overlap across connections.
	IsCurrent                func() bool
	ID                       string
	Name                     string
	BaseURL                  string
	Models                   []ProviderModelConfig
	CheckAuth                func(context.Context, *ai.Credential) (*ai.AuthCheck, error)
	FilterModels             func(context.Context, []ProviderModelConfig, *ai.Credential) ([]ProviderModelConfig, error)
	ResolveAuth              func(context.Context, *ai.Credential, ai.AuthResolutionOverrides) (*ai.AuthResult, *ai.Credential, error)
	ResolveRefreshCredential func(context.Context, *ai.Credential) (*ai.Credential, *ai.Credential, error)
	RefreshModels            func(context.Context, *ai.Credential, *ai.ModelsStoreEntry, bool, *bool, func(NativeProviderPublication) error) ([]ProviderModelConfig, error)
	Stream                   func(context.Context, *ai.Model, ai.TranscriptContext, ai.StreamOptions, bool) (*ai.AssistantMessageEventStream, error)
	// GenerateImages and Classify are the provider object's image and classifier operations; nil when it has none.
	// upstream: pi-ai Provider.generateImages, Provider.classify
	GenerateImages func(context.Context, *ai.ImageModel, ai.ImagesContext, ai.ImagesOptions) (ai.AssistantImages, error)
	Classify       func(context.Context, *ai.ClassifierModel, ai.ClassifierContext, ai.ClassifierOptions) (ai.ClassifierResult, error)
}

NativeProvider is a session-owned carrier for Pi's native Provider callbacks. Metadata is immutable; refresh publishes replacement model snapshots. The host owns credentials and persistence, and every callback receives its operation context.

type NativeProviderPublication

type NativeProviderPublication struct {
	Persist json.RawMessage        `json:"persist,omitempty"`
	Models  *[]ProviderModelConfig `json:"models,omitempty"`
}
type NavigateTreeOptions struct {
	Summarize           bool   `json:"summarize,omitempty"`
	CustomInstructions  string `json:"customInstructions,omitempty"`
	ReplaceInstructions bool   `json:"replaceInstructions,omitempty"`
	Label               string `json:"label,omitempty"`
}

NavigateTreeOptions mirrors upstream's navigateTree options.

upstream: types.ts:347-351

type NewSessionOptions

type NewSessionOptions struct {
	ParentSession string                              `json:"parentSession,omitempty"`
	Setup         func(SessionManager) error          `json:"-"`
	WithSession   func(*ReplacedSessionContext) error `json:"-"`
}

NewSessionOptions mirrors upstream's newSession parameter object.

upstream: types.ts:334-338 (ExtensionCommandContext.newSession options)

type OAuthCredentials

type OAuthCredentials = any

OAuthCredentials mirrors @earendil-works/pi-ai OAuthCredentials.

type OAuthLoginCallbacks

type OAuthLoginCallbacks = any

OAuthLoginCallbacks mirrors @earendil-works/pi-ai OAuthLoginCallbacks.

type OrderedExposures

type OrderedExposures struct {
	// contains filtered or unexported fields
}

OrderedExposures is a map of tool names or patterns to exposures that keeps its JSON key order: among patterns the first match wins.

func NewOrderedExposures

func NewOrderedExposures(pairs ...string) *OrderedExposures

NewOrderedExposures builds the map from alternating patterns and exposures.

func (*OrderedExposures) Get

func (e *OrderedExposures) Get(key string) (McpExposure, bool)

Get returns the exposure of a key.

func (*OrderedExposures) Keys

func (e *OrderedExposures) Keys() []string

Keys returns the patterns in order.

func (OrderedExposures) MarshalJSON

func (e OrderedExposures) MarshalJSON() ([]byte, error)

MarshalJSON writes the keys in order.

func (*OrderedExposures) UnmarshalJSON

func (e *OrderedExposures) UnmarshalJSON(data []byte) error

UnmarshalJSON reads an object; validation of the values is ValidateMcpServerConfig's.

type OrderedStrings

type OrderedStrings struct {
	// contains filtered or unexported fields
}

OrderedStrings is a string map that keeps its JSON key order, as a JavaScript object does.

func NewOrderedStrings

func NewOrderedStrings(pairs ...string) *OrderedStrings

NewOrderedStrings builds the map from alternating keys and values.

func (*OrderedStrings) Get

func (s *OrderedStrings) Get(key string) (string, bool)

Get returns the value of key.

func (*OrderedStrings) Keys

func (s *OrderedStrings) Keys() []string

Keys returns the keys in order.

func (OrderedStrings) MarshalJSON

func (s OrderedStrings) MarshalJSON() ([]byte, error)

MarshalJSON writes the keys in order.

func (*OrderedStrings) UnmarshalJSON

func (s *OrderedStrings) UnmarshalJSON(data []byte) error

UnmarshalJSON reads an object of strings.

type OverlayHandle

type OverlayHandle = any

OverlayHandle mirrors @earendil-works/pi-tui OverlayHandle.

type OverlayLayout

type OverlayLayout struct {
	Width        *OverlaySizeValue   `json:"width,omitempty"`
	MinWidth     *int                `json:"minWidth,omitempty"`
	MaxHeight    *OverlaySizeValue   `json:"maxHeight,omitempty"`
	Anchor       string              `json:"anchor,omitempty"`
	OffsetX      int                 `json:"offsetX,omitempty"`
	OffsetY      int                 `json:"offsetY,omitempty"`
	Row          *OverlaySizeValue   `json:"row,omitempty"`
	Col          *OverlaySizeValue   `json:"col,omitempty"`
	Margin       *OverlayMarginValue `json:"margin,omitempty"`
	NonCapturing bool                `json:"nonCapturing,omitempty"`
}

OverlayLayout is the serialisable subset of upstream pi-tui OverlayOptions: every field except the visible callback.

type OverlayMarginValue

type OverlayMarginValue struct {
	All                      *int
	Top, Right, Bottom, Left int
}

OverlayMarginValue is upstream `OverlayMargin | number`.

func (OverlayMarginValue) MarshalJSON

func (m OverlayMarginValue) MarshalJSON() ([]byte, error)

func (*OverlayMarginValue) UnmarshalJSON

func (m *OverlayMarginValue) UnmarshalJSON(data []byte) error

type OverlayOptions

type OverlayOptions = any

OverlayOptions mirrors @earendil-works/pi-tui OverlayOptions.

type OverlaySizeValue

type OverlaySizeValue struct {
	Value   float64
	Percent bool
	Invalid bool
}

OverlaySizeValue is upstream SizeValue: a cell count or an "N%" string. A string that is not a percentage is kept with Invalid set, matching upstream parseSizeValue returning undefined.

func (OverlaySizeValue) MarshalJSON

func (v OverlaySizeValue) MarshalJSON() ([]byte, error)

func (*OverlaySizeValue) UnmarshalJSON

func (v *OverlaySizeValue) UnmarshalJSON(data []byte) error

type PendingProviderRegistration

type PendingProviderRegistration struct {
	Name          string
	Config        ProviderConfig
	ExtensionPath string
}

PendingProviderRegistration retains the configuration and its owning extension until the registry is bound.

type PendingVirtualModelRegistration

type PendingVirtualModelRegistration struct {
	Definition    VirtualModelDefinition
	ExtensionPath string
}

PendingVirtualModelRegistration retains a virtual model and its owning extension until the runner binds.

upstream: types.ts:2097 (pendingVirtualModelRegistrations)

type PowerShellToolCallEvent

type PowerShellToolCallEvent struct {
	ToolCallEventBase
	ToolName string              `json:"toolName"` // "powershell"
	Input    PowerShellToolInput `json:"input"`
}

PowerShellToolCallEvent: upstream types.ts PowerShellToolCallEvent.

type PowerShellToolDetails

type PowerShellToolDetails = BashToolDetails

PowerShellToolDetails is the bash details shape (upstream powershell.ts).

type PowerShellToolInput

type PowerShellToolInput = BashToolInput

PowerShellToolInput is the bash input shape (upstream powershell.ts).

type PowerShellToolResultEvent

type PowerShellToolResultEvent struct {
	ToolResultEventBase
	ToolName string                 `json:"toolName"` // "powershell"
	Details  *PowerShellToolDetails `json:"details,omitempty"`
}

PowerShellToolResultEvent: upstream types.ts PowerShellToolResultEvent.

func (PowerShellToolResultEvent) MarshalJSON

func (e PowerShellToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type ProjectTrustEvent

type ProjectTrustEvent struct {
	Type string `json:"type"` // "project_trust"
	Cwd  string `json:"cwd"`
}

ProjectTrustEvent: upstream types.ts ProjectTrustEvent. Fired before project-local inputs load so a global/CLI extension can decide trust.

type ProjectTrustEventDecision

type ProjectTrustEventDecision string

ProjectTrustEventDecision is an extension's trust verdict for a project. Values: "yes" | "no" | "undecided". Mirrors upstream ProjectTrustEventDecision.

const (
	ProjectTrustYes       ProjectTrustEventDecision = "yes"
	ProjectTrustNo        ProjectTrustEventDecision = "no"
	ProjectTrustUndecided ProjectTrustEventDecision = "undecided"
)

type ProjectTrustEventResult

type ProjectTrustEventResult struct {
	Trusted  ProjectTrustEventDecision `json:"trusted"`
	Remember *bool                     `json:"remember,omitempty"`
}

ProjectTrustEventResult: upstream types.ts ProjectTrustEventResult. The first handler returning yes/no wins; undecided falls through.

type ProjectedSessionEntry

type ProjectedSessionEntry struct {
	SourceEntry any            `json:"sourceEntry"`
	Messages    []AgentMessage `json:"messages"`
}

ProjectedSessionEntry is one boundary preview entry and its model-visible messages.

type ProviderActions

type ProviderActions struct {
	RegisterProvider   func(name string, config ProviderConfig) error
	UnregisterProvider func(name string)
	// RegisterVirtualModel and UnregisterVirtualModel apply virtual-model registrations; the model registry's own ones apply when unset.
	// upstream: runner.ts:413-417 (providerActions.registerVirtualModel, unregisterVirtualModel)
	RegisterVirtualModel   func(definition VirtualModelDefinition) error
	UnregisterVirtualModel func(provider, id string)
}

ProviderActions supplies synchronous provider registration callbacks. Registration errors are reported per queued entry during binding and returned directly for post-bind calls. upstream: packages/coding-agent/src/core/extensions/runner.ts:bindCore

type ProviderConfig

type ProviderConfig struct {
	Name         string               `json:"name,omitempty"`
	BaseURL      string               `json:"baseUrl,omitempty"`
	APIKey       string               `json:"apiKey,omitempty"`
	API          ai.API               `json:"api,omitempty"`
	StreamSimple ProviderStreamSimple `json:"-"`
	// Images are the image-generation implementations keyed by image API.
	// upstream: types.ts:1896 (ProviderConfig.images)
	Images map[ai.ImageAPI]*ai.ProviderImages `json:"-"`
	// Classifiers are the classifier implementations keyed by classifier API.
	// upstream: types.ts:1898 (ProviderConfig.classifiers)
	Classifiers map[ai.ClassifierAPI]*ai.ProviderClassifier `json:"-"`
	Headers     map[string]string                           `json:"headers,omitempty"`

	AuthHeader bool                  `json:"authHeader,omitempty"`
	Models     []ProviderModelConfig `json:"models,omitempty"`
	OAuth      *ProviderOAuth        `json:"oauth,omitempty"`
	// Insecure skips TLS certificate verification for this provider's
	// endpoint. Opt-in only, for self-signed/internal-CA on-prem gateways.
	// pig additive (D36): additive optional field; no upstream per-provider TLS-skip.
	Insecure bool `json:"insecure,omitempty"`
	// contains filtered or unexported fields
}

ProviderConfig is the registration payload for API.RegisterProvider. Mirrors upstream's ProviderConfig 1:1.

Field semantics (from upstream JSDoc):

  • If Models is provided: replaces all existing models for this provider.
  • If only BaseURL is provided: overrides the URL for existing models.
  • If OAuth is provided: registers OAuth provider for /login support.
  • If StreamSimple is provided: registers a custom API stream handler.

func (ProviderConfig) MarshalJSON

func (config ProviderConfig) MarshalJSON() ([]byte, error)

func (*ProviderConfig) UnmarshalJSON

func (config *ProviderConfig) UnmarshalJSON(data []byte) error

type ProviderHeaders

type ProviderHeaders = map[string]*string

ProviderHeaders mirrors upstream pi-ai ProviderHeaders (`Record<string, string | null>`): a nil value signals "delete this header".

type ProviderModelConfig

type ProviderModelConfig struct {
	ID   string `json:"id"`
	Name string `json:"name"`
	// Type is "chat", "image" or "classifier". Empty is "chat".
	// upstream: types.ts:1953-1976 (type)
	Type ai.ModelType `json:"type,omitempty"`
	// API is a chat API, or for an image or classifier entry the image or classifier API id.
	API ai.API `json:"api,omitempty"`
	// Output is the output types of an image entry: it always includes "image"; "text" means the model can also return text blocks.
	// upstream: types.ts:1969 (ProviderImageModelConfig.output)
	Output           []string            `json:"output,omitempty"`
	BaseURL          string              `json:"baseUrl,omitempty"`
	Reasoning        bool                `json:"reasoning"`
	ThinkingLevelMap ai.ThinkingLevelMap `json:"thinkingLevelMap,omitempty"`
	Input            []string            `json:"input"`
	// InputLimits is upstream's provider input limits and cache-safe image
	// preprocessing metadata.
	InputLimits *ai.ModelInputLimits `json:"inputLimits,omitempty"`
	Cost        ProviderModelCost    `json:"cost"`
	// PromptCache is upstream's best-effort prompt cache lifetime in seconds
	// per retention tier.
	PromptCache    ai.ModelPromptCache `json:"promptCache,omitempty"`
	SamplingParams map[string]any      `json:"samplingParams,omitempty"`
	// SamplingParamsByThinkingLevel overrides SamplingParams for the effective Pi thinking level of a chat entry.
	// upstream: packages/coding-agent/src/core/provider-composer.ts:72 (ProviderChatModelConfig.samplingParamsByThinkingLevel), carried by extensionModelFromDefinition's spread.
	SamplingParamsByThinkingLevel ai.SamplingParamsByThinkingLevel `json:"samplingParamsByThinkingLevel,omitempty"`
	ContextWindow                 int                              `json:"contextWindow"`
	MaxTokens                     int                              `json:"maxTokens"`
	Headers                       map[string]string                `json:"headers,omitempty"`

	Compat any `json:"compat,omitempty"`
	// contains filtered or unexported fields
}

ProviderModelConfig mirrors upstream ProviderModelConfig, the union of ProviderChatModelConfig, ProviderImageModelConfig and ProviderClassifierModelConfig (types.ts:1929-1991).

Go mechanic (not a divergence): one struct carries the discriminator and the fields of all three variants, so an entry round-trips through the extension wire and the registries unchanged. Type omitted is normalized to "chat". A chat entry uses ID, Name, API, BaseURL, Reasoning, ThinkingLevelMap, Input, InputLimits, Cost, PromptCache, SamplingParams, SamplingParamsByThinkingLevel, ContextWindow, MaxTokens, Headers and Compat. An image entry uses ID, Name, API (an image API), BaseURL, Input, InputLimits, Cost, Headers and Output. A classifier entry uses ID, Name, API (a classifier API), BaseURL, Input, InputLimits, Cost, Headers and ContextWindow. A field outside its variant is not marshalled.

func (ProviderModelConfig) MarshalJSON

func (config ProviderModelConfig) MarshalJSON() ([]byte, error)

func (*ProviderModelConfig) UnmarshalJSON

func (config *ProviderModelConfig) UnmarshalJSON(data []byte) error

type ProviderModelCost

type ProviderModelCost struct {
	Input      float64       `json:"input"`
	Output     float64       `json:"output"`
	CacheRead  float64       `json:"cacheRead"`
	CacheWrite float64       `json:"cacheWrite"`
	Tiers      []ai.CostTier `json:"tiers,omitzero"`
}

ProviderModelCost mirrors upstream ProviderModelConfig.cost.

type ProviderOAuth

type ProviderOAuth struct {
	Name string `json:"name"`
	// IsSubscription marks access through this OAuth method as subscription-backed.
	IsSubscription bool                                                          `json:"isSubscription,omitempty"`
	Login          func(callbacks OAuthLoginCallbacks) (OAuthCredentials, error) `json:"-"`
	RefreshToken   func(creds OAuthCredentials) (OAuthCredentials, error)        `json:"-"`
	GetAPIKey      func(creds OAuthCredentials) string                           `json:"-"`
	ModifyModels   func(models []Model, creds OAuthCredentials) []Model          `json:"-"`
}

ProviderOAuth mirrors upstream ProviderConfig.oauth.

type ProviderStreamEvent

type ProviderStreamEvent struct {
	Type     string `json:"type"`
	Provider string `json:"provider"`
	API      string `json:"api"`
	Model    string `json:"model"`
	Data     any    `json:"data"`
}

ProviderStreamEvent: upstream types.ts ProviderStreamEvent. Fired for a parsed provider stream event before it is normalized. Data is adapter-owned and read-only.

upstream: types.ts:884-890

type ProviderStreamSimple

type ProviderStreamSimple = func(model Model, ctx AIContext, opts SimpleStreamOptions) AssistantMessageEventStream

ProviderStreamSimple mirrors upstream's optional streamSimple callback. The callback's model, request context, options, and event stream remain opaque at this dynamic extension boundary.

type ReadToolCallEvent

type ReadToolCallEvent struct {
	ToolCallEventBase
	ToolName string        `json:"toolName"` // "read"
	Input    ReadToolInput `json:"input"`
}

ReadToolCallEvent: upstream types.ts ReadToolCallEvent.

type ReadToolDetails

type ReadToolDetails struct {
	Truncation *ToolTruncation `json:"truncation,omitempty"`
}

ReadToolDetails mirrors upstream read.ts:28. Attached only when output was truncated (or the first line exceeded the byte limit).

type ReadToolInput

type ReadToolInput = any

type ReadToolResultEvent

type ReadToolResultEvent struct {
	ToolResultEventBase
	ToolName string           `json:"toolName"` // "read"
	Details  *ReadToolDetails `json:"details,omitempty"`
}

ReadToolResultEvent: upstream types.ts ReadToolResultEvent.

func (ReadToolResultEvent) MarshalJSON

func (e ReadToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

type ReadonlyFooterDataProvider

type ReadonlyFooterDataProvider = any

ReadonlyFooterDataProvider mirrors core/footer-data-provider.

type ReadonlySessionManager

type ReadonlySessionManager = any

ReadonlySessionManager mirrors core/session-manager ReadonlySessionManager.

type RegisteredCommand

type RegisteredCommand struct {
	Name                   string                  `json:"name"`
	SourceInfo             SourceInfo              `json:"sourceInfo"`
	Description            string                  `json:"description,omitempty"`
	GetArgumentCompletions ArgumentCompletionsFunc `json:"-"`
	Handler                CommandHandler          `json:"-"`
}

RegisteredCommand mirrors upstream RegisteredCommand. The host's view of a command after registration.

type RegisteredMcpServer

type RegisteredMcpServer struct {
	Name   string          `json:"name"`
	Config McpServerConfig `json:"config"`
	// Declared is the config as the extension wrote it with its exposure aliases resolved, JSON.stringify(JSON.parse(text)): every member, known or not, in the order written, the way a JavaScript object holds them. Extensions read it back through getMcpServers, so the wire carries it in place of Config, which holds the members the host uses. Empty for a server registered with a typed Config alone.
	// upstream: mcp-servers.ts:151-166,192-222 (validateMcpServerConfig returns the alias-resolved copy of the object it was given), 283 (list copies it with structuredClone)
	Declared json.RawMessage `json:"-"`
	// ExtensionPath is the path of the extension that registered the server.
	ExtensionPath string `json:"extensionPath"`
}

RegisteredMcpServer is a server an extension registered with `pi.registerMcpServer()`.

func (RegisteredMcpServer) MarshalJSON

func (s RegisteredMcpServer) MarshalJSON() ([]byte, error)

MarshalJSON writes the server as getMcpServers returns it: name, config, extensionPath, with the config as declared.

type RegisteredTool

type RegisteredTool struct {
	Definition ToolDefinition `json:"definition"`
	SourceInfo SourceInfo     `json:"sourceInfo"`
}

RegisteredTool mirrors upstream RegisteredTool: the host's bookkeeping after a tool is registered.

type RemoteEditor

type RemoteEditor interface {
	// Input delivers one keystroke to the editor's handleInput.
	Input(data string)
	// SetText, InsertTextAtCursor and AddToHistory call the editor's
	// methods of the same name, as Pi's host calls them on this.editor.
	SetText(text string)
	InsertTextAtCursor(text string)
	AddToHistory(text string)
	// Mouse delivers a left click on the editor rows to the editor's
	// handleMouse, as Pi's fullscreen renderer does.
	Mouse(event RemoteEditorMouseEvent)
	// Configure applies host editor state to the editor: Pi copies the
	// default editor's text, padding and autocomplete size when it installs
	// the editor, and the TUI sets its focus.
	Configure(config RemoteEditorConfig)
	// EmbedWorkingStatus reports whether this editor wants status in its border.
	EmbedWorkingStatus() bool
	// Bind attaches the host that receives the editor's frames and
	// callbacks. Events that arrive before Bind are delivered on binding.
	Bind(host RemoteEditorHost)
	// Close detaches the editor from the host.
	Close()
}

RemoteEditor is an editor an extension installed with ctx.ui.setEditorComponent, running in the extension's process. Pi puts the factory's editor (typically a CustomEditor subclass) in place of its own: every keystroke goes to that editor's handleInput, its render output is the editor on screen, and Pi wires the editor's callbacks to its own handlers. The host does the same across the process boundary: it hands the editor every keystroke and every text change it makes, shows the editor's frames, and receives the editor's callbacks through the bound RemoteEditorHost.

UIContext.SetEditorComponent receives a RemoteEditor; nil restores the host's own editor.

type RemoteEditorAction

type RemoteEditorAction struct {
	Action   string `json:"action"`
	Text     string `json:"text"`
	Expanded string `json:"expanded"`
	Local    bool   `json:"local"`
}

RemoteEditorAction snapshots the editor at the app-action boundary. Local means the component already applied the synchronous editor mutations; the host must not replay them into that component.

type RemoteEditorConfig

type RemoteEditorConfig struct {
	PaddingX               int  `json:"paddingX"`
	AutocompleteMaxVisible int  `json:"autocompleteMaxVisible"`
	Focused                bool `json:"focused"`
	// ThinkingLevel is the session's thinking level, whose border color Pi
	// gives the editor outside bash mode.
	ThinkingLevel string `json:"thinkingLevel"`
	// ShowHardwareCursor is the TUI's hardware-cursor setting, which the
	// editor's tui.getShowHardwareCursor() reports.
	ShowHardwareCursor bool `json:"showHardwareCursor"`
	// Shortcuts are the key ids of the extension shortcuts Pi's
	// onExtensionShortcut runs from inside the editor.
	Shortcuts        []string `json:"shortcuts"`
	Streaming        bool     `json:"streaming"`
	Compacting       bool     `json:"compacting"`
	BashRunning      bool     `json:"bashRunning"`
	InterruptHandled bool     `json:"interruptHandled"`
	// WorkingStatus is the current border status; nil clears it.
	WorkingStatus *RemoteEditorStatus `json:"workingStatus"`
}

RemoteEditorConfig is the host editor state an RemoteEditor mirrors.

type RemoteEditorHost

type RemoteEditorHost interface {
	// EditorFrame is the editor's render(width) output for the terminal
	// width. WantsKeyRelease is the editor's wantsKeyRelease flag.
	EditorFrame(lines []string, width int, wantsKeyRelease bool)
	// EditorChanged is the editor's onChange: its text and, for the host's
	// getEditorText, the text with paste markers expanded.
	EditorChanged(text, expanded string)
	// EditorSubmit is the editor's onSubmit. done runs once the host has
	// handled the submission, which settles the promise onSubmit returns.
	EditorSubmit(text string, done func())
	// EditorAction runs Pi's handler for an app action the editor
	// dispatched: app.interrupt (onEscape), app.exit (onCtrlD),
	// app.clipboard.pasteImage (onPasteImage), or an actionHandlers entry.
	EditorAction(action RemoteEditorAction)
	// EditorInputDone releases input backpressure after the key's callbacks have reached the host.
	EditorInputDone()
	// EditorShortcut runs the extension shortcut the editor's
	// onExtensionShortcut matched for data.
	EditorShortcut(data string)
	// TerminalWrite writes raw output to the terminal (tui.terminal.write).
	TerminalWrite(data string)
	// SetShowHardwareCursor is tui.setShowHardwareCursor.
	SetShowHardwareCursor(enabled bool)
	// EditorClosed reports that the extension's editor is gone (its process
	// ended); the host restores its own editor.
	EditorClosed()
}

RemoteEditorHost receives an RemoteEditor's output. The bridge calls it off the host's UI loop, in the order the extension produced the events.

type RemoteEditorMouseEvent

type RemoteEditorMouseEvent struct {
	Type       string `json:"type"`
	Button     string `json:"button"`
	X          int    `json:"x"`
	Y          int    `json:"y"`
	ScreenX    int    `json:"screenX"`
	ScreenY    int    `json:"screenY"`
	Width      int    `json:"width"`
	Height     int    `json:"height"`
	Shift      bool   `json:"shift"`
	Alt        bool   `json:"alt"`
	Ctrl       bool   `json:"ctrl"`
	ClickCount int    `json:"clickCount,omitempty"`
}

RemoteEditorMouseEvent is pi-tui's TuiMouseEvent, with the row relative to the editor's first row.

type RemoteEditorStatus

type RemoteEditorStatus struct {
	Kind              string   `json:"kind"`
	Message           string   `json:"message"`
	Frames            []string `json:"frames"`
	Frame             int      `json:"frame"`
	SpinnerColor      string   `json:"spinnerColor"`
	MessageColor      string   `json:"messageColor"`
	IndicatorVerbatim bool     `json:"indicatorVerbatim"`
}

RemoteEditorStatus is a border-status snapshot. pig divergence (D94): the host advances the animation and sends snapshots; Pi's editor-side indicator runs its own timer.

type RemoteOverlayBounds

type RemoteOverlayBounds struct {
	Row    int `json:"row"`
	Col    int `json:"col"`
	Width  int `json:"width"`
	Height int `json:"height"`
}

RemoteOverlayBounds is the last rendered terminal-relative rectangle.

type RemoteOverlayFocusTarget

type RemoteOverlayFocusTarget struct {
	Overlay any
	Editor  bool
}

RemoteOverlayFocusTarget is an explicit OverlayHandle.unfocus target resolved by the host. The zero value is Pi's null target. Overlay is another mounted overlay of the same extension, as the host registered it; Editor selects the main editor component.

type RemoteOverlayHandle

type RemoteOverlayHandle interface {
	// UpdateLines replaces the overlay's cached lines and triggers
	// a TUI render. Safe to call from any goroutine.
	UpdateLines(lines []string)
	// Close signals that the overlay is finished and unblocks the
	// originating [UIContext.RunRemoteOverlay] call with the given
	// result value. Safe to call from any goroutine.
	Close(result any)
}

RemoteOverlayHandle is returned to the caller of UIContext.RunRemoteOverlay so it can push rendered lines into the overlay and close it when the remote producer signals completion.

pig-specific: no upstream equivalent.

type RemoteOverlayHost

type RemoteOverlayHost interface {
	// OnInput is invoked for every input chunk (a single key event
	// after [tui.ReadInput] segmentation) while the overlay is
	// open. Called from the input-reading goroutine.
	OnInput(data string)
}

RemoteOverlayHost is the callback surface the bridge provides so the overlay can forward user input back to the remote producer.

pig-specific: no upstream equivalent.

type RemoteOverlayOptions

type RemoteOverlayOptions struct {
	// Title is the overlay's titlebar text. Empty hides the bar.
	Title string `json:"title,omitempty"`
	// WidthFraction is the fraction of terminal width the overlay
	// should occupy. Zero falls back to the overlay default.
	WidthFraction float64 `json:"widthFraction,omitempty"`
	// HeightFraction is the fraction of terminal height the
	// overlay should occupy. Zero falls back to the overlay default.
	HeightFraction float64 `json:"heightFraction,omitempty"`
	// Overlay opens a floating viewport overlay over the whole screen
	// instead of replacing the inline editor slot. Mirrors upstream
	// ui.custom()'s `overlay: true`. When false the component replaces
	// the editor slot.
	Overlay bool `json:"overlay,omitempty"`
	// Layout carries upstream ui.custom()'s overlayOptions (the pi-tui
	// OverlayOptions fields that can cross a process boundary). When set, or
	// when no legacy Title/fractions are given, an overlay is mounted
	// component-framed with exactly upstream's showOverlay geometry.
	Layout *OverlayLayout `json:"overlayOptions,omitempty"`
}

RemoteOverlayOptions controls how a remote (subprocess-backed) overlay is positioned and sized when the host opens it.

Upstream's `ui.custom()` takes an `overlay` boolean plus an `OverlayOptions` value. The OverlayOptions reference TUI primitives that cannot cross a process boundary, so the subprocess bridge ports the overlay flag and the size/position fields into this serialisable struct.

type RemoteOverlayState

type RemoteOverlayState struct {
	Hidden  bool                 `json:"hidden"`
	Focused bool                 `json:"focused"`
	Visible bool                 `json:"visible"`
	Bounds  *RemoteOverlayBounds `json:"bounds,omitempty"`
}

RemoteOverlayState is the host's mounted-overlay state at a control/input boundary.

type RemoteTerminalInputHandler

type RemoteTerminalInputHandler = func(ctx context.Context, data string) TerminalInputResult

RemoteTerminalInputHandler asks a terminal-input listener that runs in another process for its verdict on one chunk. It blocks until the verdict arrives, the connection fails, or ctx ends. A failure returns the zero result, which leaves the input unchanged.

pig additive (D19): upstream's TerminalInputHandler answers synchronously in process. A subprocess listener's answer crosses a socket, so the host calls this off its input loop.

type ReplacedSessionContext

type ReplacedSessionContext struct {
	*CommandContext
	// contains filtered or unexported fields
}

ReplacedSessionContext is the fresh command-capable context supplied after Session replacement and host rebinding. Its message methods await the Session operation rather than launching extension-owned background work.

func NewReplacedSessionContext

func NewReplacedSessionContext(command *CommandContext, sendMessage func(CustomMessageRef, *SendMessageOptions) error, sendUserMessage func(any, *ReplacedSessionSendUserMessageOptions) error) *ReplacedSessionContext

NewReplacedSessionContext binds the replacement Session's direct, awaited message operations to its command context.

func (*ReplacedSessionContext) SendMessage

func (c *ReplacedSessionContext) SendMessage(message CustomMessageRef, options *SendMessageOptions) error

SendMessage awaits custom-message persistence and any triggered turn.

func (*ReplacedSessionContext) SendUserMessage

func (c *ReplacedSessionContext) SendUserMessage(content any, options *ReplacedSessionSendUserMessageOptions) error

SendUserMessage awaits input handling and the selected prompt or queue operation.

type ReplacedSessionSendUserMessageOptions

type ReplacedSessionSendUserMessageOptions = SendUserMessageOptions

ReplacedSessionSendUserMessageOptions controls the awaited user-message operation on a replacement context. Template and command expansion default to false.

type ResolvedCommand

type ResolvedCommand struct {
	RegisteredCommand
	InvocationName string `json:"invocationName"`
}

ResolvedCommand mirrors upstream ResolvedCommand: RegisteredCommand plus the name under which it was actually invoked (which can differ from Name when the command exposes aliases).

type ResourceCollision

type ResourceCollision struct {
	ResourceType string `json:"resourceType"`
	Name         string `json:"name"`
	WinnerPath   string `json:"winnerPath"`
	LoserPath    string `json:"loserPath"`
	WinnerSource string `json:"winnerSource,omitempty"`
	LoserSource  string `json:"loserSource,omitempty"`
}

ResourceDiagnostic is the resolution-time warning/error/collision payload surfaced by the runner when extension resources (commands, shortcuts, flags, future: skills/prompts/themes) collide or fail to resolve cleanly.

upstream: core/diagnostics.ts:10-16 (export interface ResourceDiagnostic)

Final-home note. Upstream lives in `core/diagnostics.ts` because the type is shared between the extension runner and the resource loader (skills/prompts/themes). Until pig ports `core/resource-loader.ts` the type lives here in `coding/extension` to keep the dependency graph minimal. When that port lands, the canonical declaration moves to `coding/diagnostics/` and this declaration becomes a type alias for backward compatibility.

type ResourceDiagnostic

type ResourceDiagnostic struct {
	// Type is one of "warning", "error", "collision". Mirrors the
	// upstream literal union. Not enforced by the Go type system -
	// callers are expected to use the constants below.
	Type string `json:"type"`

	// Message is the human-readable diagnostic text. Format matches
	// upstream verbatim where the diagnostic is user-visible (e.g.
	// shortcut/command collision strings) so no fidelity drift in
	// diagnostic UIs.
	Message string `json:"message"`

	// Path is the extension's resolvedPath for attribution. Optional;
	// upstream uses `path?: string`.
	Path string `json:"path,omitempty"`

	// Collision carries structured details when Type == "collision".
	// upstream: ResourceCollision in core/diagnostics.ts.
	Collision *ResourceCollision `json:"collision,omitempty"`
}

type ResourcesDiscoverAggregateResult

type ResourcesDiscoverAggregateResult struct {
	SkillPaths  []AttributedResourcePath `json:"skillPaths"`
	PromptPaths []AttributedResourcePath `json:"promptPaths"`
	ThemePaths  []AttributedResourcePath `json:"themePaths"`
}

ResourcesDiscoverAggregateResult is the combined output of all resources_discover handlers, with each path attributed to its source extension.

upstream: anonymous return type at runner.ts:944-948

type ResourcesDiscoverEvent

type ResourcesDiscoverEvent struct {
	Type   string `json:"type"`
	Cwd    string `json:"cwd"`
	Reason string `json:"reason"` // "startup" | "reload"
}

ResourcesDiscoverEvent: upstream types.ts ResourcesDiscoverEvent. Fired after session_start to allow extensions to provide additional resource paths.

type ResourcesDiscoverResult

type ResourcesDiscoverResult struct {
	SkillPaths  []string `json:"skillPaths,omitempty"`
	PromptPaths []string `json:"promptPaths,omitempty"`
	ThemePaths  []string `json:"themePaths,omitempty"`
}

ResourcesDiscoverResult: upstream types.ts ResourcesDiscoverResult.

type ScopedModel

type ScopedModel struct {
	Model         *ai.Model
	ThinkingLevel ai.ThinkingLevel
}

Ports packages/coding-agent/src/core/model-resolver.ts. ScopedModel is a resolved member of the session's model scope. An absent thinking level supplies no per-scope override when cycling.

type SendMessageOptions

type SendMessageOptions struct {
	TriggerTurn *bool     `json:"triggerTurn,omitempty"`
	DeliverAs   DeliverAs `json:"deliverAs,omitempty"`
}

SendMessageOptions mirrors the inline options object on sendMessage.

upstream: types.ts:1161–1162

type SendMessagePayload

type SendMessagePayload struct {
	CustomType string `json:"customType"`
	// Content preserves upstream CustomMessage content across the dynamic
	// extension boundary.
	Content any `json:"content,omitempty"`
	Display any `json:"display,omitempty"`
	Details any `json:"details,omitempty"`
}

SendMessagePayload mirrors the inline `Pick<CustomMessage<T>, "customType" | "content" | "display" | "details">` parameter on upstream's sendMessage.

upstream: types.ts:1159–1163

func (*SendMessagePayload) UnmarshalJSON

func (p *SendMessagePayload) UnmarshalJSON(data []byte) error

UnmarshalJSON keeps the member order of the `details` object the extension wrote.

type SendUserMessageHandler

type SendUserMessageHandler func(content any, options *SendUserMessageOptions) error

SendUserMessageHandler injects a user message into the agent loop. content is upstream's `string | (TextContent | ImageContent)[]` union; current in-process callers use strings, while unsupported content shapes should fail at the host boundary.

upstream: types.ts:1525-1528 Go returns error so hosts can surface invalid content/delivery modes loudly instead of dropping extension calls on the floor.

type SendUserMessageOptions

type SendUserMessageOptions struct {
	DeliverAs             DeliverAs `json:"deliverAs,omitempty"`
	ExpandPromptTemplates *bool     `json:"expandPromptTemplates,omitempty"`
}

SendUserMessageOptions mirrors the inline options object on sendUserMessage. Note upstream restricts DeliverAs to {steer, followUp}; the type is shared, but DeliverAsNextTurn is invalid here and the host rejects it at runtime.

upstream: types.ts:1170–1171

type SessionBeforeCompactEvent

type SessionBeforeCompactEvent struct {
	Type               string                `json:"type"`
	Preparation        CompactionPreparation `json:"preparation"`
	BranchEntries      []SessionEntry        `json:"branchEntries"`
	CustomInstructions string                `json:"customInstructions,omitempty"`
	// reason/willRetry adopted upstream in 0.80.3.
	Reason    string          `json:"reason"`
	WillRetry bool            `json:"willRetry"`
	Signal    context.Context `json:"-"`
}

SessionBeforeCompactEvent: upstream types.ts SessionBeforeCompactEvent.

Signal carries the upstream AbortSignal through Go's context.Context.

type SessionBeforeCompactResult

type SessionBeforeCompactResult struct {
	Cancel     bool             `json:"cancel,omitempty"`
	Compaction CompactionResult `json:"compaction,omitempty"`
}

SessionBeforeCompactResult: upstream types.ts SessionBeforeCompactResult.

type SessionBeforeForkEvent

type SessionBeforeForkEvent struct {
	Type     string `json:"type"`
	EntryID  string `json:"entryId"`
	Position string `json:"position"` // "before" | "at"
}

SessionBeforeForkEvent: upstream types.ts SessionBeforeForkEvent.

type SessionBeforeForkResult

type SessionBeforeForkResult struct {
	Cancel                  bool `json:"cancel,omitempty"`
	SkipConversationRestore bool `json:"skipConversationRestore,omitempty"`
}

SessionBeforeForkResult: upstream types.ts SessionBeforeForkResult.

type SessionBeforeSwitchEvent

type SessionBeforeSwitchEvent struct {
	Type              string `json:"type"`
	Reason            string `json:"reason"` // "new" | "resume"
	TargetSessionFile string `json:"targetSessionFile,omitempty"`
}

SessionBeforeSwitchEvent: upstream types.ts SessionBeforeSwitchEvent.

type SessionBeforeSwitchResult

type SessionBeforeSwitchResult struct {
	Cancel bool `json:"cancel,omitempty"`
}

SessionBeforeSwitchResult: upstream types.ts SessionBeforeSwitchResult.

type SessionBeforeTreeEvent

type SessionBeforeTreeEvent struct {
	Type        string          `json:"type"`
	Preparation TreePreparation `json:"preparation"`
	Signal      context.Context `json:"-"`
}

SessionBeforeTreeEvent: upstream types.ts SessionBeforeTreeEvent.

Signal carries the upstream AbortSignal through Go's context.Context.

type SessionBeforeTreeResult

type SessionBeforeTreeResult struct {
	Cancel              bool                            `json:"cancel,omitempty"`
	Summary             *SessionBeforeTreeResultSummary `json:"summary,omitempty"`
	CustomInstructions  string                          `json:"customInstructions,omitempty"`
	ReplaceInstructions bool                            `json:"replaceInstructions,omitempty"`
	Label               string                          `json:"label,omitempty"`
}

SessionBeforeTreeResult: upstream types.ts SessionBeforeTreeResult.

type SessionBeforeTreeResultSummary

type SessionBeforeTreeResultSummary struct {
	Summary string `json:"summary"`
	Details any    `json:"details,omitempty"`
	// Usage is the pi-ai Usage of the extension's summarization call.
	Usage any `json:"usage,omitempty"`
}

SessionBeforeTreeResultSummary mirrors the inline `summary` object on upstream's SessionBeforeTreeResult.

func (*SessionBeforeTreeResultSummary) UnmarshalJSON

func (s *SessionBeforeTreeResultSummary) UnmarshalJSON(data []byte) error

UnmarshalJSON keeps the member order of the `details` object the extension wrote.

type SessionBoundaryDraft

type SessionBoundaryDraft struct {
	Type             string          `json:"type"`
	CustomType       string          `json:"customType,omitempty"`
	Data             any             `json:"data,omitempty"`
	Content          any             `json:"content,omitempty"`
	Display          bool            `json:"display,omitempty"`
	Details          any             `json:"details,omitempty"`
	TargetID         string          `json:"targetId,omitempty"`
	Replacement      json.RawMessage `json:"replacement,omitempty"`
	Summary          string          `json:"summary,omitempty"`
	FirstKeptEntryID *string         `json:"firstKeptEntryId,omitempty"`
	Usage            *ai.Usage       `json:"usage,omitempty"`
}

SessionBoundaryDraft is the wire representation of upstream's closed SessionBoundaryDraft union. Fields apply according to Type.

func (SessionBoundaryDraft) MarshalJSON

func (d SessionBoundaryDraft) MarshalJSON() ([]byte, error)

MarshalJSON preserves each upstream union member's required fields, including null firstKeptEntryId and replacement values.

func (*SessionBoundaryDraft) UnmarshalJSON

func (d *SessionBoundaryDraft) UnmarshalJSON(data []byte) error

UnmarshalJSON keeps the member order of the `data` and `details` objects the extension wrote.

type SessionCompactEvent

type SessionCompactEvent struct {
	Type            string          `json:"type"`
	CompactionEntry CompactionEntry `json:"compactionEntry"`
	FromExtension   bool            `json:"fromExtension"`
	// reason/willRetry adopted upstream in 0.80.3.
	Reason    string `json:"reason"`
	WillRetry bool   `json:"willRetry"`
}

SessionCompactEvent: upstream types.ts SessionCompactEvent.

type SessionCompactFailedEvent

type SessionCompactFailedEvent struct {
	Type string `json:"type"`
	// Reason is what triggered the compaction: "manual" (/compact),
	// "threshold" (the context threshold), or "overflow" (context overflow
	// recovery).
	Reason string `json:"reason"`
	// ErrorMessage is the error text when compaction failed for a
	// non-abort reason.
	ErrorMessage string `json:"errorMessage,omitempty"`
	// Aborted is true when compaction was cancelled or aborted.
	Aborted bool `json:"aborted"`
	// WillRetry is true when the aborted turn would have been retried after
	// this compaction (overflow recovery).
	WillRetry bool `json:"willRetry"`
	// FromExtension is true when the failing compaction content came from a
	// session_before_compact handler.
	FromExtension bool `json:"fromExtension"`
}

SessionCompactFailedEvent: upstream types.ts SessionCompactFailedEvent. Fired after context compaction fails or is aborted.

type SessionEntry

type SessionEntry = any

SessionEntry mirrors core/session-manager SessionEntry.

type SessionInfoChangedEvent

type SessionInfoChangedEvent struct {
	Type string `json:"type"`
	Name string `json:"name,omitempty"`
}

SessionInfoChangedEvent: upstream types.ts SessionInfoChangedEvent (adopted upstream in 0.80.3).

type SessionManager

type SessionManager = any

SessionManager mirrors core/session-manager SessionManager.

type SessionShutdownEvent

type SessionShutdownEvent struct {
	Type              string `json:"type"`
	Reason            string `json:"reason"` // "quit" | "reload" | "new" | "resume" | "fork"
	TargetSessionFile string `json:"targetSessionFile,omitempty"`
}

SessionShutdownEvent: upstream types.ts SessionShutdownEvent.

type SessionStartEvent

type SessionStartEvent struct {
	Type                string `json:"type"`
	Reason              string `json:"reason"` // "startup" | "reload" | "new" | "resume" | "fork"
	PreviousSessionFile string `json:"previousSessionFile,omitempty"`
}

SessionStartEvent: upstream types.ts SessionStartEvent.

type SessionTreeEvent

type SessionTreeEvent struct {
	Type          string             `json:"type"`
	NewLeafID     *string            `json:"newLeafId"`
	OldLeafID     *string            `json:"oldLeafId"`
	SummaryEntry  BranchSummaryEntry `json:"summaryEntry,omitempty"`
	FromExtension bool               `json:"fromExtension,omitempty"`
}

SessionTreeEvent: upstream types.ts SessionTreeEvent.

NewLeafID and OldLeafID are upstream `string | null` (NOT optional). The difference between "null" and "absent" matters for wire-format round-trip through session JSONL: upstream always emits the keys, with `null` when no leaf. We use *string so json.Marshal emits null on nil and so the distinction survives a marshal/unmarshal cycle.

type SetThemeResult

type SetThemeResult struct {
	Success bool   `json:"success"`
	Error   string `json:"error,omitempty"`
}

SetThemeResult mirrors the inline return type of `ExtensionUIContext.setTheme` (types.ts:262: `{ success, error? }`). Promoted to a named type because the inline TS object literal needs a Go-level identifier; field shape matches verbatim.

type Settings

type Settings = map[string]any

Settings is the effective settings object API.GetSettings returns: the JSON object of the global and project settings merged, with overrides. It is a copy, so a change to it does not change the settings.

Go mechanic (not a divergence): the settings manager lives in a package that imports this one, so the extension boundary carries the object as decoded JSON, the way the subprocess wire does.

upstream: .upstream/v0.99.1/packages/coding-agent/src/core/settings-manager.ts (Settings)

type ShortcutHandler

type ShortcutHandler = func(ctx context.Context) error

ShortcutHandler is invoked when a registered shortcut fires. Mirrors upstream `ExtensionAPI.registerShortcut.handler` signature.

ShortcutHandler receives cancellation and per-extension values through the Go context. Use FromContext to access the extension context.

type ShortcutOptions

type ShortcutOptions struct {
	Description string          `json:"description,omitempty"`
	Handler     ShortcutHandler `json:"-"`
}

ShortcutOptions is the registration payload for API.RegisterShortcut.

type SimpleStreamOptions

type SimpleStreamOptions = any

SimpleStreamOptions mirrors @earendil-works/pi-ai SimpleStreamOptions.

type SlashCommandInfo

type SlashCommandInfo = any

SlashCommandInfo mirrors core/slash-commands.SlashCommandInfo.

type SourceInfo

type SourceInfo = any

SourceInfo mirrors core/source-info.SourceInfo.

type SpriteDefinition

type SpriteDefinition struct {
	ID      string            `json:"id"`
	Name    string            `json:"name"`
	Tagline string            `json:"tagline"`
	Mascot  []string          `json:"mascot"`
	Palette map[string]string `json:"palette"`
}

SpriteDefinition is one sprite: its stable ID, the name and tagline /sprite lists, its pig (LoginMascotWidth by LoginMascotHeight), which the startup header draws in Pi's logo slot and /sprite preview beside the wordmark, and the palette that colors it. Grid cells are printable ASCII palette symbols; '.' is transparent.

type SpriteDefinitionError

type SpriteDefinitionError struct {
	Field   string
	Message string
}

SpriteDefinitionError identifies the invalid field in a sprite definition.

func (*SpriteDefinitionError) Error

func (e *SpriteDefinitionError) Error() string

type SpriteRegistrar

type SpriteRegistrar interface {
	RegisterSprite(owner string, definition ValidatedSpriteDefinition) error
	UnregisterSprites(owner string)
}

SpriteRegistrar is a UI that keeps extension sprites: the interactive mode adds them to /sprite. owner names the extension; a sprite's ID is unique across owners, and an owner registering an ID again replaces its sprite.

type StackError

type StackError interface {
	error
	ErrorStack() string
}

StackError is an error that carries the stack of the failure it reports, such as a JavaScript error's `stack` or a recovered Go panic's stack.

type SwitchSessionOptions

type SwitchSessionOptions struct {
	WithSession func(*ReplacedSessionContext) error `json:"-"`
}

SwitchSessionOptions mirrors upstream's switchSession options.

upstream: types.ts:354-356

type SystemPromptContextFile

type SystemPromptContextFile struct {
	Path    string `json:"path"`
	Content string `json:"content"`
}

SystemPromptContextFile mirrors the upstream anonymous `{ path: string; content: string }` element of contextFiles.

upstream: packages/coding-agent/src/core/system-prompt.ts:22

type SystemPromptSkill

type SystemPromptSkill struct {
	Name                   string     `json:"name"`
	Description            string     `json:"description"`
	FilePath               string     `json:"filePath"`
	BaseDir                string     `json:"baseDir"`
	SourceInfo             SourceInfo `json:"sourceInfo,omitempty"`
	DisableModelInvocation bool       `json:"disableModelInvocation"`
}

SystemPromptSkill mirrors the upstream `Skill` interface fields that extensions can rely on. Extensions inspect skill metadata; the physical SkillFrontmatter is not exposed.

upstream: packages/coding-agent/src/core/skills.ts:74-82 Skill

type TUI

type TUI = any

TUI mirrors @earendil-works/pi-tui TUI.

type TerminalInputHandler

type TerminalInputHandler = func(data string) TerminalInputResult

TerminalInputHandler mirrors upstream `TerminalInputHandler` (types.ts:120): raw terminal byte handler for interactive mode. Returns a result indicating whether to consume the input.

type TerminalInputResult

type TerminalInputResult struct {
	Consume bool    // true → swallow the keystroke, don't process further
	Data    *string // replacement data (nil = no replacement)
}

TerminalInputResult is the return value from a TerminalInputHandler. Mirrors upstream `{ consume?: boolean; data?: string }`. A nil Data leaves the input unchanged; a non-nil Data replaces it for later listeners and for normal handling, and an empty replacement drops it.

type TextContent

type TextContent = any

TextContent mirrors @earendil-works/pi-ai TextContent.

type Theme

type Theme = any

Theme mirrors core/modes/interactive/theme.Theme.

type ThemeMeta

type ThemeMeta struct {
	Name string `json:"name"`
	Path string `json:"path,omitempty"`
}

ThemeMeta mirrors the inline return-element type of `ExtensionUIContext.getAllThemes` (types.ts:257 - `{ name, path | undefined }[]`). Named for the same reason as SetThemeResult.

type ThinkingLevel

type ThinkingLevel = any

ThinkingLevel mirrors @earendil-works/pi-agent-core ThinkingLevel.

type ThinkingLevelSelectEvent

type ThinkingLevelSelectEvent struct {
	Type          string `json:"type"`
	Level         string `json:"level"`
	PreviousLevel string `json:"previousLevel"`
}

ThinkingLevelSelectEvent: upstream types.ts ThinkingLevelSelectEvent.

type ToolActions

type ToolActions struct {
	// ExecuteTool backs [ToolContext.ExecuteTool]. ctx is the options' Signal, or the calling tool's context; options.Signal is nil. Without it, nested calls fail with an error outcome.
	// upstream: types.ts:2162
	ExecuteTool func(ctx context.Context, callerID, name string, args json.RawMessage, options ExecuteToolOptions) (AgentToolCallOutcome, error)
	// GetCallableTools backs [ToolContext.Tools]. Without it, the list is empty.
	// upstream: types.ts:2169
	GetCallableTools func() []AgentTool
	// AppendEntry backs [ToolContext.AppendEntry]: append the entry to the session's log and report it as an `entry_appended` event. Go returns the error the log reports, where upstream throws it.
	// upstream: agent-session.ts:3321-3327 (ExtensionActions.appendEntry, types.ts:1687)
	AppendEntry func(customType string, data any) error
}

ToolActions is the host-side injection that backs ToolContext. Mirrors the executeTool and getCallableTools members of upstream ExtensionContextActions.

upstream: types.ts:2161-2169 (ExtensionContextActions.executeTool, getCallableTools)

type ToolAnnotations

type ToolAnnotations struct {
	ReadOnlyHint    *bool `json:"readOnlyHint,omitempty"`
	DestructiveHint *bool `json:"destructiveHint,omitempty"`
	IdempotentHint  *bool `json:"idempotentHint,omitempty"`
	OpenWorldHint   *bool `json:"openWorldHint,omitempty"`
}

ToolAnnotations mirrors upstream ToolAnnotations: hints about what a tool does, with the meaning of MCP tool annotations. They come from the tool's author and are not verified.

upstream: types.ts:515 (ToolAnnotations)

type ToolCallEvent

type ToolCallEvent interface {
	// contains filtered or unexported methods
}

ToolCallEvent is the sealed union of per-tool ToolCallEvent variants. Mirrors upstream's `export type ToolCallEvent = | BashToolCallEvent | PowerShellToolCallEvent | ReadToolCallEvent | EditToolCallEvent | WriteToolCallEvent | GrepToolCallEvent | FindToolCallEvent | LsToolCallEvent | CustomToolCallEvent` (types.ts:810).

Package-sealed via the unexported `isToolCallEvent` marker method: only the nine variant structs declared in this package can satisfy it. Authors handle the union via a type switch on the concrete variant. Custom UnmarshalJSON in marshalling.go probes the `toolName` field to dispatch to the correct variant when reading session JSONL.

upstream: types.ts:810

func UnmarshalToolCallEvent

func UnmarshalToolCallEvent(data []byte) (ToolCallEvent, error)

UnmarshalToolCallEvent dispatches by `toolName`. Tool names that don't match a known builtin variant fall through to CustomToolCallEvent \u2014 this matches upstream behaviour (custom tools share the wire shape with builtins; only `toolName` distinguishes them) and keeps third-party tools round-trippable through pig without code changes.

type ToolCallEventBase

type ToolCallEventBase struct {
	Type string `json:"type"`
	// ToolCallID is the call's id. For calls another tool made (with
	// ParentToolCallID set), pi assigns `<parent id>/<n>`; such ids never appear
	// as tool calls or tool results in the transcript, only in the parent
	// result's `nestedCalls` record.
	ToolCallID string `json:"toolCallId"`
	// ParentToolCallID is set when another tool (for example a codemode script)
	// issued this call. upstream: parentToolCallId?: string
	ParentToolCallID string `json:"parentToolCallId,omitempty"`
}

ToolCallEventBase mirrors upstream's internal ToolCallEventBase. Embedded in each per-tool variant so all variants share the discriminator and toolCallId fields.

Go embeds the common fields so reflection sees the same promoted shape.

type ToolCallEventResult

type ToolCallEventResult struct {
	Block  bool   `json:"block,omitempty"`
	Reason string `json:"reason,omitempty"`
	// Terminate hints that the agent should stop after the current tool batch
	// when this call is blocked. Early termination only happens when every
	// finalized tool result in the batch sets it.
	Terminate bool `json:"terminate,omitempty"`
}

ToolCallEventResult: upstream types.ts ToolCallEventResult.

type ToolContext

type ToolContext struct {
	*Context
	// contains filtered or unexported fields
}

ToolContext is the context passed to tool Execute in a session: the extension Context plus ToolContext.ExecuteTool for running other tools through the same validation, hooks, and permission checks as model-issued calls. Retrieve it with ToolContextFromContext.

A tool that no runner wrapped, such as a built-in tool run in a plain Agent or called directly, gets no ToolContext.

upstream: types.ts:383-395 (ExtensionToolContext)

func NewToolContext

func NewToolContext(base *Context, toolCallID string, signal context.Context, actions ToolActions) *ToolContext

NewToolContext builds the context of the tool call toolCallID. signal is the default cancellation of nested calls. Hosts call it; tool authors never do.

upstream: runner.ts:952-985 (createToolContext)

func ToolContextFromContext

func ToolContextFromContext(ctx context.Context) *ToolContext

ToolContextFromContext returns the ToolContext a host attached to a tool call, or nil when the tool runs outside a runner.

func (*ToolContext) AppendEntry

func (c *ToolContext) AppendEntry(customType string, data any) error

AppendEntry appends a custom entry to the session for state persistence (it is not sent to the LLM) and reports it as an `entry_appended` event. It is `pi.appendEntry()`, for a declarative Go tool that has no `pi` to close over: upstream's codemode passes `(customType, data) => pi.appendEntry(customType, data)` into its tool definition. Without a bound action the call fails with ErrRuntimeNotInitialized.

upstream: loader.ts:376-379 (appendEntry: assertActive, then runtime.appendEntry), loader.ts:157-159, 171 (notInitialized), agent-session.ts:3321-3327, codemode/index.ts:35

func (*ToolContext) ExecuteTool

func (c *ToolContext) ExecuteTool(name string, args any, options *ExecuteToolOptions) (AgentToolCallOutcome, error)

ExecuteTool runs another tool. The call gets the id `<calling id>/<n>`, and the `tool_call`, `tool_result`, and `tool_execution_*` events carry `parentToolCallId`. It does not appear in the transcript; a bounded record of it is kept as `nestedCalls` on the calling tool's result message.

It never fails for tool failures: unknown tools, validation errors, blocked calls, and thrown errors come back as an outcome with IsError set. The error is non-nil only for a stale context or unencodable arguments. The call is cancelled with options.Signal, which defaults to the calling tool's context.

upstream: types.ts:386-394 (executeTool), runner.ts:966-983

func (*ToolContext) Tools

func (c *ToolContext) Tools() ([]AgentTool, error)

Tools returns the tools ToolContext.ExecuteTool can call. Without a GetCallableTools action the list is empty.

upstream: types.ts:385 (ExtensionToolContext.tools), runner.ts:955-964, 379

type ToolDefinition

type ToolDefinition struct {
	Name                string                   `json:"name"`
	Label               string                   `json:"label"`
	Description         string                   `json:"description"`
	PromptSnippet       string                   `json:"promptSnippet,omitempty"`
	PromptGuidelines    []string                 `json:"promptGuidelines,omitempty"`
	Parameters          json.RawMessage          `json:"parameters"`
	ConstrainedSampling json.RawMessage          `json:"constrainedSampling,omitempty"`
	RenderShell         ToolRenderShell          `json:"renderShell,omitempty"`
	PrepareArguments    ToolPrepareArgumentsFunc `json:"-"`
	ExecutionMode       ToolExecutionMode        `json:"executionMode,omitempty"`
	Execute             ToolExecuteFunc          `json:"-"`
	RenderCall          ToolRenderCallFunc       `json:"-"`
	RenderResult        ToolRenderResultFunc     `json:"-"`
	// DefaultActive is whether registering the tool activates it. Default: true
	// for direct and model-only tools; other exposures are never activated on
	// registration. A tool with DefaultActive false is activated by naming it in
	// `--tools` or the `defaultTools` setting, or with SetActiveTools.
	// upstream: types.ts:600 (defaultActive)
	DefaultActive *bool `json:"defaultActive,omitempty"`
	// PrepareLoadout adjusts how the loadout is presented to the model while
	// this tool is active. Called whenever the active tools change. Tools that
	// orchestrate other tools use it, for example to list the callable tools in
	// their own description.
	// upstream: types.ts:607 (prepareLoadout)
	PrepareLoadout ToolPrepareLoadoutFunc `json:"-"`
	// ReserveCallOrder reserves this call's place among the calls the tool's requests must follow in call order. The host
	// calls it synchronously, in call order, before any call of a parallel batch or a codemode script runs, and puts the
	// result on the call's context (CallOrderFromContext). A nil result reserves nothing. Pi's calls run their
	// synchronous prefix in call order, which Go goroutines do not give; this restores it for tools whose request order is
	// observable, such as MCP tool calls to one server.
	ReserveCallOrder func(params json.RawMessage) *CallOrder `json:"-"`
	// BuiltInRenderers names the built-in tool whose renderers draw the card
	// halves this definition does not render itself. A subprocess extension
	// sets it for a tool built from Pi's create<Tool>ToolDefinition, whose
	// renderers are that built-in tool's (D73).
	BuiltInRenderers string `json:"-"`
	// ValidationParameters is the host-only representation of non-enumerable TypeBox metadata.
	ValidationParameters json.RawMessage `json:"-"`
	// OutputSchema is the schema of the structured result. upstream: types.ts:585
	OutputSchema json.RawMessage `json:"outputSchema,omitempty"`
	// Exposure is how the model reaches the tool. Default: direct. upstream: types.ts:590
	Exposure ToolExposure `json:"exposure,omitempty"`
	// Namespace groups the tool with related tools. upstream: types.ts:593
	Namespace *ToolNamespace `json:"namespace,omitempty"`
	// Annotations are hints about what the tool does. upstream: types.ts:596
	Annotations *ToolAnnotations `json:"annotations,omitempty"`
}

ToolDefinition mirrors upstream ToolDefinition<TParams, TDetails, TState>.

pig Go mechanic (not a divergence): upstream is generic over TParams (TypeBox TSchema), TDetails, and TState. Go uses json.RawMessage for parameters and any for details/state because Go interface methods cannot have type parameters and the host registry is heterogeneous. The SDK ergonomics layer in `extensions/sdk/go/` provides typed wrappers without changing the wire format.

type ToolDetailsConverter

type ToolDetailsConverter interface {
	ToolResultDetails() any
}

ToolDetailsConverter is implemented by a built-in tool's internal result details to produce the upstream SDK wire shape for the `details` field of a tool_result event. pig keeps richer internal detail structs for the TUI renderer; this contract lets the extension emission boundary convert them to the lean upstream shapes without the generic runtime depending on the concrete tool package.

type ToolExecuteFunc

type ToolExecuteFunc = func(
	ctx context.Context,
	toolCallID string,
	params json.RawMessage,
	onUpdate AgentToolUpdateCallback,
) (AgentToolResult, error)

ToolExecuteFunc mirrors upstream ToolDefinition.execute.

Go carries the upstream abort signal and extension values through one context.Context. Use FromContext to access the extension context.

type ToolExecutionEndEvent

type ToolExecutionEndEvent struct {
	Type       string `json:"type"`
	ToolCallID string `json:"toolCallId"`
	ToolName   string `json:"toolName"`
	Result     any    `json:"result"`
	// WireResult is the value the event carries for Result on the extension wire, with its members in the order the tool wrote them: a map in Result sorts them. Nil when Result marshals as it is.
	WireResult any  `json:"-"`
	IsError    bool `json:"isError"`
	// ParentToolCallID is set when another tool (for example a codemode script)
	// made this call. upstream: parentToolCallId?: string
	ParentToolCallID string `json:"parentToolCallId,omitempty"`
}

ToolExecutionEndEvent: upstream types.ts ToolExecutionEndEvent.

func (ToolExecutionEndEvent) MarshalJSON

func (e ToolExecutionEndEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event with WireResult in place of Result, in Pi's member order.

type ToolExecutionMode

type ToolExecutionMode = string

ToolExecutionMode mirrors ToolExecutionMode ("sequential" | "parallel").

type ToolExecutionStartEvent

type ToolExecutionStartEvent struct {
	Type       string `json:"type"`
	ToolCallID string `json:"toolCallId"`
	ToolName   string `json:"toolName"`
	Args       any    `json:"args"`
	// WireArgs is the JSON the event carries for Args on the extension wire: the model's arguments in the order it wrote them, which the map in Args cannot keep. Nil when Args marshals as it is.
	WireArgs json.RawMessage `json:"-"`
	// ParentToolCallID is set when another tool (for example a codemode script)
	// made this call. upstream: parentToolCallId?: string
	ParentToolCallID string `json:"parentToolCallId,omitempty"`
}

ToolExecutionStartEvent: upstream types.ts ToolExecutionStartEvent.

func (ToolExecutionStartEvent) MarshalJSON

func (e ToolExecutionStartEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event with WireArgs in place of Args, in Pi's member order.

type ToolExecutionUpdateEvent

type ToolExecutionUpdateEvent struct {
	Type       string `json:"type"`
	ToolCallID string `json:"toolCallId"`
	ToolName   string `json:"toolName"`
	Args       any    `json:"args"`
	// WireArgs is the JSON the event carries for Args on the extension wire; see [ToolExecutionStartEvent.WireArgs].
	WireArgs      json.RawMessage `json:"-"`
	PartialResult any             `json:"partialResult"`
	// WirePartialResult is the value the event carries for PartialResult on the extension wire, with its members in the order the tool wrote them. Nil when PartialResult marshals as it is.
	WirePartialResult any `json:"-"`
	// ParentToolCallID is set when another tool (for example a codemode script)
	// made this call. upstream: parentToolCallId?: string
	ParentToolCallID string `json:"parentToolCallId,omitempty"`
}

ToolExecutionUpdateEvent: upstream types.ts ToolExecutionUpdateEvent.

func (ToolExecutionUpdateEvent) MarshalJSON

func (e ToolExecutionUpdateEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event with the wire values in place of Args and PartialResult, in Pi's member order.

type ToolExposure

type ToolExposure string

ToolExposure mirrors upstream ToolExposure: how the model reaches a tool. "Callable" means callable from other tools through `ctx.executeTool()`, as the codemode tool does.

  • direct: declared to the model while active, and callable while active.
  • model-only: declared to the model while active, never callable.
  • codemode: callable whenever registered. Not declared to the model unless explicitly activated. Codemode tools list it in their description.
  • deferred: like codemode, but codemode tools do not list it; tool search can find it.
  • hidden: registered but unreachable. Activating it has no effect.

`direct` and `model-only` tools are activated when they are registered; the others are not.

upstream: types.ts:509 (ToolExposure)

const (
	ToolExposureDirect    ToolExposure = "direct"
	ToolExposureModelOnly ToolExposure = "model-only"
	ToolExposureCodemode  ToolExposure = "codemode"
	ToolExposureDeferred  ToolExposure = "deferred"
	ToolExposureHidden    ToolExposure = "hidden"
)

The exposures of upstream's ToolExposure union.

type ToolInfo

type ToolInfo struct {
	Name             string          `json:"name"`
	Description      string          `json:"description"`
	Parameters       json.RawMessage `json:"parameters"`
	PromptGuidelines []string        `json:"promptGuidelines,omitempty"`
	SourceInfo       SourceInfo      `json:"sourceInfo"`
	// Exposure, Namespace, and Annotations mirror upstream ToolInfo. upstream: types.ts:2063
	Exposure    ToolExposure     `json:"exposure,omitempty"`
	Namespace   *ToolNamespace   `json:"namespace,omitempty"`
	Annotations *ToolAnnotations `json:"annotations,omitempty"`
}

ToolInfo mirrors upstream ToolInfo: the read-only view returned by API.GetAllTools.

type ToolLoadout

type ToolLoadout struct {
	// Declared are the tools declared to the model (the active tools), in order, with their original descriptions.
	Declared []AgentTool
	// Callable are the tools callable through [ToolContext.ExecuteTool].
	Callable []AgentTool
	// Registered is every registered tool.
	Registered   []AgentTool
	GetExposure  func(name string) ToolExposure
	GetNamespace func(name string) *ToolNamespace
}

ToolLoadout is the tools of a session as ToolDefinition.PrepareLoadout sees them.

Go mechanic (not a divergence): upstream's getExposure and getNamespace methods are function-valued fields, so a test double is a struct literal.

upstream: types.ts:541-551 (ToolLoadout)

type ToolLoadoutChanges

type ToolLoadoutChanges struct {
	// Descriptions are the model-facing descriptions of declared tools, by tool name.
	Descriptions map[string]string `json:"descriptions,omitempty"`
	// HiddenDeclarations names declared tools whose declarations requests leave out. They stay active and callable, and the transcript still declares them, so the active set survives `/tree` and resume.
	HiddenDeclarations []string `json:"hiddenDeclarations,omitempty"`
}

ToolLoadoutChanges are the changes ToolDefinition.PrepareLoadout makes to what the model sees.

upstream: types.ts:554-563 (ToolLoadoutChanges)

type ToolNamespace

type ToolNamespace struct {
	Name string `json:"name"`
	// Description is a short summary shown once with the group in model-facing tool listings.
	Description string `json:"description,omitempty"`
	// Instructions is longer usage guidance, such as MCP server instructions. It is not part of tool listings; tools
	// that describe the namespace on request (codemode's describeNamespace()) return it.
	Instructions string `json:"instructions,omitempty"`
}

ToolNamespace mirrors upstream ToolNamespace: a group of related tools, such as the tools of one MCP server.

upstream: types.ts:527 (ToolNamespace)

type ToolPrepareArgumentsFunc

type ToolPrepareArgumentsFunc = func(args json.RawMessage) (json.RawMessage, error)

ToolPrepareArgumentsFunc mirrors upstream ToolDefinition.prepareArguments.

type ToolPrepareLoadoutFunc

type ToolPrepareLoadoutFunc = func(loadout ToolLoadout) *ToolLoadoutChanges

ToolPrepareLoadoutFunc mirrors upstream ToolDefinition.prepareLoadout. A nil result leaves the loadout as it is (upstream returns undefined). Upstream's hook is synchronous and reports a failure by throwing; a Go hook panics instead, and the session recovers the panic and reports it as a `prepare_loadout` extension error (agent-session.ts:1520-1533).

type ToolRenderCallFunc

type ToolRenderCallFunc = func(
	args json.RawMessage,
	theme Theme,
	context ToolRenderContext,
) Component

ToolRenderCallFunc mirrors upstream ToolDefinition.renderCall.

type ToolRenderContext

type ToolRenderContext struct {
	Args             any       `json:"args"`
	ToolCallID       string    `json:"toolCallId"`
	Invalidate       func()    `json:"-"`
	LastComponent    Component `json:"-"`
	State            any       `json:"-"`
	Cwd              string    `json:"cwd"`
	ExecutionStarted bool      `json:"executionStarted"`
	ArgsComplete     bool      `json:"argsComplete"`
	IsPartial        bool      `json:"isPartial"`
	Expanded         bool      `json:"expanded"`
	ShowImages       bool      `json:"showImages"`
	IsError          bool      `json:"isError"`
	// Card identifies the tool card being rendered. Go mechanic (not a
	// divergence): a renderer that runs in an extension process keeps State
	// and its last component there, so the host names the card they belong
	// to; upstream passes the card's objects themselves.
	Card string `json:"-"`
}

ToolRenderContext mirrors upstream ToolRenderContext<TState, TArgs>.

Go mechanic (not a divergence): upstream is generic over TState and TArgs; the Go version uses any for both because Go function-type struct fields cannot have type parameters. SDK helpers in `extensions/sdk/go/` provide typed wrappers without changing the wire format.

type ToolRenderResultFunc

type ToolRenderResultFunc = func(
	result AgentToolResult,
	options ToolRenderResultOptions,
	theme Theme,
	context ToolRenderContext,
) Component

ToolRenderResultFunc mirrors upstream ToolDefinition.renderResult.

type ToolRenderResultOptions

type ToolRenderResultOptions struct {
	Expanded  bool `json:"expanded"`
	IsPartial bool `json:"isPartial"`
}

ToolRenderResultOptions mirrors upstream ToolRenderResultOptions.

type ToolRenderShell

type ToolRenderShell string

ToolRenderShell controls whether the standard tool-execution chrome wraps the tool's renderers, or the tool draws its own framing. Mirrors upstream "default" | "self".

const (
	ToolRenderShellDefault ToolRenderShell = "default"
	ToolRenderShellSelf    ToolRenderShell = "self"
)

type ToolRendererResolver

type ToolRendererResolver = func(toolName string, next func() *ToolRenderers) *ToolRenderers

ToolRendererResolver chooses how calls to a tool are drawn, including tools that are not registered. next returns the renderers the remaining resolvers, then the registered tool, would use. A nil result means none. upstream: types.ts ToolRendererResolver

type ToolRenderers

type ToolRenderers struct {
	RenderShell  ToolRenderShell
	RenderCall   ToolRenderCallFunc
	RenderResult ToolRenderResultFunc
}

ToolRenderers is how calls to a tool are drawn: the renderShell, renderCall, and renderResult of a ToolDefinition. upstream: types.ts ToolRenderers

type ToolResultEvent

type ToolResultEvent interface {
	// contains filtered or unexported methods
}

ToolResultEvent is the sealed union of per-tool ToolResultEvent variants. Mirrors upstream's `export type ToolResultEvent = | BashToolResultEvent | PowerShellToolResultEvent | ... | CustomToolResultEvent` (types.ts:869).

Package-sealed via the unexported `isToolResultEvent` marker method. Custom UnmarshalJSON in marshalling.go dispatches by `toolName`.

upstream: types.ts:869

func UnmarshalToolResultEvent

func UnmarshalToolResultEvent(data []byte) (ToolResultEvent, error)

UnmarshalToolResultEvent dispatches by `toolName`. See UnmarshalToolCallEvent for the custom-tool fallback rationale.

type ToolResultEventBase

type ToolResultEventBase struct {
	Type string `json:"type"`
	// ToolCallID is the call's id; `<parent id>/<n>` for nested calls, see [ToolCallEventBase].
	ToolCallID string `json:"toolCallId"`
	// ParentToolCallID is set when another tool (for example a codemode script)
	// issued this call. upstream: parentToolCallId?: string
	ParentToolCallID string         `json:"parentToolCallId,omitempty"`
	Input            map[string]any `json:"input"`
	// WireInput is the tool call's arguments as the model wrote them, which a subprocess extension receives as `input` in that member order; a map in Input sorts them. Empty when Input is the only source.
	WireInput json.RawMessage `json:"-"`
	Content   []any           `json:"content"` // (TextContent | ImageContent)[]
	// StructuredContent is the machine-readable result of a tool that declares an
	// outputSchema. Handlers that redact Content should also replace this;
	// replacing Content alone drops it. upstream: structuredContent?: JsonValue
	StructuredContent json.RawMessage `json:"structuredContent,omitempty"`
	IsError           bool            `json:"isError"`
	// Usage is the usage of the tool execution itself, if available
	// (upstream `usage?: Usage`).
	Usage any `json:"usage,omitempty"`
}

ToolResultEventBase mirrors upstream's internal ToolResultEventBase.

type ToolResultEventResult

type ToolResultEventResult struct {
	Content []any `json:"content,omitempty"` // (TextContent | ImageContent)[]
	Details any   `json:"details,omitempty"`
	// StructuredContent replaces the result's structured content. upstream: structuredContent?: JsonValue
	StructuredContent json.RawMessage `json:"structuredContent,omitempty"`
	// IsError is nil when the handler leaves the error flag unchanged, as
	// upstream's optional `isError?: boolean` is undefined.
	IsError *bool `json:"isError,omitempty"`
	// Usage mirrors upstream ToolResultEventResult.usage (pi-ai Usage). Carried
	// untyped over the extension wire boundary, consistent with Details above and
	// the AgentMessage alias; folded into session usage totals by the
	// deferred-tools accounting path.
	Usage any `json:"usage,omitempty"`
}

ToolResultEventResult: upstream types.ts ToolResultEventResult. Omitted fields stay as they are, except that replacing Content without returning StructuredContent drops the structured content, because it may no longer match. Return it along with Content to keep it.

func (*ToolResultEventResult) UnmarshalJSON

func (r *ToolResultEventResult) UnmarshalJSON(data []byte) error

UnmarshalJSON keeps the member order of the `details` object the handler wrote.

type ToolResultMessage

type ToolResultMessage = any

ToolResultMessage mirrors @earendil-works/pi-ai ToolResultMessage.

type ToolTruncation

type ToolTruncation struct {
	Content               string `json:"content"`
	Truncated             bool   `json:"truncated"`
	TruncatedBy           string `json:"truncatedBy"` // "lines" | "bytes"
	TotalLines            int    `json:"totalLines"`
	TotalBytes            int    `json:"totalBytes"`
	OutputLines           int    `json:"outputLines"`
	OutputBytes           int    `json:"outputBytes"`
	LastLinePartial       bool   `json:"lastLinePartial"`
	FirstLineExceedsLimit bool   `json:"firstLineExceedsLimit"`
	MaxLines              int    `json:"maxLines"`
	MaxBytes              int    `json:"maxBytes"`
}

ToolTruncation is the upstream TruncationResult wire shape (truncate.ts:15). It is attached as the `truncation` field of read/bash/grep/find/ls tool result details when output was truncated. All fields are present in a real truncation object (it is only attached when truncation occurred).

type TreePreparation

type TreePreparation = any

TreePreparation mirrors the upstream TreePreparation interface.

type TurnEndEvent

type TurnEndEvent struct {
	*BoundaryState
	Type               string              `json:"type"`
	TurnIndex          int                 `json:"turnIndex"`
	Message            AgentMessage        `json:"message"`
	ToolResults        []ToolResultMessage `json:"toolResults"`
	MessageEntryID     string              `json:"messageEntryId"`
	ToolResultEntryIds []string            `json:"toolResultEntryIds"`
}

TurnEndEvent carries the completed turn and the actionable boundary proposal and preview (upstream types.ts TurnEndEvent).

type TurnStartEvent

type TurnStartEvent struct {
	Type      string `json:"type"`
	TurnIndex int    `json:"turnIndex"`
	Timestamp int64  `json:"timestamp"`
}

TurnStartEvent: upstream types.ts TurnStartEvent.

type UIContext

type UIContext interface {
	// Show a selector and return the user's choice.
	// upstream: types.ts:124
	Select(ctx context.Context, title string, options []string, opts ExtensionUIDialogOptions) (string, error)

	// Show a confirmation dialog.
	// upstream: types.ts:127
	Confirm(ctx context.Context, title, message string, opts ExtensionUIDialogOptions) (bool, error)

	// Show a text input dialog.
	// upstream: types.ts:130
	Input(ctx context.Context, title, placeholder string, opts ExtensionUIDialogOptions) (string, error)

	// Show a notification to the user. Type is one of
	// "info" | "warning" | "error".
	// upstream: types.ts:133
	Notify(message, kind string)

	// OnTerminalInput registers a raw-terminal-input handler
	// (interactive mode only). Returns an unsubscribe function.
	// upstream: types.ts:136
	OnTerminalInput(handler TerminalInputHandler) (unsubscribe func())

	// SetStatus sets status text in the footer/status bar. Empty
	// text clears the entry.
	// upstream: types.ts:139
	SetStatus(key, text string)

	// SetWorkingMessage sets the working/loading message shown
	// during streaming. Empty message restores the default.
	// upstream: types.ts:142
	SetWorkingMessage(message string)

	// SetWorkingVisible toggles whether the working/loading indicator is shown.
	// upstream: interactive-mode.ts oauth/rpc extension contexts
	SetWorkingVisible(visible bool)

	// SetWorkingIndicator configures the interactive working
	// indicator. Nil opts restores the default animated spinner.
	// upstream: types.ts:153
	SetWorkingIndicator(opts WorkingIndicatorOptions)

	// SetHiddenThinkingLabel sets the label shown for hidden
	// thinking blocks. Empty label restores the default.
	// upstream: types.ts:156
	SetHiddenThinkingLabel(label string)

	// SetWidget sets a widget to display above or below the editor.
	// content may be []string or a function-typed factory; opts
	// describes placement/lifecycle.
	//
	// upstream: types.ts:159 + types.ts:163 (overloaded). Go merges
	// to one signature using `any` for content because Go has no
	// method overloading.
	SetWidget(key string, content any, opts ExtensionWidgetOptions)

	// SetFooter installs a custom footer factory. Nil restores the
	// built-in footer.
	// upstream: types.ts:172
	SetFooter(factory any)

	// SetHeader installs a custom header factory. Nil restores the
	// built-in header.
	// upstream: types.ts:181
	SetHeader(factory any)

	// pig additive (D60): SetLogin validates and installs Pig's native login
	// definition in the shared header slot. Upstream Pi exposes only
	// SetHeader because its in-process extensions can supply component factories.
	SetLogin(definition LoginDefinition) error

	// SetTitle sets the terminal window/tab title.
	// upstream: types.ts:184
	SetTitle(title string)

	// Custom shows a custom component with keyboard focus and
	// returns the user's result via the `done` callback.
	//
	// upstream: types.ts:187: the generic `<T>` is erased to `any` because Go
	// interface methods cannot be generic (an ordinary TS→Go mechanic, not a
	// divergence). Authors typed-assert at the call site or use the SDK helpers.
	//
	// An extension in the host process passes a [CustomFactory] and, optionally,
	// [CustomOptions]; the call blocks until the factory's done callback returns
	// the result.
	Custom(ctx context.Context, factory any, opts any) (any, error)

	// PasteToEditor pastes text into the editor, triggering paste
	// handling (collapse for large content).
	// upstream: types.ts:204
	PasteToEditor(text string)

	// SetEditorText sets the text in the core input editor.
	// upstream: types.ts:207
	SetEditorText(text string)

	// GetEditorText returns the current text from the core input
	// editor.
	// upstream: types.ts:210
	GetEditorText() string

	// Editor shows a multi-line editor for text editing. Returns
	// the entered text or empty + context.Canceled when cancelled.
	// upstream: types.ts:213
	Editor(ctx context.Context, title, prefill string) (string, error)

	// AddAutocompleteProvider stacks additional autocomplete
	// behavior on top of the built-in provider.
	// upstream: types.ts:216
	AddAutocompleteProvider(factory AutocompleteProviderFactory) error

	// SetEditorComponent installs a custom editor component
	// factory. Nil restores the default editor.
	// upstream: types.ts:249
	SetEditorComponent(factory any)

	// GetEditorComponent returns the currently installed custom editor component.
	// Nil when the default editor is active.
	GetEditorComponent() any

	// Theme returns the current theme for styling.
	//
	// upstream: types.ts:254 (`readonly theme: Theme`). Mapped to a
	// getter method because Go interfaces cannot expose readonly
	// fields.
	Theme() Theme

	// GetAllThemes returns metadata for all available themes.
	// upstream: types.ts:257
	GetAllThemes() []ThemeMeta

	// GetTheme loads a theme by name without switching to it.
	// Returns nil + error if not found.
	// upstream: types.ts:260
	GetTheme(name string) (Theme, error)

	// SetTheme switches the current theme. theme is either a name
	// (string) or a Theme value; the result reports success +
	// optional error message.
	// upstream: types.ts:262
	SetTheme(theme any) SetThemeResult

	// GetToolsExpanded returns the current tool-output expansion
	// state.
	// upstream: types.ts:265
	GetToolsExpanded() bool

	// SetToolsExpanded sets the tool-output expansion state.
	// upstream: types.ts:268
	SetToolsExpanded(expanded bool)

	// RunRemoteOverlay opens an interactive overlay whose contents
	// are produced by a remote (subprocess) extension. The overlay
	// renders the cached lines pushed via the returned handle and
	// forwards user input chunks back to host.OnInput. Blocks until
	// the handle's Close is called and returns the result value the
	// remote producer supplied. Returns (nil, false) when the
	// overlay cannot be opened (e.g. no TUI bound, like in print or
	// RPC modes).
	//
	// pig-specific: no upstream equivalent. Upstream's Custom()
	// can't cross a subprocess boundary because its factory captures
	// in-process TUI references; this is the deserialised companion.
	RunRemoteOverlay(opts RemoteOverlayOptions, host RemoteOverlayHost, onHandle func(RemoteOverlayHandle)) (any, bool)

	// OnRemoteTerminalInput registers the raw-terminal-input listener of
	// the subprocess extension named extensionName. It takes its place in
	// registration order as OnTerminalInput does, but the host never calls
	// handler on its input loop: it asks off the loop and applies the
	// verdict in input order. Returns an unsubscribe function.
	//
	// pig additive (D19): upstream listeners run in process and answer
	// synchronously; a subprocess listener's verdict crosses a socket.
	OnRemoteTerminalInput(extensionName string, handler RemoteTerminalInputHandler) (unsubscribe func())
}

UIContext is the per-mode UI surface for extensions.

**Upstream alias:** mirrors `ExtensionUIContext` (types.ts:120-269). Each mode (interactive, RPC, print) provides its own implementation; extensions interact with whichever the host bound at runtime.

**Default:** when the host binds nothing, `Context.UI()` returns the package-level NoopUIContext (a value, not a constructor - matches upstream's module-level `noOpUIContext` constant at runner.ts:188).

**Method shape conventions (pig):**

  • Methods that upstream returns `Promise<T | undefined>` from map to `(T, error)` in Go. The error half carries cancellation and routes upstream "undefined" through the typed zero value (empty string, false). Callers distinguish "user cancelled" from "ok with default value" by inspecting `errors.Is(err, context.Canceled)`.
  • Methods that upstream returns `Promise<void>` from map to `error`-returning Go methods so cancellation propagates.
  • Methods that upstream returns synchronously stay synchronous in Go (Notify, SetStatus, etc.).
  • Method names are upstream camelCase → Go PascalCase. The `setX` family becomes `SetX`. The readonly property `theme` becomes a `Theme()` getter (Go has no readonly fields on interfaces).

**Sync-compat:** every divergence from a 1:1 method shape is a silent sync-debt risk. Method order in this interface mirrors upstream types.ts order verbatim so `git diff` against the next upstream sync is mechanical.

upstream: types.ts:120-269 (ExtensionUIContext)

var NoopUIContext UIContext = &noopUIContext{}

NoopUIContext is the package-level no-op singleton. Hosts that have no UI (print and JSON modes) wire `ContextActions.UI = NoopUIContext`; equivalently, leaving `ContextActions.UI` nil produces the same behavior because Context.UI falls back to this value.

**Identity contract:** the value is intentionally a singleton (one shared `*noopUIContext`) so `Context.HasUI()` can implement upstream's identity check (runner.ts:361: `this.uiContext !== noOpUIContext`) by pointer comparison.

upstream: runner.ts:188 (`const noOpUIContext: ExtensionUIContext = ...`)

type UIPromptEndEvent

type UIPromptEndEvent struct {
	Type   string       `json:"type"`   // "ui_prompt_end"
	Reason string       `json:"reason"` // "ui_prompt"
	Kind   UIPromptKind `json:"kind"`
	Title  string       `json:"title,omitempty"`
}

UIPromptEndEvent: upstream types.ts UIPromptEndEvent. Fired when Pi is no longer waiting on a blocking user-facing extension UI prompt. Kind and Title repeat the outermost prompt's start event.

type UIPromptKind

type UIPromptKind string

UIPromptKind mirrors upstream types.ts UIPromptKind: "select" | "confirm" | "input" | "editor" | "custom".

const (
	UIPromptKindSelect  UIPromptKind = "select"
	UIPromptKindConfirm UIPromptKind = "confirm"
	UIPromptKindInput   UIPromptKind = "input"
	UIPromptKindEditor  UIPromptKind = "editor"
	UIPromptKindCustom  UIPromptKind = "custom"
)

type UIPromptStartEvent

type UIPromptStartEvent struct {
	Type   string       `json:"type"`   // "ui_prompt_start"
	Reason string       `json:"reason"` // "ui_prompt"
	Kind   UIPromptKind `json:"kind"`
	Title  string       `json:"title,omitempty"`
}

UIPromptStartEvent: upstream types.ts UIPromptStartEvent. Fired when Pi starts waiting on a blocking user-facing extension UI prompt. Title is omitted when the prompt has none (upstream `...(title ? { title } : {})`).

type UserBashEvent

type UserBashEvent struct {
	Type               string `json:"type"`
	Command            string `json:"command"`
	ExcludeFromContext bool   `json:"excludeFromContext"`
	Cwd                string `json:"cwd"`
}

UserBashEvent: upstream types.ts UserBashEvent.

type UserBashEventResult

type UserBashEventResult struct {
	Operations BashOperations `json:"operations,omitempty"`
	Result     BashResult     `json:"result,omitempty"`
}

UserBashEventResult: upstream types.ts UserBashEventResult.

type ValidatedLoginDefinition

type ValidatedLoginDefinition struct {
	// contains filtered or unexported fields
}

ValidatedLoginDefinition is an immutable, renderer-ready login definition.

func DecodeLoginDefinitionJSON

func DecodeLoginDefinitionJSON(data []byte) (ValidatedLoginDefinition, error)

DecodeLoginDefinitionJSON strictly decodes and validates the current login wire shape. Duplicate and unknown object fields are rejected.

func ValidateLoginDefinition

func ValidateLoginDefinition(definition LoginDefinition) (ValidatedLoginDefinition, error)

ValidateLoginDefinition validates and defensively copies a login definition.

func (ValidatedLoginDefinition) Brand

func (d ValidatedLoginDefinition) Brand() []string

func (ValidatedLoginDefinition) Color

func (d ValidatedLoginDefinition) Color(symbol byte) (color.RGBA, bool)

func (ValidatedLoginDefinition) Description

func (d ValidatedLoginDefinition) Description() string

func (ValidatedLoginDefinition) Hero

func (d ValidatedLoginDefinition) Hero() []string

func (ValidatedLoginDefinition) Mascot

func (d ValidatedLoginDefinition) Mascot() []string

func (ValidatedLoginDefinition) Name

func (ValidatedLoginDefinition) Tagline

func (d ValidatedLoginDefinition) Tagline() string

type ValidatedSpriteDefinition

type ValidatedSpriteDefinition struct {
	// contains filtered or unexported fields
}

ValidatedSpriteDefinition is an immutable, renderer-ready sprite definition.

func DecodeSpriteDefinitionJSON

func DecodeSpriteDefinitionJSON(data []byte) (ValidatedSpriteDefinition, error)

DecodeSpriteDefinitionJSON strictly decodes and validates the sprite wire shape. Duplicate and unknown object fields are rejected.

func ValidateSpriteDefinition

func ValidateSpriteDefinition(definition SpriteDefinition) (ValidatedSpriteDefinition, error)

ValidateSpriteDefinition validates and defensively copies a sprite definition. The grids, palette and text follow the login definition's rules (ValidateLoginDefinition); the name has the login name's width and the tagline the login tagline's.

func (ValidatedSpriteDefinition) ID

func (ValidatedSpriteDefinition) Mascot

func (d ValidatedSpriteDefinition) Mascot() []string

func (ValidatedSpriteDefinition) Name

func (ValidatedSpriteDefinition) Palette

func (d ValidatedSpriteDefinition) Palette() map[byte]color.RGBA

Palette returns a copy of the sprite's colors by symbol.

func (ValidatedSpriteDefinition) Tagline

func (d ValidatedSpriteDefinition) Tagline() string

type VirtualModelDefinition

type VirtualModelDefinition struct {
	// Provider is the provider the virtual model is listed under. May be a provider with physical models.
	Provider string
	// ID must not be the id of a physical model of Provider.
	ID   string
	Name string
	// ThinkingLevels are the thinking levels offered for selection. Defaults to `["off"]`.
	ThinkingLevels []ai.ModelThinkingLevel
	// ContextWindow and MaxTokens are the limits shown before the first response. Afterwards, the limits of the physical model that answered apply. Unset limits are unknown (0).
	ContextWindow int
	MaxTokens     int
	// Input are the input types accepted for selection. Defaults to text and images; routed models without image support get placeholders.
	Input []string
	Route ModelRouteFunc
}

VirtualModelDefinition is a selectable catalog entry that routes each request to a physical model.

upstream: virtual-models.ts:87-101 (VirtualModelDefinition)

type VirtualModelStateData

type VirtualModelStateData struct {
	Provider string          `json:"provider"`
	ModelID  string          `json:"modelId"`
	State    json.RawMessage `json:"state"`
}

VirtualModelStateData is the data of a `pi.virtual-model-state` custom entry. State is the router's JSON state.

upstream: virtual-models.ts:35-39 (VirtualModelStateData)

type WidthLines

type WidthLines struct {
	Lines []string
	Width int
}

WidthLines is a component frame rendered outside the host (by a subprocess extension) together with the terminal width it was rendered at, so the host never paints a frame rendered for another width. Width 0 means unknown.

type WorkingIndicatorOptions

type WorkingIndicatorOptions = any

WorkingIndicatorOptions mirrors upstream WorkingIndicatorOptions.

type WriteToolCallEvent

type WriteToolCallEvent struct {
	ToolCallEventBase
	ToolName string         `json:"toolName"` // "write"
	Input    WriteToolInput `json:"input"`
}

WriteToolCallEvent: upstream types.ts WriteToolCallEvent.

type WriteToolInput

type WriteToolInput = any

type WriteToolResultEvent

type WriteToolResultEvent struct {
	ToolResultEventBase
	ToolName string `json:"toolName"` // "write"
	Details  any    `json:"details,omitempty"`
}

WriteToolResultEvent: upstream types.ts WriteToolResultEvent.

func (WriteToolResultEvent) MarshalJSON

func (e WriteToolResultEvent) MarshalJSON() ([]byte, error)

MarshalJSON writes the event in Pi's member order; see [marshalToolResultEvent].

Directories

Path Synopsis
Package builtin is the registry of upstream's built-in extensions that PiG implements natively: the `builtin:<name>` extension paths of codemode and tool-search (docs/specs/builtin-codemode-tool-search.md).
Package builtin is the registry of upstream's built-in extensions that PiG implements natively: the `builtin:<name>` extension paths of codemode and tool-search (docs/specs/builtin-codemode-tool-search.md).
codemode
Package codemode is the built-in `codemode` extension: the tool that lets the model write JavaScript that calls other tools.
Package codemode is the built-in `codemode` extension: the tool that lets the model write JavaScript that calls other tools.
toolsearch
Package toolsearch is the built-in `tool_search` extension: tool discovery with a BM25 ranker over tool metadata, shared by `searchTools()` in codemode scripts and the optional `tool_search` tool.
Package toolsearch is the built-in `tool_search` extension: tool discovery with a BM25 ranker over tool metadata, shared by `searchTools()` in codemode scripts and the optional `tool_search` tool.
Package extensiontest provides test doubles for the extension.API surface.
Package extensiontest provides test doubles for the extension.API surface.
host
cellpack
Package cellpack is the Piglet-Binary-side counterpart to the host's prebuilt-cell seam (runtimecell.PrebuiltResolver).
Package cellpack is the Piglet-Binary-side counterpart to the host's prebuilt-cell seam (runtimecell.PrebuiltResolver).
fusepack
Package fusepack holds Go extensions fused into a Piglet Binary.
Package fusepack holds Go extensions fused into a Piglet Binary.
inproc
Package inproc implements the in-process Go dispatch runner for extensions.
Package inproc implements the in-process Go dispatch runner for extensions.
runtimecell
Package runtimecell builds and resolves packed extension runtime cells.
Package runtimecell builds and resolves packed extension runtime cells.
subprocess
Package subprocess implements pig's out-of-process extension transport: extensions communicate over a local stream socket with length-prefixed JSON framing.
Package subprocess implements pig's out-of-process extension transport: extensions communicate over a local stream socket with length-prefixed JSON framing.
subprocess/internal/noderuntimegen command
Command noderuntimegen packages the Node runtime and its content identity reproducibly.
Command noderuntimegen packages the Node runtime and its content identity reproducibly.
Package installresolver is Pig's product-neutral seam for contributed package-source behavior.
Package installresolver is Pig's product-neutral seam for contributed package-source behavior.
Package pigsdk stages Pig's extension SDKs (Go, Python, and Rust) into the config root so out-of-tree extension builds and packed runtime cells can use the API that matches the running binary.
Package pigsdk stages Pig's extension SDKs (Go, Python, and Rust) into the config root so out-of-tree extension builds and packed runtime cells can use the API that matches the running binary.
Package source resolves an authorized extension path into one conventional factory or exact isolated standalone definition.
Package source resolves an authorized extension path into one conventional factory or exact isolated standalone definition.

Jump to

Keyboard shortcuts

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