///|
priv struct ChatCompletionOutput {
content : String
tool_calls : Array[Json]
}
///|
priv struct CodexChatToolSpec {
kind : String
name : String
ns_name : String?
}
///|
priv struct CodexChatToolContext {
specs : Map[String, CodexChatToolSpec]
}
///|
const TOOL_SEARCH_PROXY_NAME = "tool_search"
///|
const CUSTOM_TOOL_INPUT_FIELD = "input"
///|
const CUSTOM_TOOL_INPUT_DESCRIPTION = "Raw string input for the original custom tool. Preserve formatting exactly and follow the original tool definition embedded in the description."
///|
const CUSTOM_TOOL_PRESERVED_METADATA_HEADING = "Original tool definition:"
///|
fn codex_chat_empty_tool_context() -> CodexChatToolContext {
{ specs: {} }
}
///|
fn codex_chat_tool_context_lookup(
context : CodexChatToolContext,
chat_name : String,
) -> CodexChatToolSpec? {
context.specs.get(chat_name)
}
///|
fn codex_chat_tool_context_from_responses_request(
body : Json,
) -> CodexChatToolContext {
let context = codex_chat_empty_tool_context()
guard body is Object(obj) else { return context }
if obj.get("tools") is Some(Array(tools)) {
for tool in tools {
add_codex_response_tool_to_chat_context(tool, context, None)
}
}
match obj.get("input") {
Some(input) =>
collect_tool_search_output_tools_for_chat_context(input, context)
None => ()
}
context
}
///|
fn add_codex_response_tool_to_chat_context(
tool : Json,
context : CodexChatToolContext,
ns_name : String?,
) -> Unit {
match tool {
String(name) =>
add_chat_tool_spec(context, name, { kind: "custom", name, ns_name: None })
Object(tool_obj) =>
match json_string_from_map(tool_obj, "type") {
Some("function") => {
let name = codex_response_tool_name(tool_obj)
if name.trim().is_empty() {
return
}
let chat_name = codex_chat_name_for_response_function(
name, ns_name, context,
)
add_chat_tool_spec(context, chat_name, {
kind: if ns_name is Some(_) {
"namespace"
} else {
"function"
},
name,
ns_name,
})
}
Some("custom") => {
let name = codex_response_tool_name(tool_obj)
add_chat_tool_spec(context, name, {
kind: "custom",
name,
ns_name: None,
})
}
Some("tool_search") =>
add_chat_tool_spec(context, TOOL_SEARCH_PROXY_NAME, {
kind: "tool_search",
name: TOOL_SEARCH_PROXY_NAME,
ns_name: None,
})
Some("namespace") => {
let child_ns_name = json_string_from_map(tool_obj, "name")
if tool_obj.get("tools") is Some(Array(children)) {
for child in children {
add_codex_response_tool_to_chat_context(
child, context, child_ns_name,
)
}
}
if tool_obj.get("children") is Some(Array(children)) {
for child in children {
add_codex_response_tool_to_chat_context(
child, context, child_ns_name,
)
}
}
}
_ => ()
}
_ => ()
}
}
///|
fn add_chat_tool_spec(
context : CodexChatToolContext,
chat_name : String,
spec : CodexChatToolSpec,
) -> Unit {
if chat_name.trim().is_empty() {
return
}
if context.specs.get(chat_name) is None {
context.specs[chat_name] = spec
}
}
///|
fn collect_tool_search_output_tools_for_chat_context(
value : Json,
context : CodexChatToolContext,
) -> Unit {
match value {
Array(items) =>
for item in items {
collect_tool_search_output_tools_for_chat_context(item, context)
}
Object(obj) => {
if obj.get("type") is Some(String("tool_search_output")) &&
obj.get("tools") is Some(Array(tools)) {
for tool in tools {
add_codex_response_tool_to_chat_context(tool, context, None)
}
}
for item in obj.values() {
collect_tool_search_output_tools_for_chat_context(item, context)
}
}
_ => ()
}
}
///|
fn openai_chat_model(body : Json) -> String? {
guard body is Object(obj) else { return None }
match obj.get("model") {
Some(String(model)) => Some(model)
_ => None
}
}
///|
fn openai_chat_to_codex_response_request(
body : Json,
upstream_model : String,
) -> Json? {
guard body is Object(obj) else { return None }
guard obj.get("messages") is Some(Array(messages)) else { return None }
let input_items : Array[Json] = []
let instructions : Array[String] = []
for message in messages {
append_chat_message_as_response_item(message, input_items, instructions)
}
let request : Map[String, Json] = {
"model": Json::string(upstream_model),
"input": Json::array(input_items),
"store": Json::boolean(false),
"stream": Json::boolean(json_bool_from_map(obj, "stream").unwrap_or(false)),
}
if !instructions.is_empty() {
request["instructions"] = Json::string(instructions.join("\n\n"))
}
if obj.get("max_completion_tokens") is Some(value) {
request["max_output_tokens"] = value
} else if obj.get("max_tokens") is Some(value) {
request["max_output_tokens"] = value
}
for key in ["temperature", "top_p", "metadata", "reasoning"] {
if obj.get(key) is Some(value) {
request[key] = value
}
}
if obj.get("tools") is Some(Array(tools)) {
let codex_tools : Array[Json] = []
for tool in tools {
if openai_tool_to_codex_tool(tool) is Some(codex_tool) {
codex_tools.push(codex_tool)
}
}
if !codex_tools.is_empty() {
request["tools"] = Json::array(codex_tools)
}
}
if obj.get("tool_choice") is Some(value) {
request["tool_choice"] = openai_tool_choice_to_codex(value)
}
if json_bool_from_map(obj, "stream").unwrap_or(false) {
apply_codex_oauth_responses_constraints(request, obj, false)
}
Some(Json::object(request))
}
///|
fn codex_responses_request_to_openai_chat_completion(
body : Json,
fallback_model : String,
) -> Json? {
guard body is Object(obj) else { return None }
let tool_context = codex_chat_tool_context_from_responses_request(body)
let messages : Array[Json] = []
match json_string_from_map(obj, "instructions") {
Some(instructions) if !instructions.trim().is_empty() =>
messages.push(
Json::object({
"role": Json::string("system"),
"content": Json::string(instructions),
}),
)
_ => ()
}
append_codex_responses_input_as_openai_chat_messages(
obj.get("input"),
messages,
tool_context,
)
let result : Map[String, Json] = {
"model": Json::string(
json_string_from_map(obj, "model").unwrap_or(fallback_model),
),
"messages": Json::array(messages),
"stream": Json::boolean(json_bool_from_map(obj, "stream").unwrap_or(false)),
}
if obj.get("max_output_tokens") is Some(value) {
result["max_tokens"] = value
}
for key in ["temperature", "top_p", "metadata", "reasoning"] {
if obj.get(key) is Some(value) {
result[key] = value
}
}
append_codex_responses_tools_as_openai_chat_tools(obj, result, tool_context)
if obj.get("tool_choice") is Some(value) {
result["tool_choice"] = codex_tool_choice_to_openai_chat(
value, tool_context,
)
}
Some(Json::object(result))
}
///|
fn append_codex_responses_input_as_openai_chat_messages(
input : Json?,
messages : Array[Json],
tool_context : CodexChatToolContext,
) -> Unit {
let pending_tool_calls : Array[Json] = []
let flush_pending_tool_calls = fn() {
if !pending_tool_calls.is_empty() {
messages.push(
Json::object({
"role": Json::string("assistant"),
"content": Json::null(),
"tool_calls": Json::array(pending_tool_calls.copy()),
}),
)
pending_tool_calls.clear()
}
}
let items = match input {
Some(Array(items)) => items
Some(Object(_)) => [input.unwrap()]
Some(String(text)) =>
[
Json::object({
"role": Json::string("user"),
"content": Json::string(text),
}),
]
_ => []
}
for item in items {
guard item is Object(item_obj) else { continue }
match json_string_from_map(item_obj, "type") {
Some(type_) if codex_chat_is_call_item_type(type_) =>
pending_tool_calls.push(
openai_chat_tool_call_from_codex_item(item_obj, tool_context),
)
Some(type_) if codex_chat_is_call_output_item_type(type_) => {
flush_pending_tool_calls()
messages.push(openai_chat_tool_message_from_codex_output(item_obj))
}
_ => {
flush_pending_tool_calls()
messages.push(openai_chat_message_from_codex_input_item(item_obj))
}
}
}
flush_pending_tool_calls()
}
///|
fn openai_chat_message_from_codex_input_item(item : Map[String, Json]) -> Json {
let role = json_string_from_map(item, "role").unwrap_or("user")
Json::object({
"role": Json::string(if role == "assistant" { "assistant" } else { "user" }),
"content": codex_responses_content_to_chat_content(item.get("content")),
})
}
///|
fn codex_responses_content_to_chat_content(content : Json?) -> Json {
match content {
Some(String(text)) => Json::string(text)
Some(Array(parts)) => {
let chat_parts : Array[Json] = []
let text_parts : Array[String] = []
let mut has_non_text_part = false
for part in parts {
match part {
Object(part_obj) =>
match json_string_from_map(part_obj, "type") {
Some("input_text") | Some("output_text") =>
if json_string_from_map(part_obj, "text") is Some(text) &&
!text.is_empty() {
text_parts.push(text)
chat_parts.push(
Json::object({
"type": Json::string("text"),
"text": Json::string(text),
}),
)
}
Some("text") =>
if json_string_from_map(part_obj, "text") is Some(text) &&
!text.is_empty() {
text_parts.push(text)
chat_parts.push(
Json::object({
"type": Json::string("text"),
"text": Json::string(text),
}),
)
}
Some("refusal") =>
if json_string_from_map(part_obj, "refusal") is Some(text) &&
!text.is_empty() {
text_parts.push(text)
chat_parts.push(
Json::object({
"type": Json::string("text"),
"text": Json::string(text),
}),
)
}
Some("input_image") =>
if part_obj.get("image_url") is Some(image_url) {
let chat_image_url = match image_url {
Object(_) => image_url
String(url) => Json::object({ "url": Json::string(url) })
_ => Json::object({ "url": Json::string("") })
}
chat_parts.push(
Json::object({
"type": Json::string("image_url"),
"image_url": chat_image_url,
}),
)
has_non_text_part = true
}
Some("input_file") =>
if codex_responses_input_file_to_chat_file(part_obj)
is Some(file) {
chat_parts.push(
Json::object({ "type": Json::string("file"), "file": file }),
)
has_non_text_part = true
}
Some("input_audio") =>
if part_obj.get("input_audio") is Some(input_audio) {
chat_parts.push(
Json::object({
"type": Json::string("input_audio"),
"input_audio": input_audio,
}),
)
has_non_text_part = true
}
_ => ()
}
_ => ()
}
}
if has_non_text_part {
Json::array(chat_parts)
} else {
Json::string(text_parts.join("\n"))
}
}
Some(value) => value
None => Json::string("")
}
}
///|
fn codex_responses_input_file_to_chat_file(part : Map[String, Json]) -> Json? {
let file : Map[String, Json] = {}
let mut has_supported_file_ref = false
for key in ["file_id", "file_data", "filename"] {
if part.get(key) is Some(value) {
file[key] = value
if key != "filename" {
has_supported_file_ref = true
}
}
}
if has_supported_file_ref {
Some(Json::object(file))
} else {
None
}
}
///|
fn openai_chat_tool_call_from_codex_item(
item : Map[String, Json],
tool_context : CodexChatToolContext,
) -> Json {
let item_type = json_string_from_map(item, "type").unwrap_or("function_call")
let name = match item_type {
"tool_search_call" => TOOL_SEARCH_PROXY_NAME
"function_call" =>
codex_chat_name_for_response_function(
json_string_from_map(item, "name").unwrap_or("tool"),
json_string_from_map(item, "namespace"),
tool_context,
)
_ => json_string_from_map(item, "name").unwrap_or("tool")
}
Json::object({
"id": Json::string(
codex_chat_response_item_call_id(Json::object(item)).unwrap_or(
generate_chat_completion_id(),
),
),
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(name),
"arguments": Json::string(codex_responses_call_arguments(item)),
}),
})
}
///|
fn codex_responses_call_arguments(item : Map[String, Json]) -> String {
if json_string_from_map(item, "type") is Some("tool_search_call") {
return canonicalize_tool_arguments(item.get("arguments"))
}
if json_string_from_map(item, "type") is Some("custom_tool_call") {
let input = item.get("input").unwrap_or(Json::string(""))
let args : Map[String, Json] = {}
args[CUSTOM_TOOL_INPUT_FIELD] = input
return canonical_json_string(Json::object(args))
}
match item.get("arguments") {
Some(String(args)) => args
Some(value) => canonicalize_tool_arguments(Some(value))
None =>
match item.get("input") {
Some(String(text)) =>
Json::object({ "input": Json::string(text) }).stringify()
Some(value) => canonicalize_tool_arguments(Some(value))
None => "{}"
}
}
}
///|
fn openai_chat_tool_message_from_codex_output(item : Map[String, Json]) -> Json {
Json::object({
"role": Json::string("tool"),
"tool_call_id": Json::string(
codex_chat_response_item_call_id(Json::object(item)).unwrap_or(""),
),
"content": Json::string(codex_responses_tool_output_text(item)),
})
}
///|
fn codex_responses_tool_output_text(item : Map[String, Json]) -> String {
match json_string_from_map(item, "type") {
Some("custom_tool_call_output") | Some("tool_search_output") =>
return canonical_json_string(Json::object(item))
_ => ()
}
match item.get("output") {
Some(String(text)) => text
Some(value) => value.stringify()
None =>
match item.get("content") {
Some(String(text)) => text
Some(value) => value.stringify()
None => ""
}
}
}
///|
fn append_codex_responses_tools_as_openai_chat_tools(
source : Map[String, Json],
target : Map[String, Json],
tool_context : CodexChatToolContext,
) -> Unit {
guard source.get("tools") is Some(Array(tools)) else { return }
let converted : Array[Json] = []
for tool in tools {
append_codex_response_tool_as_openai_chat_tool(
tool,
converted,
tool_context,
None,
)
}
if !converted.is_empty() {
target["tools"] = Json::array(converted)
}
}
///|
fn append_codex_response_tool_as_openai_chat_tool(
tool : Json,
converted : Array[Json],
tool_context : CodexChatToolContext,
ns_name : String?,
) -> Unit {
match tool {
String(name) =>
append_codex_custom_tool_as_openai_chat_tool(
name,
Json::string(name),
converted,
)
Object(tool_obj) =>
match json_string_from_map(tool_obj, "type") {
Some("function") => {
let original_name = codex_response_tool_name(tool_obj)
if original_name.trim().is_empty() {
return
}
let chat_name = codex_chat_name_for_response_function(
original_name, ns_name, tool_context,
)
append_codex_function_tool_as_openai_chat_tool(
tool_obj, chat_name, converted,
)
}
Some("custom") =>
append_codex_custom_tool_as_openai_chat_tool(
codex_response_tool_name(tool_obj),
Json::object(tool_obj),
converted,
)
Some("tool_search") => append_tool_search_as_openai_chat_tool(converted)
Some("namespace") =>
if tool_obj.get("tools") is Some(Array(children)) {
let child_ns_name = json_string_from_map(tool_obj, "name")
for child in children {
append_codex_response_tool_as_openai_chat_tool(
child, converted, tool_context, child_ns_name,
)
}
} else if tool_obj.get("children") is Some(Array(children)) {
let child_ns_name = json_string_from_map(tool_obj, "name")
for child in children {
append_codex_response_tool_as_openai_chat_tool(
child, converted, tool_context, child_ns_name,
)
}
}
_ => ()
}
_ => ()
}
}
///|
fn append_codex_function_tool_as_openai_chat_tool(
tool_obj : Map[String, Json],
chat_name : String,
converted : Array[Json],
) -> Unit {
if chat_name.trim().is_empty() {
return
}
let function : Map[String, Json] = {
"name": Json::string(chat_name),
"description": tool_obj.get("description").unwrap_or(Json::string("")),
"parameters": tool_obj
.get("parameters")
.unwrap_or(tool_obj.get("input_schema").unwrap_or(Json::object({}))),
}
if tool_obj.get("strict") is Some(strict) {
function["strict"] = strict
}
converted.push(
Json::object({
"type": Json::string("function"),
"function": Json::object(function),
}),
)
}
///|
fn append_codex_custom_tool_as_openai_chat_tool(
name : String,
definition : Json,
converted : Array[Json],
) -> Unit {
if name.trim().is_empty() {
return
}
let properties : Map[String, Json] = {}
properties[CUSTOM_TOOL_INPUT_FIELD] = Json::object({
"type": Json::string("string"),
"description": Json::string(CUSTOM_TOOL_INPUT_DESCRIPTION),
})
let parameters : Map[String, Json] = {
"type": Json::string("object"),
"properties": Json::object(properties),
"required": Json::array([Json::string(CUSTOM_TOOL_INPUT_FIELD)]),
}
converted.push(
Json::object({
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(name),
"description": Json::string(
"\{CUSTOM_TOOL_PRESERVED_METADATA_HEADING}\n```json\n\{canonical_json_string(definition)}\n```",
),
"parameters": Json::object(parameters),
}),
}),
)
}
///|
fn append_tool_search_as_openai_chat_tool(converted : Array[Json]) -> Unit {
converted.push(
Json::object({
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(TOOL_SEARCH_PROXY_NAME),
"description": Json::string(
"Search and load Codex tools, plugins, connectors, and MCP namespaces for the current task.",
),
"parameters": Json::object({
"type": Json::string("object"),
"properties": Json::object({
"query": Json::object({
"type": Json::string("string"),
"description": Json::string(
"Search query for tools or connectors to load.",
),
}),
"limit": Json::object({
"type": Json::string("integer"),
"description": Json::string(
"Maximum number of tool groups to return.",
),
}),
}),
"required": Json::array([Json::string("query")]),
}),
}),
}),
)
}
///|
fn codex_response_tool_name(tool : Map[String, Json]) -> String {
match tool.get("function") {
Some(Object(function)) =>
json_string_from_map(function, "name").unwrap_or("")
_ => json_string_from_map(tool, "name").unwrap_or("")
}
}
///|
fn codex_chat_name_for_response_function(
name : String,
ns_name : String?,
tool_context : CodexChatToolContext,
) -> String {
match ns_name {
Some(ns) if !ns.is_empty() => {
let direct = "\{ns}__\{name}"
match codex_chat_tool_context_lookup(tool_context, direct) {
Some(_) => direct
None => direct
}
}
_ => name
}
}
///|
fn codex_tool_choice_to_openai_chat(
choice : Json,
tool_context : CodexChatToolContext,
) -> Json {
match choice {
String("auto") | String("none") | String("required") => choice
Object(obj) =>
if obj.get("type") is Some(String("function")) ||
obj.get("type") is Some(String("tool")) {
Json::object({
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(
codex_chat_name_for_response_function(
json_string_from_map(obj, "name").unwrap_or(""),
json_string_from_map(obj, "namespace"),
tool_context,
),
),
}),
})
} else if obj.get("type") is Some(String("tool_search")) {
Json::object({
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(TOOL_SEARCH_PROXY_NAME),
}),
})
} else if obj.get("type") is Some(String("custom")) {
Json::object({
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(
json_string_from_map(obj, "name").unwrap_or(""),
),
}),
})
} else {
Json::object(obj)
}
_ => choice
}
}
///|
fn openai_chat_completion_to_codex_response(
body : Json,
fallback_model : String,
) -> Json {
openai_chat_completion_to_codex_response_with_context(
body,
fallback_model,
codex_chat_empty_tool_context(),
)
}
///|
fn init {
ignore(openai_chat_completion_to_codex_response(Json::object({}), "model"))
}
///|
fn openai_chat_completion_to_codex_response_with_request(
body : Json,
fallback_model : String,
original_request : Json,
) -> Json {
openai_chat_completion_to_codex_response_with_context(
body,
fallback_model,
codex_chat_tool_context_from_responses_request(original_request),
)
}
///|
fn openai_chat_completion_to_codex_response_with_context(
body : Json,
fallback_model : String,
tool_context : CodexChatToolContext,
) -> Json {
let response_id = openai_chat_completion_id(body).unwrap_or(
generate_chat_completion_id(),
)
let output : Array[Json] = []
let mut model = fallback_model
guard body is Object(obj) else {
return codex_response_from_output(
response_id,
model,
output,
Json::object({}),
)
}
model = json_string_from_map(obj, "model").unwrap_or(model)
if obj.get("choices") is Some(Array(choices)) &&
choices.get(0) is Some(Object(choice)) &&
choice.get("message") is Some(Object(message)) {
append_openai_chat_message_as_codex_output(message, output, tool_context)
}
codex_response_from_output(
response_id,
model,
output,
openai_chat_usage_to_codex_usage(obj.get("usage")),
)
}
///|
fn append_openai_chat_message_as_codex_output(
message : Map[String, Json],
output : Array[Json],
tool_context : CodexChatToolContext,
) -> Unit {
match json_string_from_map(message, "content") {
Some(text) if !text.is_empty() =>
output.push(
Json::object({
"type": Json::string("message"),
"role": Json::string("assistant"),
"content": Json::array([
Json::object({
"type": Json::string("output_text"),
"text": Json::string(text),
}),
]),
}),
)
_ => ()
}
if message.get("tool_calls") is Some(Array(tool_calls)) {
for tool_call in tool_calls {
guard tool_call is Object(tool_call_obj) else { continue }
output.push(
codex_call_item_from_openai_tool_call(tool_call_obj, tool_context),
)
}
}
}
///|
fn codex_call_item_from_openai_tool_call(
tool_call : Map[String, Json],
tool_context : CodexChatToolContext,
) -> Json {
let function = match tool_call.get("function") {
Some(Object(function)) => function
_ => {}
}
let chat_name = json_string_from_map(function, "name").unwrap_or("tool")
let arguments = canonicalize_tool_arguments(function.get("arguments"))
let call_id = json_string_from_map(tool_call, "id").unwrap_or(
generate_chat_completion_id(),
)
let item = codex_response_call_item_from_chat_name(
"completed", call_id, chat_name, arguments, tool_context,
)
match json_string_from_map(tool_call, "reasoning_content") {
Some(reasoning) if !reasoning.is_empty() =>
item["reasoning_content"] = Json::string(reasoning)
_ => ()
}
Json::object(item)
}
///|
fn codex_response_call_item_from_chat_name(
status : String,
call_id : String,
chat_name : String,
arguments : String,
tool_context : CodexChatToolContext,
) -> Map[String, Json] {
match codex_chat_tool_context_lookup(tool_context, chat_name) {
Some(spec) if spec.kind == "custom" =>
{
"id": Json::string("ctc_\{call_id}"),
"type": Json::string("custom_tool_call"),
"status": Json::string(status),
"call_id": Json::string(call_id),
"name": Json::string(spec.name),
"input": Json::string(custom_tool_input_from_chat_arguments(arguments)),
}
Some(spec) if spec.kind == "tool_search" =>
{
"type": Json::string("tool_search_call"),
"status": Json::string(status),
"execution": Json::string("client"),
"call_id": Json::string(call_id),
"arguments": parse_tool_arguments_object(arguments),
}
Some(spec) => {
let result : Map[String, Json] = {
"type": Json::string("function_call"),
"call_id": Json::string(call_id),
"name": Json::string(spec.name),
"arguments": Json::string(arguments),
"status": Json::string(status),
"id": Json::string("fc_\{call_id}"),
}
match spec.ns_name {
Some(ns) if !ns.is_empty() => result["namespace"] = Json::string(ns)
_ => ()
}
result
}
None =>
{
"type": Json::string("function_call"),
"call_id": Json::string(call_id),
"name": Json::string(chat_name),
"arguments": Json::string(arguments),
"status": Json::string(status),
"id": Json::string("fc_\{call_id}"),
}
}
}
///|
fn codex_response_call_item_id_from_chat_name(
call_id : String,
chat_name : String,
tool_context : CodexChatToolContext,
) -> String {
match codex_chat_tool_context_lookup(tool_context, chat_name) {
Some(spec) if spec.kind == "custom" => "ctc_\{call_id}"
_ => "fc_\{call_id}"
}
}
///|
fn codex_chat_tool_context_is_custom(
context : CodexChatToolContext,
chat_name : String,
) -> Bool {
match codex_chat_tool_context_lookup(context, chat_name) {
Some(spec) => spec.kind == "custom"
None => false
}
}
///|
fn parse_tool_arguments_object(arguments : String) -> Json {
if arguments.trim().is_empty() {
return Json::object({})
}
let parsed = @json.parse(arguments) catch {
_ => return Json::object({ "query": Json::string(arguments) })
}
match parsed {
Object(_) => parsed
_ => Json::object({ "query": Json::string(arguments) })
}
}
///|
fn custom_tool_input_from_chat_arguments(arguments : String) -> String {
if arguments.trim().is_empty() {
return ""
}
let parsed = @json.parse(arguments) catch { _ => return arguments }
match parsed {
Object(obj) =>
json_string_from_map(obj, CUSTOM_TOOL_INPUT_FIELD).unwrap_or(arguments)
_ => arguments
}
}
///|
fn codex_response_from_output(
id : String,
model : String,
output : Array[Json],
usage : Json,
) -> Json {
Json::object({
"id": Json::string(id),
"object": Json::string("response"),
"status": Json::string("completed"),
"model": Json::string(model),
"output": Json::array(output),
"usage": usage,
})
}
///|
fn openai_chat_usage_to_codex_usage(usage : Json?) -> Json {
guard usage is Some(Object(obj)) else {
return Json::object({
"input_tokens": Json::number(0.0),
"output_tokens": Json::number(0.0),
"output_tokens_details": Json::object({
"reasoning_tokens": Json::number(0.0),
}),
})
}
let input_tokens = json_int(obj, "prompt_tokens").unwrap_or(0)
let output_tokens = json_int(obj, "completion_tokens").unwrap_or(0)
let cached_tokens = match obj.get("prompt_tokens_details") {
Some(Object(details)) => json_int(details, "cached_tokens").unwrap_or(0)
_ => 0
}
let reasoning_tokens = match obj.get("completion_tokens_details") {
Some(Object(details)) => json_int(details, "reasoning_tokens").unwrap_or(0)
_ => 0
}
Json::object({
"input_tokens": Json::number(input_tokens.to_double()),
"output_tokens": Json::number(output_tokens.to_double()),
"input_tokens_details": Json::object({
"cached_tokens": Json::number(cached_tokens.to_double()),
}),
"output_tokens_details": Json::object({
"reasoning_tokens": Json::number(reasoning_tokens.to_double()),
}),
})
}
///|
fn append_chat_message_as_response_item(
message : Json,
input_items : Array[Json],
instructions : Array[String],
) -> Unit {
guard message is Object(obj) else { return }
let role = match obj.get("role") {
Some(String(role)) => role
_ => "user"
}
if role == "system" || role == "developer" {
let text = chat_content_to_text(
obj.get("content").unwrap_or(Json::string("")),
)
if !text.trim().is_empty() {
instructions.push(text)
}
return
}
if role == "tool" {
let item : Map[String, Json] = {
"type": Json::string("function_call_output"),
"call_id": Json::string(
json_string_from_map(obj, "tool_call_id").unwrap_or(""),
),
"output": Json::string(
chat_content_to_text(obj.get("content").unwrap_or(Json::string(""))),
),
}
input_items.push(Json::object(item))
return
}
let response_role = if role == "assistant" { "assistant" } else { "user" }
let content = chat_content_to_text(
obj.get("content").unwrap_or(Json::string("")),
)
if !content.trim().is_empty() || role != "assistant" {
input_items.push(
Json::object({
"role": Json::string(response_role),
"content": Json::string(content),
}),
)
}
if obj.get("tool_calls") is Some(Array(tool_calls)) {
for tool_call in tool_calls {
if openai_tool_call_to_response_item(tool_call) is Some(item) {
input_items.push(item)
}
}
}
}
///|
fn chat_content_to_text(content : Json) -> String {
match content {
String(text) => text
Array(parts) => {
let texts : Array[String] = []
for part in parts {
match part {
String(text) => texts.push(text)
Object(obj) =>
if obj.get("text") is Some(String(text)) {
texts.push(text)
} else if obj.get("type") is Some(String("text")) &&
obj.get("content") is Some(String(text)) {
texts.push(text)
}
_ => ()
}
}
texts.join("\n")
}
_ => ""
}
}
///|
fn openai_tool_to_codex_tool(tool : Json) -> Json? {
guard tool is Object(obj) else { return None }
if obj.get("type") is Some(String("function")) &&
obj.get("function") is Some(Object(function)) {
let name = json_string_from_map(function, "name").unwrap_or("")
if name.trim().is_empty() {
return None
}
let result : Map[String, Json] = {
"type": Json::string("function"),
"name": Json::string(name),
"parameters": function.get("parameters").unwrap_or(Json::object({})),
}
if function.get("description") is Some(String(description)) {
result["description"] = Json::string(description)
}
return Some(Json::object(result))
}
if obj.get("name") is Some(String(_)) {
return Some(tool)
}
None
}
///|
fn openai_tool_choice_to_codex(choice : Json) -> Json {
match choice {
String("auto") | String("none") | String("required") => choice
Object(obj) =>
if obj.get("type") is Some(String("function")) &&
obj.get("function") is Some(Object(function)) {
Json::object({
"type": Json::string("function"),
"name": Json::string(
json_string_from_map(function, "name").unwrap_or(""),
),
})
} else {
Json::object(obj)
}
_ => choice
}
}
///|
fn openai_tool_call_to_response_item(tool_call : Json) -> Json? {
guard tool_call is Object(obj) else { return None }
guard obj.get("function") is Some(Object(function)) else { return None }
let name = json_string_from_map(function, "name").unwrap_or("")
if name.trim().is_empty() {
return None
}
let call_id = json_string_from_map(obj, "id").unwrap_or(
generate_chat_completion_id(),
)
Some(
Json::object({
"type": Json::string("function_call"),
"call_id": Json::string(call_id),
"name": Json::string(name),
"arguments": Json::string(
canonicalize_tool_arguments(function.get("arguments")),
),
}),
)
}
///|
fn codex_response_to_openai_chat_completion(
body : Json,
model : String,
) -> Json {
let output = extract_chat_completion_output(body)
let usage = token_usage_from_codex_response_auto(body).unwrap_or(
TokenUsage::empty(),
)
let message : Map[String, Json] = { "role": Json::string("assistant") }
if output.tool_calls.is_empty() {
message["content"] = Json::string(output.content)
} else {
message["content"] = Json::null()
message["tool_calls"] = Json::array(output.tool_calls)
}
let finish_reason = if output.tool_calls.is_empty() {
"stop"
} else {
"tool_calls"
}
Json::object({
"id": Json::string(
codex_response_id(body).unwrap_or(generate_chat_completion_id()),
),
"object": Json::string("chat.completion"),
"created": Json::number(@os.unix_seconds().to_double()),
"model": Json::string(model),
"choices": Json::array([
Json::object({
"index": Json::number(0.0),
"message": Json::object(message),
"finish_reason": Json::string(finish_reason),
}),
]),
"usage": openai_usage_json(usage),
})
}
///|
fn openai_chat_role_chunk(id : String, model : String, created : Int) -> Json {
Json::object({
"id": Json::string(id),
"object": Json::string("chat.completion.chunk"),
"created": Json::number(created.to_double()),
"model": Json::string(model),
"choices": Json::array([
Json::object({
"index": Json::number(0.0),
"delta": Json::object({ "role": Json::string("assistant") }),
"finish_reason": Json::null(),
}),
]),
})
}
///|
fn codex_stream_event_to_openai_chat_chunk(
data : String,
id : String,
model : String,
created : Int,
) -> Json? {
let parsed = @json.parse(data) catch { _ => return None }
guard parsed is Object(obj) else { return None }
match obj.get("type") {
Some(String("response.output_text.delta")) => {
let delta = json_string_from_map(obj, "delta").unwrap_or("")
Some(
openai_chat_delta_chunk(
id,
model,
created,
{ "content": Json::string(delta) },
Json::null(),
),
)
}
Some(String("response.output_item.done")) =>
match obj.get("item") {
Some(Object(item)) =>
if item.get("type") is Some(String("function_call")) {
Some(
openai_chat_delta_chunk(
id,
model,
created,
{
"tool_calls": Json::array([
openai_tool_call_delta_from_response_item(item),
]),
},
Json::null(),
),
)
} else {
None
}
_ => None
}
Some(String("response.completed")) =>
Some(
openai_chat_delta_chunk(id, model, created, {}, Json::string("stop")),
)
_ => None
}
}
///|
priv struct ChatToCodexResponsesToolState {
mut output_index : Int?
mut item_id : String
mut call_id : String
mut name : String
mut arguments : String
mut added : Bool
mut done : Bool
}
///|
priv struct ChatToCodexResponsesStreamState {
mut response_started : Bool
mut completed : Bool
mut response_id : String
mut model : String
mut created_at : Int
mut next_output_index : Int
mut text_output_index : Int?
mut text_item_id : String
mut text : String
mut text_added : Bool
mut text_done : Bool
tool_states : Map[Int, ChatToCodexResponsesToolState]
output_items : Array[Json]
mut latest_usage : Json?
mut finish_reason : String?
tool_context : CodexChatToolContext
}
///|
fn ChatToCodexResponsesStreamState::new_with_context(
model : String,
tool_context : CodexChatToolContext,
) -> ChatToCodexResponsesStreamState {
{
response_started: false,
completed: false,
response_id: "resp_moongate",
model,
created_at: @os.unix_seconds(),
next_output_index: 0,
text_output_index: None,
text_item_id: "",
text: "",
text_added: false,
text_done: false,
tool_states: Map([], capacity=0),
output_items: [],
latest_usage: None,
finish_reason: None,
tool_context,
}
}
///|
fn openai_chat_stream_data_to_codex_response_events(
data : String,
state : ChatToCodexResponsesStreamState,
) -> (Bool, Json?, Array[Json]) {
if data.trim() == "[DONE]" {
return (true, None, state.finish())
}
let parsed = @json.parse(data) catch { _ => return (false, None, []) }
(false, Some(parsed), state.push_chunk(parsed))
}
///|
fn ChatToCodexResponsesStreamState::push_chunk(
self : ChatToCodexResponsesStreamState,
chunk : Json,
) -> Array[Json] {
let events : Array[Json] = []
guard chunk is Object(obj) else { return events }
if json_string_from_map(obj, "id") is Some(id) {
self.response_id = codex_response_id_from_chat_id(id)
}
if json_string_from_map(obj, "model") is Some(model) && !model.is_empty() {
self.model = model
}
if json_int(obj, "created") is Some(created) {
self.created_at = created
}
events.append(self.ensure_response_started())
if obj.get("usage") is Some(Object(usage)) {
self.latest_usage = Some(
openai_chat_usage_to_codex_usage(Some(Json::object(usage))),
)
}
guard obj.get("choices") is Some(Array(choices)) else { return events }
guard choices.get(0) is Some(Object(choice)) else { return events }
if choice.get("delta") is Some(Object(delta)) {
if json_string_from_map(delta, "content") is Some(content) &&
!content.is_empty() {
events.append(self.push_text_delta(content))
}
if json_string_from_map(delta, "refusal") is Some(refusal) &&
!refusal.is_empty() {
events.append(self.push_text_delta(refusal))
}
if delta.get("tool_calls") is Some(Array(tool_calls)) {
events.append(self.finish_text())
for tool_call in tool_calls {
if tool_call is Object(tool_call_obj) {
events.append(self.push_tool_call_delta(tool_call_obj))
}
}
}
}
if json_string_from_map(choice, "finish_reason") is Some(reason) {
self.finish_reason = Some(reason)
}
events
}
///|
fn ChatToCodexResponsesStreamState::ensure_response_started(
self : ChatToCodexResponsesStreamState,
) -> Array[Json] {
if self.response_started {
return []
}
self.response_started = true
[
Json::object({
"type": Json::string("response.created"),
"response": self.base_response("in_progress"),
}),
Json::object({
"type": Json::string("response.in_progress"),
"response": self.base_response("in_progress"),
}),
]
}
///|
fn ChatToCodexResponsesStreamState::push_text_delta(
self : ChatToCodexResponsesStreamState,
delta : String,
) -> Array[Json] {
let events : Array[Json] = []
if !self.text_added {
let output_index = self.next_output_index()
let item_id = "\{self.response_id}_msg"
self.text_output_index = Some(output_index)
self.text_item_id = item_id
self.text_added = true
events.push(
Json::object({
"type": Json::string("response.output_item.added"),
"output_index": Json::number(output_index.to_double()),
"item": Json::object({
"id": Json::string(item_id),
"type": Json::string("message"),
"status": Json::string("in_progress"),
"role": Json::string("assistant"),
"content": Json::array([]),
}),
}),
)
events.push(
Json::object({
"type": Json::string("response.content_part.added"),
"item_id": Json::string(self.text_item_id),
"output_index": Json::number(output_index.to_double()),
"content_index": Json::number(0.0),
"part": Json::object({
"type": Json::string("output_text"),
"text": Json::string(""),
"annotations": Json::array([]),
}),
}),
)
}
self.text += delta
let output_index = self.text_output_index.unwrap_or(0)
events.push(
Json::object({
"type": Json::string("response.output_text.delta"),
"item_id": Json::string(self.text_item_id),
"output_index": Json::number(output_index.to_double()),
"content_index": Json::number(0.0),
"delta": Json::string(delta),
}),
)
events
}
///|
fn ChatToCodexResponsesStreamState::push_tool_call_delta(
self : ChatToCodexResponsesStreamState,
tool_call : Map[String, Json],
) -> Array[Json] {
let events : Array[Json] = []
let chat_index = json_int(tool_call, "index").unwrap_or(0)
let state = match self.tool_states.get(chat_index) {
Some(existing) => existing
None => {
let created = {
output_index: None,
item_id: "",
call_id: "",
name: "",
arguments: "",
added: false,
done: false,
}
self.tool_states.set(chat_index, created)
created
}
}
if json_string_from_map(tool_call, "id") is Some(id) && !id.is_empty() {
state.call_id = id
}
if tool_call.get("function") is Some(Object(function)) {
if json_string_from_map(function, "name") is Some(name) && !name.is_empty() {
state.name = name
}
if json_string_from_map(function, "arguments") is Some(arguments) &&
!arguments.is_empty() {
state.arguments += arguments
}
}
if !state.added && (!state.call_id.is_empty() || !state.name.is_empty()) {
let output_index = self.next_output_index()
state.added = true
state.output_index = Some(output_index)
if state.call_id.is_empty() {
state.call_id = "call_\{chat_index}"
}
if state.name.is_empty() {
state.name = "tool"
}
state.item_id = codex_response_call_item_id_from_chat_name(
state.call_id,
state.name,
self.tool_context,
)
let added_item = codex_response_call_item_from_chat_name(
"in_progress",
state.call_id,
state.name,
"",
self.tool_context,
)
events.push(
Json::object({
"type": Json::string("response.output_item.added"),
"output_index": Json::number(output_index.to_double()),
"item": Json::object(added_item),
}),
)
if !state.arguments.is_empty() &&
!codex_chat_tool_context_is_custom(self.tool_context, state.name) {
events.push(
Json::object({
"type": Json::string("response.function_call_arguments.delta"),
"item_id": Json::string(state.item_id),
"output_index": Json::number(output_index.to_double()),
"delta": Json::string(state.arguments),
}),
)
}
} else if state.added &&
tool_call.get("function") is Some(Object(function)) &&
json_string_from_map(function, "arguments") is Some(arguments) &&
!arguments.is_empty() &&
!codex_chat_tool_context_is_custom(self.tool_context, state.name) {
let output_index = state.output_index.unwrap_or(0)
events.push(
Json::object({
"type": Json::string("response.function_call_arguments.delta"),
"item_id": Json::string(state.item_id),
"output_index": Json::number(output_index.to_double()),
"delta": Json::string(arguments),
}),
)
}
events
}
///|
fn ChatToCodexResponsesStreamState::finish(
self : ChatToCodexResponsesStreamState,
) -> Array[Json] {
if self.completed {
return []
}
let events : Array[Json] = []
events.append(self.ensure_response_started())
events.append(self.finish_text())
events.append(self.finish_tools())
events.push(
Json::object({
"type": Json::string("response.completed"),
"response": self.base_response(
codex_response_status_from_chat_finish_reason(self.finish_reason),
),
}),
)
self.completed = true
events
}
///|
fn ChatToCodexResponsesStreamState::finish_text(
self : ChatToCodexResponsesStreamState,
) -> Array[Json] {
if !self.text_added || self.text_done {
return []
}
let output_index = self.text_output_index.unwrap_or(0)
let part = Json::object({
"type": Json::string("output_text"),
"text": Json::string(self.text),
"annotations": Json::array([]),
})
let item = Json::object({
"id": Json::string(self.text_item_id),
"type": Json::string("message"),
"status": Json::string("completed"),
"role": Json::string("assistant"),
"content": Json::array([part]),
})
self.output_items.push(item)
self.text_done = true
[
Json::object({
"type": Json::string("response.output_text.done"),
"item_id": Json::string(self.text_item_id),
"output_index": Json::number(output_index.to_double()),
"content_index": Json::number(0.0),
"text": Json::string(self.text),
}),
Json::object({
"type": Json::string("response.content_part.done"),
"item_id": Json::string(self.text_item_id),
"output_index": Json::number(output_index.to_double()),
"content_index": Json::number(0.0),
"part": part,
}),
Json::object({
"type": Json::string("response.output_item.done"),
"output_index": Json::number(output_index.to_double()),
"item": item,
}),
]
}
///|
fn ChatToCodexResponsesStreamState::finish_tools(
self : ChatToCodexResponsesStreamState,
) -> Array[Json] {
let events : Array[Json] = []
for _, state in self.tool_states {
if !state.added || state.done {
continue
}
let output_index = state.output_index.unwrap_or(0)
let arguments = canonicalize_tool_arguments(
Some(Json::string(state.arguments)),
)
let is_custom_tool = codex_chat_tool_context_is_custom(
self.tool_context,
state.name,
)
let item = Json::object(
codex_response_call_item_from_chat_name(
"completed",
state.call_id,
state.name,
arguments,
self.tool_context,
),
)
self.output_items.push(item)
state.done = true
if is_custom_tool {
let input = custom_tool_input_from_chat_arguments(arguments)
if !input.is_empty() {
events.push(
Json::object({
"type": Json::string("response.custom_tool_call_input.delta"),
"item_id": Json::string(state.item_id),
"output_index": Json::number(output_index.to_double()),
"delta": Json::string(input),
}),
)
}
events.push(
Json::object({
"type": Json::string("response.custom_tool_call_input.done"),
"item_id": Json::string(state.item_id),
"output_index": Json::number(output_index.to_double()),
"input": Json::string(input),
}),
)
} else {
events.push(
Json::object({
"type": Json::string("response.function_call_arguments.done"),
"item_id": Json::string(state.item_id),
"output_index": Json::number(output_index.to_double()),
"arguments": Json::string(arguments),
}),
)
}
events.push(
Json::object({
"type": Json::string("response.output_item.done"),
"output_index": Json::number(output_index.to_double()),
"item": item,
}),
)
}
events
}
///|
fn ChatToCodexResponsesStreamState::next_output_index(
self : ChatToCodexResponsesStreamState,
) -> Int {
let index = self.next_output_index
self.next_output_index += 1
index
}
///|
fn ChatToCodexResponsesStreamState::base_response(
self : ChatToCodexResponsesStreamState,
status : String,
) -> Json {
let response : Map[String, Json] = {
"id": Json::string(self.response_id),
"object": Json::string("response"),
"created_at": Json::number(self.created_at.to_double()),
"status": Json::string(status),
"model": Json::string(self.model),
"output": Json::array(self.output_items.copy()),
"usage": self.latest_usage.unwrap_or(
Json::object({
"input_tokens": Json::number(0.0),
"output_tokens": Json::number(0.0),
}),
),
}
if status == "incomplete" {
response["incomplete_details"] = Json::object({
"reason": Json::string("max_output_tokens"),
})
}
Json::object(response)
}
///|
fn codex_response_id_from_chat_id(id : String) -> String {
if id.has_prefix("resp_") {
id
} else {
"resp_\{id}"
}
}
///|
fn codex_response_status_from_chat_finish_reason(reason : String?) -> String {
match reason {
Some("length") => "incomplete"
_ => "completed"
}
}
///|
fn openai_chat_delta_chunk(
id : String,
model : String,
created : Int,
delta : Map[String, Json],
finish_reason : Json,
) -> Json {
Json::object({
"id": Json::string(id),
"object": Json::string("chat.completion.chunk"),
"created": Json::number(created.to_double()),
"model": Json::string(model),
"choices": Json::array([
Json::object({
"index": Json::number(0.0),
"delta": Json::object(delta),
"finish_reason": finish_reason,
}),
]),
})
}
///|
fn extract_chat_completion_output(body : Json) -> ChatCompletionOutput {
let mut content = ""
let tool_calls : Array[Json] = []
guard body is Object(obj) else { return { content, tool_calls } }
if obj.get("output_text") is Some(String(text)) {
content = text
}
if obj.get("output") is Some(Array(outputs)) {
for output in outputs {
guard output is Object(item) else { continue }
match item.get("type") {
Some(String("message")) =>
content += extract_response_message_text(item)
Some(String("function_call")) =>
tool_calls.push(openai_tool_call_from_response_item(item))
_ => ()
}
}
}
{ content, tool_calls }
}
///|
fn extract_response_message_text(item : Map[String, Json]) -> String {
let texts : Array[String] = []
if item.get("content") is Some(Array(parts)) {
for part in parts {
guard part is Object(part_obj) else { continue }
if part_obj.get("type") is Some(String("output_text")) &&
part_obj.get("text") is Some(String(text)) {
texts.push(text)
}
}
}
texts.join("")
}
///|
fn openai_tool_call_from_response_item(item : Map[String, Json]) -> Json {
Json::object({
"id": Json::string(
json_string_from_map(item, "call_id").unwrap_or(
generate_chat_completion_id(),
),
),
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(
json_string_from_map(item, "name").unwrap_or("unknown"),
),
"arguments": Json::string(
canonicalize_tool_arguments(item.get("arguments")),
),
}),
})
}
///|
fn openai_tool_call_delta_from_response_item(item : Map[String, Json]) -> Json {
Json::object({
"index": Json::number(0.0),
"id": Json::string(
json_string_from_map(item, "call_id").unwrap_or(
generate_chat_completion_id(),
),
),
"type": Json::string("function"),
"function": Json::object({
"name": Json::string(
json_string_from_map(item, "name").unwrap_or("unknown"),
),
"arguments": Json::string(
canonicalize_tool_arguments(item.get("arguments")),
),
}),
})
}
///|
fn openai_usage_json(usage : TokenUsage) -> Json {
Json::object({
"prompt_tokens": Json::number(usage.input_tokens.to_double()),
"completion_tokens": Json::number(usage.output_tokens.to_double()),
"total_tokens": Json::number(
(usage.input_tokens + usage.output_tokens).to_double(),
),
"prompt_tokens_details": Json::object({
"cached_tokens": Json::number(usage.cache_read_tokens.to_double()),
}),
})
}
///|
fn codex_response_id(body : Json) -> String? {
guard body is Object(obj) else { return None }
json_string_from_map(obj, "id")
}
///|
fn json_bool_from_map(obj : Map[String, Json], key : String) -> Bool? {
match obj.get(key) {
Some(true) => Some(true)
Some(false) => Some(false)
_ => None
}
}
///|
fn json_string_from_map(obj : Map[String, Json], key : String) -> String? {
match obj.get(key) {
Some(String(value)) => Some(value)
_ => None
}
}
///|
fn generate_chat_completion_id() -> String {
"chatcmpl_\{moongate_random_id()}"
}