/** * Wire definitions for transcript content: content blocks, usage, agent * messages, assistant streaming events, and the model descriptor. * * Message shapes are owned by `pi-ai`/`pi-agent-core` and grow often. Every * object in `messageDefs` is an open record (`x-open` in the bundle): clients * check the discriminator (`role`, `type`) and pass every other key through, so * persisted messages missing newer fields still decode. The conformance test * pins the discriminator sets. */ import { doc, type WireDefs } from "./dsl"; const JSON_OBJECT = "Record"; /** Open records: transcript content, messages, usage, and assistant streaming events. */ export const messageDefs = { Attribution: doc("'user' | 'agent'", "Who initiated a message, for billing and attribution."), StopReason: "'stop' | 'length' | 'toolUse' | 'error' | 'aborted'", TextContent: { type: "'text'", text: "string", "textSignature?": "string" }, ThinkingContent: { type: "'thinking'", thinking: "string", "thinkingSignature?": "string", "itemId?": "string", "narration?": doc( "boolean", "Prose the model addressed to the user, returned by the provider as thinking; present it as answer text.", ), }, RedactedThinkingContent: { type: "'redactedThinking'", data: "string" }, ImageContent: doc( { type: "'image'", data: doc("string", "Base64-encoded image bytes."), mimeType: "string", "detail?": "'auto' | 'low' | 'high' | 'original'", "url?": "string", "providerFile?": JSON_OBJECT, }, "Inline image; also the shape hosts send with prompts.", ), ToolCall: { type: "'toolCall'", id: "string", name: "string", arguments: JSON_OBJECT, "thoughtSignature?": "string", "intent?": "string", "rawBlock?": "string", "customWireName?": "string", "providerMetadata?": JSON_OBJECT, }, FallbackContent: doc( { type: "'fallback'", from: JSON_OBJECT, to: JSON_OBJECT }, "Anthropic server-side fallback boundary marker; consumers other than Anthropic ignore it.", ), AnthropicServerToolContent: { type: "'anthropicServerTool'", block: JSON_OBJECT }, UserContent: "TextContent | ImageContent", MessageContent: doc("string | UserContent[]", "Message content: plain text or content blocks."), AssistantContent: "TextContent | ThinkingContent | RedactedThinkingContent | FallbackContent | AnthropicServerToolContent | ImageContent | ToolCall", UsageCost: { input: "number", output: "number", cacheRead: "number", cacheWrite: "number", total: "number", }, Usage: { input: "number.integer", output: "number.integer", cacheRead: "number.integer", cacheWrite: "number.integer", totalTokens: "number.integer", "contextTokens?": "number.integer", "premiumRequests?": "number", "reasoningTokens?": "number.integer", "orchestration?": JSON_OBJECT, "cttl?": JSON_OBJECT, "server?": JSON_OBJECT, "credits?": JSON_OBJECT, cost: "UsageCost", }, ParentIrc: doc( { from: doc("string", "Sending parent agent id."), body: doc("string", "Message body as the parent wrote it.") }, "Parent-agent IRC message carried by a steer; render it instead of the model-facing `content` envelope.", ), UserMessage: { role: "'user'", content: "MessageContent", "parentIrc?": "ParentIrc", "synthetic?": "boolean", "steering?": "boolean", "liveSteered?": "boolean", "historyRewriteAt?": "number", "attribution?": "Attribution", "providerPayload?": JSON_OBJECT, timestamp: "number", }, DeveloperMessage: { role: "'developer'", content: "MessageContent", "attribution?": "Attribution", "synthetic?": "boolean", "userInitiated?": "boolean", "providerPayload?": JSON_OBJECT, timestamp: "number", }, AssistantMessage: { role: "'assistant'", content: "AssistantContent[]", api: "string", provider: "string", model: "string", "responseId?": "string", "upstreamProvider?": "string", "upstreamModel?": "string", usage: "Usage", stopReason: "StopReason", "errorMessage?": "string", "errorStatus?": "number.integer", "errorId?": "number", "providerPayload?": JSON_OBJECT, timestamp: "number", "duration?": "number", "ttft?": "number", "completedAt?": "number", }, ToolResultMessage: { role: "'toolResult'", toolCallId: "string", toolName: "string", content: "UserContent[]", "details?": "unknown", isError: "boolean", "attribution?": "Attribution", "prunedAt?": "number", "useless?": "boolean", timestamp: "number", }, BashExecutionMessage: { role: "'bashExecution'", command: "string", output: "string", "exitCode?": "number.integer", cancelled: "boolean", truncated: "boolean", "images?": "ImageContent[]", "meta?": JSON_OBJECT, timestamp: "number", "excludeFromContext?": "boolean", }, PythonExecutionMessage: { role: "'pythonExecution'", code: "string", output: "string", "exitCode?": "number.integer", cancelled: "boolean", truncated: "boolean", "meta?": JSON_OBJECT, timestamp: "number", "excludeFromContext?": "boolean", }, CustomMessage: { role: "'custom'", customType: "string", content: "MessageContent", display: "boolean", "details?": "unknown", "attribution?": "Attribution", timestamp: "number", }, HookMessage: { role: "'hookMessage'", customType: "string", content: "MessageContent", display: "boolean", "details?": "unknown", "attribution?": "Attribution", timestamp: "number", }, BranchSummaryMessage: { role: "'branchSummary'", summary: "string", fromId: "string", timestamp: "number" }, CompactionSummaryMessage: { role: "'compactionSummary'", summary: "string", "shortSummary?": "string", tokensBefore: "number.integer", "tokensAfter?": "number.integer", "method?": "string", "providerPayload?": JSON_OBJECT, timestamp: "number", }, FileMentionItem: { path: "string", content: "string", "lineCount?": "number.integer", "byteSize?": "number.integer", "skippedReason?": "'tooLarge' | 'binary'", "image?": "ImageContent", }, FileMentionMessage: { role: "'fileMention'", files: "FileMentionItem[]", timestamp: "number" }, AgentMessage: doc( "UserMessage | DeveloperMessage | AssistantMessage | ToolResultMessage | BashExecutionMessage | PythonExecutionMessage | CustomMessage | HookMessage | BranchSummaryMessage | CompactionSummaryMessage | FileMentionMessage", "A transcript message, discriminated by `role`.", ), AssistantStartEvent: { type: "'start'", partial: "AssistantMessage" }, AssistantTextStartEvent: { type: "'text_start'", contentIndex: "number.integer", partial: "AssistantMessage" }, AssistantTextDeltaEvent: { type: "'text_delta'", contentIndex: "number.integer", delta: "string", partial: "AssistantMessage", }, AssistantTextEndEvent: { type: "'text_end'", contentIndex: "number.integer", content: "string", partial: "AssistantMessage", }, AssistantThinkingStartEvent: { type: "'thinking_start'", contentIndex: "number.integer", partial: "AssistantMessage", }, AssistantThinkingDeltaEvent: { type: "'thinking_delta'", contentIndex: "number.integer", delta: "string", partial: "AssistantMessage", }, AssistantThinkingEndEvent: { type: "'thinking_end'", contentIndex: "number.integer", content: "string", partial: "AssistantMessage", }, AssistantImageEndEvent: { type: "'image_end'", contentIndex: "number.integer", content: "ImageContent", partial: "AssistantMessage", }, AssistantToolCallStartEvent: { type: "'toolcall_start'", contentIndex: "number.integer", partial: "AssistantMessage", }, AssistantToolCallDeltaEvent: { type: "'toolcall_delta'", contentIndex: "number.integer", delta: "string", partial: "AssistantMessage", }, AssistantToolCallEndEvent: { type: "'toolcall_end'", contentIndex: "number.integer", toolCall: "ToolCall", partial: "AssistantMessage", }, AssistantDoneEvent: { type: "'done'", reason: "'stop' | 'length' | 'toolUse'", message: "AssistantMessage" }, AssistantErrorEvent: { type: "'error'", reason: "'aborted' | 'error'", error: "AssistantMessage" }, AssistantMessageEvent: doc( "AssistantStartEvent | AssistantTextStartEvent | AssistantTextDeltaEvent | AssistantTextEndEvent | AssistantThinkingStartEvent | AssistantThinkingDeltaEvent | AssistantThinkingEndEvent | AssistantImageEndEvent | AssistantToolCallStartEvent | AssistantToolCallDeltaEvent | AssistantToolCallEndEvent | AssistantDoneEvent | AssistantErrorEvent", "Streaming update for one assistant message, discriminated by `type`.", ), } satisfies WireDefs; /** Model and thinking descriptors. */ export const modelDefs = { Effort: "'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'", ThinkingLevel: doc( "'inherit' | 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'", "Thinking selector; `inherit` defers to a higher-level selector.", ), ConfiguredThinkingLevel: doc( "'auto' | 'inherit' | 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max'", "User-configured thinking selector, including automatic selection.", ), ModelCost: doc( { input: "number", output: "number", cacheRead: "number", cacheWrite: "number" }, "Per-million-token USD rates.", ), ThinkingConfig: { mode: "string", efforts: "Effort[]", "defaultLevel?": "Effort", "effortMap?": "Record", "supportsDisplay?": "boolean", "prefixBinding?": "boolean", "effortRouting?": "Record", "effortBudgets?": "Record", "suppressWhenOff?": "boolean", "requiresEffort?": "boolean", }, ModelInfo: doc( { id: "string", name: "string", api: "string", provider: "string", baseUrl: "string", reasoning: "boolean", input: doc("string[]", "Accepted input modalities, e.g. `text`, `image`."), cost: "ModelCost", contextWindow: doc("number.integer | null", "Null when the provider does not report a limit."), maxTokens: doc("number.integer | null", "Null when the provider does not report a limit."), "headers?": "Record", "premiumMultiplier?": "number", "preferWebsockets?": "boolean", "contextPromotionTarget?": "string", "priority?": "number.integer", "thinking?": "ThinkingConfig", "compat?": JSON_OBJECT, }, "Model descriptor: the client-relevant subset of the server's model record.", ), } satisfies WireDefs;