Skip to content

feat(cz-git,plugin-loader): add apiExtraBody option - #262

Merged
Zhengqbbb merged 1 commit into
Zhengqbbb:mainfrom
yohkuri:feat/api-extra-body
Aug 18, 2026
Merged

Zhengqbbb merged 1 commit into
Zhengqbbb:mainfrom
yohkuri:feat/api-extra-body

Conversation

@yohkuri

@yohkuri yohkuri commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Related ISSUE

#261

Type Of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • πŸ“ Document (This change requires a documentation update)
  • 🎨 Theme style (Theme style beautification)
  • ⚠ Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • πŸ”¨ Workflow (Workflow changes)

Clear Describe

  • feat: add apiExtraBody option to adjust the AI request body
  • docs: add apiExtraBody option document (en / zh)

Description

useModelStrategy() builds one fixed request body for every model, and none of its fields can be
reached from config. As reported in #261, models which require max_completion_tokens therefore
cannot be used at all: they reject max_tokens at any value, and accept only the default
temperature.

apiExtraBody is merged into the request body after the defaults are built.

The one design point worth reviewing: a null value removes the field instead of overriding it.
A plain merge is not enough here β€” sending max_tokens alongside max_completion_tokens still
fails, and max_tokens: null fails as well, so the key has to be absent from the JSON entirely.
temperature, by contrast, could be repaired by overriding it with 1; null just keeps the two
cases uniform.

// ~/.config/.czrc
{
  "apiModel": "gpt-5.6-luna",
  "apiExtraBody": {
    "max_tokens": null,
    "temperature": null,
    "max_completion_tokens": 4096
  }
}

Notes on the implementation:

  • In aiLoader() the key is spread only when it is set, so an unset value in ~/.config/.czrc
    cannot clobber a project-level apiExtraBody.
  • useModelStrategy is now exported so it can be unit tested. It is not re-exported from
    generator/index.ts, so the public API is unchanged.
  • No JSON schema change: the AI options (apiModel, apiEndpoint, …) are not part of
    scripts/czrc-schema.d.ts today, so apiExtraBody follows the same treatment. Happy to add them
    all if you would prefer.

⚠ Please review the Chinese documentation

The Chinese docs in this PR β€” docs/zh/config/engineer.md and docs/zh/recipes/openai.md β€” were
written with AI assistance. I do not read Chinese and cannot verify the wording myself, so
please review those two files closely rather than trusting them. I would much rather you correct
or rewrite them than merge phrasing I am unable to check.

If you prefer, I can drop the zh changes from this PR entirely and leave them to you.

Test Case

Unit tests β€” added packages/cz-git/__tests__/api.test.ts (6 cases): default payload unchanged,
add a field, override a field, remove a field via null, the max_completion_tokens scenario, and
that the option object is not mutated.

pnpm test:run
# Test Files  13 passed (13)
#      Tests  116 passed (116)

pnpm lint

Against the real API β€” loaded the config above from ~/.config/.czrc through configLoader()
β†’ generateOptions() β†’ useModelStrategy(), then posted the resulting body to
api.openai.com/v1/chat/completions:

config resulting payload keys HTTP
apiModel: gpt-5.6-luna + the apiExtraBody above model, messages, stream, top_p, n, max_completion_tokens 200
apiModel: gpt-4o-mini, no apiExtraBody model, messages, stream, top_p, temperature, max_tokens, n 200

The second row is the regression check: with no apiExtraBody set, the request body is identical to
what it was before this change.


Unrelated note, in case it is useful: 4 tests in
packages/@cz-git/plugin-loader/__tests__/loader.test.ts fail on my machine both with and without
this change, because aiLoader() reads the real $HOME/.config/.czrc. They pass with a clean
HOME, and CI on main is green β€” so it is not a regression here, but it may be worth isolating
that test from the developer's home config.

The AI request body is hardcoded, so a model that rejects one of its
fields cannot be used at all. Models which require
`max_completion_tokens` are the current case: they reject `max_tokens`
at any value, and accept only the default `temperature`.

`apiExtraBody` is merged into the request body, and a `null` value
removes the field instead of overriding it, because such fields have to
be absent from the request rather than carry a different value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

πŸ‘· Deploy request for cz-git pending review.

Visit the deploys page to approve it

Name Link
πŸ”¨ Latest commit 00ec467

@Zhengqbbb
Zhengqbbb merged commit a22115c into Zhengqbbb:main Aug 18, 2026
6 checks passed
Zhengqbbb added a commit that referenced this pull request Aug 18, 2026
@Zhengqbbb

Copy link
Copy Markdown
Owner

LGTM πŸ‘

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.

2 participants