@zephyrdeng/pi-review 0.14.0 → 0.15.0

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.
@@ -0,0 +1,150 @@
1
+ /**
2
+ * /rv-config: show the effective pi-review configuration — the persistent
3
+ * config file (~/.pi/pi-review/config.json), per-process env overrides, and
4
+ * the resolved paths the CLI will use. Read-only, plain text (no markdown),
5
+ * locale-aware like the other /rv* commands.
6
+ */
7
+
8
+ import {
9
+ configFilePath,
10
+ loadReviewConfigFile,
11
+ parseReviewConfig,
12
+ resolveChildExtensions,
13
+ resolveConfig,
14
+ } from "@zephyrdeng/pi-review";
15
+ import type { PiReviewConfig } from "@zephyrdeng/pi-review";
16
+ import type { RvLocale } from "./rv-locale.js";
17
+
18
+ export interface RvConfigViewInput {
19
+ locale: RvLocale;
20
+ env?: NodeJS.ProcessEnv;
21
+ /** Override the config file path (tests). */
22
+ configPath?: string;
23
+ /** Override config file content (tests); null means the file is missing. */
24
+ readConfig?: (file: string) => string | null;
25
+ /** Override the resolved environment keys (tests). */
26
+ resolved?: ReturnType<typeof resolveConfig>;
27
+ }
28
+
29
+ type Strings = {
30
+ header: string;
31
+ childExtensions: string;
32
+ configFileLabel: string;
33
+ configFileMissing: string;
34
+ envSection: string;
35
+ sourceDefault: string;
36
+ sourceConfig: string;
37
+ sourceEnv: string;
38
+ warnFile: (reason: string) => string;
39
+ piBin: string;
40
+ reviewHome: string;
41
+ presetsFile: string;
42
+ panelPresetsFile: string;
43
+ systemPromptFile: string;
44
+ sessionsRoot: string;
45
+ };
46
+
47
+ const STRINGS: Record<RvLocale, Strings> = {
48
+ en: {
49
+ header: "Pi Review config",
50
+ childExtensions:
51
+ "Load host Pi extensions in review children so providers registered only by extensions (e.g. px:anthropic, zenmux) are usable; false keeps children isolated with --no-extensions (issue #8). Override one run: PI_REVIEW_CHILD_EXTENSIONS=1 or =0.",
52
+ configFileLabel: "config file",
53
+ configFileMissing: "(missing — using defaults)",
54
+ envSection: "Resolved environment",
55
+ sourceDefault: "default",
56
+ sourceConfig: "config file",
57
+ sourceEnv: "env override",
58
+ warnFile: (reason) => `config warning: ${reason} — using defaults for that key`,
59
+ piBin: "Pi executable used to spawn review children.",
60
+ reviewHome: "Directory holding the default presets and system prompt.",
61
+ presetsFile: "Review mode presets (code / plan / challenge).",
62
+ panelPresetsFile: "Named panel presets (e.g. code-experts).",
63
+ systemPromptFile: "Extra system prompt appended to every review child.",
64
+ sessionsRoot: "Persisted --keep-session review sessions.",
65
+ },
66
+ zh: {
67
+ header: "Pi Review 配置",
68
+ childExtensions:
69
+ "是否让评审子进程加载宿主 Pi 扩展,以使用仅由扩展注册的 provider(如 px:anthropic、zenmux);false 表示隔离运行(--no-extensions,issue #8)。单次覆盖:PI_REVIEW_CHILD_EXTENSIONS=1 或 =0。",
70
+ configFileLabel: "配置文件",
71
+ configFileMissing: "(不存在——使用默认值)",
72
+ envSection: "生效环境",
73
+ sourceDefault: "默认",
74
+ sourceConfig: "配置文件",
75
+ sourceEnv: "env 覆盖",
76
+ warnFile: (reason) => `配置警告:${reason}——该键按未设置处理`,
77
+ piBin: "用于启动评审子进程的 Pi 可执行文件。",
78
+ reviewHome: "存放默认 presets 与系统提示词的目录。",
79
+ presetsFile: "评审模式预设(code / plan / challenge)。",
80
+ panelPresetsFile: "命名评审面板预设(如 code-experts)。",
81
+ systemPromptFile: "附加到每个评审子进程的系统提示词。",
82
+ sessionsRoot: "持久化 --keep-session 评审会话的目录。",
83
+ },
84
+ };
85
+
86
+ function warnNotes(s: Strings, warnings: string[]): string[] {
87
+ return warnings.map((w) => s.warnFile(w));
88
+ }
89
+
90
+ /**
91
+ * Build the /rv-config display lines. Pure apart from reading the config file
92
+ * (inject readConfig for tests; null means the file is missing).
93
+ *
94
+ * The config is advisory and lenient: nothing here can fail the CLI, so the
95
+ * view and the CLI always agree — warnings are displayed, values fall back.
96
+ */
97
+ export function buildRvConfigLines(input: RvConfigViewInput): string[] {
98
+ const s = STRINGS[input.locale];
99
+ const env = input.env ?? process.env;
100
+ const file = input.configPath ?? configFilePath(env);
101
+
102
+ let cfg: PiReviewConfig = {};
103
+ const configNotes: string[] = [];
104
+ if (input.readConfig) {
105
+ let text: string | null;
106
+ try {
107
+ text = input.readConfig(file);
108
+ } catch (error) {
109
+ configNotes.push(s.warnFile(String((error as Error).message)));
110
+ text = null;
111
+ }
112
+ if (text !== null) {
113
+ const load = parseReviewConfig(text);
114
+ cfg = load.config;
115
+ configNotes.push(...warnNotes(s, load.warnings));
116
+ } else if (configNotes.length === 0) {
117
+ configNotes.push(s.configFileMissing);
118
+ }
119
+ } else {
120
+ const load = loadReviewConfigFile(file);
121
+ cfg = load.config;
122
+ configNotes.push(...warnNotes(s, load.warnings));
123
+ }
124
+
125
+ const decision = resolveChildExtensions(env, cfg);
126
+ const sourceLabel =
127
+ decision.source === "env" ? s.sourceEnv : decision.source === "config" ? s.sourceConfig : s.sourceDefault;
128
+
129
+ const resolved = input.resolved ?? resolveConfig();
130
+ const line = (key: string, value: string, description: string): string => {
131
+ const head = `${key}: ${value}`;
132
+ return [head, ` ${description}`].join("\n");
133
+ };
134
+
135
+ const lines: string[] = [];
136
+ lines.push(s.header);
137
+ lines.push(`childExtensions: ${decision.enabled} (${sourceLabel})`);
138
+ lines.push(` ${s.childExtensions}`);
139
+ lines.push(`${s.configFileLabel}: ${file}`);
140
+ for (const note of configNotes) lines.push(` ${note}`);
141
+ lines.push("");
142
+ lines.push(s.envSection);
143
+ lines.push(line("piBin", resolved.piBin, s.piBin));
144
+ lines.push(line("reviewHome", resolved.reviewHome, s.reviewHome));
145
+ lines.push(line("presetsFile", resolved.presetsFile, s.presetsFile));
146
+ lines.push(line("panelPresetsFile", resolved.panelPresetsFile, s.panelPresetsFile));
147
+ lines.push(line("systemPromptFile", resolved.systemPromptFile, s.systemPromptFile));
148
+ lines.push(line("sessionsRoot", resolved.sessionsRoot, s.sessionsRoot));
149
+ return lines;
150
+ }
@@ -532,7 +532,7 @@ function piHostRules(strategy: RvStrategy): string {
532
532
  return [
533
533
  "Follow the pi-review skill.",
534
534
  "Host: Pi interactive session (/rv*).",
535
- "Slash commands select strategy only: /rv = panel review, /rv-loop = loop closeout, /rv-models = model catalog.",
535
+ "Slash commands select strategy only: /rv = panel review, /rv-loop = loop closeout, /rv-models = model catalog, /rv-config = effective configuration.",
536
536
  "Everything after the command is a natural-language review request. Path mentions like @src are fine as text.",
537
537
  "Do not expand directory targets into multi-file lists. Strategy matching beyond the slash command (mode defaults, model choice, panel preset, path-vs-file handling) lives in the pi-review skill and CLI.",
538
538
  strategy === "panel"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zephyrdeng/pi-review",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Isolated AI-powered code and plan reviews from the command line",
5
5
  "type": "module",
6
6
  "author": "ZephyrDeng <zephyrTang@aliyun.com>",
@@ -0,0 +1,28 @@
1
+ {
2
+ "providers": {
3
+ "orcarouter": {
4
+ "baseUrl": "https://api.orcarouter.ai/v1",
5
+ "api": "openai-completions",
6
+ "apiKey": "ORCA_KEY",
7
+ "signupUrl": "https://www.orcarouter.ai/ref/ref_07ca74b3e41670e5ff36",
8
+ "models": [
9
+ {
10
+ "id": "orcarouter/auto",
11
+ "name": "OrcaRouter Auto",
12
+ "reasoning": false,
13
+ "input": ["text"],
14
+ "contextWindow": 200000,
15
+ "maxTokens": 8192
16
+ },
17
+ {
18
+ "id": "anthropic/claude-sonnet-4.6",
19
+ "name": "Claude Sonnet 4.6",
20
+ "reasoning": true,
21
+ "input": ["text"],
22
+ "contextWindow": 200000,
23
+ "maxTokens": 8192
24
+ }
25
+ ]
26
+ }
27
+ }
28
+ }
@@ -21,6 +21,17 @@ If `pi-review` is not on PATH but this skill came from the Pi package, use the p
21
21
  node ../../bin/pi-review.js --help
22
22
  ```
23
23
 
24
+ ## Registered providers (explicit opt-in)
25
+
26
+ Review children stay isolated (`--no-extensions`) unless the persistent review config enables host extensions. Enable them only when the review needs an extension-registered provider (e.g. `px:anthropic`, `zenmux`) — and only with explicit user acceptance:
27
+
28
+ ```json
29
+ // ~/.pi/pi-review/config.json
30
+ { "childExtensions": true }
31
+ ```
32
+
33
+ Before writing, tell the user the config is machine-level: every later pi-review on this machine (including bare CLI) inherits it. Write it only on acceptance; when editing an existing file, keep every unknown key and never overwrite a value the user set (invalid JSON — stop, do not overwrite). Verify on Pi with `/rv-config`, elsewhere with `cat ~/.pi/pi-review/config.json`. Isolate one run with `PI_REVIEW_CHILD_EXTENSIONS=0` (env overrides config). If a child exits with stale extension ctx after dispose/reload (issue #8), retry that one run with `PI_REVIEW_CHILD_EXTENSIONS=0`.
34
+
24
35
  ## Default workflow by host
25
36
 
26
37
  | Host | How to run `pi-review` |
@@ -51,6 +62,7 @@ Slash commands select **strategy only**. Everything after the command is a **nat
51
62
  | `/rv <natural-language target>` | Panel review via native **Pi Review Panel** (`pi_review` API tool); preset `code-experts` unless `--reviewers`/`--panel` say otherwise |
52
63
  | `/rv-loop <natural-language target>` | Loop closeout via shell `pi-review loop`; host fix point `--max-rounds 1` by default |
53
64
  | `/rv-models` | Model catalog only |
65
+ | `/rv-config` | Show the effective configuration (config file, env overrides, resolved paths) |
54
66
  | `/rv --continue <handle> [text]` | Continue a kept single-review session |
55
67
 
56
68
  - Pass the user target **as given**. Path mentions like `@src` or `@src/foo.ts` are fine as text. Do **not** expand directories into multi-file lists in the parent agent.
@@ -184,6 +196,7 @@ pi-review --reviewers 3 --ui web --ui-url-file /tmp/pi-review-ui-url.txt -- @src
184
196
  pi-review models [search]
185
197
  ```
186
198
  Rules:
199
+ - Extension-registered providers appear in the catalog only when the config enables them (`childExtensions: true`, see **Registered providers** — explicit opt-in).
187
200
  - Run this before building the review command. **Never invent a `provider/model` id** — only ids from the catalog output.
188
201
  - **Cross-model review**: identify the model this host session itself runs on (its id is in your session context), then prefer reviewer models from a different model family — same-family reviewers share the author model's blind spots. On a panel, keep the host's family to a minority of reviewers.
189
202
  - Follow **[references/model-selection.md](./references/model-selection.md)** for everything else: profile inference (code / frontend / plan), priority lists, cross-model resolution, user-named-model resolution, and thinking aliases (`max`/`最高` → `xhigh`, with fallback to the nearest supported level).
@@ -204,7 +217,7 @@ pi-review --reviewers 3 --ui web --ui-url-file /tmp/pi-review-ui-url.txt -- @src
204
217
  pi-review [--mode <name>] [--model <provider/model[:thinking]>] [--keep-session|--continue <handle>] [--progress-log <path>] -- <natural-language target...>
205
218
  ```
206
219
  Rules:
207
- - Use the model decision from step 1 and the execution path from **Default workflow by host**.
220
+ - Use the model decision from step 1 and the execution path from **Default workflow by host**. **Registered providers** enable host extensions only after explicit user acceptance (see **Registered providers**); override a single run with `PI_REVIEW_CHILD_EXTENSIONS=0`.
208
221
  - Omit `--mode` for normal code review; the command defaults to `code`.
209
222
  - Use `--keep-session` only when the user wants follow-up questions on this review; use `--continue <handle>` only with a **Session** path from a prior ASCII footer or `sessionHandle` in `PI_REVIEW_META_JSON`.
210
223
  - Pass the review request as natural language after `--`. Path mentions (`@src`, `@src/foo.ts`) are allowed as text. Do **not** expand directories into multi-file attachment lists — the CLI keeps directory `@refs` as tool path targets and only attaches real files.
@@ -10,6 +10,8 @@ Skills may use Claude Code tool names. On **Codex**, **Claude Code**, **Cursor**
10
10
 
11
11
  This file is **pi-review–specific** and ships with the pi-review package.
12
12
 
13
+ Skill-invoked runs inherit **Registered providers** from the parent skill: the persistent config enables extension-registered providers only after explicit user acceptance (`childExtensions: true` in `~/.pi/pi-review/config.json`). Verify with `cat ~/.pi/pi-review/config.json`; isolate one run with `PI_REVIEW_CHILD_EXTENSIONS=0`.
14
+
13
15
  ## Long-running `pi-review` (default on Codex / Claude Code / Cursor / agy)
14
16
 
15
17
  Native shell tools on these hosts **buffer stdout/stderr until the command exits**. A multi-minute foreground `pi-review` run looks like a silent wait, then one large dump — never promise live foreground streaming. Which side channel to use depends on the run type: panel review gets the browser dashboard; single review and `loop` get the tailed progress log.
@@ -4,7 +4,7 @@ Use this after `pi-review models` (or `pi-review models <search>`). **Never inve
4
4
 
5
5
  ## Workflow (Claude Code, Codex, Cursor, agy, Pi parent agent)
6
6
 
7
- 1. Run `pi-review models` (narrow with search if the user named a vendor or model family).
7
+ 1. Run `pi-review models` (narrow with search if the user named a vendor or model family). Extension-registered providers appear in the catalog only when the config enables them (`childExtensions: true`); if a needed provider is missing, follow the parent skill's **Registered providers** section (explicit opt-in).
8
8
  2. Infer **review profile** from the target (see table below).
9
9
  3. **Cross-model review**: identify the host session's own model — the model that wrote or will fix the code under review; its id is in your own session context. Walk the **priority list** for that profile skipping rows in the host's model family, and pick the **first** remaining row whose `idContains` matches some listed model id (case-insensitive substring). Same-family reviewers share the author model's blind spots; return to the host's own family only when no other family matches the catalog. On a panel, spread reviewer models so the host's family stays a minority. If several ids match one row, prefer the **newest** id (higher version suffix, e.g. `2.7` over `2.5`, `4-8` over `4-6`).
10
10
  4. Set `--model <exact-listed-provider/model>` from the catalog. Add `:thinking` only if that model supports it in Pi and the preset suggests it (see thinking column).