@lcv-ideas-software/cross-review 4.0.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 (122) hide show
  1. package/CHANGELOG.md +2568 -0
  2. package/LICENSE +201 -0
  3. package/NOTICE +26 -0
  4. package/README.md +208 -0
  5. package/SECURITY.md +52 -0
  6. package/dist/scripts/api-streaming-smoke.d.ts +1 -0
  7. package/dist/scripts/api-streaming-smoke.js +78 -0
  8. package/dist/scripts/api-streaming-smoke.js.map +1 -0
  9. package/dist/scripts/runtime-default-smoke.d.ts +1 -0
  10. package/dist/scripts/runtime-default-smoke.js +88 -0
  11. package/dist/scripts/runtime-default-smoke.js.map +1 -0
  12. package/dist/scripts/runtime-smoke.d.ts +1 -0
  13. package/dist/scripts/runtime-smoke.js +148 -0
  14. package/dist/scripts/runtime-smoke.js.map +1 -0
  15. package/dist/scripts/smoke.d.ts +1 -0
  16. package/dist/scripts/smoke.js +6156 -0
  17. package/dist/scripts/smoke.js.map +1 -0
  18. package/dist/src/core/cache-manifest.d.ts +22 -0
  19. package/dist/src/core/cache-manifest.js +133 -0
  20. package/dist/src/core/cache-manifest.js.map +1 -0
  21. package/dist/src/core/caller-tokens.d.ts +32 -0
  22. package/dist/src/core/caller-tokens.js +240 -0
  23. package/dist/src/core/caller-tokens.js.map +1 -0
  24. package/dist/src/core/config.d.ts +9 -0
  25. package/dist/src/core/config.js +643 -0
  26. package/dist/src/core/config.js.map +1 -0
  27. package/dist/src/core/convergence.d.ts +5 -0
  28. package/dist/src/core/convergence.js +186 -0
  29. package/dist/src/core/convergence.js.map +1 -0
  30. package/dist/src/core/cost.d.ts +59 -0
  31. package/dist/src/core/cost.js +359 -0
  32. package/dist/src/core/cost.js.map +1 -0
  33. package/dist/src/core/file-config.d.ts +316 -0
  34. package/dist/src/core/file-config.js +490 -0
  35. package/dist/src/core/file-config.js.map +1 -0
  36. package/dist/src/core/orchestrator.d.ts +199 -0
  37. package/dist/src/core/orchestrator.js +3430 -0
  38. package/dist/src/core/orchestrator.js.map +1 -0
  39. package/dist/src/core/prompt-parts.d.ts +58 -0
  40. package/dist/src/core/prompt-parts.js +122 -0
  41. package/dist/src/core/prompt-parts.js.map +1 -0
  42. package/dist/src/core/relator-lottery.d.ts +23 -0
  43. package/dist/src/core/relator-lottery.js +112 -0
  44. package/dist/src/core/relator-lottery.js.map +1 -0
  45. package/dist/src/core/reports.d.ts +2 -0
  46. package/dist/src/core/reports.js +82 -0
  47. package/dist/src/core/reports.js.map +1 -0
  48. package/dist/src/core/session-store.d.ts +149 -0
  49. package/dist/src/core/session-store.js +1923 -0
  50. package/dist/src/core/session-store.js.map +1 -0
  51. package/dist/src/core/status.d.ts +61 -0
  52. package/dist/src/core/status.js +249 -0
  53. package/dist/src/core/status.js.map +1 -0
  54. package/dist/src/core/timeouts.d.ts +2 -0
  55. package/dist/src/core/timeouts.js +3 -0
  56. package/dist/src/core/timeouts.js.map +1 -0
  57. package/dist/src/core/types.d.ts +604 -0
  58. package/dist/src/core/types.js +36 -0
  59. package/dist/src/core/types.js.map +1 -0
  60. package/dist/src/dashboard/server.d.ts +2 -0
  61. package/dist/src/dashboard/server.js +339 -0
  62. package/dist/src/dashboard/server.js.map +1 -0
  63. package/dist/src/mcp/server.d.ts +54 -0
  64. package/dist/src/mcp/server.js +1584 -0
  65. package/dist/src/mcp/server.js.map +1 -0
  66. package/dist/src/observability/logger.d.ts +9 -0
  67. package/dist/src/observability/logger.js +24 -0
  68. package/dist/src/observability/logger.js.map +1 -0
  69. package/dist/src/peers/anthropic.d.ts +14 -0
  70. package/dist/src/peers/anthropic.js +290 -0
  71. package/dist/src/peers/anthropic.js.map +1 -0
  72. package/dist/src/peers/base.d.ts +72 -0
  73. package/dist/src/peers/base.js +416 -0
  74. package/dist/src/peers/base.js.map +1 -0
  75. package/dist/src/peers/deepseek.d.ts +12 -0
  76. package/dist/src/peers/deepseek.js +246 -0
  77. package/dist/src/peers/deepseek.js.map +1 -0
  78. package/dist/src/peers/errors.d.ts +2 -0
  79. package/dist/src/peers/errors.js +185 -0
  80. package/dist/src/peers/errors.js.map +1 -0
  81. package/dist/src/peers/gemini.d.ts +13 -0
  82. package/dist/src/peers/gemini.js +215 -0
  83. package/dist/src/peers/gemini.js.map +1 -0
  84. package/dist/src/peers/grok.d.ts +17 -0
  85. package/dist/src/peers/grok.js +346 -0
  86. package/dist/src/peers/grok.js.map +1 -0
  87. package/dist/src/peers/model-selection.d.ts +4 -0
  88. package/dist/src/peers/model-selection.js +260 -0
  89. package/dist/src/peers/model-selection.js.map +1 -0
  90. package/dist/src/peers/openai.d.ts +14 -0
  91. package/dist/src/peers/openai.js +299 -0
  92. package/dist/src/peers/openai.js.map +1 -0
  93. package/dist/src/peers/perplexity.d.ts +18 -0
  94. package/dist/src/peers/perplexity.js +375 -0
  95. package/dist/src/peers/perplexity.js.map +1 -0
  96. package/dist/src/peers/registry.d.ts +3 -0
  97. package/dist/src/peers/registry.js +77 -0
  98. package/dist/src/peers/registry.js.map +1 -0
  99. package/dist/src/peers/retry.d.ts +2 -0
  100. package/dist/src/peers/retry.js +36 -0
  101. package/dist/src/peers/retry.js.map +1 -0
  102. package/dist/src/peers/stub.d.ts +13 -0
  103. package/dist/src/peers/stub.js +344 -0
  104. package/dist/src/peers/stub.js.map +1 -0
  105. package/dist/src/peers/text.d.ts +18 -0
  106. package/dist/src/peers/text.js +39 -0
  107. package/dist/src/peers/text.js.map +1 -0
  108. package/dist/src/security/redact.d.ts +2 -0
  109. package/dist/src/security/redact.js +128 -0
  110. package/dist/src/security/redact.js.map +1 -0
  111. package/docs/api-keys.md +34 -0
  112. package/docs/architecture.md +118 -0
  113. package/docs/caching.md +135 -0
  114. package/docs/costs.md +40 -0
  115. package/docs/evidence-preflight.md +88 -0
  116. package/docs/github-security-baseline.md +32 -0
  117. package/docs/model-selection.md +105 -0
  118. package/docs/reports/cross-review-v2-api-capability-smoke-2026-04-30.md +354 -0
  119. package/docs/reports/cross-review-v2-format-recovery-findings-2026-04-28.md +223 -0
  120. package/docs/reports/cross-review-v2-official-provider-docs-refresh-2026-05-05.md +60 -0
  121. package/docs/reports/cross-review-v2-token-streaming-smoke-2026-04-30.md +119 -0
  122. package/package.json +88 -0
@@ -0,0 +1,375 @@
1
+ import { statusInstruction, statusJsonSchema } from "../core/status.js";
2
+ import { BasePeerAdapter, StreamBuffer } from "./base.js";
3
+ import { classifyProviderError } from "./errors.js";
4
+ import { loadOpenAICtor } from "./openai.js";
5
+ import { withRetry } from "./retry.js";
6
+ import { userPrompt } from "./text.js";
7
+ const PERPLEXITY_BASE_URL = "https://api.perplexity.ai";
8
+ function usageFromSonar(usage, searchPerformed) {
9
+ if (!usage)
10
+ return undefined;
11
+ const result = {
12
+ input_tokens: usage.prompt_tokens,
13
+ output_tokens: usage.completion_tokens,
14
+ total_tokens: usage.total_tokens,
15
+ reasoning_tokens: usage.reasoning_tokens,
16
+ };
17
+ // Perplexity does NOT document a prompt-cache surface in the public
18
+ // Sonar API. Surface this explicitly so the cost layer + dashboard
19
+ // never silently treat the absence as a hit.
20
+ result.cache_provider_mode = "not_supported";
21
+ // v3.0.0: Sonar-specific categories surfaced so the cost layer can
22
+ // compute citation_tokens_cost + search_queries_cost (deep-research
23
+ // models). Absent on non-deep-research models.
24
+ if (typeof usage.citation_tokens === "number") {
25
+ result.citation_tokens = usage.citation_tokens;
26
+ }
27
+ if (typeof usage.num_search_queries === "number") {
28
+ result.num_search_queries = usage.num_search_queries;
29
+ }
30
+ // v3.0.0 R1 fix (codex cross-review catch 2026-05-12): per-call
31
+ // signal that the cost layer needs to correctly attribute the
32
+ // request fee. Relator (generate) calls force disable_search:true
33
+ // on the wire regardless of operator config — without this signal,
34
+ // estimateCost() would charge a request fee for searches that did
35
+ // not actually run.
36
+ result.search_performed = searchPerformed;
37
+ // v3.0.0: capture provider-reported total cost for telemetry. The
38
+ // config-driven cost.ts estimateCost remains authoritative; this is
39
+ // a sanity-check signal only.
40
+ if (typeof usage.cost?.total_cost === "number") {
41
+ result.provider_reported_total_cost_usd = usage.cost.total_cost;
42
+ }
43
+ return result;
44
+ }
45
+ // Extract plain text from a Sonar non-streamed response. Tolerant of
46
+ // soft-format outputs because, per #2 above, the search component may
47
+ // not strictly honor the requested JSON schema. Callers downstream
48
+ // (resultFromText -> status.ts decisionQualityFromStatus) classify the
49
+ // quality of the parsed response.
50
+ //
51
+ // v3.2.0 fix (codex catch sess 41244a1c, observed across v3.0.0+):
52
+ // sonar-reasoning-pro and sonar-deep-research models always emit a
53
+ // `<think>...</think>` reasoning preamble before the actual structured
54
+ // answer. The shared status parser in `core/status.ts` requires the
55
+ // text to begin with JSON-shaped content (or contain it within
56
+ // extractable shape); the thinking block breaks both code paths and
57
+ // the format-recovery retry inherits the same problem. Strip every
58
+ // `<think>...</think>` block (greedy across lines, multiple
59
+ // occurrences) before downstream extraction. Real Sonar responses
60
+ // never legitimately include the literal substring "<think>" inside
61
+ // the structured payload, so this is safe.
62
+ const PERPLEXITY_THINKING_BLOCK = /<think\b[^>]*>[\s\S]*?<\/think>/gi;
63
+ export function stripPerplexityThinkingBlock(raw) {
64
+ return raw.replace(PERPLEXITY_THINKING_BLOCK, "").trim();
65
+ }
66
+ function sonarText(response) {
67
+ const raw = response.choices?.[0]?.message?.content?.trim() || JSON.stringify(response);
68
+ return stripPerplexityThinkingBlock(raw);
69
+ }
70
+ export function clampEffortForPerplexity(effort) {
71
+ switch (effort) {
72
+ case "none":
73
+ case "minimal":
74
+ return "minimal";
75
+ case "low":
76
+ return "low";
77
+ case "medium":
78
+ return "medium";
79
+ case "high":
80
+ case "xhigh":
81
+ case "max":
82
+ case undefined:
83
+ default:
84
+ return "high";
85
+ }
86
+ }
87
+ // v3.0.0: Sonar models that accept the `reasoning_effort` body field.
88
+ // Per docs, only `sonar-reasoning-pro` and `sonar-deep-research`
89
+ // recognize it; `sonar` and `sonar-pro` ignore the field (no chain-
90
+ // of-thought stage). Exported for smoke verification.
91
+ export const PERPLEXITY_REASONING_EFFORT_MODELS = new Set([
92
+ "sonar-reasoning-pro",
93
+ "sonar-deep-research",
94
+ ]);
95
+ export function perplexityAcceptsReasoningEffort(model) {
96
+ return PERPLEXITY_REASONING_EFFORT_MODELS.has(model);
97
+ }
98
+ function buildSonarOptions(config, model, role, effortOverride) {
99
+ const opts = {
100
+ web_search_options: { search_context_size: config.perplexity.search_context_size },
101
+ };
102
+ // Relator (generate) role: search is structurally inappropriate
103
+ // because the task is to synthesize a revised draft from the other
104
+ // peers' verdicts, not to consult external sources. Force-off
105
+ // regardless of operator config.
106
+ // Reviewer (call) role: search active per config (default true; can
107
+ // be disabled via CROSS_REVIEW_PERPLEXITY_DISABLE_SEARCH=true).
108
+ if (role === "relator" || config.perplexity.disable_search) {
109
+ opts.disable_search = true;
110
+ }
111
+ if (perplexityAcceptsReasoningEffort(model)) {
112
+ opts.reasoning_effort = clampEffortForPerplexity(effortOverride ?? config.reasoning_effort.perplexity);
113
+ }
114
+ return opts;
115
+ }
116
+ export class PerplexityAdapter extends BasePeerAdapter {
117
+ id = "perplexity";
118
+ provider = "perplexity";
119
+ model;
120
+ constructor(config, modelOverride) {
121
+ super(config);
122
+ this.model = modelOverride ?? config.models.perplexity;
123
+ }
124
+ // Per v2.27.1 cold-start hardening: reuse the lazy OpenAI SDK ctor
125
+ // shared with peers/openai.ts + peers/deepseek.ts + peers/grok.ts so
126
+ // the `openai` module is loaded exactly once across all four
127
+ // OpenAI-SDK-driven adapters.
128
+ async client() {
129
+ const apiKey = this.config.api_keys.perplexity;
130
+ if (!apiKey)
131
+ throw new Error("PERPLEXITY_API_KEY was not found in environment variables.");
132
+ const Ctor = await loadOpenAICtor();
133
+ return new Ctor({ apiKey, baseURL: PERPLEXITY_BASE_URL });
134
+ }
135
+ async probe() {
136
+ const started = Date.now();
137
+ const authPresent = Boolean(this.config.api_keys.perplexity);
138
+ if (!authPresent) {
139
+ return {
140
+ peer: this.id,
141
+ provider: this.provider,
142
+ model: this.model,
143
+ available: false,
144
+ auth_present: false,
145
+ latency_ms: Date.now() - started,
146
+ model_selection: this.config.model_selection.perplexity,
147
+ message: "PERPLEXITY_API_KEY is missing.",
148
+ };
149
+ }
150
+ // Perplexity does not document a public `models.list` endpoint via
151
+ // the OpenAI-SDK base path. Probe with a minimal `disable_search`
152
+ // call to avoid burning a request fee on the health check; payload
153
+ // is single-token so token cost is negligible.
154
+ try {
155
+ const probeClient = await this.client();
156
+ await probeClient.chat.completions.create({
157
+ model: this.model,
158
+ messages: [{ role: "user", content: "probe" }],
159
+ max_tokens: 1,
160
+ disable_search: true,
161
+ }, { timeout: this.config.retry.timeout_ms });
162
+ return {
163
+ peer: this.id,
164
+ provider: this.provider,
165
+ model: this.model,
166
+ available: true,
167
+ auth_present: true,
168
+ latency_ms: Date.now() - started,
169
+ model_selection: this.config.model_selection.perplexity,
170
+ };
171
+ }
172
+ catch (error) {
173
+ const failure = classifyProviderError(this.id, this.provider, this.model, error, 1, started);
174
+ return {
175
+ peer: this.id,
176
+ provider: this.provider,
177
+ model: this.model,
178
+ available: false,
179
+ auth_present: true,
180
+ latency_ms: Date.now() - started,
181
+ model_selection: this.config.model_selection.perplexity,
182
+ message: failure.message,
183
+ };
184
+ }
185
+ }
186
+ async call(prompt, context) {
187
+ const started = Date.now();
188
+ return withRetry(this.config, async (attempt) => {
189
+ context.emit({
190
+ type: "peer.call.started",
191
+ session_id: context.session_id,
192
+ round: context.round,
193
+ peer: this.id,
194
+ message: `Perplexity review attempt ${attempt}`,
195
+ });
196
+ const sonarOptions = buildSonarOptions(this.config, this.model, "reviewer", context.reasoning_effort_override);
197
+ // v3.0.0 R1 fix (codex catch): the reviewer role HONORS config;
198
+ // disable_search is only set on the wire when config explicitly
199
+ // turns it off. Derive search_performed from the actual on-wire
200
+ // option so the cost layer charges request fee iff a search
201
+ // really ran.
202
+ const searchPerformed = sonarOptions.disable_search !== true;
203
+ const payload = {
204
+ ...sonarOptions,
205
+ model: this.model,
206
+ messages: [
207
+ { role: "system", content: this.systemPrompt(context) },
208
+ { role: "user", content: `${userPrompt(prompt)}\n\n${statusInstruction()}` },
209
+ ],
210
+ // Perplexity supports the OpenAI structured-output shape, but
211
+ // the docs warn the FIRST request with a new schema can
212
+ // incur 10-30s latency. Because the same statusJsonSchema is
213
+ // reused across every cross-review call, that one-time cost
214
+ // is amortized for the operator. Schema `name` is required
215
+ // (1-64 alphanumeric chars).
216
+ response_format: {
217
+ type: "json_schema",
218
+ json_schema: { name: "cross_review_status", schema: statusJsonSchema },
219
+ },
220
+ max_tokens: this.config.max_output_tokens,
221
+ };
222
+ if (this.shouldStreamTokens(context)) {
223
+ const streamPayload = {
224
+ ...payload,
225
+ stream: true,
226
+ stream_options: { include_usage: true },
227
+ };
228
+ const reviewClient = await this.client();
229
+ const stream = await reviewClient.chat.completions.create(streamPayload, {
230
+ signal: context.signal,
231
+ timeout: this.config.retry.timeout_ms,
232
+ });
233
+ const stream_buffer = new StreamBuffer(this.id);
234
+ const tokenStream = this.createTokenEventBuffer(context, "review", "chat.completion.chunk.delta");
235
+ let usage;
236
+ let modelReported;
237
+ let chunks = 0;
238
+ for await (const chunk of stream) {
239
+ chunks += 1;
240
+ modelReported = chunk.model ?? modelReported;
241
+ usage =
242
+ usageFromSonar(chunk.usage, searchPerformed) ??
243
+ usage;
244
+ for (const choice of chunk.choices ?? []) {
245
+ const delta = choice.delta?.content ?? "";
246
+ stream_buffer.append(delta);
247
+ tokenStream.append(delta);
248
+ }
249
+ }
250
+ // v3.4.0 Fix #1: apply stripPerplexityThinkingBlock to the
251
+ // streamed text. Non-streaming path at line ~426 uses
252
+ // sonarText(response) which already strips; streaming path was
253
+ // bypassing the strip entirely, causing <think> preambles from
254
+ // sonar-reasoning-pro to reach the status parser and fail with
255
+ // unparseable_after_recovery despite valid trailing JSON.
256
+ // Forensic evidence: sess f9a19401 (v3.3.0 self-investigation)
257
+ // — 4 peers converged READY on this exact diagnosis. Affected
258
+ // sessions: f72e597a, 99d46a2b, 00d92cce, 59776026, 41244a1c,
259
+ // e23d6920. Perplexity ready_rate was 0.28125 vs ~1.0 for
260
+ // other peers; this restores parity at the streaming path.
261
+ const text = stripPerplexityThinkingBlock(stream_buffer.text());
262
+ tokenStream.complete(text.length);
263
+ return this.resultFromText({
264
+ text,
265
+ raw: { streamed: true, provider: this.provider, chunks, model: modelReported },
266
+ usage,
267
+ started,
268
+ attempts: attempt,
269
+ modelReported,
270
+ });
271
+ }
272
+ const reviewClient = await this.client();
273
+ const response = await reviewClient.chat.completions.create(payload, {
274
+ signal: context.signal,
275
+ timeout: this.config.retry.timeout_ms,
276
+ });
277
+ return this.resultFromText({
278
+ text: sonarText(response),
279
+ raw: response,
280
+ usage: usageFromSonar(response.usage, searchPerformed),
281
+ started,
282
+ attempts: attempt,
283
+ modelReported: response.model,
284
+ });
285
+ }, (error, attempt) => classifyProviderError(this.id, this.provider, this.model, error, attempt, started));
286
+ }
287
+ async generate(prompt, context) {
288
+ const started = Date.now();
289
+ return withRetry(this.config, async (attempt) => {
290
+ context.emit({
291
+ type: "peer.generate.started",
292
+ session_id: context.session_id,
293
+ round: context.round,
294
+ peer: this.id,
295
+ message: `Perplexity generation attempt ${attempt}`,
296
+ });
297
+ const sonarOptions = buildSonarOptions(this.config, this.model, "relator", context.reasoning_effort_override);
298
+ // v3.0.0 R1 fix (codex catch): the relator role ALWAYS forces
299
+ // disable_search:true on the wire (synthesis task, not external
300
+ // lookup). search_performed is unconditionally false so the
301
+ // cost layer's request-fee accounting does not charge for a
302
+ // search that did not run.
303
+ const searchPerformed = sonarOptions.disable_search !== true;
304
+ const payload = {
305
+ ...sonarOptions,
306
+ model: this.model,
307
+ messages: [
308
+ { role: "system", content: this.systemPrompt(context) },
309
+ { role: "user", content: userPrompt(prompt) },
310
+ ],
311
+ max_tokens: this.config.max_output_tokens,
312
+ };
313
+ if (this.shouldStreamTokens(context)) {
314
+ const streamPayload = {
315
+ ...payload,
316
+ stream: true,
317
+ stream_options: { include_usage: true },
318
+ };
319
+ const generateClient = await this.client();
320
+ const stream = await generateClient.chat.completions.create(streamPayload, {
321
+ signal: context.signal,
322
+ timeout: this.config.retry.timeout_ms,
323
+ });
324
+ const stream_buffer = new StreamBuffer(this.id);
325
+ const tokenStream = this.createTokenEventBuffer(context, "generation", "chat.completion.chunk.delta");
326
+ let usage;
327
+ let modelReported;
328
+ let chunks = 0;
329
+ for await (const chunk of stream) {
330
+ chunks += 1;
331
+ modelReported = chunk.model ?? modelReported;
332
+ usage =
333
+ usageFromSonar(chunk.usage, searchPerformed) ??
334
+ usage;
335
+ for (const choice of chunk.choices ?? []) {
336
+ const delta = choice.delta?.content ?? "";
337
+ stream_buffer.append(delta);
338
+ tokenStream.append(delta);
339
+ }
340
+ }
341
+ // v3.4.0 Fix #1: streaming-path strip parity for generation
342
+ // (relator) path — same root cause as the call() branch above.
343
+ // When Perplexity is sortead as relator (e.g. sess 51973fac),
344
+ // the streamed `<think>` block reached round-N-draft.md
345
+ // verbatim and confused downstream reviewers into reviewing
346
+ // the think reasoning itself. Strip at the streaming boundary
347
+ // so the relator artifact is clean before persistence.
348
+ const text = stripPerplexityThinkingBlock(stream_buffer.text());
349
+ tokenStream.complete(text.length);
350
+ return this.generationFromText({
351
+ text,
352
+ raw: { streamed: true, provider: this.provider, chunks, model: modelReported },
353
+ usage,
354
+ started,
355
+ attempts: attempt,
356
+ modelReported,
357
+ });
358
+ }
359
+ const generateClient = await this.client();
360
+ const response = await generateClient.chat.completions.create(payload, {
361
+ signal: context.signal,
362
+ timeout: this.config.retry.timeout_ms,
363
+ });
364
+ return this.generationFromText({
365
+ text: sonarText(response),
366
+ raw: response,
367
+ usage: usageFromSonar(response.usage, searchPerformed),
368
+ started,
369
+ attempts: attempt,
370
+ modelReported: response.model,
371
+ });
372
+ }, (error, attempt) => classifyProviderError(this.id, this.provider, this.model, error, attempt, started));
373
+ }
374
+ }
375
+ //# sourceMappingURL=perplexity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perplexity.js","sourceRoot":"","sources":["../../../src/peers/perplexity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { AppConfig, PeerAdapter, PeerId } from "../core/types.js";
2
+ export declare function createAdapters(config: AppConfig, modelOverrides?: Partial<Record<PeerId, string>>): Record<PeerId, PeerAdapter>;
3
+ export declare function selectAdapters(adapters: Record<PeerId, PeerAdapter>, peers?: PeerId[]): PeerAdapter[];
@@ -0,0 +1,77 @@
1
+ import { PEERS } from "../core/types.js";
2
+ import { AnthropicAdapter } from "./anthropic.js";
3
+ import { DeepSeekAdapter } from "./deepseek.js";
4
+ import { GeminiAdapter } from "./gemini.js";
5
+ import { GrokAdapter } from "./grok.js";
6
+ import { OpenAIAdapter } from "./openai.js";
7
+ import { PerplexityAdapter } from "./perplexity.js";
8
+ import { StubAdapter } from "./stub.js";
9
+ // v2.4.0 / audit closure (P1.1) — refined after cross-review R1 (gemini
10
+ // caught a financial-safety regression in the initial fallback design).
11
+ //
12
+ // Pre-v2.4.0 a single env var (CROSS_REVIEW_STUB=1) replaced every
13
+ // real provider adapter with a stub that returned synthetic READY
14
+ // verdicts at $0 cost — so a stray dotenv or CI variable could silently
15
+ // invalidate a cross-review used as a pre-commit gate.
16
+ //
17
+ // Initial v2.4.0 attempt: when the flag was set without confirmation, the
18
+ // boot path emitted a notice and FELL BACK to real adapters. R1 (gemini)
19
+ // caught the financial-safety regression: an operator who deliberately
20
+ // set CROSS_REVIEW_STUB=1 to avoid paid calls (local dev, CI offline,
21
+ // budget kill) would now BE BILLED for real provider calls instead. The
22
+ // silent fallback violates explicit operator intent.
23
+ //
24
+ // Final v2.4.0 contract: the flag and the confirmation are paired
25
+ // — set both together or neither. If the flag is set without
26
+ // confirmation we FAIL FAST with a clear error so the operator must
27
+ // either (a) opt in deliberately to stubs by adding the confirmation,
28
+ // or (b) unset the stub flag if real adapters are intended. This
29
+ // preserves the original financial safety net that flag-only operators
30
+ // were depending on without re-introducing the silent-stub-in-prod risk.
31
+ function stubsAreSafelyEnabled(config) {
32
+ if (!config.stub)
33
+ return false;
34
+ const confirmed = process.env.NODE_ENV === "test" ||
35
+ /^(1|true|yes|on)$/i.test(process.env.CROSS_REVIEW_STUB_CONFIRMED ?? "");
36
+ if (!confirmed) {
37
+ throw new Error("CROSS_REVIEW_STUB=1 is set but stub activation is NOT confirmed. " +
38
+ "Stubs would invalidate real cross-review decisions; falling back to real adapters " +
39
+ "would charge for paid provider calls against your explicit STUB intent. " +
40
+ "To deliberately enable stubs, also set NODE_ENV=test OR " +
41
+ "CROSS_REVIEW_STUB_CONFIRMED=1 in the same environment. " +
42
+ "To deliberately use real adapters, unset CROSS_REVIEW_STUB.");
43
+ }
44
+ process.stderr.write("[cross-review] notice: stub adapters ACTIVE — every peer call returns synthetic data. " +
45
+ "Do NOT use this configuration to gate real cross-review decisions.\n");
46
+ return true;
47
+ }
48
+ export function createAdapters(config, modelOverrides = {}) {
49
+ if (stubsAreSafelyEnabled(config)) {
50
+ return {
51
+ codex: new StubAdapter(config, "codex", modelOverrides.codex),
52
+ claude: new StubAdapter(config, "claude", modelOverrides.claude),
53
+ gemini: new StubAdapter(config, "gemini", modelOverrides.gemini),
54
+ deepseek: new StubAdapter(config, "deepseek", modelOverrides.deepseek),
55
+ // v2.14.0: Grok stub for offline / CI / budget-kill smoke runs.
56
+ grok: new StubAdapter(config, "grok", modelOverrides.grok),
57
+ // v3.0.0: Perplexity stub for offline / CI / budget-kill smoke runs.
58
+ perplexity: new StubAdapter(config, "perplexity", modelOverrides.perplexity),
59
+ };
60
+ }
61
+ return {
62
+ codex: new OpenAIAdapter(config, modelOverrides.codex),
63
+ claude: new AnthropicAdapter(config, modelOverrides.claude),
64
+ gemini: new GeminiAdapter(config, modelOverrides.gemini),
65
+ deepseek: new DeepSeekAdapter(config, modelOverrides.deepseek),
66
+ // v2.14.0: Grok via xAI's OpenAI-Responses-API surface.
67
+ grok: new GrokAdapter(config, modelOverrides.grok),
68
+ // v3.0.0: Perplexity via Sonar API at https://api.perplexity.ai
69
+ // (OpenAI-Chat-Completions compatible; uses the shared
70
+ // loadOpenAICtor helper from peers/openai.ts).
71
+ perplexity: new PerplexityAdapter(config, modelOverrides.perplexity),
72
+ };
73
+ }
74
+ export function selectAdapters(adapters, peers = [...PEERS]) {
75
+ return peers.map((peer) => adapters[peer]);
76
+ }
77
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/peers/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { AppConfig, PeerFailure } from "../core/types.js";
2
+ export declare function withRetry<T>(config: AppConfig, run: (attempt: number) => Promise<T>, onFailure: (error: unknown, attempt: number, started: number) => PeerFailure): Promise<T>;
@@ -0,0 +1,36 @@
1
+ function delay(ms) {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ }
4
+ // v2.4.0 / audit closure (P2.6): full jitter on the exponential backoff.
5
+ // Without jitter, multiple peers hitting the same provider rate-limit
6
+ // synchronize their retries (10ms, 20ms, 40ms... in lockstep) and produce
7
+ // thundering-herd that prolongs the rate limit instead of relieving it.
8
+ // Full jitter (random in [0, capped]) is the AWS-recommended pattern and
9
+ // is appropriate here because the cap (`config.retry.max_delay_ms`)
10
+ // already bounds tail latency. When the provider returns an explicit
11
+ // `retry_after_ms` (P2.7 wires this), we respect it as-is — that value
12
+ // is server-authoritative and adding jitter on top would only delay
13
+ // recovery further.
14
+ function backoffWithJitter(attempt, config) {
15
+ const exponential = config.retry.base_delay_ms * 2 ** (attempt - 1);
16
+ const capped = Math.min(config.retry.max_delay_ms, exponential);
17
+ return Math.floor(Math.random() * capped);
18
+ }
19
+ export async function withRetry(config, run, onFailure) {
20
+ const started = Date.now();
21
+ let last = null;
22
+ for (let attempt = 1; attempt <= config.retry.max_attempts; attempt++) {
23
+ try {
24
+ return await run(attempt);
25
+ }
26
+ catch (error) {
27
+ last = onFailure(error, attempt, started);
28
+ if (!last.retryable || attempt >= config.retry.max_attempts)
29
+ throw error;
30
+ const wait = last.retry_after_ms ?? backoffWithJitter(attempt, config);
31
+ await delay(wait);
32
+ }
33
+ }
34
+ throw new Error(last?.message ?? "retry loop exhausted");
35
+ }
36
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../../src/peers/retry.ts"],"names":[],"mappings":"AAEA,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,yEAAyE;AACzE,sEAAsE;AACtE,0EAA0E;AAC1E,wEAAwE;AACxE,yEAAyE;AACzE,oEAAoE;AACpE,qEAAqE;AACrE,uEAAuE;AACvE,oEAAoE;AACpE,oBAAoB;AACpB,SAAS,iBAAiB,CAAC,OAAe,EAAE,MAAiB;IAC3D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,MAAiB,EACjB,GAAoC,EACpC,SAA4E;IAE5E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,IAAI,IAAI,GAAuB,IAAI,CAAC;IACpC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;QACtE,IAAI,CAAC;YACH,OAAO,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAC1C,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,YAAY;gBAAE,MAAM,KAAK,CAAC;YACzE,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,IAAI,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACvE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,IAAI,EAAE,OAAO,IAAI,sBAAsB,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { AppConfig, EvidenceAskJudgment, GenerationResult, PeerAdapter, PeerCallContext, PeerId, PeerProbeResult, PeerResult } from "../core/types.js";
2
+ import { BasePeerAdapter } from "./base.js";
3
+ export declare class StubAdapter extends BasePeerAdapter implements PeerAdapter {
4
+ readonly id: PeerId;
5
+ provider: string;
6
+ model: string;
7
+ constructor(config: AppConfig, id: PeerId, modelOverride?: string);
8
+ private streamStubText;
9
+ probe(): Promise<PeerProbeResult>;
10
+ call(prompt: string, context: PeerCallContext): Promise<PeerResult>;
11
+ generate(prompt: string, context: PeerCallContext): Promise<GenerationResult>;
12
+ judgeEvidenceAsk(ask: string, draft: string, context: PeerCallContext): Promise<EvidenceAskJudgment>;
13
+ }