pierre-review 0.1.34 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,7 @@ import { hasUserAnthropicKey, setUserAnthropicKey, } from '../../review/local-se
7
7
  import { buildAnchorIndex, buildReview, fallbackAnchor, fetchCurrentHeadSha, fetchPrDiff, findingCommentBody, prLevelFindingBody, stripNoiseFromDiff, submitGithubComment, submitGithubIssueComment, submitGithubReview, } from '../../review/post-review.js';
8
8
  import { isNoiseFile } from '../../review/prompt.js';
9
9
  import { accountIdOf } from '../plugins/auth.js';
10
- const MODELS = ['claude-opus-4-8', 'claude-sonnet-4-6'];
10
+ const MODELS = ['claude-opus-4-8', 'claude-sonnet-4-6', 'claude-haiku-4-5'];
11
11
  const VERDICTS = ['COMMENT', 'REQUEST_CHANGES', 'APPROVE'];
12
12
  const REVIEW_MODES = ['auto', 'diff_only', 'worktree'];
13
13
  const idParam = {
package/dist/config.js CHANGED
@@ -29,6 +29,17 @@ function floatFromEnv(key, fallback) {
29
29
  const n = Number.parseFloat(raw);
30
30
  return Number.isFinite(n) ? n : fallback;
31
31
  }
32
+ // The Claude Agent SDK `effort` levels (guides thinking depth + overall token
33
+ // spend). Lower effort → fewer/cheaper thinking tokens + terser output. NOTE:
34
+ // `effort` is rejected by Haiku 4.5 — only models that accept it get it (see
35
+ // review/agent.ts EFFORT_CAPABLE_MODELS).
36
+ const REVIEW_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max'];
37
+ function effortFromEnv(key, fallback) {
38
+ const raw = process.env[key];
39
+ return REVIEW_EFFORTS.includes(raw ?? '')
40
+ ? raw
41
+ : fallback;
42
+ }
32
43
  // ---- Deployment mode (the master switch) ----
33
44
  // `local` (default): SQLite via better-sqlite3, `gh auth token` auth, one
34
45
  // implicit account, no landing page — the unchanged zero-config experience.
@@ -122,10 +133,41 @@ export const config = {
122
133
  // Per-run caps (cost/disk/time runaway guards). The diff is inlined in full, so
123
134
  // reviews need far fewer turns than the old default; 30 is still generous.
124
135
  reviewMaxTurns: intFromEnv('REVIEW_MAX_TURNS', 30),
125
- reviewBudgetUsd: floatFromEnv('REVIEW_BUDGET_USD', 1.0),
136
+ // Hard USD ceiling per run. When the SDK trips this it returns an
137
+ // `error_max_budget_usd` result BEFORE the agent calls submit_review — so a run
138
+ // that hits the cap is recorded FAILED and still bills (you pay for no review).
139
+ // The cap must therefore sit ABOVE the cost of a normal completed review, not at
140
+ // it; `reviewEffort` below is the real cost lever (a large diff at default-high
141
+ // effort is what blew the old $1 cap). Lower REVIEW_BUDGET_USD only if you'd
142
+ // rather a borderline review fail than complete.
143
+ reviewBudgetUsd: floatFromEnv('REVIEW_BUDGET_USD', 1.5),
126
144
  // Turn cap for a diff-only run. These are TOOL-LESS (only submit_review), so they
127
145
  // should finish in ~2 turns; a tight cap is a cheap runaway guard.
128
146
  reviewDiffOnlyMaxTurns: intFromEnv('REVIEW_DIFF_ONLY_MAX_TURNS', 6),
147
+ // Haiku reaches a conclusion in MORE steps than Sonnet/Opus (smaller model, more
148
+ // tool round-trips), so it routinely tripped the turn cap mid-review and failed.
149
+ // Give it proportionally more turns in both modes. Its low per-token price means
150
+ // the extra turns are cheap, and maxBudgetUsd is still the real spend guard.
151
+ reviewHaikuTurnMultiplier: floatFromEnv('REVIEW_HAIKU_TURN_MULTIPLIER', 2),
152
+ // ---- Diff-size cap ----
153
+ // A very large inlined diff is the dominant cost on a big PR (it's the cached
154
+ // prefix re-read every turn). The diff shown IN THE PROMPT is truncated at a
155
+ // whole-file boundary to this many characters; routing + line anchoring still use
156
+ // the FULL diff, and the changed-file LIST stays complete (so a worktree run can
157
+ // Read the omitted files). ON by default — it proved its worth on a large PR that
158
+ // failed without it. ~60k chars ≈ ~15k tokens, so only outlier PRs are truncated
159
+ // and a normal review is unaffected; each run records diffCapped + the full diff
160
+ // size, so you can still A/B by setting REVIEW_DIFF_CAP_ENABLED=false for a
161
+ // baseline run and comparing the recorded cost.
162
+ reviewDiffCapEnabled: process.env.REVIEW_DIFF_CAP_ENABLED !== 'false',
163
+ reviewDiffCapChars: intFromEnv('REVIEW_DIFF_CAP_CHARS', 60000),
164
+ // Agent `effort` per mode — the dominant cost knob (unset ⇒ the SDK default
165
+ // `high`, which over-thinks bounded reviews). A diff-only run just hunts bugs in a
166
+ // small inlined diff, so `low` is plenty; a worktree run reasons across files, so
167
+ // `medium` keeps that while trimming the over-exploration that ran up the bill.
168
+ // Applied only to effort-capable models (Sonnet/Opus); Haiku ignores it.
169
+ reviewEffort: effortFromEnv('REVIEW_EFFORT', 'medium'),
170
+ reviewDiffOnlyEffort: effortFromEnv('REVIEW_DIFF_ONLY_EFFORT', 'low'),
129
171
  // At most one review per PR; this caps concurrent reviews across all PRs. Default
130
172
  // 4 so the user can bulk-review (extras queue, see review-manager). Raising this
131
173
  // also DISABLES the pasted-key override (which mutates process.env and is only
@@ -0,0 +1,11 @@
1
+ -- Claude Review cost telemetry (additive). Records the cache-token split (a
2
+ -- multi-turn run's input is mostly cache reads — the dominant cost the plain
3
+ -- input_tokens column hid) plus the full noise-stripped diff size and whether the
4
+ -- feature-flagged diff-size cap truncated the prompt (so capped vs uncapped runs can
5
+ -- be cost-compared). All nullable; existing rows stay NULL. SQLite-only: Claude
6
+ -- Review is force-disabled in cloud, so the Postgres claude_reviews table is never
7
+ -- populated (its baseline is regenerated separately via db:generate:pg).
8
+ ALTER TABLE `claude_reviews` ADD `cache_read_tokens` integer;--> statement-breakpoint
9
+ ALTER TABLE `claude_reviews` ADD `cache_creation_tokens` integer;--> statement-breakpoint
10
+ ALTER TABLE `claude_reviews` ADD `diff_bytes` integer;--> statement-breakpoint
11
+ ALTER TABLE `claude_reviews` ADD `diff_capped` integer;
@@ -141,6 +141,13 @@
141
141
  "when": 1780800000010,
142
142
  "tag": "0019_finding_file_in_diff",
143
143
  "breakpoints": true
144
+ },
145
+ {
146
+ "idx": 20,
147
+ "version": "6",
148
+ "when": 1780800000011,
149
+ "tag": "0020_claude_review_cost_telemetry",
150
+ "breakpoints": true
144
151
  }
145
152
  ]
146
153
  }
@@ -0,0 +1,4 @@
1
+ ALTER TABLE "claude_reviews" ADD COLUMN "cache_read_tokens" integer;--> statement-breakpoint
2
+ ALTER TABLE "claude_reviews" ADD COLUMN "cache_creation_tokens" integer;--> statement-breakpoint
3
+ ALTER TABLE "claude_reviews" ADD COLUMN "diff_bytes" integer;--> statement-breakpoint
4
+ ALTER TABLE "claude_reviews" ADD COLUMN "diff_capped" boolean;