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.
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "plugin": [
4
+ "opencode-cache-engine"
5
+ ]
6
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "plugin": [
3
+ "opencode-cache-engine"
4
+ ]
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-cache-engine",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "private": false,
5
5
  "description": "Provider-aware prompt-cache optimization and telemetry for OpenCode",
6
6
  "keywords": [
@@ -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
  // ===========================================================================