Thin OpenAI API client for MoonBit built on gaato/http and gaato/sdk-runtime: models, embeddings, responses (buffered and streaming).
Dependencies
let transport = @http_async.AsyncTransport::new()
let clock = @http_async.AsyncClock::new()
let openai = @openai.OpenAI::new(api_key~, transport, clock)
let reply = openai.chat_completion(@openai.ChatRequest::new(
model="gpt-5.6-sol",
messages=[@openai.ChatMessage::user("Hello")],
))test {
let error : @openai.ApiErrorBody = {
message: "invalid request",
type_: Some("invalid_request_error"),
param: None,
code: None,
}
assert_eq(error.message, "invalid request")
}pub(all) enum ChatEvent {
Delta(String)
ReasoningDelta(String)
ToolCallDelta(index~ : Int, id~ : String?, name~ : String?, arguments~ : String)
Finished(FinishReason)
Usage(Usage)
Other(String, Json)
} derive(Eq, Debug)test {
let message = @openai.ChatMessage::user("hello")
assert_eq(message.role, "user")
assert_eq(message.content, "hello")
}test {
assert_eq(@openai.ChatMessage::assistant("hello").role, "assistant")
}fn ChatMessage::assistant_tool_calls(tool_calls : Array[ToolCall], content? : String) -> ChatMessagetest {
let message = @openai.ChatMessage::assistant_tool_calls([
{ id: "call_1", name: "lookup", arguments: "{}", },
])
assert_eq(message.tool_calls.unwrap().length(), 1)
}test {
assert_eq(@openai.ChatMessage::system("Be concise").role, "system")
}test {
let message = @openai.ChatMessage::tool(tool_call_id="call_1", content="done")
assert_eq(message.tool_call_id, Some("call_1"))
}test {
assert_eq(@openai.ChatMessage::user("hello").role, "user")
}fn ChatRequest::new(model~ : String, messages~ : Array[ChatMessage], max_tokens? : Int, temperature? : Double, reasoning_effort? : String, tools? : Array[ToolDef], tool_choice? : Json, extra? : Map[String, Json]) -> ChatRequesttest {
let request = @openai.ChatRequest::new(model="gpt-4o-mini", messages=[
@openai.ChatMessage::user("hello"),
])
assert_eq(request.messages.length(), 1)
}fn EmbeddingRequest::new(model~ : String, input~ : Array[String], dimensions? : Int, user? : String) -> EmbeddingRequesttest {
let request = @openai.EmbeddingRequest::new(model="text-embedding-3-small", input=[
"hello",
])
assert_eq(request.input, ["hello"])
}pub struct OpenAI {
// private fields
}async fn OpenAI::chat_completion(self : OpenAI, request : ChatRequest) -> ChatCompletion raise SdkErrorasync fn OpenAI::create_embeddings(self : OpenAI, request : EmbeddingRequest) -> EmbeddingResponse raise SdkErrorasync fn OpenAI::create_response(self : OpenAI, request : ResponseRequest) -> Response raise SdkErrorfn OpenAI::new(api_key~ : String, transport : &Transport, clock : &Clock, base_url? : String, organization? : String, project? : String, retry? : RetryPolicy) -> OpenAIasync fn[E : Error] OpenAI::stream_chat_completion(self : OpenAI, request : ChatRequest, f : async (ChatEvent) -> Unit raise E) -> Unitasync fn[E : Error] OpenAI::stream_response(self : OpenAI, request : ResponseRequest, f : async (ResponseEvent) -> Unit raise E) -> Unitpub(all) enum ResponseEvent {
Created(Response)
InProgress(Response)
OutputTextDelta(String)
OutputTextDone(String)
FunctionCallArgumentsDelta(item_id~ : String, delta~ : String)
FunctionCallArgumentsDone(item_id~ : String, arguments~ : String)
Completed(Response)
Failed(Response)
Incomplete(Response)
Error(ApiErrorBody)
Other(String, Json)
} derive(Eq, Debug)fn ResponseRequest::new(model~ : String, input~ : String, instructions? : String, max_output_tokens? : Int, temperature? : Double, previous_response_id? : String, tools? : Array[ToolDef], tool_choice? : Json, extra? : Map[String, Json]) -> ResponseRequesttest {
let request = @openai.ResponseRequest::new(model="gpt-4.1", input="hello")
assert_eq(request.extra, {})
}fn ResponseRequest::with_tool_outputs(self : ResponseRequest, outputs : Array[(String, String)]) -> ResponseRequesttest {
let request = @openai.ResponseRequest::new(model="gpt-4.1", input="continue").with_tool_outputs([
("call_1", "done"),
],
)
assert_eq(request.input, "continue")
}test {
let call : @openai.ToolCall = {
id: "call_1",
name: "lookup",
arguments: "{\"id\":1}",
}
assert_eq(call.arguments_json(), { "id": 1 })
}pub struct ToolCallAccumulator {
// private fields
}test {
let calls = @openai.ToolCallAccumulator::new()
calls.feed(index=0, id="call_1", name="lookup", arguments="{}")
assert_eq(calls.finish()[0].arguments, "{}")
}fn ToolCallAccumulator::feed(self : ToolCallAccumulator, index~ : Int, id? : String, name? : String, arguments~ : String) -> Unittest {
let tool = @openai.ToolDef::new(name="lookup", parameters={ "type": "object" })
assert_eq(tool.name, "lookup")
}Install
Download zipThin OpenAI API client for MoonBit built on gaato/http and gaato/sdk-runtime: models, embeddings, responses (buffered and streaming).
Dependencies