Collapse Conduit public API surface#64
Conversation
- Add prompt injection for .jsonObject and .jsonSchema via responseFormatInstruction(), matching Anthropic's proven pattern - Strip markdown code fences from model output when JSON format is requested (on-device FM wraps JSON in fences despite instructions) - Add native generate(returning:) overrides using Apple's respond(to:generating:) for types conforming to both Conduit.Generable and FoundationModels.Generable (constrained decoding) - Wire responseFormat through all code paths: generate, stream, streamWithMetadata - Add 4 integration tests and 9 unit tests for fence stripping edge cases
- Extract shared ResponseFormat.promptInstruction computed property, removing duplicate responseFormatInstruction() from both AnthropicProvider and FoundationModelsProvider - Make stripCodeFences internal so tests use production code directly, eliminating duplicated test implementation - Consolidate two generate(returning:) overloads into shared respondStructured() private helper
Make Conduit the single public library surface, remove the ConduitAdvanced facade target, and preserve compatibility through the unified API. Stabilize provider dependency traits, docs, examples, and request/streaming behavior across OpenAI-compatible providers. Add regression coverage for canonical imports, package manifest stability, provider requests, structured output, macros, and MLX support.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 98fc93ddb7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| withLock { | ||
| if isGenerating { | ||
| isGenerating = false | ||
| lastError = AIError.cancelled | ||
| if _isGenerating { | ||
| _isGenerating = false | ||
| _lastError = AIError.cancelled | ||
| } |
There was a problem hiding this comment.
Clear active request marker when canceling
After cancel() completes, this path only flips _isGenerating/_lastError and never clears activeRequestID. Because new send/streamResponse calls require activeRequestID == nil, callers can immediately hit "already has an in-progress generation" right after await cancel(), and the session can remain blocked if the canceled task never reaches its cleanup block.
Useful? React with 👍 / 👎.
| return Provider( | ||
| makeSession: sessionProvider.makeSession, | ||
| imageGenerator: AnyImageGenerator(provider) | ||
| ) |
There was a problem hiding this comment.
Use separate provider instance for image facade
This wires the same OpenAIProvider instance into both session generation and images. Since OpenAIProvider.cancelGeneration() cancels both text and image tasks, calling conduit.images.cancel() can cancel an unrelated in-flight text request (and text cancellation can kill image generation) when both flows share one Conduit instance.
Useful? React with 👍 / 👎.
Summary
Conduitlibrary surface and remove the oldConduitFacadetarget file.Conduitimport, including structured output and streaming flows.Verification
swift buildswift test(385 tests passed)Notes
.build-default/andExamples/MLXTestApp/.build/.