@youdotcom-oss/api 0.1.0 → 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/README.md +36 -36
- package/bin/cli.js +233 -403
- package/package.json +2 -2
- package/src/cli.ts +92 -21
- package/src/contents/contents.schemas.ts +8 -7
- package/src/contents/tests/contents.request.spec.ts +109 -0
- package/src/contents/tests/contents.schema-validation.spec.ts +75 -0
- package/src/deep-search/deep-search.schemas.ts +48 -0
- package/src/deep-search/deep-search.utils.ts +75 -0
- package/src/main.ts +4 -3
- package/src/search/search.schemas.ts +65 -6
- package/src/search/search.utils.ts +6 -28
- package/src/search/tests/search.request.spec.ts +122 -0
- package/src/search/tests/search.schema-validation.spec.ts +152 -0
- package/src/search/tests/{search.utils.spec.ts → search.utils.docker.ts} +0 -10
- package/src/shared/api.constants.ts +1 -1
- package/src/shared/check-response-for-errors.ts +1 -1
- package/src/shared/command-runner.ts +95 -0
- package/src/shared/dry-run-utils.ts +141 -0
- package/src/shared/tests/command-runner.spec.ts +210 -0
- package/src/shared/use-get-user-agents.ts +1 -1
- package/src/commands/contents.ts +0 -52
- package/src/commands/express.ts +0 -52
- package/src/commands/search.ts +0 -52
- package/src/express/express.schemas.ts +0 -85
- package/src/express/express.utils.ts +0 -113
- package/src/express/tests/express.utils.spec.ts +0 -83
- /package/src/contents/tests/{contents.utils.spec.ts → contents.utils.docker.ts} +0 -0
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
|
|
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.
|
|
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: {
|
|
@@ -78,13 +78,10 @@ var package_default = {
|
|
|
78
78
|
"test:watch": "bun test --watch"
|
|
79
79
|
},
|
|
80
80
|
dependencies: {
|
|
81
|
-
zod: "^4.3.
|
|
81
|
+
zod: "^4.3.6"
|
|
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
|
-
|
|
4934
|
-
|
|
4935
|
-
|
|
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
|
|
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/
|
|
5011
|
-
var
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
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
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
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
|
|
5066
|
-
|
|
5067
|
-
|
|
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/
|
|
5098
|
-
var
|
|
5099
|
-
|
|
5100
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
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
|
|
5300
|
-
|
|
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/
|
|
5338
|
-
|
|
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(
|
|
5062
|
+
console.log(JSON.stringify(toJSONSchema(config2.schema)));
|
|
5341
5063
|
process.exit(0);
|
|
5342
5064
|
}
|
|
5343
|
-
const { values } =
|
|
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
|
|
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
|
|
5362
|
-
const
|
|
5363
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
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 } =
|
|
5288
|
+
const { values } = parseArgs2({
|
|
5459
5289
|
args,
|
|
5460
5290
|
options: {
|
|
5461
5291
|
client: { type: "string" }
|