{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -Wno-partial-fields #-}
{- |
Module : Gemini.Client.Types
Description : Typed data models for Google Gemini Interactions v1 API and Embeddings
Copyright : (c) 2025-2026 Tushar Adhatrao
License : MIT
Maintainer : Tushar Adhatrao <tusharadhatrao@gmail.com>
Stability : experimental
Fully-typed OpenAPI data models corresponding to the Google Gemini Interactions v1 API
(<https://ai.google.dev/static/api/interactions-v1.openapi.json>) and Embeddings endpoints.
-}
module Gemini.Client.Types
( -- * Interactions
Interaction (..)
, InteractionStatus (..)
, CreateInteractionRequest (..)
, defaultCreateInteractionRequest
, createModelInteraction
, createAgentInteraction
-- * Inputs and Contents
, InteractionsInput (..)
, Content (..)
-- * Steps
, Step (..)
, GoogleSearchResultItem (..)
-- * Tools
, Tool (..)
, functionTool
-- * Generation and Output
, GenerationConfig (..)
, defaultGenerationConfig
, ResponseFormat (..)
, jsonResponseFormat
, Usage (..)
, ErrorDetail (..)
-- * Streaming Events
, InteractionSseEvent (..)
, StepDeltaData (..)
-- * Embeddings
, EmbedContentRequest (..)
, EmbedContentPayload (..)
, EmbedPart (..)
, EmbedContentResponse (..)
, EmbeddingValues (..)
, BatchEmbedContentsRequest (..)
, BatchEmbedRequestItem (..)
, BatchEmbedContentsResponse (..)
) where
import Control.Applicative ((<|>))
import Data.Aeson
import qualified Data.Aeson.KeyMap as KM
import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Text as T
import GHC.Generics (Generic)
-- ---------------------------------------------------------------------------
-- Interaction & Status
-- ---------------------------------------------------------------------------
-- | Lifecycle status of an Interaction.
data InteractionStatus
= StatusInProgress
| StatusRequiresAction
| StatusCompleted
| StatusFailed
| StatusCancelled
| StatusIncomplete
deriving (Eq, Show, Generic)
instance ToJSON InteractionStatus where
toJSON = \case
StatusInProgress -> "in_progress"
StatusRequiresAction -> "requires_action"
StatusCompleted -> "completed"
StatusFailed -> "failed"
StatusCancelled -> "cancelled"
StatusIncomplete -> "incomplete"
instance FromJSON InteractionStatus where
parseJSON = withText "InteractionStatus" $ \case
"in_progress" -> pure StatusInProgress
"requires_action" -> pure StatusRequiresAction
"completed" -> pure StatusCompleted
"failed" -> pure StatusFailed
"cancelled" -> pure StatusCancelled
"incomplete" -> pure StatusIncomplete
other -> fail $ "Unknown InteractionStatus: " ++ T.unpack other
-- | An Interaction resource generated by Gemini.
data Interaction = Interaction
{ interactionId :: !Text
, interactionObject :: !(Maybe Text)
, interactionModel :: !(Maybe Text)
, interactionAgent :: !(Maybe Text)
, interactionStatus :: !InteractionStatus
, interactionSteps :: ![Step]
, interactionUsage :: !(Maybe Usage)
, interactionCreated :: !(Maybe Text)
, interactionUpdated :: !(Maybe Text)
, interactionBackground :: !(Maybe Bool)
, interactionStore :: !(Maybe Bool)
, interactionStream :: !(Maybe Bool)
, interactionSystemInstruction :: !(Maybe Text)
, interactionTools :: !(Maybe [Tool])
, interactionGenerationConfig :: !(Maybe GenerationConfig)
, interactionResponseFormat :: !(Maybe ResponseFormat)
, interactionPreviousInteractionId :: !(Maybe Text)
, interactionErrors :: !(Maybe [ErrorDetail])
}
deriving (Eq, Show, Generic)
instance FromJSON Interaction where
parseJSON = withObject "Interaction" $ \o -> do
interactionId <- o .:? "id" .!= ""
interactionObject <- o .:? "object"
interactionModel <- o .:? "model"
interactionAgent <- o .:? "agent"
interactionStatus <- o .:? "status" .!= StatusCompleted
interactionSteps <- o .:? "steps" .!= []
interactionUsage <- o .:? "usage"
interactionCreated <- o .:? "created"
interactionUpdated <- o .:? "updated"
interactionBackground <- o .:? "background"
interactionStore <- o .:? "store"
interactionStream <- o .:? "stream"
interactionSystemInstruction <- o .:? "system_instruction"
interactionTools <- o .:? "tools"
interactionGenerationConfig <- o .:? "generation_config"
interactionResponseFormat <- o .:? "response_format"
interactionPreviousInteractionId <- o .:? "previous_interaction_id"
interactionErrors <- o .:? "errors"
pure Interaction {..}
instance ToJSON Interaction where
toJSON Interaction {..} =
object $
catMaybes
[ Just ("id" .= interactionId)
, ("object" .=) <$> interactionObject
, ("model" .=) <$> interactionModel
, ("agent" .=) <$> interactionAgent
, Just ("status" .= interactionStatus)
, Just ("steps" .= interactionSteps)
, ("usage" .=) <$> interactionUsage
, ("created" .=) <$> interactionCreated
, ("updated" .=) <$> interactionUpdated
, ("background" .=) <$> interactionBackground
, ("store" .=) <$> interactionStore
, ("stream" .=) <$> interactionStream
, ("system_instruction" .=) <$> interactionSystemInstruction
, ("tools" .=) <$> interactionTools
, ("generation_config" .=) <$> interactionGenerationConfig
, ("response_format" .=) <$> interactionResponseFormat
, ("previous_interaction_id" .=) <$> interactionPreviousInteractionId
, ("errors" .=) <$> interactionErrors
]
-- | Diagnostics and error records.
data ErrorDetail = ErrorDetail
{ errorCode :: !(Maybe Text)
, errorMessage :: !Text
}
deriving (Eq, Show, Generic, ToJSON, FromJSON)
-- ---------------------------------------------------------------------------
-- Contents
-- ---------------------------------------------------------------------------
-- | Multimodal content part.
data Content
= TextContent !Text
| -- | mime_type, base64 data
ImageContent !Text !Text
| -- | mime_type, base64 data
AudioContent !Text !Text
| -- | mime_type, base64 data
DocumentContent !Text !Text
deriving (Eq, Show, Generic)
instance ToJSON Content where
toJSON = \case
TextContent txt ->
object ["type" .= ("text" :: Text), "text" .= txt]
ImageContent mime b64 ->
object ["type" .= ("image" :: Text), "mime_type" .= mime, "data" .= b64]
AudioContent mime b64 ->
object ["type" .= ("audio" :: Text), "mime_type" .= mime, "data" .= b64]
DocumentContent mime b64 ->
object ["type" .= ("document" :: Text), "mime_type" .= mime, "data" .= b64]
instance FromJSON Content where
parseJSON = withObject "Content" $ \o -> do
t <- o .: "type"
case (t :: Text) of
"text" -> TextContent <$> o .: "text"
"image" -> ImageContent <$> o .: "mime_type" <*> o .: "data"
"audio" -> AudioContent <$> o .: "mime_type" <*> o .: "data"
"document" -> DocumentContent <$> o .: "mime_type" <*> o .: "data"
other -> fail $ "Unknown Content type: " ++ T.unpack other
-- ---------------------------------------------------------------------------
-- Steps
-- ---------------------------------------------------------------------------
-- | Single step within an interaction turn.
data Step
= UserInputStep ![Content]
| ModelOutputStep ![Content]
| FunctionCallStep
{ callName :: !Text
, callArguments :: !Value
, callId :: !Text
}
| FunctionResultStep
{ resultCallId :: !Text
, resultName :: !(Maybe Text)
, resultPayload :: !Value
, resultIsError :: !(Maybe Bool)
}
| ThoughtStep
{ thoughtSignature :: !(Maybe Text)
, thoughtSummary :: !(Maybe [Content])
}
| CodeExecutionCallStep
{ codeCallId :: !Text
, codeCallCode :: !Text
, codeCallSignature :: !(Maybe Text)
}
| CodeExecutionResultStep
{ codeResultCallId :: !Text
, codeResultOutput :: !Text
, codeResultIsError :: !(Maybe Bool)
}
| GoogleSearchCallStep
{ searchCallId :: !Text
, searchQuery :: !Text
, searchType :: !(Maybe Text)
}
| GoogleSearchResultStep
{ searchResultCallId :: !Text
, searchResultItems :: ![GoogleSearchResultItem]
}
| GoogleMapsCallStep
{ mapsCallId :: !Text
, mapsQuery :: !(Maybe Text)
}
| GoogleMapsResultStep
{ mapsResultCallId :: !Text
, mapsResultPayload :: !(Maybe Value)
}
| FileSearchCallStep
{ fileSearchCallId :: !Text
, fileSearchQuery :: !(Maybe Text)
}
| FileSearchResultStep
{ fileSearchResultCallId :: !Text
, fileSearchResultPayload :: !(Maybe Value)
}
| UrlContextCallStep
{ urlCallId :: !Text
, urlQuery :: !(Maybe Text)
}
| UrlContextResultStep
{ urlResultCallId :: !Text
, urlResultPayload :: !(Maybe Value)
}
deriving (Eq, Show, Generic)
-- | Google Search result snippet.
data GoogleSearchResultItem = GoogleSearchResultItem
{ searchTitle :: !(Maybe Text)
, searchUrl :: !(Maybe Text)
, searchSnippet :: !(Maybe Text)
}
deriving (Eq, Show, Generic)
instance FromJSON GoogleSearchResultItem where
parseJSON = withObject "GoogleSearchResultItem" $ \o -> do
searchTitle <- o .:? "title"
searchUrl <- o .:? "url"
searchSnippet <- o .:? "snippet"
pure GoogleSearchResultItem {..}
instance ToJSON GoogleSearchResultItem where
toJSON GoogleSearchResultItem {..} =
object $
catMaybes
[ ("title" .=) <$> searchTitle
, ("url" .=) <$> searchUrl
, ("snippet" .=) <$> searchSnippet
]
instance ToJSON Step where
toJSON = \case
UserInputStep cs ->
object ["type" .= ("user_input" :: Text), "content" .= cs]
ModelOutputStep cs ->
object ["type" .= ("model_output" :: Text), "content" .= cs]
FunctionCallStep {..} ->
object
[ "type" .= ("function_call" :: Text)
, "name" .= callName
, "arguments" .= callArguments
, "id" .= callId
]
FunctionResultStep {..} ->
object $
[ "type" .= ("function_result" :: Text)
, "call_id" .= resultCallId
, "result" .= resultPayload
]
++ catMaybes
[ ("name" .=) <$> resultName
, ("is_error" .=) <$> resultIsError
]
ThoughtStep {..} ->
object $
("type" .= ("thought" :: Text))
: catMaybes
[ ("signature" .=) <$> thoughtSignature
, ("summary" .=) <$> thoughtSummary
]
CodeExecutionCallStep {..} ->
object $
[ "type" .= ("code_execution_call" :: Text)
, "id" .= codeCallId
, "arguments" .= object ["code" .= codeCallCode]
]
++ catMaybes [("signature" .=) <$> codeCallSignature]
CodeExecutionResultStep {..} ->
object $
[ "type" .= ("code_execution_result" :: Text)
, "call_id" .= codeResultCallId
, "result" .= codeResultOutput
]
++ catMaybes [("is_error" .=) <$> codeResultIsError]
GoogleSearchCallStep {..} ->
object $
[ "type" .= ("google_search_call" :: Text)
, "id" .= searchCallId
, "arguments" .= object ["query" .= searchQuery]
]
++ catMaybes [("search_type" .=) <$> searchType]
GoogleSearchResultStep {..} ->
object
[ "type" .= ("google_search_result" :: Text)
, "call_id" .= searchResultCallId
, "result" .= searchResultItems
]
GoogleMapsCallStep {..} ->
object $
("type" .= ("google_maps_call" :: Text))
: ("id" .= mapsCallId)
: catMaybes [("query" .=) <$> mapsQuery]
GoogleMapsResultStep {..} ->
object $
("type" .= ("google_maps_result" :: Text))
: ("call_id" .= mapsResultCallId)
: catMaybes [("result" .=) <$> mapsResultPayload]
FileSearchCallStep {..} ->
object $
("type" .= ("file_search_call" :: Text))
: ("id" .= fileSearchCallId)
: catMaybes [("query" .=) <$> fileSearchQuery]
FileSearchResultStep {..} ->
object $
("type" .= ("file_search_result" :: Text))
: ("call_id" .= fileSearchResultCallId)
: catMaybes [("result" .=) <$> fileSearchResultPayload]
UrlContextCallStep {..} ->
object $
("type" .= ("url_context_call" :: Text))
: ("id" .= urlCallId)
: catMaybes [("query" .=) <$> urlQuery]
UrlContextResultStep {..} ->
object $
("type" .= ("url_context_result" :: Text))
: ("call_id" .= urlResultCallId)
: catMaybes [("result" .=) <$> urlResultPayload]
instance FromJSON Step where
parseJSON = withObject "Step" $ \o -> do
t <- o .: "type"
case (t :: Text) of
"user_input" -> UserInputStep <$> (o .:? "content" .!= [])
"model_output" -> ModelOutputStep <$> (o .:? "content" .!= [])
"function_call" -> do
callName <- o .: "name"
callArguments <- o .:? "arguments" .!= object []
callId <- o .:? "id" .!= ""
pure FunctionCallStep {..}
"function_result" -> do
resultCallId <- o .: "call_id"
resultName <- o .:? "name"
resultPayload <- o .: "result"
resultIsError <- o .:? "is_error"
pure FunctionResultStep {..}
"thought" -> do
thoughtSignature <- o .:? "signature"
thoughtSummary <- o .:? "summary"
pure ThoughtStep {..}
"code_execution_call" -> do
codeCallId <- o .:? "id" .!= ""
args <- o .:? "arguments" .!= object []
codeCallCode <- case args of
Object ao -> ao .:? "code" .!= ""
_ -> pure ""
codeCallSignature <- o .:? "signature"
pure CodeExecutionCallStep {..}
"code_execution_result" -> do
codeResultCallId <- o .: "call_id"
codeResultOutput <- o .:? "result" .!= ""
codeResultIsError <- o .:? "is_error"
pure CodeExecutionResultStep {..}
"google_search_call" -> do
searchCallId <- o .:? "id" .!= ""
args <- o .:? "arguments" .!= object []
searchQuery <- case args of
Object ao -> ao .:? "query" .!= ""
_ -> pure ""
searchType <- o .:? "search_type"
pure GoogleSearchCallStep {..}
"google_search_result" -> do
searchResultCallId <- o .: "call_id"
searchResultItems <- o .:? "result" .!= []
pure GoogleSearchResultStep {..}
"google_maps_call" -> do
mapsCallId <- o .:? "id" .!= ""
mapsQuery <- o .:? "query"
pure GoogleMapsCallStep {..}
"google_maps_result" -> do
mapsResultCallId <- o .: "call_id"
mapsResultPayload <- o .:? "result"
pure GoogleMapsResultStep {..}
"file_search_call" -> do
fileSearchCallId <- o .:? "id" .!= ""
fileSearchQuery <- o .:? "query"
pure FileSearchCallStep {..}
"file_search_result" -> do
fileSearchResultCallId <- o .: "call_id"
fileSearchResultPayload <- o .:? "result"
pure FileSearchResultStep {..}
"url_context_call" -> do
urlCallId <- o .:? "id" .!= ""
urlQuery <- o .:? "query"
pure UrlContextCallStep {..}
"url_context_result" -> do
urlResultCallId <- o .: "call_id"
urlResultPayload <- o .:? "result"
pure UrlContextResultStep {..}
other -> fail $ "Unknown Step type: " ++ T.unpack other
-- ---------------------------------------------------------------------------
-- InteractionsInput
-- ---------------------------------------------------------------------------
-- | Flexible input format for Interaction creation.
data InteractionsInput
= TextInput !Text
| ContentInput !Content
| ContentListInput ![Content]
| StepListInput ![Step]
deriving (Eq, Show, Generic)
instance ToJSON InteractionsInput where
toJSON = \case
TextInput t -> toJSON t
ContentInput c -> toJSON c
ContentListInput cs -> toJSON cs
StepListInput ss -> toJSON ss
instance FromJSON InteractionsInput where
parseJSON v = case v of
String s -> pure $ TextInput s
Array arr ->
(StepListInput <$> parseJSON (Array arr))
<|> (ContentListInput <$> parseJSON (Array arr))
Object _ -> ContentInput <$> parseJSON v
_ -> fail "Invalid InteractionsInput format"
-- ---------------------------------------------------------------------------
-- Tools
-- ---------------------------------------------------------------------------
-- | Built-in or custom tool declared for the model.
data Tool
= FunctionTool
{ functionName :: !Text
, functionDescription :: !(Maybe Text)
, functionParameters :: !(Maybe Value)
}
| GoogleSearchTool
| GoogleMapsTool
{ mapsLatitude :: !(Maybe Double)
, mapsLongitude :: !(Maybe Double)
}
| CodeExecutionTool
| FileSearchTool
{ fileSearchStoreNames :: !(Maybe [Text])
}
| UrlContextTool
deriving (Eq, Show, Generic)
-- | Construct a standard function tool.
functionTool :: Text -> Maybe Text -> Maybe Value -> Tool
functionTool = FunctionTool
instance ToJSON Tool where
toJSON = \case
FunctionTool {..} ->
object $
[ "type" .= ("function" :: Text)
, "name" .= functionName
]
++ catMaybes
[ ("description" .=) <$> functionDescription
, ("parameters" .=) <$> functionParameters
]
GoogleSearchTool ->
object ["type" .= ("google_search" :: Text)]
GoogleMapsTool {..} ->
object $
("type" .= ("google_maps" :: Text))
: catMaybes
[ ("latitude" .=) <$> mapsLatitude
, ("longitude" .=) <$> mapsLongitude
]
CodeExecutionTool ->
object ["type" .= ("code_execution" :: Text)]
FileSearchTool {..} ->
object $
("type" .= ("file_search" :: Text))
: catMaybes [("file_search_store_names" .=) <$> fileSearchStoreNames]
UrlContextTool ->
object ["type" .= ("url_context" :: Text)]
instance FromJSON Tool where
parseJSON = withObject "Tool" $ \o -> do
t <- o .: "type"
case (t :: Text) of
"function" -> do
functionName <- o .: "name"
functionDescription <- o .:? "description"
functionParameters <- o .:? "parameters"
pure FunctionTool {..}
"google_search" -> pure GoogleSearchTool
"google_maps" -> do
mapsLatitude <- o .:? "latitude"
mapsLongitude <- o .:? "longitude"
pure GoogleMapsTool {..}
"code_execution" -> pure CodeExecutionTool
"file_search" -> do
fileSearchStoreNames <- o .:? "file_search_store_names"
pure FileSearchTool {..}
"url_context" -> pure UrlContextTool
other -> fail $ "Unknown Tool type: " ++ T.unpack other
-- ---------------------------------------------------------------------------
-- GenerationConfig & ResponseFormat
-- ---------------------------------------------------------------------------
-- | Model generation parameters.
data GenerationConfig = GenerationConfig
{ maxOutputTokens :: !(Maybe Int)
, seed :: !(Maybe Int)
, stopSequences :: !(Maybe [Text])
, thinkingLevel :: !(Maybe Text)
, thinkingSummaries :: !(Maybe Bool)
, toolChoice :: !(Maybe Text)
}
deriving (Eq, Show, Generic)
-- | Default generation configuration with all options unset.
defaultGenerationConfig :: GenerationConfig
defaultGenerationConfig = GenerationConfig Nothing Nothing Nothing Nothing Nothing Nothing
instance ToJSON GenerationConfig where
toJSON GenerationConfig {..} =
object $
catMaybes
[ ("max_output_tokens" .=) <$> maxOutputTokens
, ("seed" .=) <$> seed
, ("stop_sequences" .=) <$> stopSequences
, ("thinking_level" .=) <$> thinkingLevel
, ("thinking_summaries" .=) <$> thinkingSummaries
, ("tool_choice" .=) <$> toolChoice
]
instance FromJSON GenerationConfig where
parseJSON = withObject "GenerationConfig" $ \o -> do
maxOutputTokens <- o .:? "max_output_tokens"
seed <- o .:? "seed"
stopSequences <- o .:? "stop_sequences"
thinkingLevel <- o .:? "thinking_level"
thinkingSummaries <- o .:? "thinking_summaries"
toolChoice <- o .:? "tool_choice"
pure GenerationConfig {..}
-- | Structured output format specification.
data ResponseFormat
= TextResponseFormat
{ responseMimeType :: !(Maybe Text)
, responseSchema :: !(Maybe Value)
}
deriving (Eq, Show, Generic)
-- | Construct a JSON Schema response format constraint.
jsonResponseFormat :: Value -> ResponseFormat
jsonResponseFormat s = TextResponseFormat (Just "application/json") (Just s)
instance ToJSON ResponseFormat where
toJSON (TextResponseFormat mime sch) =
object $
("type" .= ("text" :: Text))
: catMaybes
[ ("mime_type" .=) <$> mime
, ("schema" .=) <$> sch
]
instance FromJSON ResponseFormat where
parseJSON = withObject "ResponseFormat" $ \o -> do
responseMimeType <- o .:? "mime_type"
responseSchema <- o .:? "schema"
pure TextResponseFormat {..}
-- ---------------------------------------------------------------------------
-- Usage
-- ---------------------------------------------------------------------------
-- | Token usage statistics.
data Usage = Usage
{ totalInputTokens :: !(Maybe Int)
, totalOutputTokens :: !(Maybe Int)
, totalTokens :: !(Maybe Int)
, totalThoughtTokens :: !(Maybe Int)
, totalToolUseTokens :: !(Maybe Int)
, totalCachedTokens :: !(Maybe Int)
}
deriving (Eq, Show, Generic)
instance FromJSON Usage where
parseJSON = withObject "Usage" $ \o -> do
totalInputTokens <- o .:? "total_input_tokens"
totalOutputTokens <- o .:? "total_output_tokens"
totalTokens <- o .:? "total_tokens"
totalThoughtTokens <- o .:? "total_thought_tokens"
totalToolUseTokens <- o .:? "total_tool_use_tokens"
totalCachedTokens <- o .:? "total_cached_tokens"
pure Usage {..}
instance ToJSON Usage where
toJSON Usage {..} =
object $
catMaybes
[ ("total_input_tokens" .=) <$> totalInputTokens
, ("total_output_tokens" .=) <$> totalOutputTokens
, ("total_tokens" .=) <$> totalTokens
, ("total_thought_tokens" .=) <$> totalThoughtTokens
, ("total_tool_use_tokens" .=) <$> totalToolUseTokens
, ("total_cached_tokens" .=) <$> totalCachedTokens
]
-- ---------------------------------------------------------------------------
-- CreateInteractionRequest
-- ---------------------------------------------------------------------------
-- | Request envelope for POST \/v1\/interactions.
data CreateInteractionRequest = CreateInteractionRequest
{ reqModel :: !(Maybe Text)
, reqAgent :: !(Maybe Text)
, reqInput :: !InteractionsInput
, reqSystemInstruction :: !(Maybe Text)
, reqTools :: !(Maybe [Tool])
, reqGenerationConfig :: !(Maybe GenerationConfig)
, reqResponseFormat :: !(Maybe ResponseFormat)
, reqPreviousInteractionId :: !(Maybe Text)
, reqBackground :: !(Maybe Bool)
, reqStore :: !(Maybe Bool)
, reqStream :: !(Maybe Bool)
}
deriving (Eq, Show, Generic)
-- | Construct a base request.
defaultCreateInteractionRequest :: InteractionsInput -> CreateInteractionRequest
defaultCreateInteractionRequest input =
CreateInteractionRequest
{ reqModel = Nothing
, reqAgent = Nothing
, reqInput = input
, reqSystemInstruction = Nothing
, reqTools = Nothing
, reqGenerationConfig = Nothing
, reqResponseFormat = Nothing
, reqPreviousInteractionId = Nothing
, reqBackground = Nothing
, reqStore = Nothing
, reqStream = Nothing
}
-- | Helper to create a model-based interaction.
createModelInteraction :: Text -> InteractionsInput -> CreateInteractionRequest
createModelInteraction modelName input =
(defaultCreateInteractionRequest input) {reqModel = Just modelName}
-- | Helper to create an agent-based interaction.
createAgentInteraction :: Text -> InteractionsInput -> CreateInteractionRequest
createAgentInteraction agentName input =
(defaultCreateInteractionRequest input) {reqAgent = Just agentName}
instance ToJSON CreateInteractionRequest where
toJSON CreateInteractionRequest {..} =
object $
("input" .= reqInput)
: catMaybes
[ ("model" .=) <$> reqModel
, ("agent" .=) <$> reqAgent
, ("system_instruction" .=) <$> reqSystemInstruction
, ("tools" .=) <$> reqTools
, ("generation_config" .=) <$> reqGenerationConfig
, ("response_format" .=) <$> reqResponseFormat
, ("previous_interaction_id" .=) <$> reqPreviousInteractionId
, ("background" .=) <$> reqBackground
, ("store" .=) <$> reqStore
, ("stream" .=) <$> reqStream
]
instance FromJSON CreateInteractionRequest where
parseJSON = withObject "CreateInteractionRequest" $ \o -> do
reqModel <- o .:? "model"
reqAgent <- o .:? "agent"
reqInput <- o .: "input"
reqSystemInstruction <- o .:? "system_instruction"
reqTools <- o .:? "tools"
reqGenerationConfig <- o .:? "generation_config"
reqResponseFormat <- o .:? "response_format"
reqPreviousInteractionId <- o .:? "previous_interaction_id"
reqBackground <- o .:? "background"
reqStore <- o .:? "store"
reqStream <- o .:? "stream"
pure CreateInteractionRequest {..}
-- ---------------------------------------------------------------------------
-- Server-Sent Events (SSE) Streaming
-- ---------------------------------------------------------------------------
-- | Incremental delta updates emitted during streaming.
data StepDeltaData
= TextDelta !Text
| ArgumentsDelta !Text
| ThoughtSignatureDelta !Text
| OtherDelta !Text !Value
deriving (Eq, Show, Generic)
instance FromJSON StepDeltaData where
parseJSON = withObject "StepDeltaData" $ \o -> do
t <- o .: "type"
case (t :: Text) of
"text" -> TextDelta <$> o .: "text"
"arguments" -> ArgumentsDelta <$> o .: "arguments"
"thought_signature" -> ThoughtSignatureDelta <$> o .: "signature"
other -> pure $ OtherDelta other (Object o)
instance ToJSON StepDeltaData where
toJSON = \case
TextDelta txt -> object ["type" .= ("text" :: Text), "text" .= txt]
ArgumentsDelta args -> object ["type" .= ("arguments" :: Text), "arguments" .= args]
ThoughtSignatureDelta sig -> object ["type" .= ("thought_signature" :: Text), "signature" .= sig]
OtherDelta _ val -> val
-- | SSE event types dispatched on the interaction stream.
data InteractionSseEvent
= SseInteractionCreated !Interaction
| SseInteractionStatusUpdate !Text !InteractionStatus
| SseStepStart !Int !Step
| SseStepDelta !Int !StepDeltaData
| SseStepStop !Int
| SseInteractionCompleted !Interaction
| SseError !Text !Text
| SseOther !Text !Value
deriving (Eq, Show, Generic)
instance FromJSON InteractionSseEvent where
parseJSON = withObject "InteractionSseEvent" $ \o -> do
evType <- o .: "event_type"
case (evType :: Text) of
"interaction.created" -> SseInteractionCreated <$> o .: "interaction"
"interaction.completed" -> SseInteractionCompleted <$> o .: "interaction"
"interaction.status_update" ->
SseInteractionStatusUpdate <$> o .: "interaction_id" <*> o .: "status"
"step.start" -> SseStepStart <$> o .: "index" <*> o .: "step"
"step.delta" -> SseStepDelta <$> o .: "index" <*> o .: "delta"
"step.stop" -> SseStepStop <$> o .: "index"
"error" -> do
errObj <- o .: "error"
c <- errObj .:? "code" .!= ""
m <- errObj .:? "message" .!= ""
pure $ SseError c m
other -> pure $ SseOther other (Object o)
instance ToJSON InteractionSseEvent where
toJSON = \case
SseInteractionCreated inter ->
object ["event_type" .= ("interaction.created" :: Text), "interaction" .= inter]
SseInteractionCompleted inter ->
object ["event_type" .= ("interaction.completed" :: Text), "interaction" .= inter]
SseInteractionStatusUpdate iid st ->
object
["event_type" .= ("interaction.status_update" :: Text), "interaction_id" .= iid, "status" .= st]
SseStepStart idx step ->
object ["event_type" .= ("step.start" :: Text), "index" .= idx, "step" .= step]
SseStepDelta idx d ->
object ["event_type" .= ("step.delta" :: Text), "index" .= idx, "delta" .= d]
SseStepStop idx ->
object ["event_type" .= ("step.stop" :: Text), "index" .= idx]
SseError code msg ->
object ["event_type" .= ("error" :: Text), "error" .= object ["code" .= code, "message" .= msg]]
SseOther ev val -> case val of
Object o -> Object (KM.insert "event_type" (String ev) o)
_ -> object ["event_type" .= ev, "data" .= val]
-- ---------------------------------------------------------------------------
-- Embeddings
-- ---------------------------------------------------------------------------
-- | Single text part within embedding payload.
newtype EmbedPart = EmbedPart {partText :: Text}
deriving (Eq, Show, Generic)
instance ToJSON EmbedPart where
toJSON (EmbedPart t) = object ["text" .= t]
instance FromJSON EmbedPart where
parseJSON = withObject "EmbedPart" $ \o -> EmbedPart <$> o .: "text"
-- | Content payload container for embedding.
newtype EmbedContentPayload = EmbedContentPayload {payloadParts :: [EmbedPart]}
deriving (Eq, Show, Generic)
instance ToJSON EmbedContentPayload where
toJSON (EmbedContentPayload ps) = object ["parts" .= ps]
instance FromJSON EmbedContentPayload where
parseJSON = withObject "EmbedContentPayload" $ \o -> EmbedContentPayload <$> o .: "parts"
-- | Single embedContent request body.
newtype EmbedContentRequest = EmbedContentRequest {requestContent :: EmbedContentPayload}
deriving (Eq, Show, Generic)
instance ToJSON EmbedContentRequest where
toJSON (EmbedContentRequest p) = object ["content" .= p]
instance FromJSON EmbedContentRequest where
parseJSON = withObject "EmbedContentRequest" $ \o -> EmbedContentRequest <$> o .: "content"
-- | Embedding vector result.
newtype EmbeddingValues = EmbeddingValues {embeddingValues :: [Float]}
deriving (Eq, Show, Generic)
instance FromJSON EmbeddingValues where
parseJSON = withObject "EmbeddingValues" $ \o -> EmbeddingValues <$> o .: "values"
instance ToJSON EmbeddingValues where
toJSON (EmbeddingValues vs) = object ["values" .= vs]
-- | Response from embedContent.
newtype EmbedContentResponse = EmbedContentResponse {responseEmbedding :: EmbeddingValues}
deriving (Eq, Show, Generic)
instance FromJSON EmbedContentResponse where
parseJSON = withObject "EmbedContentResponse" $ \o -> EmbedContentResponse <$> o .: "embedding"
instance ToJSON EmbedContentResponse where
toJSON (EmbedContentResponse ev) = object ["embedding" .= ev]
-- | Single item in batchEmbedContents.
data BatchEmbedRequestItem = BatchEmbedRequestItem
{ itemModel :: !Text
, itemContent :: !EmbedContentPayload
}
deriving (Eq, Show, Generic)
instance ToJSON BatchEmbedRequestItem where
toJSON BatchEmbedRequestItem {..} =
object ["model" .= itemModel, "content" .= itemContent]
instance FromJSON BatchEmbedRequestItem where
parseJSON = withObject "BatchEmbedRequestItem" $ \o -> do
itemModel <- o .: "model"
itemContent <- o .: "content"
pure BatchEmbedRequestItem {..}
-- | Batch embed request body.
newtype BatchEmbedContentsRequest = BatchEmbedContentsRequest
{ batchRequests :: [BatchEmbedRequestItem]
}
deriving (Eq, Show, Generic)
instance ToJSON BatchEmbedContentsRequest where
toJSON (BatchEmbedContentsRequest reqs) = object ["requests" .= reqs]
instance FromJSON BatchEmbedContentsRequest where
parseJSON = withObject "BatchEmbedContentsRequest" $ \o ->
BatchEmbedContentsRequest <$> o .: "requests"
-- | Response from batchEmbedContents.
newtype BatchEmbedContentsResponse = BatchEmbedContentsResponse
{ batchEmbeddings :: [EmbeddingValues]
}
deriving (Eq, Show, Generic)
instance FromJSON BatchEmbedContentsResponse where
parseJSON = withObject "BatchEmbedContentsResponse" $ \o ->
BatchEmbedContentsResponse <$> o .: "embeddings"
instance ToJSON BatchEmbedContentsResponse where
toJSON (BatchEmbedContentsResponse evs) = object ["embeddings" .= evs]