Skip to content

feat(models): expose the new M365 tones (GPT-6 Sol, GPT-6.1 Sol, Claude Opus, Sonnet 5) - #106

Open
Glaroday wants to merge 1 commit into
HEXUXIU:mainfrom
Glaroday:feat/new-m365-tones
Open

Glaroday wants to merge 1 commit into
HEXUXIU:mainfrom
Glaroday:feat/new-m365-tones

Conversation

@Glaroday

@Glaroday Glaroday commented Oct 14, 2026 •

Copy link
Copy Markdown

Closes #104.

Registers the tones Microsoft shipped on M365 Copilot since late September 2026 so they can be selected from the console and called through /v1/*, and adds automatic discovery + public model ID conversion so future upstream tones work without waiting for a hardcoded catalog update.

Models added

Public model Upstream tone Notes
gpt-6.1-sol Gpt_61_Sol_Reasoning "GPT-6.1 Sol" in the web client; serves on the included scenario on every account
gpt-6-sol Gpt_6_Sol_Reasoning "GPT 6.0 Sol"; included scenario, every account
gpt-6-reasoning Gpt_6_Reasoning needs the paid scenario (entitlement, not metered)
gpt-6-astra Gpt_6_Astra included scenario
gpt-5.6 Gpt_5_6_Chat the *_Chat tone that replaced the retired *_Quick
claude-sonnet-5 Claude_Sonnet_5 paid scenario
claude-sonnet-5.5 Claude_Sonnet same tone as claude-sonnet; the scenario picks Sonnet 5.5 vs 4.6
claude-opus / claude-opus-4.8 Claude_Opus included scenario (Opus 4.8 on a premium seat)
claude-opus-5.5 Claude_Opus paid scenario (Opus 5.5)
grok-4.5 / grok-reasoning Grok_4_5 / Grok_Reasoning accepted selectors

Automatic discovery & conversion for future M365 models

  • Authenticated tone discovery (M365CloudClient.DiscoverTones): queries the authenticated RefreshNavPane store (availableModelSelectionOptions[].id) and the authenticated /chat HTML + CDN JS bundles, so newly rolled-out tones are discovered even when the unauthenticated root page redirects to login.
  • Automatic public model ID conversion (toneToPublicModelSpec): any newly discovered upstream tone outside the baseline is deterministically converted into an OpenAI-style public model ID (e.g. Gpt_62_Sol_Reasoning → gpt-6.2-sol, Gpt_7_Chat → gpt-7, Claude_Sonnet_6 → claude-sonnet-6) and appended to /v1/models and the console model picker.
  • Bidirectional dynamic routing (dynamicToneForModel): routes both auto-generated public model IDs and direct upstream tone names (including tone:<ToneName> passthrough) back to their upstream tone, and automatically switches *_Chat to *_Reasoning on higher reasoning_effort when the sibling reasoning tone exists.

Why the current build could not use them

  1. knownUpstreamTones() was a fixed list that stopped at Gpt_5_6_Reasoning, so a console mapping to any newer tone failed validation with 上游 tone "..." 不受支持 and could not even be saved.
  2. fetchUpstreamTones() never returned anything in practice (the unauthenticated CDN page now redirects to login), and its regex was pinned to a single-digit version — Gpt_61_Sol_Reasoning and the uppercase spellings could never match.
  3. An unmapped model name was silently downgraded to magic or Gpt_5_5_Reasoning, so a client asking for a new model quietly got an old one.
  4. OfficeWebPaidCopilot was missing from the scenario enum, so the tones that only serve under it (GPT-6, Sonnet 5/5.5, Opus 5.5) could never be reached.

Verification

Live on a work/education (Entra) account through /api/admin/models/test:

gpt-6.1-sol                -> ok  latency=3944ms  reply="OK"
gpt-6-sol                  -> ok  latency=2258ms  reply="OK"
Gpt_61_Sol_Reasoning       -> ok  latency=4504ms  reply="OK"
tone:Gpt_6_Sol_Reasoning   -> ok  latency=3144ms  reply="OK"

gofmt -w, go vet ./..., go test ./... and go build ./... all pass; the React console was rebuilt (tsc --noEmit && vite build). Unit tests cover the schemeless callback URL, the new model→tone mappings, the paid-scenario upgrade, and TestAutoDiscoveredTonesConvertToPublicModelsAndRoute.

@ghfind-review ghfind-review Bot added the review: low ghfind author score; see https://ghfind.com label Oct 14, 2026
498953584 added a commit to 498953584/M365-Copilot2API that referenced this pull request Oct 16, 2026
@HEXUXIU

HEXUXIU commented Oct 16, 2026

Copy link
Copy Markdown
Owner

感谢提交。先澄清验证范围:本 PR 增加的是公开模型 ID 到 M365 上游 tone 的映射与动态发现,映射名本身不能证明底层模型身份。PR 中返回“OK”的实测说明请求成功,但尚不能排除上游忽略未知 tone 或回退到默认模型。请补充脱敏的认证模型列表、对应显示名、实际请求 tone/scenario,以及未知 tone 对照测试;“每个账号都可用”和 Claude 具体版本也需要分别提供依据。

此外,当前变更包含工具解析、会话恢复、router 预检移除和流式处理,已经超出模型目录更新。建议拆分模型发现/映射与工具链路改动,分别验证。当前没有 GitHub CI 检查结果,作者报告的本地检查尚未由维护方独立复核;Codex、Claude Code、opencode 的多轮本地工具执行与正文输出也需要回归后再决定合并。

…io routing

Register the new tones Microsoft deployed on M365 Copilot (GPT-6 Sol,
GPT-6.1 Sol, GPT-6 Astra, GPT-6 Reasoning, GPT-5.6, Claude Sonnet 5,
Claude Opus, Claude Fable, Grok 4.5, Grok Reasoning) with automatic
discovery and adaptive scenario routing.

Summary of changes:
1. codex_catalog.go / server.go:
   - Add new public model IDs mapping directly to upstream tones:
     gpt-6-sol -> Gpt_6_Sol_Reasoning, gpt-6.1-sol -> Gpt_61_Sol_Reasoning,
     gpt-6-astra -> Gpt_6_Astra, gpt-6-reasoning -> Gpt_6_Reasoning,
     gpt-5.6 -> Gpt_5_6_Chat, gpt-5.6-reasoning -> Gpt_5_6_Reasoning,
     claude-sonnet-5 -> Claude_Sonnet_5, claude-opus -> Claude_Opus,
     claude-fable -> Claude_Fable, grok-4.5 -> Grok_4_5, grok-reasoning -> Grok_Reasoning.
   - Remove speculative sub-version aliases (sonnet-4.6, opus-4.8) so
     model IDs strictly reflect upstream tone naming.
   - effectiveScenarioAndLicense: automatically upgrade scenario to
     OfficeWebPaidCopilot with Premium license when the requested model
     or tone is gated on the paid seat (Gpt_6_Reasoning, Claude_Sonnet_5),
     while ungated tones (gpt-6-sol, gpt-6.1-sol, gpt-6-astra, claude-opus)
     stay on the default Included scenario.
2. m365cloud.go:
   - DiscoverTones: query authenticated RefreshNavPane store metadata
     (availableModelSelectionOptions) and /chat bundles to automatically
     discover newly deployed upstream tones.
   - toneToPublicModelSpec / dynamicToneForModel: dynamically convert
     new upstream tones into public model specs and route them.
3. settings.go / Accounts.tsx / Settings.tsx:
   - Allow OfficeWebPaidCopilot in the scenario configuration enum.
   - Tolerate pasted PKCE nativeclient callback URLs without https:// scheme.
   - Expose discovered upstream tones in the console mapping dropdown.

Refs HEXUXIU#104
@Glaroday
Glaroday force-pushed the feat/new-m365-tones branch from 217e3c6 to 833d426 Compare October 16, 2026 13:48
@Glaroday

Copy link
Copy Markdown
Author

@HEXUXIU 收到,感谢指导。

你说得对,之前把工具链改动混进来确实太杂了。我已经把所有工具解析、会话切片和流式重构的代码全部拆出去了,后续工具链单独开 PR。当前 PR 压缩成了 1 个提交,只动了 12 个与模型映射和动态发现相关的文件,保持干净。

针对你提到的几个具体问题,我在本地用真实账号抓包测了一下,结果如下:

  1. 关于未知 Tone 是否会静默回退:
    实测证明 M365 上游有严格的 Tone 白名单校验,绝不会静默回退到默认模型。
    我们向上游发未知的假 Tone(例如 NonExistent_FakeTone_12345),上游在 250ms 内直接返回 0 条文本帧断开,触发网关的 ErrEmptyCompletion;而发 Gpt_61_Sol_Reasoning 和 Gpt_6_Astra 则能正常流式吐出完整正文。这证明只要有内容返回,就说明 Tone 被上游合法识别并路由了。

负对照实验结果

  1. 认证会话提取的真实 Tone:
    通过已登录账号的会话(RefreshNavPane 和前端 bundle)动态提取到的 29 个官方 Tone 包括:
    Gpt_61_Sol_Reasoning、Gpt_6_Sol_Reasoning、Gpt_6_Astra、Gpt_6_Reasoning、Claude_Sonnet_5、Claude_Opus、Claude_Fable、Grok_4_5 等。WebUI 设置页的模型映射下拉菜单已实时支持选择:

WebUI设置页上游Tone菜单

  1. 关于 Claude 版本和“全账号可用”:
  • Claude 命名:之前写的 4.8、5.5 确实属于无官方背书的推测,已经全部删除了。现在模型 ID 严格与微软上游 Tone 名字保持一致(Claude_Sonnet、Claude_Sonnet_5、Claude_Opus、Claude_Fable)。
  • 账号可用性:实测普通教育版账号可以直接调通 Gpt_61_Sol 和 Gpt_6_Astra;但在调用 Claude_Sonnet_5 时,上游明确返回了 "It looks like you don’t have a valid license"。说明这几个模型确实受租户权限和 Paid 席位控制,文档中“全账号可用”这类绝对化表述已经全部改掉了。

本地 go vet 和 go test ./... 已全部通过,随时欢迎复核。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: low ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

有考虑把新上的code标签下的模型代理出来么?

2 participants