Files
OmniRoute/tests/unit/m365-tone-model-variants.test.ts
N123 Project 6cd4d38e21 fix(m365): BizChat invocation shape drift + HAR-import UX + Antigravity alias note (#11069)
5 — M365 Copilot (BizChat) individual/consumer path — 3 itens: (1) forma de invocação do #10718 derivou de novo (2026-08-21 capture): optionsSets 14→34, allowedMessageTypes 6→30, tone "magic"→"Magic", plugins []→[{BingWebSearch}], disconnectBehavior em todos os tiers, +8 keys de clientInfo; verificado contra conta real com round-trip WebSocket (ping-then-close → resposta real). (2) Aviso sobre o alias Antigravity gemini-3.1-pro-high ainda não publicado (3.8.49 pré-data). (3) Botão "Import .har file" no modal de credencial M365.

Conflito resolvido em copilot-m365-frames.ts (board vs release tip): mantive o forwarding de opts.plugins/toolChoice/customInstructions do HEAD com os NOVOS defaults da captura (BingWebSearch builtin, tone "Magic"). Alinhei 3 testes pré-existentes que afirmavam o contrato antigo (m365-bizchat-frames-4042 clientInfo, m365-tone-model-variants tone, copilot-m365-tool-calls plugins) — propagação de contrato, não mascaramento. Rebaselinei AddApiKeyModal 1073→1080 (crescimento próprio da parte 3, ~Har import button) com anotação.

Validação: typecheck limpo, 142/142 testes m365/copilot verdes, changelog-integrit/file-size/eslint OK.
2026-08-21 22:32:19 -03:00

61 lines
2.9 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import {
M365_MODEL_TONE_MAP,
resolveToneForModel,
resolveChatInvocationOverrides,
} from "../../open-sse/executors/copilot-m365-frames.ts";
import { copilot_m365_webProvider } from "../../open-sse/config/providers/registry/copilot-m365-web/index.ts";
// #7872 — tone-selected model variants for copilot-m365-web.
// The wiring (model id → tone → invocation payload) is unit-tested here; whether a tone
// actually selects that model upstream is a live enterprise-tenant check (release-drain).
test("resolveToneForModel maps each variant id to its confirmed tone", () => {
assert.equal(resolveToneForModel("copilot-m365-claude-opus"), "Claude_Opus");
assert.equal(resolveToneForModel("copilot-m365-gpt-5-6-reasoning"), "Gpt_5_6_Reasoning");
assert.equal(resolveToneForModel("copilot-m365-gpt-5-5-chat"), "Gpt_5_5_Chat");
});
test("resolveToneForModel returns undefined for the bare id and unknown ids", () => {
// bare id must fall back to the tier default, not a hard-coded tone
assert.equal(resolveToneForModel("copilot-m365"), undefined);
assert.equal(resolveToneForModel("totally-unknown"), undefined);
assert.equal(resolveToneForModel(undefined), undefined);
assert.equal(resolveToneForModel(""), undefined);
});
test("model-driven tone overrides the tier default; bare id keeps the tier tone", () => {
const enterprise = resolveChatInvocationOverrides("enterprise");
const individual = resolveChatInvocationOverrides(undefined);
// enterprise tier default tone is Magic; individual/EDU now also sends
// "Magic" (capitalized) — the 2026-08-21 capture (#11069) showed lowercase
// "magic" is part of the shape that gets silently dropped (ping-only socket).
assert.equal(enterprise.tone, "Magic");
assert.equal(individual.tone, "Magic");
// precedence: resolveToneForModel(model) ?? overrides.tone (mirrors the executor wiring)
const toneFor = (model: string | undefined, tierTone: string) =>
resolveToneForModel(model) ?? tierTone;
// a variant id wins over BOTH tier defaults
assert.equal(toneFor("copilot-m365-claude-opus", enterprise.tone), "Claude_Opus");
assert.equal(toneFor("copilot-m365-claude-opus", individual.tone), "Claude_Opus");
// the bare id keeps whatever the tier resolved (both "Magic" post-#11069)
assert.equal(toneFor("copilot-m365", enterprise.tone), "Magic");
assert.equal(toneFor("copilot-m365", individual.tone), "Magic");
});
test("registry exposes the bare id (first) plus every tone variant", () => {
const ids = copilot_m365_webProvider.models.map((m) => m.id);
assert.equal(ids[0], "copilot-m365", "bare Auto/default id must be first");
for (const variantId of Object.keys(M365_MODEL_TONE_MAP)) {
assert.ok(ids.includes(variantId), `registry missing variant ${variantId}`);
}
// no duplicate ids
assert.equal(ids.length, new Set(ids).size);
});