Skip to content

Conversation

@bolinfest
Copy link
Collaborator

@bolinfest bolinfest commented May 30, 2025

Prior to this PR, there were two big misses in chat_completions.rs:

  1. The loop in stream_chat_completions() was only including items of type ResponseItem::Message when building up the "messages" JSON for the POST request to the chat/completions endpoint. This fixes things by ensuring other variants (FunctionCall, LocalShellCall, and FunctionCallOutput) are included, as well.
  2. In process_chat_sse(), we were not recording tool calls and were only emitting items of type ResponseEvent::OutputItemDone(ResponseItem::Message) to the stream. Now we introduce FunctionCallState, which is used to accumulate the deltas of type tool_calls, so we can ultimately emit a ResponseItem::FunctionCall, when appropriate.

While function calling now appears to work for chat completions with my local testing, I believe that there are still edge cases that are not covered and that this codepath would benefit from a battery of integration tests. (As part of that further cleanup, we should also work to support streaming responses in the UI.)

The other important part of this PR is some cleanup in core/src/codex.rs. In particular, it was hard to reason about how run_task() was building up the list of messages to include in a request across the various cases:

  • Responses API
  • Chat Completions API
  • Responses API used in concert with ZDR

I like to think things are a bit cleaner now where:

  • zdr_transcript (if present) contains all messages in the history of the conversation, which includes function call outputs that have not been sent back to the model yet
  • pending_input includes any messages the user has submitted while the turn is in flight that need to be injected as part of the next POST to the model
  • input_for_next_turn includes the tool call outputs that have not been sent back to the model yet

@github-actions
Copy link

Summary

Removes the legacy .github/actions/codex workflow (≈1.9 k LOC) and refactors the Rust core to centralise tool handling. A new openai_tools.rs builds tool JSON once, chat_completions gains streaming function/shell-call support, and related duplication in client.rs/codex.rs is cleaned up.

Notable changes

  • Delete .github/actions/codex + codex.yml, label templates, etc.
  • Add openai_tools.rs; reuse it from client.rs and chat_completions.rs.
  • Stream-time assembly of function calls, argument buffering, and better conversation history recording.
  • Minor justfile tweak.

Review

Nice sweep: codebase is leaner and tool logic is now in one place 👍.

  • openai_tools.rs might use OnceLock/Lazy from once_cell to avoid nightly LazyLock.
  • A couple of TODOs and commented blocks could be pruned before merge.
  • Consider adding a small unit test for create_tools_json to guard the schema rewrite.

Other than those nits, the changes look solid!


View workflow run

@bolinfest bolinfest force-pushed the pr1167 branch 2 times, most recently from ca2c197 to f6a0a3a Compare May 30, 2025 20:49
@bolinfest bolinfest changed the base branch from main to pr1177 May 30, 2025 20:49
@bolinfest bolinfest force-pushed the pr1167 branch 2 times, most recently from 8e3c9ab to 9346410 Compare May 30, 2025 21:02
bolinfest added a commit that referenced this pull request May 30, 2025
…ns.rs (#1177)

The main motivator behind this PR is that `stream_chat_completions()`
was not adding the `"tools"` entry to the payload posted to the
`/chat/completions` endpoint. This (1) refactors the existing logic to
build up the `"tools"` JSON from `client.rs` into `openai_tools.rs`, and
(2) updates the use of responses API (`client.rs`) and chat completions
API (`chat_completions.rs`) to both use it.

Note this PR alone is not sufficient to get tool calling from chat
completions working: that is done in
#1167.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/1177).
* #1167
* __->__ #1177
Base automatically changed from pr1177 to main May 30, 2025 21:07
@bolinfest bolinfest force-pushed the pr1167 branch 2 times, most recently from 47c9aaf to b7d9e36 Compare May 31, 2025 06:50
@github-actions
Copy link

Summary

This PR adds end-to-end support for streaming tool/function calls: the chat-completions client now accumulates tool_calls chunks, emits a single FunctionCall item when complete, and session logic records both the call and its output in the conversation history.

Notes

• Introduces FunctionCallState to stitch together fragmented SSE data.
• Handles FunctionCall, LocalShellCall, and their outputs when building the next prompt.
• Adds extensive tracing / debug logs.
• Minor type simplifications (use mcp_types::CallToolResult).

Review
Great step toward full tool-call parity with the classic API—code is clear and well-commented.
A few small nits before merge:

  • Consider resetting fn_call_state after emitting to avoid residue if a stream contains multiple calls.
  • The “Confirm with API team.” TODO and verbose debug logs could be trimmed or guarded with feature flags.
  • Double-check the placeholder ID handling for LocalShellCall (empty string fallback).

Overall, solid improvement—just minor clean-ups needed 👍


View workflow run

@github-actions
Copy link

Summary

Adds full streaming-tool-call support to the Rust core:

  • chat_completions.rs now assembles multi-chunk tool_calls, emits FunctionCall items, and accumulates assistant text while streaming.
  • codex.rs records these new items in history, maps them to follow-up inputs, improves logging, and tweaks a return type import.

Review

Nice step toward parity with the new Chat Completions features—code is clear and well-structured.

  • Consider resetting fn_call_state after emitting the completed call to avoid leakage on reused streams.
  • A few commented blocks / extra debug logs could be trimmed before merge.
  • Unit coverage for the new branching paths would help catch regressions.

Otherwise looks solid—LGTM once the nits above are addressed.


View workflow run

@bolinfest bolinfest force-pushed the pr1167 branch 4 times, most recently from e5f9b9c to 0b88045 Compare June 2, 2025 20:19
@bolinfest bolinfest changed the base branch from main to pr1195 June 2, 2025 20:19
@bolinfest bolinfest mentioned this pull request Jun 2, 2025
bolinfest added a commit that referenced this pull request Jun 2, 2025
Update what we log to make `RUST_LOG=debug` a bit easier to work with.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/1196).
* #1167
* __->__ #1196
Base automatically changed from pr1195 to main June 2, 2025 20:31
@bolinfest bolinfest merged commit d7245cb into main Jun 2, 2025
9 checks passed
@bolinfest bolinfest deleted the pr1167 branch June 2, 2025 20:47
@github-actions github-actions bot locked and limited conversation to collaborators Jun 2, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants