Skip to content

Polish TUI and fix Codex tool call streaming - #223

Closed
smittyPNW wants to merge 1 commit into
Twigpine:mainfrom
smittyPNW:codex/openclaude-codex-polish
Closed

smittyPNW wants to merge 1 commit into
Twigpine:mainfrom
smittyPNW:codex/openclaude-codex-polish

Conversation

@smittyPNW

Copy link
Copy Markdown

Summary

  • fix Codex/OpenAI tool-call streaming so final arguments from output item completion events are preserved
  • polish the TUI shell with cleaner prompt, status, error, tool, and startup presentation
  • add local launch and stop scripts for the patched Codex OAuth workflow

Testing

  • npx bun run build
  • npx bun test src/services/api/codexShim.test.ts
  • CLAUDE_CODE_USE_OPENAI=1 OPENAI_MODEL=codexplan node dist/cli.mjs -p --bare --permission-mode bypassPermissions "Reply with exactly: facelift smoke ok"
  • CLAUDE_CODE_USE_OPENAI=1 OPENAI_MODEL=codexplan node dist/cli.mjs -p --bare --permission-mode bypassPermissions --verbose --output-format stream-json "Use Bash to print the current directory name only."

@auriti auriti left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

The core jsonBuffer approach is correct — accumulating streamed deltas and comparing against the canonical final payload in output_item.done is the right pattern. The startTextBlockIfNeeded / closeActiveTextBlock generator refactoring is clean. No conflicts with #237.

Several issues need addressing before merge:


Critical: flush logic ambiguity

The response.output_item.done handler compares finalArgs.length > toolBlock.jsonBuffer.length to decide whether to emit a remainder delta. This silently does nothing when:

  • finalArgs.length === toolBlock.jsonBuffer.length (assumes buffer is exact prefix — OK in ideal case)
  • finalArgs.length < toolBlock.jsonBuffer.length (malformed stream delivered more deltas than the final payload) — silently proceeds with corrupt buffered JSON

Suggested fix:
```ts
if (finalArgs && finalArgs !== toolBlock.jsonBuffer) {
const remainder = finalArgs.slice(toolBlock.jsonBuffer.length)
if (remainder.length > 0) {
yield { type: 'content_block_delta', index: toolBlock.index,
delta: { type: 'input_json_delta', partial_json: remainder } }
}
toolBlock.jsonBuffer = finalArgs
}
```


Important: toolBlocksByItemId.delete key mismatch

```ts
toolBlocksByItemId.delete(String(item.id))
```

If item.id is undefined in the done event but the block was keyed with the fallback toolUseId, String(undefined) === 'undefined' won't match the original key. The entry leaks and the cleanup loop emits a spurious content_block_stop. Fix: mirror the exact key used during insertion:

```ts
const key = String(item.id ?? toolUseId)
toolBlocksByItemId.delete(key)
```


Important: test doesn't cover the actual flush path

The new test verifies input_json_delta events appear, but doesn't simulate the specific scenario: partial JSON via function_call_arguments.delta followed by a longer item.arguments in output_item.done that requires flushing the remainder. Without this fixture, the regression path is untested.


Minor

  • CondensedLogo tagline 'Codex-ready terminal for any LLM' narrows the product positioning — worth a team discussion
  • ⎿ → │ removes the end-cap visual on message boundaries — subjective but affects every response

What works well

  • jsonBuffer accumulation pattern is architecturally correct
  • startTextBlockIfNeeded / closeActiveTextBlock refactoring is clean
  • Full SSE sequence test is a solid regression baseline
  • No conflicts with #237

Fix the flush logic and the key mismatch, and this is ready.

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

@smittyPNW can you check that issues ?

@smittyPNW smittyPNW closed this by deleting the head repository Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants