@samrahimi/smol-js 0.6.4 → 0.7.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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import OpenAI from 'openai';
1
+ import OpenAI from 'openai/index.mjs';
2
2
 
3
3
  /**
4
4
  * Core types for smol-js
@@ -207,6 +207,136 @@ interface OrchestratorEvent {
207
207
  data: unknown;
208
208
  timestamp: number;
209
209
  }
210
+ type JSONEventType = 'run_start' | 'workflow_loaded' | 'agent_start' | 'agent_step' | 'agent_thinking' | 'agent_tool_call' | 'agent_tool_result' | 'agent_observation' | 'agent_end' | 'run_end' | 'error' | 'log';
211
+ interface JSONEventBase {
212
+ runId: string;
213
+ timestamp: number;
214
+ type: JSONEventType;
215
+ }
216
+ interface JSONRunStartEvent extends JSONEventBase {
217
+ type: 'run_start';
218
+ data: {
219
+ workflowPath: string;
220
+ task: string;
221
+ cwd?: string;
222
+ };
223
+ }
224
+ interface JSONWorkflowLoadedEvent extends JSONEventBase {
225
+ type: 'workflow_loaded';
226
+ data: {
227
+ name: string;
228
+ description?: string;
229
+ agents: string[];
230
+ tools: string[];
231
+ entrypoint: string;
232
+ };
233
+ }
234
+ interface JSONRunEndEvent extends JSONEventBase {
235
+ type: 'run_end';
236
+ data: {
237
+ success: boolean;
238
+ output: unknown;
239
+ totalDuration: number;
240
+ totalTokens: number;
241
+ totalSteps: number;
242
+ };
243
+ }
244
+ interface JSONAgentStartEvent extends JSONEventBase {
245
+ type: 'agent_start';
246
+ agentName: string;
247
+ depth: number;
248
+ data: {
249
+ task: string;
250
+ agentType: 'CodeAgent' | 'ToolUseAgent';
251
+ maxSteps: number;
252
+ };
253
+ }
254
+ interface JSONAgentEndEvent extends JSONEventBase {
255
+ type: 'agent_end';
256
+ agentName: string;
257
+ depth: number;
258
+ data: {
259
+ output: unknown;
260
+ totalSteps: number;
261
+ tokenUsage: TokenUsage;
262
+ duration: number;
263
+ success: boolean;
264
+ };
265
+ }
266
+ interface JSONAgentStepEvent extends JSONEventBase {
267
+ type: 'agent_step';
268
+ agentName: string;
269
+ depth: number;
270
+ data: {
271
+ stepNumber: number;
272
+ maxSteps: number;
273
+ phase: 'start' | 'thinking' | 'acting' | 'complete';
274
+ };
275
+ }
276
+ interface JSONAgentThinkingEvent extends JSONEventBase {
277
+ type: 'agent_thinking';
278
+ agentName: string;
279
+ depth: number;
280
+ data: {
281
+ stepNumber: number;
282
+ content: string;
283
+ isPartial?: boolean;
284
+ };
285
+ }
286
+ interface JSONAgentToolCallEvent extends JSONEventBase {
287
+ type: 'agent_tool_call';
288
+ agentName: string;
289
+ depth: number;
290
+ data: {
291
+ stepNumber: number;
292
+ toolCallId: string;
293
+ toolName: string;
294
+ arguments: Record<string, unknown>;
295
+ };
296
+ }
297
+ interface JSONAgentToolResultEvent extends JSONEventBase {
298
+ type: 'agent_tool_result';
299
+ agentName: string;
300
+ depth: number;
301
+ data: {
302
+ stepNumber: number;
303
+ toolCallId: string;
304
+ toolName: string;
305
+ result: unknown;
306
+ error?: string;
307
+ duration: number;
308
+ };
309
+ }
310
+ interface JSONAgentObservationEvent extends JSONEventBase {
311
+ type: 'agent_observation';
312
+ agentName: string;
313
+ depth: number;
314
+ data: {
315
+ stepNumber: number;
316
+ observation: string;
317
+ codeAction?: string;
318
+ logs?: string;
319
+ };
320
+ }
321
+ interface JSONErrorEvent extends JSONEventBase {
322
+ type: 'error';
323
+ agentName?: string;
324
+ depth?: number;
325
+ data: {
326
+ message: string;
327
+ stack?: string;
328
+ stepNumber?: number;
329
+ };
330
+ }
331
+ interface JSONLogEvent extends JSONEventBase {
332
+ type: 'log';
333
+ data: {
334
+ level: 'info' | 'warn' | 'error' | 'debug';
335
+ message: string;
336
+ };
337
+ }
338
+ type JSONEvent = JSONRunStartEvent | JSONWorkflowLoadedEvent | JSONRunEndEvent | JSONAgentStartEvent | JSONAgentEndEvent | JSONAgentStepEvent | JSONAgentThinkingEvent | JSONAgentToolCallEvent | JSONAgentToolResultEvent | JSONAgentObservationEvent | JSONErrorEvent | JSONLogEvent;
339
+ type OutputFormat = 'text' | 'json';
210
340
 
211
341
  /**
212
342
  * Tool base class for smol-js
@@ -592,6 +722,15 @@ declare abstract class Agent {
592
722
  removeTool(name: string): boolean;
593
723
  /** Get agent name */
594
724
  getName(): string;
725
+ /** Get agent type identifier */
726
+ getType(): string;
727
+ /** Get max steps configuration */
728
+ getMaxSteps(): number;
729
+ /** Set the event callback (useful for orchestration) */
730
+ setOnEvent(callback: (event: {
731
+ type: string;
732
+ data: unknown;
733
+ }) => void): void;
595
734
  /** Sleep for a specified duration */
596
735
  protected sleep(ms: number): Promise<void>;
597
736
  }
@@ -1021,26 +1160,141 @@ declare class ExaGetContentsTool extends Tool {
1021
1160
  }
1022
1161
 
1023
1162
  /**
1024
- * ExaResearchTool - Deep research on a topic using Exa.ai
1163
+ * ExaResearchTool - Agentic web research using Exa.ai Research API
1164
+ *
1165
+ * The Research API is an asynchronous, multi-step pipeline that transforms
1166
+ * open-ended questions into grounded reports with citations. The system performs
1167
+ * planning, searching, and reasoning to produce comprehensive research outputs.
1025
1168
  *
1026
- * Performs multi-step research by combining search and content retrieval
1027
- * to produce comprehensive findings on a topic.
1169
+ * See: https://docs.exa.ai/reference/exa-research
1028
1170
  */
1029
1171
 
1030
1172
  interface ExaResearchConfig {
1031
1173
  apiKey?: string;
1174
+ model?: 'exa-research-fast' | 'exa-research' | 'exa-research-pro';
1175
+ pollInterval?: number;
1176
+ maxPollTime?: number;
1032
1177
  }
1033
1178
  declare class ExaResearchTool extends Tool {
1034
1179
  readonly name = "exa_research";
1035
- readonly description = "Perform deep research on a single topic using Exa.ai. Searches for relevant sources, retrieves their content, and finds similar pages for comprehensive coverage. Returns a structured research summary with sources. Use this for thorough research on any topic.";
1180
+ readonly description = "Perform comprehensive web research using Exa.ai's agentic research system. Provide natural-language instructions about what to research, and the AI research agent will plan searches, gather sources, extract facts, and synthesize findings into a detailed markdown report with citations. Ideal for deep research on any topic. Results typically complete in 20-90 seconds.";
1036
1181
  readonly inputs: ToolInputs;
1037
1182
  readonly outputType = "string";
1038
1183
  private apiKey;
1184
+ private defaultModel;
1185
+ private pollInterval;
1186
+ private maxPollTime;
1039
1187
  constructor(config?: ExaResearchConfig);
1040
1188
  setup(): Promise<void>;
1041
1189
  execute(args: Record<string, unknown>): Promise<string>;
1042
1190
  }
1043
1191
 
1192
+ /**
1193
+ * ProxyTool - Bridges the smol-js agent runtime to an external standalone tool
1194
+ * executed in an isolated Bun process.
1195
+ *
1196
+ * The tool file is never imported into the main Node.js process. Instead, when
1197
+ * an agent invokes this proxy, it spawns `bun run <toolPath>` and communicates
1198
+ * via a lightweight stdin/stdout JSON protocol.
1199
+ *
1200
+ * Protocol (stdout of child):
1201
+ * - Lines prefixed with `[TOOL_OUTPUT]` are streaming log lines from the tool.
1202
+ * - A line prefixed with `[TOOL_RESULT]` contains the JSON-serialized return value.
1203
+ * - A line prefixed with `[TOOL_ERROR]` means the tool threw; payload is the message.
1204
+ * - Any other stdout line is treated as a streaming log line.
1205
+ *
1206
+ * Extensibility note: The transport (child_process + stdio) is encapsulated here.
1207
+ * A future subclass or factory could swap this for HTTP, gRPC, or IPC with no change
1208
+ * to the ProxyTool interface visible to agents or YAML definitions.
1209
+ */
1210
+
1211
+ interface ProxyToolConfig {
1212
+ /** Absolute path to the .ts or .js tool file */
1213
+ toolPath: string;
1214
+ /** Tool name (must match the class name inside the file) */
1215
+ name: string;
1216
+ /** Human-readable description exposed to agents */
1217
+ description: string;
1218
+ /** Input schema that the LLM will see */
1219
+ inputs: ToolInputs;
1220
+ /** Output type label */
1221
+ outputType: string;
1222
+ /** Max execution time in ms (default 60 s) */
1223
+ timeout?: number;
1224
+ }
1225
+ declare class ProxyTool extends Tool {
1226
+ readonly name: string;
1227
+ readonly description: string;
1228
+ readonly inputs: ToolInputs;
1229
+ readonly outputType: string;
1230
+ private readonly toolPath;
1231
+ private readonly timeout;
1232
+ private bunPath;
1233
+ constructor(config: ProxyToolConfig);
1234
+ /**
1235
+ * Ensure Bun is available before first invocation.
1236
+ */
1237
+ setup(): Promise<void>;
1238
+ /**
1239
+ * Spawn the tool in a Bun child process, pass serialized args via CLI,
1240
+ * stream stdout back as log lines, and parse the final result.
1241
+ */
1242
+ execute(args: Record<string, unknown>): Promise<unknown>;
1243
+ private processLine;
1244
+ }
1245
+
1246
+ /**
1247
+ * CustomToolScanner — discovers standalone tool files in a directory and
1248
+ * extracts their metadata so that ProxyTool instances can be registered
1249
+ * with the YAML loader.
1250
+ *
1251
+ * Convention over Configuration:
1252
+ * • Each file in the custom-tools folder must export a default metadata
1253
+ * object conforming to CustomToolMetadata (see standalone tool wrapper docs).
1254
+ * • The exported class name (or `name` field in metadata) MUST match the
1255
+ * file's basename (without extension). E.g. `WeatherLookup.ts` → name: "WeatherLookup".
1256
+ * • The tool is referenced in YAML by that same name.
1257
+ *
1258
+ * Metadata Extraction (zero-import approach):
1259
+ * We read the file as text and use a lightweight regex to pull the
1260
+ * `TOOL_METADATA` export block. This keeps the scanner decoupled from
1261
+ * Bun/ESM and lets it run purely in the Node.js main process.
1262
+ * The metadata block must be a single JSON object assigned to
1263
+ * `export const TOOL_METADATA = { ... };`
1264
+ */
1265
+
1266
+ interface CustomToolMetadata {
1267
+ /** Must match the file's basename (sans extension) */
1268
+ name: string;
1269
+ /** Human-readable description shown to the LLM */
1270
+ description: string;
1271
+ /** Input schema identical to Tool.inputs */
1272
+ inputs: ToolInputs;
1273
+ /** Output type label */
1274
+ outputType: string;
1275
+ /** Optional execution timeout in ms */
1276
+ timeout?: number;
1277
+ }
1278
+ interface DiscoveredTool {
1279
+ /** Absolute path to the tool file */
1280
+ filePath: string;
1281
+ /** Parsed metadata */
1282
+ metadata: CustomToolMetadata;
1283
+ }
1284
+ /**
1285
+ * Scan a directory for custom tool files and extract their metadata.
1286
+ *
1287
+ * @param folderPath Absolute path to the custom-tools directory.
1288
+ * @returns Array of discovered tools with parsed metadata.
1289
+ * @throws If any file fails metadata extraction.
1290
+ */
1291
+ declare function scanCustomTools(folderPath: string): DiscoveredTool[];
1292
+ /**
1293
+ * Scan a folder and return a Map<toolName, ProxyTool> ready for registration
1294
+ * with YAMLLoader.
1295
+ */
1296
+ declare function loadCustomTools(folderPath: string): Map<string, ProxyTool>;
1297
+
1044
1298
  /**
1045
1299
  * System prompts for CodeAgent
1046
1300
  *
@@ -1105,10 +1359,17 @@ interface LoadedWorkflow {
1105
1359
  }
1106
1360
  declare class YAMLLoader {
1107
1361
  private customTools;
1362
+ private toolInstances;
1108
1363
  /**
1109
- * Register a custom tool type for use in YAML definitions.
1364
+ * Register a custom tool type (class) for use in YAML definitions.
1110
1365
  */
1111
1366
  registerToolType(typeName: string, toolClass: new (config?: Record<string, unknown>) => Tool): void;
1367
+ /**
1368
+ * Register a pre-built tool instance for use in YAML definitions.
1369
+ * Used by the custom tool system to register ProxyTool instances
1370
+ * that are created by the scanner rather than by class instantiation.
1371
+ */
1372
+ registerToolInstance(typeName: string, tool: Tool): void;
1112
1373
  /**
1113
1374
  * Load a workflow from a YAML file path.
1114
1375
  */
@@ -1131,6 +1392,32 @@ declare class YAMLLoader {
1131
1392
  private buildAgent;
1132
1393
  }
1133
1394
 
1395
+ /**
1396
+ * JSONOutputHandler - Emits structured NDJSON events for machine-readable CLI output.
1397
+ */
1398
+
1399
+ interface JSONOutputConfig {
1400
+ runId: string;
1401
+ verbose?: boolean;
1402
+ }
1403
+ declare class JSONOutputHandler {
1404
+ private readonly runId;
1405
+ private readonly startTime;
1406
+ constructor(config: JSONOutputConfig);
1407
+ private emit;
1408
+ emitRunStart(workflowPath: string, task: string, cwd?: string): void;
1409
+ emitWorkflowLoaded(name: string, description: string | undefined, agents: string[], tools: string[], entrypoint: string): void;
1410
+ emitRunEnd(success: boolean, output: unknown, totalTokens: number, totalSteps: number): void;
1411
+ emitAgentStart(agentName: string, depth: number, task: string, agentType: string, maxSteps: number): void;
1412
+ emitAgentEnd(agentName: string, depth: number, output: unknown, totalSteps: number, tokenUsage: TokenUsage | undefined, duration: number, success: boolean): void;
1413
+ emitAgentStep(agentName: string, depth: number, stepNumber: number, maxSteps: number, phase: string): void;
1414
+ emitAgentThinking(agentName: string, depth: number, stepNumber: number, content: string, isPartial: boolean): void;
1415
+ emitToolCall(agentName: string, depth: number, stepNumber: number, toolCallId: string, toolName: string, args: Record<string, unknown>): void;
1416
+ emitToolResult(agentName: string, depth: number, stepNumber: number, toolCallId: string, toolName: string, result: unknown, error: string | undefined, duration: number): void;
1417
+ emitObservation(agentName: string, depth: number, stepNumber: number, observation: string, codeAction: string | undefined, logs: string | undefined): void;
1418
+ emitError(message: string, stack?: string, agentName?: string, depth?: number, stepNumber?: number): void;
1419
+ }
1420
+
1134
1421
  /**
1135
1422
  * Orchestrator - Loads, runs, and provides real-time visibility into agent execution
1136
1423
  */
@@ -1140,12 +1427,20 @@ interface OrchestratorConfig {
1140
1427
  verbose?: boolean;
1141
1428
  /** Callback for orchestrator events */
1142
1429
  onEvent?: (event: OrchestratorEvent) => void;
1430
+ /** Output format: 'text' for chalk-formatted console, 'json' for NDJSON streaming */
1431
+ outputFormat?: OutputFormat;
1432
+ /** Unique run identifier (required for JSON output) */
1433
+ runId?: string;
1434
+ /** Working directory for agent file operations */
1435
+ cwd?: string;
1143
1436
  }
1144
1437
  declare class Orchestrator {
1145
1438
  private loader;
1146
1439
  private config;
1147
1440
  private activeAgents;
1148
1441
  private eventLog;
1442
+ private jsonOutput;
1443
+ private isJsonMode;
1149
1444
  constructor(config?: OrchestratorConfig);
1150
1445
  /**
1151
1446
  * Load a workflow from a YAML file.
@@ -1154,11 +1449,11 @@ declare class Orchestrator {
1154
1449
  /**
1155
1450
  * Load a workflow from YAML string.
1156
1451
  */
1157
- loadWorkflowFromString(yamlContent: string): LoadedWorkflow;
1452
+ loadWorkflowFromString(yamlContent: string, sourcePath?: string): LoadedWorkflow;
1158
1453
  /**
1159
1454
  * Run a loaded workflow with a task.
1160
1455
  */
1161
- runWorkflow(workflow: LoadedWorkflow, task: string): Promise<RunResult>;
1456
+ runWorkflow(workflow: LoadedWorkflow, task: string, workflowPath?: string): Promise<RunResult>;
1162
1457
  /**
1163
1458
  * Run a standalone agent with a task.
1164
1459
  */
@@ -1167,6 +1462,10 @@ declare class Orchestrator {
1167
1462
  * Instrument an agent with orchestrator event tracking.
1168
1463
  */
1169
1464
  private instrumentAgent;
1465
+ /**
1466
+ * Emit an agent event as JSON.
1467
+ */
1468
+ private emitAgentEventAsJSON;
1170
1469
  /**
1171
1470
  * Display workflow info at startup.
1172
1471
  */
@@ -1195,6 +1494,18 @@ declare class Orchestrator {
1195
1494
  * Get the YAML loader for registering custom tools.
1196
1495
  */
1197
1496
  getLoader(): YAMLLoader;
1497
+ /**
1498
+ * Get the JSON output handler (if in JSON mode).
1499
+ */
1500
+ getJSONOutputHandler(): JSONOutputHandler | null;
1501
+ /**
1502
+ * Check if in JSON output mode.
1503
+ */
1504
+ isJSONOutputMode(): boolean;
1505
+ /**
1506
+ * Get the run ID.
1507
+ */
1508
+ getRunId(): string | undefined;
1198
1509
  }
1199
1510
 
1200
- export { type ActionOutput, type ActionStep, Agent, type AgentConfig, type AgentConfig$1 as AgentConfigType, AgentLogger, AgentMemory, AgentTool, type AgentToolConfig, type ChatMessage, CodeAgent, type CodeAgentConfig, type CodeExecutionOutput, CurlTool, ExaGetContentsTool, ExaResearchTool, ExaSearchTool, type ExecutorConfig, FINAL_ANSWER_PROMPT, type FinalAnswerStep, FinalAnswerTool, type GenerateOptions, type LoadedWorkflow, LocalExecutor, LogLevel, type MemoryStep, type MemoryStrategy, type MessageRole, Model, type ModelConfig, OpenAIModel, type OpenAIModelConfig, type OpenAIToolDefinition, Orchestrator, type OrchestratorConfig, type OrchestratorEvent, type PromptVariables, ReadFileTool, type RunResult, type StreamEvent, type SystemPromptStep, type TaskStep, type Timing, type TokenUsage, Tool, type ToolCall, type ToolCallResult, type ToolInput, type ToolInputType, type ToolInputs, ToolUseAgent, type ToolUseAgentConfig, type ToolUsePromptVariables, UserInputTool, WriteFileTool, type YAMLAgentDefinition, YAMLLoader, type YAMLModelDefinition, type YAMLToolDefinition, type YAMLWorkflowDefinition, agentAsTool, createTool, finalAnswerTool, formatToolDescriptions, generateSystemPrompt, generateToolUseSystemPrompt, getErrorRecoveryPrompt };
1511
+ export { type ActionOutput, type ActionStep, Agent, type AgentConfig, type AgentConfig$1 as AgentConfigType, AgentLogger, AgentMemory, AgentTool, type AgentToolConfig, type ChatMessage, CodeAgent, type CodeAgentConfig, type CodeExecutionOutput, CurlTool, type CustomToolMetadata, type DiscoveredTool, ExaGetContentsTool, ExaResearchTool, ExaSearchTool, type ExecutorConfig, FINAL_ANSWER_PROMPT, type FinalAnswerStep, FinalAnswerTool, type GenerateOptions, type JSONAgentEndEvent, type JSONAgentObservationEvent, type JSONAgentStartEvent, type JSONAgentStepEvent, type JSONAgentThinkingEvent, type JSONAgentToolCallEvent, type JSONAgentToolResultEvent, type JSONErrorEvent, type JSONEvent, type JSONEventBase, type JSONEventType, type JSONLogEvent, type JSONOutputConfig, JSONOutputHandler, type JSONRunEndEvent, type JSONRunStartEvent, type JSONWorkflowLoadedEvent, type LoadedWorkflow, LocalExecutor, LogLevel, type MemoryStep, type MemoryStrategy, type MessageRole, Model, type ModelConfig, OpenAIModel, type OpenAIModelConfig, type OpenAIToolDefinition, Orchestrator, type OrchestratorConfig, type OrchestratorEvent, type OutputFormat, type PromptVariables, ProxyTool, type ProxyToolConfig, ReadFileTool, type RunResult, type StreamEvent, type SystemPromptStep, type TaskStep, type Timing, type TokenUsage, Tool, type ToolCall, type ToolCallResult, type ToolInput, type ToolInputType, type ToolInputs, ToolUseAgent, type ToolUseAgentConfig, type ToolUsePromptVariables, UserInputTool, WriteFileTool, type YAMLAgentDefinition, YAMLLoader, type YAMLModelDefinition, type YAMLToolDefinition, type YAMLWorkflowDefinition, agentAsTool, createTool, finalAnswerTool, formatToolDescriptions, generateSystemPrompt, generateToolUseSystemPrompt, getErrorRecoveryPrompt, loadCustomTools, scanCustomTools };