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

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.ja-JP.md CHANGED
@@ -311,6 +311,7 @@ ocr review \
311
311
  | `--timeout` | — | `10` | 同時実行タスクのタイムアウト(分) |
312
312
  | `--audience` | — | `human` | `human`(進捗を表示)または`agent`(サマリーのみ) |
313
313
  | `--background` | `-b` | — | レビューのための任意の要件/ビジネスコンテキスト。`--commit`使用時に未指定の場合、コミットメッセージから自動取得 |
314
+ | `--model` | — | — | このレビューでLLMモデルを選択または上書き |
314
315
  | `--rule` | — | — | カスタムJSONレビュールールへのパス |
315
316
  | `--max-tools` | — | 組み込み値 | ファイルごとのツール呼び出しラウンドの上限。テンプレートのデフォルトより大きい場合のみ有効 |
316
317
  | `--max-git-procs` | — | 組み込み値 | gitサブプロセスの最大同時実行数 |
@@ -337,6 +338,10 @@ ocr review --from main --to my-feature --concurrency 4
337
338
  # 特定のコミットを詳細なJSON出力でレビュー
338
339
  ocr review --commit abc123 --format json --audience agent
339
340
 
341
+ # このレビューでモデルを選択またはオーバーライド
342
+ ocr review --model claude-opus-4-6
343
+ ocr review --commit abc123 --model claude-sonnet-4-6
344
+
340
345
  # 要件コンテキストを提供してより的確なレビューを実施
341
346
  ocr review --background "ログインAPIにレート制限を追加"
342
347
 
@@ -449,8 +454,9 @@ OCRは4層の優先度チェーンを使ってレビュールールを解決し
449
454
  | `providers.<name>.url` | string | プロバイダーのベースURLオーバーライド |
450
455
  | `providers.<name>.protocol` | string | `anthropic` \| `openai` |
451
456
  | `providers.<name>.model` | string | プロバイダーのモデル名 |
457
+ | `providers.<name>.models` | array | 対話的選択に使う任意のプロバイダーモデル一覧 |
452
458
  | `providers.<name>.auth_header` | string | `x-api-key` \| `authorization` |
453
- | `custom_providers.<name>.*` | — | `providers.<name>.*`と同じフィールド |
459
+ | `custom_providers.<name>.*` | — | 任意の`models`を含む`providers.<name>.*`と同じフィールド |
454
460
  | `llm.url` | string | `https://api.openai.com/v1/chat/completions` |
455
461
  | `llm.auth_token` | string | `sk-xxxxxxx` |
456
462
  | `llm.auth_header` | string | Anthropicのみ:`x-api-key` \| `authorization` |
package/README.ko-KR.md CHANGED
@@ -311,6 +311,7 @@ ocr review \
311
311
  | `--timeout` | - | `10` | 동시 task timeout(분) |
312
312
  | `--audience` | - | `human` | `human`(progress 표시) 또는 `agent`(summary only) |
313
313
  | `--background` | `-b` | - | 리뷰를 위한 선택적 요구사항/비즈니스 컨텍스트. `--commit` 사용 시 미지정이면 commit message에서 자동 추출 |
314
+ | `--model` | - | - | 이번 리뷰에서 LLM model 선택 또는 override |
314
315
  | `--rule` | - | - | custom JSON review rules 경로 |
315
316
  | `--max-tools` | - | built-in | 파일별 최대 tool call round. template default보다 클 때만 적용 |
316
317
  | `--max-git-procs` | - | built-in | 최대 동시 git subprocess 수 |
@@ -337,6 +338,10 @@ ocr review --from main --to my-feature --concurrency 4
337
338
  # 특정 commit을 verbose JSON output으로 리뷰
338
339
  ocr review --commit abc123 --format json --audience agent
339
340
 
341
+ # 이번 리뷰에서 model 선택 또는 override
342
+ ocr review --model claude-opus-4-6
343
+ ocr review --commit abc123 --model claude-sonnet-4-6
344
+
340
345
  # 요구사항 컨텍스트를 제공하여 더 정확한 리뷰 수행
341
346
  ocr review --background "로그인 API에 rate limiting 추가"
342
347
 
@@ -407,8 +412,9 @@ Config file: `~/.opencodereview/config.json`
407
412
  | `providers.<name>.url` | string | Provider base URL override |
408
413
  | `providers.<name>.protocol` | string | `anthropic` \| `openai` |
409
414
  | `providers.<name>.model` | string | Provider의 model 이름 |
415
+ | `providers.<name>.models` | array | 대화형 선택에 사용할 optional provider model 목록 |
410
416
  | `providers.<name>.auth_header` | string | `x-api-key` \| `authorization` |
411
- | `custom_providers.<name>.*` | — | `providers.<name>.*`과 동일한 필드 |
417
+ | `custom_providers.<name>.*` | — | optional `models`를 포함한 `providers.<name>.*`과 동일한 필드 |
412
418
  | `llm.url` | string | `https://api.openai.com/v1/chat/completions` |
413
419
  | `llm.auth_token` | string | `sk-xxxxxxx` |
414
420
  | `llm.auth_header` | string | Anthropic only: `x-api-key` \| `authorization` |
package/README.md CHANGED
@@ -313,6 +313,7 @@ See the [`examples/`](./examples/) directory for integration examples:
313
313
  | `--timeout` | — | `10` | Concurrent task timeout in minutes |
314
314
  | `--audience` | — | `human` | `human` (show progress) or `agent` (summary only) |
315
315
  | `--background` | `-b` | — | Optional requirement/business context for the review; auto-filled from commit message when using `--commit` |
316
+ | `--model` | — | — | Select or override the LLM model for this review |
316
317
  | `--rule` | — | — | Path to custom JSON review rules |
317
318
  | `--max-tools` | — | built-in | Max tool call rounds per file; only takes effect when greater than template default |
318
319
  | `--max-git-procs` | — | built-in | Max concurrent git subprocesses |
@@ -339,6 +340,10 @@ ocr review --from main --to my-feature --concurrency 4
339
340
  # Review a specific commit with verbose JSON output
340
341
  ocr review --commit abc123 --format json --audience agent
341
342
 
343
+ # Select or override model for this review
344
+ ocr review --model claude-opus-4-6
345
+ ocr review --commit abc123 --model claude-sonnet-4-6
346
+
342
347
  # Provide requirement context for more targeted review
343
348
  ocr review --background "Adding rate limiting to the login API"
344
349
 
@@ -451,8 +456,9 @@ Config file: `~/.opencodereview/config.json`
451
456
  | `providers.<name>.url` | string | Provider base URL override |
452
457
  | `providers.<name>.protocol` | string | `anthropic` \| `openai` |
453
458
  | `providers.<name>.model` | string | Model name for the provider |
459
+ | `providers.<name>.models` | array | Optional provider model list for interactive selection |
454
460
  | `providers.<name>.auth_header` | string | `x-api-key` \| `authorization` |
455
- | `custom_providers.<name>.*` | — | Same fields as `providers.<name>.*` |
461
+ | `custom_providers.<name>.*` | — | Same fields as `providers.<name>.*`, including optional `models` |
456
462
  | `llm.url` | string | `https://api.openai.com/v1/chat/completions` |
457
463
  | `llm.auth_token` | string | `sk-xxxxxxx` |
458
464
  | `llm.auth_header` | string | Anthropic only: `x-api-key` \| `authorization` |
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
 
@@ -299,6 +313,7 @@ ocr review \
299
313
  | `--timeout` | — | `10` | Таймаут конкурентной задачи в минутах |
300
314
  | `--audience` | — | `human` | `human` (показывать прогресс) или `agent` (только сводка) |
301
315
  | `--background` | `-b` | — | Необязательный контекст требований/бизнес-логики для ревью; при `--commit` автоматически заполняется из сообщения коммита |
316
+ | `--model` | — | — | Выбрать или переопределить LLM-модель для этого ревью |
302
317
  | `--rule` | — | — | Путь к пользовательским JSON-правилам ревью |
303
318
  | `--max-tools` | — | встроенное | Максимум раундов вызова инструментов на файл; действует, только если больше значения шаблона по умолчанию |
304
319
  | `--max-git-procs` | — | встроенное | Максимум одновременных git-подпроцессов |
@@ -307,6 +322,11 @@ ocr review \
307
322
  ## Примеры
308
323
 
309
324
  ```bash
325
+ # Интерактивная настройка провайдера и модели
326
+ ocr config provider
327
+ ocr config model
328
+ ocr llm providers
329
+
310
330
  # Показать, какие файлы попадут в ревью (без вызовов LLM)
311
331
  ocr review --preview
312
332
  ocr review -c abc123 -p
@@ -320,6 +340,10 @@ ocr review --from main --to my-feature --concurrency 4
320
340
  # Ревью конкретного коммита с подробным JSON-выводом
321
341
  ocr review --commit abc123 --format json --audience agent
322
342
 
343
+ # Выбрать или переопределить модель для этого ревью
344
+ ocr review --model claude-opus-4-6
345
+ ocr review --commit abc123 --model claude-sonnet-4-6
346
+
323
347
  # Передать контекст требований для более прицельного ревью
324
348
  ocr review --background "Добавляем rate limiting в API логина"
325
349
 
@@ -427,6 +451,14 @@ OCR разрешает правила ревью по цепочке приор
427
451
 
428
452
  | Ключ | Тип | Пример |
429
453
  |------|-----|--------|
454
+ | `provider` | string | `anthropic` \| `openai` \| `dashscope` \| `deepseek` \| `z-ai` |
455
+ | `providers.<name>.api_key` | string | API-ключ провайдера |
456
+ | `providers.<name>.url` | string | Переопределение base URL провайдера |
457
+ | `providers.<name>.protocol` | string | `anthropic` \| `openai` |
458
+ | `providers.<name>.model` | string | Имя модели провайдера |
459
+ | `providers.<name>.models` | array | Необязательный список моделей для интерактивного выбора |
460
+ | `providers.<name>.auth_header` | string | `x-api-key` \| `authorization` |
461
+ | `custom_providers.<name>.*` | — | Те же поля, что и `providers.<name>.*`, включая необязательное `models` |
430
462
  | `llm.url` | string | `https://api.openai.com/v1/chat/completions` |
431
463
  | `llm.auth_token` | string | `sk-xxxxxxx` |
432
464
  | `llm.auth_header` | string | Только для Anthropic: `x-api-key` \| `authorization` |
package/README.zh-CN.md CHANGED
@@ -311,6 +311,7 @@ ocr review \
311
311
  | `--timeout` | — | `10` | 并发任务超时时间(分钟) |
312
312
  | `--audience` | — | `human` | `human`(显示进度)或 `agent`(仅输出摘要) |
313
313
  | `--background` | `-b` | — | 可选的需求/业务背景信息;使用 `--commit` 时如未指定则自动从 commit message 中提取 |
314
+ | `--model` | — | — | 为本次审查选择或覆盖 LLM 模型 |
314
315
  | `--rule` | — | — | 自定义 JSON 审查规则路径 |
315
316
  | `--max-tools` | — | 内置默认 | 每个文件的最大工具调用轮次;仅在大于模板默认值时生效 |
316
317
  | `--max-git-procs` | — | 内置默认 | 最大并发 git 子进程数 |
@@ -337,6 +338,10 @@ ocr review --from main --to my-feature --concurrency 4
337
338
  # 审查特定提交并以 JSON 格式输出详细信息
338
339
  ocr review --commit abc123 --format json --audience agent
339
340
 
341
+ # 为本次审查选择或覆盖模型
342
+ ocr review --model claude-opus-4-6
343
+ ocr review --commit abc123 --model claude-sonnet-4-6
344
+
340
345
  # 提供需求背景以获得更有针对性的审查
341
346
  ocr review --background "为登录 API 添加限流"
342
347
 
@@ -439,8 +444,9 @@ OCR 通过四层优先级链解析评审规则。每层采用首次匹配原则
439
444
  | `providers.<name>.url` | string | 供应商 Base URL 覆盖 |
440
445
  | `providers.<name>.protocol` | string | `anthropic` \| `openai` |
441
446
  | `providers.<name>.model` | string | 供应商模型名称 |
447
+ | `providers.<name>.models` | array | 用于交互式选择的可选供应商模型列表 |
442
448
  | `providers.<name>.auth_header` | string | `x-api-key` \| `authorization` |
443
- | `custom_providers.<name>.*` | — | 与 `providers.<name>.*` 相同的字段 |
449
+ | `custom_providers.<name>.*` | — | 与 `providers.<name>.*` 相同的字段,包括可选的 `models` |
444
450
  | `llm.url` | string | `https://api.openai.com/v1/chat/completions` |
445
451
  | `llm.auth_token` | string | `sk-xxxxxxx` |
446
452
  | `llm.auth_header` | string | 仅 Anthropic:`x-api-key` \| `authorization` |
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.14",
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