argus-reviewer-e2e 0.3.0 → 0.4.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.
Files changed (89) hide show
  1. package/README.md +84 -71
  2. package/action/action.yml +134 -10
  3. package/action/approval-review.mjs +13 -3
  4. package/action/bootstrap.mjs +4 -0
  5. package/action/emit-review.mjs +16 -0
  6. package/action/runtime.mjs +32 -0
  7. package/action/sticky-comment.cjs +1260 -479
  8. package/dist/cli.d.ts +103 -7
  9. package/dist/cli.js +1208 -186
  10. package/dist/config.d.ts +96 -11
  11. package/dist/config.js +102 -4
  12. package/dist/detect.d.ts +29 -2
  13. package/dist/detect.js +98 -7
  14. package/dist/driver/browser.d.ts +32 -0
  15. package/dist/driver/browser.js +56 -1
  16. package/dist/driver/target.d.ts +4 -1
  17. package/dist/driver/target.js +27 -6
  18. package/dist/engine/actions.d.ts +5 -0
  19. package/dist/engine/actions.js +8 -0
  20. package/dist/engine/explore.d.ts +78 -0
  21. package/dist/engine/explore.js +373 -0
  22. package/dist/engine/loop.d.ts +2 -2
  23. package/dist/engine/loop.js +8 -8
  24. package/dist/engine/prompts.d.ts +28 -1
  25. package/dist/engine/prompts.js +88 -0
  26. package/dist/evidence/ci.d.ts +13 -1
  27. package/dist/evidence/ci.js +38 -3
  28. package/dist/evidence/gate.d.ts +8 -0
  29. package/dist/evidence/gate.js +1 -1
  30. package/dist/evidence/link.js +1 -1
  31. package/dist/executor/a0.d.ts +114 -1
  32. package/dist/executor/a0.js +216 -4
  33. package/dist/fsutil.d.ts +3 -2
  34. package/dist/fsutil.js +7 -4
  35. package/dist/journal/schema.d.ts +1 -1
  36. package/dist/log.d.ts +2 -1
  37. package/dist/log.js +10 -2
  38. package/dist/mention.d.ts +45 -0
  39. package/dist/mention.js +107 -0
  40. package/dist/pipeline/app.d.ts +126 -0
  41. package/dist/pipeline/app.js +250 -0
  42. package/dist/pipeline/budget.d.ts +1 -0
  43. package/dist/pipeline/budget.js +1 -1
  44. package/dist/pipeline/verify.d.ts +20 -3
  45. package/dist/pipeline/verify.js +189 -35
  46. package/dist/probe/persist.d.ts +68 -0
  47. package/dist/probe/persist.js +184 -0
  48. package/dist/probe/queue.d.ts +12 -0
  49. package/dist/probe/queue.js +10 -2
  50. package/dist/report/brand-assets.generated.d.ts +9 -0
  51. package/dist/report/brand-assets.generated.js +8 -0
  52. package/dist/report/comment.d.ts +99 -6
  53. package/dist/report/comment.js +292 -103
  54. package/dist/report/html.d.ts +50 -0
  55. package/dist/report/html.js +879 -0
  56. package/dist/report/manifest.d.ts +29 -0
  57. package/dist/report/manifest.js +37 -0
  58. package/dist/report/run.d.ts +54 -1
  59. package/dist/report/run.js +34 -9
  60. package/dist/report/viewmodel.d.ts +91 -0
  61. package/dist/report/viewmodel.js +241 -0
  62. package/dist/review/adjudicate.d.ts +6 -6
  63. package/dist/review/adjudicate.js +2 -2
  64. package/dist/review/inline.d.ts +44 -0
  65. package/dist/review/inline.js +95 -0
  66. package/dist/review/packs.d.ts +21 -0
  67. package/dist/review/packs.js +47 -0
  68. package/dist/review/scope.d.ts +16 -0
  69. package/dist/review/scope.js +74 -0
  70. package/dist/review/secrets.d.ts +10 -10
  71. package/dist/review/secrets.js +7 -7
  72. package/dist/review/testfiles.d.ts +18 -0
  73. package/dist/review/testfiles.js +26 -0
  74. package/dist/review/triage.d.ts +1 -1
  75. package/dist/review/triage.js +10 -10
  76. package/dist/review/validate.d.ts +41 -0
  77. package/dist/review/validate.js +76 -0
  78. package/dist/ui/errors.d.ts +54 -0
  79. package/dist/ui/errors.js +236 -0
  80. package/dist/ui/style.d.ts +34 -0
  81. package/dist/ui/style.js +48 -0
  82. package/dist/ui/summary.d.ts +38 -0
  83. package/dist/ui/summary.js +101 -0
  84. package/dist/vision/cost.d.ts +1 -1
  85. package/dist/vision/decisions.d.ts +9 -3
  86. package/dist/vision/decisions.js +31 -21
  87. package/dist/vision/openrouter.d.ts +4 -0
  88. package/dist/vision/openrouter.js +30 -4
  89. package/package.json +11 -2
@@ -21,6 +21,8 @@ export interface JsonSchema {
21
21
  export interface OpenRouterClientOptions {
22
22
  apiKey: string;
23
23
  fetch?: typeof fetch;
24
+ /** Per-request timeout in ms. Default 120_000. */
25
+ timeoutMs?: number;
24
26
  /**
25
27
  * Extra metadata sent on every request. `trace` is merged into the request
26
28
  * body `trace` field for cost attribution. `headers` are merged into the
@@ -44,10 +46,12 @@ export interface OpenRouterClientOptions {
44
46
  export declare class OpenRouterClient {
45
47
  private _apiKey;
46
48
  private _fetch;
49
+ private _timeoutMs;
47
50
  private _trace;
48
51
  private _headers;
49
52
  private _onCall;
50
53
  constructor(opts: OpenRouterClientOptions);
54
+ private _request;
51
55
  complete(opts: {
52
56
  model: string;
53
57
  messages: Message[];
@@ -1,8 +1,16 @@
1
1
  import { debug } from '../debug.js';
2
+ import { classifyHttpStatus, CliError, pickProviderError } from '../ui/errors.js';
2
3
  import { makeCallCost } from './cost.js';
4
+ /**
5
+ * Per-request timeout for OpenRouter calls. A hung connection otherwise
6
+ * blocks the caller forever — observed in the wild pinning a self-hosted
7
+ * review job for 90+ minutes on one socket.
8
+ */
9
+ const REQUEST_TIMEOUT_MS = 120_000;
3
10
  export class OpenRouterClient {
4
11
  _apiKey;
5
12
  _fetch;
13
+ _timeoutMs;
6
14
  _trace;
7
15
  _headers;
8
16
  _onCall;
@@ -12,10 +20,14 @@ export class OpenRouterClient {
12
20
  }
13
21
  this._apiKey = opts.apiKey;
14
22
  this._fetch = opts.fetch ?? globalThis.fetch;
23
+ this._timeoutMs = opts.timeoutMs ?? REQUEST_TIMEOUT_MS;
15
24
  this._trace = opts.trace;
16
25
  this._headers = opts.headers;
17
26
  this._onCall = opts.onCall;
18
27
  }
28
+ _request(url, init) {
29
+ return this._fetch(url, { ...init, signal: AbortSignal.timeout(this._timeoutMs) });
30
+ }
19
31
  async complete(opts) {
20
32
  const candidates = [opts.model, ...(opts.escalationModels ?? [])];
21
33
  const errors = [];
@@ -53,10 +65,23 @@ export class OpenRouterClient {
53
65
  errors.push(err);
54
66
  }
55
67
  }
56
- throw new Error(`OpenRouter completion failed for all candidate models: ${errors.map((e) => e.message).join('; ')}`);
68
+ const prefix = 'OpenRouter completion failed for all candidate models';
69
+ // When every candidate failed for a provider/account reason, keep the
70
+ // class (R15) so the CLI can name it and offer the matching fix.
71
+ const classified = pickProviderError(errors);
72
+ if (classified !== undefined) {
73
+ throw new CliError(classified.code, classified.message, {
74
+ cause: classified,
75
+ ...(classified.retryAfterSeconds !== undefined
76
+ ? { retryAfterSeconds: classified.retryAfterSeconds }
77
+ : {}),
78
+ ...(classified.httpStatus !== undefined ? { httpStatus: classified.httpStatus } : {}),
79
+ });
80
+ }
81
+ throw new Error(`${prefix}: ${errors.map((e) => e.message).join('; ')}`);
57
82
  }
58
83
  async reconcile(id) {
59
- const res = await this._fetch(`https://openrouter.ai/api/v1/generation?id=${encodeURIComponent(id)}`, {
84
+ const res = await this._request(`https://openrouter.ai/api/v1/generation?id=${encodeURIComponent(id)}`, {
60
85
  method: 'GET',
61
86
  headers: { Authorization: `Bearer ${this._apiKey}` },
62
87
  });
@@ -98,13 +123,14 @@ export class OpenRouterClient {
98
123
  'X-OpenRouter-Metadata': 'enabled',
99
124
  ...(this._headers ?? {}),
100
125
  };
101
- const res = await this._fetch('https://openrouter.ai/api/v1/chat/completions', {
126
+ const res = await this._request('https://openrouter.ai/api/v1/chat/completions', {
102
127
  method: 'POST',
103
128
  headers,
104
129
  body: JSON.stringify(body),
105
130
  });
106
131
  if (!res.ok) {
107
- throw new Error(`OpenRouter request failed: ${res.status} ${res.statusText}`);
132
+ throw (classifyHttpStatus(res.status, res.headers) ??
133
+ new Error(`OpenRouter request failed: ${res.status} ${res.statusText}`));
108
134
  }
109
135
  return (await res.json());
110
136
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argus-reviewer-e2e",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "argus-reviewer — open-source vision-model E2E testing harness. Record, replay, heal, and assert with any OpenRouter model under a hard budget cap.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,6 +34,7 @@
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsc -p tsconfig.build.json",
37
+ "check:dist": "test -z \"$(git status --porcelain -- dist/)\" && test -z \"$(git ls-files --others --ignored --exclude-standard -- dist/)\"",
37
38
  "test": "vitest run",
38
39
  "test:watch": "vitest",
39
40
  "lint": "eslint .",
@@ -42,16 +43,24 @@
42
43
  "prepare": "npm run build && chmod +x dist/cli.js",
43
44
  "eval": "node evals/run.mjs",
44
45
  "watch": "node scripts/watch.mjs",
46
+ "smoke:dashboard": "node tests/e2e/dashboard-smoke.mjs",
45
47
  "app": "electron electron",
46
- "demo": "node scripts/demo.mjs"
48
+ "demo": "node scripts/demo.mjs",
49
+ "demo:record": "node scripts/demo-record.mjs",
50
+ "tokens": "node scripts/build-tokens.mjs",
51
+ "brand": "node scripts/build-brand.mjs",
52
+ "render:brand": "node scripts/render-brand.mjs",
53
+ "check:contrast": "node scripts/check-contrast.mjs"
47
54
  },
48
55
  "devDependencies": {
49
56
  "@eslint/js": "^10.0.1",
57
+ "@resvg/resvg-js": "^2.6.2",
50
58
  "@types/node": "^26.6.2",
51
59
  "electron": "^44.2.0",
52
60
  "eslint": "^10.11.0",
53
61
  "globals": "^17.12.0",
54
62
  "prettier": "^3.0.0",
63
+ "svgo": "^4.1.0",
55
64
  "typescript-eslint": "^8.0.0",
56
65
  "vitest": "^5.0.1"
57
66
  },