opencode-model-router 1.0.4 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +63 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-model-router",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "OpenCode plugin that routes tasks to tiered subagents (fast/medium/heavy) based on complexity",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { Plugin, PluginInput } from "@opencode-ai/plugin";
2
- import { readFileSync, writeFileSync } from "fs";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
+ import { homedir } from "os";
3
4
  import { dirname, join } from "path";
4
5
  import { fileURLToPath } from "url";
5
6
 
@@ -37,6 +38,10 @@ interface RouterConfig {
37
38
  defaultTier: string;
38
39
  }
39
40
 
41
+ interface RouterState {
42
+ activePreset?: string;
43
+ }
44
+
40
45
  // ---------------------------------------------------------------------------
41
46
  // Config loader
42
47
  // ---------------------------------------------------------------------------
@@ -50,13 +55,59 @@ function configPath(): string {
50
55
  return join(getPluginRoot(), "tiers.json");
51
56
  }
52
57
 
58
+ function statePath(): string {
59
+ return join(homedir(), ".config", "opencode", "opencode-model-router.state.json");
60
+ }
61
+
62
+ function resolvePresetName(cfg: RouterConfig, requestedPreset: string): string | undefined {
63
+ if (cfg.presets[requestedPreset]) {
64
+ return requestedPreset;
65
+ }
66
+
67
+ const normalized = requestedPreset.trim().toLowerCase();
68
+ if (!normalized) {
69
+ return undefined;
70
+ }
71
+
72
+ return Object.keys(cfg.presets).find((name) => name.toLowerCase() === normalized);
73
+ }
74
+
53
75
  function loadConfig(): RouterConfig {
54
- return JSON.parse(readFileSync(configPath(), "utf-8")) as RouterConfig;
76
+ const cfg = JSON.parse(readFileSync(configPath(), "utf-8")) as RouterConfig;
77
+
78
+ try {
79
+ if (existsSync(statePath())) {
80
+ const state = JSON.parse(readFileSync(statePath(), "utf-8")) as RouterState;
81
+ if (state.activePreset) {
82
+ const resolved = resolvePresetName(cfg, state.activePreset);
83
+ if (resolved) {
84
+ cfg.activePreset = resolved;
85
+ }
86
+ }
87
+ }
88
+ } catch {
89
+ // Ignore state read errors and keep tiers.json active preset
90
+ }
91
+
92
+ return cfg;
55
93
  }
56
94
 
57
95
  function saveActivePreset(presetName: string): void {
58
96
  const cfg = loadConfig();
59
- cfg.activePreset = presetName;
97
+ const resolved = resolvePresetName(cfg, presetName);
98
+ if (!resolved) {
99
+ return;
100
+ }
101
+
102
+ cfg.activePreset = resolved;
103
+
104
+ // Persist user-selected preset outside package cache so it survives npm updates
105
+ const presetState: RouterState = { activePreset: resolved };
106
+ const p = statePath();
107
+ mkdirSync(dirname(p), { recursive: true });
108
+ writeFileSync(p, JSON.stringify(presetState, null, 2) + "\n", "utf-8");
109
+
110
+ // Keep local tiers.json in sync as best effort
60
111
  writeFileSync(configPath(), JSON.stringify(cfg, null, 2) + "\n", "utf-8");
61
112
  }
62
113
 
@@ -180,19 +231,22 @@ function buildPresetOutput(cfg: RouterConfig, args: string): string {
180
231
  }
181
232
 
182
233
  // Switch preset
183
- if (cfg.presets[requestedPreset]) {
184
- saveActivePreset(requestedPreset);
185
- const tiers = cfg.presets[requestedPreset]!;
234
+ const resolvedPreset = resolvePresetName(cfg, requestedPreset);
235
+ if (resolvedPreset) {
236
+ saveActivePreset(resolvedPreset);
237
+ cfg.activePreset = resolvedPreset;
238
+ const tiers = cfg.presets[resolvedPreset]!;
186
239
  const models = Object.entries(tiers)
187
240
  .map(([tier, t]) => ` @${tier} -> ${t.model}`)
188
241
  .join("\n");
189
242
  return [
190
- `Preset switched to **${requestedPreset}**.`,
243
+ `Preset switched to **${resolvedPreset}**.`,
191
244
  "",
192
245
  models,
193
246
  "",
194
- "Restart OpenCode for agent registration to take effect.",
195
- "System prompt delegation rules will update immediately.",
247
+ "Selection is now persisted in ~/.config/opencode/opencode-model-router.state.json.",
248
+ "Restart OpenCode for subagent model registration to take effect.",
249
+ "System prompt delegation rules update immediately.",
196
250
  ].join("\n");
197
251
  }
198
252