Atelia.Completion 0.1.0-preview.3

This is a prerelease version of Atelia.Completion.
dotnet add package Atelia.Completion --version 0.1.0-preview.3
                    
NuGet\Install-Package Atelia.Completion -Version 0.1.0-preview.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Atelia.Completion" Version="0.1.0-preview.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Atelia.Completion" Version="0.1.0-preview.3" />
                    
Directory.Packages.props
<PackageReference Include="Atelia.Completion" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Atelia.Completion --version 0.1.0-preview.3
                    
#r "nuget: Atelia.Completion, 0.1.0-preview.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Atelia.Completion@0.1.0-preview.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Atelia.Completion&version=0.1.0-preview.3&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Atelia.Completion&version=0.1.0-preview.3&prerelease
                    
Install as a Cake Tool

Completion transport-liveness contract

Atelia.Completion 面向 net10.0,依赖 Abstractions 与 Diagnostics。本包使用 MIT 许可证。

dotnet add package Atelia.Completion --version 0.1.0-preview.3

完整离线 public client 示例与 HttpClient 所有权见 对应版本快速上手。Release 包中 Debug 级别调用已被 [Conditional("DEBUG")] 编译裁掉,无法由环境变量恢复;需要库内详细调试时使用源码 Debug 联调。

Completion只判断能够从HTTP/SSE链路和provider协议中直接观察到的事实,不猜测LLM是否仍在工作。 一次streaming调用没有elapsed-operation timeout,也没有stream-idle timeout;不可见reasoning、排队或长时间 没有SSE frame都不是失败证据。HttpClient.Timeout统一为Timeout.InfiniteTimeSpan,调用方只能通过自己传入的 CancellationToken取消。

自 0.1.0-preview.2 起的源码变更:CompletionFailureInfo(Kind, HttpStatusCode, ProviderCode, RetryAfter) 是调用异常与 provider Failed 结果共用的事实合同,不包含重试策略。HTTP 的 Retry-After 同时接受 delta 与 date;正文读取失败不会抹掉已观察到的状态码,response 仍会释放。 CompletionStreamInterruptedException 现在继承 CompletionFailureException,不再继承 IOException; Codex 的 HTTP/transport 失败也使用共享异常,旧 Codex-specific 异常只表达 protocol compatibility。 HTTP 异常诊断正文限制为归一化单行的前 512 字符;结构化 code 从完整错误响应解析,不因诊断截断丢失。 该摘录仍可能包含 provider 数据,不应用作 UI 安全文本或持久业务原因;宿主应只发布归一化错误码。

未请求 stream usage 的 Chat 方言与 Gemini 在 finish terminal 后不等待 trailing usage; 若终止 frame 未带 usage,相应计量字段就是 unknown,完整业务结果不能因可选计量迟到而丢失。 显式请求 stream_options.include_usage 的 Chat 方言会继续读取 terminal 后的 empty-choices usage snapshot 与 [DONE];该快照是已请求的协议尾部事实,而不是可选等待。 Anthropic/Gemini 的共享 capability preflight 在最后 waiter 取消时会取消并等待 fetch 清理; 清理未完成前不启动替代 fetch。其他仍在等待同一 fetch 的调用不受单个 waiter 取消影响。

共享边界

  • 成功HTTP响应必须声明text/event-stream;HTTP、建连、打开和读取流的错误以 CompletionFailureException.Failure 报告结构化事实(Transport/Http、状态码、provider code、Retry-After)。parser/observer/投影异常不归类为网络错误。
  • 所有Provider共享CompletionSseEventReader:按SSE空行提交frame,支持CR/LF/CRLF、多行data:、注释、 UTF-8 BOM与replacement decoding;EOF时未提交的半个frame不会交给parser。
  • 只有下表中的provider terminal evidence才能确定远端结果。显式terminal到达后立即返回,不等待连接EOF。
  • 已收到合法frame但在terminal evidence前EOF,抛出CompletionStreamInterruptedException。这表示远端结果不确定, 库不透明重试,也不把它伪装为LLM拒答;宿主按调用业务语义决定是否重算,可能重复计费。唯一的窄兼容例外是Anthropic:所有content block均已关闭、 已收到非空message_delta.stop_reason、随后无pending frame的clean EOF但缺少data-free message_stop时,按该stop reason结束。
  • caller cancellation保持原CancellationToken;observer cleanup失败不得覆盖原始read/cancellation异常。
  • 未被当前版本识别、但外层event envelope合法的字段或事件保持forward-compatible;已知事件缺少必需shape、 生命周期乱序或event/data类型冲突则fail closed。
  • 如果TCP/HTTP连接进入silent half-open且系统没有报告断开,调用会无限等待。这是刻意选择:没有独立可靠的 transport证据时,不用定时器推断LLM失败。

Provider terminal matrix

Provider surface 权威成功/不完整terminal 权威provider失败 非terminal或特殊规则
OpenAI Chat Completions 单一choice的非空finish_reason;stop/tool_calls为Completed,其他值为Incomplete 顶层error [DONE]只是传输哨兵;若它先于finish_reason到达,结果仍不确定。当前明确拒绝n > 1与多choice stream
OpenAI Responses response.completed、response.incomplete;若已观察到typed refusal,两者均收口为Incomplete(response.refusal) response.failed、error response.refusal.delta/done与message refusal content不是terminal;event:与JSON type必须一致;[DONE]不能替代Responses terminal event
Anthropic Messages 首选message_stop,并要求message_start -> content blocks -> message_delta(stop_reason);兼容缺尾帧relay时,blocks全关且已有非空stop_reason后的无pending-frame clean EOF也是降级terminal evidence error ping与合法unknown named event只表示收到frame,不代表成功或失败;Anthropic没有[DONE];read failure/cancellation/protocol error绝不走clean-EOF兼容
Gemini streamGenerateContent candidate.finishReason;STOP为Completed,其他值为Incomplete;无candidate时promptFeedback.blockReason为Incomplete 顶层error envelope Gemini没有文档化的[DONE]、named terminal或heartbeat;responseId只用于关联,不是resume cursor

OpenAI Responses refusal 只按typed wire evidence识别,不从普通正文猜测。response.refusal.delta/done、 response.output_item.done 的 message refusal content,以及terminal response.output fallback 使用 (item_id, content_index)协调;streamed prefix只补final suffix,重复final不重复输出,冲突或final后delta抛protocol exception且不在异常中带refusal正文。同一时刻只允许一个未finalized key;message/output已知容器若缺失array shape、 entry不是object或缺少string type也fail closed,而合法unknown string type仍forward-compatible。正文可以作为 transient ActionMessage.Text / observer delta返回,但不会进入 Errors、termination reason/detail,也不会被SessionJournal持久化为成功AgentActionProduced。只有最终权威response terminal到达后才产生non-success result;terminal前EOF、transport failure或cancellation仍是outcome uncertain, response.failed / error仍覆盖为Failed。没有typed refusal witness时,既有response.incomplete的 content_filter等reason保持原语义;refusal始终使用独立response.refusal,不复用content_filter名称。

规格依据

ChatGPT Codex subscription client(Linux / Windows)

OpenAICodexResponsesClient 可以直接作为 ICompletionClient 使用,不需要启动 local proxy。它只借用 Codex CLI file-backed auth.json 的当前 access-token snapshot;Codex CLI 仍是唯一 login/refresh/write-back owner。

using Atelia.Completion.Abstractions;
using Atelia.Completion.OpenAI;

var credentials = new CodexCliAuthFileCredentialProvider();
CodexSubscriptionCredential firstSnapshot =
    await credentials.GetCredentialAsync(ct);

using var client = new OpenAICodexResponsesClient(
    credentials,
    new OpenAICodexResponsesClientOptions {
        ExpectedAccountFingerprint = firstSnapshot.AccountFingerprint,
        Originator = "atelia", // 构造期可配;默认值也是 atelia
        MaxConcurrentRequests = 3
    }
);

CompletionResult result = await client.StreamCompletionAsync(
    request,
    observer: null,
    ct
);

if (result.Termination.Kind == CompletionTerminationKind.Completed) {
    string text = result.Message.GetFlattenedText();
    // 将成功完成的正文交给业务层。
}
// Incomplete / Failed 应由调用方单独处理,不能把部分正文当作成功结果。

运行边界:

  • 支持 Linux / Windows file-backed credential。默认读取 CODEX_HOME 下的 auth.json;未设置时使用 Environment.SpecialFolder.UserProfile 下的 .codex/auth.json。例如 Windows 用户 gdtut 的默认路径是 C:\Users\gdtut\.codex\auth.json,不需要 WSL 或启动 Codex app-server;
  • CODEX_HOME 与显式 auth-file override 都必须是绝对路径,并指向 Codex 的普通凭据文件。 两个平台使用同一 .NET File.OpenHandle 只读实现,正常跟随 symlink/junction,由 OS 解析路径和判断读取权限;
  • provider 不检查或修改 owner/mode/ACL,不承担 no-follow 路径隔离职责。句柄允许 read/write/delete sharing, 同一句柄进行有界双读和长度检查,兼容 Codex 原地重写和原子替换;
  • provider 每个 logical attempt 重读 snapshot,但从不 materialize refresh/id token,不 refresh、不写文件;
  • access token 过期或 backend 401 且文件 generation 未变化时,先运行 Codex 让它 refresh,必要时重新 codex login;
  • endpoint 固定为 https://chatgpt.com/backend-api/codex/responses,它不是公开稳定 API;
  • originator 必须诚实稳定,允许构造时覆盖,不要伪装 codex_cli_rs、Pi 或 OpenCode;
  • public OpenAI Responses 与 Codex Responses 使用不同 ApiSpecId,两边的 provider-native reasoning payload 不能交叉 replay。

文件存储模式见 OpenAI 官方 credential storage 文档。 仅存于 OS keyring 的凭据不在此 provider 的支持范围;没有 auth.json 时返回 AuthStorageUnavailable。 可选的 JsonLinesCompletionHttpExchangeFileSink 仍只支持 Linux;Windows 默认调用不依赖 raw exchange 文件日志。

接入 Player 等调用方时,期限由传入的 CancellationToken 控制;CompletionStreamInterruptedException 表示 结果不确定,库不自动重试,宿主可以按纯生成等业务语义重新调用。HTTP 401/403/429 同样通过共享失败事实报告;401 后 credential generation 确实变化时仍只允许一次立即认证协商,不对 429/5xx/断流增加内部重试。CompletionUsage 中的 null 表示该维度未知,0 才是明确报告的零;不要为了适配 profiler 而补零或推算缺失维度。以上语义在 Linux / Windows 相同。

Galatea 接入、connection shape、安全 preflight、环境变量和 live smoke 见 docs/Completion/openai-codex-subscription-client-design.md。

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0-preview.3 48 9/23/2026
0.1.0-preview.2 47 9/20/2026
0.1.0-preview.1 63 9/14/2026