feat(kosong): support structured response formats#1397
Conversation
🦋 Changeset detectedLatest commit: d35dcaa The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f2b73f1a80
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| createParams['instructions'] = systemPrompt; | ||
| } | ||
| if (options?.responseFormat !== undefined) { | ||
| createParams['text'] = responseFormatToResponsesText(options.responseFormat); |
There was a problem hiding this comment.
Preserve existing Responses text options
When a caller has already configured Responses-specific text options via withGenerationKwargs (for example text: { verbosity: 'low' }), this assignment replaces the whole text object after ...kwargs has been applied. Adding responseFormat therefore silently drops those existing options even though text.format can coexist with them; merge the new format into the prior text config instead of overwriting it.
Useful? React with 👍 / 👎.
| if (format === undefined) return; | ||
| config['responseMimeType'] = 'application/json'; | ||
| if (format.type === 'json_schema') { | ||
| config['responseJsonSchema'] = format.jsonSchema.schema; |
There was a problem hiding this comment.
Remove conflicting Gemini schema config
If a Google provider was configured with the native responseSchema in withGenerationKwargs, using the new responseFormat: { type: 'json_schema' } leaves that existing responseSchema in config and adds responseJsonSchema here. Gemini's generateContent config treats those schema fields as mutually exclusive, so that combination turns a previously valid provider config into a rejected request; clear or replace the old schema field when applying the common format.
Useful? React with 👍 / 👎.
Signed-off-by: _Kerman <kermanx@qq.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1fa7b33236
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| createParams['instructions'] = systemPrompt; | ||
| } | ||
| if (options?.responseFormat !== undefined) { | ||
| createParams['text'] = responseFormatToResponsesText(options.responseFormat); |
There was a problem hiding this comment.
Preserve existing Responses text options
When callers have already configured other OpenAI Responses text settings through withGenerationKwargs (for example text: { verbosity: 'low' }), this assignment runs after ...kwargs and replaces the entire text object with only the structured-output format. That silently drops those text settings on every structured-output request; merge the new format into the existing text object instead.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| "@moonshot-ai/kosong": patch | |||
There was a problem hiding this comment.
Add the CLI package to this changeset
This changeset lists only the internal @moonshot-ai/kosong package, but the repository's changeset rules require internal package source changes that enter the CLI bundle to manually list @moonshot-ai/kimi-code. As written, the private/internal package can be versioned without bumping the published CLI artifact, so this provider-layer behavior may not ship in the next CLI release/changelog.
Useful? React with 👍 / 👎.
…s-kosong # Conflicts: # packages/kosong/src/providers/anthropic.ts
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4b56ef07a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| createParams['instructions'] = systemPrompt; | ||
| } | ||
| if (options?.responseFormat !== undefined) { | ||
| createParams['text'] = responseFormatToResponsesText(options.responseFormat); |
There was a problem hiding this comment.
Preserve existing Responses text options
For callers that configure Responses-only text options via withGenerationKwargs({ text: { verbosity: 'low' } }) (the interface intentionally accepts native kwargs), this assignment replaces the whole text object, so the upstream request silently drops verbosity whenever responseFormat is also supplied. The Responses API groups format and verbosity under the same text config, so this should merge the new format into any existing text object instead of overwriting it.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d35dcaad54
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| systemInstruction: systemPrompt, | ||
| ...(tools.length > 0 ? { tools: tools.map((t) => toolToGoogleGenAI(t)) } : {}), | ||
| }; | ||
| applyResponseFormat(config, options?.responseFormat); |
There was a problem hiding this comment.
Guard Gemini structured output when tools are present
When the caller asks for a Gemini structured response while any tools are supplied, the config already contains tools from the previous line and this call adds responseMimeType: 'application/json'; Gemini rejects that combination with Function calling with a response mime type: 'application/json' is unsupported. In a normal agent turn that keeps tools registered while asking for a final structured answer, the new option turns into a 400 instead of a usable response, so handle this provider limitation explicitly before dispatching.
Useful? React with 👍 / 👎.
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| "@moonshot-ai/kosong": patch | |||
There was a problem hiding this comment.
Include the CLI in the changeset
The gen-changesets rules require internal @moonshot-ai/* source changes that enter the CLI bundle to list @moonshot-ai/kimi-code, because the CLI uses workspace devDependencies and changesets will not propagate the bump automatically. This commit changes packages/kosong, which is bundled into the CLI through the internal packages, but the changeset bumps only @moonshot-ai/kosong; the published CLI can therefore ship these bits without a CLI version/changelog entry.
Useful? React with 👍 / 👎.
Related Issue
No linked issue. This addresses the provider-layer gap for passing native structured output / JSON schema response format options through
@moonshot-ai/kosong.Problem
GenerateOptionsdid not expose a common response-format constraint, so provider callers could not request native JSON object mode or JSON-schema structured outputs through the sharedkosongabstraction.What changed
ResponseFormatoption forjson_objectandjson_schemaoutput constraints.response_formattext.formatoutput_config.formatfor JSON schema, with an explicit error for schema-less JSON object moderesponseMimeTypeandresponseJsonSchema@moonshot-ai/kosongand the bundled CLI package.Protocol checks were made against the locked SDK/API type definitions used by this package and the public provider documentation for structured output fields.
Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.Validation:
./node_modules/.bin/vitest run packages/kosong/test/anthropic.test.ts packages/kosong/test/kimi.test.ts packages/kosong/test/openai-legacy.test.ts packages/kosong/test/openai-responses.test.ts packages/kosong/test/google-genai.test.ts./node_modules/.bin/tsc -p packages/kosong/tsconfig.json --noEmit./node_modules/.bin/oxlint --type-aware packages/kosong/src/provider.ts packages/kosong/src/providers/anthropic.ts packages/kosong/src/providers/google-genai.ts packages/kosong/src/providers/kimi.ts packages/kosong/src/providers/openai-legacy.ts packages/kosong/src/providers/openai-responses.ts packages/kosong/test/anthropic.test.ts packages/kosong/test/google-genai.test.ts packages/kosong/test/kimi.test.ts packages/kosong/test/openai-legacy.test.ts packages/kosong/test/openai-responses.test.tsgit diff --check