feat(cli): thread idempotency-key generation into the IR#17018
Conversation
…otencyKeyGeneration) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
AI Review Summary
Clean additive IR change threading idempotency-key generation from generator config into the IR. The plumbing is consistent with the existing user-agent precedent. One correctness concern: an empty-string custom header-name falls through to a valid string and would silently produce an empty header, and the changelog date is in the future (2026).
- 🔵 2 suggestion(s)
| } | ||
| if (typeof value === "object" && value !== null) { | ||
| const headerName = (value as { "header-name"?: unknown })["header-name"]; | ||
| return { headerName: typeof headerName === "string" ? headerName : DEFAULT_IDEMPOTENCY_KEY_HEADER }; |
There was a problem hiding this comment.
🔵 suggestion
An empty-string header-name passes the typeof === "string" check and produces { headerName: "" }, yielding an empty wire header downstream. Consider treating blank strings as "use default":
| return { headerName: typeof headerName === "string" ? headerName : DEFAULT_IDEMPOTENCY_KEY_HEADER }; | |
| return { headerName: typeof headerName === "string" && headerName.trim() !== "" ? headerName : DEFAULT_IDEMPOTENCY_KEY_HEADER }; |
| The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), | ||
| and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). | ||
|
|
||
| ## [v67.11.0] - 2026-07-08 |
There was a problem hiding this comment.
🔵 suggestion
Date is 2026-07-08 (and the entry below is 2026-07-07). Either the whole changelog is time-traveling or this is a typo — worth confirming it matches the surrounding convention before merge.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ion field Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Docs Generation Benchmark ResultsComparing PR branch against median of 5 nightly run(s) on
Docs generation runs |
SDK Generation Benchmark ResultsComparing PR branch against median of 5 nightly run(s) on Full benchmark table (click to expand)
main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via |
Description
Promotes idempotency-key auto-generation from a per-generator config flag to a single canonical IR field, so every generator reads one source of truth instead of each defining/reinterpreting its own config key (
autoGenerateIdempotencyKeyvsauto_generate_idempotency_keyvs kebab-case) and re-deriving its own POST/PUT method-gating.This PR is IR + CLI only — it adds the field and the CLI plumbing that populates it. Generators consume the published
@fern-fern/ir-sdk, so the follow-up generator PRs (which readsdkConfig.idempotencyKeyGeneration) land after this merges and the new IR (67.11.0) is published. The field is optional/additive → minor IR bump; no migration needed (the existing v67→v66 passthrough migration drops it naturally for older generators).Changes Made
ir-types-latest/definition/ir.yml): addSdkConfig.idempotencyKeyGeneration: optional<IdempotencyKeyGeneration>; newIdempotencyKeyGeneration { headerName: string; methods: list<HttpMethod> }.methodscentralizes the eligible-method set (defaults to[POST, PUT]) so gating is identical across generators rather than hard-coded per language. Presence of the optional block encodes "enabled" (absent = disabled, the default). Regenerated TS types viapnpm ir:generate.VERSION67.10.2 → 67.11.0; hand-edited IRCHANGELOG.mdentry.getIdempotencyKeyGenerationFromGeneratorConfig()inapi-workspace-commonsresolves theauto-generate-idempotency-keygenerator config (acceptstrue, or{ header-name, methods }; defaults headerIdempotency-Key, methods[POST, PUT]), modeled on the existinguser-agentprecedent. Added toCLI_ONLY_CONFIG_KEYSso it's stripped from the config forwarded to generators. Wired into all IR-construction call sites (generateIntermediateRepresentation, local + remote runners,GenerationRunner).AbstractSpecConverterand their-utilsmerge test set the new (optional) field.packages/cli/cli/changes/unreleased/add-idempotency-key-generation-ir.yml(feat).Testing
pnpm turbo run compilegreen across affected packages (ir-generator, api-workspace-commons, local/remote runners, ir-utils, v3-importer-commons).pnpm turbo run testgreen for@fern-api/ir-utils,@fern-api/ir-migrations, and@fern-api/register— updated additive snapshots only (idempotencyKeyGenerationpasses through asnull/undefined).Link to Devin session: https://app.devin.ai/sessions/c3ddfc2bb3b04f9a9e2977e756158dee
Requested by: @cadesark