Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions pages/src/content/docs/en/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,47 @@ ocr config set custom_providers.my-gateway.model llama-3-70b
ocr config set custom_providers.my-gateway.api_key "$MY_API_KEY"
```

A local model served by Ollama is just a custom provider pointing at the
local OpenAI-compatible endpoint:

```bash
ocr config set provider ollama
ocr config set custom_providers.ollama.url http://127.0.0.1:11434/v1
ocr config set custom_providers.ollama.protocol openai
ocr config set custom_providers.ollama.model qwen3:32b
ocr config set custom_providers.ollama.api_key ollama
```

Ollama ignores the API key, but custom providers require a non-empty
`api_key` (there is no environment-variable fallback for them), so set
any placeholder value. The model itself must support native tool
calling — see
["No tool calls parsed" (local models / Ollama)](../faq/#no-tool-calls-parsed-local-models-ollama)
in the FAQ before picking one.

### Timeouts

Each LLM request has an HTTP timeout, defaulting to **300 seconds**.
Slow local models (or large files) can need more. Three knobs, in
increasing scope:

- `providers.<name>.timeout_sec` / `custom_providers.<name>.timeout_sec`
— per-provider, in seconds.
- `llm.timeout_sec` — for the legacy `llm` section, in seconds.
- `OCR_LLM_TIMEOUT` environment variable — integer seconds; overrides
the config-file value for every resolution path.

The `timeout_sec` keys are not supported by `ocr config set` — edit
`~/.opencodereview/config.json` directly:

```json
{
"custom_providers": {
"ollama": { "url": "http://127.0.0.1:11434/v1", "protocol": "openai", "timeout_sec": 900 }
}
}
```

### Verify connectivity

```bash
Expand Down
39 changes: 39 additions & 0 deletions pages/src/content/docs/en/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,42 @@ OpenAI use different auth headers and different URL shapes — make sure
against the current directory. If you're not inside a Git working tree,
it exits early. Either `cd` into a repo, or pass `--repo /path/to/repo`.

### "No tool calls parsed" (local models / Ollama)

```
[ocr] No tool calls parsed for src/foo.go, retrying...
[ocr] Max tool requests reached for src/foo.go.
```

If every review loops through `No tool calls parsed` retries and ends
with "Max tool requests reached" and zero comments, the model — not the
config — is the problem. OCR drives the review entirely through tool
calls, so **the model must support native tool calling (function
calling)**. A model that merely *narrates* tool calls in its text
output (or inside `<think>` blocks) can never work with OCR, no matter
how the prompt is tuned — `deepseek-r1` is a common example. Models
with native tool support, such as `qwen3`, work fine. For Ollama, pick
from the models tagged with tools support:
<https://ollama.com/search?c=tools>.

Verify a local model directly, without OCR in the loop:

```bash
curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "qwen3:32b",
"messages": [{"role": "user", "content": "The code below has a bug, use the report_bug tool to report it.\n\nfunc add(a, b int) int {\n return a - b\n}"}],
"tools": [{"type": "function", "function": {"name": "report_bug", "description": "Report a bug in the code",
"parameters": {"type": "object", "properties": {"line": {"type": "integer"}, "description": {"type": "string"}}, "required": ["description"]}}}]
}'
```

Pass: the response contains a structured `tool_calls` array naming
`report_bug`. Fail: the "call" appears as text inside `content`.

If the model *does* support tools but responses are slow on local
hardware, raise the LLM timeout instead — see
[Timeouts](../configuration/#timeouts).

## Filtering & rules

### My file isn't being reviewed
Expand Down Expand Up @@ -173,6 +209,9 @@ usually one of:
`--max-tools 40` for more, `--max-tools 15` for fewer). Values 1–9
are clamped up to 10; `0` (the default) uses the template default of
30.
- The model does not support native tool calling at all (common with
local models) — see
["No tool calls parsed" (local models / Ollama)](#no-tool-calls-parsed-local-models-ollama).

### Some sub-agents fail; the run still exits 0

Expand Down
41 changes: 41 additions & 0 deletions pages/src/content/docs/ja/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,47 @@ ocr config set custom_providers.my-gateway.model llama-3-70b
ocr config set custom_providers.my-gateway.api_key "$MY_API_KEY"
```

Ollama で動かすローカルモデルは、ローカルの OpenAI 互換エンドポイントを
指すカスタム provider にすぎません。

```bash
ocr config set provider ollama
ocr config set custom_providers.ollama.url http://127.0.0.1:11434/v1
ocr config set custom_providers.ollama.protocol openai
ocr config set custom_providers.ollama.model qwen3:32b
ocr config set custom_providers.ollama.api_key ollama
```

Ollama は API key を無視しますが、カスタム provider は空でない `api_key` を
必要とします(カスタム provider には環境変数のフォールバックがありません)。
そのため任意のプレースホルダー値を設定してください。モデル自体はネイティブな
ツール呼び出しをサポートしている必要があります——選ぶ前に FAQ の
["No tool calls parsed"(ローカルモデル / Ollama)](../faq/#no-tool-calls-parsed-ollama)を
参照してください。

### タイムアウト(Timeouts)

各 LLM リクエストには HTTP タイムアウトがあり、デフォルトは **300 秒**です。
遅いローカルモデル(あるいは大きなファイル)では、それ以上の時間が必要になることがあります。
スコープの狭い順に、3 つの設定があります。

- `providers.<name>.timeout_sec` / `custom_providers.<name>.timeout_sec`
——provider ごと、秒単位。
- `llm.timeout_sec`——レガシーな `llm` セクション用、秒単位。
- `OCR_LLM_TIMEOUT` 環境変数——整数(秒単位)。すべての解決パスで設定ファイルの
値を上書きします。

`timeout_sec` key は `ocr config set` ではサポートされていません——
`~/.opencodereview/config.json` を直接編集してください。

```json
{
"custom_providers": {
"ollama": { "url": "http://127.0.0.1:11434/v1", "protocol": "openai", "timeout_sec": 900 }
}
}
```

### 接続性を検証する

```bash
Expand Down
36 changes: 36 additions & 0 deletions pages/src/content/docs/ja/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,39 @@ OpenAI は異なる auth header と URL フォーマットを使います——`
`git ls-files`)を実行します。Git ワークツリー内にいない場合は、早期に終了します。リポジトリに
`cd` するか、`--repo /path/to/repo` を渡してください。

### "No tool calls parsed"(ローカルモデル / Ollama)

```
[ocr] No tool calls parsed for src/foo.go, retrying...
[ocr] Max tool requests reached for src/foo.go.
```

すべてのレビューが `No tool calls parsed` のリトライをループし、"Max tool requests
reached" とコメント 0 件で終わる場合、問題は設定ではなくモデルにあります。OCR はレビュー全体を
ツール呼び出しで駆動するため、**モデルはネイティブなツール呼び出し(function calling)を
サポートしている必要があります**。ツール呼び出しをテキスト出力(あるいは `<think>` ブロック内)で
*語るだけ*のモデルは、prompt をどう調整しても OCR では決して動作しません——`deepseek-r1` は
よくある例です。`qwen3` のようなネイティブなツールサポートを持つモデルは問題なく動作します。
Ollama の場合は、tools サポートのタグが付いたモデルから選んでください:
<https://ollama.com/search?c=tools>。

OCR を介さずに、ローカルモデルを直接検証するには:

```bash
curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "qwen3:32b",
"messages": [{"role": "user", "content": "The code below has a bug, use the report_bug tool to report it.\n\nfunc add(a, b int) int {\n return a - b\n}"}],
"tools": [{"type": "function", "function": {"name": "report_bug", "description": "Report a bug in the code",
"parameters": {"type": "object", "properties": {"line": {"type": "integer"}, "description": {"type": "string"}}, "required": ["description"]}}}]
}'
```

合格: 応答に `report_bug` を指す構造化された `tool_calls` 配列が含まれる。不合格: 「呼び出し」が
`content` 内のテキストとして現れる。

モデルがツールを*サポートしている*のに、ローカルハードウェアで応答が遅い場合は、代わりに
LLM タイムアウトを引き上げてください——[タイムアウト](../configuration/#timeouts)を参照。

## フィルタリングとルール

### ファイルがレビューされない
Expand Down Expand Up @@ -163,6 +196,9 @@ JSON モードでは `warnings` にも表示されます。
- ファイルが本当に大きい、あるいはコンテキストが重く、30 回では足りない。`--max-tools <n>` で
上げるか下げるか調整してください(例: `--max-tools 40` でより多く、`--max-tools 15` でより少なく)。
1〜9 は 10 に引き上げられます。`0`(デフォルト)はテンプレートのデフォルト 30 を使います。
- モデルがネイティブなツール呼び出しを全くサポートしていない(ローカルモデルでよくある)——
["No tool calls parsed"(ローカルモデル / Ollama)](#no-tool-calls-parsed-ollama)を
参照してください。

### 一部のサブエージェントが失敗しても、実行は 0 で終了する

Expand Down
37 changes: 37 additions & 0 deletions pages/src/content/docs/zh/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,43 @@ ocr config set custom_providers.my-gateway.model llama-3-70b
ocr config set custom_providers.my-gateway.api_key "$MY_API_KEY"
```

用 Ollama 跑本地模型,就是一个指向本地 OpenAI 兼容端点的自定义 provider:

```bash
ocr config set provider ollama
ocr config set custom_providers.ollama.url http://127.0.0.1:11434/v1
ocr config set custom_providers.ollama.protocol openai
ocr config set custom_providers.ollama.model qwen3:32b
ocr config set custom_providers.ollama.api_key ollama
```

Ollama 会忽略 API key,但自定义 provider 要求非空的 `api_key`(自定义
provider 没有环境变量回退),所以设任意占位值即可。模型本身必须支持原生
工具调用——选型前请先看 FAQ 中的
["No tool calls parsed"(本地模型 / Ollama)](../faq/#no-tool-calls-parsed-本地模型-ollama)。

### 超时

每个 LLM 请求都有 HTTP 超时,默认 **300 秒**。慢的本地模型(或大文件)可能
需要更长的时间。三个配置项,作用域递增:

- `providers.<name>.timeout_sec` / `custom_providers.<name>.timeout_sec`
——per-provider,单位秒。
- `llm.timeout_sec`——用于旧版 `llm` 配置段,单位秒。
- `OCR_LLM_TIMEOUT` 环境变量——整数秒;对每条解析路径都覆盖配置文件里
的值。

`ocr config set` 不支持 `timeout_sec` key——直接编辑
`~/.opencodereview/config.json`:

```json
{
"custom_providers": {
"ollama": { "url": "http://127.0.0.1:11434/v1", "protocol": "openai", "timeout_sec": 900 }
}
}
```

### 验证连通性

```bash
Expand Down
34 changes: 34 additions & 0 deletions pages/src/content/docs/zh/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,38 @@ URL 格式——确保 `llm.use_anthropic` 与你指向的 URL 相匹配:
`ocr review` 对当前目录运行 `git diff`(以及对 untracked 文件的 `git ls-files`)。
若你不在 Git 工作树内,它会提前退出。要么 `cd` 进仓库,要么传 `--repo /path/to/repo`。

### "No tool calls parsed"(本地模型 / Ollama)

```
[ocr] No tool calls parsed for src/foo.go, retrying...
[ocr] Max tool requests reached for src/foo.go.
```

若每次评审都在 `No tool calls parsed` 重试中循环,最终以 "Max tool requests
reached" 结束且没有任何评论,问题出在模型——而非配置。OCR 完全通过工具调用驱动评审,
因此**模型必须支持原生工具调用(function calling)**。只在文本输出(或
`<think>` 块内)*叙述*工具调用的模型,无论怎么调 prompt 都永远无法与 OCR
配合使用——`deepseek-r1` 是常见例子。具备原生工具支持的模型(如 `qwen3`)则工作
正常。对 Ollama,请从带 tools 标签的模型中挑选:
<https://ollama.com/search?c=tools>。

绕开 OCR、直接验证本地模型:

```bash
curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "qwen3:32b",
"messages": [{"role": "user", "content": "The code below has a bug, use the report_bug tool to report it.\n\nfunc add(a, b int) int {\n return a - b\n}"}],
"tools": [{"type": "function", "function": {"name": "report_bug", "description": "Report a bug in the code",
"parameters": {"type": "object", "properties": {"line": {"type": "integer"}, "description": {"type": "string"}}, "required": ["description"]}}}]
}'
```

通过:响应包含指向 `report_bug` 的结构化 `tool_calls` 数组。失败:“调用”以
文本形式出现在 `content` 里。

若模型*确实*支持工具,只是在本地硬件上响应缓慢,请改为调高 LLM 超时——见
[超时](../configuration/#超时)。

## 过滤与规则

### 我的文件没被评审
Expand Down Expand Up @@ -150,6 +182,8 @@ diff 能从 plan 中受益。要为单次评审跳过它,用更小 diff 运行
- 文件确实大或上下文重,30 轮不够。用 `--max-tools <n>` 调高或调低
(如 `--max-tools 40` 更多,`--max-tools 15` 更少)。1–9 会被上调到 10;
`0`(默认)用模板默认 30。
- 模型完全不支持原生工具调用(本地模型常见)——见
["No tool calls parsed"(本地模型 / Ollama)](#no-tool-calls-parsed-本地模型-ollama)。

### 一些子 agent 失败;运行仍以 0 退出

Expand Down
15 changes: 13 additions & 2 deletions pages/src/pages/DocsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import docContentsIcon from '../assets/icons/doc-contents.svg';
import searchIcon from '../assets/icons/icon-search.svg';
import '../styles/docs-markdown.css';

// marked percent-encodes non-ASCII hrefs; heading ids are raw text from
// generateHeadingId, so fragments must be decoded before lookup.
function decodeFragment(fragment: string): string {
try {
return decodeURIComponent(fragment);
} catch {
return fragment;
}
}

/* ─── Sidebar tree data ─── */
interface SidebarItem {
id: string;
Expand Down Expand Up @@ -198,7 +208,7 @@ const DocsPage: React.FC = () => {
// Skip pure anchors (same-page scroll)
if (href.startsWith('#')) {
e.preventDefault();
const id = href.slice(1);
const id = decodeFragment(href.slice(1));
const el = document.getElementById(id);
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
return;
Expand All @@ -217,7 +227,8 @@ const DocsPage: React.FC = () => {
e.preventDefault();
navigateToDoc(slug);
// Handle anchor scroll after navigation with reliable retry
const anchor2 = href.split('#')[1];
const anchor2raw = href.split('#')[1];
const anchor2 = anchor2raw ? decodeFragment(anchor2raw) : undefined;
if (anchor2) {
const tryScroll = (attempts: number) => {
const el = document.getElementById(anchor2);
Expand Down
Loading