bigtool-ts 0.1.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/CHANGELOG.md +27 -0
- package/LICENSE +21 -0
- package/README.md +641 -0
- package/dist/adapters/agent-protocol.d.ts +149 -0
- package/dist/adapters/agent-protocol.d.ts.map +1 -0
- package/dist/adapters/agent-protocol.js +133 -0
- package/dist/adapters/agent-protocol.js.map +1 -0
- package/dist/adapters/index.d.ts +39 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +42 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/inngest.d.ts +234 -0
- package/dist/adapters/inngest.d.ts.map +1 -0
- package/dist/adapters/inngest.js +276 -0
- package/dist/adapters/inngest.js.map +1 -0
- package/dist/adapters/mastra.d.ts +201 -0
- package/dist/adapters/mastra.d.ts.map +1 -0
- package/dist/adapters/mastra.js +250 -0
- package/dist/adapters/mastra.js.map +1 -0
- package/dist/adapters/types.d.ts +42 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +6 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/vercel-ai.d.ts +176 -0
- package/dist/adapters/vercel-ai.d.ts.map +1 -0
- package/dist/adapters/vercel-ai.js +244 -0
- package/dist/adapters/vercel-ai.js.map +1 -0
- package/dist/catalog/index.d.ts +177 -0
- package/dist/catalog/index.d.ts.map +1 -0
- package/dist/catalog/index.js +244 -0
- package/dist/catalog/index.js.map +1 -0
- package/dist/graph/agent.d.ts +214 -0
- package/dist/graph/agent.d.ts.map +1 -0
- package/dist/graph/agent.js +196 -0
- package/dist/graph/agent.js.map +1 -0
- package/dist/graph/index.d.ts +5 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +4 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/nodes.d.ts +100 -0
- package/dist/graph/nodes.d.ts.map +1 -0
- package/dist/graph/nodes.js +190 -0
- package/dist/graph/nodes.js.map +1 -0
- package/dist/graph/search-tool.d.ts +34 -0
- package/dist/graph/search-tool.d.ts.map +1 -0
- package/dist/graph/search-tool.js +54 -0
- package/dist/graph/search-tool.js.map +1 -0
- package/dist/graph/state.d.ts +26 -0
- package/dist/graph/state.d.ts.map +1 -0
- package/dist/graph/state.js +29 -0
- package/dist/graph/state.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +85 -0
- package/dist/index.js.map +1 -0
- package/dist/loader/index.d.ts +172 -0
- package/dist/loader/index.d.ts.map +1 -0
- package/dist/loader/index.js +179 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/loader.d.ts +114 -0
- package/dist/loader/loader.d.ts.map +1 -0
- package/dist/loader/loader.js +185 -0
- package/dist/loader/loader.js.map +1 -0
- package/dist/search/cache.d.ts +76 -0
- package/dist/search/cache.d.ts.map +1 -0
- package/dist/search/cache.js +135 -0
- package/dist/search/cache.js.map +1 -0
- package/dist/search/index.d.ts +63 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +122 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/normalize.d.ts +104 -0
- package/dist/search/normalize.d.ts.map +1 -0
- package/dist/search/normalize.js +211 -0
- package/dist/search/normalize.js.map +1 -0
- package/dist/search/orama.d.ts +256 -0
- package/dist/search/orama.d.ts.map +1 -0
- package/dist/search/orama.js +511 -0
- package/dist/search/orama.js.map +1 -0
- package/dist/search/types.d.ts +96 -0
- package/dist/search/types.d.ts.map +1 -0
- package/dist/search/types.js +8 -0
- package/dist/search/types.js.map +1 -0
- package/dist/sources/dynamic.d.ts +200 -0
- package/dist/sources/dynamic.d.ts.map +1 -0
- package/dist/sources/dynamic.js +194 -0
- package/dist/sources/dynamic.js.map +1 -0
- package/dist/sources/index.d.ts +11 -0
- package/dist/sources/index.d.ts.map +1 -0
- package/dist/sources/index.js +14 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/local.d.ts +128 -0
- package/dist/sources/local.d.ts.map +1 -0
- package/dist/sources/local.js +155 -0
- package/dist/sources/local.js.map +1 -0
- package/dist/sources/mcp.d.ts +438 -0
- package/dist/sources/mcp.d.ts.map +1 -0
- package/dist/sources/mcp.js +438 -0
- package/dist/sources/mcp.js.map +1 -0
- package/dist/sources/types.d.ts +16 -0
- package/dist/sources/types.d.ts.map +1 -0
- package/dist/sources/types.js +7 -0
- package/dist/sources/types.js.map +1 -0
- package/dist/sources/with-metadata.d.ts +7 -0
- package/dist/sources/with-metadata.d.ts.map +1 -0
- package/dist/sources/with-metadata.js +7 -0
- package/dist/sources/with-metadata.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types.d.ts +700 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +97 -0
- package/dist/types.js.map +1 -0
- package/package.json +118 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-01-19
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Initial release of bigtool-ts
|
|
15
|
+
- `ToolCatalog` for managing tool collections with semantic search
|
|
16
|
+
- `ToolLoader` for lazy-loading tools on demand
|
|
17
|
+
- Orama-powered semantic search with caching
|
|
18
|
+
- Tool sources:
|
|
19
|
+
- `LocalToolSource` for statically defined tools
|
|
20
|
+
- `MCPToolSource` for Model Context Protocol servers
|
|
21
|
+
- `DynamicToolSource` for runtime-generated tools
|
|
22
|
+
- `withMetadata` wrapper for enriching tool metadata
|
|
23
|
+
- LangGraph integration:
|
|
24
|
+
- `createBigToolAgent` for building tool-discovery agents
|
|
25
|
+
- Pre-built graph nodes for search and execution
|
|
26
|
+
- TypeScript-first with full type inference
|
|
27
|
+
- Comprehensive test coverage
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Assistant UI Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,641 @@
|
|
|
1
|
+
# bigtool-ts
|
|
2
|
+
|
|
3
|
+
Dynamic tool discovery for AI agents. Search and load tools on-demand instead of loading all tools upfront.
|
|
4
|
+
|
|
5
|
+
Works with **LangGraph**, **Inngest AgentKit**, **Vercel AI SDK**, **Mastra**, and **Agent Protocol**.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/bigtool-ts)
|
|
8
|
+
[](https://github.com/wi-ski/bigtool-ts/blob/main/LICENSE)
|
|
9
|
+
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [The Problem](#the-problem)
|
|
13
|
+
- [Quick Start](#quick-start)
|
|
14
|
+
- [Framework Integrations](#framework-integrations)
|
|
15
|
+
- [LangGraph](#langgraph)
|
|
16
|
+
- [Inngest AgentKit](#inngest-agentkit)
|
|
17
|
+
- [Vercel AI SDK](#vercel-ai-sdk)
|
|
18
|
+
- [Mastra](#mastra)
|
|
19
|
+
- [Agent Protocol](#agent-protocol)
|
|
20
|
+
- [Features](#features)
|
|
21
|
+
- [API Reference](#api-reference)
|
|
22
|
+
- [createAgent](#createagentoptions)
|
|
23
|
+
- [LocalSource](#localsource)
|
|
24
|
+
- [MCPSource / createMCPSource](#mcpsource--createmcpsource)
|
|
25
|
+
- [DynamicSource](#dynamicsource)
|
|
26
|
+
- [withMetadata](#withmetadatatool-enhancement)
|
|
27
|
+
- [OramaSearch](#oramasearch)
|
|
28
|
+
- [Advanced Usage](#advanced-usage)
|
|
29
|
+
- [Architecture](#architecture)
|
|
30
|
+
|
|
31
|
+
## The Problem
|
|
32
|
+
|
|
33
|
+
When you have 100s or 1000s of tools, loading them all into context explodes the context window and degrades LLM performance. The model struggles to pick the right tool when presented with too many options.
|
|
34
|
+
|
|
35
|
+
**bigtool-ts** solves this by giving your agent a `search_tools` capabilityβit searches for relevant tools, loads only what it needs, and keeps context lean.
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm add bigtool-ts
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { createAgent, LocalSource, OramaSearch } from "bigtool-ts";
|
|
45
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
46
|
+
|
|
47
|
+
const agent = await createAgent({
|
|
48
|
+
llm: new ChatOpenAI({ model: "gpt-4o" }),
|
|
49
|
+
tools: [myCalculatorTool, myDatabaseTool, myGitHubTool],
|
|
50
|
+
search: new OramaSearch({ mode: "bm25" }),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const result = await agent.invoke({
|
|
54
|
+
messages: [{ role: "user", content: "Create a GitHub PR for this change" }],
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- **Dynamic Discovery** β Agent searches for tools by natural language query
|
|
61
|
+
- **Lazy Loading** β Tools loaded on-demand with LRU caching
|
|
62
|
+
- **Hybrid Search** β BM25 text search, vector semantic search, or both
|
|
63
|
+
- **Multiple Sources** β Local tools, MCP servers, or custom loaders
|
|
64
|
+
- **Zero Config Search** β BM25 mode works out of the box, no API keys needed
|
|
65
|
+
- **Multi-Framework** β Works with LangGraph, Inngest, Vercel AI, Mastra, and more
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Framework Integrations
|
|
70
|
+
|
|
71
|
+
bigtool-ts works with multiple AI agent frameworks. Choose your framework below for a quick-start snippet.
|
|
72
|
+
|
|
73
|
+
### LangGraph
|
|
74
|
+
|
|
75
|
+
Native integration via `createAgent()`. Returns a compiled StateGraph.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { createAgent, LocalSource, OramaSearch } from "bigtool-ts";
|
|
79
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
80
|
+
|
|
81
|
+
const agent = await createAgent({
|
|
82
|
+
llm: new ChatOpenAI({ model: "gpt-4o" }),
|
|
83
|
+
tools: [myCalculatorTool, myDatabaseTool, myGitHubTool],
|
|
84
|
+
search: new OramaSearch({ mode: "bm25" }),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const result = await agent.invoke({
|
|
88
|
+
messages: [{ role: "user", content: "Create a GitHub PR" }],
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Inngest AgentKit
|
|
93
|
+
|
|
94
|
+
Use the adapter with Inngest's multi-agent orchestration framework.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pnpm add @inngest/agent-kit
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { createAgent, openai } from "@inngest/agent-kit";
|
|
102
|
+
import {
|
|
103
|
+
createInngestAdapter,
|
|
104
|
+
DefaultToolCatalog,
|
|
105
|
+
DefaultToolLoader,
|
|
106
|
+
OramaSearch,
|
|
107
|
+
LocalSource,
|
|
108
|
+
} from "bigtool-ts";
|
|
109
|
+
|
|
110
|
+
// Setup bigtool-ts components
|
|
111
|
+
const catalog = new DefaultToolCatalog();
|
|
112
|
+
await catalog.register(new LocalSource(myTools));
|
|
113
|
+
|
|
114
|
+
const search = new OramaSearch({ mode: "bm25" });
|
|
115
|
+
await search.index(catalog.getAllMetadata());
|
|
116
|
+
|
|
117
|
+
const loader = new DefaultToolLoader(catalog);
|
|
118
|
+
|
|
119
|
+
// Create adapter
|
|
120
|
+
const adapter = createInngestAdapter({ catalog, loader, searchIndex: search });
|
|
121
|
+
|
|
122
|
+
// Use with Inngest agent
|
|
123
|
+
const agent = createAgent({
|
|
124
|
+
name: "tool-user",
|
|
125
|
+
model: openai({ model: "gpt-4o" }),
|
|
126
|
+
tools: [
|
|
127
|
+
adapter.createSearchTool(), // Search for tools
|
|
128
|
+
adapter.createCallToolTool(), // Execute found tools
|
|
129
|
+
],
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Vercel AI SDK
|
|
134
|
+
|
|
135
|
+
Use the adapter with Vercel's AI SDK for `generateText()` and `streamText()`.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
pnpm add ai @ai-sdk/openai
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { generateText } from "ai";
|
|
143
|
+
import { openai } from "@ai-sdk/openai";
|
|
144
|
+
import {
|
|
145
|
+
createVercelAdapter,
|
|
146
|
+
DefaultToolCatalog,
|
|
147
|
+
DefaultToolLoader,
|
|
148
|
+
OramaSearch,
|
|
149
|
+
LocalSource,
|
|
150
|
+
} from "bigtool-ts";
|
|
151
|
+
|
|
152
|
+
// Setup bigtool-ts components
|
|
153
|
+
const catalog = new DefaultToolCatalog();
|
|
154
|
+
await catalog.register(new LocalSource(myTools));
|
|
155
|
+
|
|
156
|
+
const search = new OramaSearch({ mode: "bm25" });
|
|
157
|
+
await search.index(catalog.getAllMetadata());
|
|
158
|
+
|
|
159
|
+
const loader = new DefaultToolLoader(catalog);
|
|
160
|
+
|
|
161
|
+
// Create adapter
|
|
162
|
+
const adapter = createVercelAdapter({ catalog, loader, searchIndex: search });
|
|
163
|
+
|
|
164
|
+
// Use with Vercel AI SDK
|
|
165
|
+
const result = await generateText({
|
|
166
|
+
model: openai("gpt-4o"),
|
|
167
|
+
tools: {
|
|
168
|
+
search_tools: adapter.createSearchTool(),
|
|
169
|
+
...await adapter.getToolsAsRecord(["github:create_pr", "slack:send"]),
|
|
170
|
+
},
|
|
171
|
+
prompt: "Create a PR and notify the team on Slack",
|
|
172
|
+
});
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Mastra
|
|
176
|
+
|
|
177
|
+
Use the adapter with Mastra's AI-native TypeScript framework.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pnpm add @mastra/core
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```typescript
|
|
184
|
+
import { Agent } from "@mastra/core/agent";
|
|
185
|
+
import {
|
|
186
|
+
createMastraAdapter,
|
|
187
|
+
DefaultToolCatalog,
|
|
188
|
+
DefaultToolLoader,
|
|
189
|
+
OramaSearch,
|
|
190
|
+
LocalSource,
|
|
191
|
+
} from "bigtool-ts";
|
|
192
|
+
|
|
193
|
+
// Setup bigtool-ts components
|
|
194
|
+
const catalog = new DefaultToolCatalog();
|
|
195
|
+
await catalog.register(new LocalSource(myTools));
|
|
196
|
+
|
|
197
|
+
const search = new OramaSearch({ mode: "bm25" });
|
|
198
|
+
await search.index(catalog.getAllMetadata());
|
|
199
|
+
|
|
200
|
+
const loader = new DefaultToolLoader(catalog);
|
|
201
|
+
|
|
202
|
+
// Create adapter
|
|
203
|
+
const adapter = createMastraAdapter({ catalog, loader, searchIndex: search });
|
|
204
|
+
|
|
205
|
+
// Use with Mastra Agent
|
|
206
|
+
const agent = new Agent({
|
|
207
|
+
id: "my-agent",
|
|
208
|
+
name: "Tool User",
|
|
209
|
+
model: "openai/gpt-4o",
|
|
210
|
+
tools: {
|
|
211
|
+
search_tools: adapter.createSearchTool(),
|
|
212
|
+
...await adapter.getToolsAsRecord(["github:create_pr"]),
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Agent Protocol
|
|
218
|
+
|
|
219
|
+
Expose tools via the Agent Protocol REST API specification.
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
import {
|
|
223
|
+
createAgentProtocolHandler,
|
|
224
|
+
DefaultToolCatalog,
|
|
225
|
+
DefaultToolLoader,
|
|
226
|
+
OramaSearch,
|
|
227
|
+
LocalSource,
|
|
228
|
+
} from "bigtool-ts";
|
|
229
|
+
|
|
230
|
+
// Setup bigtool-ts components
|
|
231
|
+
const catalog = new DefaultToolCatalog();
|
|
232
|
+
await catalog.register(new LocalSource(myTools));
|
|
233
|
+
|
|
234
|
+
const search = new OramaSearch({ mode: "bm25" });
|
|
235
|
+
await search.index(catalog.getAllMetadata());
|
|
236
|
+
|
|
237
|
+
const loader = new DefaultToolLoader(catalog);
|
|
238
|
+
|
|
239
|
+
// Create handler
|
|
240
|
+
const handler = createAgentProtocolHandler({ catalog, loader, searchIndex: search });
|
|
241
|
+
|
|
242
|
+
// Use with Express/Fastify/any HTTP framework
|
|
243
|
+
app.get("/tools", async (req, res) => {
|
|
244
|
+
const tools = await handler.listTools();
|
|
245
|
+
res.json({ tools });
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
app.post("/tools/search", async (req, res) => {
|
|
249
|
+
const tools = await handler.searchTools(req.body.query);
|
|
250
|
+
res.json({ tools });
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
app.post("/tools/execute", async (req, res) => {
|
|
254
|
+
const result = await handler.executeTool(req.body.name, req.body.args);
|
|
255
|
+
res.json(result);
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## API Reference
|
|
262
|
+
|
|
263
|
+
### `createAgent(options)`
|
|
264
|
+
|
|
265
|
+
Creates a LangGraph agent with dynamic tool discovery.
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { createAgent, OramaSearch } from "bigtool-ts";
|
|
269
|
+
|
|
270
|
+
const agent = await createAgent({
|
|
271
|
+
// Required
|
|
272
|
+
llm: new ChatOpenAI({ model: "gpt-4o" }),
|
|
273
|
+
search: new OramaSearch({ mode: "bm25" }),
|
|
274
|
+
|
|
275
|
+
// Tool sources (pick one or combine)
|
|
276
|
+
tools: [tool1, tool2], // Array of StructuredTool
|
|
277
|
+
sources: [localSource, mcpSource], // Array of ToolSource
|
|
278
|
+
|
|
279
|
+
// Optional
|
|
280
|
+
pinnedTools: [alwaysAvailableTool], // Always in context
|
|
281
|
+
systemPrompt: "You are a helpful assistant.",
|
|
282
|
+
searchLimit: 5, // Max tools per search (default: 5)
|
|
283
|
+
cacheSize: 100, // LRU cache size (default: 100)
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
// Use like any LangGraph agent
|
|
287
|
+
const result = await agent.invoke({
|
|
288
|
+
messages: [{ role: "user", content: "..." }],
|
|
289
|
+
});
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### `LocalSource`
|
|
293
|
+
|
|
294
|
+
Wraps in-memory StructuredTool instances.
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
import { LocalSource } from "bigtool-ts";
|
|
298
|
+
|
|
299
|
+
const source = new LocalSource([
|
|
300
|
+
myCalculatorTool,
|
|
301
|
+
myDatabaseTool,
|
|
302
|
+
myGitHubTool,
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
// Custom namespace (default: "local")
|
|
306
|
+
const namedSource = new LocalSource(tools, "my-tools");
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### `MCPSource` / `createMCPSource`
|
|
310
|
+
|
|
311
|
+
Connects to an MCP (Model Context Protocol) server. Two patterns supported:
|
|
312
|
+
|
|
313
|
+
#### Config-based (Recommended)
|
|
314
|
+
|
|
315
|
+
Pass a configuration object and let bigtool-ts manage the connection:
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
import { createMCPSource } from "bigtool-ts";
|
|
319
|
+
|
|
320
|
+
// stdio transport (local MCP server)
|
|
321
|
+
const githubSource = await createMCPSource({
|
|
322
|
+
name: "github",
|
|
323
|
+
transport: "stdio",
|
|
324
|
+
command: "npx",
|
|
325
|
+
args: ["-y", "@modelcontextprotocol/server-github"],
|
|
326
|
+
env: { GITHUB_TOKEN: process.env.GITHUB_TOKEN },
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// SSE transport (remote MCP server)
|
|
330
|
+
const remoteSource = await createMCPSource({
|
|
331
|
+
name: "remote-tools",
|
|
332
|
+
transport: "sse",
|
|
333
|
+
url: "https://mcp.example.com/sse",
|
|
334
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// Register with catalog
|
|
338
|
+
await catalog.register(githubSource);
|
|
339
|
+
await catalog.register(remoteSource);
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
#### Pre-connected Client
|
|
343
|
+
|
|
344
|
+
Pass an already-connected MCP client:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
import { MCPSource } from "bigtool-ts";
|
|
348
|
+
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
349
|
+
|
|
350
|
+
const mcpClient = new Client({ name: "my-client" });
|
|
351
|
+
await mcpClient.connect(transport);
|
|
352
|
+
|
|
353
|
+
const source = new MCPSource(mcpClient, {
|
|
354
|
+
namespace: "github", // Tool ID prefix (default: client.name)
|
|
355
|
+
refreshInterval: 60_000, // Re-fetch tool list every 60s
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Listen for tool list changes
|
|
359
|
+
source.onRefresh.on((metadata) => {
|
|
360
|
+
console.log("Tools refreshed:", metadata.length);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// Cleanup
|
|
364
|
+
source.dispose();
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### Loading 100 MCP Servers
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
import { createMCPSource } from "bigtool-ts";
|
|
371
|
+
|
|
372
|
+
const mcpConfigs = [
|
|
373
|
+
{ name: "github", transport: "stdio", command: "npx", args: ["-y", "@mcp/server-github"] },
|
|
374
|
+
{ name: "slack", transport: "stdio", command: "npx", args: ["-y", "@mcp/server-slack"] },
|
|
375
|
+
{ name: "notion", transport: "stdio", command: "npx", args: ["-y", "@mcp/server-notion"] },
|
|
376
|
+
// ... 97 more
|
|
377
|
+
];
|
|
378
|
+
|
|
379
|
+
// Connect to all servers in parallel
|
|
380
|
+
const sources = await Promise.all(
|
|
381
|
+
mcpConfigs.map(config => createMCPSource(config))
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
// Register all
|
|
385
|
+
for (const source of sources) {
|
|
386
|
+
await catalog.register(source);
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### `DynamicSource`
|
|
391
|
+
|
|
392
|
+
Lazy-loads tools on demand via a custom loader function.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import { DynamicSource } from "bigtool-ts";
|
|
396
|
+
|
|
397
|
+
const source = new DynamicSource({
|
|
398
|
+
// Metadata provided upfront for search indexing
|
|
399
|
+
metadata: [
|
|
400
|
+
{ id: "send_email", name: "send_email", description: "Send an email" },
|
|
401
|
+
{ id: "create_task", name: "create_task", description: "Create a task" },
|
|
402
|
+
],
|
|
403
|
+
// Loader called when tool is actually needed
|
|
404
|
+
loader: async (id) => {
|
|
405
|
+
const module = await import(`./tools/${id}.js`);
|
|
406
|
+
return module.default;
|
|
407
|
+
},
|
|
408
|
+
});
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### `withMetadata(tool, enhancement)`
|
|
412
|
+
|
|
413
|
+
Add search metadata to improve tool discovery.
|
|
414
|
+
|
|
415
|
+
```typescript
|
|
416
|
+
import { withMetadata } from "bigtool-ts";
|
|
417
|
+
|
|
418
|
+
const enhanced = withMetadata(myGitHubTool, {
|
|
419
|
+
categories: ["github", "git", "version-control"],
|
|
420
|
+
keywords: ["PR", "pull request", "merge", "branch"],
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
// Use enhanced tools in LocalSource
|
|
424
|
+
const source = new LocalSource([enhanced, otherTool]);
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
### `OramaSearch`
|
|
428
|
+
|
|
429
|
+
Search index powered by [@orama/orama](https://oramasearch.com/). Supports three modes for different use cases.
|
|
430
|
+
|
|
431
|
+
#### BM25 Mode (Default)
|
|
432
|
+
|
|
433
|
+
Fast keyword-based search. **No API keys needed.**
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import { OramaSearch } from "bigtool-ts";
|
|
437
|
+
|
|
438
|
+
const search = new OramaSearch({ mode: "bm25" });
|
|
439
|
+
|
|
440
|
+
// Or with field boosting
|
|
441
|
+
const search = new OramaSearch({
|
|
442
|
+
mode: "bm25",
|
|
443
|
+
boost: {
|
|
444
|
+
name: 2, // Tool name matches worth 2x
|
|
445
|
+
keywords: 1.5, // Keyword matches worth 1.5x
|
|
446
|
+
description: 1, // Normal weight
|
|
447
|
+
categories: 1, // Normal weight
|
|
448
|
+
},
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**When to use:** Most cases. Fast, deterministic, works offline.
|
|
453
|
+
|
|
454
|
+
#### Vector Mode
|
|
455
|
+
|
|
456
|
+
Semantic search using embeddings. Finds conceptually similar tools even without exact keyword matches.
|
|
457
|
+
|
|
458
|
+
```typescript
|
|
459
|
+
import { OramaSearch } from "bigtool-ts";
|
|
460
|
+
import { OpenAIEmbeddings } from "@langchain/openai";
|
|
461
|
+
|
|
462
|
+
const search = new OramaSearch({
|
|
463
|
+
mode: "vector",
|
|
464
|
+
embeddings: new OpenAIEmbeddings(),
|
|
465
|
+
});
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
**When to use:** When users describe tools conceptually (e.g., "something to post on social media" β finds `twitter_post`, `linkedin_share`).
|
|
469
|
+
|
|
470
|
+
#### Hybrid Mode
|
|
471
|
+
|
|
472
|
+
Combines BM25 and vector search for best of both worlds.
|
|
473
|
+
|
|
474
|
+
```typescript
|
|
475
|
+
import { OramaSearch } from "bigtool-ts";
|
|
476
|
+
import { OpenAIEmbeddings } from "@langchain/openai";
|
|
477
|
+
|
|
478
|
+
const search = new OramaSearch({
|
|
479
|
+
mode: "hybrid",
|
|
480
|
+
embeddings: new OpenAIEmbeddings(),
|
|
481
|
+
weights: {
|
|
482
|
+
bm25: 0.4, // 40% keyword matching
|
|
483
|
+
vector: 0.6, // 60% semantic similarity
|
|
484
|
+
},
|
|
485
|
+
boost: {
|
|
486
|
+
name: 2,
|
|
487
|
+
keywords: 1.5,
|
|
488
|
+
description: 1,
|
|
489
|
+
categories: 1,
|
|
490
|
+
},
|
|
491
|
+
});
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**When to use:** Large tool catalogs where both exact matches and semantic similarity matter.
|
|
495
|
+
|
|
496
|
+
#### Search Mode Comparison
|
|
497
|
+
|
|
498
|
+
| Mode | Speed | API Keys | Best For |
|
|
499
|
+
|------|-------|----------|----------|
|
|
500
|
+
| `bm25` | β‘ Fast | None | Exact matches, offline use |
|
|
501
|
+
| `vector` | π’ Slower | Required | Semantic similarity |
|
|
502
|
+
| `hybrid` | π’ Slower | Required | Large catalogs, mixed queries |
|
|
503
|
+
|
|
504
|
+
#### Search Options
|
|
505
|
+
|
|
506
|
+
```typescript
|
|
507
|
+
const results = await search.search("create github pr", {
|
|
508
|
+
limit: 10, // Max results (default: 5)
|
|
509
|
+
threshold: 0.3, // Min score 0-1 (default: 0)
|
|
510
|
+
categories: ["git"], // Filter by category
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
// Results format
|
|
514
|
+
// [{ toolId: "github:create_pr", score: 0.95, matchType: "bm25" }, ...]
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Advanced Usage
|
|
518
|
+
|
|
519
|
+
### Combining Multiple Sources
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
import { createAgent, LocalSource, MCPSource, OramaSearch } from "bigtool-ts";
|
|
523
|
+
|
|
524
|
+
const agent = await createAgent({
|
|
525
|
+
llm,
|
|
526
|
+
sources: [
|
|
527
|
+
new LocalSource(coreTools, "core"),
|
|
528
|
+
new MCPSource(githubMcp, { namespace: "github" }),
|
|
529
|
+
new MCPSource(slackMcp, { namespace: "slack" }),
|
|
530
|
+
],
|
|
531
|
+
search: new OramaSearch({ mode: "bm25" }),
|
|
532
|
+
});
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### Pinned Tools (Always Available)
|
|
536
|
+
|
|
537
|
+
Some tools should always be in context without searching:
|
|
538
|
+
|
|
539
|
+
```typescript
|
|
540
|
+
const agent = await createAgent({
|
|
541
|
+
llm,
|
|
542
|
+
tools: myLargeToolCollection,
|
|
543
|
+
search: new OramaSearch({ mode: "bm25" }),
|
|
544
|
+
pinnedTools: [
|
|
545
|
+
helpTool, // "Show available commands"
|
|
546
|
+
exitTool, // "End the conversation"
|
|
547
|
+
],
|
|
548
|
+
});
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Custom Catalog and Loader
|
|
552
|
+
|
|
553
|
+
For advanced use cases, build components individually:
|
|
554
|
+
|
|
555
|
+
```typescript
|
|
556
|
+
import {
|
|
557
|
+
DefaultToolCatalog,
|
|
558
|
+
DefaultToolLoader,
|
|
559
|
+
OramaSearch,
|
|
560
|
+
LocalSource,
|
|
561
|
+
} from "bigtool-ts";
|
|
562
|
+
|
|
563
|
+
// 1. Create catalog
|
|
564
|
+
const catalog = new DefaultToolCatalog();
|
|
565
|
+
|
|
566
|
+
// 2. Register sources
|
|
567
|
+
await catalog.register(new LocalSource(tools));
|
|
568
|
+
|
|
569
|
+
// 3. Create search index
|
|
570
|
+
const search = new OramaSearch({ mode: "bm25" });
|
|
571
|
+
await search.index(catalog.getAllMetadata());
|
|
572
|
+
|
|
573
|
+
// 4. Create loader with custom cache settings
|
|
574
|
+
const loader = new DefaultToolLoader(catalog, {
|
|
575
|
+
maxSize: 50,
|
|
576
|
+
ttl: 5 * 60 * 1000, // 5 minutes
|
|
577
|
+
});
|
|
578
|
+
|
|
579
|
+
// 5. Listen for catalog changes
|
|
580
|
+
catalog.onToolsChanged.on(({ added, removed }) => {
|
|
581
|
+
console.log(`Tools changed: +${added.length} -${removed.length}`);
|
|
582
|
+
search.reindex();
|
|
583
|
+
});
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## Architecture
|
|
587
|
+
|
|
588
|
+
```
|
|
589
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
590
|
+
β createAgent() β
|
|
591
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
592
|
+
β
|
|
593
|
+
βΌ
|
|
594
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
595
|
+
β ToolSource[] β
|
|
596
|
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
|
|
597
|
+
β β LocalSource β β MCPSource β βDynamicSource β β
|
|
598
|
+
β β (in-memory) β β (MCP server) β β (lazy load) β β
|
|
599
|
+
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
|
|
600
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
601
|
+
β
|
|
602
|
+
βΌ
|
|
603
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
604
|
+
β DefaultToolCatalog β
|
|
605
|
+
β Registry of all tool metadata from sources β
|
|
606
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
607
|
+
β
|
|
608
|
+
βββββββββββββββββ΄ββββββββββββββββ
|
|
609
|
+
βΌ βΌ
|
|
610
|
+
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
|
|
611
|
+
β OramaSearch β β DefaultToolLoader β
|
|
612
|
+
β BM25 / Vector / Hybrid β β LRU-cached loading β
|
|
613
|
+
β β β β
|
|
614
|
+
β query β [toolId, ...] β β toolId β StructuredToolβ
|
|
615
|
+
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
|
|
616
|
+
β β
|
|
617
|
+
βββββββββββββββββ¬ββββββββββββββββ
|
|
618
|
+
βΌ
|
|
619
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
620
|
+
β LangGraph StateGraph β
|
|
621
|
+
β β
|
|
622
|
+
β START β agent β route β search/execute β agent β ... β END β
|
|
623
|
+
β β
|
|
624
|
+
β Agent node has: β
|
|
625
|
+
β - search_tools (always available) β
|
|
626
|
+
β - pinnedTools (always available) β
|
|
627
|
+
β - selectedTools (loaded after search) β
|
|
628
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Flow:**
|
|
632
|
+
|
|
633
|
+
1. **Catalog** collects metadata from all sources
|
|
634
|
+
2. **Search** indexes metadata for fast querying
|
|
635
|
+
3. **Agent** calls `search_tools("github PR")` β gets relevant tool IDs
|
|
636
|
+
4. **Loader** loads actual tool implementations (with LRU caching)
|
|
637
|
+
5. **Agent** executes tools and continues conversation
|
|
638
|
+
|
|
639
|
+
## License
|
|
640
|
+
|
|
641
|
+
MIT
|