@thynker-labs/tools-brave 0.0.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.
@@ -0,0 +1,14 @@
1
+ import { ToolProvider } from '@thynker-labs/core';
2
+
3
+ interface BraveToolProviderConfig {
4
+ apiKeyEnv: string;
5
+ /** Required scopes for search tools (default: ["web:search"]). */
6
+ requiredScopes?: string[];
7
+ }
8
+ type BraveFetch = typeof fetch;
9
+ /**
10
+ * Brave Search ToolProvider — web and news search via Brave Search API.
11
+ */
12
+ declare function createBraveToolProvider(config: BraveToolProviderConfig, fetchImpl?: BraveFetch): ToolProvider;
13
+
14
+ export { type BraveFetch, type BraveToolProviderConfig, createBraveToolProvider };
package/dist/index.js ADDED
@@ -0,0 +1,112 @@
1
+ // src/index.ts
2
+ var BRAVE_API = "https://api.search.brave.com/res/v1";
3
+ var TOOLS = [
4
+ {
5
+ name: "brave_web_search",
6
+ description: "Search the web using Brave Search. Returns titles, URLs, and snippets for top results.",
7
+ requiredScopes: ["web:search"],
8
+ inputSchema: {
9
+ type: "object",
10
+ properties: {
11
+ query: { type: "string", description: "Search query" },
12
+ count: { type: "number", description: "Number of results (1-20, default 5)" }
13
+ },
14
+ required: ["query"]
15
+ }
16
+ },
17
+ {
18
+ name: "brave_news_search",
19
+ description: "Search recent news using Brave News Search.",
20
+ requiredScopes: ["web:search"],
21
+ inputSchema: {
22
+ type: "object",
23
+ properties: {
24
+ query: { type: "string", description: "News search query" },
25
+ count: { type: "number", description: "Number of results (1-20, default 5)" }
26
+ },
27
+ required: ["query"]
28
+ }
29
+ }
30
+ ];
31
+ function resolveApiKey(config) {
32
+ const key = process.env[config.apiKeyEnv];
33
+ if (!key) {
34
+ throw new Error(
35
+ `Missing ${config.apiKeyEnv}. Set it in .env to enable Brave Search tools.`
36
+ );
37
+ }
38
+ return key;
39
+ }
40
+ function scopesFor(config) {
41
+ return config.requiredScopes ?? ["web:search"];
42
+ }
43
+ function mapWebResults(data) {
44
+ return (data.web?.results ?? []).map((r) => ({
45
+ title: r.title ?? "",
46
+ url: r.url ?? "",
47
+ snippet: r.description ?? ""
48
+ }));
49
+ }
50
+ function mapNewsResults(data) {
51
+ return (data.results ?? []).map((r) => ({
52
+ title: r.title ?? "",
53
+ url: r.url ?? "",
54
+ snippet: r.description ?? ""
55
+ }));
56
+ }
57
+ function createBraveToolProvider(config, fetchImpl = fetch) {
58
+ const scopedTools = TOOLS.map((t) => ({
59
+ ...t,
60
+ requiredScopes: scopesFor(config)
61
+ }));
62
+ return {
63
+ async list() {
64
+ resolveApiKey(config);
65
+ return scopedTools;
66
+ },
67
+ async execute(name, args, _authCtx) {
68
+ const apiKey = resolveApiKey(config);
69
+ const query = String(args.query ?? "");
70
+ if (!query.trim()) throw new Error("query is required");
71
+ const count = Math.min(20, Math.max(1, Number(args.count ?? 5)));
72
+ if (name === "brave_web_search") {
73
+ const url = new URL(`${BRAVE_API}/web/search`);
74
+ url.searchParams.set("q", query);
75
+ url.searchParams.set("count", String(count));
76
+ const res = await fetchImpl(url.toString(), {
77
+ headers: {
78
+ Accept: "application/json",
79
+ "X-Subscription-Token": apiKey
80
+ }
81
+ });
82
+ if (!res.ok) {
83
+ const body = await res.text();
84
+ throw new Error(`Brave web search failed (${res.status}): ${body}`);
85
+ }
86
+ const data = await res.json();
87
+ return { query, results: mapWebResults(data) };
88
+ }
89
+ if (name === "brave_news_search") {
90
+ const url = new URL(`${BRAVE_API}/news/search`);
91
+ url.searchParams.set("q", query);
92
+ url.searchParams.set("count", String(count));
93
+ const res = await fetchImpl(url.toString(), {
94
+ headers: {
95
+ Accept: "application/json",
96
+ "X-Subscription-Token": apiKey
97
+ }
98
+ });
99
+ if (!res.ok) {
100
+ const body = await res.text();
101
+ throw new Error(`Brave news search failed (${res.status}): ${body}`);
102
+ }
103
+ const data = await res.json();
104
+ return { query, results: mapNewsResults(data) };
105
+ }
106
+ throw new Error(`Unknown Brave tool: ${name}`);
107
+ }
108
+ };
109
+ }
110
+ export {
111
+ createBraveToolProvider
112
+ };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@thynker-labs/tools-brave",
3
+ "version": "0.0.1",
4
+ "description": "Brave Search API ToolProvider for web search",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "dependencies": {
18
+ "@thynker-labs/core": "0.0.1"
19
+ },
20
+ "engines": {
21
+ "node": ">=20"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "scripts": {
27
+ "build": "tsup",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "vitest run"
30
+ }
31
+ }