Skip to content

Migrate OpenAI to Responses API + reasoning + images#1250

Merged
datlechin merged 12 commits into
mainfrom
feat/ai-responses-api-1112
May 14, 2026
Merged

Migrate OpenAI to Responses API + reasoning + images#1250
datlechin merged 12 commits into
mainfrom
feat/ai-responses-api-1112

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

  • Closes Migrate OpenAI provider to Responses API and add Codex models #1112. .openAI provider now uses POST /v1/responses via new OpenAIResponsesProvider. OpenRouter/Ollama/Custom keep Chat Completions via existing OpenAICompatibleProvider.
  • Adds reasoning panel (collapsible DisclosureGroup, "Reasoning…" while streaming, 80ms debounce on delta text). Surfaced for OpenAI reasoning models (gpt-5.5, gpt-5-codex, gpt-5.3-codex, gpt-5.4-mini) and Claude extended thinking (Opus 4.7, Sonnet 4.6, Haiku 4.5).
  • Adds image input: drag-and-drop, paste, attachment chip. HEIC/TIFF/BMP convert to PNG/JPEG q0.92 via ImageIO. EXIF and GPS stripped at the boundary. Stored in ~/Library/Caches/com.TablePro/AIChatImages/<uuid>.<ext>; wire holds filename + media type only.
  • Reasoning effort picker per provider, gated by descriptor.supportsReasoning and the model's supportedEffortLevels. OpenAI: minimal/low/medium/high/xhigh. Claude: low/medium/high/xhigh mapped to adaptive effort or budget_tokens on pre-adaptive models. max_output_tokens auto-scales per effort level so budget_tokens < max_tokens holds for Anthropic.
  • Strict tools by default: ChatToolSchemaBuilder.object emits additionalProperties: false, auto-includes all property keys in required, supports nullable unions for optional fields. All 8 existing tools migrated.
  • Stateless full-history replay with reasoning items round-tripped via ReasoningOpaque(itemID, value, blockType) — server-issued rs_* ID flows back into the next input array, no synthetic ID collisions. Required for Responses tool-loop correctness (server rejects function_call_output without its preceding reasoning item).
  • Curated model picker (Picker.menu) with Curated / Fetched / Other sections plus free-text fallback.
  • Zero PluginKit ABI impact (AI layer is app-only).

Test plan

  • Build clean (xcodebuild ... build)
  • SwiftLint clean (swiftlint lint --strict)
  • 27 new tests pass (parser, encoding, strict tool audit) plus all existing AI tests
  • Smoke test: OpenAI with gpt-5.5 + reasoning medium → Reasoning panel expands while streaming, collapses on done, encrypted reasoning item round-trips through tool loops without 400 error
  • Smoke test: Claude Opus 4.7 with reasoning high → adaptive thinking, signature round-trips through tool loop
  • Smoke test: drag PNG/HEIC into composer → chip appears → submit → image renders in assistant view → image block round-trips in ChatTurn history
  • Smoke test: paste image from clipboard → same flow as drop
  • Smoke test: change to Ollama provider → drop zone hidden, composer accepts no images
  • Smoke test: execute_query tool still parses correctly after strict schema migration (optional fields sent as null or omitted)

@datlechin datlechin merged commit 45e8ee7 into main May 14, 2026
2 checks passed
@datlechin datlechin deleted the feat/ai-responses-api-1112 branch May 14, 2026 01:53
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.

Migrate OpenAI provider to Responses API and add Codex models

1 participant