@youdotcom-oss/api 0.1.1 → 0.2.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/bin/cli.js CHANGED
@@ -11,11 +11,11 @@ var __export = (target, all) => {
11
11
  };
12
12
 
13
13
  // src/cli.ts
14
- import { parseArgs as parseArgs4 } from "node:util";
14
+ import { parseArgs as parseArgs2 } from "node:util";
15
15
  // package.json
16
16
  var package_default = {
17
17
  name: "@youdotcom-oss/api",
18
- version: "0.1.1",
18
+ version: "0.2.0",
19
19
  description: "You.com API client with bundled CLI for agents supporting Agent Skills",
20
20
  license: "MIT",
21
21
  engines: {
@@ -82,9 +82,6 @@ var package_default = {
82
82
  }
83
83
  };
84
84
 
85
- // src/commands/contents.ts
86
- import { parseArgs } from "node:util";
87
-
88
85
  // ../../node_modules/.bun/zod@4.3.6/node_modules/zod/v4/core/core.js
89
86
  var NEVER = Object.freeze({
90
87
  status: "aborted"
@@ -2340,114 +2337,6 @@ function handleIntersectionResults(result, left, right) {
2340
2337
  result.value = merged.data;
2341
2338
  return result;
2342
2339
  }
2343
- var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
2344
- $ZodType.init(inst, def);
2345
- inst._zod.parse = (payload, ctx) => {
2346
- const input = payload.value;
2347
- if (!isPlainObject(input)) {
2348
- payload.issues.push({
2349
- expected: "record",
2350
- code: "invalid_type",
2351
- input,
2352
- inst
2353
- });
2354
- return payload;
2355
- }
2356
- const proms = [];
2357
- const values = def.keyType._zod.values;
2358
- if (values) {
2359
- payload.value = {};
2360
- const recordKeys = new Set;
2361
- for (const key of values) {
2362
- if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
2363
- recordKeys.add(typeof key === "number" ? key.toString() : key);
2364
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
2365
- if (result instanceof Promise) {
2366
- proms.push(result.then((result2) => {
2367
- if (result2.issues.length) {
2368
- payload.issues.push(...prefixIssues(key, result2.issues));
2369
- }
2370
- payload.value[key] = result2.value;
2371
- }));
2372
- } else {
2373
- if (result.issues.length) {
2374
- payload.issues.push(...prefixIssues(key, result.issues));
2375
- }
2376
- payload.value[key] = result.value;
2377
- }
2378
- }
2379
- }
2380
- let unrecognized;
2381
- for (const key in input) {
2382
- if (!recordKeys.has(key)) {
2383
- unrecognized = unrecognized ?? [];
2384
- unrecognized.push(key);
2385
- }
2386
- }
2387
- if (unrecognized && unrecognized.length > 0) {
2388
- payload.issues.push({
2389
- code: "unrecognized_keys",
2390
- input,
2391
- inst,
2392
- keys: unrecognized
2393
- });
2394
- }
2395
- } else {
2396
- payload.value = {};
2397
- for (const key of Reflect.ownKeys(input)) {
2398
- if (key === "__proto__")
2399
- continue;
2400
- let keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
2401
- if (keyResult instanceof Promise) {
2402
- throw new Error("Async schemas not supported in object keys currently");
2403
- }
2404
- const checkNumericKey = typeof key === "string" && number.test(key) && keyResult.issues.length;
2405
- if (checkNumericKey) {
2406
- const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
2407
- if (retryResult instanceof Promise) {
2408
- throw new Error("Async schemas not supported in object keys currently");
2409
- }
2410
- if (retryResult.issues.length === 0) {
2411
- keyResult = retryResult;
2412
- }
2413
- }
2414
- if (keyResult.issues.length) {
2415
- if (def.mode === "loose") {
2416
- payload.value[key] = input[key];
2417
- } else {
2418
- payload.issues.push({
2419
- code: "invalid_key",
2420
- origin: "record",
2421
- issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
2422
- input: key,
2423
- path: [key],
2424
- inst
2425
- });
2426
- }
2427
- continue;
2428
- }
2429
- const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
2430
- if (result instanceof Promise) {
2431
- proms.push(result.then((result2) => {
2432
- if (result2.issues.length) {
2433
- payload.issues.push(...prefixIssues(key, result2.issues));
2434
- }
2435
- payload.value[keyResult.value] = result2.value;
2436
- }));
2437
- } else {
2438
- if (result.issues.length) {
2439
- payload.issues.push(...prefixIssues(key, result.issues));
2440
- }
2441
- payload.value[keyResult.value] = result.value;
2442
- }
2443
- }
2444
- }
2445
- if (proms.length) {
2446
- return Promise.all(proms).then(() => payload);
2447
- }
2448
- return payload;
2449
- };
2450
- });
2451
2340
  var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
2452
2341
  $ZodType.init(inst, def);
2453
2342
  const values = getEnumValues(def.entries);
@@ -2468,28 +2357,6 @@ var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
2468
2357
  return payload;
2469
2358
  };
2470
2359
  });
2471
- var $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
2472
- $ZodType.init(inst, def);
2473
- if (def.values.length === 0) {
2474
- throw new Error("Cannot create literal schema with no valid values");
2475
- }
2476
- const values = new Set(def.values);
2477
- inst._zod.values = values;
2478
- inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
2479
- inst._zod.parse = (payload, _ctx) => {
2480
- const input = payload.value;
2481
- if (values.has(input)) {
2482
- return payload;
2483
- }
2484
- payload.issues.push({
2485
- code: "invalid_value",
2486
- values: def.values,
2487
- input,
2488
- inst
2489
- });
2490
- return payload;
2491
- };
2492
- });
2493
2360
  var $ZodTransform = /* @__PURE__ */ $constructor("$ZodTransform", (inst, def) => {
2494
2361
  $ZodType.init(inst, def);
2495
2362
  inst._zod.parse = (payload, ctx) => {
@@ -4663,21 +4530,6 @@ function intersection(left, right) {
4663
4530
  right
4664
4531
  });
4665
4532
  }
4666
- var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
4667
- $ZodRecord.init(inst, def);
4668
- ZodType.init(inst, def);
4669
- inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
4670
- inst.keyType = def.keyType;
4671
- inst.valueType = def.valueType;
4672
- });
4673
- function record(keyType, valueType, params) {
4674
- return new ZodRecord({
4675
- type: "record",
4676
- keyType,
4677
- valueType,
4678
- ...exports_util.normalizeParams(params)
4679
- });
4680
- }
4681
4533
  var ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
4682
4534
  $ZodEnum.init(inst, def);
4683
4535
  ZodType.init(inst, def);
@@ -4724,27 +4576,6 @@ function _enum(values, params) {
4724
4576
  ...exports_util.normalizeParams(params)
4725
4577
  });
4726
4578
  }
4727
- var ZodLiteral = /* @__PURE__ */ $constructor("ZodLiteral", (inst, def) => {
4728
- $ZodLiteral.init(inst, def);
4729
- ZodType.init(inst, def);
4730
- inst._zod.processJSONSchema = (ctx, json, params) => literalProcessor(inst, ctx, json, params);
4731
- inst.values = new Set(def.values);
4732
- Object.defineProperty(inst, "value", {
4733
- get() {
4734
- if (def.values.length > 1) {
4735
- throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");
4736
- }
4737
- return def.values[0];
4738
- }
4739
- });
4740
- });
4741
- function literal(value, params) {
4742
- return new ZodLiteral({
4743
- type: "literal",
4744
- values: Array.isArray(value) ? value : [value],
4745
- ...exports_util.normalizeParams(params)
4746
- });
4747
- }
4748
4579
  var ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
4749
4580
  $ZodTransform.init(inst, def);
4750
4581
  ZodType.init(inst, def);
@@ -4926,20 +4757,19 @@ var ContentsQuerySchema = object({
4926
4757
  });
4927
4758
  var ContentsItemSchema = object({
4928
4759
  url: string2().describe("URL"),
4929
- title: string2().optional().describe("Title"),
4930
- html: string2().optional().describe("HTML content"),
4931
- markdown: string2().optional().describe("Markdown content"),
4760
+ title: string2().optional().describe("Title (optional in actual API responses)"),
4761
+ html: string2().nullable().optional().describe("HTML content"),
4762
+ markdown: string2().nullable().optional().describe("Markdown content"),
4932
4763
  metadata: object({
4933
- jsonld: array(record(string2(), unknown())).optional().describe("JSON-LD structured data (Schema.org)"),
4934
- opengraph: record(string2(), string2()).optional().describe("OpenGraph meta tags"),
4935
- twitter: record(string2(), string2()).optional().describe("Twitter Card metadata")
4936
- }).optional().describe("Structured metadata when available")
4764
+ site_name: string2().nullable().optional().describe("OpenGraph site name"),
4765
+ favicon_url: string2().describe("Favicon URL")
4766
+ }).nullable().optional().describe("Page metadata (only when metadata format requested)")
4937
4767
  });
4938
4768
  var ContentsApiResponseSchema = array(ContentsItemSchema);
4939
4769
 
4940
4770
  // src/shared/api.constants.ts
4941
4771
  var SEARCH_API_URL = "https://ydc-index.io/v1/search";
4942
- var EXPRESS_API_URL = "https://api.you.com/v1/agents/runs";
4772
+ var DEEP_SEARCH_API_URL = "https://api.you.com/v1/deep_search";
4943
4773
  var CONTENTS_API_URL = "https://ydc-index.io/v1/contents";
4944
4774
 
4945
4775
  // src/shared/check-response-for-errors.ts
@@ -5007,199 +4837,98 @@ var fetchContents = async ({
5007
4837
  return parsedResults;
5008
4838
  };
5009
4839
 
5010
- // src/shared/use-get-user-agents.ts
5011
- var useGetUserAgent = (client = "") => () => `CLI/ ${package_default.version} (You.com;${client})`;
5012
-
5013
- // src/commands/contents.ts
5014
- var contentsCommand = async (args) => {
5015
- if (args.includes("--schema")) {
5016
- console.log(JSON.stringify(toJSONSchema(ContentsQuerySchema)));
5017
- process.exit(0);
5018
- }
5019
- const { values } = parseArgs({
5020
- args,
5021
- options: {
5022
- json: { type: "string" },
5023
- "api-key": { type: "string" },
5024
- client: { type: "string" }
5025
- }
5026
- });
5027
- if (!values.json) {
5028
- throw new Error("--json flag is required");
5029
- }
5030
- const query = JSON.parse(values.json);
5031
- const apiKey = values["api-key"];
5032
- const client = values.client || process.env.YDC_CLIENT;
5033
- const YDC_API_KEY = apiKey || process.env.YDC_API_KEY;
5034
- if (!YDC_API_KEY) {
5035
- throw new Error("YDC_API_KEY environment variable is required");
5036
- }
5037
- const contentsQuery = ContentsQuerySchema.parse(query);
5038
- const response = await fetchContents({
5039
- contentsQuery,
5040
- YDC_API_KEY,
5041
- getUserAgent: useGetUserAgent(client)
5042
- });
5043
- console.log(JSON.stringify(response));
5044
- };
5045
-
5046
- // src/commands/express.ts
5047
- import { parseArgs as parseArgs2 } from "node:util";
5048
-
5049
- // src/express/express.schemas.ts
5050
- var ExpressAgentInputSchema = object({
5051
- input: string2().min(1, "Input is required").describe("Query or prompt"),
5052
- tools: array(object({
5053
- type: _enum(["web_search"]).describe("Tool type")
5054
- })).optional().describe("Tools (web search only)")
4840
+ // src/deep-search/deep-search.schemas.ts
4841
+ var SearchEffortSchema = _enum(["low", "medium", "high"]).describe("Search effort level");
4842
+ var DeepSearchQuerySchema = object({
4843
+ query: string2().min(1, "Query is required").describe("The research question or complex query requiring in-depth investigation and multi-step reasoning"),
4844
+ search_effort: SearchEffortSchema.optional().default("medium").describe("Computation budget: low (<30s), medium (<60s, default), high (<300s)")
5055
4845
  });
5056
- var ApiSearchResultItemSchema = object({
5057
- source_type: string2().nullable().optional(),
5058
- citation_uri: string2().optional(),
5059
- url: string2(),
5060
- title: string2(),
5061
- snippet: string2(),
5062
- thumbnail_url: string2().nullable().optional(),
5063
- provider: string2().nullable().optional()
4846
+ var DeepSearchSourceSchema = object({
4847
+ url: string2().describe("Source webpage URL"),
4848
+ title: string2().describe("Source webpage title"),
4849
+ snippets: array(string2()).describe("Relevant excerpts from the source page used in generating the answer")
5064
4850
  });
5065
- var ExpressAgentApiOutputItemSchema = union([
5066
- object({
5067
- type: literal("web_search.results"),
5068
- content: array(ApiSearchResultItemSchema)
5069
- }),
5070
- object({
5071
- type: literal("message.answer"),
5072
- text: string2()
5073
- })
5074
- ]);
5075
- var ExpressAgentApiResponseSchema = object({
5076
- output: array(ExpressAgentApiOutputItemSchema),
5077
- agent: string2().optional().describe("Agent identifier"),
5078
- mode: string2().optional().describe("Agent mode"),
5079
- input: array(object({
5080
- role: _enum(["user"]).describe("User role"),
5081
- content: string2().describe("User question")
5082
- })).optional().describe("Input messages")
5083
- }).passthrough();
5084
- var McpSearchResultItemSchema = object({
5085
- url: string2().describe("URL"),
5086
- title: string2().describe("Title"),
5087
- snippet: string2().describe("Snippet")
5088
- });
5089
- var ExpressAgentMcpResponseSchema = object({
5090
- answer: string2().describe("AI answer"),
5091
- results: object({
5092
- web: array(McpSearchResultItemSchema).describe("Web results")
5093
- }).optional().describe("Search results"),
5094
- agent: string2().optional().describe("Agent ID")
4851
+ var DeepSearchResponseSchema = object({
4852
+ answer: string2().describe("Comprehensive response with inline citations, formatted in Markdown"),
4853
+ results: array(DeepSearchSourceSchema).describe("List of web sources used to generate the answer")
5095
4854
  });
5096
4855
 
5097
- // src/express/express.utils.ts
5098
- var agentThrowOnFailedStatus = async (response) => {
5099
- const errorCode = response.status;
5100
- const errorData = await response.json();
5101
- if (errorCode === 400) {
5102
- throw new Error(`Bad Request:
5103
- ${JSON.stringify(errorData)}`);
5104
- } else if (errorCode === 401) {
5105
- throw new Error(`Unauthorized: The Agent APIs require a valid You.com API key with agent access. Ensure your YDC_API_KEY has permissions for agent endpoints.`);
5106
- } else if (errorCode === 403) {
5107
- throw new Error(`Forbidden: You are not allowed to use the requested tool for this agent or tenant`);
5108
- } else if (errorCode === 429) {
5109
- throw new Error("Rate limited by You.com API. Please try again later.");
5110
- }
5111
- throw new Error(`Failed to call agent. Error code: ${errorCode}`);
5112
- };
5113
- var callExpressAgent = async ({
5114
- YDC_API_KEY = process.env.YDC_API_KEY,
5115
- agentInput: { input, tools },
4856
+ // src/deep-search/deep-search.utils.ts
4857
+ var callDeepSearch = async ({
4858
+ deepSearchQuery,
4859
+ YDC_API_KEY,
5116
4860
  getUserAgent
5117
4861
  }) => {
5118
- const requestBody = {
5119
- agent: "express",
5120
- input,
5121
- stream: false
5122
- };
5123
- if (tools) {
5124
- requestBody.tools = tools;
5125
- }
5126
- const options = {
4862
+ const response = await fetch(DEEP_SEARCH_API_URL, {
5127
4863
  method: "POST",
5128
4864
  headers: new Headers({
5129
- Authorization: `Bearer ${YDC_API_KEY || ""}`,
4865
+ "X-API-Key": YDC_API_KEY || "",
5130
4866
  "Content-Type": "application/json",
5131
- Accept: "application/json",
5132
4867
  "User-Agent": getUserAgent()
5133
4868
  }),
5134
- body: JSON.stringify(requestBody)
5135
- };
5136
- const response = await fetch(EXPRESS_API_URL, options);
5137
- if (!response.ok) {
5138
- await agentThrowOnFailedStatus(response);
5139
- }
5140
- const jsonResponse = await response.json();
5141
- checkResponseForErrors(jsonResponse);
5142
- const apiResponse = ExpressAgentApiResponseSchema.parse(jsonResponse);
5143
- const answerItem = apiResponse.output.find((item) => item.type === "message.answer");
5144
- if (!answerItem) {
5145
- throw new Error("Express API response missing required message.answer item");
5146
- }
5147
- const searchItem = apiResponse.output.find((item) => item.type === "web_search.results");
5148
- const mcpResponse = {
5149
- answer: answerItem.text,
5150
- agent: apiResponse.agent
5151
- };
5152
- if (searchItem && "content" in searchItem && Array.isArray(searchItem.content)) {
5153
- mcpResponse.results = {
5154
- web: searchItem.content.map((item) => ({
5155
- url: item.url || item.citation_uri || "",
5156
- title: item.title || "",
5157
- snippet: item.snippet || ""
5158
- }))
5159
- };
5160
- }
5161
- return mcpResponse;
5162
- };
5163
-
5164
- // src/commands/express.ts
5165
- var expressCommand = async (args) => {
5166
- if (args.includes("--schema")) {
5167
- console.log(JSON.stringify(toJSONSchema(ExpressAgentInputSchema)));
5168
- process.exit(0);
5169
- }
5170
- const { values } = parseArgs2({
5171
- args,
5172
- options: {
5173
- json: { type: "string" },
5174
- "api-key": { type: "string" },
5175
- client: { type: "string" }
5176
- }
5177
- });
5178
- if (!values.json) {
5179
- throw new Error("--json flag is required");
5180
- }
5181
- const input = JSON.parse(values.json);
5182
- const apiKey = values["api-key"];
5183
- const client = values.client || process.env.YDC_CLIENT;
5184
- const YDC_API_KEY = apiKey || process.env.YDC_API_KEY;
5185
- if (!YDC_API_KEY) {
5186
- throw new Error("YDC_API_KEY environment variable is required");
5187
- }
5188
- const agentInput = ExpressAgentInputSchema.parse(input);
5189
- const response = await callExpressAgent({
5190
- agentInput,
5191
- YDC_API_KEY,
5192
- getUserAgent: useGetUserAgent(client)
4869
+ body: JSON.stringify(deepSearchQuery)
5193
4870
  });
5194
- console.log(JSON.stringify(response));
4871
+ await checkResponseForErrors(response);
4872
+ const data = await response.json();
4873
+ return DeepSearchResponseSchema.parse(data);
5195
4874
  };
5196
4875
 
5197
- // src/commands/search.ts
5198
- import { parseArgs as parseArgs3 } from "node:util";
5199
-
5200
4876
  // src/search/search.schemas.ts
4877
+ var LanguageSchema = _enum([
4878
+ "AR",
4879
+ "EU",
4880
+ "BN",
4881
+ "BG",
4882
+ "CA",
4883
+ "ZH-HANS",
4884
+ "ZH-HANT",
4885
+ "HR",
4886
+ "CS",
4887
+ "DA",
4888
+ "NL",
4889
+ "EN",
4890
+ "EN-GB",
4891
+ "ET",
4892
+ "FI",
4893
+ "FR",
4894
+ "GL",
4895
+ "DE",
4896
+ "EL",
4897
+ "GU",
4898
+ "HE",
4899
+ "HI",
4900
+ "HU",
4901
+ "IS",
4902
+ "IT",
4903
+ "JP",
4904
+ "KN",
4905
+ "KO",
4906
+ "LV",
4907
+ "LT",
4908
+ "MS",
4909
+ "ML",
4910
+ "MR",
4911
+ "NB",
4912
+ "PL",
4913
+ "PT-BR",
4914
+ "PT-PT",
4915
+ "PA",
4916
+ "RO",
4917
+ "RU",
4918
+ "SR",
4919
+ "SK",
4920
+ "SL",
4921
+ "ES",
4922
+ "SV",
4923
+ "TA",
4924
+ "TE",
4925
+ "TH",
4926
+ "TR",
4927
+ "UK",
4928
+ "VI"
4929
+ ]);
5201
4930
  var SearchQuerySchema = object({
5202
- query: string2().min(1, "Query is required").describe("Search query (supports +, -, site:, filetype:, lang:)"),
4931
+ query: string2().min(1, "Query is required").describe('Search query. Supports operators: site:domain.com (domain filter), filetype:pdf (file type), +term (include), -term (exclude), AND/OR/NOT (boolean logic), lang:en (language). Example: "machine learning (Python OR PyTorch) -TensorFlow filetype:pdf"'),
5203
4932
  count: number2().int().min(1).max(100).optional().describe("Max results per section"),
5204
4933
  freshness: string2().optional().describe("day/week/month/year or YYYY-MM-DDtoYYYY-MM-DD"),
5205
4934
  offset: number2().int().min(0).max(9).optional().describe("Pagination offset"),
@@ -5229,6 +4958,7 @@ var SearchQuerySchema = object({
5229
4958
  "CN",
5230
4959
  "PL",
5231
4960
  "PT",
4961
+ "PT-BR",
5232
4962
  "PH",
5233
4963
  "RU",
5234
4964
  "SA",
@@ -5242,11 +4972,6 @@ var SearchQuerySchema = object({
5242
4972
  "US"
5243
4973
  ]).optional().describe("Country code"),
5244
4974
  safesearch: _enum(["off", "moderate", "strict"]).optional().describe("Filter level"),
5245
- site: string2().optional().describe("Specific domain"),
5246
- fileType: string2().optional().describe("File type"),
5247
- language: string2().optional().describe("ISO 639-1 language code"),
5248
- excludeTerms: string2().optional().describe("Terms to exclude (pipe-separated)"),
5249
- exactTerms: string2().optional().describe("Exact terms (pipe-separated)"),
5250
4975
  livecrawl: _enum(["web", "news", "all"]).optional().describe("Live-crawl sections for full content"),
5251
4976
  livecrawl_formats: _enum(["html", "markdown"]).optional().describe("Format for crawled content")
5252
4977
  });
@@ -5291,24 +5016,15 @@ var SearchResponseSchema = object({
5291
5016
  // src/search/search.utils.ts
5292
5017
  var fetchSearchResults = async ({
5293
5018
  YDC_API_KEY = process.env.YDC_API_KEY,
5294
- searchQuery: { query, site, fileType, language, exactTerms, excludeTerms, ...rest },
5019
+ searchQuery,
5295
5020
  getUserAgent
5296
5021
  }) => {
5297
5022
  const url = new URL(SEARCH_API_URL);
5298
5023
  const searchParams = new URLSearchParams;
5299
- const searchQuery = [query];
5300
- site && searchQuery.push(`site:${site}`);
5301
- fileType && searchQuery.push(`filetype:${fileType}`);
5302
- language && searchQuery.push(`lang:${language}`);
5303
- if (exactTerms && excludeTerms) {
5304
- throw new Error("Cannot specify both exactTerms and excludeTerms - please use only one");
5305
- }
5306
- exactTerms && searchQuery.push(exactTerms.split("|").map((term) => `+${term}`).join(" AND "));
5307
- excludeTerms && searchQuery.push(excludeTerms.split("|").map((term) => `-${term}`).join(" AND "));
5308
- searchParams.append("query", searchQuery.join(" "));
5309
- for (const [name, value] of Object.entries(rest)) {
5310
- if (value)
5024
+ for (const [name, value] of Object.entries(searchQuery)) {
5025
+ if (value !== undefined && value !== null) {
5311
5026
  searchParams.append(name, `${value}`);
5027
+ }
5312
5028
  }
5313
5029
  url.search = searchParams.toString();
5314
5030
  const options = {
@@ -5334,39 +5050,119 @@ var fetchSearchResults = async ({
5334
5050
  return parsedResults;
5335
5051
  };
5336
5052
 
5337
- // src/commands/search.ts
5338
- var searchCommand = async (args) => {
5053
+ // src/shared/command-runner.ts
5054
+ import { parseArgs } from "node:util";
5055
+
5056
+ // src/shared/use-get-user-agents.ts
5057
+ var useGetUserAgent = (client = "") => () => `CLI/${package_default.version}(You.com;${client})`;
5058
+
5059
+ // src/shared/command-runner.ts
5060
+ var runCommand = async (args, config2) => {
5339
5061
  if (args.includes("--schema")) {
5340
- console.log(JSON.stringify(toJSONSchema(SearchQuerySchema)));
5062
+ console.log(JSON.stringify(toJSONSchema(config2.schema)));
5341
5063
  process.exit(0);
5342
5064
  }
5343
- const { values } = parseArgs3({
5065
+ const { values } = parseArgs({
5344
5066
  args,
5345
5067
  options: {
5346
5068
  json: { type: "string" },
5347
5069
  "api-key": { type: "string" },
5348
- client: { type: "string" }
5070
+ client: { type: "string" },
5071
+ "dry-run": { type: "boolean" }
5349
5072
  }
5350
5073
  });
5351
5074
  if (!values.json) {
5352
5075
  throw new Error("--json flag is required");
5353
5076
  }
5354
- const query = JSON.parse(values.json);
5077
+ const input = JSON.parse(values.json);
5355
5078
  const apiKey = values["api-key"];
5356
5079
  const client = values.client || process.env.YDC_CLIENT;
5357
5080
  const YDC_API_KEY = apiKey || process.env.YDC_API_KEY;
5358
5081
  if (!YDC_API_KEY) {
5359
5082
  throw new Error("YDC_API_KEY environment variable is required");
5360
5083
  }
5361
- const searchQuery = SearchQuerySchema.parse(query);
5362
- const response = await fetchSearchResults({
5363
- searchQuery,
5084
+ const validatedInput = config2.schema.parse(input);
5085
+ const getUserAgent = useGetUserAgent(client);
5086
+ if (values["dry-run"] && config2.dryRunHandler) {
5087
+ const dryRunResult = config2.dryRunHandler({
5088
+ input: validatedInput,
5089
+ YDC_API_KEY,
5090
+ getUserAgent
5091
+ });
5092
+ console.log(JSON.stringify(dryRunResult));
5093
+ return;
5094
+ }
5095
+ const response = await config2.handler({
5096
+ input: validatedInput,
5364
5097
  YDC_API_KEY,
5365
- getUserAgent: useGetUserAgent(client)
5098
+ getUserAgent
5366
5099
  });
5367
5100
  console.log(JSON.stringify(response));
5368
5101
  };
5369
5102
 
5103
+ // src/shared/dry-run-utils.ts
5104
+ var buildSearchRequest = ({
5105
+ searchQuery,
5106
+ YDC_API_KEY,
5107
+ getUserAgent
5108
+ }) => {
5109
+ const queryParams = {};
5110
+ for (const [name, value] of Object.entries(searchQuery)) {
5111
+ if (value !== undefined && value !== null) {
5112
+ queryParams[name] = `${value}`;
5113
+ }
5114
+ }
5115
+ return {
5116
+ url: SEARCH_API_URL,
5117
+ method: "GET",
5118
+ headers: {
5119
+ "X-API-Key": YDC_API_KEY,
5120
+ "User-Agent": getUserAgent()
5121
+ },
5122
+ queryParams
5123
+ };
5124
+ };
5125
+ var buildContentsRequest = ({
5126
+ contentsQuery: { urls, formats, format, crawl_timeout },
5127
+ YDC_API_KEY,
5128
+ getUserAgent
5129
+ }) => {
5130
+ const requestFormats = formats || (format ? [format] : ["markdown"]);
5131
+ const requestBody = {
5132
+ urls,
5133
+ formats: requestFormats
5134
+ };
5135
+ if (crawl_timeout !== undefined) {
5136
+ requestBody.crawl_timeout = crawl_timeout;
5137
+ }
5138
+ return {
5139
+ url: CONTENTS_API_URL,
5140
+ method: "POST",
5141
+ headers: {
5142
+ "X-API-Key": YDC_API_KEY,
5143
+ "Content-Type": "application/json",
5144
+ "User-Agent": getUserAgent()
5145
+ },
5146
+ body: JSON.stringify(requestBody)
5147
+ };
5148
+ };
5149
+ var buildDeepSearchRequest = ({
5150
+ deepSearchQuery,
5151
+ YDC_API_KEY,
5152
+ getUserAgent
5153
+ }) => {
5154
+ return {
5155
+ url: DEEP_SEARCH_API_URL,
5156
+ method: "POST",
5157
+ headers: {
5158
+ "X-API-Key": YDC_API_KEY,
5159
+ "Content-Type": "application/json",
5160
+ "User-Agent": getUserAgent()
5161
+ },
5162
+ body: JSON.stringify(deepSearchQuery)
5163
+ };
5164
+ };
5165
+
5370
5166
  // src/shared/generate-error-report-link.ts
5371
5167
  var generateErrorReportLink = ({
5372
5168
  errorMessage,
@@ -5406,7 +5202,7 @@ Usage: ydc <command> --json <json> [options]
5406
5202
 
5407
5203
  Commands:
5408
5204
  search Search the web with You.com
5409
- express Get AI answers with web context
5205
+ deep-search Perform deep research with comprehensive answers
5410
5206
  contents Extract content from URLs
5411
5207
 
5412
5208
  Global Options:
@@ -5414,6 +5210,7 @@ Global Options:
5414
5210
  --api-key <key> You.com API key (overrides YDC_API_KEY)
5415
5211
  --client <name> Client name for tracking and debugging
5416
5212
  --schema Output JSON schema for what can be passed to --json
5213
+ --dry-run Show request details without making API call
5417
5214
  --help, -h Show this help
5418
5215
 
5419
5216
  Environment Variables:
@@ -5426,36 +5223,69 @@ Output Format:
5426
5223
 
5427
5224
  Examples:
5428
5225
  ydc search --json '{"query":"AI developments"}' --client Openclaw
5429
- ydc express --json '{"input":"What happened today?","tools":[{"type":"web_search"}]}' --client MyAgent
5226
+ ydc deep-search --json '{"query":"What are the latest breakthroughs in AI?","search_effort":"high"}' --client MyAgent
5430
5227
  ydc contents --json '{"urls":["https://example.com"],"formats":["markdown"]}'
5431
5228
  ydc search --schema # Get JSON schema for search --json input
5229
+ ydc search --json '{"query":"AI"}' --dry-run # Inspect request without API call
5432
5230
  ydc search --json '{"query":"AI"}' | jq '.data.results.web[0].title'
5433
5231
 
5434
5232
  More info: https://github.com/youdotcom-oss/dx-toolkit/tree/main/packages/api
5435
5233
  `);
5436
5234
  process.exit(command ? 0 : 2);
5437
5235
  }
5438
- try {
5439
- switch (command) {
5440
- case "search":
5441
- await searchCommand(args);
5442
- break;
5443
- case "express":
5444
- await expressCommand(args);
5445
- break;
5446
- case "contents":
5447
- await contentsCommand(args);
5448
- break;
5449
- default:
5450
- console.error(`Unknown command: ${command}`);
5451
- console.error(`Run 'ydc --help' for usage`);
5452
- process.exit(2);
5236
+ var commands = {
5237
+ search: {
5238
+ schema: SearchQuerySchema,
5239
+ handler: ({
5240
+ input,
5241
+ YDC_API_KEY,
5242
+ getUserAgent
5243
+ }) => fetchSearchResults({ searchQuery: input, YDC_API_KEY, getUserAgent }),
5244
+ dryRunHandler: ({
5245
+ input,
5246
+ YDC_API_KEY,
5247
+ getUserAgent
5248
+ }) => buildSearchRequest({ searchQuery: input, YDC_API_KEY, getUserAgent })
5249
+ },
5250
+ "deep-search": {
5251
+ schema: DeepSearchQuerySchema,
5252
+ handler: ({
5253
+ input,
5254
+ YDC_API_KEY,
5255
+ getUserAgent
5256
+ }) => callDeepSearch({ deepSearchQuery: input, YDC_API_KEY, getUserAgent }),
5257
+ dryRunHandler: ({
5258
+ input,
5259
+ YDC_API_KEY,
5260
+ getUserAgent
5261
+ }) => buildDeepSearchRequest({ deepSearchQuery: input, YDC_API_KEY, getUserAgent })
5262
+ },
5263
+ contents: {
5264
+ schema: ContentsQuerySchema,
5265
+ handler: ({
5266
+ input,
5267
+ YDC_API_KEY,
5268
+ getUserAgent
5269
+ }) => fetchContents({ contentsQuery: input, YDC_API_KEY, getUserAgent }),
5270
+ dryRunHandler: ({
5271
+ input,
5272
+ YDC_API_KEY,
5273
+ getUserAgent
5274
+ }) => buildContentsRequest({ contentsQuery: input, YDC_API_KEY, getUserAgent })
5453
5275
  }
5276
+ };
5277
+ if (!(command in commands)) {
5278
+ console.error(`Unknown command: ${command}`);
5279
+ console.error(`Run 'ydc --help' for usage`);
5280
+ process.exit(2);
5281
+ }
5282
+ try {
5283
+ await runCommand(args, commands[command]);
5454
5284
  process.exit(0);
5455
5285
  } catch (error2) {
5456
5286
  console.error(error2);
5457
5287
  const message = error2 instanceof Error ? error2.message : String(error2);
5458
- const { values } = parseArgs4({
5288
+ const { values } = parseArgs2({
5459
5289
  args,
5460
5290
  options: {
5461
5291
  client: { type: "string" }