coder-config 0.53.3-beta → 0.53.5-beta

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/lib/constants.js CHANGED
@@ -2,7 +2,7 @@
2
2
  * Constants and tool path configurations
3
3
  */
4
4
 
5
- const VERSION = '0.53.3-beta';
5
+ const VERSION = '0.53.5-beta';
6
6
 
7
7
  // Tool-specific path configurations
8
8
  const TOOL_PATHS = {
package/lib/router.js ADDED
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Claude Code Router (CCR) configuration management
3
+ */
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { execSync } = require('child_process');
8
+
9
+ const CCR_DIR_NAME = '.claude-code-router';
10
+ const CONFIG_FILE = 'config.json';
11
+ const PRESET_DIR_NAME = 'coder-config-presets';
12
+ const CCR_PORT = 3456;
13
+
14
+ /**
15
+ * Get path to CCR config file
16
+ */
17
+ function getConfigPath() {
18
+ const homeDir = process.env.HOME || '';
19
+ return path.join(homeDir, CCR_DIR_NAME, CONFIG_FILE);
20
+ }
21
+
22
+ /**
23
+ * Read and parse CCR config, return {} if missing or invalid
24
+ */
25
+ function getConfig() {
26
+ const configPath = getConfigPath();
27
+ try {
28
+ if (!fs.existsSync(configPath)) return {};
29
+ return JSON.parse(fs.readFileSync(configPath, 'utf8'));
30
+ } catch {
31
+ return {};
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Write config JSON, creating directory if needed
37
+ */
38
+ function saveConfig(config) {
39
+ const configPath = getConfigPath();
40
+ const dir = path.dirname(configPath);
41
+ fs.mkdirSync(dir, { recursive: true });
42
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
43
+ }
44
+
45
+ /**
46
+ * Return Providers array from config, or []
47
+ */
48
+ function listProviders() {
49
+ const config = getConfig();
50
+ return Array.isArray(config.Providers) ? config.Providers : [];
51
+ }
52
+
53
+ /**
54
+ * Add or replace a provider by name
55
+ */
56
+ function addProvider(name, providerConfig) {
57
+ const config = getConfig();
58
+ if (!Array.isArray(config.Providers)) {
59
+ config.Providers = [];
60
+ }
61
+ // Remove existing provider with same name
62
+ config.Providers = config.Providers.filter(p => p.name !== name);
63
+ config.Providers.push({ name, ...providerConfig });
64
+ saveConfig(config);
65
+ }
66
+
67
+ /**
68
+ * Remove a provider by name
69
+ */
70
+ function removeProvider(name) {
71
+ const config = getConfig();
72
+ if (!Array.isArray(config.Providers)) return;
73
+ config.Providers = config.Providers.filter(p => p.name !== name);
74
+ saveConfig(config);
75
+ }
76
+
77
+ /**
78
+ * Return Router rules object or {}
79
+ */
80
+ function getRouterRules() {
81
+ const config = getConfig();
82
+ return config.Router || {};
83
+ }
84
+
85
+ /**
86
+ * Set a single router rule (task -> providerModel string)
87
+ */
88
+ function setRouterRule(task, providerModel) {
89
+ const config = getConfig();
90
+ if (!config.Router) {
91
+ config.Router = {};
92
+ }
93
+ config.Router[task] = providerModel;
94
+ saveConfig(config);
95
+ }
96
+
97
+ /**
98
+ * Return environment variables needed to activate CCR proxy
99
+ */
100
+ function getActivationEnv() {
101
+ const config = getConfig();
102
+ return {
103
+ ANTHROPIC_BASE_URL: `http://127.0.0.1:${CCR_PORT}`,
104
+ ANTHROPIC_AUTH_TOKEN: config.APIKEY || '',
105
+ NO_PROXY: '127.0.0.1',
106
+ DISABLE_TELEMETRY: '1',
107
+ DISABLE_COST_WARNINGS: '1',
108
+ };
109
+ }
110
+
111
+ /**
112
+ * Check CCR installation and running status
113
+ */
114
+ function getStatus() {
115
+ let installed = false;
116
+ try {
117
+ execSync('which ccr', { stdio: 'pipe' });
118
+ installed = true;
119
+ } catch {
120
+ // not installed
121
+ }
122
+
123
+ let running = false;
124
+ try {
125
+ execSync(`lsof -i :${CCR_PORT}`, { stdio: 'pipe' });
126
+ running = true;
127
+ } catch {
128
+ // not running
129
+ }
130
+
131
+ const configExists = fs.existsSync(getConfigPath());
132
+
133
+ return { installed, running, configExists };
134
+ }
135
+
136
+ /**
137
+ * Get presets directory path
138
+ */
139
+ function getPresetsDir() {
140
+ const homeDir = process.env.HOME || '';
141
+ return path.join(homeDir, CCR_DIR_NAME, PRESET_DIR_NAME);
142
+ }
143
+
144
+ /**
145
+ * List saved presets (names without .json extension)
146
+ */
147
+ function listPresets() {
148
+ const presetsDir = getPresetsDir();
149
+ if (!fs.existsSync(presetsDir)) return [];
150
+ return fs.readdirSync(presetsDir)
151
+ .filter(f => f.endsWith('.json'))
152
+ .map(f => f.replace(/\.json$/, ''));
153
+ }
154
+
155
+ /**
156
+ * Snapshot current config to a named preset
157
+ */
158
+ function savePreset(name) {
159
+ const config = getConfig();
160
+ const presetsDir = getPresetsDir();
161
+ fs.mkdirSync(presetsDir, { recursive: true });
162
+ fs.writeFileSync(path.join(presetsDir, `${name}.json`), JSON.stringify(config, null, 2) + '\n');
163
+ }
164
+
165
+ /**
166
+ * Restore config from a named preset
167
+ */
168
+ function loadPreset(name) {
169
+ const presetPath = path.join(getPresetsDir(), `${name}.json`);
170
+ if (!fs.existsSync(presetPath)) {
171
+ throw new Error(`Preset "${name}" not found`);
172
+ }
173
+ const config = JSON.parse(fs.readFileSync(presetPath, 'utf8'));
174
+ saveConfig(config);
175
+ }
176
+
177
+ module.exports = {
178
+ getConfigPath,
179
+ getConfig,
180
+ saveConfig,
181
+ listProviders,
182
+ addProvider,
183
+ removeProvider,
184
+ getRouterRules,
185
+ setRouterRule,
186
+ getActivationEnv,
187
+ getStatus,
188
+ listPresets,
189
+ savePreset,
190
+ loadPreset,
191
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coder-config",
3
- "version": "0.53.3-beta",
3
+ "version": "0.53.5-beta",
4
4
  "description": "Configuration manager for AI coding tools - Claude Code, Gemini CLI, Codex CLI, Antigravity. Manage MCPs, rules, permissions, memory, and workstreams.",
5
5
  "author": "regression.io",
6
6
  "main": "config-loader.js",