Commit graph

69 commits

Author SHA1 Message Date
wxwxwxw_orange
16c7734af8
feat(llm): add Tencent TokenHub and Hunyuan Token Plan providers (#142) 2026-06-16 19:54:22 +08:00
kite
0a7d14e453 fix: remove duplicate kimi provider and fix test locale
Remove the duplicate kimi provider entry introduced by overlapping PRs
(#130 and #134). Keep the Kimi Moonshot API entry with MOONSHOT_API_KEY.

Set LC_ALL=C in Makefile test target to ensure git outputs English
messages regardless of system locale.
2026-06-15 15:32:53 +08:00
wxwxwxw_orange
2bde478993
feat(llm): add volcengine and kimi providers (#134)
* feat(llm): add volcengine and kimi providers
Add pay-as-you-go OpenAI-compatible presets for Volcano Engine Ark
and Kimi Moonshot API.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Apply suggestions from code review

Co-authored-by: lizhengfeng <lizhengfeng.lzf@alibaba-inc.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: lizhengfeng <lizhengfeng.lzf@alibaba-inc.com>
2026-06-15 15:23:19 +08:00
MuoDoo
86380286be
fix: sort provider selection list (#135) 2026-06-15 14:55:41 +08:00
DanielWalnut
3236a610ec
fix: remove sonnet 4.7&4.8 (#133) 2026-06-15 12:53:48 +08:00
kite
7c0b70b02b test(diff): add unit tests for readWorkspaceFileForDiff
Cover all key branches: regular file read, path traversal rejection,
directory rejection, parent symlink escape, external/internal symlink
target handling, and nonexistent file error.
2026-06-15 11:51:51 +08:00
不许对我狗叫丶
3b68c93013
feat: add Kimi provider (#130)
* feat: add build-in kimi provider

Co-authored-by: lizhengfeng <lizhengfeng.lzf@alibaba-inc.com>
2026-06-15 11:50:25 +08:00
不许对我狗叫丶
17c5edca8a
feat: add minimax provider (#131)
* feat: add build-in minimax provider


Co-authored-by: lizhengfeng <lizhengfeng.lzf@alibaba-inc.com>
2026-06-15 11:49:14 +08:00
不许对我狗叫丶
957132e3b6
fix: change mimo token plan url to api url and add mimo flash model (#132) 2026-06-15 09:57:04 +08:00
MuoDoo
4b3f41df10
Fix workspace symlink diff containment (#125)
* Fix workspace symlink diff containment

* Share repository path containment helpers
2026-06-15 00:03:36 +08:00
不许对我狗叫丶
6b8d269c0b
feat: add mimo provider (#124)
Some checks failed
Deploy Pages / build (push) Has been cancelled
Deploy Pages / deploy (push) Has been cancelled
2026-06-14 22:31:30 +08:00
ZheNing Hu
283ec8558c
fix(diff): detect renamed and deleted files correctly in diff parsing (#105)
When a file was renamed on the target branch, ocr review emitted
'[ocr] WARNING: cannot read file <old path> at ref <to>: exit status 128'.

Two compounding bugs:

1. The parser required 'a/'/'b/' prefixes when matching '--- /dev/null' /
   '+++ /dev/null', but git emits these lines without prefixes, so
   IsNew/IsDeleted were never set and deleted files fell through to a
   doomed 'git show ref:<old path>'.

2. 'rename from' / 'rename to' extended headers were never parsed, and
   git diff/show call sites did not force rename detection, so renames
   degraded to delete+add whenever the user had diff.renames=false.

Fixes:
- Parse 'rename from'/'rename to', 'new file mode', 'deleted file mode'
  and unprefixed /dev/null markers in ParseDiffText.
- Pass --find-renames to all git diff/show invocations so rename
  detection no longer depends on user config.
- Add IsRenamed to model.Diff (json: is_renamed) and prefer it in
  diffStatus.
- Add parser unit tests and a range-mode rename regression test.

Fixes #99
2026-06-14 22:29:02 +08:00
kite
72aad2c77c feat: add interactive provider setup with TUI and documentation 2026-06-14 10:49:33 +08:00
MuoDoo
64552aee9b
fix(security): block git ref option injection (#112) 2026-06-13 11:07:59 +08:00
MuoDoo
9f81cbe486
fix(tool): constrain workspace file reads to repo (#109) 2026-06-12 17:57:28 +08:00
Daniel Grießhaber
c2c7c37e0f
fix(agent): user includes should have higher priority than system supported extensions (#51) 2026-06-12 14:29:47 +08:00
kite
01c9c85456 feat: add review filter to remove provably incorrect comments after subtask
- Add REVIEW_FILTER_TASK template and LLM conversation config
- Implement executeReviewFilter to post-process comments per file
- Add CommentsForPath and RemoveByPathAndIndices to CommentCollector
- Apply timeout from template config to review filter LLM call
- Await CommentWorkerPool before running filter to prevent race condition
- Include raw response preview in filter JSON parse error logs
2026-06-09 20:41:42 +08:00
kite
cf32900ca1 fix: force standard diff prefixes to prevent diff.noprefix/mnemonicPrefix from breaking parsing (#82)
Add --src-prefix=a/ --dst-prefix=b/ to all git diff/show calls so that
user config (diff.noprefix, diff.mnemonicPrefix) cannot alter the prefix
format the parser depends on. Also add missing ModeCommit test coverage.
2026-06-09 18:08:11 +08:00
Eldar Shlomi
c9fae8d4e9
fix: pass --no-ext-diff --no-textconv to git diff/show so external diff tools don't break parsing (#86)
When a user has configured a global external diff tool (diff.external /
GIT_EXTERNAL_DIFF) or a textconv filter, git diff/show emit the tool's
output instead of unified diff text. The provider's parser keys off
`diff --git` headers, so it parses zero diffs and the review silently
reports "No files changed".

Add --no-ext-diff --no-textconv to all four git diff/show call sites in
internal/diff/git.go (ModeRange diff, ModeCommit show, and both
workspaceTrackedDiff calls). merge-base and ls-files are left untouched
since they don't run the diff machinery.

Adds an integration test that initializes a real git repo, activates a
garbage GIT_EXTERNAL_DIFF script, and asserts the provider still parses
a non-empty diff (fails before this change, passes after).

Closes #82

AI-assisted contribution.
2026-06-09 18:02:01 +08:00
kite
48cc6a3329 feat: change default output language from Chinese to English 2026-06-09 09:57:45 +08:00
Shi Peipei
4043e9ee33
fix: handle previously swallowed json.Unmarshal errors (#78)
- Propagate json.Unmarshal error in buildAnthropicParams when parsing
  tool call arguments, preventing silent empty-map fallback on malformed JSON
- Return explicit error message in ParseComments when comments JSON
  string fails to unmarshal, instead of silently ignoring

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-08 21:03:00 +08:00
MuoDoo
adb9ac8b4e
feat(rules): add built-in Rust and Cargo.toml review rules (#74)
* Add Rust review rules

* Fix case-insensitive rule matching
2026-06-08 20:56:00 +08:00
kite
fa6c7d8e04 refactor(llm): deduplicate and validate auth header normalization
Export NormalizeAuthHeader from the llm package and remove the duplicate
normalizeConfigAuthHeader in config_cmd.go. Invalid auth_header values
now return an error at configuration time instead of being silently
accepted and causing opaque 401s at runtime.
2026-06-08 20:21:28 +08:00
zhouzhihao
48dc1b37d4
fix(llm): support Anthropic auth header (#77) 2026-06-08 19:35:12 +08:00
kite
1b3c0ab19f fix(llm): handle Anthropic thinking content blocks in multi-turn conversations
Anthropic models with extended thinking return type:"thinking" content
blocks which were silently dropped, causing empty assistant content in
conversation history. Extract thinking blocks into ReasoningContent so
the existing Content() fallback works correctly.
2026-06-07 17:09:31 +08:00
kite
5fad9ce2fa fix(llm): use max_completion_tokens instead of deprecated max_tokens for OpenAI requests
Fixes #30 — newer OpenAI models (o1, o3, o4, gpt-5.x) reject the
deprecated max_tokens parameter with a 400 error.
2026-06-07 08:33:51 +08:00
kite
0d530f3b73 fix(viewer): use real API token usage in session page instead of tiktoken estimates
The session page was showing significantly lower token counts than the console
summary because it used local tiktoken estimation while the console used actual
API-reported usage data. Now SetResponse prefers resp.Usage when available
(falling back to tiktoken), persists cache token fields to JSONL, and the
viewer displays cache read/write stats alongside prompt/completion totals.
2026-06-06 21:17:47 +08:00
kite
f24334deb2 perf(tool): stream file reads line-by-line to avoid full-file memory allocation
Replace os.ReadFile + strings.Split with bufio.Reader streaming in
FileReadProvider, so only the requested window (up to 500 lines) is kept
in memory instead of the entire file. Adds Runner.Stream for semaphore-
aware stdout piping, FileReader.ReadLines for line-windowed reading, and
validates invalid line ranges. Reduces per-goroutine memory from ~8MB to
~44KB for large files under concurrent workloads.
2026-06-06 20:59:05 +08:00
kite
2bebc86cfc feat(config): increase default max tool call rounds from 20 to 30
Allow more thorough analysis per file by raising MAX_TOOL_REQUEST_TIMES.
2026-06-06 20:35:32 +08:00
kite
ef46dfdac9 feat(tool): add global git subprocess concurrency limiter and propagate context.Context to diff layer
Introduce gitcmd.Runner with channel-based semaphore to cap concurrent
git subprocesses (default 16, configurable via --max-git-procs). Route
all tool-layer and diff-layer git calls through the shared runner.
Also fix diff.Provider.runGit lacking context.Context — now the full
chain (GetDiff → MergeBase → ParseDiffText → finalizeDiff) propagates
the caller's context for proper cancellation and timeout support.
2026-06-06 20:20:34 +08:00
kite
363d971916 fix(tool): make Registry and DiffMap concurrency-safe via freeze semantics
Registry was a plain map alias and DiffMap a shared map[string]string,
both relying on implicit write-before-read ordering with no compile-time
safety. Refactor Registry into an encapsulated struct with Freeze() that
panics on post-freeze writes, and wrap DiffMap as an immutable value type
with defensive copy on construction. Move DiffMap injection to before
filterDiffs to preserve the original behavior of exposing all file diffs.
2026-06-06 19:41:11 +08:00
kite
08bb28ced5 feat(llm): enable Anthropic prompt caching and fix token accounting
Add cache_control ephemeral breakpoints on system prompt and tool
definitions to activate Anthropic prompt caching for multi-turn
agent loops. Fix token double-counting by removing the redundant
totalTokensUsed accumulator and computing it from sub-items. Surface
cache read/write statistics in both text and JSON summary output.
2026-06-06 19:26:34 +08:00
kite
828fc6cae7 fix(tool): propagate context.Context to all tool providers to enable subprocess cancellation
Add ctx parameter to Provider.Execute interface and propagate it through
FileReader.Read, code_search.gitGrep/runGitGrep, and file_find.listGitFiles.
This ensures parent task cancellation/timeout properly terminates running
git subprocesses (grep, show, ls-files, ls-tree). Also adds 10s timeout
to file_find and fixes context.Canceled handling in code_search.
2026-06-06 19:26:34 +08:00
kite
aa86d9fa60 fix(rules): align test expectations with English rule docs and isolate global config
Rule doc files were translated from Chinese to English but tests still
expected Chinese substrings. Also added HOME isolation to prevent the
user's ~/.opencodereview/rule.json from interfering with system-default
rule assertions.
2026-06-06 19:26:34 +08:00
kite
7d75c3a9d3 refactor(llm): replace hand-rolled HTTP clients with official Anthropic and OpenAI SDKs
Migrated internal/llm from manual net/http implementation to anthropic-sdk-go v1.47.0
and openai-go/v3 v3.39.0, reducing ~400 lines of retry, request-building, and streaming
code. Simplified LLMClient interface to single CompletionsWithCtx method. Fixed Anthropic
auth to use WithAuthToken (Bearer) instead of WithAPIKey (X-Api-Key) for proxy compatibility.
Fixed OpenAI message builder to use ExtractText() for proper []ContentBlock handling.
2026-06-06 19:26:34 +08:00
kite
18e52f5555 fix(tool): add 10s timeout to code_search git grep to prevent blocking on slow I/O 2026-06-06 15:16:48 +08:00
kite
8e9772baa8 fix(llm): add context support to StreamCompletion and memory compression to prevent infinite timeouts
StreamCompletion used http.NewRequest without context and retry with
context.Background(), making streaming calls uncancellable. Memory
compression called Completions() without context, leaving async
goroutines unable to be cancelled or timed out.

- Add StreamCompletionWithCtx to LLMClient interface and both
  OpenAI/Anthropic implementations
- Propagate context through runCompression, addNextMessage, and
  triggerAsyncCompression call chain
- Add 5-minute timeout cap on async compression goroutines
- Cancel in-flight compression HTTP requests when job is superseded
2026-06-06 13:22:32 +08:00
kite
729c8647b7 fix(tool): use fixed-string matching by default in code_search to fix Linux failures
The code_search tool used -E (extended regex) by default, causing
unmatched parentheses in search patterns (e.g. "func Hello()") to
trigger "Unmatched ( or \(" fatal errors on Linux (GNU regex is strict),
while macOS (BSD regex) silently tolerated them. Since the tool
definition states the default mode is "literal text", switch to -F
(fixed string). Also capture stderr separately so real errors are
surfaced instead of being silently reported as "No matches found".
2026-06-05 23:59:01 +08:00
kite
1534085383 fix(tool): correct git grep argument order for commit/range mode (#53)
The searchText was placed after '--', causing git to interpret it as a
pathspec instead of a pattern. Use '-e' to explicitly mark the search
pattern and place the ref after it. Also replace CombinedOutput with
Output to prevent stderr from polluting result parsing.
2026-06-05 20:38:26 +08:00
kite
8c4463f657 docs(rule): Translated into English 2026-06-05 19:51:06 +08:00
Lei Zhang
95c5d5930e
feat: Add HarmonyOS support for .ets files and review configurations (#48)
* feat: add .ets file extension support for HarmonyOS development

* feat: add complete HarmonyOS review support with ArkTS rules, .json5 config, and oh_modules exclusion

- Add arkts.md rule doc with ArkTS-specific and TypeScript general checks
- Add .json5 to supported file types for HarmonyOS config files
- Map .json5 to json.md rules in system_rules.json
- Exclude oh_modules/** (HarmonyOS dependency dir) from review
- Exclude *.test.ets (HarmonyOS test files) from review
- Add unit tests for all new extensions and patterns

* refactor: merge json and json5 glob patterns into single brace expansion
2026-06-05 12:22:11 +08:00
kite
0ac1193040 feat(session,viewer): record review mode and diff refs in session
Store ReviewMode, DiffFrom, DiffTo, and DiffCommit in SessionHistory
and persist them to JSONL (conditionally, only when non-empty). Display
mode in viewer list page and show version details (from/to or commit)
on the session detail page based on review mode.
2026-06-05 09:44:33 +08:00
kite
e48b132ebf fix(tool,agent): parse git grep output correctly in range mode and retry on empty results
code_search used SplitN(":", 3) to parse git grep output, but in
range/commit mode git grep prefixes each line with the ref
(ref:file:line:content). All matches silently failed Atoi on the
filepath field, returning an empty string that caused the review
session to terminate immediately.

Fix code_search to detect the ref prefix and adjust split/index
accordingly. Also replace the hard stop on empty tool results with
a retry loop (up to 3 consecutive empty rounds) so the LLM can
recover or call task_done gracefully.
2026-06-04 23:43:26 +08:00
kite
eccb0d2b4b feat(session): track LLM request failure count with JSONL persistence
Record each LLM failure as an llm_error entry in the session JSONL log
and surface the total count in the viewer's Token Usage summary.
2026-06-04 23:11:35 +08:00
kite
99e6709603 fix(diff,tool): read file content at reviewed ref in range/commit mode
file_find and finalizeDiff always read from the working tree, even in
range/commit mode where the review targets a specific git ref. This
caused inconsistent file versions compared to file_read and code_search
which correctly used git show. Fix file_find to use git ls-tree and
finalizeDiff to use git show when a ref is specified.
2026-06-04 15:20:14 +08:00
Coldaine
a53b16cff5
fix(agent): stop leaking {{plan_guidance}} into MAIN_TASK prompts (#33)
Replace the hard-coded Chinese-only empty-plan branch with a compiled
regex + helper that strips the "### Review Plan …" wrapper (any language
variant) when the plan phase produces no output.

TWO BUGS fixed:
- The wrapper was only stripped for the Chinese literal `### 审查计划`,
  not the actual English `### Review Plan (Optional)` shipped in the
  template, so `{{plan_guidance}}` leaked into the rendered prompt on
  every review where the plan phase was skipped or failed.
- The strip ran AFTER `ReplaceAll("{{plan_guidance}}", "")`, so the
  token was already gone and the regex couldn't match the wrapper.
  Fixed ordering: strip BEFORE replace.

Also simplifies the regex alternation per Copilot review feedback:
`Review Plan` and `审查计划` already subsume the `(Optional)`/`(可选)`
suffixes because the trailing `[^\n]*` consumes them.

Adds unit tests for English, Chinese, and integration (production flow).

Co-authored-by: Copilot <copilot-pull-request-reviewer@github.com>
2026-06-04 14:11:31 +08:00
Lei Zhang
1e18a661cf
fix: handle Windows paths in session encodeRepoPath (#36)
Make encodeRepoPath cross-platform by properly handling volume names, backslash separators, and drive letter colons. Add unit tests covering Unix, Windows, and edge-case inputs.
2026-06-04 12:55:29 +08:00
Lei Zhang
482de7ac52
fix: skip binary review (#28)
* fix(agent): skip binary files during code review

Previously, binary files were passed through the review pipeline because
shouldReview only checked path/extension rules. This caused the agent to
incorrectly attempt reviewing binary content.

- Add ExcludeBinary reason to the exclusion filter
- Change shouldReview/whyExcluded to accept model.Diff instead of path
  string, enabling access to the IsBinary flag
- Check IsBinary as the first gate in whyExcluded
- Differentiate skip log messages for binary vs path-filtered files

* test: add unit tests for preview.go

* fix: normalize dash to em-dash in binary file skip log message

* test(agent): strengthen UserIncludePattern tests to cover additive semantics

- Document that include patterns are additive, not exclusive
- Add cases verifying include bypasses default-path exclusion
- Add cases for extension filter precedence over include logic
- Add TestWhyExcluded_IncludeBypassesDefaultPath for rescue semantics
- Add TestWhyExcluded_IncludeAndExcludeInteraction for priority order
2026-06-03 18:01:30 +08:00
kite
6ce1ec7511 style: apply go fmt formatting 2026-06-03 17:34:28 +08:00
@aaronjmars
7be4926372
fix(viewer): add Host-header allowlist to block DNS rebinding (#10)
The viewer's HTTP server (StartServer in internal/viewer/server.go) had no
Host-header validation, so a web page the user visits could DNS-rebind its
own origin to 127.0.0.1:5483 and read every session JSONL — which contains
LLM request messages (= source code being reviewed) and the LLM's analysis.

Adds a default-deny host guard that always allows loopback names plus the
concrete bind host. Wildcard binds and extra hostnames go through the new
OCR_VIEWER_ALLOWED_HOSTS env var, so an operator who binds the viewer on a
LAN interface has to acknowledge the exposure explicitly.

Detected by Aeon + manual review.
Severity: high
CWE-346 (Origin Validation Error), CWE-200 (Exposure of Sensitive Info)

Co-authored-by: aeonframework <aeonframework@users.noreply.github.com>
2026-06-03 17:21:27 +08:00