@youdotcom-oss/api 0.1.1 → 0.2.1
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 -400
- package/package.json +1 -1
- 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 +79 -0
- package/src/deep-search/tests/deep-search.request.spec.ts +109 -0
- package/src/deep-search/tests/deep-search.schema-validation.spec.ts +71 -0
- package/src/deep-search/tests/deep-search.utils.docker.ts +139 -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.1",
|
|
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
|
-
|
|
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,101 @@ 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)")
|
|
5055
|
-
});
|
|
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()
|
|
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)")
|
|
5064
4845
|
});
|
|
5065
|
-
var
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
|
|
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")
|
|
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")
|
|
5088
4850
|
});
|
|
5089
|
-
var
|
|
5090
|
-
answer: string2().describe("
|
|
5091
|
-
results:
|
|
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
|
-
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 ({
|
|
4856
|
+
// src/deep-search/deep-search.utils.ts
|
|
4857
|
+
var callDeepSearch = async ({
|
|
4858
|
+
deepSearchQuery,
|
|
5114
4859
|
YDC_API_KEY = process.env.YDC_API_KEY,
|
|
5115
|
-
agentInput: { input, tools },
|
|
5116
4860
|
getUserAgent
|
|
5117
4861
|
}) => {
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
input,
|
|
5121
|
-
stream: false
|
|
5122
|
-
};
|
|
5123
|
-
if (tools) {
|
|
5124
|
-
requestBody.tools = tools;
|
|
4862
|
+
if (!YDC_API_KEY) {
|
|
4863
|
+
throw new Error("YDC_API_KEY is required for Deep Search API");
|
|
5125
4864
|
}
|
|
5126
|
-
const
|
|
4865
|
+
const response = await fetch(DEEP_SEARCH_API_URL, {
|
|
5127
4866
|
method: "POST",
|
|
5128
4867
|
headers: new Headers({
|
|
5129
|
-
|
|
4868
|
+
"X-API-Key": YDC_API_KEY,
|
|
5130
4869
|
"Content-Type": "application/json",
|
|
5131
|
-
Accept: "application/json",
|
|
5132
4870
|
"User-Agent": getUserAgent()
|
|
5133
4871
|
}),
|
|
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)
|
|
4872
|
+
body: JSON.stringify(deepSearchQuery)
|
|
5193
4873
|
});
|
|
5194
|
-
|
|
4874
|
+
await checkResponseForErrors(response);
|
|
4875
|
+
const data = await response.json();
|
|
4876
|
+
return DeepSearchResponseSchema.parse(data);
|
|
5195
4877
|
};
|
|
5196
4878
|
|
|
5197
|
-
// src/commands/search.ts
|
|
5198
|
-
import { parseArgs as parseArgs3 } from "node:util";
|
|
5199
|
-
|
|
5200
4879
|
// src/search/search.schemas.ts
|
|
4880
|
+
var LanguageSchema = _enum([
|
|
4881
|
+
"AR",
|
|
4882
|
+
"EU",
|
|
4883
|
+
"BN",
|
|
4884
|
+
"BG",
|
|
4885
|
+
"CA",
|
|
4886
|
+
"ZH-HANS",
|
|
4887
|
+
"ZH-HANT",
|
|
4888
|
+
"HR",
|
|
4889
|
+
"CS",
|
|
4890
|
+
"DA",
|
|
4891
|
+
"NL",
|
|
4892
|
+
"EN",
|
|
4893
|
+
"EN-GB",
|
|
4894
|
+
"ET",
|
|
4895
|
+
"FI",
|
|
4896
|
+
"FR",
|
|
4897
|
+
"GL",
|
|
4898
|
+
"DE",
|
|
4899
|
+
"EL",
|
|
4900
|
+
"GU",
|
|
4901
|
+
"HE",
|
|
4902
|
+
"HI",
|
|
4903
|
+
"HU",
|
|
4904
|
+
"IS",
|
|
4905
|
+
"IT",
|
|
4906
|
+
"JP",
|
|
4907
|
+
"KN",
|
|
4908
|
+
"KO",
|
|
4909
|
+
"LV",
|
|
4910
|
+
"LT",
|
|
4911
|
+
"MS",
|
|
4912
|
+
"ML",
|
|
4913
|
+
"MR",
|
|
4914
|
+
"NB",
|
|
4915
|
+
"PL",
|
|
4916
|
+
"PT-BR",
|
|
4917
|
+
"PT-PT",
|
|
4918
|
+
"PA",
|
|
4919
|
+
"RO",
|
|
4920
|
+
"RU",
|
|
4921
|
+
"SR",
|
|
4922
|
+
"SK",
|
|
4923
|
+
"SL",
|
|
4924
|
+
"ES",
|
|
4925
|
+
"SV",
|
|
4926
|
+
"TA",
|
|
4927
|
+
"TE",
|
|
4928
|
+
"TH",
|
|
4929
|
+
"TR",
|
|
4930
|
+
"UK",
|
|
4931
|
+
"VI"
|
|
4932
|
+
]);
|
|
5201
4933
|
var SearchQuerySchema = object({
|
|
5202
|
-
query: string2().min(1, "Query is required").describe(
|
|
4934
|
+
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
4935
|
count: number2().int().min(1).max(100).optional().describe("Max results per section"),
|
|
5204
4936
|
freshness: string2().optional().describe("day/week/month/year or YYYY-MM-DDtoYYYY-MM-DD"),
|
|
5205
4937
|
offset: number2().int().min(0).max(9).optional().describe("Pagination offset"),
|
|
@@ -5229,6 +4961,7 @@ var SearchQuerySchema = object({
|
|
|
5229
4961
|
"CN",
|
|
5230
4962
|
"PL",
|
|
5231
4963
|
"PT",
|
|
4964
|
+
"PT-BR",
|
|
5232
4965
|
"PH",
|
|
5233
4966
|
"RU",
|
|
5234
4967
|
"SA",
|
|
@@ -5242,11 +4975,6 @@ var SearchQuerySchema = object({
|
|
|
5242
4975
|
"US"
|
|
5243
4976
|
]).optional().describe("Country code"),
|
|
5244
4977
|
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
4978
|
livecrawl: _enum(["web", "news", "all"]).optional().describe("Live-crawl sections for full content"),
|
|
5251
4979
|
livecrawl_formats: _enum(["html", "markdown"]).optional().describe("Format for crawled content")
|
|
5252
4980
|
});
|
|
@@ -5291,24 +5019,15 @@ var SearchResponseSchema = object({
|
|
|
5291
5019
|
// src/search/search.utils.ts
|
|
5292
5020
|
var fetchSearchResults = async ({
|
|
5293
5021
|
YDC_API_KEY = process.env.YDC_API_KEY,
|
|
5294
|
-
searchQuery
|
|
5022
|
+
searchQuery,
|
|
5295
5023
|
getUserAgent
|
|
5296
5024
|
}) => {
|
|
5297
5025
|
const url = new URL(SEARCH_API_URL);
|
|
5298
5026
|
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)
|
|
5027
|
+
for (const [name, value] of Object.entries(searchQuery)) {
|
|
5028
|
+
if (value !== undefined && value !== null) {
|
|
5311
5029
|
searchParams.append(name, `${value}`);
|
|
5030
|
+
}
|
|
5312
5031
|
}
|
|
5313
5032
|
url.search = searchParams.toString();
|
|
5314
5033
|
const options = {
|
|
@@ -5334,39 +5053,119 @@ var fetchSearchResults = async ({
|
|
|
5334
5053
|
return parsedResults;
|
|
5335
5054
|
};
|
|
5336
5055
|
|
|
5337
|
-
// src/
|
|
5338
|
-
|
|
5056
|
+
// src/shared/command-runner.ts
|
|
5057
|
+
import { parseArgs } from "node:util";
|
|
5058
|
+
|
|
5059
|
+
// src/shared/use-get-user-agents.ts
|
|
5060
|
+
var useGetUserAgent = (client = "") => () => `CLI/${package_default.version}(You.com;${client})`;
|
|
5061
|
+
|
|
5062
|
+
// src/shared/command-runner.ts
|
|
5063
|
+
var runCommand = async (args, config2) => {
|
|
5339
5064
|
if (args.includes("--schema")) {
|
|
5340
|
-
console.log(JSON.stringify(toJSONSchema(
|
|
5065
|
+
console.log(JSON.stringify(toJSONSchema(config2.schema)));
|
|
5341
5066
|
process.exit(0);
|
|
5342
5067
|
}
|
|
5343
|
-
const { values } =
|
|
5068
|
+
const { values } = parseArgs({
|
|
5344
5069
|
args,
|
|
5345
5070
|
options: {
|
|
5346
5071
|
json: { type: "string" },
|
|
5347
5072
|
"api-key": { type: "string" },
|
|
5348
|
-
client: { type: "string" }
|
|
5073
|
+
client: { type: "string" },
|
|
5074
|
+
"dry-run": { type: "boolean" }
|
|
5349
5075
|
}
|
|
5350
5076
|
});
|
|
5351
5077
|
if (!values.json) {
|
|
5352
5078
|
throw new Error("--json flag is required");
|
|
5353
5079
|
}
|
|
5354
|
-
const
|
|
5080
|
+
const input = JSON.parse(values.json);
|
|
5355
5081
|
const apiKey = values["api-key"];
|
|
5356
5082
|
const client = values.client || process.env.YDC_CLIENT;
|
|
5357
5083
|
const YDC_API_KEY = apiKey || process.env.YDC_API_KEY;
|
|
5358
5084
|
if (!YDC_API_KEY) {
|
|
5359
5085
|
throw new Error("YDC_API_KEY environment variable is required");
|
|
5360
5086
|
}
|
|
5361
|
-
const
|
|
5362
|
-
const
|
|
5363
|
-
|
|
5087
|
+
const validatedInput = config2.schema.parse(input);
|
|
5088
|
+
const getUserAgent = useGetUserAgent(client);
|
|
5089
|
+
if (values["dry-run"] && config2.dryRunHandler) {
|
|
5090
|
+
const dryRunResult = config2.dryRunHandler({
|
|
5091
|
+
input: validatedInput,
|
|
5092
|
+
YDC_API_KEY,
|
|
5093
|
+
getUserAgent
|
|
5094
|
+
});
|
|
5095
|
+
console.log(JSON.stringify(dryRunResult));
|
|
5096
|
+
return;
|
|
5097
|
+
}
|
|
5098
|
+
const response = await config2.handler({
|
|
5099
|
+
input: validatedInput,
|
|
5364
5100
|
YDC_API_KEY,
|
|
5365
|
-
getUserAgent
|
|
5101
|
+
getUserAgent
|
|
5366
5102
|
});
|
|
5367
5103
|
console.log(JSON.stringify(response));
|
|
5368
5104
|
};
|
|
5369
5105
|
|
|
5106
|
+
// src/shared/dry-run-utils.ts
|
|
5107
|
+
var buildSearchRequest = ({
|
|
5108
|
+
searchQuery,
|
|
5109
|
+
YDC_API_KEY,
|
|
5110
|
+
getUserAgent
|
|
5111
|
+
}) => {
|
|
5112
|
+
const queryParams = {};
|
|
5113
|
+
for (const [name, value] of Object.entries(searchQuery)) {
|
|
5114
|
+
if (value !== undefined && value !== null) {
|
|
5115
|
+
queryParams[name] = `${value}`;
|
|
5116
|
+
}
|
|
5117
|
+
}
|
|
5118
|
+
return {
|
|
5119
|
+
url: SEARCH_API_URL,
|
|
5120
|
+
method: "GET",
|
|
5121
|
+
headers: {
|
|
5122
|
+
"X-API-Key": YDC_API_KEY,
|
|
5123
|
+
"User-Agent": getUserAgent()
|
|
5124
|
+
},
|
|
5125
|
+
queryParams
|
|
5126
|
+
};
|
|
5127
|
+
};
|
|
5128
|
+
var buildContentsRequest = ({
|
|
5129
|
+
contentsQuery: { urls, formats, format, crawl_timeout },
|
|
5130
|
+
YDC_API_KEY,
|
|
5131
|
+
getUserAgent
|
|
5132
|
+
}) => {
|
|
5133
|
+
const requestFormats = formats || (format ? [format] : ["markdown"]);
|
|
5134
|
+
const requestBody = {
|
|
5135
|
+
urls,
|
|
5136
|
+
formats: requestFormats
|
|
5137
|
+
};
|
|
5138
|
+
if (crawl_timeout !== undefined) {
|
|
5139
|
+
requestBody.crawl_timeout = crawl_timeout;
|
|
5140
|
+
}
|
|
5141
|
+
return {
|
|
5142
|
+
url: CONTENTS_API_URL,
|
|
5143
|
+
method: "POST",
|
|
5144
|
+
headers: {
|
|
5145
|
+
"X-API-Key": YDC_API_KEY,
|
|
5146
|
+
"Content-Type": "application/json",
|
|
5147
|
+
"User-Agent": getUserAgent()
|
|
5148
|
+
},
|
|
5149
|
+
body: JSON.stringify(requestBody)
|
|
5150
|
+
};
|
|
5151
|
+
};
|
|
5152
|
+
var buildDeepSearchRequest = ({
|
|
5153
|
+
deepSearchQuery,
|
|
5154
|
+
YDC_API_KEY,
|
|
5155
|
+
getUserAgent
|
|
5156
|
+
}) => {
|
|
5157
|
+
return {
|
|
5158
|
+
url: DEEP_SEARCH_API_URL,
|
|
5159
|
+
method: "POST",
|
|
5160
|
+
headers: {
|
|
5161
|
+
"X-API-Key": YDC_API_KEY,
|
|
5162
|
+
"Content-Type": "application/json",
|
|
5163
|
+
"User-Agent": getUserAgent()
|
|
5164
|
+
},
|
|
5165
|
+
body: JSON.stringify(deepSearchQuery)
|
|
5166
|
+
};
|
|
5167
|
+
};
|
|
5168
|
+
|
|
5370
5169
|
// src/shared/generate-error-report-link.ts
|
|
5371
5170
|
var generateErrorReportLink = ({
|
|
5372
5171
|
errorMessage,
|
|
@@ -5406,7 +5205,7 @@ Usage: ydc <command> --json <json> [options]
|
|
|
5406
5205
|
|
|
5407
5206
|
Commands:
|
|
5408
5207
|
search Search the web with You.com
|
|
5409
|
-
|
|
5208
|
+
deep-search Perform deep research with comprehensive answers
|
|
5410
5209
|
contents Extract content from URLs
|
|
5411
5210
|
|
|
5412
5211
|
Global Options:
|
|
@@ -5414,6 +5213,7 @@ Global Options:
|
|
|
5414
5213
|
--api-key <key> You.com API key (overrides YDC_API_KEY)
|
|
5415
5214
|
--client <name> Client name for tracking and debugging
|
|
5416
5215
|
--schema Output JSON schema for what can be passed to --json
|
|
5216
|
+
--dry-run Show request details without making API call
|
|
5417
5217
|
--help, -h Show this help
|
|
5418
5218
|
|
|
5419
5219
|
Environment Variables:
|
|
@@ -5426,36 +5226,69 @@ Output Format:
|
|
|
5426
5226
|
|
|
5427
5227
|
Examples:
|
|
5428
5228
|
ydc search --json '{"query":"AI developments"}' --client Openclaw
|
|
5429
|
-
ydc
|
|
5229
|
+
ydc deep-search --json '{"query":"What are the latest breakthroughs in AI?","search_effort":"high"}' --client MyAgent
|
|
5430
5230
|
ydc contents --json '{"urls":["https://example.com"],"formats":["markdown"]}'
|
|
5431
5231
|
ydc search --schema # Get JSON schema for search --json input
|
|
5232
|
+
ydc search --json '{"query":"AI"}' --dry-run # Inspect request without API call
|
|
5432
5233
|
ydc search --json '{"query":"AI"}' | jq '.data.results.web[0].title'
|
|
5433
5234
|
|
|
5434
5235
|
More info: https://github.com/youdotcom-oss/dx-toolkit/tree/main/packages/api
|
|
5435
5236
|
`);
|
|
5436
5237
|
process.exit(command ? 0 : 2);
|
|
5437
5238
|
}
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5239
|
+
var commands = {
|
|
5240
|
+
search: {
|
|
5241
|
+
schema: SearchQuerySchema,
|
|
5242
|
+
handler: ({
|
|
5243
|
+
input,
|
|
5244
|
+
YDC_API_KEY,
|
|
5245
|
+
getUserAgent
|
|
5246
|
+
}) => fetchSearchResults({ searchQuery: input, YDC_API_KEY, getUserAgent }),
|
|
5247
|
+
dryRunHandler: ({
|
|
5248
|
+
input,
|
|
5249
|
+
YDC_API_KEY,
|
|
5250
|
+
getUserAgent
|
|
5251
|
+
}) => buildSearchRequest({ searchQuery: input, YDC_API_KEY, getUserAgent })
|
|
5252
|
+
},
|
|
5253
|
+
"deep-search": {
|
|
5254
|
+
schema: DeepSearchQuerySchema,
|
|
5255
|
+
handler: ({
|
|
5256
|
+
input,
|
|
5257
|
+
YDC_API_KEY,
|
|
5258
|
+
getUserAgent
|
|
5259
|
+
}) => callDeepSearch({ deepSearchQuery: input, YDC_API_KEY, getUserAgent }),
|
|
5260
|
+
dryRunHandler: ({
|
|
5261
|
+
input,
|
|
5262
|
+
YDC_API_KEY,
|
|
5263
|
+
getUserAgent
|
|
5264
|
+
}) => buildDeepSearchRequest({ deepSearchQuery: input, YDC_API_KEY, getUserAgent })
|
|
5265
|
+
},
|
|
5266
|
+
contents: {
|
|
5267
|
+
schema: ContentsQuerySchema,
|
|
5268
|
+
handler: ({
|
|
5269
|
+
input,
|
|
5270
|
+
YDC_API_KEY,
|
|
5271
|
+
getUserAgent
|
|
5272
|
+
}) => fetchContents({ contentsQuery: input, YDC_API_KEY, getUserAgent }),
|
|
5273
|
+
dryRunHandler: ({
|
|
5274
|
+
input,
|
|
5275
|
+
YDC_API_KEY,
|
|
5276
|
+
getUserAgent
|
|
5277
|
+
}) => buildContentsRequest({ contentsQuery: input, YDC_API_KEY, getUserAgent })
|
|
5453
5278
|
}
|
|
5279
|
+
};
|
|
5280
|
+
if (!(command in commands)) {
|
|
5281
|
+
console.error(`Unknown command: ${command}`);
|
|
5282
|
+
console.error(`Run 'ydc --help' for usage`);
|
|
5283
|
+
process.exit(2);
|
|
5284
|
+
}
|
|
5285
|
+
try {
|
|
5286
|
+
await runCommand(args, commands[command]);
|
|
5454
5287
|
process.exit(0);
|
|
5455
5288
|
} catch (error2) {
|
|
5456
5289
|
console.error(error2);
|
|
5457
5290
|
const message = error2 instanceof Error ? error2.message : String(error2);
|
|
5458
|
-
const { values } =
|
|
5291
|
+
const { values } = parseArgs2({
|
|
5459
5292
|
args,
|
|
5460
5293
|
options: {
|
|
5461
5294
|
client: { type: "string" }
|