package golem:llm@1.0.0;

interface llm {
  // --- Roles, Error Codes, Finish Reasons ---

  /// Roles of the conversation
  enum role {
    /// Instructions provided by the user
    user,
    /// Messages generated by the model
    assistant,
    /// Messages describing the system's rules
    system,
    /// Messages describing tool calls
    tool,
  }

  /// Possible error cases for LLM calls
  enum error-code {
    /// Invalid request parameters
    invalid-request,
    /// Authentication failed
    authentication-failed,
    /// Rate limit exceeded
    rate-limit-exceeded,
    /// Internal error
    internal-error,
    /// Unsupported operation
    unsupported,
    /// Unknown error
    unknown,
  }

  /// Reasons for finishing a conversation
  enum finish-reason {
    /// The conversation finished
    stop,
    /// Conversation finished because of reaching the maximum length
    length,
    /// Conversation finished with request for calling tools
    tool-calls,
    /// Conversation finished because of content filtering
    content-filter,
    /// Conversation finished with an error
    error,
    /// Other reason
    other,
  }

  /// Image detail levels
  enum image-detail {
    low,
    high,
    auto,
  }

  // --- Message Content ---

  /// Points to an image by an URL and an optional image detail level
  record image-url {
    /// The URL of the image
    url: string,
    /// Level of detail of the image
    detail: option<image-detail>,
  }

  /// Contains an inline image
  record image-source {
    /// Raw image data
    data: list<u8>,
    /// MIME type of the image
    mime-type: string,
    /// Level of detail of the image
    detail: option<image-detail>,
  }

  /// Contains an image, either a remote or an inlined one
  variant image-reference {
    /// A remote image
    url(image-url),
    /// An inlined image
    inline(image-source),
  }

  /// One part of the conversation
  variant content-part {
    /// Text content
    text(string),
    /// Image content
    image(image-reference),
  }

  /// A message in the conversation
  record message {
    /// Role of this message
    role: role,
    /// Name of the sender
    name: option<string>,
    /// Content of the message
    content: list<content-part>,
  }

  // --- Tooling ---

  /// Describes a tool callable by the LLM
  record tool-definition {
    /// Name of the tool
    name: string,
    /// Description of the tool
    description: option<string>,
    /// Schema of the tool's parameters - usually a JSON schema
    parameters-schema: string,
  }

  /// Describes a tool call request
  record tool-call {
    /// Call identifier
    id: string,
    /// Name of the tool
    name: string,
    /// Arguments of the tool call
    arguments-json: string,
  }

  /// Describes a successful tool call
  record tool-success {
    /// Call identifier
    id: string,
    /// Name of the tool
    name: string,
    /// Result of the tool call in JSON
    result-json: string,
    /// Execution time of the tool call in milliseconds
    execution-time-ms: option<u32>,
  }

  /// Describes a failed tool call
  record tool-failure {
    /// Call identifier
    id: string,
    /// Name of the tool
    name: string,
    /// Error message of the tool call
    error-message: string,
    /// Error code of the tool call
    error-code: option<string>,
  }

  /// Result of a tool call
  variant tool-result {
    /// The tool call succeeded
    success(tool-success),
    /// The tool call failed
    error(tool-failure),
  }

  // --- Configuration ---

  /// Simple key-value pair
  record kv {
    key: string,
    value: string,
  }

  /// LLM configuration
  record config {
    /// The model to use
    model: string,
    /// Temperature
    temperature: option<f32>,
    /// Maximum number of tokens
    max-tokens: option<u32>,
    /// A sequence where the model stops generating tokens
    stop-sequences: option<list<string>>,
    /// List of available tools
    tools: option<list<tool-definition>>,
    /// Tool choice policy
    tool-choice: option<string>,
    /// Additional LLM provider specific key-value pairs
    provider-options: option<list<kv>>,
  }

  // --- Usage / Metadata ---

  /// Token usage statistics
  record usage {
    /// Number of input tokens used
    input-tokens: option<u32>,
    /// Number of output tokens generated
    output-tokens: option<u32>,
    /// Total number of tokens used
    total-tokens: option<u32>,
  }

  /// Metadata about an LLM response
  record response-metadata {
    /// Reason for finishing the conversation
    finish-reason: option<finish-reason>,
    /// Usage statistics
    usage: option<usage>,
    /// Provider-specific ID
    provider-id: option<string>,
    /// Timestamp
    timestamp: option<string>,
    /// Provider-specific additional metadata in JSON
    provider-metadata-json: option<string>,
  }

  // --- Error Handling ---

  /// LLM error
  record error {
    /// Error code
    code: error-code,
    /// Error message
    message: string,
    /// More details in JSON, in a provider-specific format
    provider-error-json: option<string>,
  }

  // --- Chat Response ---

  /// Response from an LLM
  record response {
    /// Response ID
    id: string,
    /// Result contents
    content: list<content-part>,
    /// Tool call requests
    tool-calls: list<tool-call>,
    /// Response metadata
    metadata: response-metadata,
  }

  // --- Chat event  ---

  /// Chat events that can happen during a chat session
  variant event {
    /// Message asked by the user
    message(message),
    /// Response from the LLM
    response(response),
    /// Provided tool results
    tool-results(list<tool-result>),
  }

  // --- Streaming ---

  /// Changes in a streaming conversation
  record stream-delta {
    /// New content parts
    content: option<list<content-part>>,
    /// New tool calls
    tool-calls: option<list<tool-call>>,
  }

  /// Event in a streaming conversation
  variant stream-event {
    /// New incoming response content or tool call requests
    delta(stream-delta),
    /// Converstation finished
    finish(response-metadata),
  }

  /// Represents an ongoing streaming LLM conversation
  resource chat-stream {
    /// Polls for the next chunk of stream events
    poll-next: func() -> option<list<result<stream-event, error>>>;
    /// Blocks until the next chunk of stream events is available
    get-next: func() -> list<result<stream-event, error>>;
  }

  // --- Core Functions ---

  /// Make a single call to the LLM.
  /// To continue the conversation:
  /// - append tool responses and new messages to the events and use send again
  /// - or use the chat-session wrapper, which help in maintaining the chat events
  send: func(
    events: list<event>,
    config: config,
  ) -> result<response, error>;

  /// Makes a single call to the LLM and gets back a streaming API to receive the response in chunks.
  %stream: func(
    events: list<event>,
    config: config,
  ) -> chat-stream;
}

world llm-library {
    export llm;
}
