ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Operit Codex 设置、订阅额度与 PDF 输入:从 WHAM 额度查询到 Responses input_file 的完整实现

Operit Codex 设置、订阅额度与 PDF 输入:从 WHAM 额度查询到 Responses input_file 的完整实现 AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载本指南以 Operit 仓库中 docs/TODO/codex_settings_quota_pdf_20260823/ 系列文档为主体系统讲解 Operit 为 CodexOPENAI_CODEXProvider 新增的紧凑型账号设置界面、基于 ChatGPTwham/usage接口的只读订阅额度查询以及将 PDF 附件转换为 Responsesinput_file的完整链路。读完本文你将掌握WHAM 响应中primary_window/secondary_window槽位与近 5 小时/近 7 天UI 周期的映射规则、额度快照持久化方案、Codex 图片/PDF 直传的实现边界以及本地 builder 服务触发远程 Release 构建的流程。背景与目标为什么 Codex 需要一个专属设置面现状盘点在本次改动之前Operit 已经具备 Codex 的三项基础能力Codex OAuth 登录通过CodexAuthManagerapp/src/main/java/com/ai/assistance/operit/data/api/CodexAuthManager.kt完成 PKCE 授权码交换、令牌刷新与吊销动态模型目录从https://models.opencode.ai/api.json读取openai.modelsCatalog 请求无需认证协议见 docs/TODO/openai_codex_oauth_20260822/1_protocol.mdResponses 传输CodexProvider继承OpenAIResponsesProvider直连https://chatgpt.com/backend-api/codex/responses端点。但设置页仍然暴露的是通用 Provider 表单登录态、固定端点、通用模型控件以及通用的图片/音频/视频与 ToolCall 开关没有任何 Codex 专属信息展示同时Codex 附件中的 PDF 文件不会被当作 Responses 输入文件而只是作为普通附件文本处理。本次改动的意图与边界本次工作的意图Intent可以概括为三件事在设置页加入一个紧凑的 Codex 专属设置区块展示账号信息与手动的订阅额度视图在不改动既有 XML 工具执行桥的前提下为 Codex 开启图片/PDF 直接输入与 ToolCall 能力配套完成解析器/请求的单测与协议文档更新并通过本地 builder 服务触发远程 Release 构建。值得注意的是改动有着清晰的**非目标Non-Goals**约束这决定了实现的最小侵入原则不修改 XML 解析器或 ToolCall 执行架构不请求 token 活动历史也不请求/wham/profiles/me不为 Codex 增加音频/视频控件不为 Codex 开放 API Key 或端点编辑入口。也就是说本次改动把Codex 专属体验限定在设置表面与附件转换两个层面底层推理与工具执行链路保持原样。Codex 设置与订阅额度从通用表单到紧凑专属区块改动前的状态ModelApiSettingsSectionapp/src/main/java/com/ai/assistance/operit/ui/features/settings/sections/ModelApiSettingsSection.kt此前已能识别OPENAI_CODEX并渲染登录、固定端点、通用模型控件以及通用的图片/音频/视频和 ToolCall 开关OAuth 状态由CodexAuthManager提供。改动的四个要点按 1_settings_and_usage.md 的定义新的 Codex 区块保留登录/登出与模型选择不破坏既有流程展示账号身份email 或 accountId、套餐名与一个紧凑的额度胶囊quota capsule5 小时额度在主窗口缺失时以显式暂无数据行展示不画进度条7 天额度取自次窗口展示剩余百分比、进度条与重置倒计时额度只在用户显式点击刷新时请求绝不自动拉取 token 历史不记录授权头与响应体日志凭据卫生每个 Codex 账号在专用 DataStore 中只存一份最新快照避免模型配置变更导致上次成功结果丢失。紧凑额度胶囊的 UI 结构从源码看CodexAuthSettingsBlock与CodexQuotaCapsule两个 Composable 共同实现了这一区块ModelApiSettingsSection.kt未登录时显示codex_auth_not_logged_in提示与 Sign in with ChatGPT 按钮登录后显示账号codex_auth_account、套餐codex_plan、刷新 IconButtoncodex_usage_refresh与登出按钮codex_logout_action额度胶囊由两行CodexQuotaWindowRow构成近 5 小时codex_quota_five_hour与近 7 天codex_quota_seven_day每行在窗口存在时显示剩余 X%codex_quota_remaining即remainingPercent与LinearProgressIndicator(progress remainingPercent / 100f)并渲染重置倒计时codex_reset_after_days/codex_reset_after_clock窗口缺失时显示暂无数据codex_quota_no_data且不绘制进度条刷新失败时显示额度暂时不可用codex_usage_unavailable错误文本。这些文案在中文与英文资源中成对维护例如中文app/src/main/res/values/strings.xml近 5 小时、近 7 天、剩余 %1$d%%、暂无数据、额度暂时不可用、%1$d 天后重置、%1$02d:%2$02d 后重置英文app/src/main/res/values-en/strings.xmlLast 5 hours、Last 7 days、%1$d%% remaining、No data、Usage is temporarily unavailable、Resets in %1$d days、Resets in %1$02d:%2$02d。重置倒计时的格式化逻辑在formatCodexResetCountdownModelApiSettingsSection.kt中实现先以 86400 秒折算天数超过 1 天显示X 天后重置否则以HH:mm形式显示X 小时 Y 分钟后重置套餐名通过formatCodexPlanType将plus、pro_max之类的下划线/连字符命名规范化为 Title Case 展示。WHAM 额度接口与窗口映射primary_window不等于近 5 小时接口契约官方 Codex CLI 读取的是GET https://chatgpt.com/backend-api/wham/usage。该接口返回plan_type与带有使用百分比、窗口时长、重置时间戳的限流窗口。协议文档中明确记录Usage payload:plan_typeplusrate_limit.primary_windowandrate_limit.secondary_window; each window exposesused_percent,limit_window_seconds, andreset_atdocs/TODO/openai_codex_oauth_20260822/1_protocol.md这里有一个关键的陷阱响应槽位response slots并不是 UI 周期UI periods。primary_window并不保证就是近 5 小时secondary_window也不保证就是近 7 天。周期必须以limit_window_seconds来判定。这一点在 4_usage_window_mapping_and_persistence.md 中被专门作为一个待修正的问题提出并解决。窗口分类规则CodexUsageClient.parseUsageapp/src/main/java/com/ai/assistance/operit/data/api/CodexUsageClient.kt实现了完整的分类逻辑从rate_limit中依次取出primary_window与secondary_window解析为CodexUsageWindow后过滤空值按windowDurationSeconds归类18000秒5 × 60 × 60→fiveHourWindow604800秒7 × 24 × 60 × 60→sevenDayWindow单个窗口的解析要求used_percent字段存在且不小于 0limit_window_seconds与reset_at大于 0 才有效used_percent被coerceAtMost(100)钳制并通过CodexUsageWindow.remainingPercent计算为(100 - usedPercent).coerceIn(0, 100)即UI 展示的剩余百分比由 API 的已用百分比取反得到。也就是说无论 ChatGPT 服务端把哪个周期放在primary_window槽位客户端都会按时长把它重新归位到正确的 5 小时/7 天行。缺失主窗口的显式处理由于五小时窗口可能缺席例如某些套餐只提供七天窗口UI 需要在没有数据时依然保留这一行并显示暂无数据而不绘制进度条。CodexQuotaWindowRow接收可空的window参数window null时右侧文本回退为codex_quota_no_data并跳过LinearProgressIndicator分支ModelApiSettingsSection.kt。单元测试对窗口映射的验证app/src/test/java/com/ai/assistance/operit/data/api/CodexUsageClientTest.kt 覆盖了三种关键场景完整双窗口解析primary_window604800s52% used与secondary_window18000s18% used分别被归类为七天与五小时remainingPercent分别为 48 与 82且reset_at时间戳正确保留主槽位即七天窗口当primary_window是 604800s 而五小时窗口整体缺席时fiveHourWindow为null、sevenDayWindow非空——这正是五小时行显示暂无数据的数据前提快照序列化往返CodexStoredUsageSnapshot含 accountId、usage、fetchedAtMillis经 kotlinx.serialization 编码解码后与原对象相等且不含任何 token 数据验证了持久化格式的凭据卫生。额度快照的持久化为什么不能只存在 Compose 状态里问题背景在修正之前设置 UI 把额度结果只保存在以模型配置为键的 Compose 状态中用户一旦切换模型配置最后一次成功查询的额度就被丢弃若之后的刷新请求失败界面就完全失去上一份可用数据。解决方案按账号持久化的专用 DataStoreCodexUsagePreferencesapp/src/main/java/com/ai/assistance/operit/data/preferences/CodexUsagePreferences.kt使用独立的preferencesDataStore(name codex_usage_preferences)存储单条快照键为latest_snapshot值为CodexStoredUsageSnapshotaccountIdCodexUsageSnapshotfetchedAtMillis的 JSON 序列化结果解码使用ignoreUnknownKeys true, isLenient true的宽松 Json 配置解码失败时返回null并记录日志不会让整个 Flow 崩溃写入时机在CodexAuthManager.fetchUsage中成功获取额度后立即按accountId落盘CodexAuthManager.ktUI 侧通过codexAuthManager.usageSnapshotFlow.collectAsState()订阅ModelApiSettingsSection.kt。这样切换模型配置不丢额度与后续手动刷新失败时仍展示上次快照两个目标都得以实现。注意快照中只含额度数据与账号 ID绝不包含 OAuth 令牌与协议文档凭据永不进入ModelConfigData、导出备份、请求日志或自定义请求头的原则一致。Codex 的图片与 PDF 直接输入复用开关、Pool 存储与 input_file 转换输入链路现状图片附件直接存储在ImagePoolManager中并以内部媒体链接internal media link表示。OpenAIProvider.buildContentField[app/src/main/java/com/ai/assistance/operit/api/chat/llmprovider/OpenAIProvider.kt#L893-L994]把这些链接转换为 content partsOpenAIResponsesProvider再将其映射为 Responses input parts。而 PDF 附件此前只是普通附件文本不会被识别为文件输入。改动设计最小配置面 仅 Codex 的文件链接转换按 2_pdf_input_file.md 的实现复用现有 Codex 图片直传开关作为合并的图片/PDF 能力开关——不新增持久化配置字段PDF 字节存入现有媒体池表示为内部文件链接file link文件链接的转换只对 Codex 启用音频、视频、通用 OpenAI 与 XML ToolCall 行为一律不变。从AIServiceFactory的装配代码可以看到 Codex 的能力开关组合[app/src/main/java/com/ai/assistance/operit/api/chat/llmprovider/AIServiceFactory.kt#L386-L400]ApiProviderType.OPENAI_CODEX - CodexProvider( authManager CodexAuthManager.getInstance(context), modelName config.modelName, httpClient httpClient, customHeaders customHeaders, supportsVision supportsVision, supportsAudio false, supportsVideo false, supportsFiles supportsVision, // 文件能力跟随视觉开关即图片/PDF 直传共用 enableToolCall enableToolCall, enableWebSearch config.enableCodexWebSearch, thinkingConfigurations config.thinkingConfigurations, thinkingOptionId config.thinkingOptionId, )supportsFiles supportsVision正是图片直传开关同时启用 PDF 输入这一设计的落地视觉能力开启时文件PDF输入也随之可用且不新增任何配置项。Content 构建与 Responses 输入转换在buildContentField中媒体链接被按类型过滤mediaLinks.filter { it.type file }得到文件链接只有当supportsFiles fileLinks.isNotEmpty()时才进入富内容分支OpenAIProvider.kt。文件链接随后被构造成 Responsesinput_filepartOpenAIProvider.ktif (allowUserRichContent supportsFiles) { fileLinks.forEach { link - val fileName requireNotNull(link.fileName?.takeIf { it.isNotBlank() }) contentArray.put(JSONObject().apply { put(type, input_file) put(filename, fileName) put(file_data, data:${link.mimeType};base64,${link.base64Data}) }) } }file_data使用data:mime;base64,payload形式的 data URI携带 MIME 类型与 Base64 编码的文件字节。协议文档对此的约定是Codex PDF attachments use Responsesinput_filewithfilenameandfile_datadata URI fields.docs/TODO/openai_codex_oauth_20260822/1_protocol.md在 Responses 侧OpenAIResponsesProvider的内容转换同样识别input_file类型并回填filename与file_data[app/src/main/java/com/ai/assistance/operit/api/chat/llmprovider/OpenAIResponsesProvider.kt#L553-L565]保证多轮历史与工具输出回放时文件 part 不丢失。而 Deepseek 等使用相同 Responses 结构的 Provider 也遵循同一input_file契约[app/src/main/java/com/ai/assistance/operit/api/chat/llmprovider/DeepseekProvider.kt#L997-L1005]说明该格式是项目内 Responses 传输的统一约定。明确的边界图片直传走image_urlpart、PDF 走input_filepart两者由同一个 Codex 开关控制音频input_audio、视频video_url对 Codex 保持关闭supportsAudio false, supportsVideo falseXML ToolCall 执行桥没有任何改动——Codex 的工具调用仍走既有的 Responses/XML 桥接路径。验证与发布单测覆盖、协议文档与远程 Release 构建验证清单按 3_verification_and_release.md 的检查项审查完整 diff确认所有分支均为Codex-only且凭据已做脱敏不打印授权头、不记录响应体为四类行为补充单元覆盖usage payload 窗口映射、主窗口数据缺失、PDF content 映射、Responses 输入转换窗口相关测试见 CodexUsageClientTest.kt更新 Codex 协议文档加入 usage 路由与 PDF 契约已体现在 docs/TODO/openai_codex_oauth_20260822/1_protocol.md记录最终 commit 与远程 builder 任务结果。远程 Release 构建流程文档记录的发布流程为参考build.md在 worktree 包含目标改动后触发POST /api/build_current_release随后轮询/api/status、/api/jobs、/api/log直至任务结束再记录产物与校验和。本次任务留下的两条发布记录来自fix/provider-logos-token-statistics-main分支项目首次 Release最新 Fix ReleaseCommit85d35444d720b7bb84Actionbuild_releasebuild_releaseStatussuccesssuccess产物operit-release-fix_provider-logos-token-statistics-main-85d35444.apkoperit-release-fix_provider-logos-token-statistics-main-720b7bb8.apk大小403019347字节403027539字节SHA-256445026543617cbc62c244c8bb4f0b875a6ee0c6e594b1fa67acfbaaab0371083d0400cc1d40446d0ebc63f4b642daa662ab8eb5d0178f638f1efbaddba745e8f其中720b7bb84对应修正窗口分类并持久化最新额度快照这一收尾步骤index.md 步骤 6印证了窗口映射与持久化问题是在发布后经回归修复才最终完成的。总结本次 Codex 专项改动在不触碰底层推理与工具执行架构的前提下把 Codex 的账号与额度体验和多模态输入体验补齐到产品级设置面ModelApiSettingsSection以CodexAuthSettingsBlockCodexQuotaCapsule呈现紧凑账号区块展示账号、套餐与 5 小时/7 天额度行额度CodexUsageClient只读拉取wham/usage按limit_window_seconds18000/604800分类窗口缺失的 5 小时行显式显示暂无数据额度只在用户手动刷新时请求持久化codex_usage_preferencesDataStore 按账号保存最新快照模型配置变更与后续刷新失败都不丢失可见数据输入复用图片直传开关supportsFiles supportsVisionPDF 字节存入媒体池并转为内部文件链接最终构造成 Responsesinput_filefilenamefile_datadata URI音频/视频与 XML ToolCall 行为保持原样交付通过单测窗口映射、缺失数据、快照往返、PDF 转换与协议文档更新护航并经由本地 builder 服务完成远程 Release 构建与校验和记录。对希望在 Operit 中接入或复刻这一模式的开发者来说最值得借鉴的三点经验是响应槽位绝不等于业务周期、凭据永远不进持久化与日志、能力开关应尽量复用既有配置字段以保持设置面精简。赞分享AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载相关推荐Operit 中 Codex 设置与额度用量展示从 wham/usage 解析到 DataStore 快照的完整实现指南Operit 中 Codex 设置与额度用量展示从 wham/usage 解析到 DataStore 快照的完整实现指南 导读 本文围绕 Operit 在模型AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Operit Codex PDF 附件输入复用媒体池将 PDF 转为 Responses input_file 的实现解析Operit Codex PDF 附件输入复用媒体池将 PDF 转为 Responses input_file 的实现解析 导读 本文围绕 Operit 中AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化Operit Codex 设置、配额与 PDF 输入验证清单与远程发布流程实战Operit Codex 设置、配额与 PDF 输入验证清单与远程发布流程实战 导读 本文围绕 Operit 仓库中 Codex 专项功能Codex 专属设AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表