scoutline 0.7.0 → 0.9.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 (82) hide show
  1. package/README.md +11 -3
  2. package/dist/capabilities/quota.d.ts +11 -0
  3. package/dist/capabilities/quota.d.ts.map +1 -1
  4. package/dist/capabilities/quota.js.map +1 -1
  5. package/dist/capabilities/search.d.ts +11 -1
  6. package/dist/capabilities/search.d.ts.map +1 -1
  7. package/dist/commands/crawl.js +1 -1
  8. package/dist/commands/doctor.d.ts.map +1 -1
  9. package/dist/commands/doctor.js +13 -10
  10. package/dist/commands/doctor.js.map +1 -1
  11. package/dist/commands/map.js +1 -1
  12. package/dist/commands/quota.d.ts +23 -0
  13. package/dist/commands/quota.d.ts.map +1 -1
  14. package/dist/commands/quota.js +21 -4
  15. package/dist/commands/quota.js.map +1 -1
  16. package/dist/commands/read.js +1 -1
  17. package/dist/commands/repo.js +1 -1
  18. package/dist/commands/research.js +1 -1
  19. package/dist/commands/search.d.ts +2 -1
  20. package/dist/commands/search.d.ts.map +1 -1
  21. package/dist/commands/search.js +21 -12
  22. package/dist/commands/search.js.map +1 -1
  23. package/dist/index.d.ts +7 -0
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +35 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/redact.d.ts +2 -2
  28. package/dist/lib/redact.d.ts.map +1 -1
  29. package/dist/lib/redact.js +8 -2
  30. package/dist/lib/redact.js.map +1 -1
  31. package/dist/providers/brave/adapter.d.ts +42 -0
  32. package/dist/providers/brave/adapter.d.ts.map +1 -0
  33. package/dist/providers/brave/adapter.js +504 -0
  34. package/dist/providers/brave/adapter.js.map +1 -0
  35. package/dist/providers/brave/client.d.ts +161 -0
  36. package/dist/providers/brave/client.d.ts.map +1 -0
  37. package/dist/providers/brave/client.js +297 -0
  38. package/dist/providers/brave/client.js.map +1 -0
  39. package/dist/providers/brave/credentials.d.ts +33 -0
  40. package/dist/providers/brave/credentials.d.ts.map +1 -0
  41. package/dist/providers/brave/credentials.js +55 -0
  42. package/dist/providers/brave/credentials.js.map +1 -0
  43. package/dist/providers/brave/diagnostics.d.ts +46 -0
  44. package/dist/providers/brave/diagnostics.d.ts.map +1 -0
  45. package/dist/providers/brave/diagnostics.js +76 -0
  46. package/dist/providers/brave/diagnostics.js.map +1 -0
  47. package/dist/providers/brave/quota.d.ts +86 -0
  48. package/dist/providers/brave/quota.d.ts.map +1 -0
  49. package/dist/providers/brave/quota.js +247 -0
  50. package/dist/providers/brave/quota.js.map +1 -0
  51. package/dist/providers/exa/adapter.d.ts +58 -0
  52. package/dist/providers/exa/adapter.d.ts.map +1 -0
  53. package/dist/providers/exa/adapter.js +892 -0
  54. package/dist/providers/exa/adapter.js.map +1 -0
  55. package/dist/providers/exa/client.d.ts +143 -0
  56. package/dist/providers/exa/client.d.ts.map +1 -0
  57. package/dist/providers/exa/client.js +328 -0
  58. package/dist/providers/exa/client.js.map +1 -0
  59. package/dist/providers/exa/credentials.d.ts +34 -0
  60. package/dist/providers/exa/credentials.d.ts.map +1 -0
  61. package/dist/providers/exa/credentials.js +56 -0
  62. package/dist/providers/exa/credentials.js.map +1 -0
  63. package/dist/providers/exa/diagnostics.d.ts +42 -0
  64. package/dist/providers/exa/diagnostics.d.ts.map +1 -0
  65. package/dist/providers/exa/diagnostics.js +69 -0
  66. package/dist/providers/exa/diagnostics.js.map +1 -0
  67. package/dist/providers/minimax/adapter.js +1 -1
  68. package/dist/providers/minimax/adapter.js.map +1 -1
  69. package/dist/providers/registry.d.ts.map +1 -1
  70. package/dist/providers/registry.js +4 -0
  71. package/dist/providers/registry.js.map +1 -1
  72. package/dist/providers/tavily/adapter.d.ts.map +1 -1
  73. package/dist/providers/tavily/adapter.js +5 -0
  74. package/dist/providers/tavily/adapter.js.map +1 -1
  75. package/dist/providers/types.d.ts +1 -1
  76. package/dist/providers/types.d.ts.map +1 -1
  77. package/dist/providers/types.js +1 -1
  78. package/dist/providers/types.js.map +1 -1
  79. package/dist/providers/zai/adapter.d.ts.map +1 -1
  80. package/dist/providers/zai/adapter.js +7 -1
  81. package/dist/providers/zai/adapter.js.map +1 -1
  82. package/package.json +1 -1
@@ -0,0 +1,504 @@
1
+ /**
2
+ * Brave Provider Adapter (brave-tech-plan §2, §5, §6).
3
+ *
4
+ * T2 wires the Search Capability (web + news). The descriptor
5
+ * advertises `"search"` and `create()` returns an Adapter whose
6
+ * `search` Capability owns credentials, transport, Provider field
7
+ * mapping, and failure normalization. Credentials, the direct-HTTP GET
8
+ * transport, and the header-bearing fetch seam come from T1; later
9
+ * tickets widen the capability set (reader, etc.). T5 wires the
10
+ * Diagnostics Capability (one-query doctor probe); T6 wires the Quota
11
+ * Capability (1-query rate-limit-header probe with a spend caveat).
12
+ *
13
+ * Boundary rules (ARCHITECTURE.md §2):
14
+ * - May import capability types, normalized errors, Provider identity
15
+ * types, and the Adapter-local credential and transport Modules.
16
+ * - Must NOT import command presentation, output mode, or another
17
+ * Provider's Adapter.
18
+ */
19
+ import crypto from "node:crypto";
20
+ import { ApiError, AuthError, ConfigurationError, NetworkError, QuotaError, TimeoutError, UnsupportedOptionError, ValidationError, } from "../../lib/errors.js";
21
+ import { applySearchTopic } from "../../lib/search-topic.js";
22
+ import { requireBraveApiKey, isBraveConfigured } from "./credentials.js";
23
+ import { fetchBraveSearch, fetchBraveNewsSearch, fetchBraveVideoSearch, fetchBraveLlmContext, } from "./client.js";
24
+ import { createBraveDiagnosticsCapability } from "./diagnostics.js";
25
+ import { createBraveQuotaCapability } from "./quota.js";
26
+ // ---------------------------------------------------------------------------
27
+ // Provider-owned credential fingerprint
28
+ // ---------------------------------------------------------------------------
29
+ function credentialFingerprint(apiKey) {
30
+ return crypto.createHash("sha256").update(apiKey).digest("hex");
31
+ }
32
+ function resolveApiKey(env) {
33
+ return requireBraveApiKey(env);
34
+ }
35
+ // ---------------------------------------------------------------------------
36
+ // Helpers
37
+ // ---------------------------------------------------------------------------
38
+ function isPlainObject(value) {
39
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40
+ }
41
+ // ---------------------------------------------------------------------------
42
+ // Validation (FR-012): reject unsupported controls before any API access
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Controls the Brave Search Adapter does NOT accept as individuals.
46
+ * Every control (`domain`/`recency`/`location`/`topic`/`type`/
47
+ * `contentSize`) is now honored here — `contentSize:"high"` routes to
48
+ * the LLM Context endpoint (T4), and `medium`/default is a no-op depth
49
+ * on the web path. Brave therefore has NO per-control reject-list.
50
+ *
51
+ * The one Brave-specific constraint is a COMBINATION — `type:"video"`
52
+ * has no depth mode, so `type:"video"` + `contentSize` is incompatible.
53
+ * That is enforced separately as a combination guard in {@link validate}
54
+ * (it fires BEFORE dispatch, naming `contentSize` as the offending
55
+ * option, since `contentSize` is meaningful in general but not on the
56
+ * video path).
57
+ */
58
+ const UNSUPPORTED_CONTROLS = [];
59
+ function assertNoUnsupportedControls(request) {
60
+ const controls = request.controls;
61
+ if (!controls)
62
+ return;
63
+ for (const key of UNSUPPORTED_CONTROLS) {
64
+ if (controls[key] !== undefined) {
65
+ throw new UnsupportedOptionError("brave", "search", key);
66
+ }
67
+ }
68
+ }
69
+ /**
70
+ * Brave-specific combination guards for the `type:"video"` path. Video
71
+ * results have no depth mode and no editorial topic axis, so
72
+ * `type:"video"` combined with `contentSize` OR `topic` is rejected
73
+ * BEFORE dispatch. Each error names the incompatible option
74
+ * (`contentSize` / `topic`) — both are individually accepted elsewhere.
75
+ * The `type`×`topic` rule mirrors the CLI parse-time gate so the
76
+ * adapter contract holds for programmatic callers too, not just the CLI.
77
+ */
78
+ function assertNoVideoCombinations(request) {
79
+ const controls = request.controls;
80
+ if (controls?.type !== "video")
81
+ return;
82
+ if (controls.contentSize !== undefined) {
83
+ throw new UnsupportedOptionError("brave", "search", "contentSize");
84
+ }
85
+ if (controls.topic !== undefined) {
86
+ throw new UnsupportedOptionError("brave", "search", "topic");
87
+ }
88
+ }
89
+ // ---------------------------------------------------------------------------
90
+ // Control mapping (SearchControls → Brave-native API params + query mutators)
91
+ // ---------------------------------------------------------------------------
92
+ function mapRecencyToFreshness(recency) {
93
+ switch (recency) {
94
+ case "oneDay":
95
+ return "pd";
96
+ case "oneWeek":
97
+ return "pw";
98
+ case "oneMonth":
99
+ return "pm";
100
+ case "oneYear":
101
+ return "py";
102
+ case "noLimit":
103
+ return undefined;
104
+ default:
105
+ return undefined;
106
+ }
107
+ }
108
+ /**
109
+ * Map the param-bearing controls into Brave-native API fields. Query-
110
+ * mutating controls (`domain`, `topic:"finance"`) are handled separately
111
+ * in `invoke` via {@link applyQueryMutators}; `topic:"news"` is an
112
+ * endpoint switch, not a param.
113
+ */
114
+ function mapSearchControls(controls) {
115
+ if (!controls)
116
+ return undefined;
117
+ const params = {};
118
+ if (controls.recency) {
119
+ const freshness = mapRecencyToFreshness(controls.recency);
120
+ if (freshness)
121
+ params.freshness = freshness;
122
+ }
123
+ if (controls.location) {
124
+ params.country = controls.location === "us" ? "US" : "CN";
125
+ }
126
+ if (params.country === undefined && params.freshness === undefined)
127
+ return undefined;
128
+ return params;
129
+ }
130
+ /**
131
+ * Apply the query-mutating controls to `query` BEFORE dispatch (not as
132
+ * API params). `domain` appends a `site:<domain>` operator (Brave has no
133
+ * dedicated domain param); `topic:"finance"` appends the finance keyword
134
+ * via the shared helper. `topic:"news"` is NOT a query mutation — it is
135
+ * an endpoint switch handled by the dispatcher.
136
+ *
137
+ * `suppressTopic` drops the `topic:"finance"` keyword appendage while
138
+ * keeping the `domain` operator. The LLM Context (`high`) path sets it:
139
+ * `high` overrides `topic` (it routes to LLM Context regardless of
140
+ * `--topic`), so the editorial topic keyword must NOT pollute the
141
+ * passage-extraction query. Domain is a filter and still applies on the
142
+ * high path, so it is preserved.
143
+ */
144
+ function applyQueryMutators(query, controls, suppressTopic = false) {
145
+ let effective = query;
146
+ if (controls?.domain) {
147
+ effective = `${effective} site:${controls.domain}`;
148
+ }
149
+ if (!suppressTopic && controls?.topic === "finance") {
150
+ effective = applySearchTopic(effective, "finance");
151
+ }
152
+ return effective;
153
+ }
154
+ // ---------------------------------------------------------------------------
155
+ // Response normalization
156
+ // ---------------------------------------------------------------------------
157
+ /**
158
+ * Normalize one Brave result entry into a `SearchSource`.
159
+ *
160
+ * title -> title
161
+ * url -> url
162
+ * description -> summary
163
+ * meta_url.netloc -> source (only when present and string)
164
+ * page_age ?? age -> date (only when present and string)
165
+ *
166
+ * A missing/non-string title/url/description is a malformed response.
167
+ */
168
+ function normalizeBraveResultEntry(entry) {
169
+ if (!isPlainObject(entry)) {
170
+ throw new ApiError("Brave search returned a malformed response", 500);
171
+ }
172
+ const title = entry.title;
173
+ const url = entry.url;
174
+ const description = entry.description;
175
+ if (typeof title !== "string" || typeof url !== "string" || typeof description !== "string") {
176
+ throw new ApiError("Brave search returned a malformed response", 500);
177
+ }
178
+ const source = { title, url, summary: description };
179
+ const metaUrl = entry.meta_url;
180
+ if (isPlainObject(metaUrl) && typeof metaUrl.netloc === "string") {
181
+ source.source = metaUrl.netloc;
182
+ }
183
+ let dateValue;
184
+ if (typeof entry.page_age === "string") {
185
+ dateValue = entry.page_age;
186
+ }
187
+ else if (typeof entry.age === "string") {
188
+ dateValue = entry.age;
189
+ }
190
+ if (dateValue !== undefined) {
191
+ source.date = dateValue;
192
+ }
193
+ return source;
194
+ }
195
+ /**
196
+ * Normalize a raw Brave WEB search response into `SearchSource[]`.
197
+ * Reads `raw.web.results[]`. Any malformed shape is a retryable
198
+ * `ApiError` 500.
199
+ */
200
+ function normalizeBraveWebResults(raw) {
201
+ if (!isPlainObject(raw)) {
202
+ throw new ApiError("Brave search returned a malformed response", 500);
203
+ }
204
+ const web = raw.web;
205
+ if (!isPlainObject(web)) {
206
+ throw new ApiError("Brave search returned a malformed response", 500);
207
+ }
208
+ const results = web.results;
209
+ if (!Array.isArray(results)) {
210
+ throw new ApiError("Brave search returned a malformed response", 500);
211
+ }
212
+ const out = [];
213
+ for (const entry of results) {
214
+ out.push(normalizeBraveResultEntry(entry));
215
+ }
216
+ return out;
217
+ }
218
+ /**
219
+ * Normalize a raw Brave NEWS or VIDEO search response into
220
+ * `SearchSource[]`. Both responses use the same top-level `raw.results[]`
221
+ * wrapper (NOT nested under `web`), so they share one normalizer.
222
+ * Brave-only video fields (`duration`/`views`/`creator`/`thumbnail`) are
223
+ * naturally DROPPED — the shared {@link normalizeBraveResultEntry} reads
224
+ * only `title`/`url`/`description`/`meta_url.netloc`/`page_age`/`age`
225
+ * (ADR-0001). Any malformed shape is a retryable `ApiError` 500.
226
+ */
227
+ function normalizeBraveTopLevelResults(raw) {
228
+ if (!isPlainObject(raw)) {
229
+ throw new ApiError("Brave search returned a malformed response", 500);
230
+ }
231
+ const results = raw.results;
232
+ if (!Array.isArray(results)) {
233
+ throw new ApiError("Brave search returned a malformed response", 500);
234
+ }
235
+ const out = [];
236
+ for (const entry of results) {
237
+ out.push(normalizeBraveResultEntry(entry));
238
+ }
239
+ return out;
240
+ }
241
+ /**
242
+ * Normalize a raw Brave LLM Context response into `SearchSource[]`.
243
+ * Reads `raw.grounding.generic[]`; each entry carries `title`/`url` and
244
+ * a `snippets` array of extracted passages. Passages are joined with a
245
+ * blank line into `summary`. LLM Context entries do NOT carry
246
+ * `meta_url.netloc` or `page_age`/`age` (the web/news/video shape), so
247
+ * `source`/`date` are not synthesized here. Any malformed shape is a
248
+ * retryable `ApiError` 500.
249
+ */
250
+ function normalizeBraveLlmContextResults(raw) {
251
+ if (!isPlainObject(raw)) {
252
+ throw new ApiError("Brave search returned a malformed response", 500);
253
+ }
254
+ const grounding = raw.grounding;
255
+ if (!isPlainObject(grounding)) {
256
+ throw new ApiError("Brave search returned a malformed response", 500);
257
+ }
258
+ const generic = grounding.generic;
259
+ if (!Array.isArray(generic)) {
260
+ throw new ApiError("Brave search returned a malformed response", 500);
261
+ }
262
+ const out = [];
263
+ for (const entry of generic) {
264
+ if (!isPlainObject(entry)) {
265
+ throw new ApiError("Brave search returned a malformed response", 500);
266
+ }
267
+ const title = entry.title;
268
+ const url = entry.url;
269
+ const snippets = entry.snippets;
270
+ if (typeof title !== "string" ||
271
+ typeof url !== "string" ||
272
+ !Array.isArray(snippets) ||
273
+ snippets.some((s) => typeof s !== "string")) {
274
+ throw new ApiError("Brave search returned a malformed response", 500);
275
+ }
276
+ out.push({ title, url, summary: snippets.join("\n\n") });
277
+ }
278
+ return out;
279
+ }
280
+ // ---------------------------------------------------------------------------
281
+ // Failure normalization: stable public codes, no raw payloads (NFR-006)
282
+ // ---------------------------------------------------------------------------
283
+ /**
284
+ * Resolve a stable HTTP-style status code for retry classification.
285
+ * Explicit terminal client errors (400, 404, 410, 422) map to their
286
+ * real codes; transient failures map to a representative status in the
287
+ * retryable set (429 or any 5xx 500..599 inclusive, per DESIGN.md §18 /
288
+ * FR-090). Unknown failures default to 500 (transient). When the caller
289
+ * already carries a numeric status (a typed ApiError), that status is
290
+ * honoured directly.
291
+ */
292
+ function inferStatusCode(lower, known) {
293
+ if (typeof known === "number" && Number.isFinite(known))
294
+ return known;
295
+ if (lower.includes("404") || lower.includes("not found"))
296
+ return 404;
297
+ if (lower.includes("400") || lower.includes("bad request"))
298
+ return 400;
299
+ if (lower.includes("410") || lower.includes("gone"))
300
+ return 410;
301
+ if (lower.includes("422") || lower.includes("unprocessable"))
302
+ return 422;
303
+ if (lower.includes("500") || lower.includes("internal"))
304
+ return 500;
305
+ if (lower.includes("502") || lower.includes("bad gateway"))
306
+ return 502;
307
+ if (lower.includes("503") || lower.includes("service unavailable"))
308
+ return 503;
309
+ if (lower.includes("504") || lower.includes("gateway timeout"))
310
+ return 504;
311
+ return 500;
312
+ }
313
+ /**
314
+ * Status-keyed outward message for rewrapped Brave ApiErrors. The rewrap
315
+ * does not echo upstream `error.message` — a future change embedding a
316
+ * raw Provider body in an ApiError message would leak through
317
+ * normalization, the cache, and stdout. Curated constants only.
318
+ */
319
+ function braveApiErrorMessage(statusCode) {
320
+ if (statusCode === 429)
321
+ return "Brave rate limit exceeded";
322
+ return "Brave request failed";
323
+ }
324
+ /**
325
+ * Normalize a Provider failure with sanitized messages. Raw response
326
+ * bodies never cross the adapter boundary. Same pattern as
327
+ * `normalizeTavilyError` / `normalizeMiniMaxError`.
328
+ */
329
+ function normalizeBraveError(error) {
330
+ // QuotaError pass-through — terminal retry guarantee preserved.
331
+ if (error instanceof QuotaError)
332
+ return error;
333
+ // Configuration/option/validation errors carry clean, human-authored
334
+ // messages and are safe to surface verbatim.
335
+ if (error instanceof ValidationError ||
336
+ error instanceof UnsupportedOptionError ||
337
+ error instanceof ConfigurationError) {
338
+ return error;
339
+ }
340
+ // Re-wrap typed transport errors with sanitized messages so a raw
341
+ // Provider response body embedded upstream never survives. Code +
342
+ // statusCode (retry signal) are preserved.
343
+ if (error instanceof AuthError) {
344
+ return new AuthError("Brave authentication failed", "BRAVE_SEARCH_API_KEY");
345
+ }
346
+ if (error instanceof NetworkError) {
347
+ return new NetworkError("Brave network error");
348
+ }
349
+ if (error instanceof TimeoutError) {
350
+ return new TimeoutError(error.durationMs, "Try again or increase timeout with BRAVE_TIMEOUT env var");
351
+ }
352
+ if (error instanceof ApiError) {
353
+ const statusCode = inferStatusCode("", error.statusCode);
354
+ return new ApiError(braveApiErrorMessage(statusCode), statusCode);
355
+ }
356
+ const message = error instanceof Error ? error.message : String(error);
357
+ const lower = message.toLowerCase();
358
+ if (lower.includes("401") ||
359
+ lower.includes("403") ||
360
+ lower.includes("unauthorized") ||
361
+ lower.includes("forbidden")) {
362
+ return new AuthError("Brave authentication failed");
363
+ }
364
+ if (lower.includes("timeout") || lower.includes("timed out") || lower.includes("etimedout")) {
365
+ // Fallback branch: the transport wraps real timeouts into a typed
366
+ // TimeoutError (which carries the configured duration) before they
367
+ // reach this point. This untyped-message heuristic is rarely hit, so
368
+ // a constant default is fine and keeps process.env out of the
369
+ // normalization path (test isolation).
370
+ return new TimeoutError(30000);
371
+ }
372
+ if (lower.includes("econnrefused") ||
373
+ lower.includes("econnreset") ||
374
+ lower.includes("network") ||
375
+ lower.includes("enotfound") ||
376
+ lower.includes("fetch failed")) {
377
+ return new NetworkError("Brave network error");
378
+ }
379
+ if (lower.includes("429") || lower.includes("rate limit")) {
380
+ return new ApiError("Brave rate limit exceeded", 429);
381
+ }
382
+ return new ApiError("Brave request failed", inferStatusCode(lower));
383
+ }
384
+ function createBraveSearchCapability(options) {
385
+ const { env, transport } = options;
386
+ const capability = {
387
+ validate(request) {
388
+ if (!request || typeof request.query !== "string" || request.query.trim() === "") {
389
+ throw new ValidationError("Search query must contain at least one non-whitespace character");
390
+ }
391
+ // Brave supports domain, recency, location, topic, and contentSize
392
+ // (contentSize:"high" → LLM Context in T4; medium/default is a
393
+ // no-op depth on the web path). type:"video" combined with
394
+ // contentSize or topic is rejected as incompatible before any
395
+ // transport call.
396
+ assertNoUnsupportedControls(request);
397
+ assertNoVideoCombinations(request);
398
+ },
399
+ cacheIdentity(request) {
400
+ const apiKey = resolveApiKey(env);
401
+ const identityRequest = {
402
+ query: request.query,
403
+ };
404
+ if (request.controls) {
405
+ identityRequest.controls = request.controls;
406
+ }
407
+ return {
408
+ provider: "brave",
409
+ capability: "search",
410
+ credentialFingerprint: credentialFingerprint(apiKey),
411
+ request: identityRequest,
412
+ // Brave never probes legacy keys — no legacyCandidates.
413
+ };
414
+ },
415
+ async invoke(request) {
416
+ // Validate before any credential access or transport call.
417
+ capability.validate(request);
418
+ const apiKey = resolveApiKey(env);
419
+ try {
420
+ // Dispatch precedence: video > high > news > web.
421
+ // - `video` (type:"video") stays the top branch (the
422
+ // type×contentSize combination is already rejected in
423
+ // validate, so `isVideo` and `isHigh` never co-occur).
424
+ // - `high` (contentSize:"high") routes to LLM Context and
425
+ // OVERRIDES `topic`: a `high + topic:news|finance` request
426
+ // goes to LLM Context, NOT news/keyword-append.
427
+ // - `news` (topic:"news") is the news endpoint switch.
428
+ // - everything else falls through to web search.
429
+ const isVideo = request.controls?.type === "video";
430
+ const isHigh = !isVideo && request.controls?.contentSize === "high";
431
+ const isNews = !isVideo && !isHigh && request.controls?.topic === "news";
432
+ // Query-mutating controls are applied to the query BEFORE
433
+ // dispatch; param-bearing controls (recency/location) are mapped
434
+ // separately. The high path MUST suppress the `topic:finance`
435
+ // keyword appendage (`high` overrides topic, so the editorial
436
+ // keyword must not pollute the passage-extraction query); the
437
+ // `domain` operator is a filter and still applies on every path.
438
+ const effectiveQuery = isHigh
439
+ ? applyQueryMutators(request.query, request.controls, true)
440
+ : applyQueryMutators(request.query, request.controls);
441
+ const params = mapSearchControls(request.controls);
442
+ // The high path forwards `params` (country/freshness) to LLM
443
+ // Context too, so a `high` search honors `--recency`/`--location`
444
+ // rather than silently dropping them (consistent with the other
445
+ // paths). See fetchBraveLlmContext for the live gate on whether
446
+ // LLM Context honors these.
447
+ const raw = isVideo
448
+ ? await fetchBraveVideoSearch(apiKey, effectiveQuery, params, transport)
449
+ : isHigh
450
+ ? await fetchBraveLlmContext(apiKey, effectiveQuery, params, transport)
451
+ : isNews
452
+ ? await fetchBraveNewsSearch(apiKey, effectiveQuery, params, transport)
453
+ : await fetchBraveSearch(apiKey, effectiveQuery, params, transport);
454
+ return isVideo
455
+ ? normalizeBraveTopLevelResults(raw)
456
+ : isHigh
457
+ ? normalizeBraveLlmContextResults(raw)
458
+ : isNews
459
+ ? normalizeBraveTopLevelResults(raw)
460
+ : normalizeBraveWebResults(raw);
461
+ }
462
+ catch (error) {
463
+ throw normalizeBraveError(error);
464
+ }
465
+ },
466
+ };
467
+ return capability;
468
+ }
469
+ // ---------------------------------------------------------------------------
470
+ // Descriptor factory
471
+ // ---------------------------------------------------------------------------
472
+ /**
473
+ * Build the Brave Provider Descriptor. The descriptor advertises the
474
+ * Search (T2), Diagnostics (T5), and Quota (T6) capabilities and
475
+ * constructs an Adapter whose `search`/`diagnostics`/`quota`
476
+ * Capabilities own credentials, transport, Provider field mapping, and
477
+ * failure normalization. Construction is side-effect-free; the
478
+ * transport is invoked per Capability call. Tests pass `transport`
479
+ * (typically a fake-fetch wrapper); production uses the no-argument
480
+ * factory which resolves to the global `fetch` and timers inside the
481
+ * transport Module.
482
+ */
483
+ export function createBraveDescriptor(dependencies) {
484
+ const transport = dependencies?.transport;
485
+ return {
486
+ id: "brave",
487
+ isConfigured(env) {
488
+ return isBraveConfigured(env);
489
+ },
490
+ capabilities() {
491
+ // T2 wires search; T5 wires diagnostics; T6 wires quota. Later
492
+ // tickets (reader) widen this set in lockstep with the matching
493
+ // Adapter slots.
494
+ return new Set(["search", "diagnostics", "quota"]);
495
+ },
496
+ create(context) {
497
+ const search = createBraveSearchCapability({ env: context.env, transport });
498
+ const diagnostics = createBraveDiagnosticsCapability({ env: context.env, transport });
499
+ const quota = createBraveQuotaCapability({ env: context.env, transport });
500
+ return { id: "brave", search, diagnostics, quota };
501
+ },
502
+ };
503
+ }
504
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/providers/brave/adapter.ts"],"names":[],"mappings":"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"}