/**
 * Provider-shared types for the pi harness.
 *
 * One unified message + event shape regardless of which underlying LLM API
 * (Google Gemini, OpenAI-compatible /v1/chat/completions, Anthropic Messages)
 * is handling the request. Each provider implements `streamProvider(req): AsyncIterable<StreamEvent>`
 * and the session loop consumes the events without knowing the flavor.
 *
 * Modelled after pi-ai's event vocabulary (text_start/delta/end, toolcall_*,
 * done, error) so we can copy fixes from upstream if needed, but only the
 * fields bloby actually consumes are kept.
 */

export type PiRole = 'user' | 'assistant' | 'tool';

/** A single content block inside a message. */
export type PiContentBlock =
  | { type: 'text'; text: string }
  | { type: 'image'; mediaType: string; data: string }   // base64
  // `thoughtSignature` is a Gemini 3.x thinking-model field. Pi-flavored
  // providers that emit reasoning attach it to function-call parts; the API
  // rejects the next turn with HTTP 400 if we don't echo it back verbatim.
  | { type: 'tool_use'; id: string; name: string; input: any; thoughtSignature?: string }
  | { type: 'tool_result'; toolUseId: string; content: string; isError?: boolean };

export interface PiMessage {
  role: PiRole;
  content: PiContentBlock[];
}

/** Schema for one tool the model can call. Plain JSON Schema for input. */
export interface PiToolDef {
  name: string;
  description: string;
  inputSchema: Record<string, any>;
}

export interface PiStreamRequest {
  modelId: string;
  baseUrl: string;
  apiKey: string;
  systemPrompt: string;
  messages: PiMessage[];
  tools?: PiToolDef[];
  /** Hard cap on output tokens for a single turn. */
  maxOutputTokens?: number;
  /** Optional abort signal so the session can interrupt in-flight requests. */
  signal?: AbortSignal;
}

export type PiStopReason = 'end_turn' | 'tool_use' | 'max_tokens' | 'error' | 'aborted';

export type PiStreamEvent =
  | { type: 'text_delta'; delta: string }
  | { type: 'text_end'; text: string }
  | { type: 'tool_use'; id: string; name: string; input: any; thoughtSignature?: string }
  | { type: 'done'; stopReason: PiStopReason; usage?: PiUsage }
  | { type: 'error'; error: string };

export interface PiUsage {
  inputTokens?: number;
  outputTokens?: number;
}
