@search1api/ai-sdk 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -36,19 +36,28 @@ The tool set has three entries:
36
36
 
37
37
  | Tool | Model input | API | Output |
38
38
  | --- | --- | --- | --- |
39
- | `search` | `{ query }` | `/search` | Typed results with titles, links, and snippets |
40
- | `news` | `{ query }` | `/news` | Typed news results and source links |
39
+ | `search` | `{ query, search_service?, max_results?, include_sites?, exclude_sites?, time_range? }` | `/search` | Typed results with titles, links, and snippets |
40
+ | `news` | Same fields as `search`, with news engines | `/news` | Typed news results and source links |
41
41
  | `crawl` | `{ url }` | `/crawl` | A page's title, URL, and readable content |
42
42
 
43
+ The model-facing parameters match the
44
+ [Search1API MCP server](https://s1.dev/docs/integrations/mcp). The model can
45
+ pick an engine (`google`, `bing`, `duckduckgo`, `yahoo`, `x`, `reddit`, `github`,
46
+ `youtube`, `arxiv`, `wechat`, `bilibili`, `imdb`, `wikipedia`; news supports
47
+ `google`, `bing`, `duckduckgo`, `yahoo`, and `hackernews`), return 1–50 results,
48
+ scope or exclude domains, and limit results to the past day, month, or year.
49
+ Result page crawling is not exposed to the model. Unknown arguments are ignored
50
+ rather than failing the call.
51
+
43
52
  Outputs preserve the API response, including optional publication dates,
44
53
  metadata, and content. Empty results remain empty. Ask the model to cite the
45
54
  returned links; these tools do not add AI SDK source events automatically.
46
55
 
47
56
  ## Configure one tool
48
57
 
49
- Applications control the engine, result count, domains, language, and time
50
- window. The model sees only the query or URL, so it cannot change those settings
51
- or enable extra result crawling.
58
+ Settings passed in code are defaults. When the model supplies the same
59
+ parameter, the model's value is used for that call; anything it omits falls
60
+ back to your settings.
52
61
 
53
62
  ```ts
54
63
  import { search1apiSearch, search1apiCrawl } from '@search1api/ai-sdk';
@@ -72,8 +81,8 @@ const tools = search1apiTools({
72
81
  });
73
82
  ```
74
83
 
75
- Search and news default to five results with `crawlResults: 0`. Set
76
- `search.crawlResults` or `news.crawlResults` explicitly when you want result page
84
+ Search and news default to ten results with `crawlResults: 0`. Set
85
+ `search.crawlResults` or `news.crawlResults` in code when you want result page
77
86
  content included. Each successful page retrieval incurs a separate crawl charge;
78
87
  see [pricing](https://s1.dev/pricing).
79
88
 
@@ -128,6 +137,9 @@ npm run test:compatibility
128
137
  npm pack --dry-run
129
138
  ```
130
139
 
140
+ To verify the current version from the public registry, run
141
+ `node scripts/verify-package.mjs --registry` after publication.
142
+
131
143
  To validate a local build, create and install the tarball with
132
144
  `npm pack` and `npm install /absolute/path/search1api-ai-sdk-0.1.0.tgz`.
133
145
  Publication tracking is in [RELEASE.md](https://github.com/superagents-lab/search1api-ai-sdk/blob/main/RELEASE.md).
package/dist/index.cjs CHANGED
@@ -29,15 +29,73 @@ module.exports = __toCommonJS(index_exports);
29
29
  var import_client = require("@search1api/client");
30
30
  var import_ai = require("ai");
31
31
  var import_zod = require("zod");
32
- var querySchema = import_zod.z.object({
33
- query: import_zod.z.string().trim().min(1).describe("Search keywords or a specific question.")
34
- }).strict();
32
+ var SEARCH_ENGINES = [
33
+ "google",
34
+ "bing",
35
+ "duckduckgo",
36
+ "yahoo",
37
+ "x",
38
+ "reddit",
39
+ "github",
40
+ "youtube",
41
+ "arxiv",
42
+ "wechat",
43
+ "bilibili",
44
+ "imdb",
45
+ "wikipedia"
46
+ ];
47
+ var NEWS_ENGINES = [
48
+ "google",
49
+ "bing",
50
+ "duckduckgo",
51
+ "yahoo",
52
+ "hackernews"
53
+ ];
54
+ function queryFields(kind) {
55
+ const noun = kind === "search" ? "results" : "articles";
56
+ return {
57
+ query: import_zod.z.string().trim().min(1).describe(`Short, focused ${kind} query`),
58
+ max_results: import_zod.z.number().int().min(1).max(50).optional().describe(`Maximum number of ${noun} to return`),
59
+ include_sites: import_zod.z.array(import_zod.z.string()).optional().describe(
60
+ kind === "search" ? "Domains to include when the user explicitly scopes the search" : "News domains to include"
61
+ ),
62
+ exclude_sites: import_zod.z.array(import_zod.z.string()).optional().describe(
63
+ kind === "search" ? "Domains to exclude from the search" : "News domains to exclude"
64
+ ),
65
+ time_range: import_zod.z.enum(["day", "month", "year"]).optional().describe(
66
+ kind === "search" ? "Optional recency window for time-sensitive searches" : "Optional recency window; use day for breaking news"
67
+ )
68
+ };
69
+ }
70
+ var searchSchema = import_zod.z.object({
71
+ ...queryFields("search"),
72
+ search_service: import_zod.z.enum(SEARCH_ENGINES).optional().describe(
73
+ "Search engine to use; choose one only when it matches the user's source intent"
74
+ )
75
+ });
76
+ var newsSchema = import_zod.z.object({
77
+ ...queryFields("news"),
78
+ search_service: import_zod.z.enum(NEWS_ENGINES).optional().describe("News search engine to use")
79
+ });
35
80
  var crawlSchema = import_zod.z.object({
36
81
  url: import_zod.z.string().url().refine(
37
82
  (url) => ["http:", "https:"].includes(new URL(url).protocol),
38
83
  "Use an HTTP or HTTPS URL."
39
- ).describe("A public webpage URL, for example a link returned by search.")
40
- }).strict();
84
+ ).describe("Public HTTP or HTTPS URL to retrieve")
85
+ });
86
+ function requestOptions(defaults, input) {
87
+ const fromModel = {
88
+ searchService: input.search_service,
89
+ maxResults: input.max_results,
90
+ includeSites: input.include_sites,
91
+ excludeSites: input.exclude_sites,
92
+ timeRange: input.time_range
93
+ };
94
+ const overrides = Object.fromEntries(
95
+ Object.entries(fromModel).filter(([, value]) => value !== void 0)
96
+ );
97
+ return { ...defaults, ...overrides };
98
+ }
41
99
  function clientGetter(options) {
42
100
  let client = options.client;
43
101
  const { client: _client, ...settings } = options;
@@ -54,26 +112,40 @@ function clientGetter(options) {
54
112
  };
55
113
  }
56
114
  function searchTool(getClient, settings = {}) {
57
- const options = { maxResults: 5, crawlResults: 0, ...settings };
115
+ const defaults = {
116
+ maxResults: 10,
117
+ crawlResults: 0,
118
+ ...settings
119
+ };
58
120
  return (0, import_ai.tool)({
59
- description: "Search the public web for current information and sources. Returns titles, links, and snippets. Use crawl to read a result page in full.",
60
- inputSchema: querySchema,
121
+ description: "Search the live public web when the user needs current information, sources, or research. Returns titles, links, and snippets. Use crawl to read a result page in full.",
122
+ inputSchema: searchSchema,
61
123
  execute: async (input, { abortSignal }) => {
62
124
  abortSignal?.throwIfAborted();
63
- const { query } = querySchema.parse(input);
64
- return getClient().search(query, options, { signal: abortSignal });
125
+ const parsed = searchSchema.parse(input);
126
+ return getClient().search(
127
+ parsed.query,
128
+ requestOptions(defaults, parsed),
129
+ { signal: abortSignal }
130
+ );
65
131
  }
66
132
  });
67
133
  }
68
134
  function newsTool(getClient, settings = {}) {
69
- const options = { maxResults: 5, crawlResults: 0, ...settings };
135
+ const defaults = {
136
+ maxResults: 10,
137
+ crawlResults: 0,
138
+ ...settings
139
+ };
70
140
  return (0, import_ai.tool)({
71
- description: "Search news coverage of recent events and announcements. Returns article titles, links, and snippets. Use crawl to read an article in full.",
72
- inputSchema: querySchema,
141
+ description: "Search current news when the user asks about recent events, announcements, or coverage. Returns article titles, links, and snippets. Use crawl to read an article in full.",
142
+ inputSchema: newsSchema,
73
143
  execute: async (input, { abortSignal }) => {
74
144
  abortSignal?.throwIfAborted();
75
- const { query } = querySchema.parse(input);
76
- return getClient().news(query, options, { signal: abortSignal });
145
+ const parsed = newsSchema.parse(input);
146
+ return getClient().news(parsed.query, requestOptions(defaults, parsed), {
147
+ signal: abortSignal
148
+ });
77
149
  }
78
150
  });
79
151
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import { Search1API } from '@search1api/client';\nimport type {\n CrawlOptions,\n CrawlResponse,\n NewsOptions,\n NewsResponse,\n Search1APIOptions,\n SearchOptions,\n SearchResponse,\n} from '@search1api/client';\nimport { tool } from 'ai';\nimport type { Tool } from 'ai';\nimport { z } from 'zod';\n\nexport interface Search1APIToolOptions extends Search1APIOptions {\n /** Reuse an existing client. When supplied, other client options are ignored. */\n client?: Search1API;\n}\n\nexport interface Search1APISearchOptions extends Search1APIToolOptions {\n /** Application-owned search settings; the model only supplies the query. */\n search?: SearchOptions;\n}\n\nexport interface Search1APINewsOptions extends Search1APIToolOptions {\n /** Application-owned news settings; the model only supplies the query. */\n news?: NewsOptions;\n}\n\nexport interface Search1APICrawlOptions extends Search1APIToolOptions {\n crawl?: CrawlOptions;\n}\n\nexport type QueryInput = { query: string };\nexport type CrawlInput = { url: string };\n\nconst querySchema = z\n .object({\n query: z\n .string()\n .trim()\n .min(1)\n .describe('Search keywords or a specific question.'),\n })\n .strict();\n\nconst crawlSchema = z\n .object({\n url: z\n .string()\n .url()\n .refine(\n (url) => ['http:', 'https:'].includes(new URL(url).protocol),\n 'Use an HTTP or HTTPS URL.'\n )\n .describe('A public webpage URL, for example a link returned by search.'),\n })\n .strict();\n\ntype ClientGetter = () => Search1API;\n\nfunction clientGetter(options: Search1APIToolOptions): ClientGetter {\n let client = options.client;\n const { client: _client, ...settings } = options;\n return () => {\n if (!client) {\n const processLike = globalThis as typeof globalThis & {\n process?: { env?: Record<string, string | undefined> };\n };\n const env = processLike.process?.env;\n client = new Search1API({\n ...settings,\n apiKey:\n settings.apiKey || env?.SEARCH1API_API_KEY || env?.SEARCH1API_KEY,\n });\n }\n return client;\n };\n}\n\nfunction searchTool(\n getClient: ClientGetter,\n settings: SearchOptions = {}\n): Tool<QueryInput, SearchResponse> {\n const options = { maxResults: 5, crawlResults: 0, ...settings };\n return tool({\n description:\n 'Search the public web for current information and sources. Returns titles, links, and snippets. Use crawl to read a result page in full.',\n inputSchema: querySchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { query } = querySchema.parse(input);\n return getClient().search(query, options, { signal: abortSignal });\n },\n });\n}\n\nfunction newsTool(\n getClient: ClientGetter,\n settings: NewsOptions = {}\n): Tool<QueryInput, NewsResponse> {\n const options = { maxResults: 5, crawlResults: 0, ...settings };\n return tool({\n description:\n 'Search news coverage of recent events and announcements. Returns article titles, links, and snippets. Use crawl to read an article in full.',\n inputSchema: querySchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { query } = querySchema.parse(input);\n return getClient().news(query, options, { signal: abortSignal });\n },\n });\n}\n\nfunction crawlTool(\n getClient: ClientGetter,\n settings: CrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n const options = { ...settings };\n return tool({\n description:\n 'Read one public webpage and return its title, source URL, and readable content. Use a URL supplied by the user or returned by search or news.',\n inputSchema: crawlSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { url } = crawlSchema.parse(input);\n return getClient().crawl(url, options, { signal: abortSignal });\n },\n });\n}\n\nexport function search1apiSearch(\n options: Search1APISearchOptions = {}\n): Tool<QueryInput, SearchResponse> {\n return searchTool(clientGetter(options), options.search);\n}\n\nexport function search1apiNews(\n options: Search1APINewsOptions = {}\n): Tool<QueryInput, NewsResponse> {\n return newsTool(clientGetter(options), options.news);\n}\n\nexport function search1apiCrawl(\n options: Search1APICrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n return crawlTool(clientGetter(options), options.crawl);\n}\n\nexport interface Search1APIToolSet {\n search: Tool<QueryInput, SearchResponse>;\n news: Tool<QueryInput, NewsResponse>;\n crawl: Tool<CrawlInput, CrawlResponse>;\n}\n\nexport type Search1APIToolName = keyof Search1APIToolSet;\n\nexport interface Search1APIToolsOptions<\n Name extends Search1APIToolName = Search1APIToolName,\n> extends Search1APIToolOptions {\n /** Include only these tools. By default all three are included. */\n only?: readonly Name[];\n search?: SearchOptions;\n news?: NewsOptions;\n crawl?: CrawlOptions;\n}\n\nexport function search1apiTools<\n Name extends Search1APIToolName = Search1APIToolName,\n>(options: Search1APIToolsOptions<Name> = {}): Pick<Search1APIToolSet, Name> {\n const getClient = clientGetter(options);\n const tools: Search1APIToolSet = {\n search: searchTool(getClient, options.search),\n news: newsTool(getClient, options.news),\n crawl: crawlTool(getClient, options.crawl),\n };\n const names = options.only ?? (['search', 'news', 'crawl'] as const);\n const selected = {} as Pick<Search1APIToolSet, Name>;\n for (const name of names) {\n if (!Object.hasOwn(tools, name)) {\n throw new Error(`Unknown Search1API tool: ${name}`);\n }\n Object.assign(selected, { [name]: tools[name] });\n }\n return selected;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Search1API } from '@search1api/client';\nimport type {\n CrawlOptions,\n CrawlResponse,\n NewsOptions,\n NewsResponse,\n Search1APIOptions,\n SearchOptions,\n SearchResponse,\n} from '@search1api/client';\nimport { tool } from 'ai';\nimport type { Tool } from 'ai';\nimport { z } from 'zod';\n\nexport interface Search1APIToolOptions extends Search1APIOptions {\n /** Reuse an existing client. When supplied, other client options are ignored. */\n client?: Search1API;\n}\n\nexport interface Search1APISearchOptions extends Search1APIToolOptions {\n /** Default search settings; values the model supplies take precedence. */\n search?: SearchOptions;\n}\n\nexport interface Search1APINewsOptions extends Search1APIToolOptions {\n /** Default news settings; values the model supplies take precedence. */\n news?: NewsOptions;\n}\n\nexport interface Search1APICrawlOptions extends Search1APIToolOptions {\n crawl?: CrawlOptions;\n}\n\nexport type CrawlInput = { url: string };\n\n// Model-facing parameters mirror the Search1API MCP server's tool schemas,\n// except result crawling, which only application settings can enable.\nconst SEARCH_ENGINES = [\n 'google',\n 'bing',\n 'duckduckgo',\n 'yahoo',\n 'x',\n 'reddit',\n 'github',\n 'youtube',\n 'arxiv',\n 'wechat',\n 'bilibili',\n 'imdb',\n 'wikipedia',\n] as const;\nconst NEWS_ENGINES = [\n 'google',\n 'bing',\n 'duckduckgo',\n 'yahoo',\n 'hackernews',\n] as const;\n\nfunction queryFields(kind: 'search' | 'news') {\n const noun = kind === 'search' ? 'results' : 'articles';\n return {\n query: z\n .string()\n .trim()\n .min(1)\n .describe(`Short, focused ${kind} query`),\n max_results: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(`Maximum number of ${noun} to return`),\n include_sites: z\n .array(z.string())\n .optional()\n .describe(\n kind === 'search'\n ? 'Domains to include when the user explicitly scopes the search'\n : 'News domains to include'\n ),\n exclude_sites: z\n .array(z.string())\n .optional()\n .describe(\n kind === 'search'\n ? 'Domains to exclude from the search'\n : 'News domains to exclude'\n ),\n time_range: z\n .enum(['day', 'month', 'year'])\n .optional()\n .describe(\n kind === 'search'\n ? 'Optional recency window for time-sensitive searches'\n : 'Optional recency window; use day for breaking news'\n ),\n };\n}\n\n// Unknown keys are stripped rather than rejected so a stray argument does not\n// cost the agent a retry step.\nconst searchSchema = z.object({\n ...queryFields('search'),\n search_service: z\n .enum(SEARCH_ENGINES)\n .optional()\n .describe(\n \"Search engine to use; choose one only when it matches the user's source intent\"\n ),\n});\n\nconst newsSchema = z.object({\n ...queryFields('news'),\n search_service: z\n .enum(NEWS_ENGINES)\n .optional()\n .describe('News search engine to use'),\n});\n\nconst crawlSchema = z.object({\n url: z\n .string()\n .url()\n .refine(\n (url) => ['http:', 'https:'].includes(new URL(url).protocol),\n 'Use an HTTP or HTTPS URL.'\n )\n .describe('Public HTTP or HTTPS URL to retrieve'),\n});\n\nexport type SearchInput = z.input<typeof searchSchema>;\nexport type NewsInput = z.input<typeof newsSchema>;\n\ntype ModelQueryInput =\n | z.output<typeof searchSchema>\n | z.output<typeof newsSchema>;\n\n// Merge model-supplied values over application defaults, dropping omitted keys.\nfunction requestOptions<Options extends SearchOptions | NewsOptions>(\n defaults: Options,\n input: ModelQueryInput\n): Options {\n const fromModel = {\n searchService: input.search_service,\n maxResults: input.max_results,\n includeSites: input.include_sites,\n excludeSites: input.exclude_sites,\n timeRange: input.time_range,\n };\n const overrides = Object.fromEntries(\n Object.entries(fromModel).filter(([, value]) => value !== undefined)\n );\n return { ...defaults, ...overrides } as Options;\n}\n\ntype ClientGetter = () => Search1API;\n\nfunction clientGetter(options: Search1APIToolOptions): ClientGetter {\n let client = options.client;\n const { client: _client, ...settings } = options;\n return () => {\n if (!client) {\n const processLike = globalThis as typeof globalThis & {\n process?: { env?: Record<string, string | undefined> };\n };\n const env = processLike.process?.env;\n client = new Search1API({\n ...settings,\n apiKey:\n settings.apiKey || env?.SEARCH1API_API_KEY || env?.SEARCH1API_KEY,\n });\n }\n return client;\n };\n}\n\nfunction searchTool(\n getClient: ClientGetter,\n settings: SearchOptions = {}\n): Tool<SearchInput, SearchResponse> {\n const defaults: SearchOptions = {\n maxResults: 10,\n crawlResults: 0,\n ...settings,\n };\n return tool({\n description:\n 'Search the live public web when the user needs current information, sources, or research. Returns titles, links, and snippets. Use crawl to read a result page in full.',\n inputSchema: searchSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const parsed = searchSchema.parse(input);\n return getClient().search(\n parsed.query,\n requestOptions(defaults, parsed),\n { signal: abortSignal }\n );\n },\n });\n}\n\nfunction newsTool(\n getClient: ClientGetter,\n settings: NewsOptions = {}\n): Tool<NewsInput, NewsResponse> {\n const defaults: NewsOptions = {\n maxResults: 10,\n crawlResults: 0,\n ...settings,\n };\n return tool({\n description:\n 'Search current news when the user asks about recent events, announcements, or coverage. Returns article titles, links, and snippets. Use crawl to read an article in full.',\n inputSchema: newsSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const parsed = newsSchema.parse(input);\n return getClient().news(parsed.query, requestOptions(defaults, parsed), {\n signal: abortSignal,\n });\n },\n });\n}\n\nfunction crawlTool(\n getClient: ClientGetter,\n settings: CrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n const options = { ...settings };\n return tool({\n description:\n 'Read one public webpage and return its title, source URL, and readable content. Use a URL supplied by the user or returned by search or news.',\n inputSchema: crawlSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { url } = crawlSchema.parse(input);\n return getClient().crawl(url, options, { signal: abortSignal });\n },\n });\n}\n\nexport function search1apiSearch(\n options: Search1APISearchOptions = {}\n): Tool<SearchInput, SearchResponse> {\n return searchTool(clientGetter(options), options.search);\n}\n\nexport function search1apiNews(\n options: Search1APINewsOptions = {}\n): Tool<NewsInput, NewsResponse> {\n return newsTool(clientGetter(options), options.news);\n}\n\nexport function search1apiCrawl(\n options: Search1APICrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n return crawlTool(clientGetter(options), options.crawl);\n}\n\nexport interface Search1APIToolSet {\n search: Tool<SearchInput, SearchResponse>;\n news: Tool<NewsInput, NewsResponse>;\n crawl: Tool<CrawlInput, CrawlResponse>;\n}\n\nexport type Search1APIToolName = keyof Search1APIToolSet;\n\nexport interface Search1APIToolsOptions<\n Name extends Search1APIToolName = Search1APIToolName,\n> extends Search1APIToolOptions {\n /** Include only these tools. By default all three are included. */\n only?: readonly Name[];\n search?: SearchOptions;\n news?: NewsOptions;\n crawl?: CrawlOptions;\n}\n\nexport function search1apiTools<\n Name extends Search1APIToolName = Search1APIToolName,\n>(options: Search1APIToolsOptions<Name> = {}): Pick<Search1APIToolSet, Name> {\n const getClient = clientGetter(options);\n const tools: Search1APIToolSet = {\n search: searchTool(getClient, options.search),\n news: newsTool(getClient, options.news),\n crawl: crawlTool(getClient, options.crawl),\n };\n const names = options.only ?? (['search', 'news', 'crawl'] as const);\n const selected = {} as Pick<Search1APIToolSet, Name>;\n for (const name of names) {\n if (!Object.hasOwn(tools, name)) {\n throw new Error(`Unknown Search1API tool: ${name}`);\n }\n Object.assign(selected, { [name]: tools[name] });\n }\n return selected;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,33 +1,77 @@
1
1
  import { Search1API } from '@search1api/client';
2
2
  import type { CrawlOptions, CrawlResponse, NewsOptions, NewsResponse, Search1APIOptions, SearchOptions, SearchResponse } from '@search1api/client';
3
3
  import type { Tool } from 'ai';
4
+ import { z } from 'zod';
4
5
  export interface Search1APIToolOptions extends Search1APIOptions {
5
6
  /** Reuse an existing client. When supplied, other client options are ignored. */
6
7
  client?: Search1API;
7
8
  }
8
9
  export interface Search1APISearchOptions extends Search1APIToolOptions {
9
- /** Application-owned search settings; the model only supplies the query. */
10
+ /** Default search settings; values the model supplies take precedence. */
10
11
  search?: SearchOptions;
11
12
  }
12
13
  export interface Search1APINewsOptions extends Search1APIToolOptions {
13
- /** Application-owned news settings; the model only supplies the query. */
14
+ /** Default news settings; values the model supplies take precedence. */
14
15
  news?: NewsOptions;
15
16
  }
16
17
  export interface Search1APICrawlOptions extends Search1APIToolOptions {
17
18
  crawl?: CrawlOptions;
18
19
  }
19
- export type QueryInput = {
20
- query: string;
21
- };
22
20
  export type CrawlInput = {
23
21
  url: string;
24
22
  };
25
- export declare function search1apiSearch(options?: Search1APISearchOptions): Tool<QueryInput, SearchResponse>;
26
- export declare function search1apiNews(options?: Search1APINewsOptions): Tool<QueryInput, NewsResponse>;
23
+ declare const searchSchema: z.ZodObject<{
24
+ search_service: z.ZodOptional<z.ZodEnum<{
25
+ google: "google";
26
+ bing: "bing";
27
+ duckduckgo: "duckduckgo";
28
+ yahoo: "yahoo";
29
+ x: "x";
30
+ reddit: "reddit";
31
+ github: "github";
32
+ youtube: "youtube";
33
+ arxiv: "arxiv";
34
+ wechat: "wechat";
35
+ bilibili: "bilibili";
36
+ imdb: "imdb";
37
+ wikipedia: "wikipedia";
38
+ }>>;
39
+ query: z.ZodString;
40
+ max_results: z.ZodOptional<z.ZodNumber>;
41
+ include_sites: z.ZodOptional<z.ZodArray<z.ZodString>>;
42
+ exclude_sites: z.ZodOptional<z.ZodArray<z.ZodString>>;
43
+ time_range: z.ZodOptional<z.ZodEnum<{
44
+ day: "day";
45
+ month: "month";
46
+ year: "year";
47
+ }>>;
48
+ }, z.core.$strip>;
49
+ declare const newsSchema: z.ZodObject<{
50
+ search_service: z.ZodOptional<z.ZodEnum<{
51
+ google: "google";
52
+ bing: "bing";
53
+ duckduckgo: "duckduckgo";
54
+ yahoo: "yahoo";
55
+ hackernews: "hackernews";
56
+ }>>;
57
+ query: z.ZodString;
58
+ max_results: z.ZodOptional<z.ZodNumber>;
59
+ include_sites: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
+ exclude_sites: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
+ time_range: z.ZodOptional<z.ZodEnum<{
62
+ day: "day";
63
+ month: "month";
64
+ year: "year";
65
+ }>>;
66
+ }, z.core.$strip>;
67
+ export type SearchInput = z.input<typeof searchSchema>;
68
+ export type NewsInput = z.input<typeof newsSchema>;
69
+ export declare function search1apiSearch(options?: Search1APISearchOptions): Tool<SearchInput, SearchResponse>;
70
+ export declare function search1apiNews(options?: Search1APINewsOptions): Tool<NewsInput, NewsResponse>;
27
71
  export declare function search1apiCrawl(options?: Search1APICrawlOptions): Tool<CrawlInput, CrawlResponse>;
28
72
  export interface Search1APIToolSet {
29
- search: Tool<QueryInput, SearchResponse>;
30
- news: Tool<QueryInput, NewsResponse>;
73
+ search: Tool<SearchInput, SearchResponse>;
74
+ news: Tool<NewsInput, NewsResponse>;
31
75
  crawl: Tool<CrawlInput, CrawlResponse>;
32
76
  }
33
77
  export type Search1APIToolName = keyof Search1APIToolSet;
@@ -39,4 +83,5 @@ export interface Search1APIToolsOptions<Name extends Search1APIToolName = Search
39
83
  crawl?: CrawlOptions;
40
84
  }
41
85
  export declare function search1apiTools<Name extends Search1APIToolName = Search1APIToolName>(options?: Search1APIToolsOptions<Name>): Pick<Search1APIToolSet, Name>;
86
+ export {};
42
87
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,cAAc,EACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,iFAAiF;IACjF,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,4EAA4E;IAC5E,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,qBAAsB,SAAQ,qBAAqB;IAClE,0EAA0E;IAC1E,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,qBAAqB;IACnE,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,MAAM,UAAU,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAC3C,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAiGzC,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,uBAA4B,GACpC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAElC;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAEhC;AAED,wBAAgB,eAAe,CAC7B,OAAO,GAAE,sBAA2B,GACnC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAEjC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACzC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IACrC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,sBAAsB,CACrC,IAAI,SAAS,kBAAkB,GAAG,kBAAkB,CACpD,SAAQ,qBAAqB;IAC7B,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,eAAe,CAC7B,IAAI,SAAS,kBAAkB,GAAG,kBAAkB,EACpD,OAAO,GAAE,sBAAsB,CAAC,IAAI,CAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAgB3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,cAAc,EACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,iFAAiF;IACjF,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,uBAAwB,SAAQ,qBAAqB;IACpE,0EAA0E;IAC1E,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,qBAAsB,SAAQ,qBAAqB;IAClE,wEAAwE;IACxE,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,qBAAqB;IACnE,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,MAAM,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAuEzC,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;iBAQhB,CAAC;AAEH,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;iBAMd,CAAC;AAaH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AACvD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AA8GnD,wBAAgB,gBAAgB,CAC9B,OAAO,GAAE,uBAA4B,GACpC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAEnC;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,qBAA0B,GAClC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAE/B;AAED,wBAAgB,eAAe,CAC7B,OAAO,GAAE,sBAA2B,GACnC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAEjC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC1C,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IACpC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;CACxC;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,sBAAsB,CACrC,IAAI,SAAS,kBAAkB,GAAG,kBAAkB,CACpD,SAAQ,qBAAqB;IAC7B,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,eAAe,CAC7B,IAAI,SAAS,kBAAkB,GAAG,kBAAkB,EACpD,OAAO,GAAE,sBAAsB,CAAC,IAAI,CAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAgB3E"}
package/dist/index.js CHANGED
@@ -2,15 +2,73 @@
2
2
  import { Search1API } from "@search1api/client";
3
3
  import { tool } from "ai";
4
4
  import { z } from "zod";
5
- var querySchema = z.object({
6
- query: z.string().trim().min(1).describe("Search keywords or a specific question.")
7
- }).strict();
5
+ var SEARCH_ENGINES = [
6
+ "google",
7
+ "bing",
8
+ "duckduckgo",
9
+ "yahoo",
10
+ "x",
11
+ "reddit",
12
+ "github",
13
+ "youtube",
14
+ "arxiv",
15
+ "wechat",
16
+ "bilibili",
17
+ "imdb",
18
+ "wikipedia"
19
+ ];
20
+ var NEWS_ENGINES = [
21
+ "google",
22
+ "bing",
23
+ "duckduckgo",
24
+ "yahoo",
25
+ "hackernews"
26
+ ];
27
+ function queryFields(kind) {
28
+ const noun = kind === "search" ? "results" : "articles";
29
+ return {
30
+ query: z.string().trim().min(1).describe(`Short, focused ${kind} query`),
31
+ max_results: z.number().int().min(1).max(50).optional().describe(`Maximum number of ${noun} to return`),
32
+ include_sites: z.array(z.string()).optional().describe(
33
+ kind === "search" ? "Domains to include when the user explicitly scopes the search" : "News domains to include"
34
+ ),
35
+ exclude_sites: z.array(z.string()).optional().describe(
36
+ kind === "search" ? "Domains to exclude from the search" : "News domains to exclude"
37
+ ),
38
+ time_range: z.enum(["day", "month", "year"]).optional().describe(
39
+ kind === "search" ? "Optional recency window for time-sensitive searches" : "Optional recency window; use day for breaking news"
40
+ )
41
+ };
42
+ }
43
+ var searchSchema = z.object({
44
+ ...queryFields("search"),
45
+ search_service: z.enum(SEARCH_ENGINES).optional().describe(
46
+ "Search engine to use; choose one only when it matches the user's source intent"
47
+ )
48
+ });
49
+ var newsSchema = z.object({
50
+ ...queryFields("news"),
51
+ search_service: z.enum(NEWS_ENGINES).optional().describe("News search engine to use")
52
+ });
8
53
  var crawlSchema = z.object({
9
54
  url: z.string().url().refine(
10
55
  (url) => ["http:", "https:"].includes(new URL(url).protocol),
11
56
  "Use an HTTP or HTTPS URL."
12
- ).describe("A public webpage URL, for example a link returned by search.")
13
- }).strict();
57
+ ).describe("Public HTTP or HTTPS URL to retrieve")
58
+ });
59
+ function requestOptions(defaults, input) {
60
+ const fromModel = {
61
+ searchService: input.search_service,
62
+ maxResults: input.max_results,
63
+ includeSites: input.include_sites,
64
+ excludeSites: input.exclude_sites,
65
+ timeRange: input.time_range
66
+ };
67
+ const overrides = Object.fromEntries(
68
+ Object.entries(fromModel).filter(([, value]) => value !== void 0)
69
+ );
70
+ return { ...defaults, ...overrides };
71
+ }
14
72
  function clientGetter(options) {
15
73
  let client = options.client;
16
74
  const { client: _client, ...settings } = options;
@@ -27,26 +85,40 @@ function clientGetter(options) {
27
85
  };
28
86
  }
29
87
  function searchTool(getClient, settings = {}) {
30
- const options = { maxResults: 5, crawlResults: 0, ...settings };
88
+ const defaults = {
89
+ maxResults: 10,
90
+ crawlResults: 0,
91
+ ...settings
92
+ };
31
93
  return tool({
32
- description: "Search the public web for current information and sources. Returns titles, links, and snippets. Use crawl to read a result page in full.",
33
- inputSchema: querySchema,
94
+ description: "Search the live public web when the user needs current information, sources, or research. Returns titles, links, and snippets. Use crawl to read a result page in full.",
95
+ inputSchema: searchSchema,
34
96
  execute: async (input, { abortSignal }) => {
35
97
  abortSignal?.throwIfAborted();
36
- const { query } = querySchema.parse(input);
37
- return getClient().search(query, options, { signal: abortSignal });
98
+ const parsed = searchSchema.parse(input);
99
+ return getClient().search(
100
+ parsed.query,
101
+ requestOptions(defaults, parsed),
102
+ { signal: abortSignal }
103
+ );
38
104
  }
39
105
  });
40
106
  }
41
107
  function newsTool(getClient, settings = {}) {
42
- const options = { maxResults: 5, crawlResults: 0, ...settings };
108
+ const defaults = {
109
+ maxResults: 10,
110
+ crawlResults: 0,
111
+ ...settings
112
+ };
43
113
  return tool({
44
- description: "Search news coverage of recent events and announcements. Returns article titles, links, and snippets. Use crawl to read an article in full.",
45
- inputSchema: querySchema,
114
+ description: "Search current news when the user asks about recent events, announcements, or coverage. Returns article titles, links, and snippets. Use crawl to read an article in full.",
115
+ inputSchema: newsSchema,
46
116
  execute: async (input, { abortSignal }) => {
47
117
  abortSignal?.throwIfAborted();
48
- const { query } = querySchema.parse(input);
49
- return getClient().news(query, options, { signal: abortSignal });
118
+ const parsed = newsSchema.parse(input);
119
+ return getClient().news(parsed.query, requestOptions(defaults, parsed), {
120
+ signal: abortSignal
121
+ });
50
122
  }
51
123
  });
52
124
  }
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "sourcesContent": ["import { Search1API } from '@search1api/client';\nimport type {\n CrawlOptions,\n CrawlResponse,\n NewsOptions,\n NewsResponse,\n Search1APIOptions,\n SearchOptions,\n SearchResponse,\n} from '@search1api/client';\nimport { tool } from 'ai';\nimport type { Tool } from 'ai';\nimport { z } from 'zod';\n\nexport interface Search1APIToolOptions extends Search1APIOptions {\n /** Reuse an existing client. When supplied, other client options are ignored. */\n client?: Search1API;\n}\n\nexport interface Search1APISearchOptions extends Search1APIToolOptions {\n /** Application-owned search settings; the model only supplies the query. */\n search?: SearchOptions;\n}\n\nexport interface Search1APINewsOptions extends Search1APIToolOptions {\n /** Application-owned news settings; the model only supplies the query. */\n news?: NewsOptions;\n}\n\nexport interface Search1APICrawlOptions extends Search1APIToolOptions {\n crawl?: CrawlOptions;\n}\n\nexport type QueryInput = { query: string };\nexport type CrawlInput = { url: string };\n\nconst querySchema = z\n .object({\n query: z\n .string()\n .trim()\n .min(1)\n .describe('Search keywords or a specific question.'),\n })\n .strict();\n\nconst crawlSchema = z\n .object({\n url: z\n .string()\n .url()\n .refine(\n (url) => ['http:', 'https:'].includes(new URL(url).protocol),\n 'Use an HTTP or HTTPS URL.'\n )\n .describe('A public webpage URL, for example a link returned by search.'),\n })\n .strict();\n\ntype ClientGetter = () => Search1API;\n\nfunction clientGetter(options: Search1APIToolOptions): ClientGetter {\n let client = options.client;\n const { client: _client, ...settings } = options;\n return () => {\n if (!client) {\n const processLike = globalThis as typeof globalThis & {\n process?: { env?: Record<string, string | undefined> };\n };\n const env = processLike.process?.env;\n client = new Search1API({\n ...settings,\n apiKey:\n settings.apiKey || env?.SEARCH1API_API_KEY || env?.SEARCH1API_KEY,\n });\n }\n return client;\n };\n}\n\nfunction searchTool(\n getClient: ClientGetter,\n settings: SearchOptions = {}\n): Tool<QueryInput, SearchResponse> {\n const options = { maxResults: 5, crawlResults: 0, ...settings };\n return tool({\n description:\n 'Search the public web for current information and sources. Returns titles, links, and snippets. Use crawl to read a result page in full.',\n inputSchema: querySchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { query } = querySchema.parse(input);\n return getClient().search(query, options, { signal: abortSignal });\n },\n });\n}\n\nfunction newsTool(\n getClient: ClientGetter,\n settings: NewsOptions = {}\n): Tool<QueryInput, NewsResponse> {\n const options = { maxResults: 5, crawlResults: 0, ...settings };\n return tool({\n description:\n 'Search news coverage of recent events and announcements. Returns article titles, links, and snippets. Use crawl to read an article in full.',\n inputSchema: querySchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { query } = querySchema.parse(input);\n return getClient().news(query, options, { signal: abortSignal });\n },\n });\n}\n\nfunction crawlTool(\n getClient: ClientGetter,\n settings: CrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n const options = { ...settings };\n return tool({\n description:\n 'Read one public webpage and return its title, source URL, and readable content. Use a URL supplied by the user or returned by search or news.',\n inputSchema: crawlSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { url } = crawlSchema.parse(input);\n return getClient().crawl(url, options, { signal: abortSignal });\n },\n });\n}\n\nexport function search1apiSearch(\n options: Search1APISearchOptions = {}\n): Tool<QueryInput, SearchResponse> {\n return searchTool(clientGetter(options), options.search);\n}\n\nexport function search1apiNews(\n options: Search1APINewsOptions = {}\n): Tool<QueryInput, NewsResponse> {\n return newsTool(clientGetter(options), options.news);\n}\n\nexport function search1apiCrawl(\n options: Search1APICrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n return crawlTool(clientGetter(options), options.crawl);\n}\n\nexport interface Search1APIToolSet {\n search: Tool<QueryInput, SearchResponse>;\n news: Tool<QueryInput, NewsResponse>;\n crawl: Tool<CrawlInput, CrawlResponse>;\n}\n\nexport type Search1APIToolName = keyof Search1APIToolSet;\n\nexport interface Search1APIToolsOptions<\n Name extends Search1APIToolName = Search1APIToolName,\n> extends Search1APIToolOptions {\n /** Include only these tools. By default all three are included. */\n only?: readonly Name[];\n search?: SearchOptions;\n news?: NewsOptions;\n crawl?: CrawlOptions;\n}\n\nexport function search1apiTools<\n Name extends Search1APIToolName = Search1APIToolName,\n>(options: Search1APIToolsOptions<Name> = {}): Pick<Search1APIToolSet, Name> {\n const getClient = clientGetter(options);\n const tools: Search1APIToolSet = {\n search: searchTool(getClient, options.search),\n news: newsTool(getClient, options.news),\n crawl: crawlTool(getClient, options.crawl),\n };\n const names = options.only ?? (['search', 'news', 'crawl'] as const);\n const selected = {} as Pick<Search1APIToolSet, Name>;\n for (const name of names) {\n if (!Object.hasOwn(tools, name)) {\n throw new Error(`Unknown Search1API tool: ${name}`);\n }\n Object.assign(selected, { [name]: tools[name] });\n }\n return selected;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { Search1API } from '@search1api/client';\nimport type {\n CrawlOptions,\n CrawlResponse,\n NewsOptions,\n NewsResponse,\n Search1APIOptions,\n SearchOptions,\n SearchResponse,\n} from '@search1api/client';\nimport { tool } from 'ai';\nimport type { Tool } from 'ai';\nimport { z } from 'zod';\n\nexport interface Search1APIToolOptions extends Search1APIOptions {\n /** Reuse an existing client. When supplied, other client options are ignored. */\n client?: Search1API;\n}\n\nexport interface Search1APISearchOptions extends Search1APIToolOptions {\n /** Default search settings; values the model supplies take precedence. */\n search?: SearchOptions;\n}\n\nexport interface Search1APINewsOptions extends Search1APIToolOptions {\n /** Default news settings; values the model supplies take precedence. */\n news?: NewsOptions;\n}\n\nexport interface Search1APICrawlOptions extends Search1APIToolOptions {\n crawl?: CrawlOptions;\n}\n\nexport type CrawlInput = { url: string };\n\n// Model-facing parameters mirror the Search1API MCP server's tool schemas,\n// except result crawling, which only application settings can enable.\nconst SEARCH_ENGINES = [\n 'google',\n 'bing',\n 'duckduckgo',\n 'yahoo',\n 'x',\n 'reddit',\n 'github',\n 'youtube',\n 'arxiv',\n 'wechat',\n 'bilibili',\n 'imdb',\n 'wikipedia',\n] as const;\nconst NEWS_ENGINES = [\n 'google',\n 'bing',\n 'duckduckgo',\n 'yahoo',\n 'hackernews',\n] as const;\n\nfunction queryFields(kind: 'search' | 'news') {\n const noun = kind === 'search' ? 'results' : 'articles';\n return {\n query: z\n .string()\n .trim()\n .min(1)\n .describe(`Short, focused ${kind} query`),\n max_results: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(`Maximum number of ${noun} to return`),\n include_sites: z\n .array(z.string())\n .optional()\n .describe(\n kind === 'search'\n ? 'Domains to include when the user explicitly scopes the search'\n : 'News domains to include'\n ),\n exclude_sites: z\n .array(z.string())\n .optional()\n .describe(\n kind === 'search'\n ? 'Domains to exclude from the search'\n : 'News domains to exclude'\n ),\n time_range: z\n .enum(['day', 'month', 'year'])\n .optional()\n .describe(\n kind === 'search'\n ? 'Optional recency window for time-sensitive searches'\n : 'Optional recency window; use day for breaking news'\n ),\n };\n}\n\n// Unknown keys are stripped rather than rejected so a stray argument does not\n// cost the agent a retry step.\nconst searchSchema = z.object({\n ...queryFields('search'),\n search_service: z\n .enum(SEARCH_ENGINES)\n .optional()\n .describe(\n \"Search engine to use; choose one only when it matches the user's source intent\"\n ),\n});\n\nconst newsSchema = z.object({\n ...queryFields('news'),\n search_service: z\n .enum(NEWS_ENGINES)\n .optional()\n .describe('News search engine to use'),\n});\n\nconst crawlSchema = z.object({\n url: z\n .string()\n .url()\n .refine(\n (url) => ['http:', 'https:'].includes(new URL(url).protocol),\n 'Use an HTTP or HTTPS URL.'\n )\n .describe('Public HTTP or HTTPS URL to retrieve'),\n});\n\nexport type SearchInput = z.input<typeof searchSchema>;\nexport type NewsInput = z.input<typeof newsSchema>;\n\ntype ModelQueryInput =\n | z.output<typeof searchSchema>\n | z.output<typeof newsSchema>;\n\n// Merge model-supplied values over application defaults, dropping omitted keys.\nfunction requestOptions<Options extends SearchOptions | NewsOptions>(\n defaults: Options,\n input: ModelQueryInput\n): Options {\n const fromModel = {\n searchService: input.search_service,\n maxResults: input.max_results,\n includeSites: input.include_sites,\n excludeSites: input.exclude_sites,\n timeRange: input.time_range,\n };\n const overrides = Object.fromEntries(\n Object.entries(fromModel).filter(([, value]) => value !== undefined)\n );\n return { ...defaults, ...overrides } as Options;\n}\n\ntype ClientGetter = () => Search1API;\n\nfunction clientGetter(options: Search1APIToolOptions): ClientGetter {\n let client = options.client;\n const { client: _client, ...settings } = options;\n return () => {\n if (!client) {\n const processLike = globalThis as typeof globalThis & {\n process?: { env?: Record<string, string | undefined> };\n };\n const env = processLike.process?.env;\n client = new Search1API({\n ...settings,\n apiKey:\n settings.apiKey || env?.SEARCH1API_API_KEY || env?.SEARCH1API_KEY,\n });\n }\n return client;\n };\n}\n\nfunction searchTool(\n getClient: ClientGetter,\n settings: SearchOptions = {}\n): Tool<SearchInput, SearchResponse> {\n const defaults: SearchOptions = {\n maxResults: 10,\n crawlResults: 0,\n ...settings,\n };\n return tool({\n description:\n 'Search the live public web when the user needs current information, sources, or research. Returns titles, links, and snippets. Use crawl to read a result page in full.',\n inputSchema: searchSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const parsed = searchSchema.parse(input);\n return getClient().search(\n parsed.query,\n requestOptions(defaults, parsed),\n { signal: abortSignal }\n );\n },\n });\n}\n\nfunction newsTool(\n getClient: ClientGetter,\n settings: NewsOptions = {}\n): Tool<NewsInput, NewsResponse> {\n const defaults: NewsOptions = {\n maxResults: 10,\n crawlResults: 0,\n ...settings,\n };\n return tool({\n description:\n 'Search current news when the user asks about recent events, announcements, or coverage. Returns article titles, links, and snippets. Use crawl to read an article in full.',\n inputSchema: newsSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const parsed = newsSchema.parse(input);\n return getClient().news(parsed.query, requestOptions(defaults, parsed), {\n signal: abortSignal,\n });\n },\n });\n}\n\nfunction crawlTool(\n getClient: ClientGetter,\n settings: CrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n const options = { ...settings };\n return tool({\n description:\n 'Read one public webpage and return its title, source URL, and readable content. Use a URL supplied by the user or returned by search or news.',\n inputSchema: crawlSchema,\n execute: async (input, { abortSignal }) => {\n abortSignal?.throwIfAborted();\n const { url } = crawlSchema.parse(input);\n return getClient().crawl(url, options, { signal: abortSignal });\n },\n });\n}\n\nexport function search1apiSearch(\n options: Search1APISearchOptions = {}\n): Tool<SearchInput, SearchResponse> {\n return searchTool(clientGetter(options), options.search);\n}\n\nexport function search1apiNews(\n options: Search1APINewsOptions = {}\n): Tool<NewsInput, NewsResponse> {\n return newsTool(clientGetter(options), options.news);\n}\n\nexport function search1apiCrawl(\n options: Search1APICrawlOptions = {}\n): Tool<CrawlInput, CrawlResponse> {\n return crawlTool(clientGetter(options), options.crawl);\n}\n\nexport interface Search1APIToolSet {\n search: Tool<SearchInput, SearchResponse>;\n news: Tool<NewsInput, NewsResponse>;\n crawl: Tool<CrawlInput, CrawlResponse>;\n}\n\nexport type Search1APIToolName = keyof Search1APIToolSet;\n\nexport interface Search1APIToolsOptions<\n Name extends Search1APIToolName = Search1APIToolName,\n> extends Search1APIToolOptions {\n /** Include only these tools. By default all three are included. */\n only?: readonly Name[];\n search?: SearchOptions;\n news?: NewsOptions;\n crawl?: CrawlOptions;\n}\n\nexport function search1apiTools<\n Name extends Search1APIToolName = Search1APIToolName,\n>(options: Search1APIToolsOptions<Name> = {}): Pick<Search1APIToolSet, Name> {\n const getClient = clientGetter(options);\n const tools: Search1APIToolSet = {\n search: searchTool(getClient, options.search),\n news: newsTool(getClient, options.news),\n crawl: crawlTool(getClient, options.crawl),\n };\n const names = options.only ?? (['search', 'news', 'crawl'] as const);\n const selected = {} as Pick<Search1APIToolSet, Name>;\n for (const name of names) {\n if (!Object.hasOwn(tools, name)) {\n throw new Error(`Unknown Search1API tool: ${name}`);\n }\n Object.assign(selected, { [name]: tools[name] });\n }\n return selected;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@search1api/ai-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Official Search1API web search, news, and page reading tools for the Vercel AI SDK.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -14,17 +14,36 @@
14
14
  "require": "./dist/index.cjs"
15
15
  }
16
16
  },
17
- "files": ["dist", "README.md", "LICENSE"],
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
18
22
  "sideEffects": false,
19
- "engines": { "node": ">=18" },
23
+ "engines": {
24
+ "node": ">=18"
25
+ },
20
26
  "repository": {
21
27
  "type": "git",
22
28
  "url": "git+https://github.com/superagents-lab/search1api-ai-sdk.git"
23
29
  },
24
30
  "homepage": "https://s1.dev",
25
- "bugs": { "url": "https://github.com/superagents-lab/search1api-ai-sdk/issues" },
26
- "keywords": ["search1api", "ai-sdk", "vercel", "tools", "web-search", "crawl", "news", "agents"],
27
- "publishConfig": { "access": "public" },
31
+ "bugs": {
32
+ "url": "https://github.com/superagents-lab/search1api-ai-sdk/issues"
33
+ },
34
+ "keywords": [
35
+ "search1api",
36
+ "ai-sdk",
37
+ "vercel",
38
+ "tools",
39
+ "web-search",
40
+ "crawl",
41
+ "news",
42
+ "agents"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
28
47
  "scripts": {
29
48
  "build": "node scripts/build.mjs && tsc -p tsconfig.build.json",
30
49
  "test": "vitest run",
@@ -33,7 +52,9 @@
33
52
  "typecheck": "tsc --noEmit",
34
53
  "prepack": "npm run build"
35
54
  },
36
- "dependencies": { "@search1api/client": "^0.2.1" },
55
+ "dependencies": {
56
+ "@search1api/client": "^0.2.1"
57
+ },
37
58
  "peerDependencies": {
38
59
  "ai": "^5.0.0 || ^6.0.0 || ^7.0.0",
39
60
  "zod": "^3.25.76 || ^4.1.8"