opencode-cache-engine 0.3.0 → 0.3.1
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/.opencode/opencode.json +6 -0
- package/.opencode/tui.json +5 -0
- package/package.json +1 -1
- package/src/cache-engine-core.mjs +19 -0
- package/test/cache-engine.test.mjs +39 -0
package/package.json
CHANGED
|
@@ -481,6 +481,25 @@ export function mimoHitRate(cachedTokens, promptTokens) {
|
|
|
481
481
|
return Math.round((100 * cachedTokens) / promptTokens)
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
+
// Derive a provider-neutral stable ID from the logical OpenCode session ID.
|
|
485
|
+
// The full SHA-256 digest avoids intentional truncation/collapse of distinct
|
|
486
|
+
// sessions. This helper only generates an identifier; it does not select a
|
|
487
|
+
// provider or inject the identifier into any request transport.
|
|
488
|
+
export function stableSessionIdFor(sessionID) {
|
|
489
|
+
if (typeof sessionID !== "string" || sessionID.length === 0) return null
|
|
490
|
+
return `oc-ses-${createHash("sha256").update(sessionID).digest("hex")}`
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// OpenRouter session affinity is currently eligible only for the two policy
|
|
494
|
+
// families with documented affinity use: MiMo-V2.6 and GLM-5.3. This pure
|
|
495
|
+
// policy decision is separate from ID generation and transport/header injection.
|
|
496
|
+
export function isOpenRouterAffinityEligible(policyFamily, providerID) {
|
|
497
|
+
return (
|
|
498
|
+
providerID === "openrouter" &&
|
|
499
|
+
(policyFamily === POLICY_MIMO26 || policyFamily === POLICY_GLM53)
|
|
500
|
+
)
|
|
501
|
+
}
|
|
502
|
+
|
|
484
503
|
// Derive a stable, session-scoped identifier suitable for OpenRouter's
|
|
485
504
|
// documented `session_id` sticky-routing key. Pure function of the OpenCode
|
|
486
505
|
// session id only: identical sessions map to identical ids, distinct sessions
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
glmHitRatio,
|
|
29
29
|
gptCacheOptionsDelta,
|
|
30
30
|
hitRatePct,
|
|
31
|
+
isOpenRouterAffinityEligible,
|
|
31
32
|
loadConfig,
|
|
32
33
|
mimoHitRate,
|
|
33
34
|
mimoSessionIdFor,
|
|
@@ -40,6 +41,7 @@ import {
|
|
|
40
41
|
shapeFieldDiffs,
|
|
41
42
|
shorthash,
|
|
42
43
|
shouldAggregate,
|
|
44
|
+
stableSessionIdFor,
|
|
43
45
|
systemShapeHashes,
|
|
44
46
|
toolFingerprint,
|
|
45
47
|
toolWireFingerprint,
|
|
@@ -871,10 +873,22 @@ test("MiMo relocation is a no-op when start/end markers are missing", () => {
|
|
|
871
873
|
// MiMo-V2.6: sticky-session identity (pure, derived but not injected)
|
|
872
874
|
// ===========================================================================
|
|
873
875
|
|
|
876
|
+
test("stableSessionIdFor: deterministic for the same logical session", () => {
|
|
877
|
+
assert.equal(stableSessionIdFor("ses_abc123"), stableSessionIdFor("ses_abc123"))
|
|
878
|
+
})
|
|
879
|
+
|
|
880
|
+
test("stableSessionIdFor: different logical sessions produce different ids", () => {
|
|
881
|
+
assert.notEqual(stableSessionIdFor("ses_abc"), stableSessionIdFor("ses_xyz"))
|
|
882
|
+
})
|
|
883
|
+
|
|
874
884
|
test("mimoSessionIdFor: deterministic + stable for the same session", () => {
|
|
875
885
|
assert.equal(mimoSessionIdFor("ses_abc123"), mimoSessionIdFor("ses_abc123"))
|
|
876
886
|
})
|
|
877
887
|
|
|
888
|
+
test("mimoSessionIdFor preserves its existing id format", () => {
|
|
889
|
+
assert.equal(mimoSessionIdFor("ses_abc123"), `mimo-ses-${shorthash("ses_abc123")}`)
|
|
890
|
+
})
|
|
891
|
+
|
|
878
892
|
test("mimoSessionIdFor: distinct sessions produce distinct ids", () => {
|
|
879
893
|
assert.notEqual(mimoSessionIdFor("ses_abc"), mimoSessionIdFor("ses_xyz"))
|
|
880
894
|
})
|
|
@@ -898,6 +912,31 @@ test("mimoSessionIdFor: transient request fields cannot alter the id", () => {
|
|
|
898
912
|
assert.equal(mimoSessionIdFor("ses_stable"), mimoSessionIdFor("ses_stable", { turn: 7, temperature: 0.9 }))
|
|
899
913
|
})
|
|
900
914
|
|
|
915
|
+
// ===========================================================================
|
|
916
|
+
// OpenRouter session-affinity eligibility (pure policy decision only)
|
|
917
|
+
// ===========================================================================
|
|
918
|
+
|
|
919
|
+
test("OpenRouter affinity is eligible for MiMo and GLM only", () => {
|
|
920
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_MIMO26, "openrouter"), true)
|
|
921
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_GLM53, "openrouter"), true)
|
|
922
|
+
})
|
|
923
|
+
|
|
924
|
+
test("OpenRouter affinity is ineligible for non-OpenRouter providers", () => {
|
|
925
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_MIMO26, "xiaomi"), false)
|
|
926
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_GLM53, "zai"), false)
|
|
927
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_MIMO26, "unknown-provider"), false)
|
|
928
|
+
})
|
|
929
|
+
|
|
930
|
+
test("OpenRouter affinity is ineligible for DeepSeek and GPT", () => {
|
|
931
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_DEEPSEEK, "openrouter"), false)
|
|
932
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_GPT56, "openrouter"), false)
|
|
933
|
+
})
|
|
934
|
+
|
|
935
|
+
test("OpenRouter affinity is ineligible for unknown families and providers", () => {
|
|
936
|
+
assert.equal(isOpenRouterAffinityEligible("unknown-family", "openrouter"), false)
|
|
937
|
+
assert.equal(isOpenRouterAffinityEligible(POLICY_MIMO26, undefined), false)
|
|
938
|
+
})
|
|
939
|
+
|
|
901
940
|
// ===========================================================================
|
|
902
941
|
// MiMo-V2.6: cached/prompt token metrics
|
|
903
942
|
// ===========================================================================
|