@alibaba-group/open-code-review 1.3.12 → 1.3.13

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/README.ru-RU.md CHANGED
@@ -113,18 +113,22 @@ sudo cp dist/opencodereview /usr/local/bin/ocr
113
113
 
114
114
  **Перед запуском ревью необходимо настроить LLM.**
115
115
 
116
+ **Вариант A: интерактивная настройка (рекомендуется)**
117
+
118
+ ```bash
119
+ ocr config provider # Выбрать встроенного провайдера или добавить пользовательский
120
+ ocr config model # Выбрать модель для активного провайдера
121
+ ```
122
+
123
+ ![Provider setup](imgs/providers.jpg)
124
+
125
+ **Вариант B: ручная настройка**
126
+
116
127
  ```bash
117
- # Вариант A: настройка через CLI
118
128
  ocr config set llm.url https://api.anthropic.com/v1/messages
119
129
  ocr config set llm.auth_token your-api-key-here
120
130
  ocr config set llm.model claude-opus-4-6
121
131
  ocr config set llm.use_anthropic true
122
-
123
- # Вариант B: переменные окружения (наивысший приоритет)
124
- export OCR_LLM_URL=https://api.anthropic.com/v1/messages
125
- export OCR_LLM_TOKEN=your-api-key-here
126
- export OCR_LLM_MODEL=claude-opus-4-6
127
- export OCR_USE_ANTHROPIC=true
128
132
  ```
129
133
 
130
134
  Конфигурация хранится в `~/.opencodereview/config.json`.
@@ -133,12 +137,19 @@ export OCR_USE_ANTHROPIC=true
133
137
 
134
138
  ```bash
135
139
  ocr config set llm.auth_header x-api-key
136
- # или
137
- export OCR_LLM_AUTH_HEADER=x-api-key
138
140
  ```
139
141
 
140
142
  Поддерживаемые значения: `x-api-key`, `authorization` (алиас: `bearer`). Прочие значения отклоняются с ошибкой.
141
143
 
144
+ **Вариант C: переменные окружения (наивысший приоритет)**
145
+
146
+ ```bash
147
+ export OCR_LLM_URL=https://api.anthropic.com/v1/messages
148
+ export OCR_LLM_TOKEN=your-api-key-here
149
+ export OCR_LLM_MODEL=claude-opus-4-6
150
+ export OCR_USE_ANTHROPIC=true
151
+ ```
152
+
142
153
  Инструмент также совместим с переменными окружения Claude Code (`ANTHROPIC_BASE_URL`, `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`) и разбирает `~/.zshrc` / `~/.bashrc` в поисках соответствующих export'ов.
143
154
 
144
155
  > **Примечание для пользователей CC-Switch**: если вы используете [CC-Switch](https://github.com/farion1231/cc-switch) с включённым [routing service](https://www.ccswitch.io/en/docs?section=proxy&item=service), можно указать в `llm.url` адрес прокси CC-Switch без дополнительной настройки:
@@ -280,8 +291,11 @@ ocr review \
280
291
  |---------|-------|----------|
281
292
  | `ocr review` | `ocr r` | Запустить код-ревью |
282
293
  | `ocr rules check <file>` | — | Показать, какое правило ревью применяется к пути файла |
294
+ | `ocr config provider` | — | Интерактивная настройка провайдера (встроенный, пользовательский или ручной) |
295
+ | `ocr config model` | — | Интерактивный выбор модели для активного провайдера |
283
296
  | `ocr config set <key> <value>` | — | Установить значения конфигурации |
284
297
  | `ocr llm test` | — | Проверить подключение к LLM |
298
+ | `ocr llm providers` | — | Показать список встроенных LLM-провайдеров |
285
299
  | `ocr viewer` | `ocr v` | Запустить WebUI-просмотрщик сессий на `localhost:5483` |
286
300
  | `ocr version` | — | Показать информацию о версии |
287
301
 
@@ -307,6 +321,11 @@ ocr review \
307
321
  ## Примеры
308
322
 
309
323
  ```bash
324
+ # Интерактивная настройка провайдера и модели
325
+ ocr config provider
326
+ ocr config model
327
+ ocr llm providers
328
+
310
329
  # Показать, какие файлы попадут в ревью (без вызовов LLM)
311
330
  ocr review --preview
312
331
  ocr review -c abc123 -p
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alibaba-group/open-code-review",
3
- "version": "1.3.12",
3
+ "version": "1.3.13",
4
4
  "description": "OpenCodeReview CLI — AI-powered code review tool",
5
5
  "bin": {
6
6
  "ocr": "bin/ocr.js"
@@ -189,37 +189,46 @@ async function main() {
189
189
  }
190
190
 
191
191
  if (config.checksumPattern) {
192
+ const checksumUrl = buildUrl(config.checksumPattern, vars);
193
+ info("Verifying checksum...");
194
+ let shaContent;
192
195
  try {
193
- const checksumUrl = buildUrl(config.checksumPattern, vars);
194
- info("Verifying checksum...");
195
- const shaContent = await downloadText(checksumUrl);
196
- const actualSha = await computeChecksum(binaryDest);
197
-
198
- let verified = false;
199
- for (const line of shaContent.split("\n")) {
200
- const trimmed = line.trim();
201
- if (trimmed.includes(`-${os}-${arch}`)) {
202
- const expectedSha = trimmed.split(/\s+/)[0].toLowerCase();
203
- if (expectedSha) {
204
- if (actualSha !== expectedSha) {
205
- throw new Error(
206
- `Checksum mismatch! Expected: ${expectedSha}, Got: ${actualSha}`
207
- );
208
- }
209
- info("Checksum verified.");
210
- verified = true;
211
- break;
196
+ shaContent = await downloadText(checksumUrl);
197
+ } catch (e) {
198
+ try { fs.unlinkSync(binaryDest); } catch (_) {}
199
+ throw new Error(`Failed to download checksum from ${checksumUrl}: ${e.message}`);
200
+ }
201
+ let actualSha;
202
+ try {
203
+ actualSha = await computeChecksum(binaryDest);
204
+ } catch (e) {
205
+ try { fs.unlinkSync(binaryDest); } catch (_) {}
206
+ throw new Error(`Failed to compute checksum for ${binaryDest}: ${e.message}`);
207
+ }
208
+
209
+ let verified = false;
210
+ for (const line of shaContent.split("\n")) {
211
+ const trimmed = line.trim();
212
+ if (trimmed.includes(`-${os}-${arch}`)) {
213
+ const expectedSha = trimmed.split(/\s+/)[0].toLowerCase();
214
+ if (expectedSha) {
215
+ if (actualSha !== expectedSha) {
216
+ try { fs.unlinkSync(binaryDest); } catch (_) {}
217
+ throw new Error(
218
+ `Checksum mismatch! Expected: ${expectedSha}, Got: ${actualSha}`
219
+ );
212
220
  }
221
+ info("Checksum verified.");
222
+ verified = true;
223
+ break;
213
224
  }
214
225
  }
215
- if (!verified) {
216
- warn("No matching checksum entry found; skipping verification.");
217
- }
218
- } catch (e) {
219
- if (e.message.includes("mismatch")) {
220
- throw e;
221
- }
222
- warn(`Could not verify checksum: ${e.message}`);
226
+ }
227
+ if (!verified) {
228
+ try { fs.unlinkSync(binaryDest); } catch (_) {}
229
+ throw new Error(
230
+ `No matching checksum entry for ${os}-${arch} in ${checksumUrl}`
231
+ );
223
232
  }
224
233
  }
225
234
 
package/scripts/update.js CHANGED
@@ -4,7 +4,6 @@
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  const os = require("os");
7
- const http = require("http");
8
7
  const https = require("https");
9
8
  const { spawnSync } = require("child_process");
10
9
 
@@ -85,14 +84,14 @@ function fetchLatestVersion(pkg) {
85
84
  if (!pkgName) return Promise.resolve(null);
86
85
  const encodedName = pkgName.replace(/\//g, "%2F");
87
86
  const url = `${registry.replace(/\/$/, "")}/${encodedName}/latest`;
88
- const client = url.startsWith("https") ? https : http;
87
+ if (!url.startsWith("https://")) return Promise.resolve(null);
89
88
 
90
89
  return new Promise((resolve) => {
91
90
  const options = {
92
91
  headers: { "User-Agent": "ocr-updater", Accept: "application/json" },
93
92
  timeout: 15000,
94
93
  };
95
- const req = client
94
+ const req = https
96
95
  .get(url, options, (res) => {
97
96
  if (res.statusCode !== 200) {
98
97
  res.resume();
@@ -173,26 +172,38 @@ async function main() {
173
172
  }
174
173
 
175
174
  if (config.checksumPattern) {
175
+ const checksumUrl = buildUrl(config.checksumPattern, vars);
176
+ let shaContent;
176
177
  try {
177
- const checksumUrl = buildUrl(config.checksumPattern, vars);
178
- const shaContent = await downloadText(checksumUrl);
179
- const actualSha = await computeChecksum(tempPath);
180
-
181
- let verified = false;
182
- for (const line of shaContent.split("\n")) {
183
- const trimmed = line.trim();
184
- if (trimmed.includes(`-${platform}-${arch}`)) {
185
- const expectedSha = trimmed.split(/\s+/)[0].toLowerCase();
186
- if (expectedSha && actualSha !== expectedSha) {
187
- fs.unlinkSync(tempPath);
188
- return;
189
- }
190
- verified = true;
191
- break;
178
+ shaContent = await downloadText(checksumUrl);
179
+ } catch (_) {
180
+ fs.unlinkSync(tempPath);
181
+ return;
182
+ }
183
+ let actualSha;
184
+ try {
185
+ actualSha = await computeChecksum(tempPath);
186
+ } catch (_) {
187
+ fs.unlinkSync(tempPath);
188
+ return;
189
+ }
190
+
191
+ let verified = false;
192
+ for (const line of shaContent.split("\n")) {
193
+ const trimmed = line.trim();
194
+ if (trimmed.includes(`-${platform}-${arch}`)) {
195
+ const expectedSha = trimmed.split(/\s+/)[0].toLowerCase();
196
+ if (expectedSha && actualSha !== expectedSha) {
197
+ fs.unlinkSync(tempPath);
198
+ return;
192
199
  }
200
+ verified = true;
201
+ break;
193
202
  }
194
- } catch (_) {
195
- // checksum fetch failed, continue with the download
203
+ }
204
+ if (!verified) {
205
+ fs.unlinkSync(tempPath);
206
+ return;
196
207
  }
197
208
  }
198
209