@samrahimi/smol-js 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/README.md ADDED
@@ -0,0 +1,295 @@
1
+ # smol-js
2
+
3
+ A TypeScript port of the [smolagents](https://github.com/huggingface/smolagents) agentic framework. This library provides a CodeAgent that can solve tasks by generating and executing JavaScript code in a sandboxed environment.
4
+
5
+ ## Features
6
+
7
+ - **CodeAgent**: An LLM-powered agent that generates JavaScript code to solve tasks
8
+ - **Multi-step execution**: Variables persist between steps for complex workflows
9
+ - **Tool system**: Extensible tools that the agent can use as functions
10
+ - **Dynamic imports**: Import npm packages on-the-fly via CDN
11
+ - **OpenAI-compatible API**: Works with OpenRouter, OpenAI, Azure, and local servers
12
+ - **Streaming support**: Real-time output streaming from the LLM
13
+ - **Color-coded logging**: Beautiful terminal output with syntax highlighting
14
+ - **Error recovery**: Agent can recover from errors and try different approaches
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @samrahimi/smol-js
20
+ ```
21
+
22
+ Or with yarn:
23
+
24
+ ```bash
25
+ yarn add @samrahimi/smol-js
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import { CodeAgent, OpenAIModel } from '@samrahimi/smol-js';
32
+
33
+ // Create the model (uses OPENAI_API_KEY env var)
34
+ const model = new OpenAIModel({
35
+ modelId: 'anthropic/claude-sonnet-4.5', // default, via OpenRouter
36
+ });
37
+
38
+ // Create the agent
39
+ const agent = new CodeAgent({
40
+ model,
41
+ maxSteps: 10,
42
+ });
43
+
44
+ // Run a task
45
+ const result = await agent.run('Calculate the first 10 prime numbers');
46
+
47
+ console.log(result.output); // [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
48
+ ```
49
+
50
+ ## Configuration
51
+
52
+ ### Environment Variables
53
+
54
+ ```bash
55
+ # Required: API key for LLM provider
56
+ OPENAI_API_KEY=your-api-key
57
+
58
+ # Or use OpenRouter specifically
59
+ OPENROUTER_API_KEY=your-openrouter-key
60
+ ```
61
+
62
+ ### Model Configuration
63
+
64
+ ```typescript
65
+ const model = new OpenAIModel({
66
+ modelId: 'gpt-4', // Model identifier
67
+ apiKey: 'sk-...', // API key (or use env var)
68
+ baseUrl: 'https://api.openai.com/v1', // API endpoint
69
+ maxTokens: 4096, // Max tokens to generate
70
+ temperature: 0.7, // Generation temperature
71
+ timeout: 120000, // Request timeout in ms
72
+ });
73
+ ```
74
+
75
+ ### Agent Configuration
76
+
77
+ ```typescript
78
+ const agent = new CodeAgent({
79
+ model,
80
+ tools: [myTool], // Custom tools
81
+ maxSteps: 20, // Max iterations (default: 20)
82
+ codeExecutionDelay: 5000, // Delay before execution in ms (default: 5000)
83
+ customInstructions: '...', // Additional prompt instructions
84
+ verboseLevel: LogLevel.INFO, // Logging level
85
+ streamOutputs: true, // Stream LLM output
86
+ additionalAuthorizedImports: ['lodash', 'dayjs'], // Allowed npm packages
87
+ workingDirectory: '/path/to/dir', // Working dir for fs operations
88
+ });
89
+ ```
90
+
91
+ ## Creating Tools
92
+
93
+ Tools extend the agent's capabilities. Create a tool by extending the `Tool` class:
94
+
95
+ ```typescript
96
+ import { Tool } from '@samrahimi/smol-js';
97
+ import type { ToolInputs } from '@samrahimi/smol-js';
98
+
99
+ class WeatherTool extends Tool {
100
+ readonly name = 'get_weather';
101
+ readonly description = 'Get current weather for a city';
102
+ readonly inputs: ToolInputs = {
103
+ city: {
104
+ type: 'string',
105
+ description: 'The city name',
106
+ required: true,
107
+ },
108
+ };
109
+ readonly outputType = 'object';
110
+
111
+ async execute(args: Record<string, unknown>): Promise<unknown> {
112
+ const city = args.city as string;
113
+ // Fetch weather data...
114
+ return { city, temperature: 22, condition: 'sunny' };
115
+ }
116
+ }
117
+
118
+ // Use with agent
119
+ const agent = new CodeAgent({
120
+ model,
121
+ tools: [new WeatherTool()],
122
+ });
123
+ ```
124
+
125
+ Or use the `createTool` helper:
126
+
127
+ ```typescript
128
+ import { createTool } from '@samrahimi/smol-js';
129
+
130
+ const addNumbers = createTool({
131
+ name: 'add',
132
+ description: 'Adds two numbers',
133
+ inputs: {
134
+ a: { type: 'number', description: 'First number' },
135
+ b: { type: 'number', description: 'Second number' },
136
+ },
137
+ outputType: 'number',
138
+ execute: async (args) => (args.a as number) + (args.b as number),
139
+ });
140
+ ```
141
+
142
+ ## Dynamic Imports
143
+
144
+ The agent can import npm packages dynamically using `importPackage()`:
145
+
146
+ ```typescript
147
+ const agent = new CodeAgent({
148
+ model,
149
+ additionalAuthorizedImports: ['lodash', 'dayjs', 'uuid'],
150
+ });
151
+
152
+ // The agent can now use:
153
+ // const _ = await importPackage('lodash');
154
+ // const dayjs = await importPackage('dayjs');
155
+ ```
156
+
157
+ Packages are fetched from [esm.sh](https://esm.sh) CDN.
158
+
159
+ ## Built-in Capabilities
160
+
161
+ The agent has access to:
162
+
163
+ - `console.log()` / `print()` - Output logging
164
+ - `fs` - File system operations (read, write, mkdir, etc.)
165
+ - `path` - Path utilities
166
+ - `fetch()` - HTTP requests
167
+ - `JSON`, `Math`, `Date` - Standard JavaScript globals
168
+ - `final_answer(value)` - Return the final result
169
+
170
+ ## Log Levels
171
+
172
+ ```typescript
173
+ import { LogLevel } from '@samrahimi/smol-js';
174
+
175
+ LogLevel.OFF // No output
176
+ LogLevel.ERROR // Errors only
177
+ LogLevel.INFO // Normal output (default)
178
+ LogLevel.DEBUG // Detailed debugging
179
+ ```
180
+
181
+ ## Session Logging
182
+
183
+ All sessions are logged to `~/.smol-js/session-<timestamp>.log`.
184
+
185
+ ## Examples
186
+
187
+ See the `examples/` folder for complete examples:
188
+
189
+ 1. **01-simple-math.ts** - Basic calculation task
190
+ 2. **02-dynamic-imports.ts** - Using npm packages dynamically
191
+ 3. **03-variable-persistence.ts** - Multi-step state management
192
+ 4. **04-research-with-tools.ts** - Custom tools for research tasks
193
+ 5. **05-error-recovery.ts** - Handling and recovering from errors
194
+
195
+ Run all examples:
196
+
197
+ ```bash
198
+ npm run run-examples
199
+ ```
200
+
201
+ Or run a specific example:
202
+
203
+ ```bash
204
+ npx tsx examples/01-simple-math.ts
205
+ ```
206
+
207
+ ## API Reference
208
+
209
+ ### CodeAgent
210
+
211
+ Main agent class that generates and executes JavaScript code.
212
+
213
+ ```typescript
214
+ class CodeAgent {
215
+ constructor(config: CodeAgentConfig)
216
+ run(task: string, reset?: boolean): Promise<RunResult>
217
+ stop(): void
218
+ reset(): void
219
+ addTool(tool: Tool): void
220
+ removeTool(name: string): boolean
221
+ getTools(): Map<string, Tool>
222
+ getMemory(): AgentMemory
223
+ getExecutor(): LocalExecutor
224
+ }
225
+ ```
226
+
227
+ ### RunResult
228
+
229
+ ```typescript
230
+ interface RunResult {
231
+ output: unknown; // Final answer
232
+ steps: MemoryStep[]; // All execution steps
233
+ tokenUsage: TokenUsage; // Total token usage
234
+ duration: number; // Total time in ms
235
+ }
236
+ ```
237
+
238
+ ### Tool
239
+
240
+ ```typescript
241
+ abstract class Tool {
242
+ abstract readonly name: string;
243
+ abstract readonly description: string;
244
+ abstract readonly inputs: ToolInputs;
245
+ abstract readonly outputType: string;
246
+
247
+ abstract execute(args: Record<string, unknown>): Promise<unknown>;
248
+ setup(): Promise<void>;
249
+ call(args: Record<string, unknown>): Promise<unknown>;
250
+ toCodePrompt(): string;
251
+ }
252
+ ```
253
+
254
+ ### LocalExecutor
255
+
256
+ ```typescript
257
+ class LocalExecutor {
258
+ constructor(config?: ExecutorConfig)
259
+ execute(code: string): Promise<CodeExecutionOutput>
260
+ sendTools(tools: Record<string, Tool>): void
261
+ sendVariables(variables: Record<string, unknown>): void
262
+ reset(): void
263
+ getState(): Record<string, unknown>
264
+ }
265
+ ```
266
+
267
+ ## Architectural Differences from Python smolagents
268
+
269
+ | Feature | Python smolagents | smol-js |
270
+ |---------|------------------|---------|
271
+ | Code execution | Python interpreter | Node.js vm module |
272
+ | Imports | `import` statement | `await importPackage()` |
273
+ | Tool definition | `@tool` decorator | Class extending `Tool` |
274
+ | Async support | Optional | All tools are async |
275
+ | Remote executors | E2B, Docker, etc. | Local only (for now) |
276
+ | Agent types | CodeAgent, ToolCallingAgent | CodeAgent only (for now) |
277
+
278
+ ## Security Considerations
279
+
280
+ - Code executes in a sandboxed vm context
281
+ - Only authorized npm packages can be imported
282
+ - File system access is restricted to working directory
283
+ - Configurable execution delay allows user interruption
284
+
285
+ ## Contributing
286
+
287
+ Contributions are welcome! Please open an issue or PR.
288
+
289
+ ## License
290
+
291
+ MIT
292
+
293
+ ## Credits
294
+
295
+ This is a TypeScript port of [smolagents](https://github.com/huggingface/smolagents) by Hugging Face.