webfox 4.0.0 → 4.1.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.
package/README.md CHANGED
@@ -137,6 +137,7 @@ Use different providers for different tasks:
137
137
  | [Serper] | ✔︎ | | | |
138
138
  | [Tavily] | ✔︎ | ✔︎ | | |
139
139
  | [Valyu] | ✔︎ | ✔︎ | ✔︎ | ✔︎ |
140
+ | [You.com] | ✔︎ | | | |
140
141
 
141
142
  [Brave]: ./docs/provider.md#brave
142
143
  [Cloudflare]: ./docs/provider.md#cloudflare
@@ -152,6 +153,7 @@ Use different providers for different tasks:
152
153
  [Serper]: ./docs/provider.md#serper
153
154
  [Tavily]: ./docs/provider.md#tavily
154
155
  [Valyu]: ./docs/provider.md#valyu
156
+ [You.com]: ./docs/provider.md#youcom
155
157
 
156
158
  See the [provider guide](./docs/provider.md) for credentials, examples, and caveats.
157
159
 
@@ -172,7 +174,7 @@ or, on Windows, `APPDATA`. Override it with `WEBFOX_CONFIG` or `--config <path>`
172
174
  For example:
173
175
 
174
176
  ```yaml
175
- $schema: https://unpkg.com/webfox@3.5.1/dist/config.schema.json
177
+ $schema: https://unpkg.com/webfox@4.0.1/dist/config.schema.json
176
178
  defaults:
177
179
  search:
178
180
  provider: brave
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-ZVTVERW5.js";
5
5
  import {
6
6
  WEBFOX_ERROR_CODES
7
- } from "./chunk-G2YAQEET.js";
7
+ } from "./chunk-WVHMWLKU.js";
8
8
  import {
9
9
  WebfoxError
10
10
  } from "./chunk-U4BLULLV.js";
@@ -0,0 +1,124 @@
1
+ import {
2
+ trimSnippet
3
+ } from "./chunk-X6ZBIHZC.js";
4
+ import {
5
+ httpError
6
+ } from "./chunk-U4BLULLV.js";
7
+
8
+ // src/providers/youcom/adapter.ts
9
+ var DEFAULT_BASE_URL = "https://ydc-index.io";
10
+ var adapter = {
11
+ async search(request, config, context) {
12
+ const apiKey = config.credentials?.api;
13
+ if (!apiKey) throw new Error("You.com search is missing an API key");
14
+ const options = asRecord(request.options);
15
+ const response = await fetch(joinUrl(config.baseUrl), {
16
+ method: "POST",
17
+ headers: {
18
+ "content-type": "application/json",
19
+ "X-API-Key": apiKey
20
+ },
21
+ body: JSON.stringify({
22
+ query: request.query,
23
+ count: clamp(request.maxResults, 100),
24
+ ...pickDefined(options, [
25
+ "freshness",
26
+ "country",
27
+ "language",
28
+ "safesearch",
29
+ "offset",
30
+ "include_domains",
31
+ "exclude_domains",
32
+ "boost_domains",
33
+ "livecrawl",
34
+ "livecrawl_formats",
35
+ "crawl_timeout"
36
+ ])
37
+ }),
38
+ signal: context.signal
39
+ });
40
+ if (!response.ok) throw httpError(response, await buildHttpError(response));
41
+ const payload = asRecord(await response.json());
42
+ const searchMetadata = asRecord(payload.metadata);
43
+ const web = collectResults(
44
+ asRecord(payload.results).web,
45
+ "web",
46
+ searchMetadata
47
+ );
48
+ const news = collectResults(
49
+ asRecord(payload.results).news,
50
+ "news",
51
+ searchMetadata
52
+ );
53
+ const results = [];
54
+ for (let index = 0; index < Math.max(web.length, news.length); index++) {
55
+ if (web[index]) results.push(web[index]);
56
+ if (news[index]) results.push(news[index]);
57
+ }
58
+ return {
59
+ provider: "youcom",
60
+ results: results.slice(0, clamp(request.maxResults, 100))
61
+ };
62
+ }
63
+ };
64
+ function joinUrl(baseUrl) {
65
+ return `${(baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "")}/v1/search`;
66
+ }
67
+ function collectResults(results, section, searchMetadata) {
68
+ return array(results).map((entry) => asRecord(entry)).filter((entry) => Object.keys(entry).length > 0).map((entry) => {
69
+ const url = string(entry.url) ?? "";
70
+ const title = string(entry.title) ?? string(entry.name) ?? (url || "Untitled");
71
+ return {
72
+ title,
73
+ url,
74
+ snippet: buildSnippet(entry, section),
75
+ metadata: buildMetadata(entry, section, searchMetadata)
76
+ };
77
+ });
78
+ }
79
+ function buildSnippet(entry, section) {
80
+ const contents = asRecord(entry.contents);
81
+ const snippets = arrayOfStrings(entry.snippets);
82
+ if (snippets.length > 0) return trimSnippet(snippets.join("\n\n"), 1200);
83
+ const text = string(entry.description) ?? string(contents.markdown) ?? string(contents.html) ?? (section === "news" ? string(entry.page_age) : void 0) ?? "";
84
+ return trimSnippet(text);
85
+ }
86
+ function buildMetadata(entry, section, searchMetadata) {
87
+ const metadata = {
88
+ section,
89
+ ...searchMetadata ? { searchMetadata } : {},
90
+ ...entry
91
+ };
92
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
93
+ }
94
+ function pickDefined(source, keys) {
95
+ return Object.fromEntries(
96
+ keys.flatMap(
97
+ (key) => source[key] === void 0 ? [] : [[key, source[key]]]
98
+ )
99
+ );
100
+ }
101
+ function clamp(value, max) {
102
+ return Math.max(1, Math.min(max, Math.trunc(value || 0)));
103
+ }
104
+ function array(value) {
105
+ return Array.isArray(value) ? value : [];
106
+ }
107
+ function arrayOfStrings(value) {
108
+ return array(value).flatMap(
109
+ (entry) => typeof entry === "string" ? [entry] : []
110
+ );
111
+ }
112
+ function asRecord(value) {
113
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
114
+ }
115
+ function string(value) {
116
+ return typeof value === "string" ? value : void 0;
117
+ }
118
+ async function buildHttpError(response) {
119
+ const body = (await response.text()).trim();
120
+ return `You.com search request failed (${response.status}${response.statusText ? ` ${response.statusText}` : ""})${body ? `: ${body}` : "."}`;
121
+ }
122
+ export {
123
+ adapter
124
+ };
@@ -11,14 +11,14 @@ import {
11
11
  providers,
12
12
  selectProvider,
13
13
  validateConfiguredOptions
14
- } from "./chunk-L425U55P.js";
14
+ } from "./chunk-7BXAXZPA.js";
15
15
  import {
16
16
  cancelProcessGroup,
17
17
  killProcessGroup
18
18
  } from "./chunk-ZVTVERW5.js";
19
19
  import {
20
20
  CAPABILITIES
21
- } from "./chunk-G2YAQEET.js";
21
+ } from "./chunk-WVHMWLKU.js";
22
22
  import {
23
23
  WebfoxError,
24
24
  asWebfoxError
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  CAPABILITIES
3
- } from "./chunk-G2YAQEET.js";
3
+ } from "./chunk-WVHMWLKU.js";
4
4
  import {
5
5
  WebfoxError
6
6
  } from "./chunk-U4BLULLV.js";
@@ -8,7 +8,7 @@ import {
8
8
  // package.json
9
9
  var package_default = {
10
10
  name: "webfox",
11
- version: "4.0.0",
11
+ version: "4.1.0",
12
12
  description: "Search the web, extract pages, get grounded answers, and run deep research with the web CLI, a TypeScript library, and a pi extension. Bring your own providers and API keys.",
13
13
  type: "module",
14
14
  files: [
@@ -746,7 +746,7 @@ var customProvider = defineProvider({
746
746
  retrySafe: false
747
747
  }
748
748
  },
749
- load: async () => (await import("./adapter-MAG7X663.js")).adapter
749
+ load: async () => (await import("./adapter-A7LV6L55.js")).adapter
750
750
  });
751
751
 
752
752
  // src/providers/exa/definition.ts
@@ -2788,6 +2788,197 @@ var valyuProvider = defineProvider({
2788
2788
  load: async () => (await import("./adapter-UAZNLDSS.js")).adapter
2789
2789
  });
2790
2790
 
2791
+ // src/providers/youcom/definition.ts
2792
+ var domains = {
2793
+ type: "array",
2794
+ maxItems: 500,
2795
+ items: { type: "string", minLength: 1 }
2796
+ };
2797
+ var youcomProvider = defineProvider({
2798
+ id: "youcom",
2799
+ label: "You.com",
2800
+ docsUrl: "https://you.com/docs/api-reference/search/v1-search-post",
2801
+ local: false,
2802
+ credentials: [
2803
+ {
2804
+ name: "api",
2805
+ environmentVariable: "YDC_API_KEY",
2806
+ capabilities: ["search"]
2807
+ }
2808
+ ],
2809
+ fields: ["credentials", "baseUrl", "options"],
2810
+ defaults: {},
2811
+ credentialDefaults: {},
2812
+ capabilities: {
2813
+ search: {
2814
+ options: {
2815
+ type: "object",
2816
+ properties: {
2817
+ freshness: {
2818
+ type: "string",
2819
+ description: "Freshness window: day, week, month, year, or YYYY-MM-DDtoYYYY-MM-DD. You.com uses the broader timeframe when the query also specifies one."
2820
+ },
2821
+ country: {
2822
+ type: "string",
2823
+ enum: [
2824
+ "AR",
2825
+ "AU",
2826
+ "AT",
2827
+ "BE",
2828
+ "BR",
2829
+ "CA",
2830
+ "CL",
2831
+ "DK",
2832
+ "FI",
2833
+ "FR",
2834
+ "DE",
2835
+ "HK",
2836
+ "IN",
2837
+ "ID",
2838
+ "IT",
2839
+ "JP",
2840
+ "KR",
2841
+ "MY",
2842
+ "MX",
2843
+ "NL",
2844
+ "NZ",
2845
+ "NO",
2846
+ "CN",
2847
+ "PL",
2848
+ "PT",
2849
+ "PH",
2850
+ "RU",
2851
+ "SA",
2852
+ "ZA",
2853
+ "ES",
2854
+ "SE",
2855
+ "CH",
2856
+ "TW",
2857
+ "TR",
2858
+ "GB",
2859
+ "US"
2860
+ ],
2861
+ description: "Country code used to localize search results, for example US."
2862
+ },
2863
+ language: {
2864
+ type: "string",
2865
+ enum: [
2866
+ "AR",
2867
+ "EU",
2868
+ "BN",
2869
+ "BG",
2870
+ "CA",
2871
+ "ZH-HANS",
2872
+ "ZH-HANT",
2873
+ "HR",
2874
+ "CS",
2875
+ "DA",
2876
+ "NL",
2877
+ "EN",
2878
+ "EN-GB",
2879
+ "ET",
2880
+ "FI",
2881
+ "FR",
2882
+ "GL",
2883
+ "DE",
2884
+ "EL",
2885
+ "GU",
2886
+ "HE",
2887
+ "HI",
2888
+ "HU",
2889
+ "IS",
2890
+ "IT",
2891
+ "JA",
2892
+ "KN",
2893
+ "KO",
2894
+ "LV",
2895
+ "LT",
2896
+ "MS",
2897
+ "ML",
2898
+ "MR",
2899
+ "NB",
2900
+ "PL",
2901
+ "PT-BR",
2902
+ "PT-PT",
2903
+ "PA",
2904
+ "RO",
2905
+ "RU",
2906
+ "SR",
2907
+ "SK",
2908
+ "SL",
2909
+ "ES",
2910
+ "SV",
2911
+ "TA",
2912
+ "TE",
2913
+ "TH",
2914
+ "TR",
2915
+ "UK",
2916
+ "VI"
2917
+ ],
2918
+ description: "Language of web results. Uses You.com's uppercase codes; defaults to EN."
2919
+ },
2920
+ safesearch: {
2921
+ type: "string",
2922
+ enum: ["moderate", "off", "strict"],
2923
+ description: "Safe-search filtering level. Defaults to moderate."
2924
+ },
2925
+ offset: {
2926
+ type: "integer",
2927
+ minimum: 0,
2928
+ maximum: 9,
2929
+ description: "Pagination offset in count-sized pages, separately for web and news. Count is maxResults capped at 100."
2930
+ },
2931
+ include_domains: {
2932
+ ...domains,
2933
+ description: "Restrict results to these domains. Cannot be combined with exclude_domains or boost_domains."
2934
+ },
2935
+ exclude_domains: {
2936
+ ...domains,
2937
+ description: "Exclude these domains. Cannot be combined with include_domains."
2938
+ },
2939
+ boost_domains: {
2940
+ ...domains,
2941
+ description: "Boost these domains without excluding others. Can be combined with exclude_domains, but not include_domains."
2942
+ },
2943
+ livecrawl: {
2944
+ type: "string",
2945
+ enum: ["web", "news", "all"],
2946
+ description: "Fetch full page content for the selected sections. Adds latency and per-page charges, including results omitted by maxResults. Content is preserved in result metadata.contents."
2947
+ },
2948
+ livecrawl_formats: {
2949
+ type: "array",
2950
+ minItems: 1,
2951
+ maxItems: 2,
2952
+ uniqueItems: true,
2953
+ items: { type: "string", enum: ["html", "markdown"] },
2954
+ description: "Formats for livecrawled content. Defaults to html; requires livecrawl to enable crawling."
2955
+ },
2956
+ crawl_timeout: {
2957
+ type: "integer",
2958
+ minimum: 1,
2959
+ maximum: 60,
2960
+ description: "Seconds to wait for page content when livecrawl is enabled. Defaults to 10."
2961
+ }
2962
+ },
2963
+ // Property prohibitions also work for partial configured defaults:
2964
+ // unlike required-based exclusions, they survive partial validation.
2965
+ anyOf: [
2966
+ { properties: { include_domains: false } },
2967
+ { properties: { exclude_domains: false, boost_domains: false } }
2968
+ ],
2969
+ description: "You.com search options. Results alternate web and news, starting with web, up to maxResults (capped at 100)."
2970
+ },
2971
+ promptGuidelines: [
2972
+ "Use You.com search for web and news results. Results alternate web and news, starting with web, within the overall result limit.",
2973
+ "Use include_domains to restrict sources, or exclude_domains and boost_domains to adjust source selection. Do not combine include_domains with either of the other domain controls.",
2974
+ "Search snippets already contain query-relevant passages. Enable livecrawl only when full page content is needed; it adds latency and per-page charges."
2975
+ ],
2976
+ retrySafe: true
2977
+ }
2978
+ },
2979
+ load: async () => (await import("./adapter-YOHLAGYM.js")).adapter
2980
+ });
2981
+
2791
2982
  // src/providers/registry.ts
2792
2983
  var providers = {
2793
2984
  brave: braveProvider,
@@ -2803,7 +2994,8 @@ var providers = {
2803
2994
  perplexity: perplexityProvider,
2804
2995
  serper: serperProvider,
2805
2996
  tavily: tavilyProvider,
2806
- valyu: valyuProvider
2997
+ valyu: valyuProvider,
2998
+ youcom: youcomProvider
2807
2999
  };
2808
3000
 
2809
3001
  // src/configuration/options-schema.ts
@@ -19,7 +19,8 @@ var PROVIDER_IDS = [
19
19
  "perplexity",
20
20
  "serper",
21
21
  "tavily",
22
- "valyu"
22
+ "valyu",
23
+ "youcom"
23
24
  ];
24
25
  var WEBFOX_ERROR_CODES = [
25
26
  "INVALID_CONFIG",
package/dist/cli.js CHANGED
@@ -11,17 +11,17 @@ import {
11
11
  redactConfig,
12
12
  resolveConfigPath,
13
13
  setCapabilityDefault
14
- } from "./chunk-SMF5ALX7.js";
14
+ } from "./chunk-2DWEBTPX.js";
15
15
  import "./chunk-WCTOYZVB.js";
16
16
  import {
17
17
  PACKAGE_VERSION,
18
18
  validateConfiguredOptions
19
- } from "./chunk-L425U55P.js";
19
+ } from "./chunk-7BXAXZPA.js";
20
20
  import "./chunk-ZVTVERW5.js";
21
21
  import {
22
22
  CAPABILITIES,
23
23
  PROVIDER_IDS
24
- } from "./chunk-G2YAQEET.js";
24
+ } from "./chunk-WVHMWLKU.js";
25
25
  import {
26
26
  WebfoxError
27
27
  } from "./chunk-U4BLULLV.js";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://unpkg.com/webfox@4.0.0/dist/config.schema.json",
3
+ "$id": "https://unpkg.com/webfox@4.1.0/dist/config.schema.json",
4
4
  "title": "webfox configuration",
5
5
  "type": "object",
6
6
  "additionalProperties": false,
@@ -30,7 +30,8 @@
30
30
  "perplexity",
31
31
  "serper",
32
32
  "tavily",
33
- "valyu"
33
+ "valyu",
34
+ "youcom"
34
35
  ]
35
36
  },
36
37
  "maxResults": {
@@ -4263,6 +4264,252 @@
4263
4264
  }
4264
4265
  }
4265
4266
  }
4267
+ },
4268
+ "youcom": {
4269
+ "type": "object",
4270
+ "additionalProperties": false,
4271
+ "properties": {
4272
+ "credentials": {
4273
+ "type": "object",
4274
+ "additionalProperties": false,
4275
+ "properties": {
4276
+ "api": {
4277
+ "oneOf": [
4278
+ {
4279
+ "type": "object",
4280
+ "additionalProperties": false,
4281
+ "properties": {
4282
+ "env": {
4283
+ "type": "string",
4284
+ "minLength": 1
4285
+ }
4286
+ },
4287
+ "required": ["env"]
4288
+ },
4289
+ {
4290
+ "type": "object",
4291
+ "additionalProperties": false,
4292
+ "properties": {
4293
+ "value": {
4294
+ "type": "string",
4295
+ "minLength": 1
4296
+ }
4297
+ },
4298
+ "required": ["value"]
4299
+ },
4300
+ {
4301
+ "type": "object",
4302
+ "additionalProperties": false,
4303
+ "properties": {
4304
+ "command": {
4305
+ "type": "array",
4306
+ "minItems": 1,
4307
+ "items": {
4308
+ "type": "string",
4309
+ "minLength": 1
4310
+ }
4311
+ }
4312
+ },
4313
+ "required": ["command"]
4314
+ }
4315
+ ]
4316
+ }
4317
+ }
4318
+ },
4319
+ "baseUrl": {
4320
+ "type": "string",
4321
+ "minLength": 1
4322
+ },
4323
+ "options": {
4324
+ "type": "object",
4325
+ "additionalProperties": false,
4326
+ "properties": {
4327
+ "search": {
4328
+ "type": "object",
4329
+ "properties": {
4330
+ "freshness": {
4331
+ "type": "string",
4332
+ "description": "Freshness window: day, week, month, year, or YYYY-MM-DDtoYYYY-MM-DD. You.com uses the broader timeframe when the query also specifies one."
4333
+ },
4334
+ "country": {
4335
+ "type": "string",
4336
+ "enum": [
4337
+ "AR",
4338
+ "AU",
4339
+ "AT",
4340
+ "BE",
4341
+ "BR",
4342
+ "CA",
4343
+ "CL",
4344
+ "DK",
4345
+ "FI",
4346
+ "FR",
4347
+ "DE",
4348
+ "HK",
4349
+ "IN",
4350
+ "ID",
4351
+ "IT",
4352
+ "JP",
4353
+ "KR",
4354
+ "MY",
4355
+ "MX",
4356
+ "NL",
4357
+ "NZ",
4358
+ "NO",
4359
+ "CN",
4360
+ "PL",
4361
+ "PT",
4362
+ "PH",
4363
+ "RU",
4364
+ "SA",
4365
+ "ZA",
4366
+ "ES",
4367
+ "SE",
4368
+ "CH",
4369
+ "TW",
4370
+ "TR",
4371
+ "GB",
4372
+ "US"
4373
+ ],
4374
+ "description": "Country code used to localize search results, for example US."
4375
+ },
4376
+ "language": {
4377
+ "type": "string",
4378
+ "enum": [
4379
+ "AR",
4380
+ "EU",
4381
+ "BN",
4382
+ "BG",
4383
+ "CA",
4384
+ "ZH-HANS",
4385
+ "ZH-HANT",
4386
+ "HR",
4387
+ "CS",
4388
+ "DA",
4389
+ "NL",
4390
+ "EN",
4391
+ "EN-GB",
4392
+ "ET",
4393
+ "FI",
4394
+ "FR",
4395
+ "GL",
4396
+ "DE",
4397
+ "EL",
4398
+ "GU",
4399
+ "HE",
4400
+ "HI",
4401
+ "HU",
4402
+ "IS",
4403
+ "IT",
4404
+ "JA",
4405
+ "KN",
4406
+ "KO",
4407
+ "LV",
4408
+ "LT",
4409
+ "MS",
4410
+ "ML",
4411
+ "MR",
4412
+ "NB",
4413
+ "PL",
4414
+ "PT-BR",
4415
+ "PT-PT",
4416
+ "PA",
4417
+ "RO",
4418
+ "RU",
4419
+ "SR",
4420
+ "SK",
4421
+ "SL",
4422
+ "ES",
4423
+ "SV",
4424
+ "TA",
4425
+ "TE",
4426
+ "TH",
4427
+ "TR",
4428
+ "UK",
4429
+ "VI"
4430
+ ],
4431
+ "description": "Language of web results. Uses You.com's uppercase codes; defaults to EN."
4432
+ },
4433
+ "safesearch": {
4434
+ "type": "string",
4435
+ "enum": ["moderate", "off", "strict"],
4436
+ "description": "Safe-search filtering level. Defaults to moderate."
4437
+ },
4438
+ "offset": {
4439
+ "type": "integer",
4440
+ "minimum": 0,
4441
+ "maximum": 9,
4442
+ "description": "Pagination offset in count-sized pages, separately for web and news. Count is maxResults capped at 100."
4443
+ },
4444
+ "include_domains": {
4445
+ "type": "array",
4446
+ "maxItems": 500,
4447
+ "items": {
4448
+ "type": "string",
4449
+ "minLength": 1
4450
+ },
4451
+ "description": "Restrict results to these domains. Cannot be combined with exclude_domains or boost_domains."
4452
+ },
4453
+ "exclude_domains": {
4454
+ "type": "array",
4455
+ "maxItems": 500,
4456
+ "items": {
4457
+ "type": "string",
4458
+ "minLength": 1
4459
+ },
4460
+ "description": "Exclude these domains. Cannot be combined with include_domains."
4461
+ },
4462
+ "boost_domains": {
4463
+ "type": "array",
4464
+ "maxItems": 500,
4465
+ "items": {
4466
+ "type": "string",
4467
+ "minLength": 1
4468
+ },
4469
+ "description": "Boost these domains without excluding others. Can be combined with exclude_domains, but not include_domains."
4470
+ },
4471
+ "livecrawl": {
4472
+ "type": "string",
4473
+ "enum": ["web", "news", "all"],
4474
+ "description": "Fetch full page content for the selected sections. Adds latency and per-page charges, including results omitted by maxResults. Content is preserved in result metadata.contents."
4475
+ },
4476
+ "livecrawl_formats": {
4477
+ "type": "array",
4478
+ "minItems": 1,
4479
+ "maxItems": 2,
4480
+ "uniqueItems": true,
4481
+ "items": {
4482
+ "type": "string",
4483
+ "enum": ["html", "markdown"]
4484
+ },
4485
+ "description": "Formats for livecrawled content. Defaults to html; requires livecrawl to enable crawling."
4486
+ },
4487
+ "crawl_timeout": {
4488
+ "type": "integer",
4489
+ "minimum": 1,
4490
+ "maximum": 60,
4491
+ "description": "Seconds to wait for page content when livecrawl is enabled. Defaults to 10."
4492
+ }
4493
+ },
4494
+ "anyOf": [
4495
+ {
4496
+ "properties": {
4497
+ "include_domains": false
4498
+ }
4499
+ },
4500
+ {
4501
+ "properties": {
4502
+ "exclude_domains": false,
4503
+ "boost_domains": false
4504
+ }
4505
+ }
4506
+ ],
4507
+ "description": "You.com search options. Results alternate web and news, starting with web, up to maxResults (capped at 100).",
4508
+ "additionalProperties": false
4509
+ }
4510
+ }
4511
+ }
4512
+ }
4266
4513
  }
4267
4514
  }
4268
4515
  }
package/dist/domain.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export declare const CAPABILITIES: readonly ["search", "contents", "answer", "research"];
2
2
  export type Capability = (typeof CAPABILITIES)[number];
3
- export declare const PROVIDER_IDS: readonly ["brave", "cloudflare", "custom", "exa", "firecrawl", "gemini", "linkup", "ollama", "openai", "parallel", "perplexity", "serper", "tavily", "valyu"];
3
+ export declare const PROVIDER_IDS: readonly ["brave", "cloudflare", "custom", "exa", "firecrawl", "gemini", "linkup", "ollama", "openai", "parallel", "perplexity", "serper", "tavily", "valyu", "youcom"];
4
4
  export type ProviderId = (typeof PROVIDER_IDS)[number];
5
5
  export declare const WEBFOX_ERROR_CODES: readonly ["INVALID_CONFIG", "INVALID_INPUT", "PROVIDER_UNAVAILABLE", "PROVIDER_FAILURE", "PARTIAL_BATCH", "TIMEOUT", "CANCELLED"];
6
6
  export type WebfoxErrorCode = (typeof WEBFOX_ERROR_CODES)[number];
package/dist/index.js CHANGED
@@ -6,18 +6,18 @@ import {
6
6
  resolveConfigPath,
7
7
  setCapabilityDefault,
8
8
  validateConfig
9
- } from "./chunk-SMF5ALX7.js";
9
+ } from "./chunk-2DWEBTPX.js";
10
10
  import "./chunk-WCTOYZVB.js";
11
11
  import {
12
12
  CONFIG_SCHEMA_URL,
13
13
  validateConfiguredOptions
14
- } from "./chunk-L425U55P.js";
14
+ } from "./chunk-7BXAXZPA.js";
15
15
  import "./chunk-ZVTVERW5.js";
16
16
  import {
17
17
  CAPABILITIES,
18
18
  PROVIDER_IDS,
19
19
  WEBFOX_ERROR_CODES
20
- } from "./chunk-G2YAQEET.js";
20
+ } from "./chunk-WVHMWLKU.js";
21
21
  import {
22
22
  WebfoxError
23
23
  } from "./chunk-U4BLULLV.js";
@@ -8,7 +8,7 @@ declare const inputStates: {
8
8
  };
9
9
  readonly running: {
10
10
  readonly glyph: "▶︎";
11
- readonly color: "warning";
11
+ readonly color: "muted";
12
12
  };
13
13
  readonly done: {
14
14
  readonly glyph: "✔︎";
package/dist/pi.js CHANGED
@@ -3,13 +3,13 @@ import {
3
3
  } from "./chunk-QRHDXM2L.js";
4
4
  import {
5
5
  createWebfox
6
- } from "./chunk-SMF5ALX7.js";
6
+ } from "./chunk-2DWEBTPX.js";
7
7
  import "./chunk-WCTOYZVB.js";
8
- import "./chunk-L425U55P.js";
8
+ import "./chunk-7BXAXZPA.js";
9
9
  import "./chunk-ZVTVERW5.js";
10
10
  import {
11
11
  CAPABILITIES
12
- } from "./chunk-G2YAQEET.js";
12
+ } from "./chunk-WVHMWLKU.js";
13
13
  import "./chunk-U4BLULLV.js";
14
14
 
15
15
  // src/pi.ts
@@ -245,7 +245,7 @@ function renderSearchResult(details, fallback, theme) {
245
245
  // src/pi-render.ts
246
246
  var inputStates = {
247
247
  queued: { glyph: "\u25CF", color: "dim" },
248
- running: { glyph: "\u25B6\uFE0E", color: "warning" },
248
+ running: { glyph: "\u25B6\uFE0E", color: "muted" },
249
249
  done: { glyph: "\u2714\uFE0E", color: "success" },
250
250
  failed: { glyph: "\u2718\uFE0E", color: "error" },
251
251
  cancelled: { glyph: "\u25A0", color: "dim" }
@@ -84,5 +84,6 @@ export interface ProviderConfigMap {
84
84
  serper: import("./serper/types.js").Serper;
85
85
  tavily: import("./tavily/types.js").Tavily;
86
86
  valyu: import("./valyu/types.js").Valyu;
87
+ youcom: import("./youcom/types.js").Youcom;
87
88
  }
88
89
  export type ProviderConfig<T extends ProviderId = ProviderId> = ProviderConfigMap[T];
@@ -13,4 +13,5 @@ export declare const providers: {
13
13
  readonly serper: import("./definition.js").ProviderDefinitionFor<"serper">;
14
14
  readonly tavily: import("./definition.js").ProviderDefinitionFor<"tavily">;
15
15
  readonly valyu: import("./definition.js").ProviderDefinitionFor<"valyu">;
16
+ readonly youcom: import("./definition.js").ProviderDefinitionFor<"youcom">;
16
17
  };
@@ -0,0 +1,5 @@
1
+ import type { ProviderContext, SearchResponse } from "../contract.js";
2
+ import type { Youcom } from "./types.js";
3
+ export declare const adapter: {
4
+ search(request: import("../contract.js").ProviderRequest<"search">, config: Youcom, context: ProviderContext): Promise<SearchResponse>;
5
+ };
@@ -0,0 +1 @@
1
+ export declare const youcomProvider: import("../definition.js").ProviderDefinitionFor<"youcom">;
@@ -0,0 +1,4 @@
1
+ import type { Provider } from "../contract.js";
2
+ export interface Youcom extends Provider {
3
+ baseUrl?: string;
4
+ }
package/docs/provider.md CHANGED
@@ -160,6 +160,84 @@ Supports search. Set `SERPER_API_KEY`.
160
160
  web search "Node.js release notes" --provider serper
161
161
  ```
162
162
 
163
+ ## You.com
164
+
165
+ Supports search. Set `YDC_API_KEY`; the library, CLI, and Pi extension use the
166
+ same credential. No defaults change unless you select You.com.
167
+
168
+ ```sh
169
+ web search "Node.js release notes" --provider youcom \
170
+ --freshness week --country US --language EN --include-domains nodejs.org
171
+ web config default search youcom
172
+ ```
173
+
174
+ You.com returns separate web and news sections. Webfox alternates results from
175
+ these sections, starting with web and preserving each section's order, up to
176
+ `maxResults` (capped at 100 overall). If one section is exhausted, the other fills
177
+ the remaining slots. With `maxResults: 1`, web takes precedence. The `offset`
178
+ option selects pages from each section independently, using the capped
179
+ `maxResults` as the upstream page size.
180
+
181
+ Use `include_domains` to restrict sources, or combine `exclude_domains` with
182
+ `boost_domains` to exclude some sources and favor others. Don't combine
183
+ `include_domains` with either of the other domain lists. Each list supports up to
184
+ 500 domains. Country and language codes use the API's uppercase spelling, such
185
+ as `US`, `EN`, and `EN-GB`. Run `web search --provider youcom --help` for supported
186
+ values and all native options.
187
+
188
+ Search snippets already contain query-relevant passages. For full page content,
189
+ enable live crawling:
190
+
191
+ ```sh
192
+ web search "Node.js cancellation" --provider youcom \
193
+ --livecrawl web --livecrawl-formats markdown --crawl-timeout 10 --format json
194
+ ```
195
+
196
+ Live crawling adds latency and per-page charges, including pages that don't fit
197
+ within the final result limit. By default, it returns HTML; request `markdown` or
198
+ both formats as needed. Full content is preserved in each result's
199
+ `metadata.contents`; text output shows snippets rather than full pages. See
200
+ [You.com's API reference](https://you.com/docs/api-reference/search/v1-search-post)
201
+ for current pricing and filter behavior.
202
+
203
+ Provider-specific defaults belong under `providers.youcom.options.search`:
204
+
205
+ ```yaml
206
+ defaults:
207
+ search:
208
+ provider: youcom
209
+ providers:
210
+ youcom:
211
+ options:
212
+ search:
213
+ country: US
214
+ language: EN
215
+ safesearch: moderate
216
+ ```
217
+
218
+ `providers.youcom.baseUrl` optionally replaces the API origin for a proxy; webfox
219
+ appends `/v1/search`. Credential overrides use `providers.youcom.credentials.api`.
220
+ For example, `{env: MY_YOUCOM_KEY}` selects another environment variable.
221
+
222
+ The TypeScript library accepts the same native option names:
223
+
224
+ ```ts
225
+ import { createWebfox } from "webfox";
226
+
227
+ const result = await createWebfox().search({
228
+ provider: "youcom",
229
+ queries: ["Node.js release notes"],
230
+ maxResults: 5,
231
+ options: { freshness: "week", include_domains: ["nodejs.org"] },
232
+ });
233
+ ```
234
+
235
+ The provider uses the JSON POST API directly, like the HTTP-based Brave and
236
+ Serper providers. Option names follow the wire contract rather than the official
237
+ You.com SDK's camelCase names. Selecting You.com as the search default exposes
238
+ these options through the existing `web_search` Pi tool; no separate tool is
239
+ needed.
240
+
163
241
  ## Tavily
164
242
 
165
243
  Supports search and page extraction. Set `TAVILY_API_KEY`.
@@ -1,4 +1,4 @@
1
- $schema: https://unpkg.com/webfox@3.5.1/dist/config.schema.json
1
+ $schema: https://unpkg.com/webfox@4.0.1/dist/config.schema.json
2
2
  defaults:
3
3
  search:
4
4
  provider: brave
@@ -34,3 +34,11 @@ providers:
34
34
  credentials:
35
35
  api:
36
36
  env: GOOGLE_API_KEY
37
+ youcom:
38
+ credentials:
39
+ api:
40
+ env: YDC_API_KEY
41
+ options:
42
+ search:
43
+ language: EN
44
+ safesearch: moderate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webfox",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Search the web, extract pages, get grounded answers, and run deep research with the web CLI, a TypeScript library, and a pi extension. Bring your own providers and API keys.",
5
5
  "type": "module",
6
6
  "files": [