2.76.3
(fix): The README “Environments” usage example now passes the client options via the
clientOptions: named argument so the generated snippet compiles. The root
client constructor’s first positional parameter is the auth token string, so
the previous new Client(new ClientOptions { ... }) snippet passed
ClientOptions where a string? token was expected.
2.76.2
(fix): A generated nested type whose name matches the SDK’s root namespace segment now emits
global::-qualified references. Previously such a nested type shadowed the namespace
root within its enclosing type’s body, so references like Acme.Api.SomeType resolved to the
nested type and failed to compile. The global:: qualifier is applied
only to references written inside the enclosing type where the shadow is visible, so
unrelated references to the same root segment elsewhere in the SDK are left
unqualified.
2.76.1
(fix): Endpoints without a request wrapper (no request object, a request that is just
a body, or a bytes request) now send service- and endpoint-level headers whose
types are literals (e.g. Accept-Encoding: literal<"gzip">). Previously these
headers were silently dropped because there was no request object to carry them.
2.75.2
(fix): Fix a compile error in the generated OAuthTokenProvider when the token endpoint’s
expires-in response property is optional. The provider now null-checks the value
before computing the token expiry instead of passing a nullable number to
DateTime.AddSeconds.
2.75.1
(fix): Wire OAuth client-credentials authentication into the root client when the OAuth
scheme is not the first scheme in the API’s auth configuration (e.g.
auth: any with basic auth listed before OAuth). Previously the OAuth token
provider was only generated when OAuth was the first auth scheme, so the root
client silently fell back to the other schemes and never used the OAuth
credentials. When both an OAuth and an inferred auth scheme are present, the
provider-based scheme that appears first in the auth configuration is used.
2.76.0
(fix): Add an opt-in dedupe-union-base-properties configuration flag (default off) that stops
duplicating a discriminated union’s base properties on its samePropertiesAsObject variant
leaves. The decision is read from the IR fact
ObjectTypeDeclaration.deferredUnionBaseProperties (computed once in the IR with structural
type equality and an exclusive-variant guard), so the generator never re-derives it. When
enabled, the union envelope owns the shared base properties, the variant leaf class and its
example initializers omit them, and the union’s JSON reader strips union-owned properties
before deserializing a variant. Off by default, so existing generated output is unchanged; the
default is expected to flip in a future major version with a migration.
2.75.0
(feat): Add support for auto-generating an Idempotency-Key header on generated SDK
clients, driven by the IR. When sdkConfig.idempotencyKeyGeneration is present
(configured once via the auto-generate-idempotency-key generator config key
and resolved by the CLI), the SDK attaches an idempotency-key request header
whose value is a freshly generated UUIDv4 (System.Guid.NewGuid().ToString())
at request time. The wire header name and the eligible HTTP methods come from
the IR, so behavior is consistent across every generator. A caller-provided
value always wins: a declared idempotency header or a header supplied through
request-options takes precedence, and the generated UUID is only a fallback.
The header is only injected on the eligible methods. Disabled by default, so
existing generated output is unchanged.
2.74.0
(feat): Add support for server URL variables (region/edge routing). When an API’s servers
declare URL variables (e.g. https://api.{region}.example.com), each variable is
now exposed as an optional string property on ClientOptions (idiomatic PascalCase,
e.g. Region). Variable names that collide with an existing client option are
prefixed with ServerUrl (e.g. an environment variable becomes ServerUrlEnvironment).
When set at construction time, the values are interpolated into the environment base
URL(s), falling back to each variable’s default otherwise. Explicit BaseUrl or
Environment options take precedence, and interpolation fails clearly when a required
variable has neither a client option nor a default.
2.73.2
(fix): Enable automatic response decompression on the default HttpClient. The default client
is now created with an HttpClientHandler configured with AutomaticDecompression
(DecompressionMethods.All on .NET 5+, GZip | Deflate on older targets), so responses
with a Content-Encoding of gzip or deflate are decompressed transparently — including
when an Accept-Encoding request header is set explicitly by the API spec. User-supplied
HttpClients provided via ClientOptions are not modified.
2.73.1
(fix): Make the structured User-Agent (emitted when includePlatformHeaders is
enabled) comply with the RFC 7230 token grammar. The runtime token is now
dotnet instead of .NET, since a leading dot is not a valid token
character (e.g. dotnet/8.0.4). The architecture label is also normalized so
the 64-bit x86 aliases (x64, amd64, x86_64) all report as the canonical
x86_64.
2.73.0
(feat): Add opt-in support for a structured User-Agent header on generated SDK
clients of the form {sdkName}/{sdkVersion} ({os}; {arch}) {runtime}/{runtimeVersion}
(e.g. my-sdk/1.2.0 (linux; x64) .NET/8.0.4). The OS, architecture, and
runtime version are resolved at runtime via
System.Runtime.InteropServices.RuntimeInformation and System.Environment.
This is gated behind a new include-platform-headers config option and is
disabled by default, so existing generated output is unchanged. When enabled
it remains subject to the omit-fern-headers config option.
2.72.2
(fix): Make each scheme’s credentials optional under any-composed auth. Previously,
with a multi-scheme auth: any: [...] config the generated client treated OAuth
(and other) credentials as unconditionally required at construction, so a caller
who only wanted API-key auth could not instantiate the client. Credentials now
fall back to environment variables without throwing, and the OAuth/inferred token
provider and auth headers are only set up when that scheme’s credentials are present.
2.72.1
(chore): 将捆绑的 @fern-api/generator-cli 升级到 0.9.44,以便在推送到 GitHub 时对每个仅存在于本地的提交都进行签名,而不仅仅是 HEAD。Replay 分支包含多个提交(例如 [fern-generated] + [fern-replay]);此前只有 HEAD 提交通过 GitHub API 重新创建并签名,导致 PR 上更早的提交未经验证。
2.72.0
(feat): 为 C# SDK 生成器新增 default-timeout-in-milliseconds 配置选项,用于以毫秒表示默认网络超时(映射到 .NET 的 TimeSpan)。生成的 ClientOptions.Timeout 现在根据毫秒计算(当设置为 "infinity" 时为 Timeout.InfiniteTimeSpan)。default-timeout-in-seconds 选项现已弃用,但仍完全向后兼容:当仅设置秒键时,会将其转换为毫秒。当二者同时设置时,新键优先。
2.71.2
(fix): 修复当用户编写的示例以不同于 URL 路径模板的顺序列出路径参数时,mock-server 测试和 XML 文档 <example> 代码片段以错误顺序(CS1503)调用带路径参数的客户端方法的问题。生成的方法签名遵循 IR 的规范(URL 模板)顺序,但代码片段写入器此前按作者声明的顺序依位置消费示例的路径参数。现在示例值会按名称绑定到各个参数,并按端点规范的路径参数顺序输出,与生成的签名一致。
2.71.1
(fix): 修复 SSE 流重连正确性以匹配参考实现:
(1) 未配置终止符时不重连(客户端无法区分已完成的流和断开的连接)。
(2) 当服务器未发送 retry: 指令时,重连尝试之间应用默认 1 秒退避(之前为零延迟)。
(3) 使用最后一个已分发的事件 ID 进行重连,而非最后一个已解析的 id,防止在事件中途断开时静默丢失事件。
(4) 将重连函数失败视为已消耗的尝试;当上限用尽时抛出 IOException 并将最后一次失败作为 InnerException,而非静默截断流。
(5) 让 OperationCanceledException 从 reconnectFn 立即传播,而非将其作为重试尝试吞没。
(6) 仅在成功获取新响应后才释放旧 HTTP 响应,防止重试时出现 ObjectDisposedException。
2.70.0
(feat): 添加对未记录/额外参数的支持:来自 RequestOptions 的 AdditionalQueryParameters
现在应用于所有端点(之前只有定义了查询参数的端点才会合并它们)。
还为 README 生成添加了 ADDITIONAL_BODY_PROPERTIES 功能。
2.69.0
(feat): 添加 NuGet Trusted Publishing(OIDC)支持作为配置门控的发布策略。
在 generators.yml 中设置 api-key: OIDC 以生成使用 NuGet/login 进行短期 OIDC 令牌
而非长期 API 密钥的 GitHub Actions 工作流。