Skip to content

feat(kosong): support structured response formats#1397

Merged
kermanx merged 5 commits into
mainfrom
xtr/structured-outputs-kosong
Jul 7, 2026
Merged

feat(kosong): support structured response formats#1397
kermanx merged 5 commits into
mainfrom
xtr/structured-outputs-kosong

Conversation

@kermanx

@kermanx kermanx commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

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

GenerateOptions did not expose a common response-format constraint, so provider callers could not request native JSON object mode or JSON-schema structured outputs through the shared kosong abstraction.

What changed

  • Added a provider-level ResponseFormat option for json_object and json_schema output constraints.
  • Mapped the option to each provider's native protocol shape:
    • Kimi and OpenAI Chat Completions: response_format
    • OpenAI Responses: text.format
    • Anthropic Messages: output_config.format for JSON schema, with an explicit error for schema-less JSON object mode
    • Google GenAI SDK: responseMimeType and responseJsonSchema
  • Added provider request-shape tests for the supported mappings.
  • Added a patch changeset for @moonshot-ai/kosong and 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

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, 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.ts
  • git diff --check

@changeset-bot

changeset-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d35dcaa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kosong Patch

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

@pkg-pr-new

pkg-pr-new Bot commented Jul 5, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@d35dcaa
npx https://pkg.pr.new/@moonshot-ai/kimi-code@d35dcaa

commit: d35dcaa

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@kermanx

kermanx commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge 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
@kermanx

kermanx commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@kermanx

kermanx commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@kermanx kermanx merged commit 6c9abe8 into main Jul 7, 2026
10 checks passed
@kermanx kermanx deleted the xtr/structured-outputs-kosong branch July 7, 2026 14:02
@github-actions github-actions Bot mentioned this pull request Jul 7, 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.

1 participant