@samrahimi/smol-js 0.6.5 → 0.7.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.
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,147 @@ 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 via the toolHarness adapter.
1195
+ *
1196
+ * The tool file is never imported into the main Node.js process. When an agent
1197
+ * invokes this proxy, it spawns:
1198
+ *
1199
+ * bun run <toolHarness.ts> <toolPath> <argsJson>
1200
+ *
1201
+ * The harness is the ONLY place that speaks the stdout protocol. The tool
1202
+ * itself simply exports { TOOL_METADATA, execute } and knows nothing about
1203
+ * how it is being called.
1204
+ *
1205
+ * Protocol (stdout of harness/child):
1206
+ * - A line prefixed with `[TOOL_RESULT]` contains the JSON-serialized return value.
1207
+ * - A line prefixed with `[TOOL_ERROR]` means the tool threw; payload is the message.
1208
+ * - Any other stdout line (e.g. console.log inside execute()) is streaming output.
1209
+ *
1210
+ * Extensibility: The spawn+stdio transport is fully encapsulated here. A future
1211
+ * variant (HTTP, gRPC, IPC) only needs to replace execute() — the tool file and
1212
+ * YAML definition stay identical.
1213
+ */
1214
+
1215
+ interface ProxyToolConfig {
1216
+ /** Absolute path to the .ts or .js tool file */
1217
+ toolPath: string;
1218
+ /** Tool name (must match the file's base name) */
1219
+ name: string;
1220
+ /** Human-readable description exposed to agents */
1221
+ description: string;
1222
+ /** Input schema that the LLM will see */
1223
+ inputs: ToolInputs;
1224
+ /** Output type label */
1225
+ outputType: string;
1226
+ /** Max execution time in ms (default 60 s) */
1227
+ timeout?: number;
1228
+ }
1229
+ declare class ProxyTool extends Tool {
1230
+ readonly name: string;
1231
+ readonly description: string;
1232
+ readonly inputs: ToolInputs;
1233
+ readonly outputType: string;
1234
+ private readonly toolPath;
1235
+ private readonly timeout;
1236
+ private bunPath;
1237
+ private harnessPath;
1238
+ constructor(config: ProxyToolConfig);
1239
+ /**
1240
+ * Ensure Bun is available and locate the harness before first invocation.
1241
+ */
1242
+ setup(): Promise<void>;
1243
+ /**
1244
+ * Spawn the harness in a Bun child process. The harness imports the tool,
1245
+ * calls execute(args), and writes the protocol lines. Any console.log from
1246
+ * the tool flows through stdout as plain lines.
1247
+ */
1248
+ execute(args: Record<string, unknown>): Promise<unknown>;
1249
+ private processLine;
1250
+ }
1251
+
1252
+ /**
1253
+ * CustomToolScanner — discovers standalone tool files in a directory and
1254
+ * extracts their metadata so that ProxyTool instances can be registered
1255
+ * with the YAML loader.
1256
+ *
1257
+ * Convention over Configuration:
1258
+ * • Each file in the custom-tools folder must export a default metadata
1259
+ * object conforming to CustomToolMetadata (see standalone tool wrapper docs).
1260
+ * • The exported class name (or `name` field in metadata) MUST match the
1261
+ * file's basename (without extension). E.g. `WeatherLookup.ts` → name: "WeatherLookup".
1262
+ * • The tool is referenced in YAML by that same name.
1263
+ *
1264
+ * Metadata Extraction (zero-import approach):
1265
+ * We read the file as text and use a lightweight regex to pull the
1266
+ * `TOOL_METADATA` export block. This keeps the scanner decoupled from
1267
+ * Bun/ESM and lets it run purely in the Node.js main process.
1268
+ * The metadata block must be a single JSON object assigned to
1269
+ * `export const TOOL_METADATA = { ... };`
1270
+ */
1271
+
1272
+ interface CustomToolMetadata {
1273
+ /** Must match the file's basename (sans extension) */
1274
+ name: string;
1275
+ /** Human-readable description shown to the LLM */
1276
+ description: string;
1277
+ /** Input schema identical to Tool.inputs */
1278
+ inputs: ToolInputs;
1279
+ /** Output type label */
1280
+ outputType: string;
1281
+ /** Optional execution timeout in ms */
1282
+ timeout?: number;
1283
+ }
1284
+ interface DiscoveredTool {
1285
+ /** Absolute path to the tool file */
1286
+ filePath: string;
1287
+ /** Parsed metadata */
1288
+ metadata: CustomToolMetadata;
1289
+ }
1290
+ /**
1291
+ * Scan a directory for custom tool files and extract their metadata.
1292
+ *
1293
+ * @param folderPath Absolute path to the custom-tools directory.
1294
+ * @returns Array of discovered tools with parsed metadata.
1295
+ * @throws If any file fails metadata extraction.
1296
+ */
1297
+ declare function scanCustomTools(folderPath: string): DiscoveredTool[];
1298
+ /**
1299
+ * Scan a folder and return a Map<toolName, ProxyTool> ready for registration
1300
+ * with YAMLLoader.
1301
+ */
1302
+ declare function loadCustomTools(folderPath: string): Map<string, ProxyTool>;
1303
+
1044
1304
  /**
1045
1305
  * System prompts for CodeAgent
1046
1306
  *
@@ -1105,10 +1365,17 @@ interface LoadedWorkflow {
1105
1365
  }
1106
1366
  declare class YAMLLoader {
1107
1367
  private customTools;
1368
+ private toolInstances;
1108
1369
  /**
1109
- * Register a custom tool type for use in YAML definitions.
1370
+ * Register a custom tool type (class) for use in YAML definitions.
1110
1371
  */
1111
1372
  registerToolType(typeName: string, toolClass: new (config?: Record<string, unknown>) => Tool): void;
1373
+ /**
1374
+ * Register a pre-built tool instance for use in YAML definitions.
1375
+ * Used by the custom tool system to register ProxyTool instances
1376
+ * that are created by the scanner rather than by class instantiation.
1377
+ */
1378
+ registerToolInstance(typeName: string, tool: Tool): void;
1112
1379
  /**
1113
1380
  * Load a workflow from a YAML file path.
1114
1381
  */
@@ -1131,6 +1398,32 @@ declare class YAMLLoader {
1131
1398
  private buildAgent;
1132
1399
  }
1133
1400
 
1401
+ /**
1402
+ * JSONOutputHandler - Emits structured NDJSON events for machine-readable CLI output.
1403
+ */
1404
+
1405
+ interface JSONOutputConfig {
1406
+ runId: string;
1407
+ verbose?: boolean;
1408
+ }
1409
+ declare class JSONOutputHandler {
1410
+ private readonly runId;
1411
+ private readonly startTime;
1412
+ constructor(config: JSONOutputConfig);
1413
+ private emit;
1414
+ emitRunStart(workflowPath: string, task: string, cwd?: string): void;
1415
+ emitWorkflowLoaded(name: string, description: string | undefined, agents: string[], tools: string[], entrypoint: string): void;
1416
+ emitRunEnd(success: boolean, output: unknown, totalTokens: number, totalSteps: number): void;
1417
+ emitAgentStart(agentName: string, depth: number, task: string, agentType: string, maxSteps: number): void;
1418
+ emitAgentEnd(agentName: string, depth: number, output: unknown, totalSteps: number, tokenUsage: TokenUsage | undefined, duration: number, success: boolean): void;
1419
+ emitAgentStep(agentName: string, depth: number, stepNumber: number, maxSteps: number, phase: string): void;
1420
+ emitAgentThinking(agentName: string, depth: number, stepNumber: number, content: string, isPartial: boolean): void;
1421
+ emitToolCall(agentName: string, depth: number, stepNumber: number, toolCallId: string, toolName: string, args: Record<string, unknown>): void;
1422
+ emitToolResult(agentName: string, depth: number, stepNumber: number, toolCallId: string, toolName: string, result: unknown, error: string | undefined, duration: number): void;
1423
+ emitObservation(agentName: string, depth: number, stepNumber: number, observation: string, codeAction: string | undefined, logs: string | undefined): void;
1424
+ emitError(message: string, stack?: string, agentName?: string, depth?: number, stepNumber?: number): void;
1425
+ }
1426
+
1134
1427
  /**
1135
1428
  * Orchestrator - Loads, runs, and provides real-time visibility into agent execution
1136
1429
  */
@@ -1140,12 +1433,20 @@ interface OrchestratorConfig {
1140
1433
  verbose?: boolean;
1141
1434
  /** Callback for orchestrator events */
1142
1435
  onEvent?: (event: OrchestratorEvent) => void;
1436
+ /** Output format: 'text' for chalk-formatted console, 'json' for NDJSON streaming */
1437
+ outputFormat?: OutputFormat;
1438
+ /** Unique run identifier (required for JSON output) */
1439
+ runId?: string;
1440
+ /** Working directory for agent file operations */
1441
+ cwd?: string;
1143
1442
  }
1144
1443
  declare class Orchestrator {
1145
1444
  private loader;
1146
1445
  private config;
1147
1446
  private activeAgents;
1148
1447
  private eventLog;
1448
+ private jsonOutput;
1449
+ private isJsonMode;
1149
1450
  constructor(config?: OrchestratorConfig);
1150
1451
  /**
1151
1452
  * Load a workflow from a YAML file.
@@ -1154,11 +1455,11 @@ declare class Orchestrator {
1154
1455
  /**
1155
1456
  * Load a workflow from YAML string.
1156
1457
  */
1157
- loadWorkflowFromString(yamlContent: string): LoadedWorkflow;
1458
+ loadWorkflowFromString(yamlContent: string, sourcePath?: string): LoadedWorkflow;
1158
1459
  /**
1159
1460
  * Run a loaded workflow with a task.
1160
1461
  */
1161
- runWorkflow(workflow: LoadedWorkflow, task: string): Promise<RunResult>;
1462
+ runWorkflow(workflow: LoadedWorkflow, task: string, workflowPath?: string): Promise<RunResult>;
1162
1463
  /**
1163
1464
  * Run a standalone agent with a task.
1164
1465
  */
@@ -1167,6 +1468,10 @@ declare class Orchestrator {
1167
1468
  * Instrument an agent with orchestrator event tracking.
1168
1469
  */
1169
1470
  private instrumentAgent;
1471
+ /**
1472
+ * Emit an agent event as JSON.
1473
+ */
1474
+ private emitAgentEventAsJSON;
1170
1475
  /**
1171
1476
  * Display workflow info at startup.
1172
1477
  */
@@ -1195,6 +1500,18 @@ declare class Orchestrator {
1195
1500
  * Get the YAML loader for registering custom tools.
1196
1501
  */
1197
1502
  getLoader(): YAMLLoader;
1503
+ /**
1504
+ * Get the JSON output handler (if in JSON mode).
1505
+ */
1506
+ getJSONOutputHandler(): JSONOutputHandler | null;
1507
+ /**
1508
+ * Check if in JSON output mode.
1509
+ */
1510
+ isJSONOutputMode(): boolean;
1511
+ /**
1512
+ * Get the run ID.
1513
+ */
1514
+ getRunId(): string | undefined;
1198
1515
  }
1199
1516
 
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 };
1517
+ 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 };