@samrahimi/smol-js 0.7.2 → 0.7.3
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 +377 -49
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
**A TypeScript agentic framework inspired by [smolagents](https://github.com/huggingface/smolagents).**
|
|
4
4
|
|
|
5
|
-
Build AI agents that solve tasks autonomously using the ReAct (Reasoning + Acting) pattern. Agents can write and execute JavaScript code, call tools, delegate to other agents, and orchestrate complex workflows via YAML definitions.
|
|
5
|
+
Build AI agents that solve tasks autonomously using the ReAct (Reasoning + Acting) pattern. Agents can write and execute JavaScript code, call tools, run shell commands, delegate to other agents, and orchestrate complex workflows via YAML definitions.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/@samrahimi/smol-js)
|
|
8
8
|
[](https://opensource.org/licenses/MIT)
|
|
9
9
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
|
-
- **
|
|
13
|
-
- `CodeAgent`
|
|
14
|
-
- `ToolUseAgent`
|
|
12
|
+
- **Three Agent Types**:
|
|
13
|
+
- `CodeAgent` — Writes and executes JavaScript code in a sandboxed VM
|
|
14
|
+
- `ToolUseAgent` — Uses native LLM function calling (OpenAI-style)
|
|
15
|
+
- `TerminalAgent` — Executes shell commands on your macOS terminal
|
|
15
16
|
- **YAML Orchestration**: Define complex agent workflows declaratively
|
|
16
|
-
- **
|
|
17
|
-
- **Extensible Tool System**: Built-in tools + easy custom tool creation
|
|
17
|
+
- **Custom Tool Plugins**: Drop standalone `.ts` tool files into a folder — no build step, no config
|
|
18
18
|
- **Nested Agents**: Manager-worker patterns for hierarchical task delegation
|
|
19
|
+
- **Sandboxed Execution**: JavaScript runs in Node's vm module with state persistence
|
|
19
20
|
- **Exa.ai Integration**: Semantic web search, content extraction, and research automation
|
|
20
|
-
- **Dynamic Imports**: Import npm packages on-the-fly
|
|
21
|
+
- **Dynamic Imports**: Import npm packages on-the-fly in CodeAgent
|
|
21
22
|
- **OpenAI-Compatible**: Works with OpenRouter, OpenAI, Azure, Anthropic, and local servers
|
|
22
23
|
- **Streaming**: Real-time output streaming from the LLM
|
|
23
24
|
- **Memory Management**: Context-aware with truncate/compact strategies
|
|
@@ -29,6 +30,12 @@ Build AI agents that solve tasks autonomously using the ReAct (Reasoning + Actin
|
|
|
29
30
|
npm install @samrahimi/smol-js
|
|
30
31
|
```
|
|
31
32
|
|
|
33
|
+
Or run workflows directly without installing:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx @samrahimi/smol-js workflow.yaml --task "Your task here"
|
|
37
|
+
```
|
|
38
|
+
|
|
32
39
|
## Quick Start
|
|
33
40
|
|
|
34
41
|
### Via CLI (YAML Workflows)
|
|
@@ -101,6 +108,8 @@ const result = await agent.run('Calculate the first 10 prime numbers');
|
|
|
101
108
|
console.log(result.output); // [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
|
|
102
109
|
```
|
|
103
110
|
|
|
111
|
+
---
|
|
112
|
+
|
|
104
113
|
## Agent Types
|
|
105
114
|
|
|
106
115
|
### CodeAgent
|
|
@@ -127,7 +136,7 @@ await agent.run('Analyze the file data.csv and create a summary');
|
|
|
127
136
|
|
|
128
137
|
### ToolUseAgent
|
|
129
138
|
|
|
130
|
-
Uses native LLM function calling (OpenAI-style tool calling).
|
|
139
|
+
Uses native LLM function calling (OpenAI-style tool calling). Best for LLMs with strong structured-output capabilities.
|
|
131
140
|
|
|
132
141
|
```typescript
|
|
133
142
|
import { ToolUseAgent, OpenAIModel } from '@samrahimi/smol-js';
|
|
@@ -142,6 +151,258 @@ const agent = new ToolUseAgent({
|
|
|
142
151
|
await agent.run('Search for recent AI papers and summarize the top 3');
|
|
143
152
|
```
|
|
144
153
|
|
|
154
|
+
### TerminalAgent
|
|
155
|
+
|
|
156
|
+
Accomplishes tasks by reasoning about and executing shell commands on your terminal. Tuned for macOS — uses zsh, understands BSD conventions, and gives you full visibility into what it's doing.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import { TerminalAgent, OpenAIModel } from '@samrahimi/smol-js';
|
|
160
|
+
|
|
161
|
+
const agent = new TerminalAgent({
|
|
162
|
+
model,
|
|
163
|
+
maxSteps: 10,
|
|
164
|
+
commandDelay: 5, // seconds before running commands (Ctrl+C window)
|
|
165
|
+
maxOutputLength: 8000, // chars of command output fed back to the LLM
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
await agent.run('Set up a new Node.js project with TypeScript and Jest');
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**How it works:**
|
|
172
|
+
1. Agent reasons about what shell commands to run
|
|
173
|
+
2. Commands are displayed for your review (with a configurable delay — default 5 seconds — so you can Ctrl+C if anything looks wrong)
|
|
174
|
+
3. Commands execute sequentially via `/bin/zsh`
|
|
175
|
+
4. stdout, stderr, and exit codes are captured and fed back as observations
|
|
176
|
+
5. Repeats until the agent signals completion with `FINAL_ANSWER:`
|
|
177
|
+
|
|
178
|
+
**Key behaviours:**
|
|
179
|
+
- **Verbose by default.** You see the agent's reasoning, pending commands, and live output at every step.
|
|
180
|
+
- **Safety delay.** Every command batch pauses for 5 seconds before execution. Read what's about to run. Press Ctrl+C to abort.
|
|
181
|
+
- **Error recovery.** If a command fails (non-zero exit code), the agent sees the error and tries a different approach.
|
|
182
|
+
- **No user-assigned tools.** TerminalAgent is a pure shell agent. It can only delegate to sub-agents (via the manager-worker pattern) — it doesn't use function-calling tools.
|
|
183
|
+
|
|
184
|
+
#### TerminalAgent in YAML
|
|
185
|
+
|
|
186
|
+
```yaml
|
|
187
|
+
name: system-inspector
|
|
188
|
+
description: Gathers system information using shell commands.
|
|
189
|
+
|
|
190
|
+
model:
|
|
191
|
+
modelId: anthropic/claude-sonnet-4.5
|
|
192
|
+
baseUrl: https://openrouter.ai/api/v1
|
|
193
|
+
|
|
194
|
+
agents:
|
|
195
|
+
inspector:
|
|
196
|
+
type: TerminalAgent
|
|
197
|
+
maxSteps: 5
|
|
198
|
+
commandDelay: 3
|
|
199
|
+
customInstructions: >
|
|
200
|
+
Gather system information: OS version, CPU, RAM, disk usage,
|
|
201
|
+
and list running processes sorted by CPU. Summarize your findings.
|
|
202
|
+
|
|
203
|
+
entrypoint: inspector
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Run it:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npx @samrahimi/smol-js system-inspector.yaml --task "What are my system specs?"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### TerminalAgent as a Sub-Agent (Manager-Worker)
|
|
213
|
+
|
|
214
|
+
One of the most powerful patterns: a ToolUseAgent manager that delegates shell tasks to a TerminalAgent while handling other work itself.
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
name: manager-demo
|
|
218
|
+
description: >
|
|
219
|
+
A ToolUseAgent manager orchestrates a TerminalAgent (shell commands)
|
|
220
|
+
and a ToolUseAgent file reader. The manager delegates and synthesizes.
|
|
221
|
+
|
|
222
|
+
model:
|
|
223
|
+
modelId: anthropic/claude-sonnet-4.5
|
|
224
|
+
baseUrl: https://openrouter.ai/api/v1
|
|
225
|
+
|
|
226
|
+
tools:
|
|
227
|
+
read:
|
|
228
|
+
type: read_file
|
|
229
|
+
|
|
230
|
+
agents:
|
|
231
|
+
terminal_worker:
|
|
232
|
+
type: TerminalAgent
|
|
233
|
+
description: Runs shell commands to gather system information.
|
|
234
|
+
maxSteps: 3
|
|
235
|
+
customInstructions: >
|
|
236
|
+
Gather the requested system information by running shell commands.
|
|
237
|
+
When you have everything, call final_answer with a clear summary.
|
|
238
|
+
|
|
239
|
+
file_worker:
|
|
240
|
+
type: ToolUseAgent
|
|
241
|
+
description: Reads files from the project and summarizes their contents.
|
|
242
|
+
tools:
|
|
243
|
+
- read
|
|
244
|
+
maxSteps: 3
|
|
245
|
+
customInstructions: >
|
|
246
|
+
Read the file(s) you are asked about and return a concise summary
|
|
247
|
+
of the relevant details.
|
|
248
|
+
|
|
249
|
+
manager:
|
|
250
|
+
type: ToolUseAgent
|
|
251
|
+
description: >
|
|
252
|
+
Delegates to terminal_worker for shell tasks and file_worker for
|
|
253
|
+
file reads, then synthesizes the results.
|
|
254
|
+
agents:
|
|
255
|
+
- terminal_worker
|
|
256
|
+
- file_worker
|
|
257
|
+
maxSteps: 5
|
|
258
|
+
customInstructions: >
|
|
259
|
+
You are a manager agent. You have no tools of your own — your job
|
|
260
|
+
is to delegate to your sub-agents and combine their results.
|
|
261
|
+
- terminal_worker: use for anything that needs shell commands or live system state
|
|
262
|
+
- file_worker: use for reading files on disk
|
|
263
|
+
Delegate both tasks in parallel if possible, then synthesize a final answer.
|
|
264
|
+
|
|
265
|
+
entrypoint: manager
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Run it:
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
npx @samrahimi/smol-js examples/js/agents/manager-demo.yaml \
|
|
272
|
+
--task "Tell me my macOS version and summarize the smol-js README"
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Custom Tool Plugins
|
|
278
|
+
|
|
279
|
+
The custom tool system lets you write standalone tool files that any agent can use — without modifying the framework or writing boilerplate. Drop a `.ts` file into a folder, point the CLI at it, and it just works.
|
|
280
|
+
|
|
281
|
+
### How It Works
|
|
282
|
+
|
|
283
|
+
1. You write a single `.ts` file that exports `TOOL_METADATA` and an `execute()` function
|
|
284
|
+
2. You tell the CLI where to find your tools: `--custom-tools-folder ./my-tools`
|
|
285
|
+
3. At startup, smol-js scans the folder, discovers your tools, and makes them available in YAML workflows
|
|
286
|
+
4. When an agent calls your tool, smol-js spawns an isolated [Bun](https://bun.sh) process to run it
|
|
287
|
+
|
|
288
|
+
The tool file is **transport-agnostic**. It has zero knowledge of how it's invoked. All the process management, argument passing, and result serialization is handled by a harness adapter that ships with the package.
|
|
289
|
+
|
|
290
|
+
### Writing a Custom Tool
|
|
291
|
+
|
|
292
|
+
A custom tool is a single `.ts` file. Here's a complete example — `WeatherLookup.ts`:
|
|
293
|
+
|
|
294
|
+
```typescript
|
|
295
|
+
/**
|
|
296
|
+
* WeatherLookup — fetches weather data from Open-Meteo API.
|
|
297
|
+
*
|
|
298
|
+
* This file exports two things and nothing else:
|
|
299
|
+
* 1. TOOL_METADATA — describes the tool to the smol-js scanner
|
|
300
|
+
* 2. execute(args) — the actual function; called by the toolHarness adapter
|
|
301
|
+
*
|
|
302
|
+
* It has zero knowledge of how it is invoked. The harness handles argument
|
|
303
|
+
* deserialization, protocol framing, and process lifecycle.
|
|
304
|
+
*
|
|
305
|
+
* Dependencies are resolved by Bun at runtime — no package.json or
|
|
306
|
+
* npm install needed.
|
|
307
|
+
*/
|
|
308
|
+
|
|
309
|
+
import chalk from 'chalk'; // Bun resolves this from npm automatically
|
|
310
|
+
import dayjs from 'dayjs'; // Same here — zero config
|
|
311
|
+
|
|
312
|
+
// TOOL_METADATA — parsed by the scanner at discovery time.
|
|
313
|
+
// The `name` field MUST match this file's basename (WeatherLookup).
|
|
314
|
+
export const TOOL_METADATA = {
|
|
315
|
+
name: 'WeatherLookup',
|
|
316
|
+
description: 'Fetches current weather for a given city using the Open-Meteo API.',
|
|
317
|
+
inputs: {
|
|
318
|
+
city: {
|
|
319
|
+
type: 'string',
|
|
320
|
+
description: 'The city to look up (e.g. "London", "Tokyo")',
|
|
321
|
+
required: true,
|
|
322
|
+
},
|
|
323
|
+
units: {
|
|
324
|
+
type: 'string',
|
|
325
|
+
description: 'Temperature units: "celsius" (default) or "fahrenheit"',
|
|
326
|
+
required: false,
|
|
327
|
+
default: 'celsius',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
outputType: 'string',
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
// execute — the tool's entry point. Just a function.
|
|
334
|
+
// args contains the deserialized parameters passed by the agent.
|
|
335
|
+
// Return your result. Throw an Error if something goes wrong.
|
|
336
|
+
// console.log() calls are streamed back as output the agent can see.
|
|
337
|
+
export async function execute(args: Record<string, unknown>): Promise<string> {
|
|
338
|
+
const city = args.city as string;
|
|
339
|
+
console.log(chalk.dim(` Geocoding "${city}"...`));
|
|
340
|
+
|
|
341
|
+
// ... fetch weather data ...
|
|
342
|
+
|
|
343
|
+
return `Weather in ${city}: 22°C, Partly cloudy`;
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### The Rules
|
|
348
|
+
|
|
349
|
+
1. **File name must match `TOOL_METADATA.name`** — if the metadata says `WeatherLookup`, the file must be `WeatherLookup.ts`
|
|
350
|
+
2. **Export exactly two things**: `TOOL_METADATA` and `execute()`
|
|
351
|
+
3. **Dependencies are free** — Bun resolves npm packages natively. Just `import` them. No `package.json`, no `npm install`.
|
|
352
|
+
4. **Don't add a `main()` function.** Don't read `process.argv`. Don't write `[TOOL_RESULT]` lines. The framework's harness handles all of that.
|
|
353
|
+
5. **`execute` must be async** and return a `Promise`
|
|
354
|
+
6. **`console.log()` works** — output is streamed back and visible to the agent as context
|
|
355
|
+
|
|
356
|
+
### Using Custom Tools in a Workflow
|
|
357
|
+
|
|
358
|
+
Reference your tool by its metadata name in the `tools` section:
|
|
359
|
+
|
|
360
|
+
```yaml
|
|
361
|
+
name: weather-assistant
|
|
362
|
+
description: A helpful weather assistant.
|
|
363
|
+
|
|
364
|
+
model:
|
|
365
|
+
modelId: anthropic/claude-haiku-4.5
|
|
366
|
+
baseUrl: https://openrouter.ai/api/v1
|
|
367
|
+
|
|
368
|
+
tools:
|
|
369
|
+
WeatherLookup:
|
|
370
|
+
type: WeatherLookup # Must match TOOL_METADATA.name
|
|
371
|
+
|
|
372
|
+
agents:
|
|
373
|
+
assistant:
|
|
374
|
+
type: ToolUseAgent
|
|
375
|
+
tools:
|
|
376
|
+
- WeatherLookup
|
|
377
|
+
maxSteps: 5
|
|
378
|
+
customInstructions: >
|
|
379
|
+
You are a friendly weather assistant. Use WeatherLookup to get
|
|
380
|
+
current conditions. Present results conversationally.
|
|
381
|
+
|
|
382
|
+
entrypoint: assistant
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Run it:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
npx @samrahimi/smol-js weather-assistant.yaml \
|
|
389
|
+
--task "What's the weather in Tokyo?" \
|
|
390
|
+
--custom-tools-folder ./custom-tools
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Tool-Maker Agent
|
|
394
|
+
|
|
395
|
+
If you'd rather have an AI write your custom tools, there's a tool-maker agent in the examples:
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
npx @samrahimi/smol-js examples/js/agents/tool-maker/tool-maker.yaml \
|
|
399
|
+
--task "Create a tool that converts currencies using the ExchangeRate API"
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
The tool-maker reads the WeatherLookup reference, understands the contract, generates a new standalone tool file, creates a matching YAML workflow, and outputs a ready-to-run `npx` command. Drop the output into any `--custom-tools-folder` and it works.
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
145
406
|
## Configuration
|
|
146
407
|
|
|
147
408
|
### Environment Variables
|
|
@@ -183,11 +444,25 @@ const agent = new CodeAgent({
|
|
|
183
444
|
persistent: false, // Retain memory between run() calls
|
|
184
445
|
maxContextLength: 100000, // Token limit for context
|
|
185
446
|
memoryStrategy: 'truncate', // 'truncate' or 'compact'
|
|
186
|
-
additionalAuthorizedImports: ['lodash'],
|
|
187
|
-
workingDirectory: '/path/to/dir',
|
|
447
|
+
additionalAuthorizedImports: ['lodash'], // npm packages (CodeAgent only)
|
|
448
|
+
workingDirectory: '/path/to/dir', // Working dir for fs operations
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### TerminalAgent Configuration
|
|
453
|
+
|
|
454
|
+
```typescript
|
|
455
|
+
const agent = new TerminalAgent({
|
|
456
|
+
model,
|
|
457
|
+
maxSteps: 10,
|
|
458
|
+
commandDelay: 5, // Seconds before executing commands (default: 5)
|
|
459
|
+
maxOutputLength: 8000, // Max chars of output fed back per command (default: 8000)
|
|
460
|
+
customInstructions: 'Focus on Python tooling only.',
|
|
188
461
|
});
|
|
189
462
|
```
|
|
190
463
|
|
|
464
|
+
---
|
|
465
|
+
|
|
191
466
|
## Built-in Tools
|
|
192
467
|
|
|
193
468
|
- **FinalAnswerTool**: Return the final result (always available)
|
|
@@ -200,9 +475,9 @@ const agent = new CodeAgent({
|
|
|
200
475
|
- **ExaResearchTool**: Multi-step research workflow
|
|
201
476
|
- **AgentTool**: Wrap agents as tools for nested architectures
|
|
202
477
|
|
|
203
|
-
## Creating Custom Tools
|
|
478
|
+
## Creating Custom Tools (Class-Based)
|
|
204
479
|
|
|
205
|
-
|
|
480
|
+
For tools that need to live inside your TypeScript project (rather than as standalone plugin files), extend the `Tool` class:
|
|
206
481
|
|
|
207
482
|
```typescript
|
|
208
483
|
import { Tool } from '@samrahimi/smol-js';
|
|
@@ -256,6 +531,8 @@ const orchestrator = new Orchestrator();
|
|
|
256
531
|
await orchestrator.runWorkflow(workflow, 'Your task here');
|
|
257
532
|
```
|
|
258
533
|
|
|
534
|
+
---
|
|
535
|
+
|
|
259
536
|
## YAML Workflow System
|
|
260
537
|
|
|
261
538
|
Define complex agent architectures declaratively:
|
|
@@ -282,7 +559,7 @@ tools:
|
|
|
282
559
|
type: write_file
|
|
283
560
|
|
|
284
561
|
agents:
|
|
285
|
-
# Worker
|
|
562
|
+
# Worker: specialized in research
|
|
286
563
|
researcher:
|
|
287
564
|
type: ToolUseAgent
|
|
288
565
|
tools:
|
|
@@ -290,25 +567,32 @@ agents:
|
|
|
290
567
|
- read
|
|
291
568
|
maxSteps: 8
|
|
292
569
|
temperature: 0.3
|
|
293
|
-
customInstructions: "
|
|
570
|
+
customInstructions: "Be thorough and cite sources."
|
|
294
571
|
|
|
295
|
-
# Worker
|
|
572
|
+
# Worker: specialized in writing
|
|
296
573
|
writer:
|
|
297
574
|
type: CodeAgent
|
|
298
575
|
tools:
|
|
299
576
|
- write
|
|
300
577
|
maxSteps: 5
|
|
301
578
|
temperature: 0.7
|
|
302
|
-
customInstructions: "
|
|
579
|
+
customInstructions: "Create clear, engaging content."
|
|
580
|
+
|
|
581
|
+
# Worker: runs shell commands
|
|
582
|
+
sysadmin:
|
|
583
|
+
type: TerminalAgent
|
|
584
|
+
maxSteps: 5
|
|
585
|
+
customInstructions: "Handle any system or environment setup tasks."
|
|
303
586
|
|
|
304
|
-
# Manager
|
|
587
|
+
# Manager: delegates to all three workers
|
|
305
588
|
manager:
|
|
306
589
|
type: ToolUseAgent
|
|
307
590
|
agents:
|
|
308
|
-
- researcher
|
|
309
|
-
- writer
|
|
591
|
+
- researcher
|
|
592
|
+
- writer
|
|
593
|
+
- sysadmin
|
|
310
594
|
maxSteps: 10
|
|
311
|
-
customInstructions: "
|
|
595
|
+
customInstructions: "Coordinate research, writing, and system tasks. Delegate appropriately."
|
|
312
596
|
|
|
313
597
|
entrypoint: manager
|
|
314
598
|
```
|
|
@@ -319,24 +603,26 @@ Run it:
|
|
|
319
603
|
npx @samrahimi/smol-js research-workflow.yaml --task "Write a report on quantum computing"
|
|
320
604
|
```
|
|
321
605
|
|
|
606
|
+
---
|
|
607
|
+
|
|
322
608
|
## Nested Agents (Manager-Worker Pattern)
|
|
323
609
|
|
|
324
610
|
Use agents as tools for hierarchical task delegation:
|
|
325
611
|
|
|
326
612
|
```typescript
|
|
327
|
-
import { CodeAgent, ToolUseAgent, OpenAIModel, AgentTool } from '@samrahimi/smol-js';
|
|
613
|
+
import { CodeAgent, ToolUseAgent, TerminalAgent, OpenAIModel, AgentTool } from '@samrahimi/smol-js';
|
|
328
614
|
|
|
329
615
|
// Create specialized worker agents
|
|
330
616
|
const mathAgent = new CodeAgent({
|
|
331
617
|
model,
|
|
332
618
|
maxSteps: 5,
|
|
333
|
-
verboseLevel: LogLevel.OFF,
|
|
619
|
+
verboseLevel: LogLevel.OFF,
|
|
334
620
|
});
|
|
335
621
|
|
|
336
|
-
const
|
|
622
|
+
const sysAgent = new TerminalAgent({
|
|
337
623
|
model,
|
|
338
|
-
|
|
339
|
-
|
|
624
|
+
maxSteps: 5,
|
|
625
|
+
commandDelay: 3,
|
|
340
626
|
verboseLevel: LogLevel.OFF,
|
|
341
627
|
});
|
|
342
628
|
|
|
@@ -344,25 +630,27 @@ const researchAgent = new ToolUseAgent({
|
|
|
344
630
|
const mathExpert = new AgentTool({
|
|
345
631
|
agent: mathAgent,
|
|
346
632
|
name: 'math_expert',
|
|
347
|
-
description: 'Delegate math and calculation tasks
|
|
633
|
+
description: 'Delegate math and calculation tasks',
|
|
348
634
|
});
|
|
349
635
|
|
|
350
|
-
const
|
|
351
|
-
agent:
|
|
352
|
-
name: '
|
|
353
|
-
description: 'Delegate
|
|
636
|
+
const sysAdmin = new AgentTool({
|
|
637
|
+
agent: sysAgent,
|
|
638
|
+
name: 'sys_admin',
|
|
639
|
+
description: 'Delegate shell commands and system tasks',
|
|
354
640
|
});
|
|
355
641
|
|
|
356
|
-
//
|
|
642
|
+
// Manager delegates to workers
|
|
357
643
|
const manager = new ToolUseAgent({
|
|
358
644
|
model,
|
|
359
|
-
tools: [mathExpert,
|
|
645
|
+
tools: [mathExpert, sysAdmin],
|
|
360
646
|
maxSteps: 10,
|
|
361
647
|
});
|
|
362
648
|
|
|
363
|
-
await manager.run('
|
|
649
|
+
await manager.run('Check disk usage and calculate how many GB are free as a percentage');
|
|
364
650
|
```
|
|
365
651
|
|
|
652
|
+
---
|
|
653
|
+
|
|
366
654
|
## Exa.ai Integration
|
|
367
655
|
|
|
368
656
|
Three tools for web research powered by Exa.ai:
|
|
@@ -413,10 +701,11 @@ const researchTool = new ExaResearchTool({
|
|
|
413
701
|
// 4. Synthesizes findings into a markdown report with citations
|
|
414
702
|
// 5. Returns the complete report (typically 20-90 seconds)
|
|
415
703
|
|
|
416
|
-
|
|
417
|
-
await agent.run('Use exa_research to write a comprehensive report on quantum computing breakthroughs in 2024');
|
|
704
|
+
await agent.run('Use exa_research to write a report on quantum computing breakthroughs in 2024');
|
|
418
705
|
```
|
|
419
706
|
|
|
707
|
+
---
|
|
708
|
+
|
|
420
709
|
## Built-in Capabilities (CodeAgent)
|
|
421
710
|
|
|
422
711
|
The CodeAgent sandbox includes:
|
|
@@ -448,6 +737,8 @@ const agent = new CodeAgent({
|
|
|
448
737
|
|
|
449
738
|
Packages are fetched from [jsdelivr CDN](https://www.jsdelivr.com/) and cached in `~/.smol-js/packages/`.
|
|
450
739
|
|
|
740
|
+
---
|
|
741
|
+
|
|
451
742
|
## Examples
|
|
452
743
|
|
|
453
744
|
See the `examples/js/` directory for complete examples:
|
|
@@ -455,11 +746,17 @@ See the `examples/js/` directory for complete examples:
|
|
|
455
746
|
- **main.ts**: Main demo with custom tools and YAML workflows
|
|
456
747
|
- **custom-tools.ts**: Custom tool implementations (TimestampTool, TextStatsTool, SlugifyTool)
|
|
457
748
|
- **agents/**: YAML workflow definitions
|
|
458
|
-
- `
|
|
749
|
+
- `custom-tool-workflow.yaml`: Weather assistant using the standalone custom tool plugin system
|
|
750
|
+
- `manager-demo.yaml`: Manager + TerminalAgent worker + file-reader worker
|
|
751
|
+
- `tool-maker/tool-maker.yaml`: AI agent that generates custom tool files
|
|
459
752
|
- `bloomberg.yaml`: Bloomberg research workflow
|
|
460
753
|
- `policy.yaml`: Policy analysis workflow
|
|
461
754
|
- `simple-test.yaml`: Simple test workflow
|
|
462
755
|
|
|
756
|
+
And the `custom-tools/` directory at the repo root contains example standalone tool plugins:
|
|
757
|
+
|
|
758
|
+
- `WeatherLookup.ts`: Fetches weather from Open-Meteo (demonstrates npm deps, streaming output, error handling)
|
|
759
|
+
|
|
463
760
|
Run an example:
|
|
464
761
|
|
|
465
762
|
```bash
|
|
@@ -468,6 +765,8 @@ npm install
|
|
|
468
765
|
npx tsx main.ts
|
|
469
766
|
```
|
|
470
767
|
|
|
768
|
+
---
|
|
769
|
+
|
|
471
770
|
## Memory Management
|
|
472
771
|
|
|
473
772
|
Agents track all execution steps and manage context automatically:
|
|
@@ -494,11 +793,15 @@ await persistentAgent.run('What is X?'); // Remembers X = 42
|
|
|
494
793
|
- **truncate**: Removes oldest steps when over token limit
|
|
495
794
|
- **compact**: Uses LLM to summarize older steps
|
|
496
795
|
|
|
796
|
+
---
|
|
797
|
+
|
|
497
798
|
## Session Logging
|
|
498
799
|
|
|
499
800
|
All sessions are logged to `~/.smol-js/`:
|
|
500
|
-
- `session-<timestamp>.log`
|
|
501
|
-
- `packages/`
|
|
801
|
+
- `session-<timestamp>.log` — Full session transcript with color codes
|
|
802
|
+
- `packages/` — Cached npm packages from dynamic imports
|
|
803
|
+
|
|
804
|
+
---
|
|
502
805
|
|
|
503
806
|
## API Reference
|
|
504
807
|
|
|
@@ -533,7 +836,20 @@ class ToolUseAgent extends Agent {
|
|
|
533
836
|
}
|
|
534
837
|
|
|
535
838
|
interface ToolUseAgentConfig extends AgentConfig {
|
|
536
|
-
enableParallelToolCalls?: boolean;
|
|
839
|
+
enableParallelToolCalls?: boolean;
|
|
840
|
+
}
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
### TerminalAgent
|
|
844
|
+
|
|
845
|
+
```typescript
|
|
846
|
+
class TerminalAgent extends Agent {
|
|
847
|
+
constructor(config: TerminalAgentConfig)
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
interface TerminalAgentConfig extends AgentConfig {
|
|
851
|
+
commandDelay?: number; // Seconds before executing (default: 5)
|
|
852
|
+
maxOutputLength?: number; // Max chars of output per command (default: 8000)
|
|
537
853
|
}
|
|
538
854
|
```
|
|
539
855
|
|
|
@@ -585,11 +901,14 @@ class Orchestrator {
|
|
|
585
901
|
```typescript
|
|
586
902
|
class YAMLLoader {
|
|
587
903
|
registerToolType(typeName: string, toolClass: typeof Tool): void
|
|
904
|
+
registerToolInstance(name: string, tool: Tool): void
|
|
588
905
|
loadFromFile(filePath: string): Workflow
|
|
589
906
|
loadFromString(yaml: string): Workflow
|
|
590
907
|
}
|
|
591
908
|
```
|
|
592
909
|
|
|
910
|
+
---
|
|
911
|
+
|
|
593
912
|
## CLI Reference
|
|
594
913
|
|
|
595
914
|
```bash
|
|
@@ -601,18 +920,24 @@ npx @samrahimi/smol-js run <workflow.yaml> [options]
|
|
|
601
920
|
npx @samrahimi/smol-js validate <workflow.yaml>
|
|
602
921
|
|
|
603
922
|
# Options
|
|
604
|
-
--task, -t <task>
|
|
605
|
-
--
|
|
606
|
-
--
|
|
923
|
+
--task, -t <task> Task description (prompted if not provided)
|
|
924
|
+
--custom-tools-folder <path> Path to folder containing standalone tool plugins
|
|
925
|
+
--quiet, -q Reduce output verbosity
|
|
926
|
+
--help, -h Show help message
|
|
607
927
|
```
|
|
608
928
|
|
|
929
|
+
---
|
|
930
|
+
|
|
609
931
|
## Security Considerations
|
|
610
932
|
|
|
611
933
|
- **Sandboxed Execution**: Code runs in Node's vm module, isolated from the main process
|
|
612
|
-
- **Authorized Imports**: Only explicitly allowed npm packages can be imported
|
|
934
|
+
- **Authorized Imports**: Only explicitly allowed npm packages can be imported in CodeAgent
|
|
613
935
|
- **File System Isolation**: fs operations are restricted to configured working directory
|
|
614
|
-
- **Execution Delay**: Configurable delay before code execution allows user interruption (Ctrl+C)
|
|
615
|
-
- **Timeout Protection**: Code execution has a configurable timeout (default: 30s)
|
|
936
|
+
- **Execution Delay**: Configurable delay before code/command execution allows user interruption (Ctrl+C)
|
|
937
|
+
- **Timeout Protection**: Code execution has a configurable timeout (default: 30s); shell commands timeout at 2 minutes
|
|
938
|
+
- **Isolated Tool Processes**: Custom tool plugins run in separate Bun processes — a misbehaving tool can't affect the main framework
|
|
939
|
+
|
|
940
|
+
---
|
|
616
941
|
|
|
617
942
|
## Comparison with Python smolagents
|
|
618
943
|
|
|
@@ -625,9 +950,12 @@ npx @samrahimi/smol-js validate <workflow.yaml>
|
|
|
625
950
|
| Async support | Optional | All tools are async |
|
|
626
951
|
| HTTP requests | Requires tool | Built-in `fetch()` |
|
|
627
952
|
| Remote executors | E2B, Docker, etc. | Local only |
|
|
628
|
-
| Agent types | CodeAgent, ToolCallingAgent | CodeAgent, ToolUseAgent |
|
|
953
|
+
| Agent types | CodeAgent, ToolCallingAgent | CodeAgent, ToolUseAgent, TerminalAgent |
|
|
629
954
|
| YAML workflows | ❌ | ✅ |
|
|
630
955
|
| Exa.ai integration | ❌ | ✅ Built-in |
|
|
956
|
+
| Custom tool plugins | ❌ | ✅ Standalone `.ts` files |
|
|
957
|
+
|
|
958
|
+
---
|
|
631
959
|
|
|
632
960
|
## Contributing
|
|
633
961
|
|
|
@@ -635,8 +963,8 @@ Contributions are welcome! Please follow OOP principles and open an issue or PR
|
|
|
635
963
|
|
|
636
964
|
```bash
|
|
637
965
|
# Clone and install
|
|
638
|
-
git clone https://github.com/samrahimi/
|
|
639
|
-
cd
|
|
966
|
+
git clone https://github.com/samrahimi/smol.git
|
|
967
|
+
cd smol/smol-js
|
|
640
968
|
npm install
|
|
641
969
|
|
|
642
970
|
# Build
|
|
@@ -659,4 +987,4 @@ MIT
|
|
|
659
987
|
|
|
660
988
|
## Credits
|
|
661
989
|
|
|
662
|
-
This is a TypeScript framework inspired by [smolagents](https://github.com/huggingface/smolagents) by Hugging Face, with additional features including YAML orchestration, ToolUseAgent, and Exa.ai integration.
|
|
990
|
+
This is a TypeScript framework inspired by [smolagents](https://github.com/huggingface/smolagents) by Hugging Face, with additional features including YAML orchestration, ToolUseAgent, TerminalAgent, custom tool plugins, and Exa.ai integration.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@samrahimi/smol-js",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "A TypeScript agentic framework - CodeAgent and ToolUseAgent with YAML orchestration, built-in tools, and Exa.ai integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -72,5 +72,10 @@
|
|
|
72
72
|
},
|
|
73
73
|
"engines": {
|
|
74
74
|
"node": ">=18.0.0"
|
|
75
|
+
},
|
|
76
|
+
"repository": {
|
|
77
|
+
"type": "git",
|
|
78
|
+
"url": "https://github.com/samrahimi/smol.git",
|
|
79
|
+
"directory": "smol-js"
|
|
75
80
|
}
|
|
76
81
|
}
|