coderev-cli 1.0.25 → 1.1.0

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.
@@ -1,6 +1,6 @@
1
- const { describe, it } = require('node:test');
1
+ const { describe, it, beforeEach } = require('node:test');
2
2
  const assert = require('assert');
3
- const { BUILTIN_TEMPLATES, resolveTemplate, listTemplates, getTemplate } = require('./models');
3
+ const { BUILTIN_TEMPLATES, resolveTemplate, listTemplates, getTemplate, autoDetectProvider, AUTO_DETECT_PRIORITY } = require('./models');
4
4
 
5
5
  describe('models.js', () => {
6
6
  it('should have all 11 built-in templates', () => {
@@ -78,3 +78,140 @@ describe('models.js', () => {
78
78
  assert.strictEqual(t.model, 'deepseek-reasoner');
79
79
  });
80
80
  });
81
+
82
+ describe('autoDetectProvider', () => {
83
+ const savedEnv = {};
84
+
85
+ beforeEach(() => {
86
+ // Save and clear all known API key env vars
87
+ const allKeys = Object.values(BUILTIN_TEMPLATES).map(t => t.apiKeyEnv);
88
+ for (const key of [...new Set(allKeys)]) {
89
+ savedEnv[key] = process.env[key];
90
+ delete process.env[key];
91
+ }
92
+ });
93
+
94
+ // Restore env vars after each test
95
+ const { afterEach } = require('node:test');
96
+ afterEach(() => {
97
+ for (const [key, val] of Object.entries(savedEnv)) {
98
+ if (val !== undefined) {
99
+ process.env[key] = val;
100
+ } else {
101
+ delete process.env[key];
102
+ }
103
+ }
104
+ });
105
+
106
+ it('should return null when no API keys are set', () => {
107
+ const result = autoDetectProvider();
108
+ assert.strictEqual(result, null);
109
+ });
110
+
111
+ it('should detect a single available provider', () => {
112
+ process.env.DEEPSEEK_API_KEY = 'sk-test-deepseek-key';
113
+ const result = autoDetectProvider();
114
+ assert.ok(result);
115
+ assert.strictEqual(result.chosen, 'deepseek');
116
+ assert.ok(result.allDetected.includes('deepseek'));
117
+ assert.ok(result.allDetected.includes('deepseek-r1'));
118
+ assert.strictEqual(result.template.model, 'deepseek-chat');
119
+ });
120
+
121
+ it('should prioritize deepseek over openai when both are available', () => {
122
+ process.env.DEEPSEEK_API_KEY = 'sk-deepseek';
123
+ process.env.OPENAI_API_KEY = 'sk-openai';
124
+ const result = autoDetectProvider();
125
+ assert.ok(result);
126
+ assert.strictEqual(result.chosen, 'deepseek');
127
+ assert.ok(result.allDetected.includes('deepseek'));
128
+ assert.ok(result.allDetected.includes('openai'));
129
+ });
130
+
131
+ it('should detect qwen as fallback when deepseek is not available', () => {
132
+ process.env.DASHSCOPE_API_KEY = 'sk-qwen';
133
+ const result = autoDetectProvider();
134
+ assert.ok(result);
135
+ assert.strictEqual(result.chosen, 'qwen-coder');
136
+ assert.ok(result.allDetected.includes('qwen-coder'));
137
+ assert.ok(result.allDetected.includes('qwen'));
138
+ });
139
+
140
+ it('should detect openai when deepseek and qwen are not available', () => {
141
+ process.env.OPENAI_API_KEY = 'sk-openai-test';
142
+ const result = autoDetectProvider();
143
+ assert.ok(result);
144
+ assert.strictEqual(result.chosen, 'openai');
145
+ assert.ok(result.allDetected.includes('openai'));
146
+ assert.ok(result.allDetected.includes('openai-o3'));
147
+ });
148
+
149
+ it('should detect claude when ANTHROPIC_API_KEY is set', () => {
150
+ process.env.ANTHROPIC_API_KEY = 'sk-ant-test';
151
+ const result = autoDetectProvider();
152
+ assert.ok(result);
153
+ assert.strictEqual(result.chosen, 'claude');
154
+ });
155
+
156
+ it('should detect gemini when GEMINI_API_KEY is set', () => {
157
+ process.env.GEMINI_API_KEY = 'test-gemini-key';
158
+ const result = autoDetectProvider();
159
+ assert.ok(result);
160
+ assert.strictEqual(result.chosen, 'gemini');
161
+ });
162
+
163
+ it('should detect zhipu when ZHIPU_API_KEY is set', () => {
164
+ process.env.ZHIPU_API_KEY = 'test-zhipu-key';
165
+ const result = autoDetectProvider();
166
+ assert.ok(result);
167
+ assert.strictEqual(result.chosen, 'zhipu');
168
+ });
169
+
170
+ it('should detect moonshot when MOONSHOT_API_KEY is set', () => {
171
+ process.env.MOONSHOT_API_KEY = 'test-moonshot-key';
172
+ const result = autoDetectProvider();
173
+ assert.ok(result);
174
+ assert.strictEqual(result.chosen, 'moonshot');
175
+ });
176
+
177
+ it('should detect codestral when MISTRAL_API_KEY is set', () => {
178
+ process.env.MISTRAL_API_KEY = 'test-mistral-key';
179
+ const result = autoDetectProvider();
180
+ assert.ok(result);
181
+ assert.strictEqual(result.chosen, 'codestral');
182
+ });
183
+
184
+ it('should return all detected providers in allDetected', () => {
185
+ process.env.DEEPSEEK_API_KEY = 'sk-ds';
186
+ process.env.OPENAI_API_KEY = 'sk-oa';
187
+ process.env.ANTHROPIC_API_KEY = 'sk-ant';
188
+ const result = autoDetectProvider();
189
+ assert.ok(result);
190
+ assert.strictEqual(result.chosen, 'deepseek');
191
+ assert.ok(result.allDetected.includes('deepseek'));
192
+ assert.ok(result.allDetected.includes('openai'));
193
+ assert.ok(result.allDetected.includes('claude'));
194
+ });
195
+
196
+ it('AUTO_DETECT_PRIORITY should include all standard provider names', () => {
197
+ const allNames = Object.keys(BUILTIN_TEMPLATES);
198
+ const standardProviders = allNames.filter(n => {
199
+ const t = BUILTIN_TEMPLATES[n];
200
+ // Each unique apiKeyEnv should appear at least once
201
+ return true;
202
+ });
203
+ // Priority should cover at least all standard-tier templates
204
+ const standardKeys = [...new Set(
205
+ allNames
206
+ .filter(n => BUILTIN_TEMPLATES[n].tier !== 'reasoning')
207
+ .map(n => BUILTIN_TEMPLATES[n].apiKeyEnv)
208
+ )];
209
+ // Check that priority covers each unique key
210
+ const priorityKeys = [...new Set(
211
+ AUTO_DETECT_PRIORITY.map(n => BUILTIN_TEMPLATES[n]?.apiKeyEnv).filter(Boolean)
212
+ )];
213
+ for (const key of standardKeys) {
214
+ assert.ok(priorityKeys.includes(key), `Priority should include provider with key: ${key}`);
215
+ }
216
+ });
217
+ });