opencode-cache-engine 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cache-engine-core.mjs +42 -5
- package/src/cache-engine.ts +57 -4
- package/test/cache-engine.test.mjs +180 -3
package/package.json
CHANGED
|
@@ -500,14 +500,51 @@ export function isOpenRouterAffinityEligible(policyFamily, providerID) {
|
|
|
500
500
|
)
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
+
// Produce safe telemetry fields for one affinity-capable request. Provider
|
|
504
|
+
// identity is observable and recorded; header values are deliberately not.
|
|
505
|
+
// A supplied non-OpenRouter identity is classified from the observed value
|
|
506
|
+
// rather than guessed against a provider allowlist.
|
|
507
|
+
export function affinityTelemetryFields(policyFamily, providerID, headerSource) {
|
|
508
|
+
if (policyFamily !== POLICY_MIMO26 && policyFamily !== POLICY_GLM53) return null
|
|
509
|
+
|
|
510
|
+
const identity = typeof providerID === "string" && providerID.length > 0 ? providerID : null
|
|
511
|
+
const eligible = isOpenRouterAffinityEligible(policyFamily, identity)
|
|
512
|
+
if (!eligible) {
|
|
513
|
+
return {
|
|
514
|
+
reason: identity
|
|
515
|
+
? "openrouter_affinity_bypassed_non_openrouter"
|
|
516
|
+
: "openrouter_affinity_bypassed_provider_missing_or_unknown",
|
|
517
|
+
eligible: false,
|
|
518
|
+
providerIdentityKnown: identity !== null,
|
|
519
|
+
provider: identity,
|
|
520
|
+
headerPresent: false,
|
|
521
|
+
headerAttached: false,
|
|
522
|
+
headerSource: "not_applicable",
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const source = ["cache_engine", "preexisting", "unavailable"].includes(headerSource)
|
|
527
|
+
? headerSource
|
|
528
|
+
: "unavailable"
|
|
529
|
+
const headerPresent = source === "cache_engine" || source === "preexisting"
|
|
530
|
+
return {
|
|
531
|
+
reason: "openrouter_affinity_eligible",
|
|
532
|
+
eligible: true,
|
|
533
|
+
providerIdentityKnown: true,
|
|
534
|
+
provider: identity,
|
|
535
|
+
headerPresent,
|
|
536
|
+
headerAttached: source === "cache_engine",
|
|
537
|
+
headerSource: source,
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
503
541
|
// Derive a stable, session-scoped identifier suitable for OpenRouter's
|
|
504
542
|
// documented `session_id` sticky-routing key. Pure function of the OpenCode
|
|
505
543
|
// session id only: identical sessions map to identical ids, distinct sessions
|
|
506
|
-
// map to distinct ids, and transient request contents cannot influence it.
|
|
507
|
-
//
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
// so this id is currently recorded as telemetry only and is never injected.
|
|
544
|
+
// map to distinct ids, and transient request contents cannot influence it. The
|
|
545
|
+
// value is printable, contains no whitespace, and is far below the 256-char cap
|
|
546
|
+
// (25 chars). The plugin uses it as the existing OpenRouter x-session-id header
|
|
547
|
+
// value for eligible MiMo/GLM requests.
|
|
511
548
|
export function mimoSessionIdFor(sessionID) {
|
|
512
549
|
if (typeof sessionID !== "string" || sessionID.length === 0) return null
|
|
513
550
|
return `mimo-ses-${shorthash(sessionID)}`
|
package/src/cache-engine.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Event, Message, Part } from "@opencode-ai/sdk"
|
|
|
3
3
|
import {
|
|
4
4
|
DEFAULT_CONFIG_PATH,
|
|
5
5
|
DIGEST_TEMPLATE,
|
|
6
|
+
affinityTelemetryFields,
|
|
6
7
|
POLICY_GLM53,
|
|
7
8
|
POLICY_GPT56,
|
|
8
9
|
POLICY_MIMO26,
|
|
@@ -127,6 +128,7 @@ type SessionState = {
|
|
|
127
128
|
reasoningSeen: Map<string, number>
|
|
128
129
|
reasoningLastSeq: string[] | null
|
|
129
130
|
mimoProvider: { providerID: string; modelID: string } | null
|
|
131
|
+
glmProvider: { providerID: string; modelID: string } | null
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
const emptyShape = (): Shape => ({
|
|
@@ -175,6 +177,7 @@ export const CacheEngine: Plugin = async ({ client, directory }) => {
|
|
|
175
177
|
reasoningSeen: new Map(),
|
|
176
178
|
reasoningLastSeq: null,
|
|
177
179
|
mimoProvider: null,
|
|
180
|
+
glmProvider: null,
|
|
178
181
|
}
|
|
179
182
|
sessions.set(sid, s)
|
|
180
183
|
}
|
|
@@ -493,14 +496,37 @@ export const CacheEngine: Plugin = async ({ client, directory }) => {
|
|
|
493
496
|
const model = input.model as unknown as ChatParamsModel
|
|
494
497
|
const providerID = String(model?.providerID ?? "")
|
|
495
498
|
const family = detectPolicy(model)
|
|
496
|
-
if (
|
|
499
|
+
if (family !== POLICY_MIMO26 && family !== POLICY_GLM53) return
|
|
497
500
|
|
|
498
501
|
const hasSessionIDHeader = (headers?: Record<string, string>) =>
|
|
499
502
|
Object.keys(headers ?? {}).some((name) => name.toLowerCase() === "x-session-id")
|
|
500
|
-
|
|
503
|
+
let headerSource = "not_applicable"
|
|
504
|
+
if (providerID === "openrouter") {
|
|
505
|
+
if (hasSessionIDHeader(model?.headers) || hasSessionIDHeader(output.headers)) {
|
|
506
|
+
headerSource = "preexisting"
|
|
507
|
+
} else {
|
|
508
|
+
const sessionID = mimoSessionIdFor(input.sessionID)
|
|
509
|
+
if (sessionID) {
|
|
510
|
+
output.headers["x-session-id"] = sessionID
|
|
511
|
+
headerSource = "cache_engine"
|
|
512
|
+
} else {
|
|
513
|
+
headerSource = "unavailable"
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
501
517
|
|
|
502
|
-
const
|
|
503
|
-
if (
|
|
518
|
+
const telemetry = affinityTelemetryFields(family, providerID, headerSource)
|
|
519
|
+
if (telemetry) {
|
|
520
|
+
rec.record({
|
|
521
|
+
kind: "boundary",
|
|
522
|
+
sid: input.sessionID,
|
|
523
|
+
ts: Date.now(),
|
|
524
|
+
policy: family,
|
|
525
|
+
provider: telemetry.provider,
|
|
526
|
+
model: String(model?.api?.id ?? model?.id ?? "") || null,
|
|
527
|
+
...telemetry,
|
|
528
|
+
})
|
|
529
|
+
}
|
|
504
530
|
} catch (e) {
|
|
505
531
|
rec.record({ kind: "telemetry-error", ts: Date.now(), error: String(e) })
|
|
506
532
|
}
|
|
@@ -552,6 +578,33 @@ export const CacheEngine: Plugin = async ({ client, directory }) => {
|
|
|
552
578
|
return
|
|
553
579
|
}
|
|
554
580
|
|
|
581
|
+
// ---- GLM-5.3 provider identity observation (telemetry only) ----------
|
|
582
|
+
if (family === POLICY_GLM53 && policyEnabled(cfg, POLICY_GLM53) && info) {
|
|
583
|
+
const live = input.model as unknown as ChatParamsModel
|
|
584
|
+
const cur = {
|
|
585
|
+
providerID: String(live?.providerID ?? ""),
|
|
586
|
+
modelID: String(live?.api?.id ?? live?.id ?? ""),
|
|
587
|
+
}
|
|
588
|
+
if (cur.providerID) {
|
|
589
|
+
const s = get(input.sessionID)
|
|
590
|
+
const ev = providerChangeEvent(s.glmProvider, cur)
|
|
591
|
+
if (ev.changed) {
|
|
592
|
+
rec.record({
|
|
593
|
+
kind: "boundary",
|
|
594
|
+
sid: input.sessionID,
|
|
595
|
+
ts: Date.now(),
|
|
596
|
+
reason: "glm_provider_changed",
|
|
597
|
+
policy: POLICY_GLM53,
|
|
598
|
+
from: ev.from,
|
|
599
|
+
to: ev.to,
|
|
600
|
+
note: "OpenCode providerID changed; provider-specific upstream routing is not plugin-visible",
|
|
601
|
+
})
|
|
602
|
+
}
|
|
603
|
+
s.glmProvider = cur
|
|
604
|
+
}
|
|
605
|
+
return
|
|
606
|
+
}
|
|
607
|
+
|
|
555
608
|
if (!(family === POLICY_GPT56 && policyEnabled(cfg, POLICY_GPT56))) {
|
|
556
609
|
// DeepSeek / GLM / neutral: nothing to inject. GLM has no cache-key API;
|
|
557
610
|
// DeepSeek caching is fully passive; we never mutate requests for them.
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
POLICY_GPT56,
|
|
20
20
|
POLICY_MIMO26,
|
|
21
21
|
POLICY_NEUTRAL,
|
|
22
|
+
affinityTelemetryFields,
|
|
22
23
|
canonicalStringify,
|
|
23
24
|
commonPrefixLength,
|
|
24
25
|
createRecorder,
|
|
@@ -938,6 +939,42 @@ test("OpenRouter affinity is ineligible for unknown families and providers", ()
|
|
|
938
939
|
assert.equal(isOpenRouterAffinityEligible(POLICY_MIMO26, undefined), false)
|
|
939
940
|
})
|
|
940
941
|
|
|
942
|
+
test("affinity telemetry fields classify eligibility, attachment, bypass, and missing identity", () => {
|
|
943
|
+
assert.deepEqual(affinityTelemetryFields(POLICY_MIMO26, "openrouter", "cache_engine"), {
|
|
944
|
+
reason: "openrouter_affinity_eligible",
|
|
945
|
+
eligible: true,
|
|
946
|
+
providerIdentityKnown: true,
|
|
947
|
+
provider: "openrouter",
|
|
948
|
+
headerPresent: true,
|
|
949
|
+
headerAttached: true,
|
|
950
|
+
headerSource: "cache_engine",
|
|
951
|
+
})
|
|
952
|
+
assert.deepEqual(affinityTelemetryFields(POLICY_GLM53, "openrouter", "preexisting"), {
|
|
953
|
+
reason: "openrouter_affinity_eligible",
|
|
954
|
+
eligible: true,
|
|
955
|
+
providerIdentityKnown: true,
|
|
956
|
+
provider: "openrouter",
|
|
957
|
+
headerPresent: true,
|
|
958
|
+
headerAttached: false,
|
|
959
|
+
headerSource: "preexisting",
|
|
960
|
+
})
|
|
961
|
+
assert.equal(affinityTelemetryFields(POLICY_MIMO26, "xiaomi", "not_applicable").reason,
|
|
962
|
+
"openrouter_affinity_bypassed_non_openrouter")
|
|
963
|
+
assert.equal(affinityTelemetryFields(POLICY_GLM53, "unknown-provider", "not_applicable").reason,
|
|
964
|
+
"openrouter_affinity_bypassed_non_openrouter")
|
|
965
|
+
assert.deepEqual(affinityTelemetryFields(POLICY_MIMO26, "", "not_applicable"), {
|
|
966
|
+
reason: "openrouter_affinity_bypassed_provider_missing_or_unknown",
|
|
967
|
+
eligible: false,
|
|
968
|
+
providerIdentityKnown: false,
|
|
969
|
+
provider: null,
|
|
970
|
+
headerPresent: false,
|
|
971
|
+
headerAttached: false,
|
|
972
|
+
headerSource: "not_applicable",
|
|
973
|
+
})
|
|
974
|
+
assert.equal(affinityTelemetryFields(POLICY_DEEPSEEK, "openrouter", "not_applicable"), null)
|
|
975
|
+
assert.equal(affinityTelemetryFields(POLICY_GPT56, "openrouter", "not_applicable"), null)
|
|
976
|
+
})
|
|
977
|
+
|
|
941
978
|
// ===========================================================================
|
|
942
979
|
// MiMo-V2.6: cached/prompt token metrics
|
|
943
980
|
// ===========================================================================
|
|
@@ -1019,8 +1056,10 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1019
1056
|
const coreURL = new URL("../src/cache-engine-core.mjs", import.meta.url).href
|
|
1020
1057
|
const script = `
|
|
1021
1058
|
import assert from "node:assert/strict"
|
|
1059
|
+
import { readFileSync } from "node:fs"
|
|
1060
|
+
process.env.CACHE_ENGINE_METRICS_FILE = process.env.HOME + "/affinity-metrics.jsonl"
|
|
1022
1061
|
const { CacheEngine } = await import(${JSON.stringify(pluginURL)})
|
|
1023
|
-
const { mimoSessionIdFor } = await import(${JSON.stringify(coreURL)})
|
|
1062
|
+
const { detectPolicy, mimoSessionIdFor, POLICY_GLM53, POLICY_MIMO26 } = await import(${JSON.stringify(coreURL)})
|
|
1024
1063
|
const client = {
|
|
1025
1064
|
app: { log: async () => ({}) },
|
|
1026
1065
|
session: { get: async () => ({ data: { parentID: null } }) },
|
|
@@ -1031,14 +1070,29 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1031
1070
|
const invoke = async (model, sessionID, existingHeaders = {}) => {
|
|
1032
1071
|
const output = { headers: { ...existingHeaders } }
|
|
1033
1072
|
const headersRef = output.headers
|
|
1073
|
+
const family = detectPolicy(model)
|
|
1074
|
+
if (family === POLICY_MIMO26 || family === POLICY_GLM53) {
|
|
1075
|
+
await hooks["chat.params"]({
|
|
1076
|
+
sessionID,
|
|
1077
|
+
agent: "build",
|
|
1078
|
+
model,
|
|
1079
|
+
provider: { source: "config", info: { id: model.providerID }, options: {} },
|
|
1080
|
+
message: { id: "msg", sessionID, role: "user", content: "probe" },
|
|
1081
|
+
}, { options: {} })
|
|
1082
|
+
}
|
|
1034
1083
|
await hooks["chat.headers"]({
|
|
1035
1084
|
sessionID,
|
|
1036
1085
|
agent: "build",
|
|
1037
1086
|
model,
|
|
1038
|
-
provider: { id: model.providerID },
|
|
1087
|
+
provider: { source: "config", info: { id: model.providerID }, options: {} },
|
|
1039
1088
|
message: { id: "msg", sessionID, role: "user", content: "probe" },
|
|
1040
1089
|
}, output)
|
|
1041
|
-
return {
|
|
1090
|
+
return {
|
|
1091
|
+
headers: output.headers,
|
|
1092
|
+
sameObject: output.headers === headersRef,
|
|
1093
|
+
outputKeys: Object.keys(output),
|
|
1094
|
+
modelHeaders: model.headers,
|
|
1095
|
+
}
|
|
1042
1096
|
}
|
|
1043
1097
|
const mimoOpenRouter = {
|
|
1044
1098
|
providerID: "openrouter",
|
|
@@ -1057,6 +1111,33 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1057
1111
|
const glm2 = await invoke(glmOpenRouter, "ses_glm_same")
|
|
1058
1112
|
const glmDifferent = await invoke(glmOpenRouter, "ses_glm_other")
|
|
1059
1113
|
const glmDirect = await invoke({ ...glmOpenRouter, providerID: "zai" }, "ses_glm_direct", { "User-Agent": "preserve-glm" })
|
|
1114
|
+
const mimoSwitchOpen = await invoke(mimoOpenRouter, "ses_mimo_switch")
|
|
1115
|
+
const mimoSwitchDirect = await invoke({ ...mimoOpenRouter, providerID: "xiaomi" }, "ses_mimo_switch")
|
|
1116
|
+
const glmSwitchOpen = await invoke(glmOpenRouter, "ses_glm_switch")
|
|
1117
|
+
const glmSwitchDirect = await invoke({ ...glmOpenRouter, providerID: "zai" }, "ses_glm_switch")
|
|
1118
|
+
const nonOpenRouterMatrix = [
|
|
1119
|
+
["mimo-direct", { ...mimoOpenRouter, providerID: "xiaomi" }],
|
|
1120
|
+
["glm-direct", { ...glmOpenRouter, providerID: "zai" }],
|
|
1121
|
+
["deepseek-direct", { providerID: "deepseek", id: "deepseek-v4.1-flash", api: { id: "deepseek-v4.1-flash" }, headers: {} }],
|
|
1122
|
+
["gpt-openai", { providerID: "openai", id: "gpt-5.6", api: { id: "gpt-5.6", npm: "@ai-sdk/openai" }, headers: {} }],
|
|
1123
|
+
["unknown-provider", { ...mimoOpenRouter, providerID: "unknown-provider" }],
|
|
1124
|
+
["missing-provider", { ...mimoOpenRouter, providerID: undefined }],
|
|
1125
|
+
["opencode-go-mimo", { ...mimoOpenRouter, providerID: "opencode" }],
|
|
1126
|
+
["opencode-go-glm", { ...glmOpenRouter, providerID: "opencode" }],
|
|
1127
|
+
]
|
|
1128
|
+
const compatibility = []
|
|
1129
|
+
for (const [name, model] of nonOpenRouterMatrix) {
|
|
1130
|
+
const existing = { "User-Agent": "preserve-" + name, "x-compat-test": name }
|
|
1131
|
+
compatibility.push({ name, ...(await invoke(model, "ses_" + name, existing)), expected: existing })
|
|
1132
|
+
}
|
|
1133
|
+
const gptOutput = { options: {} }
|
|
1134
|
+
await hooks["chat.params"]({
|
|
1135
|
+
sessionID: "ses_gpt_native_cache",
|
|
1136
|
+
agent: "build",
|
|
1137
|
+
model: { providerID: "openai", id: "gpt-5.6", api: { id: "gpt-5.6", npm: "@ai-sdk/openai" } },
|
|
1138
|
+
provider: { source: "config", info: { id: "openai" }, options: {} },
|
|
1139
|
+
message: { id: "msg-gpt", sessionID: "ses_gpt_native_cache", role: "user", content: "probe" },
|
|
1140
|
+
}, gptOutput)
|
|
1060
1141
|
const configured = await invoke({
|
|
1061
1142
|
...mimoOpenRouter,
|
|
1062
1143
|
headers: { "X-Session-Id": "user-configured-value" },
|
|
@@ -1073,6 +1154,12 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1073
1154
|
glm2,
|
|
1074
1155
|
glmDifferent,
|
|
1075
1156
|
glmDirect,
|
|
1157
|
+
mimoSwitchOpen,
|
|
1158
|
+
mimoSwitchDirect,
|
|
1159
|
+
glmSwitchOpen,
|
|
1160
|
+
glmSwitchDirect,
|
|
1161
|
+
compatibility,
|
|
1162
|
+
gptOptions: gptOutput.options,
|
|
1076
1163
|
configured,
|
|
1077
1164
|
configuredModelHeaders: configured.modelHeaders,
|
|
1078
1165
|
earlierPlugin,
|
|
@@ -1080,6 +1167,8 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1080
1167
|
expectedOther: mimoSessionIdFor("ses_other"),
|
|
1081
1168
|
expectedGlm: mimoSessionIdFor("ses_glm_same"),
|
|
1082
1169
|
expectedGlmOther: mimoSessionIdFor("ses_glm_other"),
|
|
1170
|
+
telemetry: readFileSync(process.env.CACHE_ENGINE_METRICS_FILE, "utf8")
|
|
1171
|
+
.trim().split("\\n").filter(Boolean).map((line) => JSON.parse(line)),
|
|
1083
1172
|
}
|
|
1084
1173
|
assert.equal(configured.headers["x-session-id"], undefined)
|
|
1085
1174
|
assert.equal(earlierPlugin.headers["X-SESSION-ID"], "earlier-plugin-value")
|
|
@@ -1139,3 +1228,91 @@ test("GLM direct Z.AI does not receive x-session-id", async () => {
|
|
|
1139
1228
|
assert.equal(result.glmDirect.headers["x-session-id"], undefined)
|
|
1140
1229
|
assert.deepEqual(result.glmDirect.headers, { "User-Agent": "preserve-glm" })
|
|
1141
1230
|
})
|
|
1231
|
+
|
|
1232
|
+
test("non-OpenRouter endpoint matrix is x-session-id non-mutating and preserves unrelated headers", async () => {
|
|
1233
|
+
const result = await miMoHeaderResults()
|
|
1234
|
+
assert.equal(result.compatibility.length, 8)
|
|
1235
|
+
for (const item of result.compatibility) {
|
|
1236
|
+
assert.equal(item.headers["x-session-id"], undefined, `${item.name} must not receive OpenRouter affinity`)
|
|
1237
|
+
assert.deepEqual(item.headers, item.expected, `${item.name} unrelated headers must remain unchanged`)
|
|
1238
|
+
assert.equal(item.sameObject, true, `${item.name} headers object must be preserved`)
|
|
1239
|
+
assert.deepEqual(item.outputKeys, ["headers"], `${item.name} hook output remains headers-only`)
|
|
1240
|
+
}
|
|
1241
|
+
})
|
|
1242
|
+
|
|
1243
|
+
test("OpenAI GPT retains its existing chat.params cache options without affinity headers", async () => {
|
|
1244
|
+
const result = await miMoHeaderResults()
|
|
1245
|
+
assert.equal(typeof result.gptOptions.promptCacheKey, "string")
|
|
1246
|
+
assert.deepEqual(result.gptOptions.promptCacheOptions, { mode: "implicit", ttl: "30m" })
|
|
1247
|
+
})
|
|
1248
|
+
|
|
1249
|
+
test("affinity telemetry classifies eligible, attached, preexisting, bypassed, and missing-provider requests", async () => {
|
|
1250
|
+
const result = await miMoHeaderResults()
|
|
1251
|
+
const events = result.telemetry.filter((event) => event.reason?.startsWith("openrouter_affinity_"))
|
|
1252
|
+
const eventFor = (sid, policy) => events.find((event) => event.sid === sid && event.policy === policy)
|
|
1253
|
+
|
|
1254
|
+
for (const [sid, policy] of [
|
|
1255
|
+
["ses_same", POLICY_MIMO26],
|
|
1256
|
+
["ses_glm_same", POLICY_GLM53],
|
|
1257
|
+
]) {
|
|
1258
|
+
const event = eventFor(sid, policy)
|
|
1259
|
+
assert.equal(event.reason, "openrouter_affinity_eligible")
|
|
1260
|
+
assert.equal(event.eligible, true)
|
|
1261
|
+
assert.equal(event.provider, "openrouter")
|
|
1262
|
+
assert.equal(event.headerPresent, true)
|
|
1263
|
+
assert.equal(event.headerAttached, true)
|
|
1264
|
+
assert.equal(event.headerSource, "cache_engine")
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
const configured = eventFor("ses_configured", POLICY_MIMO26)
|
|
1268
|
+
assert.equal(configured.reason, "openrouter_affinity_eligible")
|
|
1269
|
+
assert.equal(configured.headerPresent, true)
|
|
1270
|
+
assert.equal(configured.headerAttached, false)
|
|
1271
|
+
assert.equal(configured.headerSource, "preexisting")
|
|
1272
|
+
|
|
1273
|
+
for (const [sid, policy, provider] of [
|
|
1274
|
+
["ses_direct", POLICY_MIMO26, "xiaomi"],
|
|
1275
|
+
["ses_glm_direct", POLICY_GLM53, "zai"],
|
|
1276
|
+
["ses_unknown", POLICY_MIMO26, "unknown-provider"],
|
|
1277
|
+
]) {
|
|
1278
|
+
const event = eventFor(sid, policy)
|
|
1279
|
+
assert.equal(event.reason, "openrouter_affinity_bypassed_non_openrouter")
|
|
1280
|
+
assert.equal(event.eligible, false)
|
|
1281
|
+
assert.equal(event.provider, provider)
|
|
1282
|
+
assert.equal(event.headerAttached, false)
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
const missing = eventFor("ses_missing_provider", POLICY_MIMO26)
|
|
1286
|
+
assert.equal(missing.reason, "openrouter_affinity_bypassed_provider_missing_or_unknown")
|
|
1287
|
+
assert.equal(missing.providerIdentityKnown, false)
|
|
1288
|
+
assert.equal(missing.provider, null)
|
|
1289
|
+
assert.equal(missing.headerAttached, false)
|
|
1290
|
+
|
|
1291
|
+
// New affinity-observation records contain classifications, never the
|
|
1292
|
+
// generated or pre-existing x-session-id value.
|
|
1293
|
+
for (const event of events) {
|
|
1294
|
+
assert.equal(Object.hasOwn(event, "x-session-id"), false)
|
|
1295
|
+
assert.equal(Object.hasOwn(event, "headerValue"), false)
|
|
1296
|
+
}
|
|
1297
|
+
const serializedAffinityEvents = JSON.stringify(events)
|
|
1298
|
+
assert.equal(serializedAffinityEvents.includes(result.expectedSame), false)
|
|
1299
|
+
assert.equal(serializedAffinityEvents.includes(result.expectedGlm), false)
|
|
1300
|
+
})
|
|
1301
|
+
|
|
1302
|
+
test("affinity telemetry preserves non-OpenRouter families and reports provider changes", async () => {
|
|
1303
|
+
const result = await miMoHeaderResults()
|
|
1304
|
+
const events = result.telemetry
|
|
1305
|
+
const affinityEvents = events.filter((event) => event.reason?.startsWith("openrouter_affinity_"))
|
|
1306
|
+
assert.equal(affinityEvents.some((event) => event.policy === POLICY_DEEPSEEK), false)
|
|
1307
|
+
assert.equal(affinityEvents.some((event) => event.policy === POLICY_GPT56), false)
|
|
1308
|
+
|
|
1309
|
+
const mimoChange = events.find((event) => event.reason === "mimo_provider_changed" && event.sid === "ses_mimo_switch")
|
|
1310
|
+
assert.equal(mimoChange.from.providerID, "openrouter")
|
|
1311
|
+
assert.equal(mimoChange.to.providerID, "xiaomi")
|
|
1312
|
+
|
|
1313
|
+
const glmChange = events.find((event) => event.reason === "glm_provider_changed" && event.sid === "ses_glm_switch")
|
|
1314
|
+
assert.equal(glmChange.kind, "boundary")
|
|
1315
|
+
assert.equal(glmChange.from.providerID, "openrouter")
|
|
1316
|
+
assert.equal(glmChange.to.providerID, "zai")
|
|
1317
|
+
assert.equal(glmChange.policy, POLICY_GLM53)
|
|
1318
|
+
})
|