@zephyrdeng/pi-review 0.7.1 → 0.8.1

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.
Files changed (181) hide show
  1. package/README.md +37 -8
  2. package/README.zh-CN.md +31 -5
  3. package/dist/args.d.ts +4 -0
  4. package/dist/args.d.ts.map +1 -1
  5. package/dist/args.js +61 -4
  6. package/dist/args.js.map +1 -1
  7. package/dist/args.test.js +62 -1
  8. package/dist/args.test.js.map +1 -1
  9. package/dist/child-process.d.ts +3 -0
  10. package/dist/child-process.d.ts.map +1 -1
  11. package/dist/child-process.js +27 -5
  12. package/dist/child-process.js.map +1 -1
  13. package/dist/child-process.test.js +42 -1
  14. package/dist/child-process.test.js.map +1 -1
  15. package/dist/cli-exit.test.js +14 -5
  16. package/dist/cli-exit.test.js.map +1 -1
  17. package/dist/cli.js +8 -3
  18. package/dist/cli.js.map +1 -1
  19. package/dist/index.d.ts +7 -5
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +5 -4
  22. package/dist/index.js.map +1 -1
  23. package/dist/install-args.test.js +1 -1
  24. package/dist/install-args.test.js.map +1 -1
  25. package/dist/install.d.ts.map +1 -1
  26. package/dist/install.js +2 -3
  27. package/dist/install.js.map +1 -1
  28. package/dist/json-events.d.ts +6 -0
  29. package/dist/json-events.d.ts.map +1 -1
  30. package/dist/json-events.js +48 -6
  31. package/dist/json-events.js.map +1 -1
  32. package/dist/json-events.test.js +20 -1
  33. package/dist/json-events.test.js.map +1 -1
  34. package/dist/loop.d.ts +28 -2
  35. package/dist/loop.d.ts.map +1 -1
  36. package/dist/loop.js +45 -3
  37. package/dist/loop.js.map +1 -1
  38. package/dist/loop.test.js +24 -1
  39. package/dist/loop.test.js.map +1 -1
  40. package/dist/matcher.test.js +1 -1
  41. package/dist/matcher.test.js.map +1 -1
  42. package/dist/meta-footer.d.ts +4 -8
  43. package/dist/meta-footer.d.ts.map +1 -1
  44. package/dist/meta-footer.js +19 -5
  45. package/dist/meta-footer.js.map +1 -1
  46. package/dist/meta-footer.test.js +11 -4
  47. package/dist/meta-footer.test.js.map +1 -1
  48. package/dist/panel-aggregate.test.js +1 -1
  49. package/dist/panel-aggregate.test.js.map +1 -1
  50. package/dist/panel-cancellation.test.js +33 -2
  51. package/dist/panel-cancellation.test.js.map +1 -1
  52. package/dist/panel-cli-ui.test.d.ts +2 -0
  53. package/dist/panel-cli-ui.test.d.ts.map +1 -0
  54. package/dist/panel-cli-ui.test.js +91 -0
  55. package/dist/panel-cli-ui.test.js.map +1 -0
  56. package/dist/panel-cli.test.js +37 -39
  57. package/dist/panel-cli.test.js.map +1 -1
  58. package/dist/panel-config.d.ts +38 -0
  59. package/dist/panel-config.d.ts.map +1 -1
  60. package/dist/panel-config.js +135 -2
  61. package/dist/panel-config.js.map +1 -1
  62. package/dist/panel-config.test.js +79 -2
  63. package/dist/panel-config.test.js.map +1 -1
  64. package/dist/panel-loop.test.js +1 -1
  65. package/dist/panel-loop.test.js.map +1 -1
  66. package/dist/panel-tools.test.js +1 -1
  67. package/dist/panel-tools.test.js.map +1 -1
  68. package/dist/panel-ui.d.ts +20 -0
  69. package/dist/panel-ui.d.ts.map +1 -0
  70. package/dist/panel-ui.js +84 -0
  71. package/dist/panel-ui.js.map +1 -0
  72. package/dist/panel-ui.test.d.ts +2 -0
  73. package/dist/panel-ui.test.d.ts.map +1 -0
  74. package/dist/panel-ui.test.js +122 -0
  75. package/dist/panel-ui.test.js.map +1 -0
  76. package/dist/panel-view.d.ts +1 -0
  77. package/dist/panel-view.d.ts.map +1 -1
  78. package/dist/panel-view.js +40 -6
  79. package/dist/panel-view.js.map +1 -1
  80. package/dist/panel-view.test.js +68 -1
  81. package/dist/panel-view.test.js.map +1 -1
  82. package/dist/panel.d.ts +11 -1
  83. package/dist/panel.d.ts.map +1 -1
  84. package/dist/panel.js +67 -21
  85. package/dist/panel.js.map +1 -1
  86. package/dist/prompt.d.ts +2 -0
  87. package/dist/prompt.d.ts.map +1 -1
  88. package/dist/prompt.js +34 -3
  89. package/dist/prompt.js.map +1 -1
  90. package/dist/prompt.test.js +21 -2
  91. package/dist/prompt.test.js.map +1 -1
  92. package/dist/review-events.test.js +1 -1
  93. package/dist/review-events.test.js.map +1 -1
  94. package/dist/review-result.test.js +1 -1
  95. package/dist/review-result.test.js.map +1 -1
  96. package/dist/review.js +3 -3
  97. package/dist/review.js.map +1 -1
  98. package/dist/review.meta.test.js +1 -1
  99. package/dist/review.meta.test.js.map +1 -1
  100. package/dist/skill-protocol.test.js +1 -1
  101. package/dist/skill-protocol.test.js.map +1 -1
  102. package/dist/skill-update.test.d.ts +2 -0
  103. package/dist/skill-update.test.d.ts.map +1 -0
  104. package/dist/skill-update.test.js +23 -0
  105. package/dist/skill-update.test.js.map +1 -0
  106. package/dist/skill.d.ts +22 -0
  107. package/dist/skill.d.ts.map +1 -1
  108. package/dist/skill.js +109 -22
  109. package/dist/skill.js.map +1 -1
  110. package/dist/types.d.ts +23 -1
  111. package/dist/types.d.ts.map +1 -1
  112. package/dist/types.js.map +1 -1
  113. package/dist/ui-client.d.ts +13 -0
  114. package/dist/ui-client.d.ts.map +1 -0
  115. package/dist/ui-client.js +161 -0
  116. package/dist/ui-client.js.map +1 -0
  117. package/dist/ui-client.test.d.ts +2 -0
  118. package/dist/ui-client.test.d.ts.map +1 -0
  119. package/dist/ui-client.test.js +48 -0
  120. package/dist/ui-client.test.js.map +1 -0
  121. package/dist/ui-html.d.ts +7 -0
  122. package/dist/ui-html.d.ts.map +1 -0
  123. package/dist/ui-html.js +52 -0
  124. package/dist/ui-html.js.map +1 -0
  125. package/dist/ui-html.test.d.ts +2 -0
  126. package/dist/ui-html.test.d.ts.map +1 -0
  127. package/dist/ui-html.test.js +26 -0
  128. package/dist/ui-html.test.js.map +1 -0
  129. package/dist/ui-server-main.d.ts +3 -0
  130. package/dist/ui-server-main.d.ts.map +1 -0
  131. package/dist/ui-server-main.js +128 -0
  132. package/dist/ui-server-main.js.map +1 -0
  133. package/dist/ui-server-main.test.d.ts +2 -0
  134. package/dist/ui-server-main.test.d.ts.map +1 -0
  135. package/dist/ui-server-main.test.js +123 -0
  136. package/dist/ui-server-main.test.js.map +1 -0
  137. package/dist/ui-server.d.ts +42 -0
  138. package/dist/ui-server.d.ts.map +1 -0
  139. package/dist/ui-server.js +233 -0
  140. package/dist/ui-server.js.map +1 -0
  141. package/dist/ui-server.test.d.ts +2 -0
  142. package/dist/ui-server.test.d.ts.map +1 -0
  143. package/dist/ui-server.test.js +236 -0
  144. package/dist/ui-server.test.js.map +1 -0
  145. package/dist/update.d.ts +2 -0
  146. package/dist/update.d.ts.map +1 -1
  147. package/dist/update.js +80 -20
  148. package/dist/update.js.map +1 -1
  149. package/dist/update.test.d.ts +2 -0
  150. package/dist/update.test.d.ts.map +1 -0
  151. package/dist/update.test.js +17 -0
  152. package/dist/update.test.js.map +1 -0
  153. package/extensions/panel-tool.test.ts +366 -8
  154. package/extensions/panel-tool.ts +289 -68
  155. package/extensions/review.test.ts +79 -0
  156. package/extensions/review.ts +188 -44
  157. package/extensions/rv-completions.test.ts +177 -18
  158. package/extensions/rv-completions.ts +490 -60
  159. package/extensions/rv-interactive.test.ts +562 -0
  160. package/extensions/rv-interactive.ts +616 -0
  161. package/extensions/rv-locale.test.ts +12 -4
  162. package/extensions/rv-locale.ts +44 -11
  163. package/extensions/rv-model-picker.test.ts +172 -0
  164. package/extensions/rv-model-picker.ts +313 -0
  165. package/extensions/rv-model-priorities.test.ts +29 -9
  166. package/extensions/rv-model-priorities.ts +23 -8
  167. package/extensions/rv-prompts.test.ts +274 -2
  168. package/extensions/rv-prompts.ts +479 -33
  169. package/extensions/rv-resolve.test.ts +189 -0
  170. package/extensions/rv-resolve.ts +313 -0
  171. package/extensions/rv-semantic.test.ts +1 -1
  172. package/extensions/rv-semantic.ts +38 -4
  173. package/package.json +7 -4
  174. package/resources/rv-model-priorities.json +18 -9
  175. package/skills/pi-review/SKILL.md +84 -60
  176. package/skills/pi-review/references/codex-tools.md +18 -11
  177. package/skills/pi-review/references/model-selection.md +49 -28
  178. package/dist/extensions/review.d.ts +0 -2
  179. package/dist/extensions/review.js +0 -22
  180. package/dist/extensions/rv-prompts.d.ts +0 -19
  181. package/dist/extensions/rv-prompts.js +0 -132
@@ -0,0 +1,236 @@
1
+ import assert from "node:assert/strict";
2
+ import fs from "node:fs";
3
+ import http from "node:http";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { test, afterEach } from "vitest";
7
+ import { createDashboardRequestListener, createRunDirectory, formatSseEvent, generateCapabilityToken, isAllowedHost, isAllowedOrigin, isValidToken, securityHeaders, splitCompleteLines, writeUrlFileAtomic, } from "./ui-server.js";
8
+ // ---------------------------------------------------------------------------
9
+ // Pure helpers
10
+ // ---------------------------------------------------------------------------
11
+ test("generateCapabilityToken returns high-entropy, unique, URL-safe tokens", () => {
12
+ const a = generateCapabilityToken();
13
+ const b = generateCapabilityToken();
14
+ assert.notEqual(a, b);
15
+ assert.ok(a.length >= 40);
16
+ assert.match(a, /^[A-Za-z0-9_-]+$/);
17
+ });
18
+ test("isValidToken accepts only an exact match and rejects undefined/short candidates", () => {
19
+ const token = generateCapabilityToken();
20
+ assert.equal(isValidToken(token, token), true);
21
+ assert.equal(isValidToken(`${token}x`, token), false);
22
+ assert.equal(isValidToken(token.slice(0, -1), token), false);
23
+ assert.equal(isValidToken(undefined, token), false);
24
+ assert.equal(isValidToken("", token), false);
25
+ });
26
+ test("isAllowedHost accepts only loopback hostnames bound to the server's own port", () => {
27
+ assert.equal(isAllowedHost("127.0.0.1:4100", 4100), true);
28
+ assert.equal(isAllowedHost("localhost:4100", 4100), true);
29
+ assert.equal(isAllowedHost("LOCALHOST:4100", 4100), true);
30
+ assert.equal(isAllowedHost("[::1]:4100", 4100), true);
31
+ assert.equal(isAllowedHost("127.0.0.1:9999", 4100), false);
32
+ assert.equal(isAllowedHost("evil.example:4100", 4100), false);
33
+ assert.equal(isAllowedHost("127.0.0.1", 4100), false);
34
+ assert.equal(isAllowedHost(undefined, 4100), false);
35
+ assert.equal(isAllowedHost("[::1", 4100), false);
36
+ });
37
+ test("isAllowedOrigin allows a missing Origin and exact loopback matches only", () => {
38
+ assert.equal(isAllowedOrigin(undefined, 4100), true);
39
+ assert.equal(isAllowedOrigin("http://127.0.0.1:4100", 4100), true);
40
+ assert.equal(isAllowedOrigin("http://localhost:4100", 4100), true);
41
+ assert.equal(isAllowedOrigin("http://[::1]:4100", 4100), true);
42
+ assert.equal(isAllowedOrigin("http://127.0.0.1:9999", 4100), false);
43
+ assert.equal(isAllowedOrigin("https://evil.example", 4100), false);
44
+ assert.equal(isAllowedOrigin("null", 4100), false);
45
+ });
46
+ test("securityHeaders disables framing, remote assets, and caching", () => {
47
+ const headers = securityHeaders();
48
+ assert.match(headers["Content-Security-Policy"], /default-src 'none'/);
49
+ assert.match(headers["Content-Security-Policy"], /frame-ancestors 'none'/);
50
+ assert.equal(headers["X-Frame-Options"], "DENY");
51
+ assert.equal(headers["Cache-Control"], "no-store");
52
+ });
53
+ test("createRunDirectory creates an owner-only directory", () => {
54
+ const dir = createRunDirectory(`test-${generateCapabilityToken()}`, os.tmpdir());
55
+ try {
56
+ const stat = fs.statSync(dir);
57
+ assert.ok(stat.isDirectory());
58
+ if (process.platform !== "win32") {
59
+ assert.equal(stat.mode & 0o777, 0o700);
60
+ }
61
+ }
62
+ finally {
63
+ fs.rmSync(dir, { recursive: true, force: true });
64
+ }
65
+ });
66
+ test("writeUrlFileAtomic leaves only the final file with no temp remnants", () => {
67
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-ui-test-"));
68
+ try {
69
+ const target = path.join(dir, "url.txt");
70
+ writeUrlFileAtomic(target, "http://127.0.0.1:4100/run/abc");
71
+ assert.equal(fs.readFileSync(target, "utf8"), "http://127.0.0.1:4100/run/abc\n");
72
+ const remaining = fs.readdirSync(dir);
73
+ assert.deepEqual(remaining, ["url.txt"]);
74
+ }
75
+ finally {
76
+ fs.rmSync(dir, { recursive: true, force: true });
77
+ }
78
+ });
79
+ test("formatSseEvent emits an id: line for Last-Event-ID replay plus a data: line", () => {
80
+ const frame = formatSseEvent(3, { type: "reviewer.started" });
81
+ assert.equal(frame, 'id: 3\ndata: {"type":"reviewer.started"}\n\n');
82
+ });
83
+ test("splitCompleteLines buffers a trailing partial line across chunks", () => {
84
+ const first = splitCompleteLines("", 'line-a\nline-b\npart');
85
+ assert.deepEqual(first.lines, ["line-a", "line-b"]);
86
+ assert.equal(first.leftover, "part");
87
+ const second = splitCompleteLines(first.leftover, "ial\nline-c\n");
88
+ assert.deepEqual(second.lines, ["partial", "line-c"]);
89
+ assert.equal(second.leftover, "");
90
+ });
91
+ function httpGet(port, requestPath, headers = {}) {
92
+ return new Promise((resolve, reject) => {
93
+ const req = http.request({ host: "127.0.0.1", port, path: requestPath, headers }, (res) => {
94
+ let body = "";
95
+ res.on("data", (c) => (body += c));
96
+ res.on("end", () => resolve({ status: res.statusCode ?? 0, headers: res.headers, body }));
97
+ });
98
+ req.on("error", reject);
99
+ req.end();
100
+ });
101
+ }
102
+ /** Collect SSE frames until `minFrames` arrive or the timeout fires, then close the connection. */
103
+ function collectSse(port, requestPath, headers, minFrames) {
104
+ return new Promise((resolve, reject) => {
105
+ const req = http.request({ host: "127.0.0.1", port, path: requestPath, headers }, (res) => {
106
+ let body = "";
107
+ const timer = setTimeout(() => {
108
+ req.destroy();
109
+ resolve(body);
110
+ }, 2000);
111
+ res.on("data", (c) => {
112
+ body += c;
113
+ if ((body.match(/^id: /gm) ?? []).length >= minFrames) {
114
+ clearTimeout(timer);
115
+ req.destroy();
116
+ resolve(body);
117
+ }
118
+ });
119
+ res.on("error", () => resolve(body));
120
+ });
121
+ req.on("error", reject);
122
+ req.end();
123
+ });
124
+ }
125
+ let activeServer;
126
+ let activeDir;
127
+ afterEach(() => {
128
+ if (activeServer) {
129
+ activeServer.closeAllConnections();
130
+ activeServer.close();
131
+ activeServer = undefined;
132
+ }
133
+ if (activeDir) {
134
+ fs.rmSync(activeDir, { recursive: true, force: true });
135
+ activeDir = undefined;
136
+ }
137
+ });
138
+ async function startTestServer(overrides = {}) {
139
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-ui-test-"));
140
+ activeDir = dir;
141
+ const eventsPath = path.join(dir, "events.jsonl");
142
+ fs.writeFileSync(eventsPath, "");
143
+ const token = generateCapabilityToken();
144
+ const server = http.createServer();
145
+ await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
146
+ const port = server.address().port;
147
+ const ctx = {
148
+ token,
149
+ port,
150
+ eventsPath,
151
+ html: "<!doctype html><title>pi-review dashboard</title>",
152
+ staticAssets: { "panel-view.js": { contentType: "text/javascript; charset=utf-8", body: "export const x = 1;" } },
153
+ pollIntervalMs: 20,
154
+ ...overrides,
155
+ };
156
+ server.on("request", createDashboardRequestListener(ctx));
157
+ activeServer = server;
158
+ return { port, token, eventsPath };
159
+ }
160
+ test("dashboard serves the HTML page for a valid capability token", async () => {
161
+ const { port, token } = await startTestServer();
162
+ const res = await httpGet(port, `/run/${token}`, { Host: `127.0.0.1:${port}` });
163
+ assert.equal(res.status, 200);
164
+ assert.match(res.headers["content-type"] ?? "", /text\/html/);
165
+ assert.match(res.body, /pi-review dashboard/);
166
+ assert.equal(res.headers["x-frame-options"], "DENY");
167
+ assert.match(String(res.headers["content-security-policy"] ?? ""), /frame-ancestors 'none'/);
168
+ });
169
+ test("dashboard rejects an invalid or wrong-length capability token with 404", async () => {
170
+ const { port, token } = await startTestServer();
171
+ const wrong = await httpGet(port, `/run/${token}x`, { Host: `127.0.0.1:${port}` });
172
+ assert.equal(wrong.status, 404);
173
+ const garbage = await httpGet(port, "/run/not-a-token", { Host: `127.0.0.1:${port}` });
174
+ assert.equal(garbage.status, 404);
175
+ });
176
+ test("dashboard rejects a non-loopback Host header", async () => {
177
+ const { port, token } = await startTestServer();
178
+ const res = await httpGet(port, `/run/${token}`, { Host: "evil.example" });
179
+ assert.equal(res.status, 400);
180
+ });
181
+ test("dashboard rejects a cross-origin request but allows a missing Origin", async () => {
182
+ const { port, token } = await startTestServer();
183
+ const bad = await httpGet(port, `/run/${token}`, { Host: `127.0.0.1:${port}`, Origin: "https://evil.example" });
184
+ assert.equal(bad.status, 403);
185
+ const ok = await httpGet(port, `/run/${token}`, { Host: `127.0.0.1:${port}`, Origin: `http://127.0.0.1:${port}` });
186
+ assert.equal(ok.status, 200);
187
+ const missing = await httpGet(port, `/run/${token}`, { Host: `127.0.0.1:${port}` });
188
+ assert.equal(missing.status, 200);
189
+ });
190
+ test("dashboard serves a static asset under the token boundary and 404s unknown assets", async () => {
191
+ const { port, token } = await startTestServer();
192
+ const res = await httpGet(port, `/run/${token}/static/panel-view.js`, { Host: `127.0.0.1:${port}` });
193
+ assert.equal(res.status, 200);
194
+ assert.match(res.headers["content-type"] ?? "", /javascript/);
195
+ assert.match(res.body, /export const x/);
196
+ const missing = await httpGet(port, `/run/${token}/static/does-not-exist.js`, { Host: `127.0.0.1:${port}` });
197
+ assert.equal(missing.status, 404);
198
+ });
199
+ test("dashboard SSE stream replays existing events then tails new appends in seq order", async () => {
200
+ const { port, token, eventsPath } = await startTestServer();
201
+ fs.appendFileSync(eventsPath, `${JSON.stringify({ v: 1, runId: "r1", seq: 1, at: 1, type: "panel.started" })}\n`);
202
+ fs.appendFileSync(eventsPath, `${JSON.stringify({ v: 1, runId: "r1", seq: 2, at: 2, type: "reviewer.queued" })}\n`);
203
+ const collecting = collectSse(port, `/run/${token}/events`, { Host: `127.0.0.1:${port}` }, 3);
204
+ await new Promise((resolve) => setTimeout(resolve, 60));
205
+ fs.appendFileSync(eventsPath, `${JSON.stringify({ v: 1, runId: "r1", seq: 3, at: 3, type: "reviewer.started" })}\n`);
206
+ const body = await collecting;
207
+ assert.match(body, /id: 1\n/);
208
+ assert.match(body, /id: 2\n/);
209
+ assert.match(body, /id: 3\n/);
210
+ assert.match(body, /"type":"panel.started"/);
211
+ assert.match(body, /"type":"reviewer.started"/);
212
+ });
213
+ test("dashboard SSE stream honors Last-Event-ID and only replays newer events", async () => {
214
+ const { port, token, eventsPath } = await startTestServer();
215
+ fs.appendFileSync(eventsPath, `${JSON.stringify({ v: 1, runId: "r1", seq: 1, at: 1, type: "panel.started" })}\n`);
216
+ fs.appendFileSync(eventsPath, `${JSON.stringify({ v: 1, runId: "r1", seq: 2, at: 2, type: "reviewer.queued" })}\n`);
217
+ fs.appendFileSync(eventsPath, `${JSON.stringify({ v: 1, runId: "r1", seq: 3, at: 3, type: "reviewer.started" })}\n`);
218
+ const body = await collectSse(port, `/run/${token}/events`, { Host: `127.0.0.1:${port}`, "Last-Event-ID": "2" }, 1);
219
+ assert.doesNotMatch(body, /id: 1\n/);
220
+ assert.doesNotMatch(body, /id: 2\n/);
221
+ assert.match(body, /id: 3\n/);
222
+ });
223
+ test("dashboard rejects non-GET/HEAD methods", async () => {
224
+ const { port, token } = await startTestServer();
225
+ const res = await new Promise((resolve, reject) => {
226
+ const req = http.request({ host: "127.0.0.1", port, path: `/run/${token}`, method: "POST", headers: { Host: `127.0.0.1:${port}` } }, (r) => {
227
+ let body = "";
228
+ r.on("data", (c) => (body += c));
229
+ r.on("end", () => resolve({ status: r.statusCode ?? 0, headers: r.headers, body }));
230
+ });
231
+ req.on("error", reject);
232
+ req.end();
233
+ });
234
+ assert.equal(res.status, 405);
235
+ });
236
+ //# sourceMappingURL=ui-server.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-server.test.js","sourceRoot":"","sources":["../src/ui-server.test.ts"],"names":[],"mappings":"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"}
package/dist/update.d.ts CHANGED
@@ -1,2 +1,4 @@
1
+ /** Compare numeric semver cores (1.2.3[-tag] → major.minor.patch). Returns -1/0/1. */
2
+ export declare function compareSemver(a: string, b: string): number;
1
3
  export declare function runUpdate(): void;
2
4
  //# sourceMappingURL=update.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AA6BA,wBAAgB,SAAS,IAAI,IAAI,CA4ChC"}
1
+ {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAoBA,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAgB1D;AA4BD,wBAAgB,SAAS,IAAI,IAAI,CAkFhC"}
package/dist/update.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { createRequire } from "node:module";
3
+ import { runUpdateSkill } from "./skill.js";
3
4
  const PKG_NAME = "@zephyrdeng/pi-review";
4
5
  function getCurrentVersion() {
5
6
  const require = createRequire(import.meta.url);
@@ -13,6 +14,26 @@ function getLatestVersion() {
13
14
  });
14
15
  return result.status === 0 ? result.stdout.trim() : null;
15
16
  }
17
+ /** Compare numeric semver cores (1.2.3[-tag] → major.minor.patch). Returns -1/0/1. */
18
+ export function compareSemver(a, b) {
19
+ const parse = (v) => {
20
+ const core = v.trim().replace(/^v/i, "").split("-")[0] ?? "";
21
+ const parts = core.split(".").map((p) => {
22
+ const n = Number.parseInt(p, 10);
23
+ return Number.isFinite(n) ? n : 0;
24
+ });
25
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
26
+ };
27
+ const pa = parse(a);
28
+ const pb = parse(b);
29
+ for (let i = 0; i < 3; i++) {
30
+ if (pa[i] < pb[i])
31
+ return -1;
32
+ if (pa[i] > pb[i])
33
+ return 1;
34
+ }
35
+ return 0;
36
+ }
16
37
  function box(lines) {
17
38
  const width = Math.max(...lines.map((l) => l.length));
18
39
  const pad = (s) => s + " ".repeat(width - s.length);
@@ -22,6 +43,19 @@ function box(lines) {
22
43
  const body = lines.map((l) => `│ ${pad(l)} │`).join("\n");
23
44
  return `${top}\n${empty}\n${body}\n${empty}\n${bot}\n`;
24
45
  }
46
+ function refreshSkill() {
47
+ const skill = runUpdateSkill();
48
+ if (!skill.ok) {
49
+ process.stderr.write(box([
50
+ "Skill refresh failed.",
51
+ "",
52
+ "Retry with:",
53
+ " pi-review install-skill",
54
+ ]));
55
+ return false;
56
+ }
57
+ return true;
58
+ }
25
59
  export function runUpdate() {
26
60
  const current = getCurrentVersion();
27
61
  const latest = getLatestVersion();
@@ -29,36 +63,62 @@ export function runUpdate() {
29
63
  process.stderr.write(box(["Failed to fetch latest version from npm registry"]));
30
64
  process.exit(1);
31
65
  }
32
- if (current === latest) {
66
+ const cmp = compareSemver(current, latest);
67
+ let packageLine;
68
+ if (cmp === 0) {
69
+ packageLine = `Package already up to date (v${current})`;
33
70
  process.stdout.write(box([
34
71
  `pi-review v${current}`,
35
72
  "",
36
- "Already up to date ✓",
73
+ "Package already up to date ✓",
74
+ "Refreshing agent skill...",
37
75
  ]));
38
- return;
39
76
  }
40
- process.stdout.write(box([
41
- `Update available: ${current} → ${latest}`,
42
- "",
43
- "Updating...",
44
- ]));
45
- const install = spawnSync("npm", ["install", "-g", `${PKG_NAME}@latest`], {
46
- encoding: "utf8",
47
- stdio: "inherit",
48
- timeout: 60_000,
49
- });
50
- if (install.status !== 0) {
51
- process.stderr.write(box([
52
- "Update failed. Run manually:",
77
+ else if (cmp > 0) {
78
+ // Local/dev build is ahead of the registry — do not reinstall @latest (would downgrade).
79
+ packageLine = `Local v${current} is newer than npm v${latest}`;
80
+ process.stdout.write(box([
81
+ packageLine,
53
82
  "",
54
- `npm install -g ${PKG_NAME}@latest`,
83
+ "Skipping package install (would downgrade)",
84
+ "Refreshing agent skill...",
85
+ ]));
86
+ }
87
+ else {
88
+ process.stdout.write(box([
89
+ `Update available: ${current} → ${latest}`,
90
+ "",
91
+ "Updating package...",
92
+ ]));
93
+ const install = spawnSync("npm", ["install", "-g", `${PKG_NAME}@latest`], {
94
+ encoding: "utf8",
95
+ stdio: "inherit",
96
+ timeout: 60_000,
97
+ });
98
+ if (install.status !== 0) {
99
+ process.stderr.write(box([
100
+ "Update failed. Run manually:",
101
+ "",
102
+ `npm install -g ${PKG_NAME}@latest`,
103
+ ]));
104
+ process.exit(1);
105
+ }
106
+ packageLine = `Package updated: ${current} → ${latest}`;
107
+ process.stdout.write(box([
108
+ packageLine,
109
+ "",
110
+ "Refreshing agent skill...",
55
111
  ]));
56
- process.exit(1);
57
112
  }
113
+ // skills CLI pulls latest skill content from the source repo; the direct
114
+ // fallback copies from this package tree (refreshed on disk after npm -g).
115
+ const skillOk = refreshSkill();
58
116
  process.stdout.write(box([
59
- `Updated: ${current} → ${latest}`,
117
+ packageLine,
118
+ skillOk ? "Skill refreshed ✓" : "Skill refresh failed",
60
119
  "",
61
- "Done ✓",
120
+ skillOk ? "Done ✓" : "Package ok; skill needs manual install-skill",
62
121
  ]));
122
+ process.exit(skillOk ? 0 : 1);
63
123
  }
64
124
  //# sourceMappingURL=update.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../src/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AAEzC,SAAS,iBAAiB;IACxB,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAwB,CAAC;IAC9D,OAAO,GAAG,CAAC,OAAO,CAAC;AACrB,CAAC;AAED,SAAS,gBAAgB;IACvB,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,EAAE;QAC7D,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,MAAM;KAChB,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,CAAS,EAAE,CAAS;IAChD,MAAM,KAAK,GAAG,CAAC,CAAS,EAAY,EAAE;QACpC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YACtC,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjC,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC;IACF,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,IAAI,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE;YAAE,OAAO,CAAC,CAAC,CAAC;QAC/B,IAAI,EAAE,CAAC,CAAC,CAAE,GAAG,EAAE,CAAC,CAAC,CAAE;YAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,GAAG,CAAC,KAAe;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;IACzC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1D,OAAO,GAAG,GAAG,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,GAAG,IAAI,CAAC;AACzD,CAAC;AAED,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;YACF,uBAAuB;YACvB,EAAE;YACF,aAAa;YACb,2BAA2B;SAC5B,CAAC,CACH,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,kDAAkD,CAAC,CAAC,CAAC,CAAC;QAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC3C,IAAI,WAAmB,CAAC;IAExB,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,WAAW,GAAG,gCAAgC,OAAO,GAAG,CAAC;QACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;YACF,cAAc,OAAO,EAAE;YACvB,EAAE;YACF,8BAA8B;YAC9B,2BAA2B;SAC5B,CAAC,CACH,CAAC;IACJ,CAAC;SAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QACnB,yFAAyF;QACzF,WAAW,GAAG,UAAU,OAAO,uBAAuB,MAAM,EAAE,CAAC;QAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;YACF,WAAW;YACX,EAAE;YACF,4CAA4C;YAC5C,2BAA2B;SAC5B,CAAC,CACH,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;YACF,qBAAqB,OAAO,MAAM,MAAM,EAAE;YAC1C,EAAE;YACF,qBAAqB;SACtB,CAAC,CACH,CAAC;QAEF,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,QAAQ,SAAS,CAAC,EAAE;YACxE,QAAQ,EAAE,MAAM;YAChB,KAAK,EAAE,SAAS;YAChB,OAAO,EAAE,MAAM;SAChB,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;gBACF,8BAA8B;gBAC9B,EAAE;gBACF,kBAAkB,QAAQ,SAAS;aACpC,CAAC,CACH,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,WAAW,GAAG,oBAAoB,OAAO,MAAM,MAAM,EAAE,CAAC;QACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;YACF,WAAW;YACX,EAAE;YACF,2BAA2B;SAC5B,CAAC,CACH,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,2EAA2E;IAC3E,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAE/B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,CAAC;QACF,WAAW;QACX,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,sBAAsB;QACtD,EAAE;QACF,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,8CAA8C;KACpE,CAAC,CACH,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=update.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.d.ts","sourceRoot":"","sources":["../src/update.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "vitest";
3
+ import { compareSemver } from "./update.js";
4
+ test("compareSemver orders patch/minor/major", () => {
5
+ assert.equal(compareSemver("0.7.1", "0.8.0"), -1);
6
+ assert.equal(compareSemver("0.8.0", "0.7.1"), 1);
7
+ assert.equal(compareSemver("0.8.0", "0.8.0"), 0);
8
+ assert.equal(compareSemver("1.0.0", "0.9.9"), 1);
9
+ assert.equal(compareSemver("v0.8.0", "0.8.0"), 0);
10
+ });
11
+ test("compareSemver treats update direction as current → latest only when latest is newer", () => {
12
+ const current = "0.7.1";
13
+ const latest = "0.8.0";
14
+ assert.ok(compareSemver(current, latest) < 0, "registry newer → should upgrade");
15
+ assert.ok(compareSemver(latest, current) > 0, "local newer → must not install @latest");
16
+ });
17
+ //# sourceMappingURL=update.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.test.js","sourceRoot":"","sources":["../src/update.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qFAAqF,EAAE,GAAG,EAAE;IAC/F,MAAM,OAAO,GAAG,OAAO,CAAC;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,iCAAiC,CAAC,CAAC;IACjF,MAAM,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,wCAAwC,CAAC,CAAC;AAC1F,CAAC,CAAC,CAAC"}