opencode-cache-engine 0.3.2 → 0.3.4
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.ts +8 -7
- package/test/cache-engine.test.mjs +71 -6
package/package.json
CHANGED
package/src/cache-engine.ts
CHANGED
|
@@ -482,17 +482,18 @@ export const CacheEngine: Plugin = async ({ client, directory }) => {
|
|
|
482
482
|
// use a deterministic separate namespace (<root>:compact) so a compaction
|
|
483
483
|
// cache write never interferes with the useful live-session cache.
|
|
484
484
|
//
|
|
485
|
-
// MiMo-V2.6 + OpenRouter session affinity. Gate on the actual
|
|
486
|
-
// provider identity as well as the detected family; a matching
|
|
487
|
-
// on a direct endpoint is not sufficient. The runtime merges
|
|
488
|
-
// before this hook's output, so preserve a case-insensitive
|
|
489
|
-
// earlier-plugin x-session-id rather than silently overwriting
|
|
490
|
-
// add the deterministic ID derived from the logical
|
|
485
|
+
// MiMo-V2.6 / GLM-5.3 + OpenRouter session affinity. Gate on the actual
|
|
486
|
+
// OpenCode provider identity as well as the detected family; a matching
|
|
487
|
+
// model slug on a direct endpoint is not sufficient. The runtime merges
|
|
488
|
+
// model.headers before this hook's output, so preserve a case-insensitive
|
|
489
|
+
// user/model or earlier-plugin x-session-id rather than silently overwriting
|
|
490
|
+
// it. Otherwise add the deterministic ID derived from the logical session.
|
|
491
491
|
"chat.headers": async (input, output) => {
|
|
492
492
|
try {
|
|
493
493
|
const model = input.model as unknown as ChatParamsModel
|
|
494
494
|
const providerID = String(model?.providerID ?? "")
|
|
495
|
-
|
|
495
|
+
const family = detectPolicy(model)
|
|
496
|
+
if (providerID !== "openrouter" || (family !== POLICY_MIMO26 && family !== POLICY_GLM53)) return
|
|
496
497
|
|
|
497
498
|
const hasSessionIDHeader = (headers?: Record<string, string>) =>
|
|
498
499
|
Object.keys(headers ?? {}).some((name) => name.toLowerCase() === "x-session-id")
|
|
@@ -1035,10 +1035,15 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1035
1035
|
sessionID,
|
|
1036
1036
|
agent: "build",
|
|
1037
1037
|
model,
|
|
1038
|
-
provider: { id: model.providerID },
|
|
1038
|
+
provider: { source: "config", info: { id: model.providerID }, options: {} },
|
|
1039
1039
|
message: { id: "msg", sessionID, role: "user", content: "probe" },
|
|
1040
1040
|
}, output)
|
|
1041
|
-
return {
|
|
1041
|
+
return {
|
|
1042
|
+
headers: output.headers,
|
|
1043
|
+
sameObject: output.headers === headersRef,
|
|
1044
|
+
outputKeys: Object.keys(output),
|
|
1045
|
+
modelHeaders: model.headers,
|
|
1046
|
+
}
|
|
1042
1047
|
}
|
|
1043
1048
|
const mimoOpenRouter = {
|
|
1044
1049
|
providerID: "openrouter",
|
|
@@ -1052,7 +1057,34 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1052
1057
|
const direct = await invoke({ ...mimoOpenRouter, providerID: "xiaomi" }, "ses_direct", { "User-Agent": "preserve-me" })
|
|
1053
1058
|
const unknown = await invoke({ ...mimoOpenRouter, providerID: "unknown-provider" }, "ses_unknown")
|
|
1054
1059
|
const missingProvider = await invoke({ ...mimoOpenRouter, providerID: undefined }, "ses_missing_provider")
|
|
1055
|
-
const
|
|
1060
|
+
const glmOpenRouter = { providerID: "openrouter", id: "z-ai/glm-5.3", api: { id: "z-ai/glm-5.3" }, headers: {} }
|
|
1061
|
+
const glm1 = await invoke(glmOpenRouter, "ses_glm_same")
|
|
1062
|
+
const glm2 = await invoke(glmOpenRouter, "ses_glm_same")
|
|
1063
|
+
const glmDifferent = await invoke(glmOpenRouter, "ses_glm_other")
|
|
1064
|
+
const glmDirect = await invoke({ ...glmOpenRouter, providerID: "zai" }, "ses_glm_direct", { "User-Agent": "preserve-glm" })
|
|
1065
|
+
const nonOpenRouterMatrix = [
|
|
1066
|
+
["mimo-direct", { ...mimoOpenRouter, providerID: "xiaomi" }],
|
|
1067
|
+
["glm-direct", { ...glmOpenRouter, providerID: "zai" }],
|
|
1068
|
+
["deepseek-direct", { providerID: "deepseek", id: "deepseek-v4.1-flash", api: { id: "deepseek-v4.1-flash" }, headers: {} }],
|
|
1069
|
+
["gpt-openai", { providerID: "openai", id: "gpt-5.6", api: { id: "gpt-5.6", npm: "@ai-sdk/openai" }, headers: {} }],
|
|
1070
|
+
["unknown-provider", { ...mimoOpenRouter, providerID: "unknown-provider" }],
|
|
1071
|
+
["missing-provider", { ...mimoOpenRouter, providerID: undefined }],
|
|
1072
|
+
["opencode-go-mimo", { ...mimoOpenRouter, providerID: "opencode" }],
|
|
1073
|
+
["opencode-go-glm", { ...glmOpenRouter, providerID: "opencode" }],
|
|
1074
|
+
]
|
|
1075
|
+
const compatibility = []
|
|
1076
|
+
for (const [name, model] of nonOpenRouterMatrix) {
|
|
1077
|
+
const existing = { "User-Agent": "preserve-" + name, "x-compat-test": name }
|
|
1078
|
+
compatibility.push({ name, ...(await invoke(model, "ses_" + name, existing)), expected: existing })
|
|
1079
|
+
}
|
|
1080
|
+
const gptOutput = { options: {} }
|
|
1081
|
+
await hooks["chat.params"]({
|
|
1082
|
+
sessionID: "ses_gpt_native_cache",
|
|
1083
|
+
agent: "build",
|
|
1084
|
+
model: { providerID: "openai", id: "gpt-5.6", api: { id: "gpt-5.6", npm: "@ai-sdk/openai" } },
|
|
1085
|
+
provider: { source: "config", info: { id: "openai" }, options: {} },
|
|
1086
|
+
message: { id: "msg-gpt", sessionID: "ses_gpt_native_cache", role: "user", content: "probe" },
|
|
1087
|
+
}, gptOutput)
|
|
1056
1088
|
const configured = await invoke({
|
|
1057
1089
|
...mimoOpenRouter,
|
|
1058
1090
|
headers: { "X-Session-Id": "user-configured-value" },
|
|
@@ -1065,12 +1097,19 @@ async function runMiMoHeaderHookProbe() {
|
|
|
1065
1097
|
direct,
|
|
1066
1098
|
unknown,
|
|
1067
1099
|
missingProvider,
|
|
1068
|
-
|
|
1100
|
+
glm1,
|
|
1101
|
+
glm2,
|
|
1102
|
+
glmDifferent,
|
|
1103
|
+
glmDirect,
|
|
1104
|
+
compatibility,
|
|
1105
|
+
gptOptions: gptOutput.options,
|
|
1069
1106
|
configured,
|
|
1070
1107
|
configuredModelHeaders: configured.modelHeaders,
|
|
1071
1108
|
earlierPlugin,
|
|
1072
1109
|
expectedSame: mimoSessionIdFor("ses_same"),
|
|
1073
1110
|
expectedOther: mimoSessionIdFor("ses_other"),
|
|
1111
|
+
expectedGlm: mimoSessionIdFor("ses_glm_same"),
|
|
1112
|
+
expectedGlmOther: mimoSessionIdFor("ses_glm_other"),
|
|
1074
1113
|
}
|
|
1075
1114
|
assert.equal(configured.headers["x-session-id"], undefined)
|
|
1076
1115
|
assert.equal(earlierPlugin.headers["X-SESSION-ID"], "earlier-plugin-value")
|
|
@@ -1117,7 +1156,33 @@ test("MiMo affinity preserves existing x-session-id values case-insensitively",
|
|
|
1117
1156
|
assert.deepEqual(result.earlierPlugin.headers, { "X-SESSION-ID": "earlier-plugin-value" })
|
|
1118
1157
|
})
|
|
1119
1158
|
|
|
1120
|
-
test("
|
|
1159
|
+
test("GLM/OpenRouter attaches the deterministic session ID", async () => {
|
|
1160
|
+
const result = await miMoHeaderResults()
|
|
1161
|
+
assert.equal(result.glm1.headers["x-session-id"], result.expectedGlm)
|
|
1162
|
+
assert.equal(result.glm2.headers["x-session-id"], result.expectedGlm)
|
|
1163
|
+
assert.equal(result.glmDifferent.headers["x-session-id"], result.expectedGlmOther)
|
|
1164
|
+
assert.notEqual(result.glmDifferent.headers["x-session-id"], result.glm1.headers["x-session-id"])
|
|
1165
|
+
})
|
|
1166
|
+
|
|
1167
|
+
test("GLM direct Z.AI does not receive x-session-id", async () => {
|
|
1168
|
+
const result = await miMoHeaderResults()
|
|
1169
|
+
assert.equal(result.glmDirect.headers["x-session-id"], undefined)
|
|
1170
|
+
assert.deepEqual(result.glmDirect.headers, { "User-Agent": "preserve-glm" })
|
|
1171
|
+
})
|
|
1172
|
+
|
|
1173
|
+
test("non-OpenRouter endpoint matrix is x-session-id non-mutating and preserves unrelated headers", async () => {
|
|
1174
|
+
const result = await miMoHeaderResults()
|
|
1175
|
+
assert.equal(result.compatibility.length, 8)
|
|
1176
|
+
for (const item of result.compatibility) {
|
|
1177
|
+
assert.equal(item.headers["x-session-id"], undefined, `${item.name} must not receive OpenRouter affinity`)
|
|
1178
|
+
assert.deepEqual(item.headers, item.expected, `${item.name} unrelated headers must remain unchanged`)
|
|
1179
|
+
assert.equal(item.sameObject, true, `${item.name} headers object must be preserved`)
|
|
1180
|
+
assert.deepEqual(item.outputKeys, ["headers"], `${item.name} hook output remains headers-only`)
|
|
1181
|
+
}
|
|
1182
|
+
})
|
|
1183
|
+
|
|
1184
|
+
test("OpenAI GPT retains its existing chat.params cache options without affinity headers", async () => {
|
|
1121
1185
|
const result = await miMoHeaderResults()
|
|
1122
|
-
assert.equal(result.
|
|
1186
|
+
assert.equal(typeof result.gptOptions.promptCacheKey, "string")
|
|
1187
|
+
assert.deepEqual(result.gptOptions.promptCacheOptions, { mode: "implicit", ttl: "30m" })
|
|
1123
1188
|
})
|