mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-08-25 08:32:59 +00:00
601 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e93197d6e4
|
fix(llm): serve GPT-5.6 models via the OpenAI Responses API (#559) (#938)
Some checks are pending
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
* fix(llm): serve GPT-5.6 models via the OpenAI Responses API (#559) The built-in "openai" preset listed gpt-5.6-sol/terra/luna but used the Chat Completions protocol (/v1/chat/completions). Selecting one of those models for `ocr review` fails with a 400 because GPT-5.6 tool calls with reasoning effort are only supported through the Responses API (/v1/responses). Move the GPT-5.6 models to a dedicated "openai-responses" preset that uses ProtocolOpenAIResponses, so a user can select them without knowing which OpenAI API protocol is required. Other openai models are unchanged. Fixes #559 * fix(llm): separate Responses API credentials Use OPENAI_RESPONSES_API_KEY for the built-in Responses preset and document it across the site translations.\n\nRED→GREEN: focused provider test failed on OPENAI_API_KEY, then passed with the separate key. Full local CI remained green at 91.3% coverage. * chore(llm): remove verbose provider comment * refactor(llm): inline OPENAI_RESPONSES_API_KEY literal in registry Remove the one-use openAIResponsesAPIKeyEnv constant and write the env-var name directly in the provider entry, consistent with every other built-in provider. --------- Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
b17460a6a3
|
fix(cli): exit 128+signo when the native binary is killed by a signal (#1054)
The launcher forwarded spawnSync's result as status ?? (error ? 1 : 0), so a child terminated by a signal (status=null, error=undefined) exited 0. Downstream pipelines gating on the exit code read an OOM kill or any signal death as a clean success. Exit 128+signo for signal deaths, keep the existing status/error behavior otherwise. The exit-code mapping moves to an exported launcherExitCode so it can be unit-tested; the launcher body is guarded by require.main to stay require-safe. Fixes #931 |
||
|
|
a66240084b
|
feat(agent): group semantically related files for multi-file review (#808)
* feat(agent): group semantically related files for multi-file review
Introduce LLM-based semantic file grouping so that related files (e.g.
implementation + test, i18n variants, interface + impl) are reviewed
together in a single LLM call instead of individually. This enables
cross-file consistency checks and reduces total LLM calls.
Key changes:
- Add grouping.go with LLM-based file grouping (GROUPING_TASK template)
that clusters changed files by semantic relationship, with fallback
to per-file dispatch on any error
- Refactor dispatchSubtasks to iterate over FileGroup instead of
individual Diff, updating budget estimation, error handling, panic
recovery, and session recording to work at group granularity
- Move the 'path' field from tool-level to per-comment level in
code_comment tool schema, since one review call now covers multiple
files — remove the forced path override in loop.go
- Rewrite plan phase output from JSON to a structured Review Directive
with MUST/SHOULD/MAY severity tiers and concrete verification actions
- Update main_task prompts to accept {{diffs}} (multi-file XML) instead
of {{diff}} + {{current_file_path}}, with cross-file review guidance
- Add enforceGroupTokenBudget and enforceMaxFilesPerGroup safety limits
- Treat partial completion (comments produced before round exhaustion)
as partial success instead of hard error
* test(agent): improve grouping test coverage
* fix(llmloop): add per-item path to thinking backfill tests
ParseComments skips comments with empty path. After removing the
top-level args path override, these tests need path in each comment
object to match the new per-item path contract.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(llmloop): backfill comment thinking from turn output (#773)
* feat(llmloop): backfill comment thinking from the turn's reasoning or message
Expose ChatResponse.ReasoningContent and backfill per-comment thinking
with the current turn's reasoning content, falling back to the assistant
message for models that do not expose reasoning, so --format json output
carries thinking even when the model omits it.
* fix(llmloop): drop content fallback for comment thinking backfill
The turn's assistant message is usually a short user-facing preamble
rather than real reasoning, so backfill per-comment thinking only from
the model's native reasoning_content and leave it empty otherwise.
Add a full-wiring RunPerFile test for the reasoning backfill and a
regression test that fails if the content fallback returns. Sync the
thinking docs across en/zh/ja/ru.
* docs(llmloop): note that turn-level thinking is shared by design
Document in the main loop and at the code_comment backfill site that
the model emits reasoning once per turn, so every tool call and
comment in the same turn intentionally shares the same thinking.
* fix(tool): fall back to newPath when comment omits path field
The multi-file grouping change moved path from a top-level arg
to per-comment objects and removed the args["path"] = newPath
injection. This broke single-file RunPerFile calls where the model
does not emit path per comment.
Add ParseCommentsWithPath that applies newPath as a default when
comments lack an explicit path, restoring the previous behavior.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(prompt): remove redundant Comment Attribution section
The path field is already marked required in the tool JSON schema
with a clear description. Repeating it in the system prompt wastes
tokens without adding signal.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(agent): rename file_metadata_table to file_list
The placeholder renders a plain one-per-line list, not a table.
The old name misleadingly suggests markdown table formatting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(prompt): reference actual <file> elements instead of nonexistent <review_files>
The system prompt mentioned <review_files> but no such tag exists in
the rendered user message. The files are wrapped in <file path="...">
elements by buildConcatenatedDiffs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(prompt): wrap diffs in <review_files> container
Add <review_files> wrapper in the user prompt template around {{diffs}}
so the system prompt can reference it as the explicit review scope,
consistent with <other_changed_files> and <user_task> containers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(prompt): clean up system/user prompts for multi-file review
- Consolidate scope constraints into Strict Focus Rules; remove
duplicated 'don't' items from Capabilities
- Remove redundant path instruction from user prompt (already in
tool schema)
- Fix末尾 instruction to reference <review_files> instead of <file>
- Fix plan output format: each category numbers independently
- Replace // comments with plain text in user prompts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(agent): restore design-decision comments lost during refactor
The grouping refactor deleted explanatory comments about budget
look-ahead semantics, why SetRunFailure is NOT used, and the
panic-isolation contract. These explain non-obvious WHY decisions
and are restored in condensed form.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(prompt): restore review recall lost to plan-phase suppression
The semantic-grouping branch cut comment recall from 20.0% to 12.7%
(F1 25.2% -> 19.1%) on the 194-PR benchmark. Ground truth shows the
396 dropped comments had a 27.8% hit rate — only 14% better than a
random cut of the same size, so the loss was indiscriminate thinning
rather than targeted noise removal.
Four causes, all addressed here:
- The plan prompt lost its third severity tier. code_comment accepts
four severities but the plan offered only MUST/SHOULD, so nothing
could feed a `low` comment. Add CONSIDER.
- main_task_system.md lost its only positive instruction to produce
feedback ("pointing out areas for improvement"), leaving a prompt
made entirely of restrictions. Restore it and the obligation wording
in Role.
- Nothing obliged the model to cover every file in a group, so secondary
members were starved: .h files lost 79% of their comments and went
silent 68% of the time, against ~30% for implementation files at the
same comment density. Gate task_done on a per-<file> pass.
- PLAN_MODE_LINE_THRESHOLD was calibrated per file but is now compared
against a group's summed churn, making the plan phase effectively
unconditional. Gate on the largest single-file churn instead.
Also relax the [deep] abandonment threshold from 3-4 to 6-8 tool calls
(tool calls per file had fallen 4.12 -> 2.92) and make plan adherence
rule 4 an obligation rather than a permission.
The plan.skipped event keeps its original lines.changed attribute and
gains lines.changed.max_file, so existing dashboards keep resolving;
the telemetry docs are synced across all four locales, which also
picks up the file.path -> group.label rename from the grouping commit.
Round-budget and failure-attribution fixes are deliberately left out so
their effect can be measured separately.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* test(llmloop): use per-comment path in re-location identity tests
These predate the code_comment schema migration (path moved from
tool-level to per-comment level in the grouping commit) and only
surfaced once the grouping commit was rebased ahead of them: the
tool-level path was silently ignored, comments were dropped for an
empty path, and TestReLocation_Identity got 0 requests instead of 1.
* refactor(prompt): emit the review plan as plain text instead of JSON
Nothing parses the plan output: executeGroupPlanPhase hands
resp.Content() straight into {{plan_guidance}}, so the JSON envelope
only cost output tokens and forced the model to escape newlines in the
code snippets every plan item quotes. Malformed JSON degraded silently
into the main-task prompt because no validation stood between them.
Keep the exact field set (change_summary, issues[].severity,
issues[].description, issues[].tool_guidance[].name/arguments/reason)
and carry it in plain text instead: a Summary: line, numbered issues
tagged [high|medium|low], and one arrow line per tool guidance. Headings
and code fences are now forbidden in the output, because the plan is
injected under a "### Review Plan" heading inside <user_task> and the
plan result is never fence-stripped. Align the plan user message, which
still asked for a JSON fence.
Restore the main_task system prompt to its pre-grouping wording, keeping
the trimmed Role section and dropping Review Plan Adherence, whose
MUST/SHOULD/CONSIDER and [quick]/[deep] vocabulary no longer exists in
the plan output. Two rules stay rescoped to the group instead: Strict
Focus Rules would otherwise tell the model to ignore its own group
members, and without the per-file pass requirement a group's secondary
files get marked completed in the manifest without ever being read.
* fix(agent): tag each rule block with the files it governs
A group spanning two languages resolved two rule sets and concatenated
them with a bare newline, so the model received (say) the Java checklist
immediately followed by the MyBatis one and nothing saying which file
each governs. A group holding exactly that mix is what the grouping
prompt asks for: interface plus implementation, i18n/config variants of
one resource.
Group the files by resolved rule text and wrap each block in
<rules for="...">, matching the <review_files>/<file path="..."> framing
already used for the diffs. A group covered by a single rule set — every
single-file group, and every group whose files share a language —
returns that text bare, so the rendered prompt stays byte-identical for
those runs and the prompt-cache prefix does not churn.
Resolve in path order as well. The diffs arrive in the grouping LLM's
response order, which varies between runs and would otherwise reorder
the blocks; clone before sorting, since the caller's slice is shared
with a.diffs.
Drop the four single-file helpers the grouping refactor left behind
(resolveSystemRule, buildChangeFilesExcept, executePlanPhase,
buildFilterCommentsJSON). All four had no caller outside their own
tests, and executePlanPhase still substituted {{current_file_path}} and
{{diff}}, placeholders no longer present in any template — reading it
suggested the single-file path was still live.
Their tests are ported to the group functions rather than deleted:
executeGroupPlanPhase, buildChangeFilesExceptGroup and
buildGroupFilterCommentsJSON had no coverage at all, so deleting the
tests with the code would have left the live path untested. The ports
assert what the group versions changed — plan records filed under the
group key, comment ids running globally across files, every group member
excluded from the change-file list including a renamed member's old
path.
* fix(agent): drop the stray trailing newline from the change-file list
buildChangeFilesExceptGroup appended the separator after each entry,
guarded by the entry's index into a.diffs. The loop skips binaries and
every group member, so whenever the final diff was one of the skipped
ones the last emitted entry still passed the index test and the list
ended with a newline. Excluding a whole group rather than a single file
makes that the common case, not the rare one.
Emit the separator before each entry instead, guarded on anything having
been written yet. Separators between entries were never affected — any
emitted entry followed by another necessarily sits below the final index
— so this only removes the trailing one.
Assert the exact string in three cases: a skipped final diff, a skip
between two entries, and everything excluded. The existing checks used
strings.Contains, which cannot see a trailing newline at all.
* fix(prompt): adapt the review filter to multi-file groups
The filter template still described its input as "one file's diff" and
fenced it with ```{{path}}, while executeGroupReviewFilter substitutes
the comma-joined group key and a multi-file <file> sequence. The fence
language read ```src/a.go,src/b.go, and the diff body is now XML that can
itself contain a fence and truncate the block.
The substantive cost was Ground A. Its shapes are inherently per-file —
"discusses the body of a function, on a file that only declares it",
"discusses host-language logic on a file that holds none" — but nothing
told the model to pair a comment with the <file> matching its path, so a
sibling file holding the construct could rescue a comment that its own
file refutes. The filter got more lenient, which is its safe direction,
but the ground stopped doing its job.
State the pairing rule up front, and keep the two grounds asymmetric:
Ground A is judged against the subject file alone, Ground B against any
file in the group, because a comment calling an identifier unused is
genuinely wrong once any of these files uses it. Sibling files stay
usable as evidence — that is what group-level filtering is for — they
just cannot substitute for the subject file.
Carry the diffs in <review_files> instead of a fenced block, matching
main_task_user.md, which also retires the bogus fence language and the
truncation risk. The system message loses "you can see only a single
diff" for the same reason. {{path}} is left substituted in agent.go: no
shipped template uses it now, but a user template still might.
* fix(agent): classify group coverage per file, not per group
A file group that stops before task_done (round/token budget
exhaustion) could still have produced usable comments for some of its
files. The dispatch loop was marking every file in the group as
Failed regardless, so a single stuck file dragged its whole group -
and, when it was the only dispatched group, the whole run - down to
terminal_state=failed even though real coverage existed.
Classify each file by whether it actually has comments: files with
output are marked Completed, files without stay Failed. This lets
computeTerminal report partial (exit 0) instead of failed (exit 1)
when a group is a genuine mix of the two.
Also fix subtaskFailed to count only the files marked failed in this
loop instead of assuming reportAsError implies the whole group
failed - a group can now legitimately end up partially completed.
* feat(agent): add multi-round review to improve recall coverage
Wrap the Main Loop + Review Filter in a per-group round loop
(default MAX_REVIEW_ROUNDS=2). Each round after the first injects
confirmed findings from prior rounds into the prompt, instructing the
model to find different issues rather than repeating known ones.
Key design points:
- Round 1 prompt is byte-identical to the previous single-round behavior
- Round 2+ strips the plan to avoid it acting as a coverage ceiling
- Per-path baselines (not global Snapshot) for concurrency safety
- Per-round filter ensures only verified findings enter confirmed set
- Early stop: zero new confirmed, or >= 30 confirmed, or budget exceeded
- Per-group timeout auto-scales 1.5x when rounds > 1
- budgetExceeded field converted to atomic.Bool to fix data race
- UTF-8 safe rune-based truncation for confirmed comment serialization
* feat(config): raise MAX_TOOL_REQUEST_TIMES to 100, minMaxTools to 50
Grouped file review needs more tool call rounds than single-file mode
since one RunPerFile call now serves multiple files. Raise the default
from 30 to 100 and the user-configurable minimum from 10 to 50.
* feat(config): add group plan threshold and separate prompt/completion token limits
- Add PLAN_MODE_GROUP_LINE_THRESHOLD (default 120) so multi-file groups
trigger the plan phase when their combined churn is substantial, even
if no single file exceeds the per-file threshold. This fixes round-1
review quality regression for grouped files.
- Separate MAX_TOKENS (prompt ceiling, raised to 200000) from
MAX_COMPLETION_TOKENS (output cap, 16384). Previously both roles were
conflated in a single value. This allows larger file groups to stay
intact without inflating the model's output budget.
- Add Template.PlanRequired() helper with dual-threshold logic
- Extract groupChurn() helper from executeGroupSubtask
- Remove runtime MaxCompletionTokens=MaxTokens assignment in review/scan
commands (now loaded from template JSON directly)
* feat(config): add --effort flag to control review rounds
Introduce a review effort preset (--effort low|medium|high) that maps
to the number of review rounds:
- low: 1 round (fast, suitable for large PRs or time-sensitive CI)
- medium (default): 2 rounds (best balance of recall and cost)
- high: 3 rounds (maximum coverage)
Supported via CLI flag, persistent config (ocr config set effort low),
and three-tier precedence (CLI > config > default).
Also reorder tools.json to place file_read after code_search.
* feat(output): include file group info in --format json output
Add a 'groups' field to the JSON output showing which files were
grouped together for review. Each entry has a label and file list.
This enables post-run analysis of grouping behavior for evaluation.
Also reorder Strict Focus Rules in main_task_system.md and move
file_read after code_search in tools.json.
* fix(prompt): rewrite Strict Focus Rules for clarity
- Lead with positive scope instruction (review every file individually)
- Encourage cross-file observations within <review_files>
- Clarify that context tools are for background info, and comments must
target code within <review_files> — avoids ambiguity that could
suppress legitimate findings discovered via context gathering
* style: gofmt -s output.go
* docs: sync documentation with semantic grouping and effort features
Update all four language variants (en, zh, ja, ru) to reflect:
- MAX_TOOL_REQUEST_TIMES default 30 → 100
- MAX_TOKENS 58888 → 200000 (prompt ceiling only)
- New MAX_COMPLETION_TOKENS = 16384 (output cap)
- New PLAN_MODE_GROUP_LINE_THRESHOLD = 100
- New --effort low|medium|high flag (1/2/3 rounds)
- Semantic file grouping pipeline
- --max-tools raise-only semantics (min 50)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: xujiejie <80671406+yingjiexu2002@users.noreply.github.com>
|
||
|
|
0c44f1049e
|
fix(diff): surface git's own message when a diff command fails (#1039)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
* fix(diff): surface git's own message when a diff command fails
GetDiff runs git through runGit, which captures stdout and stderr together,
then discarded that output on every failure path. A user whose `git show`
failed saw only:
Error: review failed: load diffs: get diffs: git show failed: exit status 129
The exit status alone cannot distinguish an unsupported option from a bad
revision or a permission problem, so diagnosing #972 meant asking the reporter
to re-run the command by hand to see what git actually said.
Quote git's output in the error for the three diff-producing paths (range,
commit, workspace-tracked). The same failure now reads:
... git show failed: exit status 129: error: unknown option `diff-merges=first-parent'
Output is capped, keeping the tail, because runGit's combined output means a
command that failed partway through carries a prefix of real diff along with
the diagnosis. The cap cuts on a rune boundary: git speaks the user's locale,
and #972 came from a Japanese-language Windows install, so a byte-wise cut
would replace a confusing error with an unreadable one.
The other runGit callers deliberately swallow errors and fall back, so they
are left alone.
* test(diff): pin which command speaks when both workspace diffs fail
Addresses review feedback on the two-stage fallback in workspaceTrackedDiff.
Reaching `git diff --staged` means `git diff HEAD` already failed, and in
the case the fallback exists for -- a repository with no commits -- it failed
with "bad revision 'HEAD'", which is expected rather than diagnostic.
Surfacing both would put that benign message ahead of the one describing what
actually blocked the review, so the behavior is deliberate and now has a test
saying so.
* fix(diff): quote stderr, not combined output, when git fails
Review feedback: a `git show` killed mid-write contributed a 2036-byte tail
made entirely of diff content, with no diagnosis anywhere in it. SIGKILL
leaves stderr empty, so keeping the tail kept repository source -- and
whatever that source contains.
That string does not stay local. reviewResultError hands it to
span.RecordError (review_cmd.go:259), and signal.NotifyContext (:99) puts
Ctrl-C on the path that reaches it, so the leak had a route to whatever
telemetry backend is configured. classifyItemError guards the run manifest
against raw error text for the same reason.
Add runGitSplit and give the three diff-producing callers stderr alone. Git
writes its diagnosis to stderr by construction, since die() writes there, so
this loses nothing a reader wants and cannot carry diff. Mirrors runGitGrep in
internal/tool/code_search.go, cancellation guard included: a signalled process
reports the signal rather than the reason, so a cancelled run now says
"context deadline exceeded" instead of "signal: killed" -- which also lets
classifyItemError reach its timeout class instead of the generic provider one.
The three failure modes this PR targets write to stderr, so their messages are
byte-identical and #972 still gets its diagnosis.
workspaceTrackedDiff returns stderr separately rather than overloading its
first return value, which also retires the dual-meaning the earlier review
flagged.
Also fix the regression test asserting "fatal:"/"error:", which git
translates: under zh_CN the line opens with a translated prefix, so it passed
only because CI runs in English. Anchor on the object name instead, the one
part no locale rewrites -- the same pairing isNotGitRepoError uses.
* docs(diff): correct the reasons recorded around gitFailure
Two comments described mechanisms that are not there.
The cancellation assertion in TestGetDiff_CancelledMidWriteReportsCancellation
credited classifyItemError with reading the error's type. It never sees it:
GetDiff is reached through loadDiffs, whose failure is recorded at agent.go:284
as a fixed SetRunFailure(RunFailureInput, "failed to resolve review input")
without inspecting err. classifyItemError has a single call site, agent.go:712,
for per-item subtask errors. Neither reviewResultError nor main.go branches on
the type either, so nothing downstream observes it today.
What the assertion actually holds is runGitSplit's cancellation guard: the leak
assertion above it passes either way, since quoting stderr alone keeps stdout
out of the error, so without this second assertion the guard could be removed
silently. Verified by dropping the guard -- only this assertion fails.
gitDiagLimit and gitFailure still justified themselves by runGit's combined
output, which no caller passes anymore. The ceiling and the keep-the-tail rule
both survive on stderr, but for a different reason: die() exits the process, so
the fatal is last, behind any warnings. Parameter renamed out -> stderr to match
what the three call sites pass.
No behavior change. make test, go vet, gofmt, english-only and coverage (94.0%)
all pass.
---------
Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com>
|
||
|
|
e95bdda4f2
|
feat(cli): add --output flag to write review/scan results to a file (#852)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
* feat(cli): add --output flag to write review/scan results to a file Add `--output <path>` / `-o` to `ocr review` and `ocr scan`, writing the result JSON or text directly to a UTF-8 file instead of stdout. The file is created lazily on the first write so a failed run never truncates an existing target; text-mode files are ANSI-stripped so terminal color codes never pollute the result file. A `[ocr] Results written to <path>` hint is printed to stderr once the file is actually created, and failure output keeps going to stderr so agents always find the failure reason. Closes #851 Signed-off-by: 历代星辰 * test(cli): cover --output flag parsing and file output behavior Add tests for --output/-o flag parsing, the stripAnsiWriter state machine (including escape sequences split across Write calls), lazy file creation (failed runs leave existing targets untouched, never-written targets are not created), and the Results-written stderr hint. Adapt existing emitRunResult / renderComment / outputPreview call sites to the new io.Writer parameter. Signed-off-by: 历代星辰 * fix(test): isolate USERPROFILE so Windows tests never touch the real OCR home os.UserHomeDir() prefers USERPROFILE over HOME on Windows, so t.Setenv("HOME", ...) alone left tests reading and writing the developer's real ~/.opencodereview: config tests overwrote config.json and session/agent tests polluted the sessions store. Add a setTestHome helper (per affected package) that also overrides USERPROFILE, and route every scattered HOME override through it. Signed-off-by: 历代星辰 * fix(cli): propagate output write failures and strip multi-byte ANSI escapes Address the ocr review findings on the --output feature: - lazyFileWriter now records the first write error (Err()) and emits the "Results written" hint only after a successful write; emitRunResult and outputPreview check it after text rendering, so a failed --output write (permission, disk full) exits non-zero like JSON mode already does instead of silently exiting 0 with no file. - stripAnsiWriter keeps multi-byte escapes (ESC + intermediate byte, DCS/PM/APC strings) inside the escape state so trailing bytes are discarded with the sequence instead of leaking into the result file. Signed-off-by: 历代星辰 * fix(cli): re-parse trailing byte after bare-ESC OSC termination and fix Write return semantics Addresses review comments on #852: - stripAnsiWriter ansiOSCEsc: a non-ST byte after ESC is no longer dropped. The OSC ends at a bare ESC terminator and the trailing byte is re-parsed — an ESC starts a new escape sequence, any other byte is forwarded as text. Previously the first byte after a bare-ESC-terminated OSC was silently lost. - stripAnsiWriter Write: report the underlying dst error but return len(p), since the state machine has already consumed the input; returning 0 made a caller retrying on n < len(p) feed the same bytes through twice. - Clarify --output help text: default is stdout and '-' also means stdout. Adds regression tests for both bugs (bare-ESC + trailing text, bare-ESC + new escape, and dst-failure return contract). Signed-off-by: 历代星辰 * fix(cli): reinforce ANSI stripper state machine and validate format flag * docs(cli): document output flag across localized references and READMEs * fix(cli): cap escape intermediate bytes and normalize format in output handlers --------- Signed-off-by: 历代星辰 |
||
|
|
6612029127
|
fix(scan): join background memory compression before session finalization (#1026)
Some checks failed
CI / cross-compile (arm64, linux) (push) Has been cancelled
CI / cross-compile (arm64, windows) (push) Has been cancelled
CI / test (push) Has been cancelled
CI / windows (push) Has been cancelled
CI / cross-compile (amd64, darwin) (push) Has been cancelled
CI / cross-compile (amd64, windows) (push) Has been cancelled
CI / cross-compile (arm64, darwin) (push) Has been cancelled
CodeQL Advanced / Analyze (go) (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
* fix(scan): join background memory compression before session finalization
* test(scan): exercise background compression join barrier in ScanAgent.Run
- Rewrite TestScanAgent_WaitBackground_NoLeakOnRun using a blocking compression client pattern
- Verify that ScanAgent.Run waits for in-flight memory compression before session finalization
- Assert that memory_compression_task is recorded and session_end is the final record in session JSONL
- Update Runner.WaitBackground doc comment in llmloop/loop.go to reflect scan mode usage
* style: format internal/scan/agent_test.go with gofmt -s
* test(scan): avoid premature cancel exit in blocking compression mock
* fix(test): eliminate race in WaitBackground regression test
The original test had two timing bugs that made it pass even when
WaitBackground() was removed:
1. The mock's round-2 response (task_done) could return before the
background compression goroutine reached the mock, allowing Run to
finish before 'started' was ever closed. Fix: round 2 now waits on
<-c.started so the main loop cannot complete until compression is
in-flight.
2. The 'select { default: }' check fires instantly — if Run hadn't
returned YET (still in cleanup, not because WaitBackground held it),
the test passed spuriously. Fix: use time.After(200ms) which is
vastly longer than the sub-millisecond cleanup path, so Run will
have returned if WaitBackground is missing.
Verified: test now correctly FAILs when WaitBackground is commented out
and PASSes when it is present.
---------
Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com>
|
||
|
|
132de7d55b
|
fix(scan): persist safe dedup checkpoints on resume (#1035)
* fix(scan): persist deduplicated comments on resume * fix(scan): preserve dedup checkpoint provenance * refactor(scan): return batch error last |
||
|
|
3b11812fff
|
feat(cli): clarify LLM request failures by review stage (#1022)
Some checks are pending
CI / test (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
* feat(cli): group the LLM retry report by review stage Make the text retry report easier to scan by grouping noteworthy LLM requests only by review stage. Replace internal task_type and request_no labels with human-readable stage names and error phrases, render each request on one line, and make the summary explicit that failed outcomes are request failures. Within each stage, list failed requests before recovered requests and sort matching outcomes by path. Cap each stage at five entries while keeping full details in JSON. Keep the change rendering-only: the retry report schema, manifest wording, JSON fields, warnings, and retry behavior remain unchanged. * test(cli): align retry report assertions * fix(cli): handle retry report edge cases * style(cli): keep the retry report terminal output ASCII-only The grouped report introduced U+2192 and U+2014 as separators. Both pass english-check (it tests for letters, not for non-ASCII bytes), but they render as replacement glyphs on a terminal that is not UTF-8 and they break a habitual grep for "-> failed". The arrow returns to "->", as it was before the regrouping. The two em dashes cannot both become "--" without reading oddly, so the entry separator becomes ":" -- the form the flat listing used, and the one that reads as "this file: this is what happened to it" -- while the summary line keeps a dash as "--". Terminal rendering only. The JSON report never went through this path: outputJSONWithWarnings encodes llm.RetryReport directly, so error_class stays the raw enum and attempts stays a structured array. --------- Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
4d61c979a8
|
fix(vscode): list merge commit files (#1029) | ||
|
|
4b6874bd23
|
fix(agent): name the main-loop stop trigger in item failure reasons (#855)
Some checks failed
CI / cross-compile (amd64, darwin) (push) Has been cancelled
CI / cross-compile (amd64, windows) (push) Has been cancelled
CI / test (push) Has been cancelled
CI / windows (push) Has been cancelled
CI / cross-compile (arm64, darwin) (push) Has been cancelled
CI / cross-compile (arm64, linux) (push) Has been cancelled
CI / cross-compile (arm64, windows) (push) Has been cancelled
CodeQL Advanced / Analyze (go) (push) Has been cancelled
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Pages / build (push) Has been cancelled
Deploy Pages / deploy (push) Has been cancelled
* fix(agent): name the main-loop stop trigger in item failure reasons StopEmptyRounds and StopCompression previously collapsed into the same "main task stopped before completing" string as StopNone, so a failed item's manifest could not say whether the model spun without usable tool results or the context outgrew its compression threshold. In --format json runs the progress lines that name the trigger are discarded, which made the manifest reason the only diagnostic that leaves a CI runner — and it said the same thing for every stop. Keep the unknown failure class (the taxonomy has no fitting category) but give each stop its own reason, mirroring the StopMaxRounds precedent. Fixes #842 * fix(llmloop): share the main-loop stop reason with the scan path PR #855 named the empty-round and compression stops in the diff-review manifest reason, but two gaps remained. A MainLoopStop constant added later would fall through classifyMainLoopStop's default and inherit the collapsed "main task stopped before completing" text without failing a test — the exact shape of #842, reintroduced by the next enum addition. classifyMainLoopStop now keys only on StopMaxRounds for the budget class and delegates every reason to MainLoopStop.Reason(), whose own default names the unrecognized value. internal/scan discarded the MainLoopStop entirely and hardcoded a second opaque sentence. Scan sessions opt out of the run manifest, so that string is their whole diagnostic: warningsForOutput only drops scan_subtask_error warnings when a manifest exists, and under --format json the [ocr] progress lines that would say which exit fired are discarded. It now appends the shared Reason(), keeping the prefix that resume records and existing warnings match on. MainLoopStop also gains String(), so a stop no longer formats as a bare integer in telemetry, logs and test failure messages. Tests pin String() and Reason() for every stop, assert neither collides across stops, and fail when a constant is added past StopCompression — the prompt to give it its own case. The scan warning test now requires the trigger to be named rather than only that the task did not complete. --------- Co-authored-by: Fanzzzd <fanzzzd@users.noreply.github.com> Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
43bbc48779
|
refactor(background): treat --background and --background-file as mutually exclusive with file precedence (#1016)
* refactor(background): treat --background and --background-file as mutually exclusive with file precedence Replace mergeBackground with selectBackground: when both flags are provided, --background-file wins and --background is ignored (with a stderr warning). The commit-message fallback now fires only when neither entry point was used. This fixes the inconsistency where review and delegate produced different backgrounds for equivalent input (issue #1013), and makes the effective background deterministic regardless of which command is invoked. Closes #1013 * refactor(background): extract resolveBackground helper and fix tests Address reviewer feedback: - Extract resolveBackground() so review and delegate share one call site, making future drift impossible. - Rewrite tests to call resolveBackground directly instead of duplicating the if/else-if logic (which could never fail). - Fix stale comment on TestBackgroundFilePrecedenceOverCommit. |
||
|
|
699c91444a
|
test(llm): cover tool_choice mapping for all three provider protocols (#1011)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
Add table-driven tests for buildOpenAIParams, buildAnthropicParams, and buildResponsesParams asserting how ChatRequest.ToolChoice="required" is translated into each SDK's own tool_choice representation, and that the mapping is skipped when no tools are attached. These parameter-building functions previously had no direct coverage for tool_choice, so a regression in any of the three branches would go unnoticed by CI. |
||
|
|
9c5e90d0b1
|
feat(providers): add AWS Bedrock as a built-in provider with native SigV4 auth (#705)
* feat(providers): add AWS Bedrock as a built-in provider
Bedrock serves the same Messages API as api.anthropic.com, so this reuses
AnthropicClient wholesale and lets the official SDK's bedrock middleware
handle what differs: SigV4 signing, moving the model from the body into the
URL path, injecting anthropic_version, and deriving the host from the region.
No new protocol implementation, no AWS request plumbing.
Configuration is an empty provider entry — there is no api_key to set:
{
"provider": "bedrock",
"model": "us.anthropic.claude-sonnet-4-6",
"providers": { "bedrock": { "aws_profile": "...", "aws_region": "..." } }
}
aws_profile and aws_region are optional; without them the standard AWS chain
decides, as with any other AWS tool. Setting them makes a run reproducible
without exporting AWS_PROFILE first. Model accepts a foundation model ID, an
inference profile ID, or an application inference profile ARN when usage has
to be attributed for cost allocation.
Four things this needed beyond registering a provider, each found by running
it rather than reading it:
- The resolver required a non-empty api_key, and separately required both
URL and Token to consider an endpoint complete. Bedrock has none of the
three, so a correct config fell through every strategy and reported "no
valid LLM endpoint configured" — the error for having configured nothing.
Both gates now recognise ambient authentication, via an AmbientAuth flag
on Provider and ResolvedEndpoint. Providers that do use api_key are
unaffected, which TestNonAmbientProviderStillRequiresAPIKey pins.
- bedrock.WithConfig prefers bearer auth over SigV4 whenever
cfg.BearerAuthTokenProvider is non-nil, and LoadDefaultConfig populates
that provider from the SSO token cache. An SSO-authenticated caller —
most enterprise setups — therefore sent its OIDC access token and got
403 "Invalid API Key format: Must start with pre-defined prefix". The
provider is cleared unless AWS_BEARER_TOKEN_BEDROCK was set deliberately,
which restores SigV4 while leaving an explicit bearer token working.
- The SDK would also attach an API-key header of its own, which Bedrock
rejects even when empty. Authorization and X-Api-Key are removed before
the signing middleware runs.
- bedrock.WithLoadDefaultConfig panics when AWS config cannot be loaded.
A CLI should not answer an expired session with a stack trace, so the
config is loaded directly and the failure deferred to the first request
as a sentence naming the likely fix.
The preset's Models list is taken verbatim from `aws bedrock list-inference-profiles`
on a live account rather than inferred: suffix conventions vary per family, so
us.anthropic.claude-sonnet-5 is correct while us.anthropic.claude-sonnet-5-v1:0 is
rejected with 400 "The provided model identifier is invalid." The global.* cross-region
variants are listed alongside us.* since either is a valid routing target. That list
only gates --model overrides; an application inference profile ARN still works via the
model field.
Two existing tests needed updating: the provider-order list gains "bedrock",
and TestProviders_AllProtocolsCanonical now delegates to ValidateProtocol
instead of re-listing the canonical names, so the next protocol added cannot
silently leave it behind.
Verified end-to-end against a live Bedrock account: reviews complete and
return findings using SigV4 credentials from an SSO profile, with no AWS
variables in the environment.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* feat(config): configure and diagnose an ambient-auth provider from the CLI
Registering the provider was not enough to make it usable: every config-related
path still assumed an api_key, and Bedrock's own error wording sends users after
the wrong problem.
- ProviderEntry gains aws_profile and aws_region. They were readable by the
resolver but absent from the struct the CLI marshals, and config is
unmarshalled into it and written back on every config command — so a
hand-written aws_region was silently deleted the first time the user ran
`ocr config model`, with no error and nothing to suggest why the next review
reached a different region.
- `ocr config set providers.<name>.aws_region|aws_profile` now works, for both
the providers and custom_providers paths. Values are trimmed; whitespace
inside one is rejected. Region names are deliberately not validated against
a fixed list — AWS adds regions faster than an embedded list stays correct,
and a wrong region already fails at request time. Setting either field on a
provider that authenticates by api_key is an error rather than dead config
that reads as applied.
- The provider wizard treats the model step as final for an ambient provider
instead of demanding a key. An API-key prompt that has to be left blank reads
as a step the user failed to complete, and applyOfficialProviderConfig
rejected the empty value anyway, so bedrock was unreachable through
`ocr config provider` entirely. The gate is now a named check keyed off
AmbientAuth, so key-based providers keep the requirement.
- `ocr llm test` prints the resolved region and profile in place of the URL,
which is empty for bedrock because the region decides the host. A request
that reached the wrong region otherwise fails as though the model ID were
malformed.
- Bedrock rejections are translated into the action that fixes them, since two
of them are actively misleading as the service words them: "Invalid API Key
format" names a credential no bedrock user can configure (it means a bearer
token reached the request), and a model merely absent from the region comes
back as "The provided model identifier is invalid." Expired credentials point
at `aws sso login` with the profile filled in; AccessDenied is named as an
IAM gap on bedrock:InvokeModel rather than a bad credential; a rejected model
points at `aws bedrock list-inference-profiles` and the -v1:0 suffix trap.
Every other protocol shares this client type, so the translation is gated on
the bedrock flag and returns other errors untouched.
The unknown-config-key message is pinned byte-for-byte by an existing test; it is
updated for the two new provider fields and for anthropic-bedrock as a protocol
value.
Verified against a live Bedrock account: `ocr llm test` reports region and
profile and completes over SigV4; a -v1:0 model ID and an unresolvable profile
each produce their intended message rather than a bare 400 or 403.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(bedrock): correct bearer-token precedence, error triage, and model gating
Four defects found reviewing the two commits before this one. Each was verified
by execution or against SDK source, not inferred.
- AWS_BEARER_TOKEN_BEDROCK was unreachable for exactly the users it was meant
to serve. The provider was cleared only when the variable was unset, on the
strength of WithConfig's doc comment ("if the AWS_BEARER_TOKEN_BEDROCK
environment variable is set, it is used"). The code disagrees with that
comment: bedrock.go consults the variable only `if
cfg.BearerAuthTokenProvider == nil`. So an SSO profile plus a deliberately
configured Bedrock API key sent the SSO OIDC token instead of the key — the
same silent substitution this patch exists to prevent, and explainError then
blamed a token that never left the machine. Cleared unconditionally now,
which is what gives the variable the precedence it documents.
- A model that the account has not enabled was reported as an IAM problem.
Bedrock answers both authorization failures with AccessDeniedException, and
the fixes have nothing in common: "You don't have access to the model with
the specified model ID" needs model access granted in the console, per
account and per region, which no IAM policy provides. The specific wording
is now matched ahead of the generic code, and the clause for it is no longer
stranded in an unreachable branch.
- A bare ValidationException match claimed every request-shape rejection was a
model-ID problem: "Input is too long for requested model" sent the user off
to list inference profiles. Only the model-identifier wording is matched now;
everything else keeps the service's own message, which is the whole point of
the function. The credential-expiry arm likewise no longer matches a bare
"expired", which caught `x509: certificate has expired`.
- --model rejected any Bedrock identifier absent from the preset's Models list,
contradicting both the preset's own comment and this PR's description. A
preset list cannot be an allowlist here: identifiers are scoped to an account
and a region, and an application inference profile ARN — the value to use
when spend has to be attributed — can never appear in a list compiled
upstream. The list stays a picker for `ocr config model`; it no longer gates
an override for an ambient-auth provider. Key-based providers keep the
check, so a typo against a hosted API is still caught locally.
Also: dropped a cfg.URL normalization block that could not have any effect,
since WithConfig is appended last and installs its own base URL — the comment
claimed a purpose the code did not have. Pinned AWS_CONFIG_FILE in the test that
constructs a client, which was reading the developer's real ~/.aws/config. Fixed
the column alignment of the region line in `ocr llm test`.
Verified: `ocr llm test` still completes over SigV4 against a live account; an
identifier the preset does not list now reaches Bedrock and returns Bedrock's own
verdict rather than a local rejection.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(bedrock): honour an entry-level protocol override for ambient auth
OCR's own review of this PR found that ambient auth was read off the preset while
the protocol could be overridden per entry, which left two ways to configure
something that reads as applied and cannot work.
`providers.bedrock.protocol = openai` resolved with no api_key and no URL: the
key requirement was skipped because the preset declares AmbientAuth, but the
endpoint then spoke a protocol with no SigV4 signing and carried nothing to
authenticate with. Ambient auth is now derived from the protocol actually in
force, after the override is applied, so such an entry needs a token again — and
conversely an entry that selects the bedrock protocol explicitly signs its
requests whatever preset it sits under. The same value gates the --model
allowlist, which had the same preset-only assumption.
`ocr config set providers.bedrock.aws_region` accepted AWS settings on that same
overridden entry. The check now lets the entry's protocol decide whenever it sets
one, falling back to the preset's flag only when the entry is silent.
Also corrects two stale doc comments the review flagged: ValidateProtocol accepts
four protocol names, not three, and the package comment now lists
anthropic-bedrock among the supported protocols.
The third finding in that review — a bare ValidationException match in
explainError — was already fixed in the preceding commit; the bot reviewed the
commit before it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* build(deps): bump aws-sdk-go-v2 to clear GO-2026-5764
govulncheck fails the CI test job because the pinned AWS SDK tree pulls
in github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3, which
is affected by GO-2026-5764 (fixed in v1.7.8). Upgrading the direct
dependency aws-sdk-go-v2/config to current resolves eventstream to
v1.7.16, past the fixed version.
The diff is scoped to the AWS module tree (plus smithy-go, its runtime
companion); no other dependencies move. The Bedrock provider's behavior
is unchanged: the newer config module still populates
BearerAuthTokenProvider from the SSO token cache, so the unconditional
clearing in NewAnthropicBedrockClient remains necessary and correct,
and it still does not consult AWS_BEARER_TOKEN_BEDROCK itself, so the
anthropic-sdk-go re-read of that variable keeps its documented
precedence.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(bedrock): correct error triage, ambient credential handling, and the protocol's reach
Addresses the six pre-merge items from review.
- "not authorized to invoke this API operation" sat in the model-access
branch. It is IAM's own wording, so it pointed at a console toggle when
the fix is a policy change; it now falls to the AccessDenied branch,
whose message names bedrock:InvokeModel. A test case carries the phrase
without "AccessDenied" in the text, so the phrase itself is pinned to
the authorization branch rather than the exception name.
- TestExplainErrorClassifiesBedrockFailures read the ambient
AWS_BEARER_TOKEN_BEDROCK and asserted the message produced when it is
unset, so the suite failed on any machine that exports one. It pins the
variable empty. Reproduced before the fix with
AWS_BEARER_TOKEN_BEDROCK=sk-x go test -run TestExplainError.
- api_key_cmd ran for an ambient-auth provider. The output is discarded by
a signed request, and the command is typically a secret-manager read, so
a bedrock user got a real 1Password / Touch ID prompt for nothing — while
the comment above the call claimed it could not happen. Gated on
!ambientAuth; the new test proves non-execution with a sentinel file, and
fails without the gate.
- llm.protocol and OCR_LLM_PROTOCOL validated anthropic-bedrock and then
ignored it. Both strategies describe one URL and one token, have nowhere
to carry a region or a profile, and bedrock uses neither value they do
carry, so the request would have been signed and re-hosted with the rest
of the block silently dropped. Both now reject it, as does
`ocr config set llm.protocol`, at the point the value is typed.
- The custom-provider contract was split in two: the TUI never offered
bedrock, while the resolver demanded a url the bedrock client never
reads. Settled toward supporting it — a provider entry is the one place
with somewhere to put aws_region and aws_profile, which is what lets a
second region or profile have its own entry. url is now required for
every protocol except bedrock, the Custom form offers bedrock and ends at
the protocol step (there is no url, api key or auth header to collect),
and switching an existing entry to it clears the three fields the
previous protocol needed rather than leaving them as dead config. The
Manual form keeps the three-protocol list, since it writes llm.url and
llm.auth_token.
- Documented the bedrock.WithConfig append site: options wrap in order, so
appending last leaves signing innermost — closest to the wire, and re-run
on each retry rather than replaying a stale signature.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* docs(pages): document the bedrock provider in all four locales
The provider shipped with no documentation: no row in the built-in table, and
no mention of aws_region or aws_profile, so the only way to learn either field
existed was to read the resolver.
Adds to en, ja, ru and zh:
- a `bedrock` row in the built-in provider table, with the host derived from
aws_region and no API key env var, since neither applies;
- an "AWS Bedrock" section covering the two AWS fields and what each falls
back to, why model IDs are not validated against the shipped list (they are
scoped to an account and a region, and an application inference profile ARN
can never appear in a list compiled upstream), the `-v1:0` suffix trap, and
the region/profile lines `ocr llm test` prints in place of a URL;
- anthropic-bedrock in the custom-provider protocol list, with the example
that needs no url and takes the same AWS fields — the supported way to run
a second region or profile;
- a note that llm.protocol and OCR_LLM_PROTOCOL reject it, and why.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix(bedrock): clear stale AWS settings on protocol switch, bound config load
applyProviderField's "protocol" case only validated and wrote the new
protocol, leaving aws_region/aws_profile behind when an entry switched
away from anthropic-bedrock. Setting the AWS fields first (while the
entry was still ambient) and only then switching protocol produced
exactly the dead config the aws_region/aws_profile write path already
guards against on the other ordering. Clear both fields when the new
protocol isn't anthropic-bedrock, with a stderr warning, mirroring the
TUI's cpAmbientProtocol() cleanup.
Also bound NewAnthropicBedrockClient's awsconfig.LoadDefaultConfig with
a context timeout instead of context.Background(), as defense in
depth against network calls region auto-detection can still make.
Credential resolution itself (SSO refresh, AssumeRole,
credential_process) is lazy and already bounded by cfg.Timeout at
request time, so this does not fix an observed hang, but removes an
unbounded context where the AWS SDK's own defaults are the only guard.
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com>
|
||
|
|
756203c31a
|
fix(cmd): suppress ANSI color when stdout is not a TTY (#927)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
* fix(cmd): suppress ANSI color when stdout is not a TTY Text output hardcoded ANSI escape sequences with no terminal detection, so piping or redirecting a review leaked raw escapes into the consumer. Piping into `gh issue comment` produced a comment full of literal `^[[2m` sequences. Color is now resolved once per run, in this order: `--no-color`/`--color=never` turn it off, `--color=always` forces it on even through a pipe, `NO_COLOR` (any non-empty value, per no-color.org) and `TERM=dumb` turn it off, and otherwise it follows whether stdout is a terminal. Explicit flags outrank the environment because a flag is a per-invocation decision while the variable is a standing preference. Both text paths — review findings and `--preview` — route every escape through colorize(), so plain mode keeps all the information the color carried: the diff gutter still shows +/-/space and the status badges still read [A]/[M]/... Preview counts are padded before colorizing so the columns align in either mode. The flags are persistent on the root command, so `ocr --no-color review` and `ocr review --no-color` are equivalent, and an invalid `--color` value is rejected rather than silently treated as auto. Fixes #682 * refactor(cmd): drop --no-color flag and NO_COLOR env var support --no-color was just an alias for --color=never with no added capability, and NO_COLOR isn't a universal enough convention to bake in speculatively. --color <auto|always|never> alone already covers every case. TERM=dumb stays, since that closes a real gap in TTY detection rather than adding another way to configure the same toggle. --------- Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
d8fc4cd2af
|
chore(examples): add explicit --audience agent to codeup_ci and action.yml (#1004)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Since PR #929 made 'human' the default audience and redirected [ocr] progress lines to stderr, the two non-interactive CI call sites that omitted --audience now emit progress noise on stderr. Add --audience agent to match the other four examples. - examples/codeup_ci/post_review.py: add --audience agent to cmd - action.yml: add --audience agent to ARGS (also covers github_actions) - examples/codeup_ci/post_review_test.py: update exact cmd assertion Exit-code handling, JSON parsing, and comment-posting logic are unchanged. Closes #1003 |
||
|
|
f6e5e98564
|
refactor(skill): simplify review flow, use native severity (#1002)
* refactor(skill): move prerequisites check to troubleshooting section - Remove upfront `which ocr` / `ocr llm test` from main workflow - Keep inline installation fallback hint in Step 2 - Add Troubleshooting section with install and LLM config guidance - Update Gotchas entry to reference Troubleshooting instead of requiring pre-run check * refactor(skill): use native OCR severity/category instead of manual classification - Step 3: remove manual High/Medium/Low classification; use OCR output severity/category directly - Step 4: reference severity field instead of custom priority levels - Output Format: add category/severity to field list; group template by severity - Remove duplicated Priority classification definition - Retain mispositioned comments handling and thinking field * refactor(skill): apply prerequisites/severity refactor to canonical skill Mirrors the plugin skill refactor: - Move prerequisites check to Troubleshooting section - Use native OCR severity/category instead of manual classification - Retain mispositioned comments handling and thinking field - Retain truncation guidance added in |
||
|
|
66d71b23eb
|
fix(cmd): stream review progress to stderr for json and sarif (#929)
`--audience human --format json` ran completely silent: newQuietHandle replaced stdout with io.Discard whenever the format was machine-readable, without ever looking at the audience, so `--audience human` was ignored and the user watched a blank terminal until the document appeared at the end. `--format text` streamed progress but is not stable to parse, leaving no way to have both live progress and machine-readable output. Progress is now redirected to stderr instead of discarded when a human asked to watch a machine-readable run. This is safe because every result document (json, sarif, text) is encoded straight to os.Stdout and never travels through stdout.Writer(), so stdout remains a single parseable document while stderr carries the live [ocr] lines. Discarding was never necessary to protect stdout; the two streams were already separate. The three cases are now explicit: audience=agent discards progress regardless of format because the caller asked for none, a machine-readable format with a human audience redirects to stderr, and everything else leaves progress on stdout. Progress lines keep their existing text form. Emitting them as structured NDJSON events, which the report also asks for, would mean defining an event schema and reworking every call site; it is left for separate work. Tests cover where progress lands for each format/audience pair, that stdout stays empty and parseable while stderr receives the lines, and an end-to-end review asserting stdout unmarshals as JSON with no [ocr] line while stderr shows progress. Reverting the fix fails exactly the human-audience assertions and leaves the agent ones passing. The flag help and the CLI reference in all four locales are updated, along with the tip that implied `--format json` means a quiet terminal. Fixes #928 |
||
|
|
f269d0ce00
|
chore(deps): bump the go-dependencies group across 1 directory with 18 updates (#880)
Bumps the go-dependencies group with 14 updates in the / directory: | Package | From | To | | --- | --- | --- | | [charm.land/bubbles/v2](https://github.com/charmbracelet/bubbles) | `2.1.0` | `2.1.1` | | [charm.land/bubbletea/v2](https://github.com/charmbracelet/bubbletea) | `2.0.7` | `2.0.8` | | [charm.land/lipgloss/v2](https://github.com/charmbracelet/lipgloss) | `2.0.4` | `2.0.6` | | [github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go) | `1.55.1` | `1.63.1` | | [github.com/modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) | `1.6.1` | `1.7.0` | | [github.com/openai/openai-go/v3](https://github.com/openai/openai-go) | `3.41.0` | `3.51.0` | | [github.com/spf13/pflag](https://github.com/spf13/pflag) | `1.0.9` | `1.0.10` | | [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | | [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | | [go.opentelemetry.io/otel/exporters/stdout/stdoutmetric](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | | [go.opentelemetry.io/otel/exporters/stdout/stdouttrace](https://github.com/open-telemetry/opentelemetry-go) | `1.44.0` | `1.45.0` | Updates `charm.land/bubbles/v2` from 2.1.0 to 2.1.1 - [Release notes](https://github.com/charmbracelet/bubbles/releases) - [Commits](https://github.com/charmbracelet/bubbles/compare/v2.1.0...v2.1.1) Updates `charm.land/bubbletea/v2` from 2.0.7 to 2.0.8 - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v2.0.7...v2.0.8) Updates `charm.land/lipgloss/v2` from 2.0.4 to 2.0.6 - [Release notes](https://github.com/charmbracelet/lipgloss/releases) - [Commits](https://github.com/charmbracelet/lipgloss/compare/v2.0.4...v2.0.6) Updates `github.com/anthropics/anthropic-sdk-go` from 1.55.1 to 1.63.1 - [Release notes](https://github.com/anthropics/anthropic-sdk-go/releases) - [Changelog](https://github.com/anthropics/anthropic-sdk-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/anthropics/anthropic-sdk-go/compare/v1.55.1...v1.63.1) Updates `github.com/modelcontextprotocol/go-sdk` from 1.6.1 to 1.7.0 - [Release notes](https://github.com/modelcontextprotocol/go-sdk/releases) - [Commits](https://github.com/modelcontextprotocol/go-sdk/compare/v1.6.1...v1.7.0) Updates `github.com/openai/openai-go/v3` from 3.41.0 to 3.51.0 - [Release notes](https://github.com/openai/openai-go/releases) - [Changelog](https://github.com/openai/openai-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/openai/openai-go/compare/v3.41.0...v3.51.0) Updates `github.com/spf13/pflag` from 1.0.9 to 1.0.10 - [Release notes](https://github.com/spf13/pflag/releases) - [Commits](https://github.com/spf13/pflag/compare/v1.0.9...v1.0.10) Updates `go.opentelemetry.io/otel` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/exporters/stdout/stdoutmetric` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/exporters/stdout/stdouttrace` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/metric` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/sdk` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/sdk/metric` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) Updates `go.opentelemetry.io/otel/trace` from 1.44.0 to 1.45.0 - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.44.0...v1.45.0) --- updated-dependencies: - dependency-name: charm.land/bubbles/v2 dependency-version: 2.1.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: charm.land/bubbletea/v2 dependency-version: 2.0.8 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: charm.land/lipgloss/v2 dependency-version: 2.0.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: github.com/anthropics/anthropic-sdk-go dependency-version: 1.62.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/modelcontextprotocol/go-sdk dependency-version: 1.7.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/openai/openai-go/v3 dependency-version: 3.50.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: github.com/spf13/pflag dependency-version: 1.0.10 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdoutmetric dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/exporters/stdout/stdouttrace dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/metric dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/sdk dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/sdk/metric dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies - dependency-name: go.opentelemetry.io/otel/trace dependency-version: 1.45.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
68492a5372
|
feat(installation): support asset download via OCR_GITHUB_MIRROR (#893)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
* rewrite mirrored install shell script * rewrite mirrored install pwsh script and code cmt * scripts updates * spelling qwq * docs: update * docs: powershell users * merge scripts * warn about security risks & docs * trim the DOMAIN string * fix spelling * docs: update fix naming * docs: refactor docs * fixes * apply suggestions * fix: download checksums from mirror * docs: clarify mirror security * fix(installation): normalize OCR_GITHUB_MIRROR input across platforms - Strip https://, http:// scheme prefix and trailing slash automatically - Unify whitespace handling: trim leading/trailing only, error on internal spaces - Both install.sh and install.ps1 now behave identically for edge inputs --------- Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
ab9a83e36d
|
chore(ci): change dependabot schedule from weekly to monthly (#998)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
|
||
|
|
35a06a4951
|
feat(providers): add gemini to built-in providers (#930)
* add gemini providers and tests * docs: update * chore: add more models * chore: reorder models * fix: Apply suggestion from @lizhengfeng101 --------- Co-authored-by: Kite <254839944+lizhengfeng101@users.noreply.github.com> |
||
|
|
24c2dd0cde
|
feat(language): add support for .ipynb files (#980)
Some checks are pending
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
* chore: new extensions for `.ipynb` * docs: update site docs * chore(allowlist): skip Jupyter .ipynb_checkpoints autosaves Jupyter writes autosave copies of a notebook into a sibling .ipynb_checkpoints/ directory. Now that .ipynb is in the extension allowlist, an accidentally committed checkpoint would be reviewed as a regular file and produce comments duplicating those on the real notebook. Exclude the directory by default, alongside the other tool-generated artifacts. --------- Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
6c4a89faaf
|
feat(allowlist): add Thrift and Cap'n Proto support (#960)
Thrift IDL (.thrift) and Cap'n Proto schema (.capnp) files were dropped at the extension gate, so no rule could ever run on them. Both are IDLs whose main review risk is silent wire-compatibility breakage, which is exactly what protobuf.md already covers for .proto. Adds both extensions to the allowlist, registers thrift.md and capnp.md in path_rule_map, and excludes the compilers' generated output. The gen-* and kitex_gen excludes are scoped by extension rather than by directory because IsExcludedPath applies every pattern to every path with no language dispatch; a bare gen-*/** would drop unrelated files in other languages. Data only, no Go source changes. |
||
|
|
9a01ec0427
|
feat(lang): review support for R (#988)
* feat: new support for R * docs: update * chore: update site docs * fixup: missing * for mapper * chore; switch r to uppercase * fix: `internal/config/allowlist/allowed_ext_test.go` |
||
|
|
794a971a9a
|
i18n(pages): add Korean (ko) locale (#857)
Add a complete Korean translation of the docs site UI strings and wire ko
into the language switcher.
- pages/src/i18n/ko.ts: all 273 keys from en.ts, in the same order.
Terminology follows README.ko-KR.md (세션 뷰어, 텔레메트리, 위임 모드,
정밀도/재현율). Product names, protocol names, CLI flags and code
identifiers are left in their original form.
- Language union, translations record and SUPPORTED_LANGUAGES gain 'ko',
so browser language detection picks up ko-KR automatically.
- Navbar/Footer language menus list 한국어; the navbar badge glyph 한 gets
a Korean font stack instead of falling back to the Chinese one.
- docsMap gains an empty ko entry: doc pages fall back to English until
pages/src/content/docs/ko/ is contributed in a follow-up.
- styles/index.css: word-break: keep-all scoped to :lang(ko). Korean
separates 어절 with spaces, and the default breaking split headings
mid-word ("Agent 시스" / "템"). zh/ja depend on any-character breaking
and are verified unchanged; keep-all is a no-op for Latin text.
Verified with npm run typecheck, lint, test, build and size, plus headless
screenshots of the ko locale at 1440px across home, features, benchmark,
quickstart and docs.
Refs #471
|
||
|
|
c4d3f52b72
|
feat(allowlist): add Zig support (#937)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Recognize .zig source files in the review allowlist, exclude conventional Zig test files, and add a Zig-specific review rule doc so .zig changes no longer fall back to the generic default checklist. - Add .zig to supported_file_types.json - Exclude **/test/**/*.zig and **/*_test.zig in default_exclude_patterns.json - Map .zig to a new rule_docs/zig.md via system_rules.json - Cover extension recognition, test-path exclusion, and rule resolution in tests |
||
|
|
533f7367cd
|
fix(updater): discard stale version hints (#720)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
|
||
|
|
b712856403
|
docs(site): update for elm (#978)
Some checks are pending
CI / test (push) Waiting to run
CI / windows (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
|
||
|
|
6cc10949a6
|
fix(ci): line endings check fails on symbolic links (#952)
* fix(ci): line endings check fails on symbolic links * chore: update err msg |
||
|
|
ec5f6851d2
|
fix(pages): make install-channel command box scrollable (#912) | ||
|
|
b741d7d0b5
|
feat(rules): add Jsonnet review rules (#470) (#962)
Route `.jsonnet` and `.libsonnet` to a new rule doc. `.libsonnet` is a naming convention for importable libraries, not a separate language, so both share one doc (as .hs/.lhs and .nim/.nims/.nimble already do). The vendor exclude is extension-scoped rather than a bare `**/vendor/**`: IsExcludedPath applies every pattern to every path with no language dispatch, so an unscoped directory pattern would also drop vendored Go and PHP sources, whose extensions are allowlisted. No test-file pattern is added — real Jsonnet projects split between `test_*.libsonnet`, `tests/*.jsonnet` and `*_test.jsonnet`, and an over-broad glob silently drops handwritten files. Verified: go test ./... and gofmt -l internal/config clean. |
||
|
|
1ae808e100
|
fix(scripts): stop license checks failing on valid headers (#971)
`echo "$header" | grep -q ...` races. grep -q exits on the first match, so echo can die of SIGPIPE (141); `set -o pipefail` makes that the pipeline's status, and verify-license.sh reports a header that is present as missing. Measured on a 410-byte header under CPU load: 4 spurious failures in 3000 iterations, naming a different file each time. has_header() in add-license.sh has the same race, and there a false negative makes add_header() prepend a second copyright block to a file that already has one. Feed the header through a here-string instead, and read the year with bash's regex match rather than a grep | grep | head chain that can take SIGPIPE the same way. |
||
|
|
e288e1a33f
|
fix(pages): serve 404 pages on non-existent GET requests but render no React Route (#955)
* core: NotFoundPage Page for 404 * chore: write tests(AI) * route 404 request to ./pages/NotFoundPage * chore: write tests (AI) * chore: translations sync * fixup: updated webpack cfg so unknown HTML paths are also rewritten to the app shell * refactor: enhance NotFoundPage tests with dynamic translation handling * docs: Apply suggestion from @lizhengfeng101 --------- Co-authored-by: Kite <254839944+lizhengfeng101@users.noreply.github.com> |
||
|
|
e51d65706f
|
fix(allowlist): allow .properties, .po and .pot so their rules can run (#958)
system_rules.json maps **/*.properties, **/*.po and **/*.pot to
properties.md, po.md and pot.md, but none of the three extensions were in
supported_file_types.json. Both filter paths (internal/scan/agent.go:483
and internal/agent/preview.go:51) reject a file on its extension before any
rule is resolved, so the three docs were unreachable by default while
pages/src/content/docs/en/review-rules.md advertised them.
Adds the extensions, plus a TestSystemRulesIntegrity subtest that fails when
any extension glob in path_rule_map names an extension IsAllowedExt rejects.
Filename globs (**/pom.xml) and infix globs (**/*{mapper,dao}*.xml) make no
extension claim and are skipped.
|
||
|
|
f75c43af45
|
feat(config): resolve api_key/auth_token from a command (#236) (#605)
* feat(config): resolve api_key/auth_token from a command (#236) Add `api_key_cmd` (provider entries) and `auth_token_cmd` (legacy llm block) so the LLM credential can be fetched from a secret manager at review time instead of stored plaintext in config.json — same pattern as git credential.helper / AWS credential_process. Resolution precedence (single site, presets and custom providers alike): static api_key always wins (stderr warning if a command is also set) → api_key_cmd → preset env var → error. The legacy llm block gets a mirrored auth_token_cmd; an incomplete legacy block never executes the command, and a set-but-failing command on a complete block is a hard error (never a silent fallback). Command execution is a build-tag split (sh -c / cmd /C) with a 60s timeout; the child's stderr passes through so pinentry/1Password/op prompts stay visible. Stdout is trimmed and used in memory only — never written to config or logged. Empty, whitespace-only, multi-line, and timed-out output are all hard errors. No caching (resolution runs once per process). - config set: api_key_cmd/auth_token_cmd are settable and round-trip; not masked (they are command lines, not secrets). - TUI cloneProviderEntry preserves api_key_cmd. - docs: 'API key from a command' section in configuration.md (en/zh/ja). Tests: table-driven runner matrix (success/trim/non-zero/empty/ whitespace/multi-line/not-found/timeout) + resolver precedence and legacy-fallthrough rows. Coverage 81.3%; Windows arm compile-checked (CI is Linux-only). * fix(llm): harden the credential command and cover it on Windows Follow-up hardening on the api_key_cmd/auth_token_cmd path, plus the CI job that actually exercises its Windows arm. The 60s timeout was not a real bound. It killed the shell, but a helper that leaves a background process holding the inherited stdout pipe (gpg-agent, pinentry, a first-use `op` daemon) kept Cmd.Wait blocked on the read long after the context died — `api_key_cmd = "sleep 200 & printf tok"` hung for over 90s. Buffer stdout through a writer os/exec copies in its own goroutine and set WaitDelay, which is what lets Wait force the pipe closed; ErrWaitDelay on its own is not a failure, since the command exited and its output is already buffered. Three more ways a resolved value could not be used: - Stdin was /dev/null, so a helper needing a passphrase saw EOF or refused to prompt for lack of a tty. Wired to os.Stdin, which is safe because no path resolves an endpoint while the bubbletea TUI is reading stdin. - Output was unbounded; `cat /dev/urandom` grew the heap without limit. Capped at 64KiB, refusing the write so the child dies of SIGPIPE. - Control bytes reached the Authorization header, where net/http rejects them as an opaque `invalid header field value`. Rejected up front with the offending byte and offset, matching httpguts.ValidHeaderFieldValue. A lone interior CR survived both TrimRight and TrimSpace, so it is now caught as multi-line output. Ordering: the command ran before the rest of the config was known to be usable, so `ocr review --model nonexistent` fired a biometric prompt and only then failed on the model name. Execution is deferred past validation at both sites — the source selection in tryProviderConfig, and ResolveEndpointWithModelOverride, which parsed OCR_LLM_TIMEOUT and OCR_LLM_EXTRA_HEADERS after resolving the credential. A whitespace-only static api_key also used to win precedence over a working api_key_cmd and send `Authorization: Bearer `; it now normalizes to unset, and the Manual TUI tab trims its token like the other two tabs. `ocr config provider` rejected api_key_cmd-only providers in both directions: non-interactively applyOfficialProviderConfig demanded a static key or an env var, and interactively the API-key step could not be confirmed because the field renders blank for such a provider. Both now treat a configured command as satisfying the requirement, and the error messages name the option that would fix it. Windows: the command line goes to cmd.exe through SysProcAttr.CmdLine with /S rather than through Args, because os/exec quotes Args with syscall.EscapeArg, which targets CommandLineToArgvW; cmd.exe is a documented exception whose escaping mangles any command containing a double quote, so `op read "op://Private/My Vault/api-key"` arrived as a single literal filename. Args stays at its one-element default rather than nil (syscall.StartProcess ignores argv when CmdLine is set) so Cmd.String() cannot panic on Args[1:]. CI ran only self-hosted Linux, and the cross-compile job proves the windows arms compile but never runs them, so keycmd_windows.go had zero coverage on any platform. Adds a windows-latest job that vets, tests, builds and smoke-tests natively. It installs Go with setup-go instead of the shared golang:1.26.5 image because GitHub does not support `container:` on Windows runners (actions/runner#904); no -race, since the detector needs a C toolchain there and races are OS-independent; no coverage gate, since the //go:build !windows files legitimately put the total under the Linux job's 80%. Six existing tests needed a guard for that job, none a behavior change: three assert an unreadable path is skipped, but Chmod(0000) on Windows only sets the read-only bit (and their os.Getuid() == 0 guard cannot cover it, since Getuid returns -1 there); TestSaveConfig asserts the 0600 the config is written with, which Windows reports as 0666; the symlink-safety test needs a privilege an unelevated CI account lacks; and the "absolute unchanged" background-path case was passing a rooted but non-absolute path, so it had been exercising the relative branch. Running that job turned up more of the same, all of it in tests and none of it needing a production change. os.UserHomeDir reads USERPROFILE on Windows and never falls back to HOME, so every test that redirects a home dir was quietly reading the real profile: TestLoadGlobalRule, TestShellRCFiles, TestTryShellRC and the session writer-creation test now set both. So do the retry e2e helper and TestLoadLLMRuntime_BadAppConfig, where it had gone past reading the wrong profile to failing outright. The e2e test blocks session persistence by occupying $HOME/.opencodereview/ sessions with a regular file, and on Windows found the runner's real directory already sitting there, so the setup write died with "is a directory"; the config test wrote its invalid config.json into a temp home nothing read, so resolution reported a missing endpoint instead of the parse failure the test is named for. unwritableConfigPath put the config below a regular-file parent, which Windows reports as ERROR_PATH_NOT_FOUND; os.IsNotExist accepts that, so loadOrCreateConfig read it as "no config yet" and the six save-failure tests never reached the rollback they are named for. It now points at a directory, which fails both the write and the reload on every platform, so those six keep their coverage rather than taking a skip. Two do get one, the mechanism being absent rather than different: the chmod(0000) sniff error in internal/scan, and ReadDir on a regular file, which comes back as an empty listing on Windows instead of ENOTDIR. captureStdout and captureStderr -- and the two helpers shaped like them in the delegate and config tests -- drained their pipe only after the captured function returned, so that function could write one pipe buffer and then blocked forever. That is what hung TestReviewE2E_RecoveredAndFailedReachesJSONExit for the package's entire 10m budget. Linux only hid it: 1MiB through the old helper deadlocks there too. They now drain concurrently, which fixes the bug instead of skipping the test. Docs (en/zh/ja) spell out the failure modes, the 60s budget including the time spent answering a prompt, the inherited stdin/stderr, the extra 5s a daemon holding the pipe costs, and that config.json is trusted input because the value is executed as a shell command. Review follow-ups in the same pass. A whitespace-only api_key_cmd was the one credential field this path had not normalized: it is empty to `sh` but non-empty to Go, so it suppressed the env-var fallback and then failed with "produced empty output". It now reads as unset, the same as the equivalent typo in api_key. Same for auth_token_cmd on the legacy block. The wizard checked those same fields for emptiness without the trim, so `ocr config provider` would accept a command of " ", save a config with no static key, and leave the resolver to refuse it with "no api_key or api_key_cmd configured". Both gates read through apiKeyCmdForStep and manualAuthTokenCmd, so the trim goes in those two accessors and covers the render sites with them; applyOfficialProviderConfig reads the entry directly and gets its own. The TUI never showed that a command already satisfies the credential step, so the API-key field looked unconfigured on a provider that resolves fine; it now says so on both the provider tabs and the Manual tab. The hint names the config key rather than echoing the command. Usually the command is a bare reference to a secret manager, but nothing stops a user inlining a credential into it (`VAULT_TOKEN=hvs.xxx vault kv get ...`), and this wizard masks every other secret it puts on screen -- one user-authored string printed verbatim into screenshots and terminal recordings was the hole in that. There is exactly one command per provider, so the key name is enough to identify which one is configured. Left as it is, deliberately: SysProcAttr.Setpgid would let us SIGKILL the whole process group and so reap a grandchild the command backgrounded, which `sleep 200 & printf tok` does leak today. It would also put the child outside the terminal's foreground process group, where it takes SIGTTIN the moment it reads the tty -- measured, a child running `read -r x </dev/tty` answers in 7ms as written and returns nothing at all under Setpgid. That read is what pinentry and `op`'s fallback prompt do, which is the case c.Stdin = os.Stdin exists to support and the docs promise. The group has to be chosen at Start, so this cannot be narrowed to the timeout path, and reaping the grandchild properly needs tcsetpgrp-style job control. A process the user's own command asked to background, outliving a CLI that exits seconds later exactly as it would from their shell, is not worth a broken credential prompt. keycmd_unix.go records the measurement so the trade is not re-litigated. The static-key-wins tests asserted only on the resolved token, which would have held just as well if the command ran and its output were discarded — i.e. a spurious biometric prompt on every review of a config that keeps a command as a fallback. They now use a filesystem witness to assert non-execution. The docs note that a command written for `sh` is generally not portable to `cmd.exe`, since the Windows arm is where that bites. * fix(config): drop duplicated license header in testconnection The SPDX and copyright block was emitted twice at the top of internal/config/testconnection/testconnection.go, a rebase artifact from the first commit on this branch rather than an intentional change. The file is now byte-identical to main. make license-check passed throughout: it verifies a valid header is present, not that there is only one. * docs(i18n): sync api_key_cmd configuration docs to ru The en, ja and zh pages gained the "API key from a command" section; ru was left behind. Adds the same section, in the same position, with the config keys and shell snippets untranslated as the rest of the file does. |
||
|
|
7ef8e50bd2
|
feat(allowlist): add Elm language support (#940) (#953) | ||
|
|
5cbc8a1cd0
|
docs: fix code of conduct reporting links (#968)
Co-authored-by: Bo Zhang <187063395+Tethys0@users.noreply.github.com> |
||
|
|
ea1de41a4f
|
fix(plugin): separate client marketplace registrations (#908)
Some checks are pending
CI / test (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Register the Claude Code and Codex integrations in their respective native marketplace manifests so each client only exposes its compatible plugin. Co-authored-by: Xwell <180168103+Xvvln@users.noreply.github.com> |
||
|
|
75cb3d0c45
|
feat(scan): report token budget stop in JSON summary.budget_exceeded (#791)
scan already detects the aggregate token-budget stop (it prints the
"[ocr] token budget reached" line and records a token_budget_reached
warning) but BudgetExceeded() was hard-coded false, so
summary.budget_exceeded never appeared in `ocr scan --format json`.
The write goes next to `budgetHit = true` in dispatchBatch's per-file
gate. That is the only site that sets budgetHit, and it covers all three
exits that carry the stop out of dispatchBatch: normal return, ctx-cancel
return, and the caller's `if budgetHit { break }`. Setting it at the
dispatchSubtasks break instead would lose it on the ctx-cancel path.
Plain bool, no mutex: dispatchBatch's loop is the only writer, it runs on
the caller's goroutine, and the value is read by emitRunResult after Run
returns. The spawned subtask goroutines never touch it. Matches the
existing internal/agent.Agent.budgetExceeded field.
Status and exit code are untouched — reaching the budget is a controlled
truncation, so out.Status stays the warning-derived value.
|
||
|
|
b8bee97184
|
feat(providers): add kimi-global (Moonshot international API) to built-in providers (#914)
Some checks failed
CI / test (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Has been cancelled
Deploy Pages / deploy (push) Has been cancelled
Moonshot operates two first-party endpoints: api.moonshot.cn (mainland China, already registered as `kimi`) and api.moonshot.ai (international). Only the former is currently available, so users outside mainland China cannot select a Kimi model without hand-configuring a custom base URL. Registers `kimi-global` pointing at https://api.moonshot.ai/v1. The endpoint is OpenAI-compatible, so it uses the existing openai-chat-completions protocol with no new client code — the same shape as the existing global/CN provider pairs (siliconflow / siliconflow-cn, minimax / minimax-cn). - Base URL: https://api.moonshot.ai/v1 - Auth: MOONSHOT_GLOBAL_API_KEY (mirrors SILICONFLOW_GLOBAL_API_KEY naming) - Models: mirrors the existing `kimi` list; kimi-k3 is served on the international platform (kimi-k3 API live since 2026-07-16) The existing `kimi` provider is left untouched, so this is non-breaking for current users. |
||
|
|
9a371c9b36
|
fix(diff): re-file comments whose code lives in another file (#921)
Some checks are pending
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / test (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
|
||
|
|
44a946a68d
|
feat(rules): add Swift review rules (#918) | ||
|
|
1abfb70fcb
|
docs(cli-reference): add missing ocr review flags examples (#920)
* document flags * translations sync fixup fixup * remove conflicting `--exclude` in docs |
||
|
|
c8b6a390b8
|
fix(review-filter): add submit_filter_result func for review filter stage (#295)
* fix(review-filter): add `submit_filter_result` func for review filter stage At review filter stage, LLM(test GLM5.2) may return natural language content such as: """ Looking at each comment... - commit 1: ... - commit 2: ... Summary: ```json [...]``` """ add function calling for LLM will get more stable result for some model of providers. and this tool only appears at review filter stage, so it does no harm for review quality. * fix(filter): log tool call argument parse failures for observability * refactor(filter): two-tool design with required choice for review filter - Replace single submit_filter_result tool with two mutually exclusive tools: report_incorrect_comments and approve_all_comments - Add ToolChoice field to ChatRequest, wired through OpenAI Chat, OpenAI Responses, and Anthropic client paths - Set ToolChoice to 'required' so the model must always make an explicit decision (no silent text-only fallback) - Aggregate results across multiple tool calls for robustness - Update prompt to instruct exactly-one-tool usage - Preserve text-based fallback for providers without tool support * fix(filter): stop the review filter from deleting real findings An A/B benchmark over 194 identical commit ranges (50 OSS repos, claude-opus-4-6) showed the filter removing 22 comments at 36% precision: 8 of them reported real defects — a heap overflow, an ignored LOCKMODE parameter, a static/non-static linkage conflict, a dropped success status, double URL encoding, an always-true condition. Two causes, one of them structural. Field order in report_incorrect_comments. Go serializes the parameter map alphabetically, so comment_ids was emitted before any reasoning field and the model had to commit before it had finished thinking. Replaying recorded sessions with a diagnostic field made this visible: it wrote "this is a protected subject, I should not remove it" while the id stayed in the list it had already produced. Adding an "analysis" array — alphabetically first, required — lets it reason before concluding. parseFilterToolCalls is unchanged; it reads comment_ids and ignores the rest. Prompt scope. Step 2 "Issue Classification" asked whether the comment "misidentifies clearly normal code as a defect", which invited a value judgement and was the entry point for most wrong removals. It is gone. Removal now needs one of two grounds: the code the comment targets is absent from the diff, or a single diff line literally contradicts its central claim. Protected subjects (memory safety, concurrency, linkage, behavioral change, unused parameters) and style-only comments that state something true are vetoed as the first two steps of the method, not as prose the model reads and then skips. Replaying all 455 recorded filter calls with the same inputs: precision 36% -> 88%, real findings deleted 8 -> 0, at +37% filter tokens and +7% mean latency. Caveat: the grounds were derived from this same dataset, so the figure is a training-set result and wants a hold-out range set before it is trusted. --------- Co-authored-by: kite <lizhengfeng.lzf@alibaba-inc.com> |
||
|
|
96b2728ec2
|
docs(cli-reference): document missing review flags (#900) | ||
|
|
f7344e798a
|
feat(providers): add xAI (Grok) to built-in providers (#899)
* feat(llm): add xAI Grok provider preset * Update internal/llm/providers.go Co-authored-by: Tao Xin <wu2196674@icloud.com> * Update internal/llm/providers.go Co-authored-by: Tao Xin <wu2196674@icloud.com> * apply ccec85 for test * Update internal/llm/providers.go Co-authored-by: Tao Xin <wu2196674@icloud.com> --------- Co-authored-by: Tao Xin <wu2196674@icloud.com> |
||
|
|
d8b222a180
|
refactor(telemetry): replace PrintTraceSummary positional params with TraceSummary struct (#909)
* refactor(telemetry): replace PrintTraceSummary positional params with TraceSummary struct PrintTraceSummary had grown to nine positional parameters after the session ID landed in #870, making call sites hard to read and easy to get wrong. Introduce a TraceSummary struct and pass it as a single argument (Option A in the issue); printed output is unchanged. Also add stdout.Swap, which swaps the package writer under the existing mutex and returns a restore function, so tests can capture and assert output written through stdout.Writer(). The PrintTraceSummary tests now assert the exact summary, cache-token, and session lines instead of only verifying the call does not panic. Closes #906 * docs(stdout): clarify Swap concurrency doc comment The mutex in Swap and its restore closure already guarantees memory safety under concurrent access; the remaining hazard is semantic — concurrent swaps produce non-deterministic restore ordering. Rephrase the comment to state that distinction, as suggested in PR review. |
||
|
|
7ce7cf78a2
|
feat(providers): add glm-5.3 to the Z.AI Coding Plan provider (#915)
Some checks are pending
CI / cross-compile (arm64, windows) (push) Waiting to run
CI / test (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
|
||
|
|
0c8c0670f2
|
docs(cli): document review no-filter option (#871)
Some checks are pending
CI / test (push) Waiting to run
CI / cross-compile (amd64, darwin) (push) Waiting to run
CI / cross-compile (amd64, windows) (push) Waiting to run
CI / cross-compile (arm64, darwin) (push) Waiting to run
CI / cross-compile (arm64, linux) (push) Waiting to run
CI / cross-compile (arm64, windows) (push) Waiting to run
CodeQL Advanced / Analyze (go) (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Pages / build (push) Waiting to run
Deploy Pages / deploy (push) Blocked by required conditions
|
||
|
|
31db10fa63
|
fix(resume): preserve checkpoints after Ctrl-C (#902)
* fix(resume): preserve checkpoints after Ctrl-C * fix(resume): tighten cancellation dispatch |